jest-websocket-mock icon indicating copy to clipboard operation
jest-websocket-mock copied to clipboard

Add ability to flush pending message queue

Open Coteh opened this issue 3 years ago • 5 comments

I am currently utilizing this library to mock communication between my frontend app and an IRC gateway called webircgateway for my unit tests, and I wasn't able to find a function that can clear out the pending message queue within a test. I am testing whether my app can send out a message, and I currently have to copy and paste await server.nextMessage so that I can discard the IRC initial communication messages (PASS, NICK, and USER) which I don't care about so that I can then call toReceiveMessage and toHaveReceivedMessages on the PRIVMSG message, which I do care about.

I attempted to make my own makeshift flush function:

async function flushWebSocketMessages(server: WS) {
    while (1) {
        const result = await promiseWithTimeout(server.nextMessage);
        if (result === null) {
            break;
        }
    }
}

function promiseWithTimeout<T>(promise: Promise<T>) {
    return new Promise((resolve, reject) => {
        promise
            .then((val) => resolve(val))
            .catch((err) => reject(err));

        setTimeout(() => {
            resolve(null);
        }, 2000);
    });
}

However, it does not seem to work because once I clear out the queue (which happens when we cannot get any more messages and the 2s timeout returns null) any message I send through the WebSocket is reported by the mock server as undefined:

 expect(WS).toReceiveMessage(expected)

    Expected the next received message to equal:
      "PRIVMSG #mychannel :Hello there"
    Received:
      undefined

    Difference:

      Comparing two different types of values. Expected string but received undefined.

I have decided to work around this for the time being by copy and pasting await server.nextMessage like I mentioned earlier in order to clear out the queue, but I would like to know why this is happening if possible. Also, let me know if flushing the pending message queue is something that can benefit this project, thanks.

Coteh avatar Dec 24 '20 03:12 Coteh

Hi @Coteh !

Thanks for the feedback, that's a good point!

I'm totally up for implementing something like that, but I'm afraid that the best solution would be a breaking change:

  • .toReceiveMesage should be updated to not stop at the next message, but instead wait until it finds a message matching the expected value
  • we should add a toReceiveMessageNext matcher that works like the existing toReceiveMessage

Would that fix your problem? If so, is that something you'd be interested in working on?

romgain avatar Jan 20 '21 17:01 romgain

I believe this would fix my problem yes, and I’d love to take a crack at it. :) You can assign the issue to me and hopefully I’ll have some time on the weekend to work on it.

On Jan 20, 2021, at 12:29 PM, Romain Bertrand <[email protected]mailto:[email protected]> wrote:

Hi @Cotehhttps://github.com/Coteh !

Thanks for the feedback, that's a good point!

I'm totally up for implementing something like that, but I'm afraid that the best solution would be a breaking change:

  • .toReceiveMesage should be updated to not stop at the next message, but instead wait until it finds a message matching the expected value
  • we should add a toReceiveMessageNext matcher that works like the existing toReceiveMessage

Would that fix your problem? If so, is that something you'd be interested in working on?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/romgain/jest-websocket-mock/issues/51#issuecomment-763809670, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAY74PQT5ZM2Q6FLLHC7JXLS24HFXANCNFSM4VHWUAOQ.

Coteh avatar Jan 21 '21 02:01 Coteh

Thanks @Coteh !

romgain avatar Jan 21 '21 11:01 romgain

Hey just wondering what you think should happen if .toReceiveMessage is called but the expected message is never received. I am thinking that we can wait until the timeout occurs and if the message doesn't come by that point, then we can confidently say that the message will not arrive. What do you think?

From what I've read of the codebase so far, it doesn't seem to me that would be any timing issues with messages being received much later than they're supposed to, but just want to confirm with you if this is the case. Thanks.

Coteh avatar Jan 31 '21 00:01 Coteh

Yup, that sounds good 👍

What would also be useful when we hit the timeout, would be to show all the messages we received since the toReceiceMessage call, something similar to the .toHaveBeenCalledWith output.

Maybe something like “Expected message foo was not received within XXXms. Received X Y Z instead.” With the same green/red colours as in the default toHaveBeenCalledWith output.

romgain avatar Jan 31 '21 19:01 romgain