Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mock ws inside web worker #356

Open
alexandrzavalii opened this issue Mar 21, 2022 · 3 comments
Open

Mock ws inside web worker #356

alexandrzavalii opened this issue Mar 21, 2022 · 3 comments

Comments

@alexandrzavalii
Copy link

Currently mocking web sockets within web worker is not possible.

Window and global object within web worker is not shared

@Atrue
Copy link
Collaborator

Atrue commented Mar 24, 2022

What library do you use for testing workers? I can suggest creating another module for WebSocket (and import it from the worker) and trying to mock this module using jest or sinon if it works for you

@alexandrzavalii
Copy link
Author

alexandrzavalii commented Mar 29, 2022

I am running the component in storybook and I do not mock workers.
The only thing I need to be mocked is the websocket.

Window.WebSocket = WebSocket; will not mock the websocket inside worker.

So I wonder if there is a way around this problem.

I tried injecting WebSocket implementation from Window object to Worker but had no luck

@Atrue
Copy link
Collaborator

Atrue commented Apr 5, 2022

Anyway, it's not enough to mock the WebSocket, you need all the code inside the worker scope. So you need to have also a Server instance from this module and describe how it should work. So you can't manage it outside this worker. Just to note: when you create a Server instance the WebSocket is mocked automatically and is restored when you call server.stop()

You can try to inject some script using importScript that creates a Server instance from mock-socket (but you need to use importScript again for mock-socket). Or try worker modules to use es imports https://web.dev/module-workers/#enter-module-workers. But do not forget about the production, this code should not get there.

But I'd suggest changing the code a little bit to have the WebSocket in the main thread, so instead of sending and receiving the data to WebSocket it would send and receive events to the main thread. It'd have all the logic inside the worker, and it'd be possible to manage the WebSocket in the main thread, so you can mock it the same way:

/** 
 * main.js
 */
const worker = new Worker('...');
let websocket;

worker.onmessage = ({ data }) => {
    switch (data.type) {
        case 'connect': {
            websocket = new WebSocket(data.url);
            websocket.onmessage = msg => worker.postMessage({ type: 'message', data: msg.data });
            break;
        }
        case 'message': {
            websocket?.send(data.data);
            break;
        }
        case 'close': {
            websocket?.close();
            break;
        }
    }
}

/**
 * worker.js
 */
self.onmessage = ({ data }) => {
    if (data.type === 'message') {
        // handle websocket message;
    }
}
// create connection
self.postMessage({ type: 'connect', url: 'some-url '});

/**
 * test.js
 */
const mockServer = new Server('some-url');

mockServer.on('connection', socket => {
  socket.send('message');
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants