mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
test(playwright): add spyOnEvent for Locators (#25328)
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
|
import type { JSHandle } from '@playwright/test';
|
||||||
|
|
||||||
import type { E2EPage } from '../playwright-declarations';
|
import type { E2EPage } from '../playwright-declarations';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,15 +92,20 @@ export const initPageEvents = async (page: E2EPage) => {
|
|||||||
* page context to updates the _e2eEvents map
|
* page context to updates the _e2eEvents map
|
||||||
* when an event is fired.
|
* when an event is fired.
|
||||||
*/
|
*/
|
||||||
export const addE2EListener = async (page: E2EPage, eventName: string, callback: (ev: any) => void) => {
|
export const addE2EListener = async (
|
||||||
|
page: E2EPage,
|
||||||
|
elmHandle: JSHandle,
|
||||||
|
eventName: string,
|
||||||
|
callback: (ev: any) => void
|
||||||
|
) => {
|
||||||
const id = page._e2eEventsIds++;
|
const id = page._e2eEventsIds++;
|
||||||
page._e2eEvents.set(id, {
|
page._e2eEvents.set(id, {
|
||||||
eventName,
|
eventName,
|
||||||
callback,
|
callback,
|
||||||
});
|
});
|
||||||
|
|
||||||
await page.evaluate(
|
await elmHandle.evaluate(
|
||||||
([eventName, id]) => {
|
(elm, [eventName, id]) => {
|
||||||
(window as any).stencilSerializeEventTarget = (target: any) => {
|
(window as any).stencilSerializeEventTarget = (target: any) => {
|
||||||
// BROWSER CONTEXT
|
// BROWSER CONTEXT
|
||||||
if (!target) {
|
if (!target) {
|
||||||
@ -146,7 +153,7 @@ export const addE2EListener = async (page: E2EPage, eventName: string, callback:
|
|||||||
return serializedEvent;
|
return serializedEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener(eventName as string, (ev: Event) => {
|
elm.addEventListener(eventName as string, (ev: Event) => {
|
||||||
(window as any).ionicOnEvent(id, (window as any).serializeStencilEvent(ev));
|
(window as any).ionicOnEvent(id, (window as any).serializeStencilEvent(ev));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -4,3 +4,4 @@ export * from './get-snapshot-settings';
|
|||||||
export * from './set-ion-viewport';
|
export * from './set-ion-viewport';
|
||||||
export * from './spy-on-event';
|
export * from './spy-on-event';
|
||||||
export * from './set-content';
|
export * from './set-content';
|
||||||
|
export * from './locator';
|
||||||
|
41
core/src/utils/test/playwright/page/utils/locator.ts
Normal file
41
core/src/utils/test/playwright/page/utils/locator.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import type { Locator } from '@playwright/test';
|
||||||
|
|
||||||
|
import type { E2EPage } from '../../playwright-declarations';
|
||||||
|
import { EventSpy, addE2EListener } from '../event-spy';
|
||||||
|
|
||||||
|
export type LocatorOptions = {
|
||||||
|
hasText?: string | RegExp;
|
||||||
|
has?: Locator;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface E2ELocator extends Locator {
|
||||||
|
/**
|
||||||
|
* Creates a new EventSpy and listens
|
||||||
|
* on the element for an event.
|
||||||
|
* The test will timeout if the event
|
||||||
|
* never fires.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* const input = page.locator('ion-input');
|
||||||
|
* const ionChange = await locator.spyOnEvent('ionChange');
|
||||||
|
* ...
|
||||||
|
* await ionChange.next();
|
||||||
|
*/
|
||||||
|
spyOnEvent: (eventName: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const locator = (
|
||||||
|
page: E2EPage,
|
||||||
|
originalFn: typeof page.locator,
|
||||||
|
selector: string,
|
||||||
|
options?: LocatorOptions
|
||||||
|
): E2ELocator => {
|
||||||
|
const locator = originalFn(selector, options) as E2ELocator;
|
||||||
|
locator.spyOnEvent = async (eventName: string) => {
|
||||||
|
const spy = new EventSpy(eventName);
|
||||||
|
const handle = await locator.evaluateHandle((node: HTMLElement) => node);
|
||||||
|
await addE2EListener(page, handle, eventName, (ev: CustomEvent) => spy.push(ev));
|
||||||
|
return spy;
|
||||||
|
};
|
||||||
|
return locator;
|
||||||
|
};
|
@ -4,7 +4,9 @@ import { addE2EListener, EventSpy } from '../event-spy';
|
|||||||
export const spyOnEvent = async (page: E2EPage, eventName: string): Promise<EventSpy> => {
|
export const spyOnEvent = async (page: E2EPage, eventName: string): Promise<EventSpy> => {
|
||||||
const spy = new EventSpy(eventName);
|
const spy = new EventSpy(eventName);
|
||||||
|
|
||||||
await addE2EListener(page, eventName, (ev: CustomEvent) => spy.push(ev));
|
const handle = await page.evaluateHandle(() => window);
|
||||||
|
|
||||||
|
await addE2EListener(page, handle, eventName, (ev: CustomEvent) => spy.push(ev));
|
||||||
|
|
||||||
return spy;
|
return spy;
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import type { Page, Response } from '@playwright/test';
|
import type { Page, Response } from '@playwright/test';
|
||||||
|
|
||||||
import type { EventSpy } from './page/event-spy';
|
import type { EventSpy } from './page/event-spy';
|
||||||
|
import type { LocatorOptions, E2ELocator } from './page/utils/locator';
|
||||||
|
|
||||||
export interface E2EPage extends Page {
|
export interface E2EPage extends Page {
|
||||||
/**
|
/**
|
||||||
@ -28,6 +29,13 @@ export interface E2EPage extends Page {
|
|||||||
* [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
|
* [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
|
||||||
*/
|
*/
|
||||||
goto: (url: string) => Promise<null | Response>;
|
goto: (url: string) => Promise<null | Response>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an element by selector.
|
||||||
|
* See https://playwright.dev/docs/locators for more information.
|
||||||
|
*/
|
||||||
|
locator: (selector: string, options?: LocatorOptions) => E2ELocator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases the size of the page viewport to match the `ion-content` contents.
|
* Increases the size of the page viewport to match the `ion-content` contents.
|
||||||
* Use this method when taking full-screen screenshots.
|
* Use this method when taking full-screen screenshots.
|
||||||
|
@ -15,7 +15,9 @@ import {
|
|||||||
setIonViewport,
|
setIonViewport,
|
||||||
spyOnEvent,
|
spyOnEvent,
|
||||||
waitForChanges,
|
waitForChanges,
|
||||||
|
locator,
|
||||||
} from './page/utils';
|
} from './page/utils';
|
||||||
|
import type { LocatorOptions } from './page/utils';
|
||||||
import type { E2EPage } from './playwright-declarations';
|
import type { E2EPage } from './playwright-declarations';
|
||||||
|
|
||||||
type CustomTestArgs = PlaywrightTestArgs &
|
type CustomTestArgs = PlaywrightTestArgs &
|
||||||
@ -32,10 +34,12 @@ type CustomFixtures = {
|
|||||||
export const test = base.extend<CustomFixtures>({
|
export const test = base.extend<CustomFixtures>({
|
||||||
page: async ({ page }: CustomTestArgs, use: (r: E2EPage) => Promise<void>, testInfo: TestInfo) => {
|
page: async ({ page }: CustomTestArgs, use: (r: E2EPage) => Promise<void>, testInfo: TestInfo) => {
|
||||||
const originalGoto = page.goto.bind(page);
|
const originalGoto = page.goto.bind(page);
|
||||||
|
const originalLocator = page.locator.bind(page);
|
||||||
|
|
||||||
// Overridden Playwright methods
|
// Overridden Playwright methods
|
||||||
page.goto = (url: string) => goToPage(page, url, testInfo, originalGoto);
|
page.goto = (url: string) => goToPage(page, url, testInfo, originalGoto);
|
||||||
page.setContent = (html: string) => setContent(page, html);
|
page.setContent = (html: string) => setContent(page, html);
|
||||||
|
page.locator = (selector: string, options?: LocatorOptions) => locator(page, originalLocator, selector, options);
|
||||||
// Custom Ionic methods
|
// Custom Ionic methods
|
||||||
page.getSnapshotSettings = () => getSnapshotSettings(page, testInfo);
|
page.getSnapshotSettings = () => getSnapshotSettings(page, testInfo);
|
||||||
page.setIonViewport = () => setIonViewport(page);
|
page.setIonViewport = () => setIonViewport(page);
|
||||||
|
Reference in New Issue
Block a user