mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
refactor(test): add cls
and dcls
util functions (#4513)
To build string for matching class names.
This commit is contained in:
parent
c4e4b83740
commit
9eb512b5a4
3 changed files with 33 additions and 6 deletions
|
@ -3,6 +3,7 @@ import path from 'node:path';
|
||||||
import { appendPath } from '@silverhand/essentials';
|
import { appendPath } from '@silverhand/essentials';
|
||||||
|
|
||||||
import { consolePassword, consoleUsername, logtoConsoleUrl } from '#src/constants.js';
|
import { consolePassword, consoleUsername, logtoConsoleUrl } from '#src/constants.js';
|
||||||
|
import { dcls } from '#src/utils.js';
|
||||||
|
|
||||||
import ExpectPage, { ExpectPageError } from './expect-page.js';
|
import ExpectPage, { ExpectPageError } from './expect-page.js';
|
||||||
import { expectConfirmModalAndAct, expectToSaveChanges } from './index.js';
|
import { expectConfirmModalAndAct, expectToSaveChanges } from './index.js';
|
||||||
|
@ -53,7 +54,7 @@ export default class ExpectConsole extends ExpectPage {
|
||||||
async gotoPage(pathname: string, title: ConsoleTitle) {
|
async gotoPage(pathname: string, title: ConsoleTitle) {
|
||||||
await this.navigateTo(this.buildUrl(path.join(this.options.tenantId, pathname)));
|
await this.navigateTo(this.buildUrl(path.join(this.options.tenantId, pathname)));
|
||||||
await expect(this.page).toMatchElement(
|
await expect(this.page).toMatchElement(
|
||||||
'div[class*=_main] div[class*=_container] div[class*=_cardTitle]',
|
[dcls('main'), dcls('container'), dcls('cardTitle')].join(' '),
|
||||||
{ text: title }
|
{ text: title }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +68,7 @@ export default class ExpectConsole extends ExpectPage {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
titles.map(async (title) => {
|
titles.map(async (title) => {
|
||||||
return expect(this.page).toMatchElement(
|
return expect(this.page).toMatchElement(
|
||||||
'div[class*=_tabContent] div[class*=_card] div[class*=_title]',
|
[dcls('tabContent'), dcls('card'), dcls('title')].join(' '),
|
||||||
{ text: new RegExp(title, 'i'), visible: true }
|
{ text: new RegExp(title, 'i'), visible: true }
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -78,7 +79,7 @@ export default class ExpectConsole extends ExpectPage {
|
||||||
const fieldTitle = await expect(this.page).toMatchElement(
|
const fieldTitle = await expect(this.page).toMatchElement(
|
||||||
// Use `:has()` for a quick and dirty way to match the field title.
|
// Use `:has()` for a quick and dirty way to match the field title.
|
||||||
// Not harmful in most cases.
|
// Not harmful in most cases.
|
||||||
'div[class*=_field]:has(div[class*=_title])',
|
`${dcls('field')}:has(${dcls('title')})`,
|
||||||
{
|
{
|
||||||
text: new RegExp(title, 'i'),
|
text: new RegExp(title, 'i'),
|
||||||
visible: true,
|
visible: true,
|
||||||
|
@ -100,7 +101,9 @@ export default class ExpectConsole extends ExpectPage {
|
||||||
* Click a `<nav>` navigation tab (not the page tab) in the Console.
|
* Click a `<nav>` navigation tab (not the page tab) in the Console.
|
||||||
*/
|
*/
|
||||||
async toClickTab(tabName: string | RegExp) {
|
async toClickTab(tabName: string | RegExp) {
|
||||||
await expect(this.page).toClick(`nav div[class*=_item] div[class*=_link] a`, { text: tabName });
|
await expect(this.page).toClick(['nav', dcls('item'), dcls('link'), 'a'].join(' '), {
|
||||||
|
text: tabName,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async toSaveChanges(confirmation?: string | RegExp) {
|
async toSaveChanges(confirmation?: string | RegExp) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { condString } from '@silverhand/essentials';
|
import { condString } from '@silverhand/essentials';
|
||||||
import { type ElementHandle, type Page } from 'puppeteer';
|
import { type ElementHandle, type Page } from 'puppeteer';
|
||||||
|
|
||||||
import { expectNavigation } from '#src/utils.js';
|
import { cls, dcls, expectNavigation } from '#src/utils.js';
|
||||||
|
|
||||||
/** Error thrown by {@link ExpectPage}. */
|
/** Error thrown by {@link ExpectPage}. */
|
||||||
export class ExpectPageError extends Error {
|
export class ExpectPageError extends Error {
|
||||||
|
@ -141,7 +141,7 @@ export default class ExpectPage {
|
||||||
*/
|
*/
|
||||||
async waitForToast(text: string | RegExp, type?: 'success' | 'error') {
|
async waitForToast(text: string | RegExp, type?: 'success' | 'error') {
|
||||||
const toast = await expect(this.page).toMatchElement(
|
const toast = await expect(this.page).toMatchElement(
|
||||||
`[class*=toast]${condString(type && `[class*=${type}]`)}:has(div[class$=message]`,
|
`${cls('toast')}${condString(type && cls(type))}:has(${dcls('message')})`,
|
||||||
{
|
{
|
||||||
text,
|
text,
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,3 +81,27 @@ export const expectNavigation = async <T>(
|
||||||
]);
|
]);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the string for a CSS selector that matches a class name.
|
||||||
|
*
|
||||||
|
* Since we use CSS modules, the class names are prefixed with a hash followed by a `_`.
|
||||||
|
* For example, the class name `foo` will be transformed to `abc123_foo`. This function
|
||||||
|
* returns a selector that matches any class name that contains `_foo`.
|
||||||
|
*
|
||||||
|
* It is accurate enough for our tests, as long as our class names are camelCased.
|
||||||
|
*/
|
||||||
|
export const cls = <C extends string>(className: C) => `[class*=_${className}]` as const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the string for a CSS selector that matches a class name for a `<div>` element.
|
||||||
|
* This is a shorthand for `div${cls(className)}`.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* dcls('foo') // => 'div[class*=_foo]'
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @see {@link cls}
|
||||||
|
*/
|
||||||
|
export const dcls = <C extends string>(className: C) => `div${cls(className)}` as const;
|
||||||
|
|
Loading…
Reference in a new issue