Skip to content

Commit

Permalink
test: add isolated response test for iframes (#2205)
Browse files Browse the repository at this point in the history
  • Loading branch information
kettanaito committed Jul 18, 2024
1 parent 1a0b39d commit e52f10b
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<iframe id="frame-one" src="./one.html"></iframe>
<iframe id="frame-two" src="./two.html"></iframe>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { http } from 'msw'
import { setupWorker } from 'msw/browser'

const worker = setupWorker()
worker.start()

// @ts-ignore
window.msw = {
worker,
http,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as path from 'path'
import * as express from 'express'
import type { Frame, Page } from '@playwright/test'
import { test, expect } from '../../../../playwright.extend'

const staticMiddleware = (router: express.Router) => {
router.use(express.static(__dirname))
}

function getFrameById(id: string, page: Page): Frame {
const frame = page
.mainFrame()
.childFrames()
.find((frame) => frame.name() === id)

if (!frame) {
throw new Error(`Unable to find frame with id "${id}" on the page`)
}

return frame
}

test('responds with different responses for the same request based on request referrer (frame url)', async ({
loadExample,
page,
}) => {
await loadExample(require.resolve('./iframe-isolated-response.mocks.ts'), {
markup: path.resolve(__dirname, 'app.html'),
beforeNavigation(compilation) {
compilation.use(staticMiddleware)
},
})

const frameOne = getFrameById('frame-one', page)!
const frameTwo = getFrameById('frame-two', page)!

await Promise.all([
frameOne.evaluate(() => window.request()),
frameTwo.evaluate(() => window.request()),
])

/**
* @note Each frame is able to receive a unique response
* because it uses the `isolatedResolver` utility.
* It's IMPORTANT it runs in the frame's context. We cannot
* ship that logic in MSW because MSW always runs in the
* main thread (the top-level client, which is the parent).
*/
await expect(frameOne.getByText('one')).toBeVisible()
await expect(frameTwo.getByText('two')).toBeVisible()
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script>
const { worker, http } = window.parent.msw

function isolatedResolver(resolver) {
return (info) => {
if (info.request.referrer !== location.href) {
return
}
return resolver(info)
}
}

worker.use(
http.get(
'./resource',
isolatedResolver(({ request }) => {
return new Response('one')
}),
),
)

window.request = () => {
return fetch('./resource')
.then((response) => response.text())
.then((data) => {
const node = document.createElement('p')
node.innerText = data
document.body.appendChild(node)
})
.catch((error) => console.error(error))
}

document.addEventListener('click', window.request)
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script>
const { worker, http } = window.parent.msw

function isolatedResolver(resolver) {
return (info) => {
if (info.request.referrer !== location.href) {
return
}
return resolver(info)
}
}

worker.use(
http.get(
'./resource',
isolatedResolver(({ request }) => {
return new Response('two')
}),
),
)

window.request = () => {
return fetch('./resource')
.then((response) => response.text())
.then((data) => {
const node = document.createElement('p')
node.innerText = data
document.body.appendChild(node)
})
.catch((error) => console.error(error))
}

document.addEventListener('click', window.request)
</script>

0 comments on commit e52f10b

Please sign in to comment.