Skip to content

Commit

Permalink
fix(WebSocketClientManager): clear inMemoryClients on localStorage re…
Browse files Browse the repository at this point in the history
…moval
  • Loading branch information
kettanaito committed Apr 12, 2024
1 parent 78c46a0 commit aca9f05
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/browser/setupWorker/stop/createStop.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { devUtils } from '~/core/utils/internal/devUtils'
import { MSW_WEBSOCKET_CLIENTS_KEY } from '~/core/ws/WebSocketClientManager'
import { SetupWorkerInternalContext, StopHandler } from '../glossary'
import { printStopMessage } from './utils/printStopMessage'

Expand All @@ -24,6 +25,9 @@ export const createStop = (
context.isMockingEnabled = false
window.clearInterval(context.keepAliveInterval)

// Clear the WebSocket clients from the shared storage.
localStorage.removeItem(MSW_WEBSOCKET_CLIENTS_KEY)

printStopMessage({ quiet: context.startOptions?.quiet })
}
}
20 changes: 19 additions & 1 deletion src/core/ws/WebSocketClientManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
} from '@mswjs/interceptors/WebSocket'
import { matchRequestUrl, type Path } from '../utils/matching/matchRequestUrl'

const MSW_WEBSOCKET_CLIENTS_KEY = 'msw:ws:clients'
export const MSW_WEBSOCKET_CLIENTS_KEY = 'msw:ws:clients'

export type WebSocketBroadcastChannelMessage =
| {
Expand Down Expand Up @@ -42,6 +42,22 @@ export class WebSocketClientManager {
private url: Path,
) {
this.inMemoryClients = new Set()

if (typeof localStorage !== 'undefined') {
// When the worker clears the local storage key in "worker.stop()",
// also clear the in-memory clients map.
localStorage.removeItem = new Proxy(localStorage.removeItem, {
apply: (target, thisArg, args) => {
const [key] = args

if (key === MSW_WEBSOCKET_CLIENTS_KEY) {
this.inMemoryClients.clear()
}

return Reflect.apply(target, thisArg, args)
},
})
}
}

/**
Expand All @@ -53,6 +69,8 @@ export class WebSocketClientManager {
if (typeof localStorage !== 'undefined') {
const inMemoryClients = Array.from(this.inMemoryClients)

console.log('get clients()', inMemoryClients, this.getSerializedClients())

return new Set(
inMemoryClients.concat(
this.getSerializedClients()
Expand Down
44 changes: 43 additions & 1 deletion test/browser/ws-api/ws.clients.browser.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { WebSocketLink, ws } from 'msw'
import type { setupWorker } from 'msw/browser'
import type { SetupWorker, setupWorker } from 'msw/browser'
import { test, expect } from '../playwright.extend'

declare global {
Expand All @@ -8,6 +8,7 @@ declare global {
ws: typeof ws
setupWorker: typeof setupWorker
}
worker: SetupWorker
link: WebSocketLink
ws: WebSocket
messages: string[]
Expand Down Expand Up @@ -164,3 +165,44 @@ test('broadcasts messages across runtimes', async ({
'hi from two',
])
})

test('clears the list of clients when the worker is stopped', async ({
loadExample,
page,
}) => {
await loadExample(require.resolve('./ws.runtime.js'), {
skipActivation: true,
})

await page.evaluate(async () => {
const { setupWorker, ws } = window.msw
const api = ws.link('wss://example.com')
const worker = setupWorker(api.on('connection', () => {}))
window.link = api
window.worker = worker
await worker.start()
})

await page.evaluate(async () => {
const ws = new WebSocket('wss://example.com')
await new Promise((done) => (ws.onopen = done))
})

// Must return 1 after a single client joined.
expect(
await page.evaluate(() => {
return window.link.clients.size
}),
).toBe(1)

await page.evaluate(() => {
window.worker.stop()
})

/**
* @fixme This will still be 1 because "inMemoryClients" in the manager
* keeps the client connection reference even when the localStorage is purged.
* Argh.
*/
expect(await page.evaluate(() => window.link.clients.size)).toBe(0)
})

0 comments on commit aca9f05

Please sign in to comment.