@interfere/test-utils 9.0.1-canary.1 → 9.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- //#region src/vitest/msw-browser.d.ts
1
+ //#region src/vitest/msw/browser.d.ts
2
2
  declare const worker: import("msw/browser").SetupWorker;
3
3
  declare function enableMSW(): void;
4
4
  //#endregion
@@ -0,0 +1 @@
1
+ import{afterAll,afterEach,beforeAll}from"vitest";import{setupWorker}from"msw/browser";const worker=setupWorker();function enableMSW(){beforeAll(async()=>{await worker.start({onUnhandledRequest:`bypass`,quiet:!0})}),afterEach(()=>{worker.resetHandlers()}),afterAll(()=>{worker.stop()})}export{enableMSW,worker};
@@ -1,4 +1,4 @@
1
- //#region src/vitest/msw-http.d.ts
1
+ //#region src/vitest/msw/http.d.ts
2
2
  type HttpMethod = "post" | "get" | "put" | "delete" | "patch";
3
3
  type JsonValue = string | number | boolean | null | JsonValue[] | {
4
4
  [key: string]: JsonValue;
@@ -0,0 +1 @@
1
+ import{worker}from"./browser.mjs";import{HttpResponse,http}from"msw";async function parseBody(request){let clone=request.clone();if((clone.headers.get(`content-type`)??``).includes(`multipart/form-data`)){let formData=await clone.formData();return Object.fromEntries(formData.entries())}return clone.json().catch(()=>null)}function createHttpInterceptor(baseUrl){function intercept(method,path,response,status=200){let calls=[];return worker.use(http[method](`${baseUrl}${path}`,async({request,params})=>(calls.push({body:await parseBody(request),params}),HttpResponse.json(response,{status})))),calls}function interceptNetworkError(method,path){worker.use(http[method](`${baseUrl}${path}`,()=>HttpResponse.error()))}return{intercept,interceptNetworkError}}export{createHttpInterceptor};
@@ -0,0 +1,13 @@
1
+ import { HttpMethod, JsonValue } from "./http.mjs";
2
+
3
+ //#region src/vitest/msw/node.d.ts
4
+ declare const server: import("msw/node").SetupServer;
5
+ declare function useMswServer(): typeof server;
6
+ interface CapturedRequest {
7
+ headers: Headers;
8
+ url: URL;
9
+ }
10
+ declare function interceptJson(method: HttpMethod, url: string, response: JsonValue, status?: number): CapturedRequest[];
11
+ declare function interceptError(method: HttpMethod, url: string): void;
12
+ //#endregion
13
+ export { CapturedRequest, interceptError, interceptJson, server, useMswServer };
@@ -0,0 +1 @@
1
+ import{afterAll,afterEach,beforeAll}from"vitest";import{HttpResponse,http}from"msw";import{setupServer}from"msw/node";const server=setupServer();function useMswServer(){return beforeAll(()=>server.listen({onUnhandledRequest:`error`})),afterEach(()=>server.resetHandlers()),afterAll(()=>server.close()),server}function interceptJson(method,url,response,status=200){let calls=[];return server.use(http[method](url,({request})=>(calls.push({headers:request.headers,url:new URL(request.url)}),HttpResponse.json(response,{status})))),calls}function interceptError(method,url){server.use(http[method](url,()=>HttpResponse.error()))}export{interceptError,interceptJson,server,useMswServer};
@@ -1,4 +1,4 @@
1
- import{dirname,join}from"node:path";import{expect}from"vitest";import{execFile}from"node:child_process";import{mkdir,mkdtemp,readFile,rename,rm,symlink}from"node:fs/promises";import{tmpdir}from"node:os";import{fileURLToPath}from"node:url";import{promisify}from"node:util";const execFileAsync=promisify(execFile),PACKED_LINE=/^packed\s+\S+\s+(.+)$/,TGZ_LINE=/^(\S+\.tgz)$/,PACKAGE_CONTRACT_TIMEOUT_MS=3e4;async function expectPackedPackageFiles({expectedFiles,packageJsonUrl}){let packedPackage=await createPackedPackage(packageJsonUrl);try{expect(packedPackage.files).toEqual(expect.arrayContaining(expectedFiles)),expect(packedPackage.files.filter(path=>path.startsWith(`src/`))).toEqual([]),expect(packedPackage.files.filter(path=>path.endsWith(`.map`))).toEqual([]),expect(packedPackage.packageJson.private).toBeUndefined(),expect(Object.keys(packedPackage.packageJson.devDependencies??{})).not.toContain(`@interfere/tsdown-config`)}finally{await packedPackage.cleanup()}}async function expectNodeCanLoadPackageSpecifiers({packageJsonUrl,specifiers}){let packedPackage=await createPackedPackage(packageJsonUrl);try{await runNodeScript({args:[`--input-type=module`,`--eval`,importScript(specifiers)],cwd:packedPackage.consumerDir,label:`ESM import`}),await runNodeScript({args:[`--eval`,requireScript(specifiers)],cwd:packedPackage.consumerDir,label:`CommonJS require`})}finally{await packedPackage.cleanup()}}async function createPackedPackage(packageJsonUrl){let packageDir=dirname(fileURLToPath(packageJsonUrl)),tempDir=await mkdtemp(join(tmpdir(),`interfere-package-contract-`)),consumerDir=join(tempDir,`consumer`),nodeModulesDir=join(consumerDir,`node_modules`),packageJson=JSON.parse(await readFile(packageJsonUrl,`utf8`)),installedPackageDir=joinPackageName(nodeModulesDir,packageJson.name);await mkdir(dirname(installedPackageDir),{recursive:!0});let{stdout}=await execFileAsync(`bun`,[`pm`,`pack`,`--ignore-scripts`],{cwd:packageDir}),{filename,files}=parseBunPackOutput(stdout),tarballPath=join(packageDir,filename),extractedDir=join(tempDir,`extracted`);await mkdir(extractedDir),await execFileAsync(`tar`,[`-xzf`,tarballPath,`-C`,extractedDir]),await rm(tarballPath),await rename(join(extractedDir,`package`),installedPackageDir),await linkRuntimeDependencies({nodeModulesDir,packageDir,packageJson});let packedPackageJson=JSON.parse(await readFile(join(installedPackageDir,`package.json`),`utf8`));return{cleanup:()=>rm(tempDir,{force:!0,recursive:!0}),consumerDir,files:files.toSorted(),packageJson:packedPackageJson}}function parseBunPackOutput(stdout){let files=[],filename=``;for(let line of stdout.split(`
1
+ import{dirname,join}from"node:path";import{execFile}from"node:child_process";import{mkdir,mkdtemp,readFile,rename,rm,symlink}from"node:fs/promises";import{tmpdir}from"node:os";import{fileURLToPath}from"node:url";import{promisify}from"node:util";import{expect}from"vitest";const execFileAsync=promisify(execFile),PACKED_LINE=/^packed\s+\S+\s+(.+)$/,TGZ_LINE=/^(\S+\.tgz)$/,PACKAGE_CONTRACT_TIMEOUT_MS=3e4;async function expectPackedPackageFiles({expectedFiles,packageJsonUrl}){let packedPackage=await createPackedPackage(packageJsonUrl);try{expect(packedPackage.files).toEqual(expect.arrayContaining(expectedFiles)),expect(packedPackage.files.filter(path=>path.startsWith(`src/`))).toEqual([]),expect(packedPackage.files.filter(path=>path.endsWith(`.map`))).toEqual([]),expect(packedPackage.packageJson.private).toBeUndefined(),expect(Object.keys(packedPackage.packageJson.devDependencies??{})).not.toContain(`@interfere/tsdown-config`)}finally{await packedPackage.cleanup()}}async function expectNodeCanLoadPackageSpecifiers({packageJsonUrl,specifiers}){let packedPackage=await createPackedPackage(packageJsonUrl);try{await runNodeScript({args:[`--input-type=module`,`--eval`,importScript(specifiers)],cwd:packedPackage.consumerDir,label:`ESM import`}),await runNodeScript({args:[`--eval`,requireScript(specifiers)],cwd:packedPackage.consumerDir,label:`CommonJS require`})}finally{await packedPackage.cleanup()}}async function createPackedPackage(packageJsonUrl){let packageDir=dirname(fileURLToPath(packageJsonUrl)),tempDir=await mkdtemp(join(tmpdir(),`interfere-package-contract-`)),consumerDir=join(tempDir,`consumer`),nodeModulesDir=join(consumerDir,`node_modules`),packageJson=JSON.parse(await readFile(packageJsonUrl,`utf8`)),installedPackageDir=joinPackageName(nodeModulesDir,packageJson.name);await mkdir(dirname(installedPackageDir),{recursive:!0});let{stdout}=await execFileAsync(`bun`,[`pm`,`pack`,`--ignore-scripts`],{cwd:packageDir}),{filename,files}=parseBunPackOutput(stdout),tarballPath=join(packageDir,filename),extractedDir=join(tempDir,`extracted`);await mkdir(extractedDir),await execFileAsync(`tar`,[`-xzf`,tarballPath,`-C`,extractedDir]),await rm(tarballPath),await rename(join(extractedDir,`package`),installedPackageDir),await linkRuntimeDependencies({nodeModulesDir,packageDir,packageJson});let packedPackageJson=JSON.parse(await readFile(join(installedPackageDir,`package.json`),`utf8`));return{cleanup:()=>rm(tempDir,{force:!0,recursive:!0}),consumerDir,files:files.toSorted(),packageJson:packedPackageJson}}function parseBunPackOutput(stdout){let files=[],filename=``;for(let line of stdout.split(`
2
2
  `)){let packMatch=line.match(PACKED_LINE);if(packMatch?.[1]){files.push(packMatch[1]);continue}let tgzMatch=line.match(TGZ_LINE);tgzMatch?.[1]&&(filename=tgzMatch[1])}if(!filename)throw Error(`bun pm pack did not produce a tarball:\n${stdout}`);return{filename,files}}async function linkRuntimeDependencies({nodeModulesDir,packageDir,packageJson}){let dependencies=new Set([...Object.keys(packageJson.dependencies??{}),...Object.keys(packageJson.peerDependencies??{})]);for(let dependencyName of Array.from(dependencies)){if(dependencyName===packageJson.name)continue;let source=joinPackageName(join(packageDir,`node_modules`),dependencyName),target=joinPackageName(nodeModulesDir,dependencyName);await mkdir(dirname(target),{recursive:!0}),await symlink(source,target,`junction`)}}function joinPackageName(nodeModulesDir,packageName){return join(nodeModulesDir,...packageName.split(`/`))}async function runNodeScript({args,cwd,label}){try{await execFileAsync(process.execPath,args,{cwd})}catch(error){throw error instanceof Error?Error(`${label} package contract failed:\n${error.message}`):error}}function importScript(specifiers){return specifiers.map(specifier=>`await import(${JSON.stringify(specifier)});`).join(`
3
3
  `)}function requireScript(specifiers){return specifiers.map(specifier=>`require(${JSON.stringify(specifier)});`).join(`
4
4
  `)}export{PACKAGE_CONTRACT_TIMEOUT_MS,expectNodeCanLoadPackageSpecifiers,expectPackedPackageFiles};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interfere/test-utils",
3
- "version": "9.0.1-canary.1",
3
+ "version": "9.0.1",
4
4
  "license": "MIT",
5
5
  "description": "Shared test utilities used across Interfere packages.",
6
6
  "homepage": "https://interfere.com",
@@ -38,6 +38,11 @@
38
38
  "types": "./dist/vitest/presets/*.d.mts",
39
39
  "default": "./dist/vitest/presets/*.mjs"
40
40
  },
41
+ "./vitest/msw/*": {
42
+ "monorepo": "./src/vitest/msw/*.ts",
43
+ "types": "./dist/vitest/msw/*.d.mts",
44
+ "default": "./dist/vitest/msw/*.mjs"
45
+ },
41
46
  "./package.json": "./package.json"
42
47
  },
43
48
  "publishConfig": {
@@ -69,14 +74,14 @@
69
74
  }
70
75
  },
71
76
  "dependencies": {
72
- "@interfere/helpers": "^9.0.1-canary.1",
77
+ "@interfere/helpers": "^9.0.1-canary.2",
73
78
  "dotenv": "^17.4.2"
74
79
  },
75
80
  "devDependencies": {
76
- "@interfere/typescript-config": "^9.0.1-canary.0",
81
+ "@interfere/typescript-config": "^9.0.1-canary.1",
77
82
  "@playwright/test": "^1.61.1",
78
- "@types/node": "^26.0.0",
79
- "@typescript/native-preview": "7.0.0-dev.20260623.1",
83
+ "@types/node": "^26.1.0",
84
+ "@typescript/native-preview": "7.0.0-dev.20260701.1",
80
85
  "@vitejs/plugin-react": "^6.0.3",
81
86
  "@vitest/browser-playwright": "4.1.9",
82
87
  "msw": "^2.14.6",
@@ -1 +0,0 @@
1
- import{setupWorker}from"msw/browser";import{afterAll,afterEach,beforeAll}from"vitest";const worker=setupWorker();function enableMSW(){beforeAll(async()=>{await worker.start({onUnhandledRequest:`bypass`,quiet:!0})}),afterEach(()=>{worker.resetHandlers()}),afterAll(()=>{worker.stop()})}export{enableMSW,worker};
@@ -1 +0,0 @@
1
- import{worker}from"./msw-browser.mjs";import{HttpResponse,http}from"msw";async function parseBody(request){let clone=request.clone();if((clone.headers.get(`content-type`)??``).includes(`multipart/form-data`)){let formData=await clone.formData();return Object.fromEntries(formData.entries())}return clone.json().catch(()=>null)}function createHttpInterceptor(baseUrl){function intercept(method,path,response,status=200){let calls=[];return worker.use(http[method](`${baseUrl}${path}`,async({request,params})=>(calls.push({body:await parseBody(request),params}),HttpResponse.json(response,{status})))),calls}function interceptNetworkError(method,path){worker.use(http[method](`${baseUrl}${path}`,()=>HttpResponse.error()))}return{intercept,interceptNetworkError}}export{createHttpInterceptor};