javascript - hvordan kan jeg få playwright til at lytte til beskedbegivenheder
Jeg har et websted, der kommunikerer gennem postMessage-kommandoer
window.parent.postMessage(communication, this.origin);
Når jeg bruger Playwright, prøver jeg at lave en "on message"-håndtering
function eventListener(returnEvent: any): any {
window.addEventListener('message', function(event: MessageEvent) {
console.log('Im here');
if (event.data.messageId === 'payment-method') {
console.log('setting return event', event);
returnEvent = event;
return returnEvent;
}
});
}
...
let returnEvent: any = {};
await page.evaluate(eventListener, returnEvent);
await creditCardDetailsPage.fillFormValid();
await page.waitForTimeout(5000); //give time for message event to fire
console.log('event was', returnEvent);
await expect(returnEvent).toEqual(<MY DATA OBJECT HERE>)
konsoloutput
Im here
setting return event MessageEvent
event was {}
Jeg kan ikke sætte mine forventninger i page.evaluate()-koden, fordi den så kører inden for konteksten af det javascript-tag, som den injicerer, og ikke inden for konteksten af spec'en.
Svar #1
Jeg ville til sidst få det til et expect, snarere end et evaluate eller et waitForEvent.
Desværre kunne jeg ikke finde noget til at lytte til en beskedhændelse. I stedet går vi bare efter console.info.
Denne løsning pakker page.on('console', ...) ind i en asynkron funktion, som vi simpelthen kan bruge som en 'opfyld hvis succes, hæng hvis fejl'-switch
// Return true if the page emits 'Hello, World!' to the console info level
async function waitForMessageAsync(): Promise<boolean> {
return new Promise(function (resolve) {
page.on('console', (msg) => {
if (msg.type() === 'log' && msg.text() === 'Hello, World!') {
resolve(true);
}
});
});
}
await expect(await waitForMessageAsync).toBeTruthy();
På denne måde vil expect fejle testen, hvis den timeout'er, mens den venter på vores 'Hello, World!' besked! 🥳
Svar #2
Man kan påstå kald til window.parent.postMessage eller andre browser-API'er ved at overskrive browser-API-implementeringen for at skubbe metodekald ind i Node.js-hukommelsen ved hjælp af exposeFunction og addInitScript. Derefter kan påstande udføres asynkront på disse kald ved hjælp af expect.poll.
For eksempel:
import { test, expect, Page } from "@playwright/test";
const setupMockPostMessage = async (page: Page) => {
// Store calls to postMessage
let calls: any[] = [];
// Expose function for pushing messages to the Node.js environment
const logCall = (args: any[]) => {
calls.push(args);
};
await page.exposeFunction("logCall", logCall);
// Inject script into the page to intercept postMessage calls
await page.addInitScript(() => {
window.parent.postMessage = (...args) => {
logCall(args);
};
});
// Return object for performing assertions
return {
calls,
lastCalledWith: () => calls.at(-1),
callTimes: () => calls.length,
clear: () => (calls = []),
};
};
test("iframe message channel", async ({ page }) => {
const mockPostMessage = await setupMockPostMessage(page);
await page.goto("/");
await expect.poll(mockPostMessage.lastCalledWith).toEqual(["LOAD", "*"]);
await expect.poll(mockPostMessage.callTimes).toEqual(1);
});
