@interfere/test-utils 9.0.0 → 9.0.1-canary.0
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.
- package/dist/lib/tags.mjs +1 -6
- package/dist/lib/viewports.mjs +1 -11
- package/dist/playwright/base.d.mts +5 -3
- package/dist/playwright/base.mjs +1 -32
- package/dist/playwright/define-config.mjs +1 -9
- package/dist/playwright/protection-bypass.d.mts +5 -0
- package/dist/playwright/protection-bypass.mjs +1 -0
- package/dist/vitest/base.d.mts +8 -0
- package/dist/vitest/base.mjs +1 -57
- package/dist/vitest/define-config.mjs +1 -9
- package/dist/vitest/msw-browser.d.mts +1 -3
- package/dist/vitest/msw-browser.mjs +1 -20
- package/dist/vitest/msw-http.mjs +1 -33
- package/dist/vitest/package-contract.d.mts +21 -0
- package/dist/vitest/package-contract.mjs +4 -0
- package/dist/vitest/presets/browser.mjs +1 -60
- package/dist/vitest/presets/integration.d.mts +36 -0
- package/dist/vitest/presets/integration.mjs +1 -0
- package/dist/vitest/presets/node.mjs +1 -26
- package/dist/vitest/presets/vite.d.mts +15 -0
- package/dist/vitest/presets/vite.mjs +1 -0
- package/package.json +20 -20
- package/dist/lib/tags.d.mts.map +0 -1
- package/dist/lib/tags.mjs.map +0 -1
- package/dist/lib/viewports.d.mts.map +0 -1
- package/dist/lib/viewports.mjs.map +0 -1
- package/dist/playwright/base.d.mts.map +0 -1
- package/dist/playwright/base.mjs.map +0 -1
- package/dist/playwright/define-config.d.mts.map +0 -1
- package/dist/playwright/define-config.mjs.map +0 -1
- package/dist/vitest/base.d.mts.map +0 -1
- package/dist/vitest/base.mjs.map +0 -1
- package/dist/vitest/define-config.d.mts.map +0 -1
- package/dist/vitest/define-config.mjs.map +0 -1
- package/dist/vitest/msw-browser.d.mts.map +0 -1
- package/dist/vitest/msw-browser.mjs.map +0 -1
- package/dist/vitest/msw-http.d.mts.map +0 -1
- package/dist/vitest/msw-http.mjs.map +0 -1
- package/dist/vitest/presets/browser.d.mts.map +0 -1
- package/dist/vitest/presets/browser.mjs.map +0 -1
- package/dist/vitest/presets/node.d.mts.map +0 -1
- package/dist/vitest/presets/node.mjs.map +0 -1
package/dist/lib/tags.mjs
CHANGED
package/dist/lib/viewports.mjs
CHANGED
|
@@ -1,11 +1 @@
|
|
|
1
|
-
|
|
2
|
-
const DESKTOP = {
|
|
3
|
-
width: 1280,
|
|
4
|
-
height: 720
|
|
5
|
-
};
|
|
6
|
-
const MOBILE = {
|
|
7
|
-
width: 390,
|
|
8
|
-
height: 844
|
|
9
|
-
};
|
|
10
|
-
//#endregion
|
|
11
|
-
export { DESKTOP, MOBILE };
|
|
1
|
+
const DESKTOP={width:1280,height:720},MOBILE={width:390,height:844};export{DESKTOP,MOBILE};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import * as _$_playwright_test0 from "@playwright/test";
|
|
2
|
-
|
|
3
1
|
//#region src/playwright/base.d.ts
|
|
4
2
|
declare const _default: {
|
|
5
3
|
fullyParallel: true;
|
|
6
4
|
forbidOnly: boolean;
|
|
5
|
+
retries: number;
|
|
7
6
|
reporter: ["html"][] | (["github"] | ["junit", {
|
|
8
7
|
outputFile: string;
|
|
9
8
|
}])[];
|
|
@@ -11,6 +10,9 @@ declare const _default: {
|
|
|
11
10
|
trace: "on-first-retry";
|
|
12
11
|
screenshot: "only-on-failure";
|
|
13
12
|
actionTimeout?: number;
|
|
13
|
+
launchOptions?: {
|
|
14
|
+
executablePath: string;
|
|
15
|
+
};
|
|
14
16
|
};
|
|
15
17
|
expect?: {
|
|
16
18
|
timeout: number;
|
|
@@ -19,7 +21,7 @@ declare const _default: {
|
|
|
19
21
|
name: string;
|
|
20
22
|
grep: RegExp;
|
|
21
23
|
use: {
|
|
22
|
-
viewport:
|
|
24
|
+
viewport: import("@playwright/test").ViewportSize;
|
|
23
25
|
userAgent: string;
|
|
24
26
|
deviceScaleFactor: number;
|
|
25
27
|
isMobile: boolean;
|
package/dist/playwright/base.mjs
CHANGED
|
@@ -1,32 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { MOBILE as MOBILE$1 } from "../lib/viewports.mjs";
|
|
3
|
-
import { devices } from "@playwright/test";
|
|
4
|
-
//#region src/playwright/base.ts
|
|
5
|
-
const ci = !!process.env["CI"];
|
|
6
|
-
var base_default = {
|
|
7
|
-
fullyParallel: true,
|
|
8
|
-
forbidOnly: ci,
|
|
9
|
-
reporter: ci ? [["github"], ["junit", { outputFile: "./test-results/e2e-junit.xml" }]] : [["html"]],
|
|
10
|
-
use: {
|
|
11
|
-
trace: "on-first-retry",
|
|
12
|
-
screenshot: "only-on-failure",
|
|
13
|
-
...ci && { actionTimeout: 1e4 }
|
|
14
|
-
},
|
|
15
|
-
...ci && { expect: { timeout: 1e4 } },
|
|
16
|
-
projects: [{
|
|
17
|
-
name: "desktop",
|
|
18
|
-
grep: new RegExp(`${DESKTOP}|${COMMON}`),
|
|
19
|
-
use: { ...devices["Desktop Chrome"] }
|
|
20
|
-
}, {
|
|
21
|
-
name: "mobile",
|
|
22
|
-
grep: new RegExp(`${MOBILE}|${COMMON}`),
|
|
23
|
-
use: {
|
|
24
|
-
...devices["Desktop Chrome"],
|
|
25
|
-
viewport: MOBILE$1,
|
|
26
|
-
isMobile: true,
|
|
27
|
-
hasTouch: true
|
|
28
|
-
}
|
|
29
|
-
}]
|
|
30
|
-
};
|
|
31
|
-
//#endregion
|
|
32
|
-
export { base_default as default };
|
|
1
|
+
import{COMMON,DESKTOP,MOBILE}from"../lib/tags.mjs";import{MOBILE as MOBILE$1}from"../lib/viewports.mjs";import{devices}from"@playwright/test";const ci=!!process.env.CI,chromiumExecutablePath=process.env.CHROMIUM_EXECUTABLE_PATH;var base_default={fullyParallel:!0,forbidOnly:ci,retries:ci?2:0,reporter:ci?[[`github`],[`junit`,{outputFile:`./test-results/e2e-junit.xml`}]]:[[`html`]],use:{trace:`on-first-retry`,screenshot:`only-on-failure`,...ci&&{actionTimeout:1e4},...chromiumExecutablePath&&{launchOptions:{executablePath:chromiumExecutablePath}}},...ci&&{expect:{timeout:1e4}},projects:[{name:`desktop`,grep:RegExp(`${DESKTOP}|${COMMON}`),use:{...devices[`Desktop Chrome`]}},{name:`mobile`,grep:RegExp(`${MOBILE}|${COMMON}`),use:{...devices[`Desktop Chrome`],viewport:MOBILE$1,isMobile:!0,hasTouch:!0}}]};export{base_default as default};
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
import base_default from
|
|
2
|
-
import { defineConfig as defineConfig$1 } from "@playwright/test";
|
|
3
|
-
import { deepMerge } from "@interfere/helpers/deep-merge";
|
|
4
|
-
//#region src/playwright/define-config.ts
|
|
5
|
-
function defineConfig(...overrides) {
|
|
6
|
-
return defineConfig$1(deepMerge(base_default, ...overrides));
|
|
7
|
-
}
|
|
8
|
-
//#endregion
|
|
9
|
-
export { defineConfig };
|
|
1
|
+
import base_default from"./base.mjs";import{defineConfig as defineConfig$1}from"@playwright/test";import{deepMerge}from"@interfere/helpers/deep-merge";function defineConfig(...overrides){return defineConfig$1(deepMerge(base_default,...overrides))}export{defineConfig};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
//#region src/playwright/protection-bypass.d.ts
|
|
2
|
+
type ProtectionProvider = "cloudflare-access";
|
|
3
|
+
declare function protectionBypassHeaders(baseURL: string | undefined, provider: ProtectionProvider): Record<string, string> | undefined;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { ProtectionProvider, protectionBypassHeaders };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const LOCAL_HOSTNAMES=new Set([`localhost`,`127.0.0.1`,`0.0.0.0`,`[::1]`]);function isLocal(baseURL){try{return LOCAL_HOSTNAMES.has(new URL(baseURL).hostname)}catch{return!1}}function cloudflareAccessHeaders(baseURL){let clientId=process.env.CF_ACCESS_CLIENT_ID,clientSecret=process.env.CF_ACCESS_CLIENT_SECRET;if(!(clientId&&clientSecret))throw Error([`Missing CF_ACCESS_CLIENT_ID / CF_ACCESS_CLIENT_SECRET while BASE_URL points at a remote Cloudflare deployment.`,`BASE_URL=${baseURL}`,"Playwright cannot bypass Cloudflare Access without the `cf-iac-ci` service token.","Fetch both values from GSM: `cf-access-service-token-id` and `cf-access-service-token-secret`."].join(` `));return{"CF-Access-Client-Id":clientId,"CF-Access-Client-Secret":clientSecret}}function protectionBypassHeaders(baseURL,provider){if(!(!baseURL||isLocal(baseURL))){if(provider===`cloudflare-access`)return cloudflareAccessHeaders(baseURL);throw Error(`Unsupported protection provider: ${provider}`)}}export{protectionBypassHeaders};
|
package/dist/vitest/base.d.mts
CHANGED
|
@@ -20,15 +20,23 @@ declare const _default: {
|
|
|
20
20
|
maxWorkers: string;
|
|
21
21
|
clearMocks: true;
|
|
22
22
|
restoreMocks: true;
|
|
23
|
+
ui: boolean;
|
|
23
24
|
unstubEnvs: true;
|
|
24
25
|
unstubGlobals: true;
|
|
25
26
|
sequence: {
|
|
26
27
|
shuffle: boolean;
|
|
27
28
|
};
|
|
29
|
+
server: {
|
|
30
|
+
deps: {
|
|
31
|
+
inline: string[];
|
|
32
|
+
};
|
|
33
|
+
};
|
|
28
34
|
include: string[];
|
|
29
35
|
exclude: string[];
|
|
30
36
|
reporters: ("default" | "junit")[];
|
|
31
37
|
coverage: {
|
|
38
|
+
enabled: true;
|
|
39
|
+
provider: "v8";
|
|
32
40
|
include: string[];
|
|
33
41
|
exclude: string[];
|
|
34
42
|
reporter: ("json" | "json-summary" | "lcov")[] | ("clover" | "html" | "json" | "text")[];
|
package/dist/vitest/base.mjs
CHANGED
|
@@ -1,57 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { resolve } from "node:path";
|
|
4
|
-
import { config } from "dotenv";
|
|
5
|
-
import { configDefaults } from "vitest/config";
|
|
6
|
-
//#region src/vitest/base.ts
|
|
7
|
-
const root = process.cwd();
|
|
8
|
-
const isCI = Boolean(process.env["CI"]);
|
|
9
|
-
const env = config({
|
|
10
|
-
path: resolve(root, ".env.test"),
|
|
11
|
-
quiet: true
|
|
12
|
-
}).parsed ?? {};
|
|
13
|
-
const setupFiles = ["./test/setup.ts", "./test/unit/setup.ts"].filter((rel) => existsSync(resolve(root, rel)));
|
|
14
|
-
var base_default = {
|
|
15
|
-
root,
|
|
16
|
-
resolve: { conditions: ["@source"] },
|
|
17
|
-
ssr: { resolve: { conditions: ["@source"] } },
|
|
18
|
-
test: {
|
|
19
|
-
env: {
|
|
20
|
-
...env,
|
|
21
|
-
NODE_ENV: "test"
|
|
22
|
-
},
|
|
23
|
-
environment: "node",
|
|
24
|
-
globals: true,
|
|
25
|
-
isolate: true,
|
|
26
|
-
pool: "forks",
|
|
27
|
-
maxWorkers: "50%",
|
|
28
|
-
clearMocks: true,
|
|
29
|
-
restoreMocks: true,
|
|
30
|
-
unstubEnvs: true,
|
|
31
|
-
unstubGlobals: true,
|
|
32
|
-
sequence: { shuffle: !isCI },
|
|
33
|
-
include: ["src/**/*.{test,spec}.?(c|m)[jt]s?(x)", "test/**/*.{test,spec}.?(c|m)[jt]s?(x)"],
|
|
34
|
-
exclude: ["test/e2e/**/*.{test,spec}.?(c|m)[jt]s?(x)", ...configDefaults.exclude],
|
|
35
|
-
reporters: isCI ? ["default", "junit"] : ["default"],
|
|
36
|
-
coverage: {
|
|
37
|
-
include: ["src/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}"],
|
|
38
|
-
exclude: [...configDefaults.coverage?.exclude ?? []],
|
|
39
|
-
reporter: isCI ? [
|
|
40
|
-
"json",
|
|
41
|
-
"json-summary",
|
|
42
|
-
"lcov"
|
|
43
|
-
] : [
|
|
44
|
-
"text",
|
|
45
|
-
"html",
|
|
46
|
-
"clover",
|
|
47
|
-
"json"
|
|
48
|
-
]
|
|
49
|
-
},
|
|
50
|
-
...omitUndefined({
|
|
51
|
-
setupFiles: setupFiles.length > 0 ? setupFiles : void 0,
|
|
52
|
-
outputFile: isCI ? { junit: "./test-results/junit.xml" } : void 0
|
|
53
|
-
})
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
//#endregion
|
|
57
|
-
export { base_default as default };
|
|
1
|
+
import{omitUndefined}from"@interfere/helpers/omit-undefined";import{existsSync}from"node:fs";import{resolve}from"node:path";import{config}from"dotenv";import{configDefaults}from"vitest/config";const root=process.cwd(),isCI=!!process.env.CI,env=config({path:resolve(root,`.env.test`),quiet:!0}).parsed??{},setupFiles=[`./test/setup.ts`,`./test/unit/setup.ts`].filter(rel=>existsSync(resolve(root,rel)));var base_default={root,resolve:{conditions:[`monorepo`]},ssr:{resolve:{conditions:[`monorepo`]}},test:{env:{...env,NODE_ENV:`test`},environment:`node`,globals:!0,isolate:!0,pool:`forks`,maxWorkers:`50%`,clearMocks:!0,restoreMocks:!0,ui:!!process.env.UI,unstubEnvs:!0,unstubGlobals:!0,sequence:{shuffle:!isCI},server:{deps:{inline:[`zod`]}},include:[`src/**/*.{test,spec}.?(c|m)[jt]s?(x)`,`test/**/*.{test,spec}.?(c|m)[jt]s?(x)`],exclude:[`test/e2e/**/*.{test,spec}.?(c|m)[jt]s?(x)`,...configDefaults.exclude],reporters:isCI?[`default`,`junit`]:[`default`],coverage:{enabled:!0,provider:`v8`,include:[`src/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}`],exclude:[`**/*.json`,...configDefaults.coverage?.exclude??[]],reporter:isCI?[`json`,`json-summary`,`lcov`]:[`text`,`html`,`clover`,`json`]},...omitUndefined({setupFiles:setupFiles.length>0?setupFiles:void 0,outputFile:isCI?{junit:`./test-results/junit.xml`}:void 0})}};export{base_default as default};
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
import base_default from
|
|
2
|
-
import { deepMerge } from "@interfere/helpers/deep-merge";
|
|
3
|
-
import { defineConfig as defineConfig$1 } from "vitest/config";
|
|
4
|
-
//#region src/vitest/define-config.ts
|
|
5
|
-
function defineConfig(...overrides) {
|
|
6
|
-
return defineConfig$1(deepMerge(base_default, ...overrides));
|
|
7
|
-
}
|
|
8
|
-
//#endregion
|
|
9
|
-
export { defineConfig };
|
|
1
|
+
import base_default from"./base.mjs";import{deepMerge}from"@interfere/helpers/deep-merge";import{defineConfig as defineConfig$1}from"vitest/config";function defineConfig(...overrides){return defineConfig$1(deepMerge(base_default,...overrides))}export{defineConfig};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import * as _$msw_browser0 from "msw/browser";
|
|
2
|
-
|
|
3
1
|
//#region src/vitest/msw-browser.d.ts
|
|
4
|
-
declare const worker:
|
|
2
|
+
declare const worker: import("msw/browser").SetupWorker;
|
|
5
3
|
declare function enableMSW(): void;
|
|
6
4
|
//#endregion
|
|
7
5
|
export { enableMSW, worker };
|
|
@@ -1,20 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { afterAll, afterEach, beforeAll } from "vitest";
|
|
3
|
-
//#region src/vitest/msw-browser.ts
|
|
4
|
-
const worker = setupWorker();
|
|
5
|
-
function enableMSW() {
|
|
6
|
-
beforeAll(async () => {
|
|
7
|
-
await worker.start({
|
|
8
|
-
onUnhandledRequest: "bypass",
|
|
9
|
-
quiet: true
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
afterEach(() => {
|
|
13
|
-
worker.resetHandlers();
|
|
14
|
-
});
|
|
15
|
-
afterAll(() => {
|
|
16
|
-
worker.stop();
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
//#endregion
|
|
20
|
-
export { enableMSW, worker };
|
|
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};
|
package/dist/vitest/msw-http.mjs
CHANGED
|
@@ -1,33 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { HttpResponse, http } from "msw";
|
|
3
|
-
//#region src/vitest/msw-http.ts
|
|
4
|
-
async function parseBody(request) {
|
|
5
|
-
const clone = request.clone();
|
|
6
|
-
if ((clone.headers.get("content-type") ?? "").includes("multipart/form-data")) {
|
|
7
|
-
const formData = await clone.formData();
|
|
8
|
-
return Object.fromEntries(formData.entries());
|
|
9
|
-
}
|
|
10
|
-
return clone.json().catch(() => null);
|
|
11
|
-
}
|
|
12
|
-
function createHttpInterceptor(baseUrl) {
|
|
13
|
-
function intercept(method, path, response, status = 200) {
|
|
14
|
-
const calls = [];
|
|
15
|
-
worker.use(http[method](`${baseUrl}${path}`, async ({ request, params }) => {
|
|
16
|
-
calls.push({
|
|
17
|
-
body: await parseBody(request),
|
|
18
|
-
params
|
|
19
|
-
});
|
|
20
|
-
return HttpResponse.json(response, { status });
|
|
21
|
-
}));
|
|
22
|
-
return calls;
|
|
23
|
-
}
|
|
24
|
-
function interceptNetworkError(method, path) {
|
|
25
|
-
worker.use(http[method](`${baseUrl}${path}`, () => HttpResponse.error()));
|
|
26
|
-
}
|
|
27
|
-
return {
|
|
28
|
-
intercept,
|
|
29
|
-
interceptNetworkError
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
//#endregion
|
|
33
|
-
export { createHttpInterceptor };
|
|
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};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/vitest/package-contract.d.ts
|
|
2
|
+
declare const PACKAGE_CONTRACT_TIMEOUT_MS = 30000;
|
|
3
|
+
interface PackageContractOptions {
|
|
4
|
+
packageJsonUrl: URL;
|
|
5
|
+
}
|
|
6
|
+
interface PackedPackageFilesOptions extends PackageContractOptions {
|
|
7
|
+
expectedFiles: string[];
|
|
8
|
+
}
|
|
9
|
+
interface NodePackageResolutionOptions extends PackageContractOptions {
|
|
10
|
+
specifiers: string[];
|
|
11
|
+
}
|
|
12
|
+
declare function expectPackedPackageFiles({
|
|
13
|
+
expectedFiles,
|
|
14
|
+
packageJsonUrl
|
|
15
|
+
}: PackedPackageFilesOptions): Promise<void>;
|
|
16
|
+
declare function expectNodeCanLoadPackageSpecifiers({
|
|
17
|
+
packageJsonUrl,
|
|
18
|
+
specifiers
|
|
19
|
+
}: NodePackageResolutionOptions): Promise<void>;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { PACKAGE_CONTRACT_TIMEOUT_MS, expectNodeCanLoadPackageSpecifiers, expectPackedPackageFiles };
|
|
@@ -0,0 +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(`
|
|
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
|
+
`)}function requireScript(specifiers){return specifiers.map(specifier=>`require(${JSON.stringify(specifier)});`).join(`
|
|
4
|
+
`)}export{PACKAGE_CONTRACT_TIMEOUT_MS,expectNodeCanLoadPackageSpecifiers,expectPackedPackageFiles};
|
|
@@ -1,60 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import base_default from "../base.mjs";
|
|
3
|
-
import { deepMerge } from "@interfere/helpers/deep-merge";
|
|
4
|
-
import { resolve } from "node:path";
|
|
5
|
-
import react from "@vitejs/plugin-react";
|
|
6
|
-
import { playwright } from "@vitest/browser-playwright";
|
|
7
|
-
//#region src/vitest/presets/browser.ts
|
|
8
|
-
const INSTANCE_BASELINE_EXCLUDE = ["test/e2e/**/*.{test,spec}.?(c|m)[jt]s?(x)"];
|
|
9
|
-
/**
|
|
10
|
-
* Glob matching all tests under a `mobile/` directory. Used by `dualViewport`
|
|
11
|
-
* to split the Desktop / Mobile test runs from a single file tree.
|
|
12
|
-
*/
|
|
13
|
-
const MOBILE_TESTS = "src/**/mobile/*.{test,spec}.?(c|m)[jt]s?(x)";
|
|
14
|
-
/**
|
|
15
|
-
* Standard Desktop + Mobile viewport split for UI apps. Desktop runs every
|
|
16
|
-
* test except those under `src/**/mobile/**`; Mobile runs only those.
|
|
17
|
-
*/
|
|
18
|
-
function dualViewport() {
|
|
19
|
-
return [{
|
|
20
|
-
browser: "chromium",
|
|
21
|
-
name: "Chrome - Desktop",
|
|
22
|
-
viewport: DESKTOP,
|
|
23
|
-
exclude: [...INSTANCE_BASELINE_EXCLUDE, MOBILE_TESTS]
|
|
24
|
-
}, {
|
|
25
|
-
browser: "chromium",
|
|
26
|
-
name: "Chrome - Mobile",
|
|
27
|
-
viewport: MOBILE,
|
|
28
|
-
exclude: INSTANCE_BASELINE_EXCLUDE,
|
|
29
|
-
include: [MOBILE_TESTS]
|
|
30
|
-
}];
|
|
31
|
-
}
|
|
32
|
-
function browserProject(opts) {
|
|
33
|
-
const { instances, trace, testAlias = "test/unit", ...rest } = opts;
|
|
34
|
-
return deepMerge({ server: {
|
|
35
|
-
port: 0,
|
|
36
|
-
strictPort: false
|
|
37
|
-
} }, base_default, {
|
|
38
|
-
test: {
|
|
39
|
-
name: "browser",
|
|
40
|
-
browser: {
|
|
41
|
-
enabled: true,
|
|
42
|
-
provider: playwright(),
|
|
43
|
-
screenshotFailures: false,
|
|
44
|
-
instances,
|
|
45
|
-
...trace && { trace: { mode: "retain-on-failure" } }
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
plugins: [...react()],
|
|
49
|
-
optimizeDeps: {
|
|
50
|
-
entries: ["src/**/*.{ts,tsx}", "test/unit/**/*.{ts,tsx}"],
|
|
51
|
-
exclude: ["fsevents"]
|
|
52
|
-
},
|
|
53
|
-
...testAlias !== false && { resolve: {
|
|
54
|
-
tsconfigPaths: true,
|
|
55
|
-
alias: { "@test": resolve(process.cwd(), testAlias) }
|
|
56
|
-
} }
|
|
57
|
-
}, rest);
|
|
58
|
-
}
|
|
59
|
-
//#endregion
|
|
60
|
-
export { MOBILE_TESTS, browserProject, dualViewport };
|
|
1
|
+
import{DESKTOP,MOBILE}from"../../lib/viewports.mjs";import base_default from"../base.mjs";import{deepMerge}from"@interfere/helpers/deep-merge";import{resolve}from"node:path";import react from"@vitejs/plugin-react";import{playwright}from"@vitest/browser-playwright";const INSTANCE_BASELINE_EXCLUDE=[`test/e2e/**/*.{test,spec}.?(c|m)[jt]s?(x)`],chromiumExecutablePath=process.env.CHROMIUM_EXECUTABLE_PATH,MOBILE_TESTS=`src/**/mobile/*.{test,spec}.?(c|m)[jt]s?(x)`;function dualViewport(){return[{browser:`chromium`,name:`Chrome - Desktop`,viewport:DESKTOP,exclude:[...INSTANCE_BASELINE_EXCLUDE,MOBILE_TESTS]},{browser:`chromium`,name:`Chrome - Mobile`,viewport:MOBILE,exclude:INSTANCE_BASELINE_EXCLUDE,include:[MOBILE_TESTS]}]}function browserProject(opts){let{instances,trace,testAlias=`test/unit`,...rest}=opts;return deepMerge(base_default,{server:{port:0,strictPort:!1},test:{name:`browser`,browser:{enabled:!0,provider:chromiumExecutablePath?playwright({launchOptions:{executablePath:chromiumExecutablePath}}):playwright(),screenshotFailures:!1,instances,...trace&&{trace:{mode:`retain-on-failure`}}}},plugins:[react()],optimizeDeps:{entries:[`src/**/*.{ts,tsx}`,`test/unit/**/*.{ts,tsx}`],exclude:[`fsevents`,`@opentelemetry/otlp-transformer`]},...testAlias!==!1&&{resolve:{tsconfigPaths:!0,alias:{"@test":resolve(process.cwd(),testAlias)}}}},rest)}export{MOBILE_TESTS,browserProject,dualViewport};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ViteUserConfig } from "vitest/config";
|
|
2
|
+
|
|
3
|
+
//#region src/vitest/presets/integration.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Integration test resources. Each entry maps to a globalSetup module in
|
|
6
|
+
* `@interfere/internal-test-utils` that owns a single shared container for
|
|
7
|
+
* the duration of the run and tears it down on success, failure, and most
|
|
8
|
+
* signal scenarios.
|
|
9
|
+
*
|
|
10
|
+
* The matching per-worker harness lives at
|
|
11
|
+
* `@interfere/internal-test-utils/lifecycle/<resource>/harness` — import it
|
|
12
|
+
* from your `test/setup.ts`.
|
|
13
|
+
*/
|
|
14
|
+
type IntegrationResource = "pg" | "redis";
|
|
15
|
+
interface IntegrationOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Container resources to provision once per run. Defaults to `["pg"]`.
|
|
18
|
+
*/
|
|
19
|
+
resources?: IntegrationResource[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build a Vitest config for an integration-test package. Wires up the
|
|
23
|
+
* shared-container globalSetup modules so each test run spins up exactly
|
|
24
|
+
* one of each requested resource (instead of one per worker fork) and tears
|
|
25
|
+
* them down reliably on exit.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* export default defineIntegrationConfig({ resources: ["pg", "redis"] }, {
|
|
30
|
+
* test: { coverage: { provider: "v8" } },
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare function defineIntegrationConfig(options?: IntegrationOptions, ...overrides: Array<Partial<ViteUserConfig> | undefined>): ViteUserConfig;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { IntegrationOptions, IntegrationResource, defineIntegrationConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import base_default from"../base.mjs";import{deepMerge}from"@interfere/helpers/deep-merge";import{defineConfig}from"vitest/config";const GLOBAL_SETUP_BY_RESOURCE={pg:`@interfere/internal-test-utils/lifecycle/pg/global-setup`,redis:`@interfere/internal-test-utils/lifecycle/redis/global-setup`};function defineIntegrationConfig(options={},...overrides){let resources=options.resources??[`pg`],globalSetup=resources.map(r=>GLOBAL_SETUP_BY_RESOURCE[r]),redisOverrides=resources.includes(`redis`)?{test:{fileParallelism:!1}}:{};return defineConfig(deepMerge(base_default,{test:{globalSetup}},redisOverrides,...overrides))}export{defineIntegrationConfig};
|
|
@@ -1,26 +1 @@
|
|
|
1
|
-
import base_default from
|
|
2
|
-
import { deepMerge } from "@interfere/helpers/deep-merge";
|
|
3
|
-
//#region src/vitest/presets/node.ts
|
|
4
|
-
/**
|
|
5
|
-
* Build a Vitest project config running against the Node environment.
|
|
6
|
-
* Spreads `opts` over a shared base; caller-provided fields win.
|
|
7
|
-
*
|
|
8
|
-
* `*.test.{tsx,jsx}` files are excluded by default — React test files can't
|
|
9
|
-
* import `vitest-browser-react` outside of Browser Mode, so they always
|
|
10
|
-
* belong in the `browserProject`. Opt a specific TSX test in by adding its
|
|
11
|
-
* path to the caller's `test.include`.
|
|
12
|
-
*/
|
|
13
|
-
function nodeProject(opts = {}) {
|
|
14
|
-
return deepMerge(base_default, { test: {
|
|
15
|
-
name: "node",
|
|
16
|
-
environment: "node",
|
|
17
|
-
exclude: [
|
|
18
|
-
"**/*.{test,spec}.tsx",
|
|
19
|
-
"**/*.{test,spec}.jsx",
|
|
20
|
-
"**/*.{test,spec}.mtsx",
|
|
21
|
-
"**/*.{test,spec}.mjsx"
|
|
22
|
-
]
|
|
23
|
-
} }, opts);
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
|
-
export { nodeProject };
|
|
1
|
+
import base_default from"../base.mjs";import{deepMerge}from"@interfere/helpers/deep-merge";function nodeProject(opts={}){return deepMerge(base_default,{test:{name:`node`,environment:`node`,exclude:[`**/*.{test,spec}.tsx`,`**/*.{test,spec}.jsx`,`**/*.{test,spec}.mtsx`,`**/*.{test,spec}.mjsx`]}},opts)}export{nodeProject};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TestUserConfig, UserWorkspaceConfig } from "vitest/config";
|
|
2
|
+
|
|
3
|
+
//#region src/vitest/presets/vite.d.ts
|
|
4
|
+
type BrowserConfig = NonNullable<TestUserConfig["browser"]>;
|
|
5
|
+
type BrowserInstance = NonNullable<BrowserConfig["instances"]>[number];
|
|
6
|
+
interface BrowserProjectOptions {
|
|
7
|
+
instances: BrowserInstance[];
|
|
8
|
+
testAlias?: string | false;
|
|
9
|
+
trace?: boolean;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
declare function dualViewport(): BrowserInstance[];
|
|
13
|
+
declare function viteProject(opts: BrowserProjectOptions): UserWorkspaceConfig;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { BrowserInstance, BrowserProjectOptions, dualViewport, viteProject };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DESKTOP,MOBILE}from"../../lib/viewports.mjs";import base_default from"../base.mjs";import{deepMerge}from"@interfere/helpers/deep-merge";import{playwright}from"@vitest/browser-playwright";const INSTANCE_BASELINE_EXCLUDE=[`test/e2e/**/*.{test,spec}.?(c|m)[jt]s?(x)`],chromiumExecutablePath=process.env.CHROMIUM_EXECUTABLE_PATH;function dualViewport(){return[{browser:`chromium`,name:`Chrome - Desktop`,viewport:DESKTOP,exclude:INSTANCE_BASELINE_EXCLUDE},{browser:`chromium`,name:`Chrome - Mobile`,viewport:MOBILE,exclude:INSTANCE_BASELINE_EXCLUDE}]}function viteProject(opts){let{instances,trace,testAlias=`test/unit`,...rest}=opts;return deepMerge({server:{port:0,strictPort:!1}},base_default,{test:{name:`vite`,browser:{enabled:!0,provider:chromiumExecutablePath?playwright({launchOptions:{executablePath:chromiumExecutablePath}}):playwright(),screenshotFailures:!1,instances,...trace&&{trace:{mode:`retain-on-failure`}}}}},rest)}export{dualViewport,viteProject};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interfere/test-utils",
|
|
3
|
-
"version": "9.0.0",
|
|
3
|
+
"version": "9.0.1-canary.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Shared test utilities used across Interfere packages.",
|
|
6
6
|
"homepage": "https://interfere.com",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "Interfere <support@interfere.com> (https://interfere.com)",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "git+https://
|
|
13
|
+
"url": "git+https://interfere.ghe.com/interfere/interfere.git",
|
|
14
14
|
"directory": "src/packages/public/test-utils"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
@@ -19,22 +19,22 @@
|
|
|
19
19
|
"type": "module",
|
|
20
20
|
"exports": {
|
|
21
21
|
"./lib/*": {
|
|
22
|
-
"
|
|
22
|
+
"monorepo": "./src/lib/*.ts",
|
|
23
23
|
"types": "./dist/lib/*.d.mts",
|
|
24
24
|
"default": "./dist/lib/*.mjs"
|
|
25
25
|
},
|
|
26
26
|
"./playwright/*": {
|
|
27
|
-
"
|
|
27
|
+
"monorepo": "./src/playwright/*.ts",
|
|
28
28
|
"types": "./dist/playwright/*.d.mts",
|
|
29
29
|
"default": "./dist/playwright/*.mjs"
|
|
30
30
|
},
|
|
31
31
|
"./vitest/*": {
|
|
32
|
-
"
|
|
32
|
+
"monorepo": "./src/vitest/*.ts",
|
|
33
33
|
"types": "./dist/vitest/*.d.mts",
|
|
34
34
|
"default": "./dist/vitest/*.mjs"
|
|
35
35
|
},
|
|
36
36
|
"./vitest/presets/*": {
|
|
37
|
-
"
|
|
37
|
+
"monorepo": "./src/vitest/presets/*.ts",
|
|
38
38
|
"types": "./dist/vitest/presets/*.d.mts",
|
|
39
39
|
"default": "./dist/vitest/presets/*.mjs"
|
|
40
40
|
},
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "tsdown",
|
|
48
|
-
"typecheck": "
|
|
48
|
+
"typecheck": "tsgo --noEmit"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
-
"@playwright/test": "
|
|
52
|
-
"@vitejs/plugin-react": "
|
|
53
|
-
"@vitest/browser-playwright": "
|
|
54
|
-
"msw": "
|
|
55
|
-
"vitest": "
|
|
51
|
+
"@playwright/test": "^1.61.1",
|
|
52
|
+
"@vitejs/plugin-react": "^6.0.3",
|
|
53
|
+
"@vitest/browser-playwright": "4.1.9",
|
|
54
|
+
"msw": "^2.14.6",
|
|
55
|
+
"vitest": "4.1.9"
|
|
56
56
|
},
|
|
57
57
|
"peerDependenciesMeta": {
|
|
58
58
|
"@playwright/test": {
|
|
@@ -74,13 +74,13 @@
|
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@interfere/typescript-config": "^9.0.0",
|
|
77
|
-
"@playwright/test": "^1.
|
|
78
|
-
"@types/node": "^
|
|
79
|
-
"@
|
|
80
|
-
"@
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"vitest": "
|
|
77
|
+
"@playwright/test": "^1.61.1",
|
|
78
|
+
"@types/node": "^26.0.0",
|
|
79
|
+
"@typescript/native-preview": "7.0.0-dev.20260623.1",
|
|
80
|
+
"@vitejs/plugin-react": "^6.0.3",
|
|
81
|
+
"@vitest/browser-playwright": "4.1.9",
|
|
82
|
+
"msw": "^2.14.6",
|
|
83
|
+
"tsdown": "^0.22.2",
|
|
84
|
+
"vitest": "4.1.9"
|
|
85
85
|
}
|
|
86
86
|
}
|
package/dist/lib/tags.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tags.d.mts","names":[],"sources":["../../src/lib/tags.ts"],"mappings":";cAAa,MAAA;AAAA,cACA,OAAA;AAAA,cACA,MAAA"}
|
package/dist/lib/tags.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tags.mjs","names":[],"sources":["../../src/lib/tags.ts"],"sourcesContent":["export const COMMON = \"@common\" as const;\nexport const DESKTOP = \"@desktop\" as const;\nexport const MOBILE = \"@mobile\" as const;\n"],"mappings":";AAAA,MAAa,SAAS;AACtB,MAAa,UAAU;AACvB,MAAa,SAAS"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"viewports.d.mts","names":[],"sources":["../../src/lib/viewports.ts"],"mappings":";;;KAEY,QAAA,GAAW,WAAA,CAAY,cAAA;AAAA,cAEtB,OAAA;EAAA,SAAkE,KAAA;EAAA,SAAA,MAAA;AAAA;AAAA,cAClE,MAAA;EAAA,SAAgE,KAAA;EAAA,SAAA,MAAA;AAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"viewports.mjs","names":[],"sources":["../../src/lib/viewports.ts"],"sourcesContent":["import type { TestUserConfig } from \"vitest/config\";\n\nexport type Viewport = NonNullable<TestUserConfig[\"browser\"]>[\"viewport\"];\n\nexport const DESKTOP = { width: 1280, height: 720 } as const satisfies Viewport;\nexport const MOBILE = { width: 390, height: 844 } as const satisfies Viewport;\n"],"mappings":";AAIA,MAAa,UAAU;CAAE,OAAO;CAAM,QAAQ;CAAK;AACnD,MAAa,SAAS;CAAE,OAAO;CAAK,QAAQ;CAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.mts","names":[],"sources":["../../src/playwright/base.ts"],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base.mjs","names":["MOBILE_TAG","MOBILE"],"sources":["../../src/playwright/base.ts"],"sourcesContent":["import { devices, type PlaywrightTestConfig } from \"@playwright/test\";\n\nimport { COMMON, DESKTOP, MOBILE as MOBILE_TAG } from \"../lib/tags.js\";\nimport { MOBILE } from \"../lib/viewports.js\";\n\nconst ci = !!process.env[\"CI\"];\n\nexport default {\n fullyParallel: true,\n forbidOnly: ci,\n reporter: ci\n ? [[\"github\"], [\"junit\", { outputFile: \"./test-results/e2e-junit.xml\" }]]\n : [[\"html\"]],\n\n use: {\n trace: \"on-first-retry\",\n screenshot: \"only-on-failure\",\n ...(ci && {\n actionTimeout: 10_000,\n }),\n },\n\n ...(ci && {\n expect: { timeout: 10_000 },\n }),\n\n projects: [\n {\n name: \"desktop\",\n grep: new RegExp(`${DESKTOP}|${COMMON}`),\n use: { ...devices[\"Desktop Chrome\"] },\n },\n {\n name: \"mobile\",\n grep: new RegExp(`${MOBILE_TAG}|${COMMON}`),\n use: {\n ...devices[\"Desktop Chrome\"],\n viewport: MOBILE,\n isMobile: true,\n hasTouch: true,\n },\n },\n ],\n} satisfies PlaywrightTestConfig;\n"],"mappings":";;;;AAKA,MAAM,KAAK,CAAC,CAAC,QAAQ,IAAI;AAEzB,IAAA,eAAe;CACb,eAAe;CACf,YAAY;CACZ,UAAU,KACN,CAAC,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,YAAY,gCAAgC,CAAC,CAAC,GACvE,CAAC,CAAC,OAAO,CAAC;CAEd,KAAK;EACH,OAAO;EACP,YAAY;EACZ,GAAI,MAAM,EACR,eAAe,KAChB;EACF;CAED,GAAI,MAAM,EACR,QAAQ,EAAE,SAAS,KAAQ,EAC5B;CAED,UAAU,CACR;EACE,MAAM;EACN,MAAM,IAAI,OAAO,GAAG,QAAQ,GAAG,SAAS;EACxC,KAAK,EAAE,GAAG,QAAQ,mBAAmB;EACtC,EACD;EACE,MAAM;EACN,MAAM,IAAI,OAAO,GAAGA,OAAW,GAAG,SAAS;EAC3C,KAAK;GACH,GAAG,QAAQ;GACX,UAAUC;GACV,UAAU;GACV,UAAU;GACX;EACF,CACF;CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"define-config.d.mts","names":[],"sources":["../../src/playwright/define-config.ts"],"mappings":";;;iBASgB,YAAA,CAAA,GACX,SAAA,EAAW,KAAA,CAAM,OAAA,CAAQ,oBAAA,iBAAkC,oBAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"define-config.mjs","names":["pwDefineConfig","base"],"sources":["../../src/playwright/define-config.ts"],"sourcesContent":["import { deepMerge } from \"@interfere/helpers/deep-merge\";\n\nimport {\n type PlaywrightTestConfig,\n defineConfig as pwDefineConfig,\n} from \"@playwright/test\";\n\nimport base from \"./base.js\";\n\nexport function defineConfig(\n ...overrides: Array<Partial<PlaywrightTestConfig> | undefined>\n) {\n return pwDefineConfig(deepMerge<PlaywrightTestConfig>(base, ...overrides));\n}\n"],"mappings":";;;;AASA,SAAgB,aACd,GAAG,WACH;AACA,QAAOA,eAAe,UAAgCC,cAAM,GAAG,UAAU,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.mts","names":[],"sources":["../../src/vitest/base.ts"],"mappings":""}
|
package/dist/vitest/base.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base.mjs","names":[],"sources":["../../src/vitest/base.ts"],"sourcesContent":["import { omitUndefined } from \"@interfere/helpers/omit-undefined\";\n\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { config } from \"dotenv\";\nimport { configDefaults, type ViteUserConfig } from \"vitest/config\";\n\nconst root = process.cwd();\nconst isCI = Boolean(process.env[\"CI\"]);\n\nconst env =\n config({ path: resolve(root, \".env.test\"), quiet: true }).parsed ?? {};\n\nconst setupFiles = [\"./test/setup.ts\", \"./test/unit/setup.ts\"].filter((rel) =>\n existsSync(resolve(root, rel))\n);\n\nexport default {\n root,\n resolve: { conditions: [\"@source\"] },\n ssr: { resolve: { conditions: [\"@source\"] } },\n test: {\n env: { ...env, NODE_ENV: \"test\" },\n environment: \"node\",\n globals: true,\n isolate: true,\n pool: \"forks\",\n maxWorkers: \"50%\",\n clearMocks: true,\n restoreMocks: true,\n unstubEnvs: true,\n unstubGlobals: true,\n sequence: { shuffle: !isCI },\n include: [\n \"src/**/*.{test,spec}.?(c|m)[jt]s?(x)\",\n \"test/**/*.{test,spec}.?(c|m)[jt]s?(x)\",\n ],\n exclude: [\n \"test/e2e/**/*.{test,spec}.?(c|m)[jt]s?(x)\",\n ...configDefaults.exclude,\n ],\n reporters: isCI ? [\"default\", \"junit\"] : [\"default\"],\n coverage: {\n include: [\"src/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}\"],\n exclude: [...(configDefaults.coverage?.exclude ?? [])],\n reporter: isCI\n ? [\"json\", \"json-summary\", \"lcov\"]\n : [\"text\", \"html\", \"clover\", \"json\"],\n },\n ...omitUndefined({\n setupFiles: setupFiles.length > 0 ? setupFiles : undefined,\n outputFile: isCI ? { junit: \"./test-results/junit.xml\" } : undefined,\n }),\n },\n} satisfies ViteUserConfig;\n"],"mappings":";;;;;;AAOA,MAAM,OAAO,QAAQ,KAAK;AAC1B,MAAM,OAAO,QAAQ,QAAQ,IAAI,MAAM;AAEvC,MAAM,MACJ,OAAO;CAAE,MAAM,QAAQ,MAAM,YAAY;CAAE,OAAO;CAAM,CAAC,CAAC,UAAU,EAAE;AAExE,MAAM,aAAa,CAAC,mBAAmB,uBAAuB,CAAC,QAAQ,QACrE,WAAW,QAAQ,MAAM,IAAI,CAAC,CAC/B;AAED,IAAA,eAAe;CACb;CACA,SAAS,EAAE,YAAY,CAAC,UAAU,EAAE;CACpC,KAAK,EAAE,SAAS,EAAE,YAAY,CAAC,UAAU,EAAE,EAAE;CAC7C,MAAM;EACJ,KAAK;GAAE,GAAG;GAAK,UAAU;GAAQ;EACjC,aAAa;EACb,SAAS;EACT,SAAS;EACT,MAAM;EACN,YAAY;EACZ,YAAY;EACZ,cAAc;EACd,YAAY;EACZ,eAAe;EACf,UAAU,EAAE,SAAS,CAAC,MAAM;EAC5B,SAAS,CACP,wCACA,wCACD;EACD,SAAS,CACP,6CACA,GAAG,eAAe,QACnB;EACD,WAAW,OAAO,CAAC,WAAW,QAAQ,GAAG,CAAC,UAAU;EACpD,UAAU;GACR,SAAS,CAAC,2CAA2C;GACrD,SAAS,CAAC,GAAI,eAAe,UAAU,WAAW,EAAE,CAAE;GACtD,UAAU,OACN;IAAC;IAAQ;IAAgB;IAAO,GAChC;IAAC;IAAQ;IAAQ;IAAU;IAAO;GACvC;EACD,GAAG,cAAc;GACf,YAAY,WAAW,SAAS,IAAI,aAAa,KAAA;GACjD,YAAY,OAAO,EAAE,OAAO,4BAA4B,GAAG,KAAA;GAC5D,CAAC;EACH;CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"define-config.d.mts","names":[],"sources":["../../src/vitest/define-config.ts"],"mappings":";;;iBASgB,YAAA,CAAA,GACX,SAAA,EAAW,KAAA,CAAM,OAAA,CAAQ,cAAA,iBAA4B,cAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"define-config.mjs","names":["vitestDefineConfig","base"],"sources":["../../src/vitest/define-config.ts"],"sourcesContent":["import { deepMerge } from \"@interfere/helpers/deep-merge\";\n\nimport {\n type ViteUserConfig,\n defineConfig as vitestDefineConfig,\n} from \"vitest/config\";\n\nimport base from \"./base.js\";\n\nexport function defineConfig(\n ...overrides: Array<Partial<ViteUserConfig> | undefined>\n) {\n return vitestDefineConfig(deepMerge<ViteUserConfig>(base, ...overrides));\n}\n"],"mappings":";;;;AASA,SAAgB,aACd,GAAG,WACH;AACA,QAAOA,eAAmB,UAA0BC,cAAM,GAAG,UAAU,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"msw-browser.d.mts","names":[],"sources":["../../src/vitest/msw-browser.ts"],"mappings":";;;cAGa,MAAA,EAAsB,cAAA,CAAhB,WAAA;AAAA,iBAEH,SAAA,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"msw-browser.mjs","names":[],"sources":["../../src/vitest/msw-browser.ts"],"sourcesContent":["import { setupWorker } from \"msw/browser\";\nimport { afterAll, afterEach, beforeAll } from \"vitest\";\n\nexport const worker = setupWorker();\n\nexport function enableMSW(): void {\n beforeAll(async () => {\n await worker.start({ onUnhandledRequest: \"bypass\", quiet: true });\n });\n\n afterEach(() => {\n worker.resetHandlers();\n });\n\n afterAll(() => {\n worker.stop();\n });\n}\n"],"mappings":";;;AAGA,MAAa,SAAS,aAAa;AAEnC,SAAgB,YAAkB;AAChC,WAAU,YAAY;AACpB,QAAM,OAAO,MAAM;GAAE,oBAAoB;GAAU,OAAO;GAAM,CAAC;GACjE;AAEF,iBAAgB;AACd,SAAO,eAAe;GACtB;AAEF,gBAAe;AACb,SAAO,MAAM;GACb"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"msw-http.d.mts","names":[],"sources":["../../src/vitest/msw-http.ts"],"mappings":";KAIY,UAAA;AAAA,KACA,SAAA,sCAKR,SAAA;EAAA,CACG,GAAA,WAAc,SAAA;AAAA;AAAA,UAEJ,gBAAA;EACf,IAAA;EACA,MAAA,EAAQ,MAAA;AAAA;AAAA,iBAaM,qBAAA,CAAsB,OAAA;sBAE1B,UAAA,EAAU,IAAA,UACN,QAAA,EACF,SAAA,EAAS,MAAA,cAElB,gBAAA;kCAiBoC,UAAA,EAAU,IAAA;AAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"msw-http.mjs","names":[],"sources":["../../src/vitest/msw-http.ts"],"sourcesContent":["import { HttpResponse, http } from \"msw\";\n\nimport { worker } from \"./msw-browser.js\";\n\nexport type HttpMethod = \"post\" | \"get\" | \"put\" | \"delete\" | \"patch\";\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\nexport interface CapturedHttpCall {\n body: unknown;\n params: Record<string, string | readonly string[] | undefined>;\n}\n\nasync function parseBody(request: Request): Promise<unknown> {\n const clone = request.clone();\n const contentType = clone.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"multipart/form-data\")) {\n const formData = await clone.formData();\n return Object.fromEntries(formData.entries());\n }\n return clone.json().catch(() => null);\n}\n\nexport function createHttpInterceptor(baseUrl: string) {\n function intercept(\n method: HttpMethod,\n path: string,\n response: JsonValue,\n status = 200\n ): CapturedHttpCall[] {\n const calls: CapturedHttpCall[] = [];\n\n worker.use(\n http[method](`${baseUrl}${path}`, async ({ request, params }) => {\n calls.push({\n body: await parseBody(request),\n params,\n });\n\n return HttpResponse.json(response, { status });\n })\n );\n\n return calls;\n }\n\n function interceptNetworkError(method: HttpMethod, path: string): void {\n worker.use(http[method](`${baseUrl}${path}`, () => HttpResponse.error()));\n }\n\n return {\n intercept,\n interceptNetworkError,\n };\n}\n"],"mappings":";;;AAkBA,eAAe,UAAU,SAAoC;CAC3D,MAAM,QAAQ,QAAQ,OAAO;AAE7B,MADoB,MAAM,QAAQ,IAAI,eAAe,IAAI,IACzC,SAAS,sBAAsB,EAAE;EAC/C,MAAM,WAAW,MAAM,MAAM,UAAU;AACvC,SAAO,OAAO,YAAY,SAAS,SAAS,CAAC;;AAE/C,QAAO,MAAM,MAAM,CAAC,YAAY,KAAK;;AAGvC,SAAgB,sBAAsB,SAAiB;CACrD,SAAS,UACP,QACA,MACA,UACA,SAAS,KACW;EACpB,MAAM,QAA4B,EAAE;AAEpC,SAAO,IACL,KAAK,QAAQ,GAAG,UAAU,QAAQ,OAAO,EAAE,SAAS,aAAa;AAC/D,SAAM,KAAK;IACT,MAAM,MAAM,UAAU,QAAQ;IAC9B;IACD,CAAC;AAEF,UAAO,aAAa,KAAK,UAAU,EAAE,QAAQ,CAAC;IAC9C,CACH;AAED,SAAO;;CAGT,SAAS,sBAAsB,QAAoB,MAAoB;AACrE,SAAO,IAAI,KAAK,QAAQ,GAAG,UAAU,cAAc,aAAa,OAAO,CAAC,CAAC;;AAG3E,QAAO;EACL;EACA;EACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.mts","names":[],"sources":["../../../src/vitest/presets/browser.ts"],"mappings":";;;KAUK,aAAA,GAAgB,WAAA,CAAY,cAAA;AAAA,KACrB,eAAA,GAAkB,WAAA,CAAY,aAAA;AAAA,UAIzB,qBAAA;EALC;;;;AAClB;EAUE,SAAA,EAAW,eAAA;EACX,SAAA;EACA,KAAA;EAAA,CACC,GAAA;AAAA;;;;;cAOU,YAAA;;;;;iBAMG,YAAA,CAAA,GAAgB,eAAA;AAAA,iBAkBhB,cAAA,CACd,IAAA,EAAM,qBAAA,GACL,mBAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"browser.mjs","names":["base"],"sources":["../../../src/vitest/presets/browser.ts"],"sourcesContent":["import { deepMerge } from \"@interfere/helpers/deep-merge\";\n\nimport { resolve } from \"node:path\";\nimport react from \"@vitejs/plugin-react\";\nimport { playwright } from \"@vitest/browser-playwright\";\nimport type { TestUserConfig, UserWorkspaceConfig } from \"vitest/config\";\n\nimport { DESKTOP, MOBILE } from \"../../lib/viewports.js\";\nimport base from \"../base.js\";\n\ntype BrowserConfig = NonNullable<TestUserConfig[\"browser\"]>;\nexport type BrowserInstance = NonNullable<BrowserConfig[\"instances\"]>[number];\n\nconst INSTANCE_BASELINE_EXCLUDE = [\"test/e2e/**/*.{test,spec}.?(c|m)[jt]s?(x)\"];\n\nexport interface BrowserProjectOptions {\n /**\n * Playwright browser instances to run against. Use `dualViewport()` for the\n * standard Desktop + Mobile split keyed on the `src/**/mobile/**` glob\n * convention.\n */\n instances: BrowserInstance[];\n testAlias?: string | false;\n trace?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Glob matching all tests under a `mobile/` directory. Used by `dualViewport`\n * to split the Desktop / Mobile test runs from a single file tree.\n */\nexport const MOBILE_TESTS = \"src/**/mobile/*.{test,spec}.?(c|m)[jt]s?(x)\";\n\n/**\n * Standard Desktop + Mobile viewport split for UI apps. Desktop runs every\n * test except those under `src/**/mobile/**`; Mobile runs only those.\n */\nexport function dualViewport(): BrowserInstance[] {\n return [\n {\n browser: \"chromium\",\n name: \"Chrome - Desktop\",\n viewport: DESKTOP,\n exclude: [...INSTANCE_BASELINE_EXCLUDE, MOBILE_TESTS],\n },\n {\n browser: \"chromium\",\n name: \"Chrome - Mobile\",\n viewport: MOBILE,\n exclude: INSTANCE_BASELINE_EXCLUDE,\n include: [MOBILE_TESTS],\n },\n ];\n}\n\nexport function browserProject(\n opts: BrowserProjectOptions\n): UserWorkspaceConfig {\n const { instances, trace, testAlias = \"test/unit\", ...rest } = opts;\n\n return deepMerge<UserWorkspaceConfig>(\n { server: { port: 0, strictPort: false } },\n base,\n {\n test: {\n name: \"browser\",\n browser: {\n enabled: true,\n provider: playwright(),\n screenshotFailures: false,\n instances,\n ...(trace && { trace: { mode: \"retain-on-failure\" as const } }),\n },\n },\n plugins: [...react()],\n optimizeDeps: {\n entries: [\"src/**/*.{ts,tsx}\", \"test/unit/**/*.{ts,tsx}\"],\n exclude: [\"fsevents\"],\n },\n ...(testAlias !== false && {\n resolve: {\n tsconfigPaths: true,\n alias: {\n \"@test\": resolve(process.cwd(), testAlias),\n },\n },\n }),\n },\n rest\n );\n}\n"],"mappings":";;;;;;;AAaA,MAAM,4BAA4B,CAAC,4CAA4C;;;;;AAkB/E,MAAa,eAAe;;;;;AAM5B,SAAgB,eAAkC;AAChD,QAAO,CACL;EACE,SAAS;EACT,MAAM;EACN,UAAU;EACV,SAAS,CAAC,GAAG,2BAA2B,aAAa;EACtD,EACD;EACE,SAAS;EACT,MAAM;EACN,UAAU;EACV,SAAS;EACT,SAAS,CAAC,aAAa;EACxB,CACF;;AAGH,SAAgB,eACd,MACqB;CACrB,MAAM,EAAE,WAAW,OAAO,YAAY,aAAa,GAAG,SAAS;AAE/D,QAAO,UACL,EAAE,QAAQ;EAAE,MAAM;EAAG,YAAY;EAAO,EAAE,EAC1CA,cACA;EACE,MAAM;GACJ,MAAM;GACN,SAAS;IACP,SAAS;IACT,UAAU,YAAY;IACtB,oBAAoB;IACpB;IACA,GAAI,SAAS,EAAE,OAAO,EAAE,MAAM,qBAA8B,EAAE;IAC/D;GACF;EACD,SAAS,CAAC,GAAG,OAAO,CAAC;EACrB,cAAc;GACZ,SAAS,CAAC,qBAAqB,0BAA0B;GACzD,SAAS,CAAC,WAAW;GACtB;EACD,GAAI,cAAc,SAAS,EACzB,SAAS;GACP,eAAe;GACf,OAAO,EACL,SAAS,QAAQ,QAAQ,KAAK,EAAE,UAAU,EAC3C;GACF,EACF;EACF,EACD,KACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.mts","names":[],"sources":["../../../src/vitest/presets/node.ts"],"mappings":";;;;;AAeA;;;;;;;iBAAgB,WAAA,CACd,IAAA,GAAM,OAAA,CAAQ,mBAAA,IACb,mBAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node.mjs","names":["base"],"sources":["../../../src/vitest/presets/node.ts"],"sourcesContent":["import { deepMerge } from \"@interfere/helpers/deep-merge\";\n\nimport type { UserWorkspaceConfig } from \"vitest/config\";\n\nimport base from \"../base.js\";\n\n/**\n * Build a Vitest project config running against the Node environment.\n * Spreads `opts` over a shared base; caller-provided fields win.\n *\n * `*.test.{tsx,jsx}` files are excluded by default — React test files can't\n * import `vitest-browser-react` outside of Browser Mode, so they always\n * belong in the `browserProject`. Opt a specific TSX test in by adding its\n * path to the caller's `test.include`.\n */\nexport function nodeProject(\n opts: Partial<UserWorkspaceConfig> = {}\n): UserWorkspaceConfig {\n return deepMerge<UserWorkspaceConfig>(\n base,\n {\n test: {\n name: \"node\",\n environment: \"node\",\n exclude: [\n \"**/*.{test,spec}.tsx\",\n \"**/*.{test,spec}.jsx\",\n \"**/*.{test,spec}.mtsx\",\n \"**/*.{test,spec}.mjsx\",\n ],\n },\n },\n opts\n );\n}\n"],"mappings":";;;;;;;;;;;;AAeA,SAAgB,YACd,OAAqC,EAAE,EAClB;AACrB,QAAO,UACLA,cACA,EACE,MAAM;EACJ,MAAM;EACN,aAAa;EACb,SAAS;GACP;GACA;GACA;GACA;GACD;EACF,EACF,EACD,KACD"}
|