mirror of
https://github.com/hanzoai/msw.git
synced 2026-09-24 17:00:34 +00:00
feat: migrate to ESM internally, remain CJS-first (#2490)
Co-authored-by: Mateusz Burzyński <[email protected]>
This commit is contained in:
committed by
GitHub
co-authored by
Mateusz Burzyński
parent
b678b44033
commit
37d96f55ab
@@ -33,8 +33,8 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
|
||||
- name: Validate package.json exports
|
||||
run: pnpm check:exports
|
||||
- name: Lint package
|
||||
run: pnpm publint
|
||||
|
||||
- name: Test modules (Node.js)
|
||||
run: pnpm test:modules:node
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
matrix:
|
||||
# As a general rule, when adding a new version, remove the oldest version
|
||||
# Check if the oldest version is EOL or not first.
|
||||
ts: ['4.8', '4.9', '5.0', '5.1', '5.2', '5.3', '5.4', '5.5']
|
||||
ts: ['5.0', '5.1', '5.2', '5.3', '5.4', '5.5']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
+1
-1
@@ -19,4 +19,4 @@ msw-*.tgz
|
||||
/package.json.copy
|
||||
/examples
|
||||
/test/modules/node/node-esm-tests
|
||||
tsconfig.vitest-temp.json
|
||||
*.vitest-temp.json
|
||||
|
||||
+1
-1
@@ -175,7 +175,7 @@ import { test, expect } from './playwright.extend'
|
||||
|
||||
test('returns a mocked response', async ({ loadExample, fetch }) => {
|
||||
// Compile the given usage example on runtime.
|
||||
await loadExample(require.resolve('./example.mocks.ts'))
|
||||
await loadExample(new URL('./example.mocks.ts', import.meta.url))
|
||||
|
||||
// Perform the "GET /books" request in the browser.
|
||||
const res = await fetch('/books')
|
||||
|
||||
+28
-3
@@ -1,5 +1,30 @@
|
||||
{
|
||||
"main": "../lib/browser/index.js",
|
||||
"module": "../lib/browser/index.mjs",
|
||||
"types": "../lib/browser/index.d.ts"
|
||||
"type": "module",
|
||||
"main": "../lib/browser/index.mjs",
|
||||
"types": "../lib/browser/index.d.mts",
|
||||
"exports": {
|
||||
".": {
|
||||
"module-sync": {
|
||||
"types": "./../lib/browser/index.d.mts",
|
||||
"default": "./../lib/browser/index.mjs"
|
||||
},
|
||||
"module": {
|
||||
"types": "./../lib/browser/index.d.mts",
|
||||
"default": "./../lib/browser/index.mjs"
|
||||
},
|
||||
"browser": {
|
||||
"types": "./../lib/browser/index.d.mts",
|
||||
"default": "./../lib/browser/index.mjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./../lib/browser/index.d.mts",
|
||||
"default": "./../lib/browser/index.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./../lib/browser/index.d.ts",
|
||||
"default": "./../lib/browser/index.js"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,7 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
const yargs = require('yargs')
|
||||
import yargs from 'yargs'
|
||||
import { init } from './init.js'
|
||||
|
||||
yargs
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
yargs(process.argv.slice(2))
|
||||
.usage('$0 <cmd> [args]')
|
||||
.command(
|
||||
'init',
|
||||
@@ -27,7 +29,7 @@ yargs
|
||||
.example('msw init ./public')
|
||||
.example('msw init ./static --save')
|
||||
},
|
||||
require('./init'),
|
||||
init,
|
||||
)
|
||||
.demandCommand()
|
||||
.help().argv
|
||||
|
||||
+12
-7
@@ -1,11 +1,11 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const colors = require('picocolors')
|
||||
const confirm = require('@inquirer/confirm').default
|
||||
const invariant = require('./invariant')
|
||||
const { SERVICE_WORKER_BUILD_PATH } = require('../config/constants')
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import colors from 'picocolors'
|
||||
import confirm from '@inquirer/confirm'
|
||||
import { invariant } from './invariant.js'
|
||||
import { SERVICE_WORKER_BUILD_PATH } from '../config/constants.js'
|
||||
|
||||
module.exports = async function init(args) {
|
||||
export async function init(args) {
|
||||
const CWD = args.cwd || process.cwd()
|
||||
const publicDir = args._[1] ? normalizePath(args._[1]) : undefined
|
||||
|
||||
@@ -33,6 +33,7 @@ module.exports = async function init(args) {
|
||||
// You can also provide the "--no-save" option, and then "args.save"
|
||||
// will equal to false.
|
||||
else if (args.save == null) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`\
|
||||
${colors.cyan(
|
||||
'INFO',
|
||||
@@ -126,6 +127,7 @@ async function copyWorkerScript(destination, cwd) {
|
||||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Copying the worker script at "%s"...', absolutePublicDir)
|
||||
|
||||
const workerFilename = path.basename(SERVICE_WORKER_BUILD_PATH)
|
||||
@@ -140,6 +142,7 @@ async function copyWorkerScript(destination, cwd) {
|
||||
* @param {Array<string>} paths
|
||||
*/
|
||||
function printSuccessMessage(paths) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`
|
||||
${colors.green('Worker script successfully copied!')}
|
||||
${paths.map((path) => colors.gray(` - ${path}\n`))}
|
||||
@@ -151,6 +154,7 @@ ${colors.red(colors.bold('https://mswjs.io/docs/getting-started'))}
|
||||
}
|
||||
|
||||
function printFailureMessage(pathsWithErrors) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`\
|
||||
${colors.red('Copying the worker script failed at following paths:')}
|
||||
${pathsWithErrors
|
||||
@@ -166,6 +170,7 @@ ${pathsWithErrors
|
||||
function saveWorkerDirectory(packageJsonPath, publicDir) {
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
colors.gray('Updating "msw.workerDirectory" at "%s"...'),
|
||||
packageJsonPath,
|
||||
|
||||
+3
-2
@@ -1,7 +1,8 @@
|
||||
const colors = require('picocolors')
|
||||
import colors from 'picocolors'
|
||||
|
||||
module.exports = function invariant(predicate, message, ...args) {
|
||||
export function invariant(predicate, message, ...args) {
|
||||
if (!predicate) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(colors.red(message), ...args)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
+9
-13
@@ -1,17 +1,13 @@
|
||||
const path = require('path')
|
||||
import url from 'node:url'
|
||||
import path from 'node:path'
|
||||
|
||||
const SERVICE_WORKER_SOURCE_PATH = path.resolve(
|
||||
__dirname,
|
||||
'../src/mockServiceWorker.js',
|
||||
export const SERVICE_WORKER_SOURCE_PATH = url.fileURLToPath(
|
||||
new URL('../src/mockServiceWorker.js', import.meta.url),
|
||||
)
|
||||
|
||||
const SERVICE_WORKER_BUILD_PATH = path.resolve(
|
||||
__dirname,
|
||||
'../lib',
|
||||
path.basename(SERVICE_WORKER_SOURCE_PATH),
|
||||
export const SERVICE_WORKER_BUILD_PATH = url.fileURLToPath(
|
||||
new URL(
|
||||
path.join('../lib', path.basename(SERVICE_WORKER_SOURCE_PATH)),
|
||||
import.meta.url,
|
||||
),
|
||||
)
|
||||
|
||||
module.exports = {
|
||||
SERVICE_WORKER_SOURCE_PATH,
|
||||
SERVICE_WORKER_BUILD_PATH,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { until } from '@open-draft/until'
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ export default async function copyServiceWorker(
|
||||
}
|
||||
|
||||
const packageJson = JSON.parse(
|
||||
fs.readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf8'),
|
||||
fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'),
|
||||
)
|
||||
|
||||
const nextFileContent = readFileResult.data
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import crypto from 'crypto'
|
||||
import minify from 'babel-minify'
|
||||
import { invariant } from 'outvariant'
|
||||
import type { Plugin } from 'esbuild'
|
||||
import copyServiceWorker from '../../copyServiceWorker'
|
||||
import copyServiceWorker from '../../copyServiceWorker.js'
|
||||
|
||||
const SERVICE_WORKER_ENTRY_PATH = path.resolve(
|
||||
process.cwd(),
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { Plugin } from 'esbuild'
|
||||
import { type Plugin } from 'esbuild'
|
||||
|
||||
export const ESM_EXTENSION = '.mjs'
|
||||
export const CJS_EXTENSION = '.js'
|
||||
|
||||
export function forceEsmExtensionsPlugin(): Plugin {
|
||||
return {
|
||||
@@ -16,7 +19,7 @@ export function forceEsmExtensionsPlugin(): Plugin {
|
||||
// This ignores additional files emitted, like sourcemaps ("*.js.map").
|
||||
if (
|
||||
!(
|
||||
outputFile.path.endsWith('.js') ||
|
||||
outputFile.path.endsWith(ESM_EXTENSION) ||
|
||||
outputFile.path.endsWith('.mjs')
|
||||
)
|
||||
) {
|
||||
@@ -37,7 +40,7 @@ const CJS_RELATIVE_IMPORT_EXP = /require\(["'](\..+)["']\)(;)?/gm
|
||||
const ESM_RELATIVE_IMPORT_EXP = /from ["'](\..+)["'](;)?/gm
|
||||
|
||||
function modifyRelativeImports(contents: string, isEsm: boolean): string {
|
||||
const extension = isEsm ? '.mjs' : '.js'
|
||||
const extension = isEsm ? ESM_EXTENSION : CJS_EXTENSION
|
||||
const importExpression = isEsm
|
||||
? ESM_RELATIVE_IMPORT_EXP
|
||||
: CJS_RELATIVE_IMPORT_EXP
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import fs from 'fs/promises'
|
||||
import fs from 'node:fs'
|
||||
import type { Plugin } from 'esbuild'
|
||||
|
||||
/**
|
||||
@@ -16,7 +16,7 @@ export function graphqlImportPlugin(): Plugin {
|
||||
}
|
||||
|
||||
build.onLoad({ filter: /\.ts$/ }, async (args) => {
|
||||
const contents = await fs.readFile(args.path, 'utf-8')
|
||||
const contents = await fs.promises.readFile(args.path, 'utf-8')
|
||||
const match = /require\(['"]graphql['"]\)/g.exec(contents)
|
||||
|
||||
if (match) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Plugin } from 'esbuild'
|
||||
|
||||
const { replaceCoreImports } = require('../../replaceCoreImports')
|
||||
import { replaceCoreImports } from '../../replaceCoreImports.js'
|
||||
import { ESM_EXTENSION } from './forceEsmExtensionsPlugin.js'
|
||||
|
||||
export function resolveCoreImportsPlugin(): Plugin {
|
||||
return {
|
||||
@@ -12,7 +12,7 @@ export function resolveCoreImportsPlugin(): Plugin {
|
||||
}
|
||||
|
||||
for (const outputFile of result.outputFiles || []) {
|
||||
const isEsm = outputFile.path.endsWith('.mjs')
|
||||
const isEsm = outputFile.path.endsWith(ESM_EXTENSION)
|
||||
const fileContents = outputFile.text
|
||||
const nextFileContents = replaceCoreImports(fileContents, isEsm)
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@ function getCoreImportPattern(isEsm) {
|
||||
return isEsm ? CORE_ESM_IMPORT_PATTERN : CORE_CJS_IMPORT_PATTERN
|
||||
}
|
||||
|
||||
function hasCoreImports(fileContents, isEsm) {
|
||||
export function hasCoreImports(fileContents, isEsm) {
|
||||
return getCoreImportPattern(isEsm).test(fileContents)
|
||||
}
|
||||
|
||||
function replaceCoreImports(fileContents, isEsm) {
|
||||
export function replaceCoreImports(fileContents, isEsm) {
|
||||
return fileContents.replace(
|
||||
getCoreImportPattern(isEsm),
|
||||
(_, __, maybeSubmodulePath, maybeSemicolon) => {
|
||||
@@ -17,13 +17,8 @@ function replaceCoreImports(fileContents, isEsm) {
|
||||
const semicolon = maybeSemicolon || ''
|
||||
|
||||
return isEsm
|
||||
? `from "../core${submodulePath}"${semicolon}`
|
||||
? `from "../core${submodulePath.endsWith('.mjs') ? submodulePath : submodulePath + '.mjs'}"${semicolon}`
|
||||
: `require("../core${submodulePath}")${semicolon}`
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hasCoreImports,
|
||||
replaceCoreImports,
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
const fs = require('node:fs')
|
||||
const { exec } = require('node:child_process')
|
||||
const path = require('node:path')
|
||||
const { promisify } = require('node:util')
|
||||
const { invariant } = require('outvariant')
|
||||
const glob = require('glob')
|
||||
const { hasCoreImports, replaceCoreImports } = require('../replaceCoreImports')
|
||||
import fs from 'node:fs'
|
||||
import url from 'node:url'
|
||||
import { exec } from 'node:child_process'
|
||||
import { promisify } from 'node:util'
|
||||
import { invariant } from 'outvariant'
|
||||
import * as glob from 'glob'
|
||||
import { hasCoreImports, replaceCoreImports } from '../replaceCoreImports.js'
|
||||
|
||||
const execAsync = promisify(exec)
|
||||
|
||||
const BUILD_DIR = path.resolve(__dirname, '../../lib')
|
||||
const BUILD_DIR = url.fileURLToPath(new URL('../../lib', import.meta.url))
|
||||
|
||||
async function patchTypeDefs() {
|
||||
const typeDefsPaths = glob.sync('**/*.d.{ts,mts}', {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { execSync } = require('child_process')
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { execSync } from 'node:child_process'
|
||||
|
||||
// When executing the "postinstall" script, the "process.cwd" equals
|
||||
// the package directory, not the parent project where the package is installed.
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { invariant } = require('outvariant')
|
||||
|
||||
const ROOT_PATH = path.resolve(__dirname, '../..')
|
||||
|
||||
function fromRoot(...paths) {
|
||||
return path.resolve(ROOT_PATH, ...paths)
|
||||
}
|
||||
|
||||
const PKG_JSON_PATH = fromRoot('package.json')
|
||||
const PKG_JSON = require(PKG_JSON_PATH)
|
||||
|
||||
function validatePackageExports() {
|
||||
const { exports } = PKG_JSON
|
||||
|
||||
// Validate the "main", "browser", and "types" root fields.
|
||||
invariant('main' in PKG_JSON, 'Missing "main" field in package.json')
|
||||
invariant('module' in PKG_JSON, 'Missing "module" field in package.json')
|
||||
invariant('types' in PKG_JSON, 'Missing "types" field in package.json')
|
||||
|
||||
invariant(
|
||||
fs.existsSync(fromRoot(PKG_JSON.main)),
|
||||
'The "main" field points at a non-existing path at "%s"',
|
||||
PKG_JSON.main,
|
||||
)
|
||||
|
||||
// The "exports" key must be present.
|
||||
invariant(exports, 'package.json must have an "exports" field')
|
||||
|
||||
// The "exports" must list expected paths.
|
||||
const expectedExportPaths = [
|
||||
'.',
|
||||
'./browser',
|
||||
'./node',
|
||||
'./package.json',
|
||||
'./native',
|
||||
]
|
||||
expectedExportPaths.forEach((exportPath) => {
|
||||
invariant(exportPath in exports, 'Missing exports path "%s"', exportPath)
|
||||
})
|
||||
|
||||
// Must describe the root export properly.
|
||||
const rootExport = exports['.']
|
||||
|
||||
validateExportConditions(`exports['.']`, rootExport)
|
||||
validateBundle(rootExport.require, false)
|
||||
validateBundle(rootExport.import, true)
|
||||
validateTypeDefs(rootExport.types)
|
||||
|
||||
// Validate "./browser" exports.
|
||||
const browserExports = exports['./browser']
|
||||
validateExportConditions(`exports['./browser']`, browserExports)
|
||||
invariant(
|
||||
browserExports.node === null,
|
||||
'The "browser" export must set the "node" field to null',
|
||||
)
|
||||
validateBundle(browserExports.require, false)
|
||||
validateBundle(browserExports.import, true)
|
||||
validateTypeDefs(browserExports.types)
|
||||
|
||||
// Validate "./node" exports.
|
||||
const nodeExports = exports['./node']
|
||||
validateExportConditions(`exports['./node']`, nodeExports)
|
||||
invariant(
|
||||
nodeExports.browser === null,
|
||||
'The "node" export must set the "browser" field to null',
|
||||
)
|
||||
validateBundle(nodeExports.require, false)
|
||||
validateBundle(nodeExports.import, true)
|
||||
validateTypeDefs(nodeExports.types)
|
||||
|
||||
// Validate "./native" exports.
|
||||
const nativeExports = exports['./native']
|
||||
validateExportConditions(`exports['./native']`, nativeExports)
|
||||
invariant(
|
||||
nativeExports.browser === null,
|
||||
'The "native" export must set the "browser" field to null',
|
||||
)
|
||||
validateBundle(nativeExports.require, false)
|
||||
validateBundle(nativeExports.import, true)
|
||||
validateTypeDefs(nativeExports.types)
|
||||
|
||||
// Validate "./package.json" exports.
|
||||
validateExportConditions(
|
||||
`exports['./package.json]`,
|
||||
exports['./package.json'],
|
||||
)
|
||||
|
||||
console.log('✅ Validated package.json exports')
|
||||
}
|
||||
|
||||
function validateExportConditions(pointer, conditions, level = 0) {
|
||||
if (typeof conditions === 'string') {
|
||||
invariant(
|
||||
fs.existsSync(conditions),
|
||||
'Expected a valid path at "%s" but got %s',
|
||||
pointer,
|
||||
conditions,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const keys = Object.keys(conditions)
|
||||
|
||||
if (level == 0 && conditions[keys[0]] !== null) {
|
||||
invariant(keys[0] === 'types', 'FS')
|
||||
}
|
||||
|
||||
// Ensure that paths point to existing files.
|
||||
keys.forEach((key) => {
|
||||
const relativeExportPath = conditions[key]
|
||||
|
||||
if (relativeExportPath === null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof relativeExportPath === 'object') {
|
||||
validateExportConditions(
|
||||
`${pointer}.${key}`,
|
||||
relativeExportPath,
|
||||
level + 1,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const exportPath = fromRoot(relativeExportPath)
|
||||
invariant(
|
||||
fs.existsSync(exportPath),
|
||||
'Expected the path at "%s" ("%s") to point at existing file but got %s',
|
||||
pointer,
|
||||
key,
|
||||
exportPath,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const ESM_CORE_IMPORT_EXP = /from ["'](..\/)+core(.*)["'];?$/gm
|
||||
const CJS_CORE_IMPORT_EXP = /require\(["'](..\/)+core(.*)["']\);?$/gm
|
||||
|
||||
function getCodeSnippetAt(contents, index) {
|
||||
return contents.slice(index - 100, index + 50)
|
||||
}
|
||||
|
||||
function validateBundle(bundlePath, isEsm = false) {
|
||||
const expectedExtension = isEsm ? '.mjs' : '.js'
|
||||
|
||||
invariant(
|
||||
bundlePath.endsWith(expectedExtension),
|
||||
'Failed to validate bundle: provided bundle path does not point at an ".mjs" file: %s',
|
||||
bundlePath,
|
||||
)
|
||||
|
||||
const absoluteBundlePath = fromRoot(bundlePath)
|
||||
const contents = fs.readFileSync(absoluteBundlePath, 'utf8')
|
||||
|
||||
// The "~/core" imports must be overwritten on the bundler level.
|
||||
invariant(
|
||||
!contents.includes('~/core'),
|
||||
'Bundle at "%s" includes unresolved "~/core" imports:\n\n%s',
|
||||
bundlePath,
|
||||
getCodeSnippetAt(contents, contents.indexOf('~/core')),
|
||||
)
|
||||
|
||||
// The "core" imports must end with the explicit ".mjs" extension.
|
||||
const coreImportsMatches =
|
||||
contents.matchAll(isEsm ? ESM_CORE_IMPORT_EXP : CJS_CORE_IMPORT_EXP) || []
|
||||
|
||||
for (const match of coreImportsMatches) {
|
||||
const [, backslashes, relativeImportPath] = match
|
||||
|
||||
invariant(
|
||||
backslashes === '../',
|
||||
'Found a "core" import with incorrect nesting level',
|
||||
)
|
||||
|
||||
invariant(
|
||||
relativeImportPath !== '',
|
||||
'Found a "core" import without an explicit path at "%s":\n\n%s',
|
||||
absoluteBundlePath,
|
||||
getCodeSnippetAt(contents, match.index),
|
||||
)
|
||||
|
||||
if (isEsm) {
|
||||
// Ensure that all relative imports in the ESM bundle end with ".mjs".
|
||||
// This way bundlers can distinguish between the referenced modules
|
||||
// since the "core" directory contains both ".js" and ".mjs" modules on the same level.
|
||||
invariant(
|
||||
relativeImportPath.endsWith('.mjs'),
|
||||
`Found a "core" import without "${expectedExtension}" extension at "%s":\n\n%s`,
|
||||
absoluteBundlePath,
|
||||
getCodeSnippetAt(contents, match.index),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('✅ Validated bundle at "%s"', bundlePath)
|
||||
}
|
||||
|
||||
function validateTypeDefs(typeDefsPath) {
|
||||
const absoluteTypeDefsPath = fromRoot(typeDefsPath)
|
||||
invariant(
|
||||
fs.existsSync(absoluteTypeDefsPath),
|
||||
'Failed to validate type definitions at "%s": file does not exist',
|
||||
absoluteTypeDefsPath,
|
||||
)
|
||||
|
||||
const contents = fs.readFileSync(absoluteTypeDefsPath, 'utf8')
|
||||
|
||||
// The "~/core" imports must also be replaced with relative paths on build.
|
||||
invariant(
|
||||
!contents.includes('~/core'),
|
||||
'Found unresolved "~/core" imports at "%s":\n\n%s',
|
||||
absoluteTypeDefsPath,
|
||||
getCodeSnippetAt(contents, contents.indexOf('~/core')),
|
||||
)
|
||||
|
||||
console.log('✅ Validated type definitions at "%s"', typeDefsPath)
|
||||
}
|
||||
|
||||
function validatePackageFiles() {
|
||||
const { files } = PKG_JSON
|
||||
|
||||
const expectedFiles = [
|
||||
'config/constants.js',
|
||||
'config/scripts/postinstall.js',
|
||||
'cli',
|
||||
'lib',
|
||||
'browser',
|
||||
'node',
|
||||
'native',
|
||||
]
|
||||
|
||||
// Must list all the expcted files.
|
||||
expectedFiles.forEach((expectedFile) => {
|
||||
invariant(
|
||||
files.includes(expectedFile),
|
||||
'"%s" is not listed in "files" in package.json',
|
||||
expectedFile,
|
||||
)
|
||||
})
|
||||
|
||||
// All the listed files must exist.
|
||||
expectedFiles.every((expectedFile) => {
|
||||
invariant(
|
||||
fs.existsSync(fromRoot(expectedFile)),
|
||||
'The file "%s" in "files" points at non-existing file',
|
||||
expectedFile,
|
||||
)
|
||||
})
|
||||
|
||||
console.log('✅ Validated package.json "files" field')
|
||||
}
|
||||
|
||||
validatePackageExports()
|
||||
validatePackageFiles()
|
||||
+25
-1
@@ -1,6 +1,30 @@
|
||||
{
|
||||
"type": "commonjs",
|
||||
"browser": null,
|
||||
"main": "../lib/native/index.js",
|
||||
"module": "../lib/native/index.mjs",
|
||||
"types": "../lib/native/index.d.ts"
|
||||
"types": "../lib/native/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"react-native": {
|
||||
"import": {
|
||||
"types": "./../lib/native/index.d.mts",
|
||||
"default": "./../lib/native/index.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./../lib/native/index.d.ts",
|
||||
"default": "./../lib/native/index.js"
|
||||
}
|
||||
},
|
||||
"browser": null,
|
||||
"import": {
|
||||
"types": "./../lib/native/index.d.mts",
|
||||
"default": "./../lib/native/index.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./../lib/native/index.d.ts",
|
||||
"default": "./../lib/native/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-1
@@ -1,6 +1,33 @@
|
||||
{
|
||||
"type": "commonjs",
|
||||
"browser": null,
|
||||
"main": "../lib/node/index.js",
|
||||
"module": "../lib/node/index.mjs",
|
||||
"types": "../lib/node/index.d.ts"
|
||||
"types": "../lib/node/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"module-sync": {
|
||||
"types": "./../lib/node/index.d.mts",
|
||||
"default": "./../lib/node/index.mjs"
|
||||
},
|
||||
"module": {
|
||||
"types": "./../lib/node/index.d.mts",
|
||||
"default": "./../lib/node/index.mjs"
|
||||
},
|
||||
"node": {
|
||||
"require": "./../lib/node/index.js",
|
||||
"import": "./../lib/node/index.mjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./../lib/node/index.d.mts",
|
||||
"default": "./../lib/node/index.mjs"
|
||||
},
|
||||
"browser": null,
|
||||
"react-native": null,
|
||||
"default": {
|
||||
"types": "./../lib/node/index.d.ts",
|
||||
"default": "./../lib/node/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+144
-46
@@ -2,67 +2,162 @@
|
||||
"name": "msw",
|
||||
"version": "2.7.6",
|
||||
"description": "Seamless REST/GraphQL API mocking library for browser and Node.js.",
|
||||
"type": "commonjs",
|
||||
"main": "./lib/core/index.js",
|
||||
"module": "./lib/core/index.mjs",
|
||||
"types": "./lib/core/index.d.ts",
|
||||
"packageManager": "[email protected]",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/core/index.d.ts",
|
||||
"require": "./lib/core/index.js",
|
||||
"import": "./lib/core/index.mjs",
|
||||
"default": "./lib/core/index.js"
|
||||
"module-sync": {
|
||||
"types": "./lib/core/index.d.mts",
|
||||
"default": "./lib/core/index.mjs"
|
||||
},
|
||||
"module": {
|
||||
"types": "./lib/core/index.d.mts",
|
||||
"default": "./lib/core/index.mjs"
|
||||
},
|
||||
"react-native": {
|
||||
"import": {
|
||||
"types": "./lib/core/index.d.mts",
|
||||
"default": "./lib/core/index.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./lib/core/index.d.ts",
|
||||
"default": "./lib/core/index.js"
|
||||
}
|
||||
},
|
||||
"import": {
|
||||
"types": "./lib/core/index.d.mts",
|
||||
"default": "./lib/core/index.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./lib/core/index.d.ts",
|
||||
"default": "./lib/core/index.js"
|
||||
}
|
||||
},
|
||||
"./browser": {
|
||||
"types": "./lib/browser/index.d.ts",
|
||||
"module-sync": {
|
||||
"types": "./lib/browser/index.d.mts",
|
||||
"default": "./lib/browser/index.mjs"
|
||||
},
|
||||
"module": {
|
||||
"types": "./lib/browser/index.d.mts",
|
||||
"default": "./lib/browser/index.mjs"
|
||||
},
|
||||
"browser": {
|
||||
"require": "./lib/browser/index.js",
|
||||
"import": "./lib/browser/index.mjs"
|
||||
"types": "./lib/browser/index.d.mts",
|
||||
"default": "./lib/browser/index.mjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./lib/browser/index.d.mts",
|
||||
"default": "./lib/browser/index.mjs"
|
||||
},
|
||||
"node": null,
|
||||
"require": "./lib/browser/index.js",
|
||||
"import": "./lib/browser/index.mjs",
|
||||
"default": "./lib/browser/index.js"
|
||||
"react-native": null,
|
||||
"default": {
|
||||
"types": "./lib/browser/index.d.ts",
|
||||
"default": "./lib/browser/index.js"
|
||||
}
|
||||
},
|
||||
"./node": {
|
||||
"types": "./lib/node/index.d.ts",
|
||||
"browser": null,
|
||||
"react-native": null,
|
||||
"module-sync": {
|
||||
"types": "./lib/node/index.d.mts",
|
||||
"default": "./lib/node/index.mjs"
|
||||
},
|
||||
"module": {
|
||||
"types": "./lib/node/index.d.mts",
|
||||
"default": "./lib/node/index.mjs"
|
||||
},
|
||||
"node": {
|
||||
"require": "./lib/node/index.js",
|
||||
"import": "./lib/node/index.mjs"
|
||||
},
|
||||
"browser": null,
|
||||
"require": "./lib/node/index.js",
|
||||
"import": "./lib/node/index.mjs",
|
||||
"default": "./lib/node/index.mjs"
|
||||
"import": {
|
||||
"types": "./lib/node/index.d.mts",
|
||||
"default": "./lib/node/index.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./lib/node/index.d.ts",
|
||||
"default": "./lib/node/index.js"
|
||||
}
|
||||
},
|
||||
"./native": {
|
||||
"types": "./lib/native/index.d.ts",
|
||||
"react-native": {
|
||||
"require": "./lib/native/index.js",
|
||||
"import": "./lib/native/index.mjs"
|
||||
},
|
||||
"browser": null,
|
||||
"require": "./lib/native/index.js",
|
||||
"import": "./lib/native/index.mjs",
|
||||
"default": "./lib/native/index.js"
|
||||
"react-native": {
|
||||
"import": {
|
||||
"types": "./lib/native/index.d.mts",
|
||||
"default": "./lib/native/index.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./lib/native/index.d.ts",
|
||||
"default": "./lib/native/index.js"
|
||||
}
|
||||
},
|
||||
"import": {
|
||||
"types": "./lib/native/index.d.mts",
|
||||
"default": "./lib/native/index.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./lib/native/index.d.ts",
|
||||
"default": "./lib/native/index.js"
|
||||
}
|
||||
},
|
||||
"./core/http": {
|
||||
"types": "./lib/core/http.d.ts",
|
||||
"require": "./lib/core/http.js",
|
||||
"import": "./lib/core/http.mjs",
|
||||
"default": "./lib/core/http.js"
|
||||
"module-sync": {
|
||||
"types": "./lib/core/http.d.mts",
|
||||
"default": "./lib/core/http.mjs"
|
||||
},
|
||||
"module": {
|
||||
"types": "./lib/core/http.d.mts",
|
||||
"default": "./lib/core/http.mjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./lib/core/http.d.mts",
|
||||
"default": "./lib/core/http.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./lib/core/http.d.ts",
|
||||
"default": "./lib/core/http.js"
|
||||
}
|
||||
},
|
||||
"./core/graphql": {
|
||||
"types": "./lib/core/graphql.d.ts",
|
||||
"require": "./lib/core/graphql.js",
|
||||
"import": "./lib/core/graphql.mjs",
|
||||
"default": "./lib/core/graphql.js"
|
||||
"module-sync": {
|
||||
"types": "./lib/core/graphql.d.mts",
|
||||
"default": "./lib/core/graphql.mjs"
|
||||
},
|
||||
"module": {
|
||||
"types": "./lib/core/graphql.d.mts",
|
||||
"default": "./lib/core/graphql.mjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./lib/core/graphql.d.mts",
|
||||
"default": "./lib/core/graphql.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./lib/core/graphql.d.ts",
|
||||
"default": "./lib/core/graphql.js"
|
||||
}
|
||||
},
|
||||
"./core/ws": {
|
||||
"types": "./lib/core/ws.d.ts",
|
||||
"require": "./lib/core/ws.js",
|
||||
"import": "./lib/core/ws.mjs",
|
||||
"default": "./lib/core/ws.js"
|
||||
"module-sync": {
|
||||
"types": "./lib/core/ws.d.mts",
|
||||
"default": "./lib/core/ws.mjs"
|
||||
},
|
||||
"module": {
|
||||
"types": "./lib/core/ws.d.mts",
|
||||
"default": "./lib/core/ws.mjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./lib/core/ws.d.mts",
|
||||
"default": "./lib/core/ws.mjs"
|
||||
},
|
||||
"default": {
|
||||
"types": "./lib/core/ws.d.ts",
|
||||
"default": "./lib/core/ws.js"
|
||||
}
|
||||
},
|
||||
"./mockServiceWorker.js": "./lib/mockServiceWorker.js",
|
||||
"./package.json": "./package.json"
|
||||
@@ -79,20 +174,20 @@
|
||||
"lint": "eslint \"{cli,src}/**/*.ts\"",
|
||||
"build": "pnpm clean && cross-env NODE_ENV=production tsup && pnpm patch:dts",
|
||||
"patch:dts": "node \"./config/scripts/patch-ts.js\"",
|
||||
"check:exports": "node \"./config/scripts/validate-esm.js\"",
|
||||
"publint": "publint",
|
||||
"test": "pnpm test:unit && pnpm test:node && pnpm test:browser && pnpm test:native",
|
||||
"test:unit": "vitest",
|
||||
"test:node": "vitest --config=./test/node/vitest.config.mts",
|
||||
"test:native": "vitest --config=./test/native/vitest.config.mts",
|
||||
"test:node": "vitest --config=./test/node/vitest.config.ts",
|
||||
"test:native": "vitest --config=./test/native/vitest.config.ts",
|
||||
"test:browser": "playwright test -c ./test/browser/playwright.config.ts",
|
||||
"test:modules:node": "vitest --config=./test/modules/node/vitest.config.mts",
|
||||
"test:modules:node": "vitest run --config=./test/modules/node/vitest.config.ts",
|
||||
"test:modules:browser": "playwright test -c ./test/modules/browser/playwright.config.ts",
|
||||
"test:e2e": "vitest run --config=./test/e2e/vitest.config.mts",
|
||||
"test:ts": "vitest --typecheck --config=./test/typings/vitest.config.mts",
|
||||
"test:e2e": "vitest run --config=./test/e2e/vitest.config.ts",
|
||||
"test:ts": "vitest --config=./test/typings/vitest.config.ts",
|
||||
"prepare": "pnpm simple-git-hooks init",
|
||||
"prepack": "pnpm build",
|
||||
"release": "release publish",
|
||||
"postinstall": "node -e \"try{require('./config/scripts/postinstall')}catch(e){}\"",
|
||||
"postinstall": "node -e \"try{import('./config/scripts/postinstall.js')}catch(e){}\"",
|
||||
"knip": "knip"
|
||||
},
|
||||
"lint-staged": {
|
||||
@@ -106,7 +201,7 @@
|
||||
"homepage": "https://mswjs.io",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mswjs/msw"
|
||||
"url": "git+https://github.com/mswjs/msw.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "Artem Zakharchenko",
|
||||
@@ -115,6 +210,7 @@
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/mswjs",
|
||||
"files": [
|
||||
"config/package.json",
|
||||
"config/constants.js",
|
||||
"config/scripts/postinstall.js",
|
||||
"cli",
|
||||
@@ -179,7 +275,7 @@
|
||||
"cross-env": "^7.0.3",
|
||||
"cross-fetch": "^4.0.0",
|
||||
"cz-conventional-changelog": "3.3.0",
|
||||
"esbuild": "^0.24.0",
|
||||
"esbuild": "^0.25.3",
|
||||
"esbuild-loader": "^4.2.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
@@ -192,16 +288,18 @@
|
||||
"json-bigint": "^1.0.0",
|
||||
"knip": "^5.51.1",
|
||||
"lint-staged": "^15.2.10",
|
||||
"msw": "workspace:*",
|
||||
"page-with": "^0.6.1",
|
||||
"prettier": "^3.4.2",
|
||||
"publint": "^0.3.12",
|
||||
"regenerator-runtime": "^0.14.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"simple-git-hooks": "^2.9.0",
|
||||
"tsup": "^8.3.0",
|
||||
"tsup": "^8.4.0",
|
||||
"typescript": "^5.5.2",
|
||||
"undici": "^6.20.0",
|
||||
"url-loader": "^4.1.1",
|
||||
"vitest": "^2.1.8",
|
||||
"vitest": "^3.1.3",
|
||||
"vitest-environment-miniflare": "^2.14.4",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack-http-server": "^0.5.0"
|
||||
|
||||
Generated
+530
-265
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -111,7 +111,7 @@ const standardGraphQLHandlers = {
|
||||
* return HttpResponse.json({ data: { name: 'John' } })
|
||||
* })
|
||||
*
|
||||
* @see {@link https://mswjs.io/docs/api/graphql#graphloperationresolver `graphql.operation()` API reference}
|
||||
* @see {@link https://mswjs.io/docs/api/graphql#graphqloperationresolver `graphql.operation()` API reference}
|
||||
*/
|
||||
operation: createGraphQLOperationHandler('*'),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
import { gql } from '../../support/graphql'
|
||||
import { waitFor } from '../../support/waitFor'
|
||||
@@ -36,7 +36,7 @@ test('does not warn on anonymous GraphQL operation when no GraphQL handlers are
|
||||
query,
|
||||
spyOnConsole,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./anonymous-operation.mocks.ts'))
|
||||
await loadExample(new URL('./anonymous-operation.mocks.ts', import.meta.url))
|
||||
const consoleSpy = spyOnConsole()
|
||||
|
||||
const endpointUrl = httpServer.http.url('/graphql')
|
||||
@@ -85,7 +85,7 @@ test('warns on handled anonymous GraphQL operation', async ({
|
||||
spyOnConsole,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./anonymous-operation.mocks.ts'))
|
||||
await loadExample(new URL('./anonymous-operation.mocks.ts', import.meta.url))
|
||||
const consoleSpy = spyOnConsole()
|
||||
|
||||
await page.evaluate(() => {
|
||||
@@ -148,7 +148,7 @@ test('does not print a warning on anonymous GraphQL operation handled by "graphq
|
||||
page,
|
||||
query,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./anonymous-operation.mocks.ts'))
|
||||
await loadExample(new URL('./anonymous-operation.mocks.ts', import.meta.url))
|
||||
const consoleSpy = spyOnConsole()
|
||||
|
||||
await page.evaluate(() => {
|
||||
|
||||
@@ -7,7 +7,7 @@ test('sets cookie on the mocked GraphQL response', async ({
|
||||
query,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./cookies.mocks.ts'))
|
||||
await loadExample(new URL('./cookies.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await query('/graphql', {
|
||||
query: gql`
|
||||
|
||||
@@ -2,7 +2,7 @@ import { test, expect } from '../playwright.extend'
|
||||
import { gql } from '../../support/graphql'
|
||||
|
||||
test('mocks a GraphQL error response', async ({ loadExample, query }) => {
|
||||
await loadExample(require.resolve('./errors.mocks.ts'))
|
||||
await loadExample(new URL('./errors.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await query('/graphql', {
|
||||
query: gql`
|
||||
|
||||
@@ -5,7 +5,7 @@ test('mocks a GraphQL response with both data and extensions', async ({
|
||||
loadExample,
|
||||
query,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./extensions.mocks.ts'))
|
||||
await loadExample(new URL('./extensions.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await query('/graphql', {
|
||||
query: gql`
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
import { gql } from '../../support/graphql'
|
||||
|
||||
const LINK_EXAMPLE = require.resolve('./link.mocks.ts')
|
||||
const LINK_EXAMPLE = new URL('./link.mocks.ts', import.meta.url)
|
||||
|
||||
const server = new HttpServer((app) => {
|
||||
app.post('/graphql', (req, res) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { waitFor } from '../../support/waitFor'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
import { gql } from '../../support/graphql'
|
||||
|
||||
const LOGGING_EXAMPLE = require.resolve('./logging.mocks.ts')
|
||||
const LOGGING_EXAMPLE = new URL('./logging.mocks.ts', import.meta.url)
|
||||
|
||||
test('prints a log for a GraphQL query', async ({
|
||||
loadExample,
|
||||
|
||||
@@ -4,7 +4,7 @@ test('accepts a file from a GraphQL mutation', async ({
|
||||
loadExample,
|
||||
query,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./multipart-data.mocks.ts'))
|
||||
await loadExample(new URL('./multipart-data.mocks.ts', import.meta.url))
|
||||
|
||||
const UPLOAD_MUTATION = `
|
||||
mutation UploadFile(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
import { gql } from '../../support/graphql'
|
||||
|
||||
const MUTATION_EXAMPLE = require.resolve('./mutation.mocks.ts')
|
||||
const MUTATION_EXAMPLE = new URL('./mutation.mocks.ts', import.meta.url)
|
||||
|
||||
const server = new HttpServer((app) => {
|
||||
app.use('*', (req, res) => res.status(405).end())
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { test, expect } from '../playwright.extend'
|
||||
|
||||
const OPERATION_REFERENCE_EXAMPLE = require.resolve(
|
||||
const OPERATION_REFERENCE_EXAMPLE = new URL(
|
||||
'./operation-reference.mocks.ts',
|
||||
import.meta.url,
|
||||
)
|
||||
|
||||
test('allows referencing the request body in the GraphQL query handler', async ({
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
import { gql } from '../../support/graphql'
|
||||
|
||||
const OPERATION_EXAMPLE = require.resolve('./operation.mocks.ts')
|
||||
const OPERATION_EXAMPLE = new URL('./operation.mocks.ts', import.meta.url)
|
||||
|
||||
const server = new HttpServer((app) => {
|
||||
app.post('/search', (req, res) => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
import { gql } from '../../support/graphql'
|
||||
|
||||
const EXAMPLE_PATH = require.resolve('./query.mocks.ts')
|
||||
const EXAMPLE_PATH = new URL('./query.mocks.ts', import.meta.url)
|
||||
|
||||
const server = new HttpServer((app) => {
|
||||
app.use('*', (_, res) => res.status(405).end())
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { ExecutionResult } from 'graphql'
|
||||
import { buildSchema, graphql } from 'graphql'
|
||||
import { SetupWorkerApi } from 'msw/browser'
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
import { gql } from '../../support/graphql'
|
||||
|
||||
@@ -50,7 +50,7 @@ test.afterEach(async () => {
|
||||
})
|
||||
|
||||
test('patches a GraphQL response', async ({ loadExample, page }) => {
|
||||
await loadExample(require.resolve('./response-patching.mocks.ts'))
|
||||
await loadExample(new URL('./response-patching.mocks.ts', import.meta.url))
|
||||
const endpointUrl = httpServer.http.url('/graphql')
|
||||
|
||||
await page.evaluate(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { gql } from '../../support/graphql'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
|
||||
const EXAMPLE_PATH = require.resolve('./variables.mocks.ts')
|
||||
const EXAMPLE_PATH = new URL('./variables.mocks.ts', import.meta.url)
|
||||
|
||||
test('can access variables from a GraphQL query', async ({
|
||||
loadExample,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { test, expect } from '../../playwright.extend'
|
||||
|
||||
const DELAY_EXAMPLE = require.resolve('./delay.mocks.ts')
|
||||
const DELAY_EXAMPLE = new URL('./delay.mocks.ts', import.meta.url)
|
||||
|
||||
declare global {
|
||||
namespace PlaywrightTest {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as fs from 'fs'
|
||||
import fs from 'node:fs'
|
||||
import { test, expect } from '../../playwright.extend'
|
||||
|
||||
test('supports the usage of the iife bundle in a <script> tag', async ({
|
||||
@@ -7,13 +7,13 @@ test('supports the usage of the iife bundle in a <script> tag', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./iife.mocks.js'), {
|
||||
await loadExample(new URL('./iife.mocks.js', import.meta.url), {
|
||||
markup: `<script src="./iife/index.js"></script>`,
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use((router) => {
|
||||
router.get('/iife/index.js', (_, res) => {
|
||||
fs.createReadStream(
|
||||
require.resolve('../../../../lib/iife/index.js'),
|
||||
new URL('../../../../lib/iife/index.js', import.meta.url),
|
||||
).pipe(res)
|
||||
|
||||
return res
|
||||
|
||||
@@ -5,7 +5,7 @@ test('activates the worker without errors', async ({
|
||||
spyOnConsole,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./exception-handling.mocks.ts'))
|
||||
await loadExample(new URL('./exception-handling.mocks.ts', import.meta.url))
|
||||
|
||||
expect(consoleSpy.get('error')).toBeUndefined()
|
||||
})
|
||||
@@ -15,7 +15,7 @@ test('transforms uncaught exceptions into a 500 response', async ({
|
||||
fetch,
|
||||
spyOnConsole,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./exception-handling.mocks.ts'))
|
||||
await loadExample(new URL('./exception-handling.mocks.ts', import.meta.url))
|
||||
const consoleSpy = spyOnConsole()
|
||||
|
||||
const res = await fetch('https://api.github.com/users/octocat')
|
||||
|
||||
@@ -6,7 +6,7 @@ test('keeps the mocking enabled after hard-reload of the page', async ({
|
||||
fetch,
|
||||
waitForMswActivation,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./hard-reload.mocks.ts'))
|
||||
await loadExample(new URL('./hard-reload.mocks.ts', import.meta.url))
|
||||
|
||||
page.evaluate(() => {
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import fs from 'node:fs'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
import copyServiceWorker from '../../../config/copyServiceWorker'
|
||||
import { version } from '../../../package.json'
|
||||
|
||||
const { SERVICE_WORKER_SOURCE_PATH } = require('../../../config/constants')
|
||||
import packageJson from '../../../package.json' assert { type: 'json' }
|
||||
// @ts-expect-error Importing a Javascript module.
|
||||
import { SERVICE_WORKER_SOURCE_PATH } from '../../../config/constants.js'
|
||||
|
||||
test('activates the worker without errors given the latest integrity', async ({
|
||||
loadExample,
|
||||
@@ -12,7 +11,9 @@ test('activates the worker without errors given the latest integrity', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./integrity-check-valid.mocks.ts'))
|
||||
await loadExample(
|
||||
new URL('./integrity-check-valid.mocks.ts', import.meta.url),
|
||||
)
|
||||
|
||||
expect(consoleSpy.get('error')).toBeUndefined()
|
||||
|
||||
@@ -31,10 +32,10 @@ test('errors when activating the worker with an outdated integrity', async ({
|
||||
fetch,
|
||||
waitFor,
|
||||
}) => {
|
||||
const TEMP_SERVICE_WORKER_PATH = path.resolve(
|
||||
__dirname,
|
||||
const TEMP_SERVICE_WORKER_PATH = new URL(
|
||||
'../../tmp/mockServiceWorker-outdated.js',
|
||||
)
|
||||
import.meta.url,
|
||||
).pathname
|
||||
|
||||
// Manually create a Service Worker file with invalid integrity
|
||||
await copyServiceWorker(
|
||||
@@ -44,31 +45,34 @@ test('errors when activating the worker with an outdated integrity', async ({
|
||||
)
|
||||
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./integrity-check-invalid.mocks.ts'), {
|
||||
skipActivation: true,
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use((router) => {
|
||||
router.use('/', (_, res, next) => {
|
||||
// Appended router are relative to the compilation path.
|
||||
// Allow the nested worker script to control the root scope.
|
||||
res.setHeader('Service-Worker-Allowed', '/')
|
||||
next()
|
||||
})
|
||||
await loadExample(
|
||||
new URL('./integrity-check-invalid.mocks.ts', import.meta.url),
|
||||
{
|
||||
skipActivation: true,
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use((router) => {
|
||||
router.use('/', (_, res, next) => {
|
||||
// Appended router are relative to the compilation path.
|
||||
// Allow the nested worker script to control the root scope.
|
||||
res.setHeader('Service-Worker-Allowed', '/')
|
||||
next()
|
||||
})
|
||||
|
||||
router.get('/mockServiceWorker-outdated.js', (_, res) => {
|
||||
return res
|
||||
.set('content-type', 'application/javascript')
|
||||
.send(fs.readFileSync(TEMP_SERVICE_WORKER_PATH, 'utf8'))
|
||||
router.get('/mockServiceWorker-outdated.js', (_, res) => {
|
||||
return res
|
||||
.set('content-type', 'application/javascript')
|
||||
.send(fs.readFileSync(TEMP_SERVICE_WORKER_PATH, 'utf8'))
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
// Produces a meaningful error in the browser's console.
|
||||
expect(consoleSpy.get('warning')).toEqual(
|
||||
expect.arrayContaining([
|
||||
`[MSW] The currently registered Service Worker has been generated by a different version of MSW (${version}) and may not be fully compatible with the installed version.
|
||||
`[MSW] The currently registered Service Worker has been generated by a different version of MSW (${packageJson.version}) and may not be fully compatible with the installed version.
|
||||
|
||||
It's recommended you update your worker script by running this command:
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ test('handles a stream response without throwing a timeout error', async ({
|
||||
loadExample,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./2129-worker-use.mocks.ts'))
|
||||
await loadExample(new URL('./2129-worker-use.mocks.ts', import.meta.url))
|
||||
|
||||
const getResponse = await fetch('/v1/issues')
|
||||
expect(await getResponse.text()).toBe('get-body')
|
||||
|
||||
@@ -20,7 +20,7 @@ test('handles a stream response without throwing a timeout error', async ({
|
||||
})
|
||||
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./handle-stream.mocks.ts'))
|
||||
await loadExample(new URL('./handle-stream.mocks.ts', import.meta.url))
|
||||
|
||||
const getStreamResponse = () => {
|
||||
return page.evaluate(
|
||||
|
||||
@@ -6,7 +6,7 @@ for (const code of [204, 205, 304]) {
|
||||
fetch,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./null-body.mocks.ts'))
|
||||
await loadExample(new URL('./null-body.mocks.ts', import.meta.url))
|
||||
|
||||
const errors: Array<Error> = []
|
||||
page.on('pageerror', (pageError) => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { HttpResponse, http, passthrough } from 'msw'
|
||||
import { SetupWorkerApi } from 'msw/browser'
|
||||
import { expect, test } from '../../playwright.extend'
|
||||
|
||||
const PASSTHROUGH_EXAMPLE = require.resolve('./passthrough.mocks.ts')
|
||||
const PASSTHROUGH_EXAMPLE = new URL('./passthrough.mocks.ts', import.meta.url)
|
||||
|
||||
declare namespace window {
|
||||
export const msw: {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { test, expect } from '../../playwright.extend'
|
||||
|
||||
test('throws a network error', async ({ spyOnConsole, loadExample, page }) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./network-error.mocks.ts'))
|
||||
await loadExample(new URL('./network-error.mocks.ts', import.meta.url))
|
||||
|
||||
// Do not use `runtime.request()`, because it always awaits a response.
|
||||
// In this case we await a network error, performing a request manually.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SetupWorkerApi } from 'msw/browser'
|
||||
import { createTeardown } from 'fs-teardown'
|
||||
import { Page } from '@playwright/test'
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { fromTemp } from '../../../../support/utils'
|
||||
import { test, expect } from '../../../playwright.extend'
|
||||
|
||||
@@ -63,7 +63,7 @@ test.beforeAll(async () => {
|
||||
|
||||
test.beforeEach(async ({ webpackServer }, testInfo) => {
|
||||
const compilation = await webpackServer.compile([
|
||||
require.resolve('./fallback-mode.mocks.ts'),
|
||||
new URL('./fallback-mode.mocks.ts', import.meta.url).pathname,
|
||||
])
|
||||
const bundleUrl = new URL('./main.js', compilation.previewUrl)
|
||||
await fsMock.create({
|
||||
|
||||
@@ -5,7 +5,7 @@ test('throws an error given an Array of request handlers to "setupWorker"', asyn
|
||||
page,
|
||||
waitFor,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./input-validation.mocks.ts'), {
|
||||
await loadExample(new URL('./input-validation.mocks.ts', import.meta.url), {
|
||||
skipActivation: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { SetupWorker } from 'msw/browser'
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import type { ConsoleMessages } from 'page-with'
|
||||
import { test, expect } from '../../../playwright.extend'
|
||||
|
||||
@@ -9,7 +9,7 @@ declare namespace window {
|
||||
}
|
||||
}
|
||||
|
||||
const ON_EXAMPLE = require.resolve('./on.mocks.ts')
|
||||
const ON_EXAMPLE = new URL('./on.mocks.ts', import.meta.url)
|
||||
|
||||
const server = new HttpServer((app) => {
|
||||
app.post('/no-response', (_req, res) => {
|
||||
|
||||
@@ -7,7 +7,7 @@ declare namespace window {
|
||||
}
|
||||
}
|
||||
|
||||
const ON_EXAMPLE = require.resolve('./on.mocks.ts')
|
||||
const ON_EXAMPLE = new URL('./on.mocks.ts', import.meta.url)
|
||||
|
||||
test('removes all listeners attached to the worker instance', async ({
|
||||
loadExample,
|
||||
|
||||
@@ -17,7 +17,7 @@ test('removes a listener by the event name', async ({
|
||||
makeUrl,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./on.mocks.ts'))
|
||||
await loadExample(new URL('./on.mocks.ts', import.meta.url))
|
||||
|
||||
await page.evaluate(() => {
|
||||
const { msw } = window
|
||||
|
||||
@@ -10,7 +10,7 @@ declare namespace window {
|
||||
}
|
||||
}
|
||||
|
||||
const LIST_HANDLER_EXAMPLE = require.resolve('./listHandlers.mocks.ts')
|
||||
const LIST_HANDLER_EXAMPLE = new URL('./listHandlers.mocks.ts', import.meta.url)
|
||||
|
||||
test('lists all current request handlers', async ({ loadExample, page }) => {
|
||||
await loadExample(LIST_HANDLER_EXAMPLE)
|
||||
|
||||
@@ -11,7 +11,7 @@ declare namespace window {
|
||||
}
|
||||
}
|
||||
|
||||
const USE_EXAMPLE = require.resolve('./use.mocks.ts')
|
||||
const USE_EXAMPLE = new URL('./use.mocks.ts', import.meta.url)
|
||||
|
||||
test('removes all runtime request handlers when resetting without explicit next handlers', async ({
|
||||
loadExample,
|
||||
|
||||
@@ -12,7 +12,7 @@ test('prints the response info to the console', async ({
|
||||
fetch,
|
||||
waitFor,
|
||||
}) => {
|
||||
await loadExample(require.resolve('../../rest-api/basic.mocks.ts'))
|
||||
await loadExample(new URL('../../rest-api/basic.mocks.ts', import.meta.url))
|
||||
const consoleSpy = spyOnConsole()
|
||||
|
||||
const waitForResponseLog = async (exp: RegExp) => {
|
||||
|
||||
@@ -15,7 +15,7 @@ test('returns a mocked response from the used one-time request handler when rest
|
||||
page,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./use.mocks.ts'))
|
||||
await loadExample(new URL('./use.mocks.ts', import.meta.url))
|
||||
|
||||
await page.evaluate(() => {
|
||||
const { worker, http, HttpResponse } = window.msw
|
||||
|
||||
@@ -5,7 +5,7 @@ test('uses a custom transformer to parse BigInt in response body', async ({
|
||||
loadExample,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./custom-transformers.mocks.ts'))
|
||||
await loadExample(new URL('./custom-transformers.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('/user')
|
||||
const body = await res.text()
|
||||
|
||||
@@ -8,7 +8,7 @@ test('propagates the exception originating from a handled request', async ({
|
||||
makeUrl,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./internal-error.mocks.ts'))
|
||||
await loadExample(new URL('./internal-error.mocks.ts', import.meta.url))
|
||||
|
||||
const endpointUrl = makeUrl('/user')
|
||||
const res = await fetch(endpointUrl)
|
||||
|
||||
@@ -10,7 +10,7 @@ test('propagates a mocked network error', async ({
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
const { workerConsole } = await loadExample(
|
||||
require.resolve('./network-error.mocks.ts'),
|
||||
new URL('./network-error.mocks.ts', import.meta.url),
|
||||
)
|
||||
|
||||
const endpointUrl = makeUrl('/user')
|
||||
@@ -34,7 +34,7 @@ test('propagates a CORS violation error from a non-matching request', async ({
|
||||
waitFor,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./network-error.mocks.ts'))
|
||||
await loadExample(new URL('./network-error.mocks.ts', import.meta.url))
|
||||
|
||||
await until(() => page.evaluate(() => fetch('/user')))
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ test('falls through all relevant request handlers until response is returned', a
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./fall-through.mocks.ts'))
|
||||
await loadExample(new URL('./fall-through.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('/user')
|
||||
const body = await res.json()
|
||||
@@ -29,7 +29,7 @@ test('falls through all relevant handler even if none returns response', async (
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./fall-through.mocks.ts'))
|
||||
await loadExample(new URL('./fall-through.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('/blog/article', {
|
||||
method: 'POST',
|
||||
|
||||
+9
-7
@@ -1,10 +1,9 @@
|
||||
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))
|
||||
router.use(express.static(new URL('./', import.meta.url).pathname))
|
||||
}
|
||||
|
||||
export function getFrameById(id: string, page: Page): Frame {
|
||||
@@ -24,12 +23,15 @@ test('responds with different responses for the same request based on request re
|
||||
loadExample,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./iframe-isolated-response.mocks.ts'), {
|
||||
markup: path.resolve(__dirname, 'app.html'),
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use(staticMiddleware)
|
||||
await loadExample(
|
||||
new URL('./iframe-isolated-response.mocks.ts', import.meta.url),
|
||||
{
|
||||
markup: new URL('app.html', import.meta.url).pathname,
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use(staticMiddleware)
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
const frameOne = getFrameById('frame-one', page)!
|
||||
const frameTwo = getFrameById('frame-two', page)!
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as path from 'path'
|
||||
import { Frame } from '@playwright/test'
|
||||
import * as express from 'express'
|
||||
import { test, expect } from '../../../../playwright.extend'
|
||||
@@ -14,15 +13,15 @@ function findFrame(frame: Frame) {
|
||||
}
|
||||
|
||||
const staticMiddleware = (router: express.Router) => {
|
||||
router.use(express.static(__dirname))
|
||||
router.use(express.static(new URL('./', import.meta.url).pathname))
|
||||
}
|
||||
|
||||
test('intercepts a request from an iframe (nested client)', async ({
|
||||
loadExample,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./iframe.mocks.ts'), {
|
||||
markup: path.resolve(__dirname, 'page-in-iframe.html'),
|
||||
await loadExample(new URL('./iframe.mocks.ts', import.meta.url), {
|
||||
markup: new URL('page-in-iframe.html', import.meta.url).pathname,
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use(staticMiddleware)
|
||||
},
|
||||
@@ -41,8 +40,8 @@ test('intercepts a request from a deeply nested iframe', async ({
|
||||
loadExample,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./iframe.mocks.ts'), {
|
||||
markup: path.resolve(__dirname, 'page-in-nested-iframe.html'),
|
||||
await loadExample(new URL('./iframe.mocks.ts', import.meta.url), {
|
||||
markup: new URL('page-in-nested-iframe.html', import.meta.url).pathname,
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use(staticMiddleware)
|
||||
},
|
||||
@@ -67,8 +66,8 @@ test('intercepts a request from a deeply nested iframe given MSW is registered i
|
||||
loadExample,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./iframe.mocks.ts'), {
|
||||
markup: path.resolve(__dirname, 'page-in-iframe.html'),
|
||||
await loadExample(new URL('./iframe.mocks.ts', import.meta.url), {
|
||||
markup: new URL('page-in-iframe.html', import.meta.url).pathname,
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use(staticMiddleware)
|
||||
},
|
||||
@@ -95,12 +94,12 @@ test('intercepts a request from an iframe given MSW is registered in a sibling i
|
||||
context,
|
||||
}) => {
|
||||
// A frame that registers MSW, but does no requests.
|
||||
await loadExample(require.resolve('./iframe.mocks.ts'))
|
||||
await loadExample(new URL('./iframe.mocks.ts', import.meta.url))
|
||||
|
||||
// A request-issuing frame. Here lives the `window.fetch` call.
|
||||
const requestPage = await context.newPage()
|
||||
const requestCompilation = await webpackServer.compile([], {
|
||||
markup: path.resolve(__dirname, 'page-in-iframe.html'),
|
||||
markup: new URL('page-in-iframe.html', import.meta.url).pathname,
|
||||
})
|
||||
requestCompilation.use(staticMiddleware)
|
||||
await requestPage.goto(requestCompilation.previewUrl)
|
||||
|
||||
+2
-2
@@ -5,10 +5,10 @@ test('intercepts a request issued by child frame when both child and parent have
|
||||
page,
|
||||
}) => {
|
||||
const parentCompilation = await webpackServer.compile([
|
||||
require.resolve('./parent.mocks.ts'),
|
||||
new URL('./parent.mocks.ts', import.meta.url).pathname,
|
||||
])
|
||||
const childCompilation = await webpackServer.compile([
|
||||
require.resolve('./child.mocks.ts'),
|
||||
new URL('./child.mocks.ts', import.meta.url).pathname,
|
||||
])
|
||||
|
||||
await page.goto(parentCompilation.previewUrl, { waitUntil: 'networkidle' })
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { test, expect } from '../../../../playwright.extend'
|
||||
|
||||
const {
|
||||
SERVICE_WORKER_BUILD_PATH,
|
||||
} = require('../../../../../../config/constants')
|
||||
// @ts-expect-error Importing a JavaScript module.
|
||||
import { SERVICE_WORKER_BUILD_PATH } from '../../../../../../config/constants.js'
|
||||
|
||||
test('warns when visiting the page outside of the worker scope', async ({
|
||||
loadExample,
|
||||
@@ -10,7 +8,7 @@ test('warns when visiting the page outside of the worker scope', async ({
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
const { compilation } = await loadExample(
|
||||
require.resolve('./scope-nested.mocks.ts'),
|
||||
new URL('./scope-nested.mocks.ts', import.meta.url),
|
||||
{
|
||||
beforeNavigation(compilation) {
|
||||
// Create a proxy to the worker script located under a nested ("/public") path.
|
||||
@@ -40,7 +38,7 @@ test('does not print the scope warning when the page is within the worker scope'
|
||||
spyOnConsole,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./scope-root.mocks.ts'))
|
||||
await loadExample(new URL('./scope-root.mocks.ts', import.meta.url))
|
||||
|
||||
expect(consoleSpy.get('warning')).toEqual(undefined)
|
||||
expect(consoleSpy.get('error')).toEqual(undefined)
|
||||
@@ -51,7 +49,7 @@ test('does not print the scope warning when the "quiet" option is enabled', asyn
|
||||
spyOnConsole,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./scope-nested-quiet.mocks.ts'), {
|
||||
await loadExample(new URL('./scope-nested-quiet.mocks.ts', import.meta.url), {
|
||||
skipActivation: true,
|
||||
beforeNavigation(compilation) {
|
||||
// Create a proxy to the worker script located under a nested ("/public") path.
|
||||
|
||||
@@ -11,10 +11,10 @@ test('does not interfere with a shared worker', async ({
|
||||
page,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./shared-worker.mocks.ts'), {
|
||||
await loadExample(new URL('./shared-worker.mocks.ts', import.meta.url), {
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use((router) => {
|
||||
router.use(express.static(__dirname))
|
||||
router.use(express.static(new URL('./', import.meta.url).pathname))
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ test('bypasses the unhandled request with the "Accept" header containing "text/e
|
||||
})
|
||||
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./text-event-stream.mocks.ts'))
|
||||
await loadExample(new URL('./text-event-stream.mocks.ts', import.meta.url))
|
||||
|
||||
await page.evaluate((endpointUrl) => {
|
||||
const source = new EventSource(endpointUrl)
|
||||
|
||||
@@ -11,7 +11,7 @@ test('rejects with a custom error message when given a non-existing worker scrip
|
||||
loadExample,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./error.mocks.ts'), {
|
||||
await loadExample(new URL('./error.mocks.ts', import.meta.url), {
|
||||
skipActivation: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ test('resolves the "start" Promise and returns a ServiceWorkerRegistration when
|
||||
page,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./find-worker.mocks.ts'))
|
||||
await loadExample(new URL('./find-worker.mocks.ts', import.meta.url))
|
||||
|
||||
await page.waitForFunction(() => {
|
||||
return typeof window.msw !== 'undefined'
|
||||
@@ -46,7 +46,7 @@ test('fails to return a ServiceWorkerRegistration when using a findWorker that r
|
||||
page,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./find-worker.error.mocks.ts'), {
|
||||
await loadExample(new URL('./find-worker.error.mocks.ts', import.meta.url), {
|
||||
skipActivation: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ test('bypasses an unhandled request', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./bypass.mocks.ts'))
|
||||
await loadExample(new URL('./bypass.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('https://mswjs.io/non-existing-page')
|
||||
const status = res.status()
|
||||
|
||||
@@ -6,7 +6,7 @@ test('executes a default "warn" strategy in a custom callback', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./callback-print.mocks.ts'))
|
||||
await loadExample(new URL('./callback-print.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('https://mswjs.io/use-warn')
|
||||
const status = res.status()
|
||||
@@ -40,7 +40,7 @@ test('executes a default "error" strategy in a custom callback', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./callback-print.mocks.ts'))
|
||||
await loadExample(new URL('./callback-print.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('https://mswjs.io/use-error')
|
||||
const status = res.status()
|
||||
|
||||
@@ -6,7 +6,7 @@ test('executes a given callback on an unhandled request', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./callback.mocks.ts'))
|
||||
await loadExample(new URL('./callback.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('https://mswjs.io/non-existing-page')
|
||||
const status = res.status()
|
||||
|
||||
@@ -6,7 +6,7 @@ test('warns on unhandled requests by default', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./default.mocks.ts'))
|
||||
await loadExample(new URL('./default.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('https://mswjs.io/non-existing-page')
|
||||
const status = res.status()
|
||||
|
||||
@@ -6,7 +6,7 @@ test('warns on an unhandled REST API request with an absolute URL', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./warn.mocks.ts'))
|
||||
await loadExample(new URL('./warn.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('https://mswjs.io/non-existing-page')
|
||||
const status = res.status()
|
||||
@@ -31,7 +31,7 @@ test('warns on an unhandled REST API request with a relative URL', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./warn.mocks.ts'))
|
||||
await loadExample(new URL('./warn.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('/user-details')
|
||||
const status = res.status()
|
||||
@@ -56,7 +56,7 @@ test('does not warn on request which handler explicitly returns no mocked respon
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./warn.mocks.ts'))
|
||||
await loadExample(new URL('./warn.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('/explicit-return', { method: 'POST' })
|
||||
const status = res.status()
|
||||
@@ -77,7 +77,7 @@ test('does not warn on request which handler implicitly returns no mocked respon
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./warn.mocks.ts'))
|
||||
await loadExample(new URL('./warn.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('/implicit-return', { method: 'POST' })
|
||||
const status = res.status()
|
||||
@@ -98,7 +98,7 @@ test('ignores common static assets when using the "warn" strategy', async ({
|
||||
page,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./warn.mocks.ts'))
|
||||
await loadExample(new URL('./warn.mocks.ts', import.meta.url))
|
||||
|
||||
// This request will error so perform it accordingly.
|
||||
await page.evaluate(() => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as path from 'path'
|
||||
import { test, expect } from '../../../playwright.extend'
|
||||
|
||||
test('respects a custom "scope" Service Worker option', async ({
|
||||
@@ -7,7 +6,7 @@ test('respects a custom "scope" Service Worker option', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(path.resolve(__dirname, 'options-sw-scope.mocks.ts'))
|
||||
await loadExample(new URL('options-sw-scope.mocks.ts', import.meta.url))
|
||||
|
||||
expect(consoleSpy.get('startGroupCollapsed')).toEqual(
|
||||
expect.arrayContaining([expect.stringContaining('[MSW] Mocking enabled.')]),
|
||||
|
||||
@@ -14,7 +14,7 @@ test('does not log the intercepted request when the "quiet" option is set to "tr
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./quiet.mocks.ts'), {
|
||||
await loadExample(new URL('./quiet.mocks.ts', import.meta.url), {
|
||||
// Using the "quiet" option to suppress the activation message.
|
||||
skipActivation: true,
|
||||
})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as path from 'path'
|
||||
import { SetupWorkerApi } from 'msw/browser'
|
||||
import { TestFixtures, test, expect } from '../../../playwright.extend'
|
||||
|
||||
@@ -9,13 +8,13 @@ declare namespace window {
|
||||
}
|
||||
|
||||
const exampleOptions: Parameters<TestFixtures['loadExample']> = [
|
||||
require.resolve('./start.mocks.ts'),
|
||||
new URL('./start.mocks.ts', import.meta.url),
|
||||
{
|
||||
skipActivation: true,
|
||||
beforeNavigation(compilation) {
|
||||
compilation.use((router) => {
|
||||
router.get('/worker.js', (_, res) => {
|
||||
res.sendFile(path.resolve(__dirname, 'worker.delayed.js'))
|
||||
res.sendFile(new URL('worker.delayed.js', import.meta.url).pathname)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
@@ -6,7 +6,9 @@ test('warns on the "waitUntilReady" option in "worker.start()"', async ({
|
||||
spyOnConsole,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./warn-on-wait-until-ready.mocks.ts'))
|
||||
await loadExample(
|
||||
new URL('./warn-on-wait-until-ready.mocks.ts', import.meta.url),
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(consoleSpy.get('warning')).toEqual([
|
||||
|
||||
@@ -39,7 +39,7 @@ test('disables the mocking when the worker is stopped', async ({
|
||||
fetch,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./stop.mocks.ts'))
|
||||
await loadExample(new URL('./stop.mocks.ts', import.meta.url))
|
||||
await stopWorkerOn(page)
|
||||
|
||||
const res = await fetch('https://api.github.com')
|
||||
@@ -56,7 +56,9 @@ test('keeps the mocking enabled in one tab when stopping the worker in another t
|
||||
context,
|
||||
fetch,
|
||||
}) => {
|
||||
const { compilation } = await loadExample(require.resolve('./stop.mocks.ts'))
|
||||
const { compilation } = await loadExample(
|
||||
new URL('./stop.mocks.ts', import.meta.url),
|
||||
)
|
||||
|
||||
const firstPage = await context.newPage()
|
||||
await firstPage.goto(compilation.previewUrl, {
|
||||
@@ -90,7 +92,7 @@ test('prints a warning on multiple "worker.stop()" calls', async ({
|
||||
page,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./stop.mocks.ts'))
|
||||
await loadExample(new URL('./stop.mocks.ts', import.meta.url))
|
||||
|
||||
function byStopMessage(text: string): boolean {
|
||||
return text === '[MSW] Mocking disabled.'
|
||||
|
||||
@@ -7,7 +7,7 @@ declare namespace window {
|
||||
}
|
||||
}
|
||||
|
||||
const QUIET_EXAMPLE = require.resolve('./quiet.mocks.ts')
|
||||
const QUIET_EXAMPLE = new URL('./quiet.mocks.ts', import.meta.url)
|
||||
|
||||
test('prints out the console stop message', async ({
|
||||
loadExample,
|
||||
|
||||
@@ -15,9 +15,12 @@ test('removes all listeners when the worker is stopped', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./removes-all-listeners.mocks.ts'), {
|
||||
skipActivation: true,
|
||||
})
|
||||
await loadExample(
|
||||
new URL('./removes-all-listeners.mocks.ts', import.meta.url),
|
||||
{
|
||||
skipActivation: true,
|
||||
},
|
||||
)
|
||||
|
||||
await page.waitForFunction(() => {
|
||||
return typeof window.msw !== 'undefined'
|
||||
|
||||
@@ -15,7 +15,7 @@ test('returns a mocked response from a runtime request handler upon match', asyn
|
||||
fetch,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./use.mocks.ts'))
|
||||
await loadExample(new URL('./use.mocks.ts', import.meta.url))
|
||||
|
||||
await page.evaluate(() => {
|
||||
const { worker, http, HttpResponse } = window.msw
|
||||
@@ -48,7 +48,7 @@ test('returns a mocked response from a persistent request handler override', asy
|
||||
fetch,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./use.mocks.ts'))
|
||||
await loadExample(new URL('./use.mocks.ts', import.meta.url))
|
||||
|
||||
await page.evaluate(() => {
|
||||
const { worker, http, HttpResponse } = window.msw
|
||||
@@ -78,7 +78,7 @@ test('returns a mocked response from a one-time request handler override only up
|
||||
fetch,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./use.mocks.ts'))
|
||||
await loadExample(new URL('./use.mocks.ts', import.meta.url))
|
||||
|
||||
await page.evaluate(() => {
|
||||
const { worker, http, HttpResponse } = window.msw
|
||||
@@ -112,7 +112,7 @@ test('returns a mocked response from a one-time request handler override only up
|
||||
fetch,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./use.mocks.ts'))
|
||||
await loadExample(new URL('./use.mocks.ts', import.meta.url))
|
||||
|
||||
await page.evaluate(() => {
|
||||
const { worker, http, HttpResponse } = window.msw
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { test, expect } from '../../playwright.extend'
|
||||
|
||||
const httpServer = new HttpServer((app) => {
|
||||
@@ -20,7 +20,9 @@ test('removes the internal passthrough request header', async ({
|
||||
loadExample,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./worker-passthrough-header.mocks.ts'))
|
||||
await loadExample(
|
||||
new URL('./worker-passthrough-header.mocks.ts', import.meta.url),
|
||||
)
|
||||
|
||||
const response = await fetch(httpServer.http.url('/resource'), {
|
||||
headers: { 'x-custom-header': 'yes' },
|
||||
@@ -39,7 +41,9 @@ test('preserves existing "accept" header values when removing the internal passt
|
||||
loadExample,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./worker-passthrough-header.mocks.ts'))
|
||||
await loadExample(
|
||||
new URL('./worker-passthrough-header.mocks.ts', import.meta.url),
|
||||
)
|
||||
|
||||
const response = await fetch(httpServer.http.url('/resource'), {
|
||||
headers: {
|
||||
|
||||
@@ -14,7 +14,7 @@ test('unregisters itself when not prompted to be activated again', async ({
|
||||
waitForMswActivation,
|
||||
}) => {
|
||||
const { compilation } = await loadExample(
|
||||
require.resolve('./unregister.mocks.ts'),
|
||||
new URL('./unregister.mocks.ts', import.meta.url),
|
||||
{
|
||||
skipActivation: true,
|
||||
beforeNavigation(compilation) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { PlaywrightTestConfig, devices } from '@playwright/test'
|
||||
import { type PlaywrightTestConfig, devices } from '@playwright/test'
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: __dirname,
|
||||
export default {
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
@@ -26,6 +25,4 @@ const config: PlaywrightTestConfig = {
|
||||
// and there's no shared state leaking from the shared compilation
|
||||
// server or the preview server.
|
||||
fullyParallel: true,
|
||||
}
|
||||
|
||||
export default config
|
||||
} satisfies PlaywrightTestConfig
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as crypto from 'crypto'
|
||||
import url from 'node:url'
|
||||
import crypto from 'node:crypto'
|
||||
import { test as base, expect, type Response, Page } from '@playwright/test'
|
||||
import {
|
||||
Headers,
|
||||
@@ -7,7 +8,10 @@ import {
|
||||
type FlatHeadersObject,
|
||||
} from 'headers-polyfill'
|
||||
import { spyOnConsole, ConsoleMessages } from 'page-with'
|
||||
import { HttpServer, HttpServerMiddleware } from '@open-draft/test-server/http'
|
||||
import {
|
||||
HttpServer,
|
||||
HttpServerMiddleware,
|
||||
} from '@open-draft/test-server/lib/http.js'
|
||||
import {
|
||||
Compilation,
|
||||
CompilationOptions,
|
||||
@@ -24,7 +28,7 @@ export interface TestFixtures {
|
||||
createServer(...middleware: Array<HttpServerMiddleware>): Promise<HttpServer>
|
||||
webpackServer: WebpackHttpServer
|
||||
loadExample(
|
||||
entry: string | Array<string>,
|
||||
entry: string | Array<string> | URL,
|
||||
options?: CompilationOptions & {
|
||||
/**
|
||||
* Do not await the "Mocking enabled" message in the console.
|
||||
@@ -88,8 +92,11 @@ export const test = base.extend<TestFixtures>({
|
||||
let compilation: Compilation | undefined
|
||||
|
||||
await use(async (entry, options = {}) => {
|
||||
const resolvedEntry =
|
||||
entry instanceof URL ? url.fileURLToPath(entry) : entry
|
||||
|
||||
compilation = await webpackServer.compile(
|
||||
Array.prototype.concat([], entry),
|
||||
Array.prototype.concat([], resolvedEntry),
|
||||
options,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
|
||||
const httpServer = new HttpServer((app) => {
|
||||
@@ -24,7 +24,7 @@ test('handles a 204 status response without Response instance exceptions', async
|
||||
fetch,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./basic.mocks.ts'))
|
||||
await loadExample(new URL('./basic.mocks.ts', import.meta.url))
|
||||
|
||||
let pageError: Error
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @see https://github.com/mswjs/msw/issues/1972
|
||||
*/
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { expect, test } from '../playwright.extend'
|
||||
|
||||
const encoder = new TextEncoder()
|
||||
@@ -46,7 +46,7 @@ test('forwards the 206 response to a bypassed "Range" request', async ({
|
||||
loadExample,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./206-response.mocks.ts'))
|
||||
await loadExample(new URL('./206-response.mocks.ts', import.meta.url))
|
||||
|
||||
const response = await fetch(server.http.url('/range'), {
|
||||
headers: {
|
||||
@@ -68,7 +68,7 @@ test('responds with a 206 response to a mocked "Range" request', async ({
|
||||
loadExample,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./206-response.mocks.ts'))
|
||||
await loadExample(new URL('./206-response.mocks.ts', import.meta.url))
|
||||
|
||||
const response = await fetch('/mocked-range', {
|
||||
headers: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { test, expect } from '../playwright.extend'
|
||||
|
||||
test('mocks response to a GET request', async ({ loadExample, fetch }) => {
|
||||
await loadExample(require.resolve('./basic.mocks.ts'))
|
||||
await loadExample(new URL('./basic.mocks.ts', import.meta.url))
|
||||
|
||||
const response = await fetch('https://example.com/users/octocat')
|
||||
const status = response.status()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { test, expect } from '../playwright.extend'
|
||||
|
||||
const EXAMPLE_PATH = require.resolve('./body.mocks.ts')
|
||||
const EXAMPLE_PATH = new URL('./body.mocks.ts', import.meta.url)
|
||||
|
||||
test('handles a GET request without a body', async ({ loadExample, fetch }) => {
|
||||
await loadExample(EXAMPLE_PATH)
|
||||
|
||||
@@ -4,7 +4,7 @@ test('composes various context utilities into a valid mocked response', async ({
|
||||
loadExample,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./context.mocks.ts'))
|
||||
await loadExample(new URL('./context.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch('https://test.mswjs.io/')
|
||||
const headers = await res.allHeaders()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HttpServer } from '@open-draft/test-server/http'
|
||||
import { HttpServer } from '@open-draft/test-server/lib/http.js'
|
||||
import { test, expect } from '../playwright.extend'
|
||||
|
||||
const server = new HttpServer((app) => {
|
||||
@@ -27,7 +27,7 @@ test('handles a CORS request with an "opaque" response', async ({
|
||||
fetch,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./cors.mocks.ts'))
|
||||
await loadExample(new URL('./cors.mocks.ts', import.meta.url))
|
||||
|
||||
const errors = []
|
||||
page.on('pageerror', (error) => errors.push(error))
|
||||
|
||||
@@ -13,7 +13,7 @@ test('supports a generator function as the response resolver', async ({
|
||||
loadExample,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./generator.mocks.ts'))
|
||||
await loadExample(new URL('./generator.mocks.ts', import.meta.url))
|
||||
|
||||
const assertRequest = async (expectedBody: ExpectedResponseBody) => {
|
||||
const res = await fetch('/polling/3')
|
||||
@@ -35,7 +35,7 @@ test('supports one-time handlers with the generator as the response resolver', a
|
||||
loadExample,
|
||||
fetch,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./generator.mocks.ts'))
|
||||
await loadExample(new URL('./generator.mocks.ts', import.meta.url))
|
||||
|
||||
const assertRequest = async (expectedBody: ExpectedResponseBody) => {
|
||||
const res = await fetch('/polling/once/3')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { test, expect } from '../playwright.extend'
|
||||
|
||||
const EXAMPLE_PATH = require.resolve('./headers-multiple.mocks.ts')
|
||||
const EXAMPLE_PATH = new URL('./headers-multiple.mocks.ts', import.meta.url)
|
||||
|
||||
test('receives all headers from the request header with multiple values', async ({
|
||||
loadExample,
|
||||
|
||||
@@ -8,7 +8,7 @@ test('prints the intercepted request info into browser console', async ({
|
||||
fetch,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./basic.mocks.ts'))
|
||||
await loadExample(new URL('./basic.mocks.ts', import.meta.url))
|
||||
|
||||
await fetch('https://example.com/users/octocat')
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { test, expect } from '../playwright.extend'
|
||||
|
||||
test('parses request URL parameters', async ({ loadExample, fetch }) => {
|
||||
await loadExample(require.resolve('./params.mocks.ts'))
|
||||
await loadExample(new URL('./params.mocks.ts', import.meta.url))
|
||||
|
||||
const res = await fetch(
|
||||
'https://api.github.com/users/octocat/messages/abc-123',
|
||||
|
||||
@@ -5,7 +5,7 @@ test('returns a plain Response as a mocked response', async ({
|
||||
fetch,
|
||||
spyOnConsole,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./plain-response.mocks.ts'))
|
||||
await loadExample(new URL('./plain-response.mocks.ts', import.meta.url))
|
||||
const consoleSpy = spyOnConsole()
|
||||
|
||||
const response = await fetch('/greeting')
|
||||
|
||||
@@ -6,7 +6,7 @@ test('warns when a request handler URL contains query parameters', async ({
|
||||
spyOnConsole,
|
||||
}) => {
|
||||
const consoleSpy = spyOnConsole()
|
||||
await loadExample(require.resolve('./query-params-warning.mocks.ts'))
|
||||
await loadExample(new URL('./query-params-warning.mocks.ts', import.meta.url))
|
||||
|
||||
expect(consoleSpy.get('warning')).toEqual([
|
||||
`[MSW] Found a redundant usage of query parameters in the request handler URL for "GET /user?name=admin". Please match against a path instead and access query parameters using \"new URL(request.url).searchParams\" instead. Learn more: https://mswjs.io/docs/recipes/query-parameters`,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { test, expect } from '../playwright.extend'
|
||||
|
||||
const EXAMPLE_PATH = require.resolve('./query.mocks.ts')
|
||||
const EXAMPLE_PATH = new URL('./query.mocks.ts', import.meta.url)
|
||||
|
||||
test('retrieves a single request URL query parameter', async ({
|
||||
loadExample,
|
||||
|
||||
@@ -6,7 +6,7 @@ test('supports redirect in a mocked response', async ({
|
||||
makeUrl,
|
||||
page,
|
||||
}) => {
|
||||
await loadExample(require.resolve('./redirect.mocks.ts'))
|
||||
await loadExample(new URL('./redirect.mocks.ts', import.meta.url))
|
||||
|
||||
const [res, redirectRes] = await Promise.all([
|
||||
await fetch('/login'),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user