Skip to content

Commit

Permalink
feat: isolate parent and child frames when handling requests (#2324)
Browse files Browse the repository at this point in the history
  • Loading branch information
kettanaito authored Oct 22, 2024
1 parent c949d19 commit a1a81ba
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 5 deletions.
7 changes: 6 additions & 1 deletion src/browser/setupWorker/glossary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ export type ServiceWorkerIncomingResponse = Pick<
* Map of the events that can be received from the Service Worker.
*/
export interface ServiceWorkerIncomingEventsMap {
MOCKING_ENABLED: boolean
MOCKING_ENABLED: {
client: {
id: string
frameType: string
}
}
INTEGRITY_CHECK_RESPONSE: {
packageVersion: string
checksum: string
Expand Down
3 changes: 2 additions & 1 deletion src/browser/setupWorker/start/utils/enableMocking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export async function enableMocking(
options: StartOptions,
) {
context.workerChannel.send('MOCK_ACTIVATE')
await context.events.once('MOCKING_ENABLED')
const { payload } = await context.events.once('MOCKING_ENABLED')

// Warn the developer on multiple "worker.start()" calls.
// While this will not affect the worker in any way,
Expand All @@ -28,5 +28,6 @@ export async function enableMocking(
quiet: options.quiet,
workerScope: context.registration?.scope,
workerUrl: context.worker?.scriptURL,
client: payload.client,
})
}
7 changes: 7 additions & 0 deletions src/browser/setupWorker/start/utils/printStartMessage.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { ServiceWorkerIncomingEventsMap } from 'browser/setupWorker/glossary'
import { devUtils } from '~/core/utils/internal/devUtils'

export interface PrintStartMessageArgs {
quiet?: boolean
message?: string
workerUrl?: string
workerScope?: string
client?: ServiceWorkerIncomingEventsMap['MOCKING_ENABLED']['client']
}

/**
Expand Down Expand Up @@ -41,6 +43,11 @@ export function printStartMessage(args: PrintStartMessageArgs = {}) {
console.log('Worker scope:', args.workerScope)
}

if (args.client) {
// eslint-disable-next-line no-console
console.log('Client ID: %s (%s)', args.client.id, args.client.frameType)
}

// eslint-disable-next-line no-console
console.groupEnd()
}
11 changes: 10 additions & 1 deletion src/mockServiceWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ self.addEventListener('message', async function (event) {

sendToClient(client, {
type: 'MOCKING_ENABLED',
payload: true,
payload: {
client: {
id: client.id,
frameType: client.frameType,
},
},
})
break
}
Expand Down Expand Up @@ -155,6 +160,10 @@ async function handleRequest(event, requestId) {
async function resolveMainClient(event) {
const client = await self.clients.get(event.clientId)

if (activeClientIds.has(event.clientId)) {
return client
}

if (client?.frameType === 'top-level') {
return client
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { setupWorker } from 'msw/browser'
const worker = setupWorker()
worker.start()

// @ts-ignore
window.msw = {
// @ts-ignore
worker,
http,
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const staticMiddleware = (router: express.Router) => {
router.use(express.static(__dirname))
}

function getFrameById(id: string, page: Page): Frame {
export function getFrameById(id: string, page: Page): Frame {
const frame = page
.mainFrame()
.childFrames()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { http } from 'msw'
import { setupWorker } from 'msw/browser'

const worker = setupWorker(
http.get('/resource', () => {
return new Response('hello world')
}),
)

worker.start()
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { test, expect } from '../../../../../playwright.extend'

test('intercepts a request issued by child frame when both child and parent have MSW', async ({
webpackServer,
page,
}) => {
const parentCompilation = await webpackServer.compile([
require.resolve('./parent.mocks.ts'),
])
const childCompilation = await webpackServer.compile([
require.resolve('./child.mocks.ts'),
])

await page.goto(parentCompilation.previewUrl, { waitUntil: 'networkidle' })

await page.evaluate((childFrameUrl) => {
const iframe = document.createElement('iframe')
iframe.setAttribute('id', 'child-frame')
iframe.setAttribute('src', childFrameUrl)
document.body.appendChild(iframe)
}, childCompilation.previewUrl)

const childFrameElement = await page.locator('#child-frame').elementHandle()
const childFrame = await childFrameElement!.contentFrame()
await childFrame!.waitForLoadState('networkidle')

const responseText = await childFrame!.evaluate(async () => {
const response = await fetch('/resource')
return response.text()
})

expect(responseText).toBe('hello world')
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { setupWorker } from 'msw/browser'

// The parent frame has a worker without any handlers.
const worker = setupWorker()

// This registration is awaited by the `loadExample` command in the test.
worker.start()

0 comments on commit a1a81ba

Please sign in to comment.