javascript - bagaimana saya boleh membuat playwright mendengar acara mesej
Saya mempunyai sebuah laman web yang berkomunikasi melalui arahan postMessage
window.parent.postMessage(communication, this.origin);
Apabila menggunakan playwright, saya sedang cuba melakukan pengendali "on message"
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>)
output konsol
Im here
setting return event MessageEvent
event was {}
Saya tidak boleh meletakkan jangkaan saya dalam kod page.evaluate(), kerana ia kemudian dijalankan dalam konteks tag javascript yang disuntikkan, dan bukan dalam konteks spesifikasi.
Jawapan #1
Saya ingin akhirnya menjadikannya sebuah expect, daripada sebuah evaluate atau waitForEvent.
Sayangnya saya tidak dapat menemui apa-apa untuk mendengar acara mesej. Sebaliknya, kami hanya menggunakan console.info.
Penyelesaian ini membungkus page.on('console', ...) ke dalam fungsi async yang boleh kita gunakan sebagai suis 'selesaikan jika berjaya, tergantung jika gagal'
// 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();
Dengan cara ini, expect akan gagal dalam ujian jika ia tamat masa menunggu mesej 'Hello, World!' kita! 🥳
Jawapan #2
Seseorang boleh membuat penegasan terhadap panggilan ke window.parent.postMessage, atau API pelayar lain, dengan menulis semula pelaksanaan API pelayar untuk menolak panggilan kaedah ke dalam memori Node.js menggunakan exposeFunction dan addInitScript. Kemudian, penegasan boleh dilakukan secara asinkron terhadap panggilan ini menggunakan expect.poll.
Sebagai contoh:
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);
});
