test(playwright): add spyOnEvent for Locators (#25328)

This commit is contained in:
Liam DeBeasi
2022-05-23 10:03:33 -04:00
committed by GitHub
parent 5aa610709d
commit a9893640b7
6 changed files with 68 additions and 5 deletions

View File

@ -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));
});
},

View File

@ -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';

View 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;
};

View File

@ -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;
};

View File

@ -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.

View File

@ -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);