 614740a4ff
			
		
	
	614740a4ff
	
	
	
		
			
			* web: Prep ESBuild plugin for publish. * prettier-config: Update deps. * eslint-config: Update deps. * docusaurus-config: Update deps. * docs: Update deps. * docs: Enable linter. * docs: Lint. * web/sfe: Clean up types. Prep for monorepo. * esbuild-plugin-live-reload: Update deps. * web: Tidy ESLint, script commands. * web: Fix logs. * web: Lint. * web: Split compile check from cached version.
		
			
				
	
	
		
			227 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { browser } from "@wdio/globals";
 | |
| import { match } from "ts-pattern";
 | |
| import { Key } from "webdriverio";
 | |
| 
 | |
| export async function doBlur(el: WebdriverIO.Element | ChainablePromiseElement) {
 | |
|     const element = await el;
 | |
|     browser.execute((element) => element.blur(), element);
 | |
| }
 | |
| 
 | |
| export function tap<A>(a: A) {
 | |
|     console.log("TAP:", a);
 | |
|     return a;
 | |
| }
 | |
| 
 | |
| const makeComparator = (value: string | RegExp) =>
 | |
|     typeof value === "string"
 | |
|         ? (sample: string) => sample === value
 | |
|         : (sample: string) => value.test(sample);
 | |
| 
 | |
| export async function checkIsPresent(name: string) {
 | |
|     await expect(await $(name)).toBeDisplayed();
 | |
| }
 | |
| 
 | |
| export async function clickButton(name: string, ctx?: WebdriverIO.Element) {
 | |
|     const context = ctx ?? browser;
 | |
|     const button = await (async () => {
 | |
|         for await (const button of context.$$("button")) {
 | |
|             if ((await button.isDisplayed()) && (await button.getText()).indexOf(name) !== -1) {
 | |
|                 return button;
 | |
|             }
 | |
|         }
 | |
|     })();
 | |
| 
 | |
|     if (!(button && (await button.isDisplayed()))) {
 | |
|         throw new Error(`Unable to find button '${name}'`);
 | |
|     }
 | |
| 
 | |
|     await button.scrollIntoView();
 | |
|     await button.click();
 | |
|     await doBlur(button);
 | |
| }
 | |
| 
 | |
| export async function clickToggleGroup(name: string, value: string | RegExp) {
 | |
|     const comparator = makeComparator(value);
 | |
|     const button = await (async () => {
 | |
|         for await (const button of $(`>>>[data-ouid-component-name=${name}]`).$$(
 | |
|             ">>>.pf-c-toggle-group__button",
 | |
|         )) {
 | |
|             if (comparator(await button.$(">>>.pf-c-toggle-group__text").getText())) {
 | |
|                 return button;
 | |
|             }
 | |
|         }
 | |
|     })();
 | |
| 
 | |
|     if (!(button && (await button?.isDisplayed()))) {
 | |
|         throw new Error(`Unable to locate toggle button ${name}:${value.toString()}`);
 | |
|     }
 | |
| 
 | |
|     await button.scrollIntoView();
 | |
|     await button.click();
 | |
|     await doBlur(button);
 | |
| }
 | |
| 
 | |
| export async function setFormGroup(name: string | RegExp, setting: "open" | "closed") {
 | |
|     const comparator = makeComparator(name);
 | |
|     const formGroup = await (async () => {
 | |
|         for await (const group of browser.$$(">>>ak-form-group")) {
 | |
|             // Delightfully, wizards may have slotted elements that *exist* but are not *attached*,
 | |
|             // and this can break the damn tests.
 | |
|             if (!(await group.isDisplayed())) {
 | |
|                 continue;
 | |
|             }
 | |
|             if (
 | |
|                 comparator(
 | |
|                     await group.$(">>>div.pf-c-form__field-group-header-title-text").getText(),
 | |
|                 )
 | |
|             ) {
 | |
|                 return group;
 | |
|             }
 | |
|         }
 | |
|     })();
 | |
| 
 | |
|     if (!(formGroup && (await formGroup.isDisplayed()))) {
 | |
|         throw new Error(`Unable to find ak-form-group[name="${name}"]`);
 | |
|     }
 | |
| 
 | |
|     await formGroup.scrollIntoView();
 | |
|     const toggle = await formGroup.$(">>>div.pf-c-form__field-group-toggle-button button");
 | |
|     await match([await toggle.getAttribute("aria-expanded"), setting])
 | |
|         .with(["false", "open"], async () => await toggle.click())
 | |
|         .with(["true", "closed"], async () => await toggle.click())
 | |
|         .otherwise(async () => {});
 | |
|     await doBlur(formGroup);
 | |
| }
 | |
| 
 | |
| export async function setRadio(name: string, value: string | RegExp) {
 | |
|     const control = await $(`>>>ak-radio[name="${name}"]`);
 | |
|     await control.scrollIntoView();
 | |
| 
 | |
|     const comparator = makeComparator(value);
 | |
|     const item = await (async () => {
 | |
|         for await (const item of control.$$(">>>div.pf-c-radio")) {
 | |
|             if (comparator(await item.$(">>>.pf-c-radio__label").getText())) {
 | |
|                 return item;
 | |
|             }
 | |
|         }
 | |
|     })();
 | |
| 
 | |
|     if (!(item && (await item.isDisplayed()))) {
 | |
|         throw new Error(`Unable to find a radio that matches ${name}:${value.toString()}`);
 | |
|     }
 | |
| 
 | |
|     await item.scrollIntoView();
 | |
|     await item.click();
 | |
|     await doBlur(control);
 | |
| }
 | |
| 
 | |
| export async function setSearchSelect(name: string, value: string | RegExp) {
 | |
|     const control = await (async () => {
 | |
|         try {
 | |
|             const control = await $(`>>>ak-search-select[name="${name}"]`);
 | |
|             await control.waitForExist({ timeout: 500 });
 | |
|             return control;
 | |
|         } catch (_e: unknown) {
 | |
|             const control = await $(`>>>ak-search-selects-ez[name="${name}"]`);
 | |
|             return control;
 | |
|         }
 | |
|     })();
 | |
| 
 | |
|     if (!(control && (await control.isExisting()))) {
 | |
|         throw new Error(`Unable to find an ak-search-select variant matching ${name}}`);
 | |
|     }
 | |
| 
 | |
|     // Find the search select input control and activate it.
 | |
|     const view = await control.$(">>>ak-search-select-view");
 | |
|     const input = await view.$('>>>input[type="text"]');
 | |
|     await input.scrollIntoView();
 | |
|     await input.click();
 | |
| 
 | |
|     const comparator = makeComparator(value);
 | |
|     const button = await (async () => {
 | |
|         for await (const button of $(`>>>div[data-managed-for*="${name}"]`)
 | |
|             .$(">>>ak-list-select")
 | |
|             .$$("button")) {
 | |
|             if (comparator(await button.getText())) {
 | |
|                 return button;
 | |
|             }
 | |
|         }
 | |
|     })();
 | |
| 
 | |
|     if (!(button && (await button.isDisplayed()))) {
 | |
|         throw new Error(
 | |
|             `Unable to find an ak-search-select entry matching ${name}:${value.toString()}`,
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     await (await button).click();
 | |
|     await browser.keys(Key.Tab);
 | |
|     await doBlur(control);
 | |
| }
 | |
| 
 | |
| export async function setTextInput(name: string, value: string) {
 | |
|     const control = await $(`>>>input[name="${name}"]`);
 | |
|     await control.scrollIntoView();
 | |
|     await control.setValue(value);
 | |
|     await doBlur(control);
 | |
| }
 | |
| 
 | |
| export async function setTextareaInput(name: string, value: string) {
 | |
|     const control = await $(`>>>textarea[name="${name}"]`);
 | |
|     await control.scrollIntoView();
 | |
|     await control.setValue(value);
 | |
|     await doBlur(control);
 | |
| }
 | |
| 
 | |
| export async function setToggle(name: string, set: boolean) {
 | |
|     const toggle = await $(`>>>input[name="${name}"]`);
 | |
|     await toggle.scrollIntoView();
 | |
|     await expect(await toggle.getAttribute("type")).toBe("checkbox");
 | |
|     const state = await toggle.isSelected();
 | |
|     if (set !== state) {
 | |
|         const control = await (await toggle.parentElement()).$(">>>.pf-c-switch__toggle");
 | |
|         await control.click();
 | |
|         await doBlur(control);
 | |
|     }
 | |
| }
 | |
| 
 | |
| export async function setTypeCreate(name: string, value: string | RegExp) {
 | |
|     const control = await $(`>>>ak-wizard-page-type-create[name="${name}"]`);
 | |
|     await control.scrollIntoView();
 | |
| 
 | |
|     const comparator = makeComparator(value);
 | |
|     const card = await (async () => {
 | |
|         for await (const card of $(">>>ak-wizard-page-type-create").$$(
 | |
|             '>>>[data-ouid-component-type="ak-type-create-grid-card"]',
 | |
|         )) {
 | |
|             if (comparator(await card.$(">>>.pf-c-card__title").getText())) {
 | |
|                 return card;
 | |
|             }
 | |
|         }
 | |
|     })();
 | |
| 
 | |
|     if (!(card && (await card.isDisplayed()))) {
 | |
|         throw new Error(`Unable to locate radio card ${name}:${value.toString()}`);
 | |
|     }
 | |
| 
 | |
|     await card.scrollIntoView();
 | |
|     await card.click();
 | |
|     await doBlur(control);
 | |
| }
 | |
| 
 | |
| export type TestInteraction =
 | |
|     | [typeof checkIsPresent, ...Parameters<typeof checkIsPresent>]
 | |
|     | [typeof clickButton, ...Parameters<typeof clickButton>]
 | |
|     | [typeof clickToggleGroup, ...Parameters<typeof clickToggleGroup>]
 | |
|     | [typeof setFormGroup, ...Parameters<typeof setFormGroup>]
 | |
|     | [typeof setRadio, ...Parameters<typeof setRadio>]
 | |
|     | [typeof setSearchSelect, ...Parameters<typeof setSearchSelect>]
 | |
|     | [typeof setTextInput, ...Parameters<typeof setTextInput>]
 | |
|     | [typeof setTextareaInput, ...Parameters<typeof setTextareaInput>]
 | |
|     | [typeof setToggle, ...Parameters<typeof setToggle>]
 | |
|     | [typeof setTypeCreate, ...Parameters<typeof setTypeCreate>];
 | |
| 
 | |
| export type TestSequence = TestInteraction[];
 | |
| 
 | |
| export type TestProvider = () => TestSequence;
 |