diff --git a/test/browser/ws-api/ws.client.send.test.ts b/test/browser/ws-api/ws.client.send.test.ts new file mode 100644 index 000000000..84a30b226 --- /dev/null +++ b/test/browser/ws-api/ws.client.send.test.ts @@ -0,0 +1,132 @@ +import type { ws } from 'msw' +import type { setupWorker } from 'msw/browser' +import type { Page } from '@playwright/test' +import { test, expect } from '../playwright.extend' + +declare global { + interface Window { + msw: { + ws: typeof ws + setupWorker: typeof setupWorker + } + } +} + +test('sends data to a single client on connection', async ({ + loadExample, + page, +}) => { + await loadExample(require.resolve('./ws.runtime.js'), { + skipActivation: true, + }) + + await page.evaluate(async () => { + const { setupWorker, ws } = window.msw + const service = ws.link('wss://example.com') + + const worker = setupWorker( + service.addEventListener('connection', ({ client }) => { + // Send a message to the client as soon as it connects. + client.send('hello world') + }), + ) + await worker.start() + }) + + const clientMessage = await page.evaluate(async () => { + const socket = new WebSocket('wss://example.com') + return new Promise((resolve, reject) => { + socket.onmessage = (event) => resolve(event.data) + socket.onerror = () => reject(new Error('WebSocket error')) + }).finally(() => socket.close()) + }) + + expect(clientMessage).toBe('hello world') +}) + +test('sends data to multiple clients on connection', async ({ + loadExample, + browser, + page, +}) => { + const { compilation } = await loadExample( + require.resolve('./ws.runtime.js'), + { + skipActivation: true, + }, + ) + + async function createSocketAndGetFirstMessage(page: Page) { + await page.evaluate(async () => { + const { setupWorker, ws } = window.msw + const service = ws.link('wss://example.com') + + const worker = setupWorker( + service.addEventListener('connection', ({ client }) => { + // Send a message to the client as soon as it connects. + client.send('hello world') + }), + ) + await worker.start() + }) + + return page.evaluate(async () => { + const socket = new WebSocket('wss://example.com') + return new Promise((resolve, reject) => { + socket.onmessage = (event) => resolve(event.data) + socket.onerror = () => reject(new Error('WebSocket error')) + }).finally(() => socket.close()) + }) + } + + const secondPage = await browser.newPage() + await secondPage.goto(compilation.previewUrl) + + const [firstClientMessage, secondClientMessage] = await Promise.all([ + createSocketAndGetFirstMessage(page), + createSocketAndGetFirstMessage(secondPage), + ]) + + expect(firstClientMessage).toBe('hello world') + expect(secondClientMessage).toBe('hello world') +}) + +test('sends data in response to a client message', async ({ + loadExample, + page, +}) => { + await loadExample(require.resolve('./ws.runtime.js'), { + skipActivation: true, + }) + + await page.evaluate(async () => { + const { setupWorker, ws } = window.msw + const service = ws.link('wss://example.com') + + const worker = setupWorker( + service.addEventListener('connection', ({ client }) => { + client.addEventListener('message', (event) => { + if (typeof event.data === 'string' && event.data === 'hello') { + client.send('hello world') + } + }) + }), + ) + await worker.start() + }) + + const clientMessage = await page.evaluate(async () => { + const socket = new WebSocket('wss://example.com') + socket.onopen = () => { + socket.send('ignore this') + socket.send('hello') + } + + return new Promise((resolve, reject) => { + socket.onmessage = (event) => resolve(event.data) + socket.onerror = () => reject(new Error('WebSocket error')) + }).finally(() => socket.close()) + }) + + expect(clientMessage).toBe('hello world') +}) diff --git a/test/browser/ws-api/ws.server.connect.browser.test.ts b/test/browser/ws-api/ws.server.connect.browser.test.ts index 7741e9b47..c9f070cb5 100644 --- a/test/browser/ws-api/ws.server.connect.browser.test.ts +++ b/test/browser/ws-api/ws.server.connect.browser.test.ts @@ -50,12 +50,9 @@ test('does not connect to the actual server by default', async ({ const socket = new WebSocket(serverUrl) return new Promise((resolve, reject) => { - socket.onmessage = (event) => { - resolve(event.data) - socket.close() - } - socket.onerror = reject - }) + socket.onmessage = (event) => resolve(event.data) + socket.onerror = () => reject(new Error('WebSocket error')) + }).finally(() => socket.close()) }, server.url) expect(clientMessage).toBe('mock')