I have a website that communicates through postMessage commands
window.parent.postMessage(communication, this.origin);
When using playwright, I'm trying to do an "on message" handler
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>)
console output
Im here
setting return event MessageEvent
event was {}
I cannot put my expects in the page.evaluate()
code, because then it's executing within the context of the javascript tag that it's injecting, and not within the context of the spec.
I wanted to eventually get it to an expect
, rather an evaluate
or a waitForEvent
.
Sadly I couldn't find anything for listening to a message event. Instead we just go for console.info
.
This solution wraps the page.on('console', ...)
into an async function that we can simply use as a 'resolve if success, hang if failure' 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();
This way, expect
will fail the test if it times out waiting for our 'Hello, World!'
message! 🥳