mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +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';
|
||||
|
||||
/**
|
||||
@ -90,15 +92,20 @@ export const initPageEvents = async (page: E2EPage) => {
|
||||
* page context to updates the _e2eEvents map
|
||||
* 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++;
|
||||
page._e2eEvents.set(id, {
|
||||
eventName,
|
||||
callback,
|
||||
});
|
||||
|
||||
await page.evaluate(
|
||||
([eventName, id]) => {
|
||||
await elmHandle.evaluate(
|
||||
(elm, [eventName, id]) => {
|
||||
(window as any).stencilSerializeEventTarget = (target: any) => {
|
||||
// BROWSER CONTEXT
|
||||
if (!target) {
|
||||
@ -146,7 +153,7 @@ export const addE2EListener = async (page: E2EPage, eventName: string, callback:
|
||||
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));
|
||||
});
|
||||
},
|
||||
|
@ -4,3 +4,4 @@ export * from './get-snapshot-settings';
|
||||
export * from './set-ion-viewport';
|
||||
export * from './spy-on-event';
|
||||
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> => {
|
||||
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;
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { Page, Response } from '@playwright/test';
|
||||
|
||||
import type { EventSpy } from './page/event-spy';
|
||||
import type { LocatorOptions, E2ELocator } from './page/utils/locator';
|
||||
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
* Use this method when taking full-screen screenshots.
|
||||
|
@ -15,7 +15,9 @@ import {
|
||||
setIonViewport,
|
||||
spyOnEvent,
|
||||
waitForChanges,
|
||||
locator,
|
||||
} from './page/utils';
|
||||
import type { LocatorOptions } from './page/utils';
|
||||
import type { E2EPage } from './playwright-declarations';
|
||||
|
||||
type CustomTestArgs = PlaywrightTestArgs &
|
||||
@ -32,10 +34,12 @@ type CustomFixtures = {
|
||||
export const test = base.extend<CustomFixtures>({
|
||||
page: async ({ page }: CustomTestArgs, use: (r: E2EPage) => Promise<void>, testInfo: TestInfo) => {
|
||||
const originalGoto = page.goto.bind(page);
|
||||
const originalLocator = page.locator.bind(page);
|
||||
|
||||
// Overridden Playwright methods
|
||||
page.goto = (url: string) => goToPage(page, url, testInfo, originalGoto);
|
||||
page.setContent = (html: string) => setContent(page, html);
|
||||
page.locator = (selector: string, options?: LocatorOptions) => locator(page, originalLocator, selector, options);
|
||||
// Custom Ionic methods
|
||||
page.getSnapshotSettings = () => getSnapshotSettings(page, testInfo);
|
||||
page.setIonViewport = () => setIonViewport(page);
|
||||
|
Reference in New Issue
Block a user