diff --git a/.github/workflows/release-preview.yml b/.github/workflows/release-preview.yml index 7ff57bf94..7c97fb2af 100644 --- a/.github/workflows/release-preview.yml +++ b/.github/workflows/release-preview.yml @@ -3,8 +3,8 @@ name: release-preview on: pull_request: push: - branches: - - '**' + branches-ignore: + - 'main' tags: - '!**' workflow_dispatch: diff --git a/package.json b/package.json index 703417b42..6697892b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "msw", - "version": "2.10.4", + "version": "2.10.5", "description": "Seamless REST/GraphQL API mocking library for browser and Node.js.", "type": "commonjs", "main": "./lib/core/index.js", diff --git a/src/core/index.ts b/src/core/index.ts index 4c079a284..aafc36394 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -49,6 +49,7 @@ export type { GraphQLQuery, GraphQLVariables, GraphQLRequestBody, + GraphQLResponseBody, GraphQLJsonRequestBody, } from './handlers/GraphQLHandler' export type { GraphQLRequestHandler, GraphQLResponseResolver } from './graphql' diff --git a/test/browser/msw-api/setup-worker/start/on-unhandled-request/warn.test.ts b/test/browser/msw-api/setup-worker/start/on-unhandled-request/warn.test.ts index aff193e91..27eddb41b 100644 --- a/test/browser/msw-api/setup-worker/start/on-unhandled-request/warn.test.ts +++ b/test/browser/msw-api/setup-worker/start/on-unhandled-request/warn.test.ts @@ -4,11 +4,15 @@ test('warns on an unhandled REST API request with an absolute URL', async ({ loadExample, spyOnConsole, fetch, + createServer, }) => { + const server = await createServer((app) => { + app.get('/resource', (req, res) => res.status(404).end()) + }) const consoleSpy = spyOnConsole() await loadExample(new URL('./warn.mocks.ts', import.meta.url)) - const res = await fetch('https://mswjs.io/non-existing-page') + const res = await fetch(server.http.url('/resource')) const status = res.status() expect(status).toBe(404) @@ -17,7 +21,7 @@ test('warns on an unhandled REST API request with an absolute URL', async ({ expect.stringContaining(`\ [MSW] Warning: intercepted a request without a matching request handler: - • GET https://mswjs.io/non-existing-page + • GET ${server.http.url('/resource')} If you still wish to intercept this unhandled request, please create a request handler for it. Read more: https://mswjs.io/docs/http/intercepting-requests`), @@ -102,7 +106,7 @@ test('ignores common static assets when using the "warn" strategy', async ({ // This request will error so perform it accordingly. await page.evaluate(() => { - return fetch('https://example.com/styles/main.css').catch(() => null) + return fetch('http://localhost/styles/main.css').catch(() => null) }) expect(consoleSpy.get('warning')).toBeUndefined() diff --git a/test/browser/playwright.extend.ts b/test/browser/playwright.extend.ts index bd90bfa1b..8606b3047 100644 --- a/test/browser/playwright.extend.ts +++ b/test/browser/playwright.extend.ts @@ -20,6 +20,7 @@ import { import { waitFor } from '../support/waitFor' import { WorkerConsole } from './setup/workerConsole' import { getWebpackServer } from './setup/webpackHttpServer' +import { WebSocketServer } from '../support/WebSocketServer' export interface TestFixtures { /** @@ -50,6 +51,7 @@ export interface TestFixtures { spyOnConsole(): ConsoleMessages waitFor(predicate: () => unknown): Promise waitForMswActivation(): Promise + defineWebSocketServer(): Promise } interface FetchOptions { @@ -319,6 +321,14 @@ export const test = base.extend({ messages?.clear() }, + async defineWebSocketServer({ page }, use) { + const server = new WebSocketServer() + await use(async () => { + await server.listen() + return server + }) + await server.close() + }, }) export { expect } diff --git a/test/browser/rest-api/request/body/body-arraybuffer-range.mocks.ts b/test/browser/rest-api/request/body/body-arraybuffer-range.mocks.ts new file mode 100644 index 000000000..0babf22be --- /dev/null +++ b/test/browser/rest-api/request/body/body-arraybuffer-range.mocks.ts @@ -0,0 +1,31 @@ +import { http, HttpResponse } from 'msw' +import { setupWorker } from 'msw/browser' + +const buffer = new TextEncoder().encode('hello world') + +const worker = setupWorker( + http.get('/resource', async ({ request }) => { + const range = request.headers.get('range') + + if (!range) { + throw new Response('Missing range', { status: 400 }) + } + + const ranges = range.replace(/bytes=/, '').split('-') + const start = +ranges[0] + const end = ranges[1] ? +ranges[1] : buffer.byteLength - 1 + const content = buffer.slice(start, end) + + return HttpResponse.arrayBuffer(content, { + status: 206, + headers: { + 'accept-range': 'bytes', + 'content-range': `bytes=${start}-${end}/${buffer.byteLength}`, + 'content-length': content.byteLength.toString(), + 'content-type': 'text/plain', + }, + }) + }), +) + +worker.start() diff --git a/test/browser/rest-api/request/body/body-arraybuffer-range.test.ts b/test/browser/rest-api/request/body/body-arraybuffer-range.test.ts new file mode 100644 index 000000000..660adec14 --- /dev/null +++ b/test/browser/rest-api/request/body/body-arraybuffer-range.test.ts @@ -0,0 +1,19 @@ +import { test, expect } from '../../../playwright.extend' + +test('responds with a range of a mocked buffer response', async ({ + loadExample, + fetch, +}) => { + await loadExample( + new URL('./body-arraybuffer-range.mocks.ts', import.meta.url), + ) + + const response = await fetch('/resource', { + headers: { + range: 'bytes=4-8', + }, + }) + + expect.soft(response.status()).toBe(206) + await expect.soft(response.text()).resolves.toBe('o wo') +}) diff --git a/test/browser/ws-api/ws.intercept.server.browser.test.ts b/test/browser/ws-api/ws.intercept.server.browser.test.ts index 324d40966..80c97bcb6 100644 --- a/test/browser/ws-api/ws.intercept.server.browser.test.ts +++ b/test/browser/ws-api/ws.intercept.server.browser.test.ts @@ -1,7 +1,6 @@ import type { ws } from 'msw' import type { setupWorker } from 'msw/browser' import { test, expect } from '../playwright.extend' -import { WebSocketServer } from '../../support/WebSocketServer' declare global { interface Window { @@ -12,20 +11,12 @@ declare global { } } -const server = new WebSocketServer() - -test.beforeAll(async () => { - await server.listen() -}) - -test.afterAll(async () => { - await server.close() -}) - test('intercepts incoming server text message', async ({ loadExample, page, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, }) @@ -71,7 +62,9 @@ test('intercepts incoming server text message', async ({ test('intercepts incoming server Blob message', async ({ loadExample, page, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, }) @@ -121,7 +114,9 @@ test('intercepts incoming server Blob message', async ({ test('intercepts outgoing server ArrayBuffer message', async ({ loadExample, page, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, }) diff --git a/test/browser/ws-api/ws.logging.browser.test.ts b/test/browser/ws-api/ws.logging.browser.test.ts index fe1679c47..d0bcea3c1 100644 --- a/test/browser/ws-api/ws.logging.browser.test.ts +++ b/test/browser/ws-api/ws.logging.browser.test.ts @@ -1,7 +1,6 @@ import type { ws } from 'msw' import type { setupWorker } from 'msw/browser' import { test, expect } from '../playwright.extend' -import { WebSocketServer } from '../../support/WebSocketServer' declare global { interface Window { @@ -12,20 +11,6 @@ declare global { } } -const server = new WebSocketServer() - -test.beforeAll(async () => { - await server.listen() -}) - -test.afterEach(async () => { - server.resetState() -}) - -test.afterAll(async () => { - await server.close() -}) - test('does not log anything if "quiet" was set to "true"', async ({ loadExample, page, @@ -132,7 +117,9 @@ test('logs the close event initiated by the original server', async ({ spyOnConsole, page, waitFor, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() const consoleSpy = spyOnConsole() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, @@ -420,7 +407,9 @@ test('logs incoming server messages', async ({ page, spyOnConsole, waitFor, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() const consoleSpy = spyOnConsole() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, @@ -484,7 +473,9 @@ test('logs raw incoming server events', async ({ page, spyOnConsole, waitFor, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() const consoleSpy = spyOnConsole() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, @@ -539,7 +530,9 @@ test('logs mocked outgoing client message (server.send)', async ({ page, spyOnConsole, waitFor, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() const consoleSpy = spyOnConsole() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, @@ -577,7 +570,9 @@ test('logs mocked incoming server message (client.send)', async ({ page, spyOnConsole, waitFor, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() const consoleSpy = spyOnConsole() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, @@ -614,7 +609,9 @@ test('marks the prevented outgoing client event as dashed', async ({ page, spyOnConsole, waitFor, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() const consoleSpy = spyOnConsole() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, @@ -654,7 +651,9 @@ test('marks the prevented incoming server event as dashed', async ({ page, spyOnConsole, waitFor, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() const consoleSpy = spyOnConsole() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, diff --git a/test/browser/ws-api/ws.server.connect.browser.test.ts b/test/browser/ws-api/ws.server.connect.browser.test.ts index 027c86d95..215cdd198 100644 --- a/test/browser/ws-api/ws.server.connect.browser.test.ts +++ b/test/browser/ws-api/ws.server.connect.browser.test.ts @@ -1,7 +1,6 @@ import type { ws } from 'msw' import type { setupWorker } from 'msw/browser' import { test, expect } from '../playwright.extend' -import { WebSocketServer } from '../../support/WebSocketServer' declare global { interface Window { @@ -12,20 +11,12 @@ declare global { } } -const server = new WebSocketServer() - -test.beforeAll(async () => { - await server.listen() -}) - -test.afterAll(async () => { - await server.close() -}) - test('does not connect to the actual server by default', async ({ loadExample, page, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, }) @@ -61,7 +52,9 @@ test('does not connect to the actual server by default', async ({ test('forwards incoming server events to the client once connected', async ({ loadExample, page, + defineWebSocketServer, }) => { + const server = await defineWebSocketServer() await loadExample(new URL('./ws.runtime.js', import.meta.url), { skipActivation: true, })