### Install @msw/playwright Source: https://github.com/mswjs/playwright/blob/main/README.md Install the necessary packages for @msw/playwright integration. This includes `msw` and `@msw/playwright`. ```bash npm i msw @msw/playwright ``` -------------------------------- ### Setup Playwright with MSW Network Fixture Source: https://context7.com/mswjs/playwright/llms.txt Configure the Playwright test environment to use the MSW network fixture. This setup automatically enables request interception for all tests. ```typescript import { test as testBase } from '@playwright/test' import { http, HttpResponse, type AnyHandler } from 'msw' import { defineNetworkFixture, type NetworkFixture } from '@msw/playwright' import { handlers } from './mocks/handlers.js' interface Fixtures { handlers: Array network: NetworkFixture } export const test = testBase.extend({ // Default handlers shared across all tests (overridable per-test via the `handlers` option). handlers: [handlers, { option: true }], // The network fixture wires MSW into the Playwright BrowserContext. network: [ async ({ context, handlers }, use) => { const network = defineNetworkFixture({ context, // Required: Playwright BrowserContext handlers, // Optional: initial request handlers onUnhandledRequest: 'warn', // Optional: 'bypass' | 'warn' | 'error' (default: 'bypass') skipAssetRequests: true, // Optional: skip .html/.css/.js etc. (default: true) }) await network.enable() // Start intercepting requests await use(network) // Run the test await network.disable() // Tear down routes and dispose handlers }, { auto: true }, // Automatically apply to every test ], }) ``` -------------------------------- ### Mocking WebSocket Connections Source: https://context7.com/mswjs/playwright/llms.txt Illustrates how to mock WebSocket connections using MSW's `ws` namespace. This includes handling connection events, sending messages to the client, and echoing client messages. ```APIDOC ## ws.link('ws://localhost/api').addEventListener('connection', ...) - Mock WebSocket Connection ### Description Mocks a WebSocket connection to 'ws://localhost/api'. The handler can send messages to the client upon connection. ### Method WebSocket Event Listener ### Endpoint ws://localhost/api ### Parameters #### Event Handlers - **connection**: Callback function executed when a client connects. - **client**: Represents the connected WebSocket client. - **send(message)**: Sends a message to the client. ### Request Example ```ts const api = ws.link('ws://localhost/api') network.use( api.addEventListener('connection', ({ client }) => { client.send('hello from server') }) ) ``` ### Response Example ``` hello from server ``` ## ws.link('ws://localhost/api').addEventListener('connection', ...) - Echo WebSocket Messages ### Description Mocks a WebSocket connection to 'ws://localhost/api' that echoes messages received from the client back to the client. ### Method WebSocket Event Listener ### Endpoint ws://localhost/api ### Parameters #### Event Handlers - **connection**: Callback function executed when a client connects. - **client**: Represents the connected WebSocket client. - **addEventListener('message', handler)**: Listens for messages from the client. - **event.data**: The message data sent by the client. - **send(message)**: Sends a message to the client. ### Request Example ```ts const api = ws.link('ws://localhost/api') network.use( api.addEventListener('connection', ({ client }) => { client.addEventListener('message', (event) => { client.send(`echo: ${event.data}`) }) }) ) ``` ### Response Example ``` echo: ping ``` ## ws.link('ws://localhost/api').addEventListener('connection', ...) - Close WebSocket Connection ### Description Mocks a WebSocket connection to 'ws://localhost/api' that closes the connection with a specified code and reason. ### Method WebSocket Event Listener ### Endpoint ws://localhost/api ### Parameters #### Event Handlers - **connection**: Callback function executed when a client connects. - **client**: Represents the connected WebSocket client. - **close(code, reason)**: Closes the WebSocket connection. ### Request Example ```ts const api = ws.link('ws://localhost/api') network.use( api.addEventListener('connection', ({ client }) => { queueMicrotask(() => client.close(1000, 'done')) }) ) ``` ### Response Example ```json { "code": 1000, "reason": "done" } ``` ``` -------------------------------- ### Mocking HTTP Responses Source: https://context7.com/mswjs/playwright/llms.txt Demonstrates how to use `network.use()` with `HttpResponse` to mock different types of HTTP responses: JSON, text, and streams. It also shows how to simulate network errors. ```APIDOC ## http.get('/api/items') - Mock JSON Response ### Description Mocks an HTTP GET request to '/api/items' and returns a JSON response. ### Method GET ### Endpoint /api/items ### Request Body None ### Response #### Success Response (200) - **body** (array) - A JSON array of items. ### Request Example ```ts network.use( http.get('/api/items', () => HttpResponse.json([{ id: 1, name: 'Widget' }])) ) ``` ### Response Example ```json [ { "id": 1, "name": "Widget" } ] ``` ## http.get('/api/ping') - Mock Text Response ### Description Mocks an HTTP GET request to '/api/ping' and returns a plain text response. ### Method GET ### Endpoint /api/ping ### Request Body None ### Response #### Success Response (200) - **body** (string) - The text 'pong'. ### Request Example ```ts network.use(http.get('/api/ping', () => HttpResponse.text('pong'))) ``` ### Response Example ``` pong ``` ## http.get('/api/stream') - Mock Streaming Response ### Description Mocks an HTTP GET request to '/api/stream' and returns a streaming response. ### Method GET ### Endpoint /api/stream ### Request Body None ### Response #### Success Response (200) - **body** (ReadableStream) - A stream of text chunks. ### Request Example ```ts network.use( http.get('/api/stream', () => { const stream = new ReadableStream({ start(controller) { controller.enqueue(new TextEncoder().encode('chunk1')) controller.enqueue(new TextEncoder().encode('chunk2')) controller.close() }, }) return new HttpResponse(stream) }), ) ``` ### Response Example ``` chunk1chunk2 ``` ## http.get('/api/fail') - Simulate Network Error ### Description Mocks an HTTP GET request to '/api/fail' to simulate a network error. ### Method GET ### Endpoint /api/fail ### Request Body None ### Response #### Error Response - Simulates a fetch failure. ### Request Example ```ts network.use(http.get('/api/fail', () => HttpResponse.error())) ``` ``` -------------------------------- ### Proxying WebSocket Connections Source: https://context7.com/mswjs/playwright/llms.txt Explains how to use `server.connect()` to proxy WebSocket connections to the real server while intercepting and modifying messages. ```APIDOC ## ws.link('wss://realtime.example.com/feed').addEventListener('connection', ...) - Proxy WebSocket Connection ### Description Establishes a proxy connection to a real WebSocket server ('wss://realtime.example.com/feed'). It allows intercepting messages from the server, modifying them, and sending them to the client, as well as sending synthetic messages to the client. ### Method WebSocket Event Listener ### Endpoint wss://realtime.example.com/feed ### Parameters #### Event Handlers - **connection**: Callback function executed when a client connects. - **client**: Represents the connected WebSocket client. - **send(message)**: Sends a message to the client. - **server**: Represents the connection to the real WebSocket server. - **connect()**: Establishes the connection to the real server. - **addEventListener('message', handler)**: Listens for messages from the real server. - **event.data**: The message data received from the server. ### Request Example ```ts const api = ws.link('wss://realtime.example.com/feed') network.use( api.addEventListener('connection', ({ client, server }) => { server.connect() server.addEventListener('message', (event) => { const data = JSON.parse(event.data as string) client.send(JSON.stringify({ ...data, injected: true })) }) client.send(JSON.stringify({ type: 'connected', injected: true })) }) ) ``` ``` -------------------------------- ### Mock HTTP Requests on Dynamically Created Pages Source: https://context7.com/mswjs/playwright/llms.txt Handlers defined with `network.use()` apply to all pages within the `BrowserContext`, including those created programmatically with `context.newPage()`. ```typescript import { http, HttpResponse } from 'msw' import { test, expect } from './playwright.setup.js' test('mocks requests on a dynamically created page', async ({ network, context }) => { network.use( http.get('/api/data', () => HttpResponse.json({ value: 42 })), ) const newPage = await context.newPage() await newPage.goto('/') const result = await newPage.evaluate(async () => { const res = await fetch('/api/data') return res.json() }) expect(result).toEqual({ value: 42 }) }) ``` -------------------------------- ### Configure Playwright Test Fixtures with @msw/playwright Source: https://github.com/mswjs/playwright/blob/main/README.md Set up custom Playwright test fixtures to manage network handlers and enable network mocking. The `network` fixture uses `defineNetworkFixture` to initialize and control the MSW worker within the Playwright context. ```typescript // playwright.setup.ts import { test as testBase } from '@playwright/test' import { type AnyHandler } from 'msw' import { defineNetworkFixture, type NetworkFixture } from '@msw/playwright' import { handlers } from '../mocks/handlers.js' interface Fixtures { handlers: Array network: NetworkFixture } const test = testBase.extend({ // Initial list of the network handlers. handlers: [handlers, { option: true }], // A fixture you use to control the network in your tests. network: [ async ({ context, handlers }, use) => { const network = defineNetworkFixture({ context, handlers, }) await network.enable() await use(network) await network.disable() }, { auto: true }, ], }) ``` -------------------------------- ### defineNetworkFixture(options) Source: https://context7.com/mswjs/playwright/llms.txt Creates a NetworkFixture instance that intercepts HTTP and WebSocket traffic for a Playwright BrowserContext. This fixture mirrors the setupWorker API from MSW and integrates with Playwright's routing. ```APIDOC ## defineNetworkFixture(options) — Create a network fixture for Playwright ### Description Creates and returns a `NetworkFixture` instance that intercepts HTTP and WebSocket traffic for a Playwright `BrowserContext`. The returned object exposes `enable()`, `disable()`, and the full MSW `use()` / `resetHandlers()` / `restoreHandlers()` API. ### Parameters #### Request Body - **context** (BrowserContext) - Required - Playwright BrowserContext. - **handlers** (Array) - Optional - Initial MSW request/WS handlers. - **onUnhandledRequest** (UnhandledRequestStrategy) - Optional - Strategy for unhandled requests ('bypass' | 'warn' | 'error'). Defaults to 'bypass'. - **skipAssetRequests** (boolean) - Optional - Whether to skip common asset requests like .html/.css/.js. Defaults to true. ### Request Example ```ts // playwright.setup.ts import { test as testBase } from '@playwright/test' import { http, HttpResponse, type AnyHandler } from 'msw' import { defineNetworkFixture, type NetworkFixture } from '@msw/playwright' import { handlers } from './mocks/handlers.js' interface Fixtures { handlers: Array network: NetworkFixture } export const test = testBase.extend({ // Default handlers shared across all tests (overridable per-test via the `handlers` option). handlers: [handlers, { option: true }], // The network fixture wires MSW into the Playwright BrowserContext. network: [ async ({ context, handlers }, use) => { const network = defineNetworkFixture({ context, // Required: Playwright BrowserContext handlers, // Optional: initial request handlers onUnhandledRequest: 'warn', // Optional: 'bypass' | 'warn' | 'error' (default: 'bypass') skipAssetRequests: true, // Optional: skip .html/.css/.js etc. (default: true) }) await network.enable() // Start intercepting requests await use(network) // Run the test await network.disable() // Tear down routes and dispose handlers }, { auto: true }, // Automatically apply to every test ], }) ``` ``` -------------------------------- ### Enable Asset Request Interception with `skipAssetRequests: false` Source: https://context7.com/mswjs/playwright/llms.txt Configure the network fixture to intercept common asset requests like .html, .js, and .css by setting `skipAssetRequests` to `false`. This is useful when you need to mock these assets. ```typescript import { http, HttpResponse } from 'msw' import { test as testBase, expect } from '@playwright/test' import { defineNetworkFixture, type NetworkFixture, type NetworkFixtureOptions } from '@msw/playwright' // Custom fixture with asset interception enabled const test = testBase.extend<{ network: NetworkFixture }>({ network: [ async ({ context }, use) => { const network = defineNetworkFixture({ context, skipAssetRequests: false, // Allow intercepting .html, .js, etc. }) await network.enable() await use(network) await network.disable() }, { auto: true }, ], }) test('intercepts an HTML asset request', async ({ network, page }) => { network.use( http.get('/index.html', () => { return HttpResponse.text('Mocked!', { headers: { 'Content-Type': 'text/html' }, }) }), ) await page.goto('/') const body = await page.evaluate(() => fetch('/index.html').then(r => r.text())) expect(body).toBe('Mocked!') }) ``` -------------------------------- ### NetworkFixtureOptions Interface Source: https://context7.com/mswjs/playwright/llms.txt Defines the configuration options for the `defineNetworkFixture` function. The `context` is mandatory, while other options control request handling and asset skipping. ```typescript import type { BrowserContext } from '@playwright/test' import type { AnyHandler, UnhandledRequestStrategy } from 'msw' interface NetworkFixtureOptions { context: BrowserContext // Playwright BrowserContext (required) handlers?: Array // Initial MSW request/WS handlers onUnhandledRequest?: UnhandledRequestStrategy // 'bypass' | 'warn' | 'error' skipAssetRequests?: boolean // Skip common assets (default: true) } ``` -------------------------------- ### network.use(...handlers) Source: https://context7.com/mswjs/playwright/llms.txt Adds runtime handlers for the current test. These handlers take precedence over the initial handlers and are reset after the test when `network.disable()` is called. ```APIDOC ## network.use(...handlers) — Add one-time or override handlers ### Description Adds runtime handlers for the current test. These handlers take precedence over the initial handlers and are reset after the test when `network.disable()` is called. ### Parameters #### Request Body - **...handlers** (AnyHandler) - One or more MSW request handlers to be used for the current test. ### Request Example ```ts // my-test.spec.ts import { http, HttpResponse, graphql } from 'msw' import { test, expect } from './playwright.setup.js' test('displays user dashboard with mocked data', async ({ network, page }) => { // Override: return mocked JSON for this test only network.use( http.get('/api/user', () => { return HttpResponse.json({ id: 'abc-123', firstName: 'John', lastName: 'Maverick', }) }), // Also mock a POST endpoint http.post('/api/login', async ({ request }) => { const body = await request.json() if (body.username === 'admin') { return HttpResponse.json({ token: 'secret-token' }, { status: 200 }) } return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 }) }), ) await page.goto('/dashboard') await expect(page.getByText('John Maverick')).toBeVisible() }) ``` ``` -------------------------------- ### Mocking WebSocket Connections with `ws` Source: https://context7.com/mswjs/playwright/llms.txt Intercept and mock WebSocket connections using MSW's `ws` namespace. Use `ws.link(url)` to bind handlers to specific URLs and manage client/server events. ```ts import { ws } from 'msw' import { test, expect } from './playwright.setup.js' const api = ws.link('ws://localhost/api') test('sends a message to the client on connection', async ({ network, page }) => { network.use( api.addEventListener('connection', ({ client }) => { client.send('hello from server') }), ) await page.goto('/') const message = await page.evaluate(() => { return new Promise((resolve, reject) => { const socket = new WebSocket('ws://localhost/api') socket.onerror = () => reject('connection failed') socket.onmessage = (event) => resolve(event.data) }) }) expect(message).toBe('hello from server') }) ``` ```ts test('echoes client messages back', async ({ network, page }) => { network.use( api.addEventListener('connection', ({ client }) => { client.addEventListener('message', (event) => { client.send(`echo: ${event.data}`) }) }), ) await page.goto('/') const reply = await page.evaluate(() => { return new Promise((resolve) => { const socket = new WebSocket('ws://localhost/api') socket.onopen = () => socket.send('ping') socket.onmessage = (event) => resolve(event.data) }) }) expect(reply).toBe('echo: ping') }) ``` ```ts test('closes the connection with a custom code', async ({ network, page }) => { network.use( api.addEventListener('connection', ({ client }) => { queueMicrotask(() => client.close(1000, 'done')) }), ) await page.goto('/') const result = await page.evaluate(() => { return new Promise<{ code: number; reason: string }>((resolve) => { const socket = new WebSocket('ws://localhost/api') socket.onclose = (event) => resolve({ code: event.code, reason: event.reason }) }) }) expect(result).toEqual({ code: 1000, reason: 'done' }) }) ``` -------------------------------- ### Mocking HTTP Responses with HttpResponse Source: https://context7.com/mswjs/playwright/llms.txt Use `HttpResponse` to mock various response types like JSON, text, streams, and network errors. Ensure necessary imports from 'msw' and your testing utility. ```ts import { http, HttpResponse } from 'msw' import { test, expect } from './playwright.setup.js' test('mocks a JSON response', async ({ network, page }) => { network.use( http.get('/api/items', () => HttpResponse.json([{ id: 1, name: 'Widget' }])), ) await page.goto('/') const data = await page.evaluate(() => fetch('/api/items').then(r => r.json())) expect(data).toEqual([{ id: 1, name: 'Widget' }]) }) ``` ```ts test('mocks a text response', async ({ network, page }) => { network.use(http.get('/api/ping', () => HttpResponse.text('pong'))) await page.goto('/') const text = await page.evaluate(() => fetch('/api/ping').then(r => r.text())) expect(text).toBe('pong') }) ``` ```ts test('mocks a streaming response', async ({ network, page }) => { network.use( http.get('/api/stream', () => { const stream = new ReadableStream({ start(controller) { controller.enqueue(new TextEncoder().encode('chunk1')) controller.enqueue(new TextEncoder().encode('chunk2')) controller.close() }, }) return new HttpResponse(stream) }), ) await page.goto('/') const result = await page.evaluate(() => fetch('/api/stream').then(r => r.text())) expect(result).toBe('chunk1chunk2') }) ``` ```ts test('simulates a network error', async ({ network, page }) => { network.use(http.get('/api/fail', () => HttpResponse.error())) await page.goto('/') const error = await page.evaluate(() => fetch('/api/fail').catch((e: Error) => e.message), ) expect(error).toBe('Failed to fetch') }) ``` -------------------------------- ### Mock WebSocket Events on Dynamically Created Pages Source: https://context7.com/mswjs/playwright/llms.txt Intercept and mock WebSocket events, such as connection messages, on pages created dynamically within the test context. ```typescript import { http, HttpResponse, ws } from 'msw' import { test, expect } from './playwright.setup.js' test('mocks WebSocket on a dynamically created page', async ({ network, context }) => { const api = ws.link('ws://localhost:5173/api') network.use( api.addEventListener('connection', ({ client }) => { client.send('hello from fixture') }), ) const newPage = await context.newPage() await newPage.goto('/') const message = await newPage.evaluate(() => { const pending = Promise.withResolvers() const socket = new WebSocket('/api') socket.onmessage = (e) => pending.resolve(e.data) socket.onerror = () => pending.reject('error') return pending.promise }) expect(message).toBe('hello from fixture') }) ``` -------------------------------- ### Add Runtime Handlers with network.use() Source: https://context7.com/mswjs/playwright/llms.txt Temporarily add or override request handlers for a specific test. These handlers take precedence and are automatically reset after the test. ```typescript import { http, HttpResponse, graphql } from 'msw' import { test, expect } from './playwright.setup.js' test('displays user dashboard with mocked data', async ({ network, page }) => { // Override: return mocked JSON for this test only network.use( http.get('/api/user', () => { return HttpResponse.json({ id: 'abc-123', firstName: 'John', lastName: 'Maverick', }) }), // Also mock a POST endpoint http.post('/api/login', async ({ request }) => { const body = await request.json() if (body.username === 'admin') { return HttpResponse.json({ token: 'secret-token' }, { status: 200 }) } return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 }) }), ) await page.goto('/dashboard') await expect(page.getByText('John Maverick')).toBeVisible() }) ``` -------------------------------- ### Proxying WebSocket Connections with `server.connect()` Source: https://context7.com/mswjs/playwright/llms.txt Use `server.connect()` within a WebSocket connection handler to proxy traffic to the real server. This allows intercepting and modifying messages while maintaining the live connection. ```ts import { ws } from 'msw' import { test, expect } from './playwright.setup.js' test('proxies to the real server and injects a message', async ({ network, page }) => { const api = ws.link('wss://realtime.example.com/feed') network.use( api.addEventListener('connection', ({ client, server }) => { // Establish the real server connection server.connect() // Intercept messages from the server and modify them server.addEventListener('message', (event) => { const data = JSON.parse(event.data as string) client.send(JSON.stringify({ ...data, injected: true })) }) // Also send a synthetic message to the client immediately client.send(JSON.stringify({ type: 'connected', injected: true })) }), ) await page.goto('/') // ... assertions }) ``` -------------------------------- ### Configure `onUnhandledRequest` Behavior Source: https://context7.com/mswjs/playwright/llms.txt Control how unmatched requests are handled. Set to 'warn' to log a console warning or 'error' to fail the test, ensuring no unintended real network requests are made. ```typescript import { defineNetworkFixture } from '@msw/playwright' // In your fixture setup: const network = defineNetworkFixture({ context, onUnhandledRequest: 'warn', // Console output for unhandled GET http://localhost/unmatched: // [MSW] Warning: intercepted a request without a matching request handler: // • GET http://localhost/unmatched // If you still wish to intercept this unhandled request, please create a request handler for it. }) // Or throw an error to fail the test on any unhandled request (strict mode): const strictNetwork = defineNetworkFixture({ context, onUnhandledRequest: 'error', }) ``` -------------------------------- ### Mocking API Requests in Playwright Tests Source: https://github.com/mswjs/playwright/blob/main/README.md Use the `network` fixture provided by `@msw/playwright` to mock specific API requests within your Playwright tests. This allows you to simulate responses for endpoints like `/user` and test your application's UI behavior. ```typescript import { http, HttpResponse } from 'msw' import { test } from './playwright.setup.js' test('displays the user dashboard', async ({ network, page }) => { // Access the network fixture and use it as the `setupWorker()` API. // No more disrupted context between processes. network.use( http.get('/user', () => { return HttpResponse.json({ id: 'abc-123', firstName: 'John', lastName: 'Maverick', }) }), ) await page.goto('/dashboard') }) ``` -------------------------------- ### Accessing MSW Worker in Playwright Evaluate Source: https://github.com/mswjs/playwright/blob/main/README.md When using MSW in Playwright's `page.evaluate`, you need to expose the worker instance and its utilities (like `http`, `graphql`) to the `window` object. This allows you to reference and use them within the browser context. ```typescript await page.evaluate(() => { // In order to reference the worker instance in your tests, // you have to set it on `window` alongside any other // functions from the `msw` package you want to use since // you cannot reference them in `page.evaluate` directly. const { worker, http, graphql } = window.msw worker.use(...overrides) }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.