Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

window.postMessage does not seem to work inside Promises

650 views
Skip to first unread message

Miguel Cubells Baeza

unread,
Jul 27, 2020, 11:13:44 PM7/27/20
to jsdom
Hi all.

I'm running some test with jest + jsdom, and found a problem, not sure if there is a bug or I'm missing something.

The following test snippet creates an event listener for the 'message' type, and then posts a message:

    const messageHandler = event => {
      console.log('message handler called');
    };

    window.addEventListener('message', messageHandler, false);
    window.postMessage('called', '*');

    await new Promise(resolve => setTimeout(resolve, 1000)); // wait a bit

If we run the above test, we can see in the console the message 'message handler called' as expected.

However, when creating the event listener inside a Promise, calling the corresponding postMessage does not seem to trigger the event, and the Promise cannot be resolved.

Example:

   const functionThatReturnsPromise = function() {
      return new Promise((resolve) => {
          const messageHandlerForPromise = event => {
              console.log('message handler for promise called');
              // solve the Promise if message is posted                         
              resolve({ data: 'solved' });
          }
          // adding event listener inside the Promise
          window.addEventListener('message', messageHandlerForPromise, false);
      });
    };

    window.postMessage('called', '*');
    await new Promise(resolve => setTimeout(resolve, 100)); // wait a bit
    
    const promiseToSolve = functionThatReturnsPromise();
    return promiseToSolve.then(result => {      
      expect(result.data).toBe('solved');
    });

In the above code, the Promise will never get resolved, as the postMessage does not seems to trigger the event listener.

Is this a bug, or there is something missing here ?

Thanks a lot in advance,

Full test here:

test("window.postMessage", async () => {  
    
    const messageHandler = event => {
      console.log('message handler called');
    };

    window.addEventListener('message', messageHandler, false);
    window.postMessage('called', '*');

    await new Promise(resolve => setTimeout(resolve, 1000)); // wait a bit 
    window.removeEventListener('message', messageHandler, false);

    const functionThatReturnsPromise = function() {
      return new Promise((resolve) => {
          const messageHandlerForPromise = event => {
              console.log('message handler for promise called');              
              resolve({ data: 'solved' });
          }
          window.addEventListener('message', messageHandlerForPromise, false);
      });
    };

    window.postMessage('called', '*');
    await new Promise(resolve => setTimeout(resolve, 100)); // wait a bit
    
    const promiseToSolve = functionThatReturnsPromise();
    return promiseToSolve.then(result => {      
      expect(result.data).toBe('solved');
  });
  }, 5000);

Sebastian Mayr

unread,
Jul 27, 2020, 11:20:11 PM7/27/20
to js...@googlegroups.com
Looks like you're not attaching the event handler in time to catch the message in the second example.

You'll need to call functionThatReturnsPromise before you call postMessage.

--
You received this message because you are subscribed to the Google Groups "jsdom" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jsdom+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jsdom/bacd41f4-9955-45ff-acc5-e3477948df81n%40googlegroups.com.

Miguel Cubells Baeza

unread,
Jul 28, 2020, 12:14:24 AM7/28/20
to jsdom
Thanks, you are right... using the right order works fine.
However this is just a dummy example... the real code that we are trying to test uses the correct approach, but still fails.

Will have to dig more...

Thanks a lot anyway !
Reply all
Reply to author
Forward
0 new messages