mirror of
https://github.com/hanzoai/msw.git
synced 2026-09-24 17:00:34 +00:00
Co-authored-by: Felmon Fekadu <[email protected]> Co-authored-by: Felmon Fekadu <[email protected]>
218 lines
5.8 KiB
TypeScript
218 lines
5.8 KiB
TypeScript
import type { SetupWorkerApi } from 'msw/browser'
|
|
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
|
import type { ConsoleMessages } from 'page-with'
|
|
import { test, expect } from '../../../playwright.extend'
|
|
|
|
declare namespace window {
|
|
export const msw: {
|
|
worker: SetupWorkerApi
|
|
}
|
|
}
|
|
|
|
const ON_EXAMPLE = new URL('./on.mocks.ts', import.meta.url)
|
|
|
|
const server = new HttpServer((app) => {
|
|
app.post('/no-response', (_req, res) => {
|
|
res.send('original-response')
|
|
})
|
|
app.get('/unknown-route', (_req, res) => {
|
|
res.status(404)
|
|
res.send('majestic-unknown')
|
|
})
|
|
app.get('/passthrough', (_req, res) => {
|
|
res.send('passthrough-response')
|
|
})
|
|
app.post('/bypass', (_req, res) => {
|
|
res.send('bypassed-response')
|
|
})
|
|
})
|
|
|
|
export function getRequestId(messages: ConsoleMessages) {
|
|
const requestStartMessage = messages.get('warning')?.find((message) => {
|
|
return message.startsWith('[request:start]')
|
|
})
|
|
return requestStartMessage?.split(' ')?.[3]
|
|
}
|
|
|
|
test.beforeAll(async () => {
|
|
await server.listen()
|
|
})
|
|
|
|
test.afterAll(async () => {
|
|
await server.close()
|
|
})
|
|
|
|
test('emits events for a handled request and mocked response', async ({
|
|
loadExample,
|
|
spyOnConsole,
|
|
fetch,
|
|
}) => {
|
|
const consoleSpy = spyOnConsole()
|
|
await loadExample(ON_EXAMPLE)
|
|
|
|
const url = server.http.url('/user')
|
|
await fetch(url)
|
|
const requestId = getRequestId(consoleSpy)
|
|
|
|
await expect
|
|
.poll(() => consoleSpy.get('warning'))
|
|
.toContainEqual(expect.stringContaining('[response:mocked]'))
|
|
|
|
expect(consoleSpy.get('warning')).toEqual([
|
|
`[request:start] GET ${url} ${requestId}`,
|
|
`[request:match] GET ${url} ${requestId}`,
|
|
`[request:end] GET ${url} ${requestId}`,
|
|
`[response:mocked] 400 ${url} response-body GET ${url} ${requestId}`,
|
|
])
|
|
})
|
|
|
|
test('emits events for a handled request with no response', async ({
|
|
loadExample,
|
|
spyOnConsole,
|
|
fetch,
|
|
}) => {
|
|
const consoleSpy = spyOnConsole()
|
|
await loadExample(ON_EXAMPLE)
|
|
|
|
const url = server.http.url('/no-response')
|
|
await fetch(url, { method: 'POST' })
|
|
const requestId = getRequestId(consoleSpy)
|
|
|
|
await expect
|
|
.poll(() => consoleSpy.get('warning'))
|
|
.toContainEqual(expect.stringContaining('[response:bypass]'))
|
|
|
|
expect(consoleSpy.get('warning')).toEqual([
|
|
`[request:start] POST ${url} ${requestId}`,
|
|
`[request:match] POST ${url} ${requestId}`,
|
|
`[request:end] POST ${url} ${requestId}`,
|
|
`[response:bypass] 200 ${url} original-response POST ${url} ${requestId}`,
|
|
])
|
|
})
|
|
|
|
test('emits events for an unhandled request', async ({
|
|
loadExample,
|
|
spyOnConsole,
|
|
fetch,
|
|
}) => {
|
|
const consoleSpy = spyOnConsole()
|
|
await loadExample(ON_EXAMPLE)
|
|
|
|
const url = server.http.url('/unknown-route')
|
|
await fetch(url)
|
|
const requestId = getRequestId(consoleSpy)
|
|
|
|
await expect
|
|
.poll(() => consoleSpy.get('warning'))
|
|
.toContainEqual(expect.stringContaining('[response:bypass]'))
|
|
|
|
expect(consoleSpy.get('warning')).toEqual([
|
|
`[request:start] GET ${url} ${requestId}`,
|
|
`[request:unhandled] GET ${url} ${requestId}`,
|
|
`[request:end] GET ${url} ${requestId}`,
|
|
`[response:bypass] 404 ${url} majestic-unknown GET ${url} ${requestId}`,
|
|
])
|
|
})
|
|
|
|
test('emits events for a passthrough request', async ({
|
|
loadExample,
|
|
spyOnConsole,
|
|
fetch,
|
|
}) => {
|
|
const consoleSpy = spyOnConsole()
|
|
await loadExample(ON_EXAMPLE)
|
|
|
|
// Explicit "passthrough()" request must go through the
|
|
// same request processing pipeline to contain both
|
|
// "request" and "response" in the life-cycle event listener.
|
|
const url = server.http.url('/passthrough')
|
|
await fetch(url)
|
|
const requestId = getRequestId(consoleSpy)
|
|
|
|
await expect
|
|
.poll(() => consoleSpy.get('warning'))
|
|
.toEqual([
|
|
`[request:start] GET ${url} ${requestId}`,
|
|
`[request:match] GET ${url} ${requestId}`,
|
|
`[request:end] GET ${url} ${requestId}`,
|
|
`[response:bypass] 200 ${url} passthrough-response GET ${url} ${requestId}`,
|
|
])
|
|
})
|
|
|
|
test('emits events for a bypassed request', async ({
|
|
loadExample,
|
|
spyOnConsole,
|
|
fetch,
|
|
page,
|
|
}) => {
|
|
const consoleSpy = spyOnConsole()
|
|
await loadExample(ON_EXAMPLE)
|
|
|
|
const pageErrors: Array<Error> = []
|
|
page.on('pageerror', (error) => pageErrors.push(error))
|
|
|
|
const url = server.http.url('/bypass')
|
|
await fetch(url)
|
|
|
|
// First, must print the events for the original (mocked) request.
|
|
await expect
|
|
.poll(() => consoleSpy.get('warning'))
|
|
.toEqual(
|
|
expect.arrayContaining([
|
|
expect.stringContaining(`[request:start] GET ${url}`),
|
|
expect.stringContaining(`[request:end] GET ${url}`),
|
|
expect.stringContaining(
|
|
`[response:mocked] 200 ${url} bypassed-response GET ${url}`,
|
|
),
|
|
]),
|
|
)
|
|
|
|
// Then, must also print events for the bypassed request.
|
|
expect(consoleSpy.get('warning')).toEqual(
|
|
expect.arrayContaining([
|
|
expect.stringContaining(`[request:start] POST ${url}`),
|
|
expect.stringContaining(`[request:end] POST ${url}`),
|
|
expect.stringContaining(
|
|
`[response:bypass] 200 ${url} bypassed-response POST ${url}`,
|
|
),
|
|
]),
|
|
)
|
|
|
|
expect(pageErrors).toEqual([])
|
|
})
|
|
|
|
test('emits unhandled exceptions in the request handler', async ({
|
|
loadExample,
|
|
spyOnConsole,
|
|
fetch,
|
|
}) => {
|
|
const consoleSpy = spyOnConsole()
|
|
await loadExample(ON_EXAMPLE)
|
|
|
|
const url = server.http.url('/unhandled-exception')
|
|
await fetch(url)
|
|
const requestId = getRequestId(consoleSpy)
|
|
|
|
expect(consoleSpy.get('warning')).toContain(
|
|
`[unhandledException] GET ${url} ${requestId} Unhandled resolver error`,
|
|
)
|
|
})
|
|
|
|
test('stops emitting events once the worker is stopped', async ({
|
|
loadExample,
|
|
spyOnConsole,
|
|
page,
|
|
}) => {
|
|
const consoleSpy = spyOnConsole()
|
|
await loadExample(ON_EXAMPLE)
|
|
|
|
await page.evaluate(() => {
|
|
return window.msw.worker.stop()
|
|
})
|
|
|
|
const url = server.http.url('/passthrough')
|
|
await page.evaluate((url) => fetch(url), url)
|
|
|
|
expect(consoleSpy.get('warning')).toBeUndefined()
|
|
})
|