@entifix/testing-e2e 0.3.0 → 0.4.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.
- package/dist/playwright/{test.d.ts → fixture.d.ts} +1 -1
- package/dist/playwright/fixture.d.ts.map +1 -0
- package/dist/playwright/{test.js → fixture.js} +9 -4
- package/dist/playwright/fixture.js.map +1 -0
- package/dist/playwright/index.d.ts +1 -1
- package/dist/playwright/index.d.ts.map +1 -1
- package/dist/playwright/index.js +1 -1
- package/dist/playwright/index.js.map +1 -1
- package/dist/service/define-service-e2e.js.map +1 -1
- package/package.json +14 -13
- package/dist/playwright/test.d.ts.map +0 -1
- package/dist/playwright/test.js.map +0 -1
|
@@ -48,4 +48,4 @@ export declare const baseTest: import("@playwright/test").TestType<import("@play
|
|
|
48
48
|
export declare const defineEntifixE2eTest: ({ handlers, passthroughOrigins, }?: EntifixE2eTestOptions) => import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & Pick<EntifixE2eFixtures, "expectedServer"> & EntifixE2eFixtures, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
|
|
49
49
|
export type { NetworkFixture } from '@msw/playwright';
|
|
50
50
|
export { expect } from '@playwright/test';
|
|
51
|
-
//# sourceMappingURL=
|
|
51
|
+
//# sourceMappingURL=fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../../src/playwright/fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAKtC,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,qEAAqE;IACrE,OAAO,EAAE,cAAc,CAAC;IACxB,kEAAkE;IAClE,cAAc,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAeD;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,0RAUpB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAAI,oCAGlC,qBAA0B,kTAwCzB,CAAC;AAEL,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -58,11 +58,16 @@ import { assertExpectedServerOnce } from './assert-expected-server.js';
|
|
|
58
58
|
// escape to the network: a spec that passes because it silently
|
|
59
59
|
// talked to nothing is worse than one that fails. The app's own
|
|
60
60
|
// origin is exempt — it legitimately serves itself.
|
|
61
|
-
onUnhandledRequest
|
|
62
|
-
|
|
61
|
+
// `onUnhandledFrame` since msw 3; the old `onUnhandledRequest` is
|
|
62
|
+
// ignored rather than rejected. A frame is HTTP or WebSocket, and only
|
|
63
|
+
// an HTTP frame carries a request — read structurally, because
|
|
64
|
+
// `instanceof` against msw's class fails across two installed copies.
|
|
65
|
+
onUnhandledFrame: ({ frame, defaults })=>{
|
|
66
|
+
const request = frame.data.request;
|
|
67
|
+
if (request !== undefined && passthroughOrigins.some((origin)=>request.url.startsWith(origin))) {
|
|
63
68
|
return;
|
|
64
69
|
}
|
|
65
|
-
|
|
70
|
+
defaults.error();
|
|
66
71
|
}
|
|
67
72
|
});
|
|
68
73
|
await network.enable();
|
|
@@ -76,4 +81,4 @@ import { assertExpectedServerOnce } from './assert-expected-server.js';
|
|
|
76
81
|
});
|
|
77
82
|
export { expect } from '@playwright/test';
|
|
78
83
|
|
|
79
|
-
//# sourceMappingURL=
|
|
84
|
+
//# sourceMappingURL=fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/playwright/fixture.ts"],"sourcesContent":["import { defineNetworkFixture, type NetworkFixture } from '@msw/playwright';\nimport { test as base } from '@playwright/test';\nimport type { AnyHandler } from 'msw';\n\nimport { isMockProfile } from '../profile/profile.js';\nimport { assertExpectedServerOnce } from './assert-expected-server.js';\n\nexport interface EntifixE2eFixtures {\n /** The handlers the mock profile starts from. Overridable per project. */\n handlers: AnyHandler[];\n /** The msw network, for per-test overrides in a `*.mock.spec.ts`. */\n network: NetworkFixture;\n /** Refuses a hermetic run against a reused development server. */\n expectedServer: void;\n}\n\nexport interface EntifixE2eTestOptions {\n /**\n * The mock backend. Ignored in the `live` profile, where the app talks to a\n * real service.\n */\n handlers?: AnyHandler[];\n /**\n * Origins whose unstubbed requests are allowed through — in practice the app\n * under test itself, which serves its own documents, RSC payloads and\n * dev-tooling endpoints.\n *\n * Everything else must be stubbed: a request to a *service* that nobody\n * handled fails the test rather than escaping to a machine that may not even\n * be running.\n */\n passthroughOrigins?: string[];\n}\n\n/**\n * In `live`, the network is untouched — so reaching for it is a mistake worth\n * reporting rather than a silent no-op that makes a spec assert nothing.\n */\nconst liveNetwork = (): NetworkFixture =>\n new Proxy({} as NetworkFixture, {\n get(_target, property) {\n throw new Error(\n `The network fixture is not available in the live profile (tried to use \"${String(property)}\"). Move this expectation into a *.mock.spec.ts file.`,\n );\n },\n });\n\n/**\n * Playwright's own `test`, plus the reused-server guard and nothing else.\n *\n * For a spec that wants no msw network and no seeded session — proving the\n * unauthenticated redirect, say. It exists so that \"this spec needs no\n * fixtures\" cannot quietly mean \"this spec is not checked against the artifact\n * it is running on\": importing `test` straight from `@playwright/test` is what\n * left the account journeys resolving a principal against a live auth-service\n * while claiming to be hermetic.\n */\nexport const baseTest = base.extend<Pick<EntifixE2eFixtures, 'expectedServer'>>(\n {\n expectedServer: [\n async ({ baseURL }, use) => {\n await assertExpectedServerOnce(baseURL);\n await use();\n },\n { auto: true },\n ],\n },\n);\n\n/**\n * Builds the `test` an entifix app e2e project imports.\n *\n * In `mock` it installs the msw handlers over Playwright's `page.route()`\n * (via `@msw/playwright`), so the browser talks to the fixture backend and the\n * app itself is untouched — no worker script, no `NEXT_PUBLIC_*` switch, no\n * mocking code shipped in the application bundle. In `live` the fixture stands\n * down and the same specs hit the real service.\n */\nexport const defineEntifixE2eTest = ({\n handlers = [],\n passthroughOrigins = [],\n}: EntifixE2eTestOptions = {}) =>\n baseTest.extend<EntifixE2eFixtures>({\n handlers: [handlers, { option: true }],\n\n network: [\n async ({ context, handlers: activeHandlers }, use) => {\n if (!isMockProfile()) {\n await use(liveNetwork());\n return;\n }\n\n const network = defineNetworkFixture({\n context,\n handlers: activeHandlers,\n // An unstubbed *service* request must fail the test rather than\n // escape to the network: a spec that passes because it silently\n // talked to nothing is worse than one that fails. The app's own\n // origin is exempt — it legitimately serves itself.\n // `onUnhandledFrame` since msw 3; the old `onUnhandledRequest` is\n // ignored rather than rejected. A frame is HTTP or WebSocket, and only\n // an HTTP frame carries a request — read structurally, because\n // `instanceof` against msw's class fails across two installed copies.\n onUnhandledFrame: ({ frame, defaults }) => {\n const request = (frame.data as { request?: Request }).request;\n if (\n request !== undefined &&\n passthroughOrigins.some(origin => request.url.startsWith(origin))\n ) {\n return;\n }\n defaults.error();\n },\n });\n\n await network.enable();\n await use(network);\n await network.disable();\n },\n { auto: true },\n ],\n });\n\nexport type { NetworkFixture } from '@msw/playwright';\nexport { expect } from '@playwright/test';\n"],"names":["defineNetworkFixture","test","base","isMockProfile","assertExpectedServerOnce","liveNetwork","Proxy","get","_target","property","Error","String","baseTest","extend","expectedServer","baseURL","use","auto","defineEntifixE2eTest","handlers","passthroughOrigins","option","network","context","activeHandlers","onUnhandledFrame","frame","defaults","request","data","undefined","some","origin","url","startsWith","error","enable","disable","expect"],"mappings":"AAAA,SAASA,oBAAoB,QAA6B,kBAAkB;AAC5E,SAASC,QAAQC,IAAI,QAAQ,mBAAmB;AAGhD,SAASC,aAAa,QAAQ,wBAAwB;AACtD,SAASC,wBAAwB,QAAQ,8BAA8B;AA6BvE;;;CAGC,GACD,MAAMC,cAAc,IAClB,IAAIC,MAAM,CAAC,GAAqB;QAC9BC,KAAIC,OAAO,EAAEC,QAAQ;YACnB,MAAM,IAAIC,MACR,CAAC,wEAAwE,EAAEC,OAAOF,UAAU,qDAAqD,CAAC;QAEtJ;IACF;AAEF;;;;;;;;;CASC,GACD,OAAO,MAAMG,WAAWV,KAAKW,MAAM,CACjC;IACEC,gBAAgB;QACd,OAAO,EAAEC,OAAO,EAAE,EAAEC;YAClB,MAAMZ,yBAAyBW;YAC/B,MAAMC;QACR;QACA;YAAEC,MAAM;QAAK;KACd;AACH,GACA;AAEF;;;;;;;;CAQC,GACD,OAAO,MAAMC,uBAAuB,CAAC,EACnCC,WAAW,EAAE,EACbC,qBAAqB,EAAE,EACD,GAAG,CAAC,CAAC,GAC3BR,SAASC,MAAM,CAAqB;QAClCM,UAAU;YAACA;YAAU;gBAAEE,QAAQ;YAAK;SAAE;QAEtCC,SAAS;YACP,OAAO,EAAEC,OAAO,EAAEJ,UAAUK,cAAc,EAAE,EAAER;gBAC5C,IAAI,CAACb,iBAAiB;oBACpB,MAAMa,IAAIX;oBACV;gBACF;gBAEA,MAAMiB,UAAUtB,qBAAqB;oBACnCuB;oBACAJ,UAAUK;oBACV,gEAAgE;oBAChE,gEAAgE;oBAChE,gEAAgE;oBAChE,oDAAoD;oBACpD,kEAAkE;oBAClE,uEAAuE;oBACvE,+DAA+D;oBAC/D,sEAAsE;oBACtEC,kBAAkB,CAAC,EAAEC,KAAK,EAAEC,QAAQ,EAAE;wBACpC,MAAMC,UAAU,AAACF,MAAMG,IAAI,CAA2BD,OAAO;wBAC7D,IACEA,YAAYE,aACZV,mBAAmBW,IAAI,CAACC,CAAAA,SAAUJ,QAAQK,GAAG,CAACC,UAAU,CAACF,UACzD;4BACA;wBACF;wBACAL,SAASQ,KAAK;oBAChB;gBACF;gBAEA,MAAMb,QAAQc,MAAM;gBACpB,MAAMpB,IAAIM;gBACV,MAAMA,QAAQe,OAAO;YACvB;YACA;gBAAEpB,MAAM;YAAK;SACd;IACH,GAAG;AAGL,SAASqB,MAAM,QAAQ,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/playwright/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/playwright/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
|
package/dist/playwright/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/playwright/index.ts"],"sourcesContent":["export * from './assert-expected-server.js';\nexport * from './config.js';\nexport * from './entity-table.js';\nexport * from './
|
|
1
|
+
{"version":3,"sources":["../../src/playwright/index.ts"],"sourcesContent":["export * from './assert-expected-server.js';\nexport * from './config.js';\nexport * from './entity-table.js';\nexport * from './fixture.js';\nexport * from './session.js';\n"],"names":[],"mappings":"AAAA,cAAc,8BAA8B;AAC5C,cAAc,cAAc;AAC5B,cAAc,oBAAoB;AAClC,cAAc,eAAe;AAC7B,cAAc,eAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/service/define-service-e2e.ts"],"sourcesContent":["import axios, { type AxiosInstance } from 'axios';\nimport { afterAll, beforeAll } from 'vitest';\n\nimport {\n type E2eProfile,\n requireLiveUrl,\n resolveE2eProfile,\n} from '../profile/profile.js';\n\n/** A service booted for the run, whichever profile started it. */\nexport interface RunningService {\n readonly baseUrl: string;\n close(): Promise<void>;\n}\n\nexport interface ServiceE2eOptions {\n /**\n * The variable a `live` run reads its target from, e.g.\n * `MARKETPLACE_ADMIN_SERVICE_URL`.\n */\n liveUrlEnvVar: string;\n /**\n * Boots the service in-process for a `mock` run. Supplied by the e2e project\n * rather than by this package, because only the project knows its own\n * `router` and which fakes stand in for its infrastructure — and because a\n * package under `entifix` must not depend on a `shells` one.\n */\n startMock: () => Promise<RunningService>;\n /**\n * Default `Authorization` header for every request the suite makes, built\n * once at start-up.\n *\n * A guarded service answers `401` to an anonymous request, which would turn\n * every journey in the suite into an authentication test. Supplying a\n * principal here keeps the specs about what they are actually asserting;\n * the guard itself is covered by its own spec, which omits or corrupts the\n * header on purpose.\n */\n authorization?: () => Promise<string>;\n}\n\n/**\n * The handle a service e2e spec works through. `client` and `baseUrl` are only\n * valid once the suite has started, so both are getters that fail loudly rather\n * than handing out an empty string.\n */\nexport interface ServiceE2eContext {\n readonly profile: E2eProfile;\n readonly baseUrl: string;\n readonly client: AxiosInstance;\n}\n\n/**\n * Wires a service e2e suite to the active profile.\n *\n * In `mock` the service is booted in-process against driver fakes; in `live` it\n * is the process already running on `liveUrlEnvVar`. Either way the spec gets\n * the same axios client against the same routes, so ONE suite covers both — no\n * `test.skip` on an env var, and no second copy of the journeys.\n *\n * Call it at the top level of a spec file; it registers the suite hooks itself.\n */\nexport const defineServiceE2e = ({\n liveUrlEnvVar,\n startMock,\n authorization,\n}: ServiceE2eOptions): ServiceE2eContext => {\n const profile = resolveE2eProfile();\n let running: RunningService | undefined;\n let client: AxiosInstance | undefined;\n\n const started = (): RunningService => {\n if (running === undefined) {\n throw new Error(\n 'The e2e service is not running yet — read `baseUrl`/`client` inside a test, not at module scope.',\n );\n }\n return running;\n };\n\n beforeAll(async () => {\n running =\n profile === 'mock'\n ? await startMock()\n : {\n baseUrl: requireLiveUrl(liveUrlEnvVar),\n // Nothing to tear down: the live process outlives the run.\n close: () => Promise.resolve(),\n };\n client = axios.create({\n baseURL: running.baseUrl,\n headers:\n authorization === undefined\n ? undefined\n : { Authorization: await authorization() },\n // 4xx and 5xx are assertion subjects in these suites, not transport\n // failures — a service e2e that cannot assert on a 400 is missing half\n // its surface.\n validateStatus: () => true,\n });\n });\n\n afterAll(async () => {\n await running?.close();\n running = undefined;\n client = undefined;\n });\n\n return {\n profile,\n get baseUrl() {\n return started().baseUrl;\n },\n get client() {\n started();\n return client as AxiosInstance;\n },\n };\n};\n"],"names":["axios","afterAll","beforeAll","requireLiveUrl","resolveE2eProfile","defineServiceE2e","liveUrlEnvVar","startMock","authorization","profile","running","client","started","undefined","Error","baseUrl","close","Promise","resolve","create","baseURL","headers","Authorization","validateStatus"],"mappings":"AAAA,OAAOA,WAAmC,QAAQ;AAClD,SAASC,QAAQ,EAAEC,SAAS,QAAQ,SAAS;AAE7C,SAEEC,cAAc,EACdC,iBAAiB,QACZ,wBAAwB;AA6C/B;;;;;;;;;CASC,GACD,OAAO,MAAMC,mBAAmB,CAAC,EAC/BC,aAAa,EACbC,SAAS,EACTC,aAAa,EACK;IAClB,MAAMC,UAAUL;IAChB,IAAIM;IACJ,IAAIC;IAEJ,MAAMC,UAAU;QACd,IAAIF,YAAYG,WAAW;YACzB,MAAM,IAAIC,MACR;QAEJ;QACA,OAAOJ;IACT;IAEAR,UAAU;QACRQ,UACED,YAAY,SACR,MAAMF,cACN;YACEQ,SAASZ,eAAeG;YACxB,2DAA2D;YAC3DU,OAAO,IAAMC,QAAQC,OAAO;QAC9B;QACNP,SAASX,MAAMmB,MAAM,CAAC;YACpBC,SAASV,QAAQK,OAAO;YACxBM,SACEb,kBAAkBK,YACdA,YACA;gBAAES,eAAe,MAAMd;YAAgB;YAC7C,oEAAoE;YACpE,uEAAuE;YACvE,eAAe;YACfe,gBAAgB,IAAM;QACxB;IACF;IAEAtB,SAAS;QACP,OAAMS,2BAAAA,QAASM,KAAK;QACpBN,UAAUG;QACVF,SAASE;IACX;IAEA,OAAO;QACLJ;QACA,IAAIM
|
|
1
|
+
{"version":3,"sources":["../../src/service/define-service-e2e.ts"],"sourcesContent":["import axios, { type AxiosInstance } from 'axios';\nimport { afterAll, beforeAll } from 'vitest';\n\nimport {\n type E2eProfile,\n requireLiveUrl,\n resolveE2eProfile,\n} from '../profile/profile.js';\n\n/** A service booted for the run, whichever profile started it. */\nexport interface RunningService {\n readonly baseUrl: string;\n close(): Promise<void>;\n}\n\nexport interface ServiceE2eOptions {\n /**\n * The variable a `live` run reads its target from, e.g.\n * `MARKETPLACE_ADMIN_SERVICE_URL`.\n */\n liveUrlEnvVar: string;\n /**\n * Boots the service in-process for a `mock` run. Supplied by the e2e project\n * rather than by this package, because only the project knows its own\n * `router` and which fakes stand in for its infrastructure — and because a\n * package under `entifix` must not depend on a `shells` one.\n */\n startMock: () => Promise<RunningService>;\n /**\n * Default `Authorization` header for every request the suite makes, built\n * once at start-up.\n *\n * A guarded service answers `401` to an anonymous request, which would turn\n * every journey in the suite into an authentication test. Supplying a\n * principal here keeps the specs about what they are actually asserting;\n * the guard itself is covered by its own spec, which omits or corrupts the\n * header on purpose.\n */\n authorization?: () => Promise<string>;\n}\n\n/**\n * The handle a service e2e spec works through. `client` and `baseUrl` are only\n * valid once the suite has started, so both are getters that fail loudly rather\n * than handing out an empty string.\n */\nexport interface ServiceE2eContext {\n readonly profile: E2eProfile;\n readonly baseUrl: string;\n readonly client: AxiosInstance;\n}\n\n/**\n * Wires a service e2e suite to the active profile.\n *\n * In `mock` the service is booted in-process against driver fakes; in `live` it\n * is the process already running on `liveUrlEnvVar`. Either way the spec gets\n * the same axios client against the same routes, so ONE suite covers both — no\n * `test.skip` on an env var, and no second copy of the journeys.\n *\n * Call it at the top level of a spec file; it registers the suite hooks itself.\n */\nexport const defineServiceE2e = ({\n liveUrlEnvVar,\n startMock,\n authorization,\n}: ServiceE2eOptions): ServiceE2eContext => {\n const profile = resolveE2eProfile();\n let running: RunningService | undefined;\n let client: AxiosInstance | undefined;\n\n const started = (): RunningService => {\n if (running === undefined) {\n throw new Error(\n 'The e2e service is not running yet — read `baseUrl`/`client` inside a test, not at module scope.',\n );\n }\n return running;\n };\n\n beforeAll(async () => {\n running =\n profile === 'mock'\n ? await startMock()\n : {\n baseUrl: requireLiveUrl(liveUrlEnvVar),\n // Nothing to tear down: the live process outlives the run.\n close: () => Promise.resolve(),\n };\n client = axios.create({\n baseURL: running.baseUrl,\n headers:\n authorization === undefined\n ? undefined\n : { Authorization: await authorization() },\n // 4xx and 5xx are assertion subjects in these suites, not transport\n // failures — a service e2e that cannot assert on a 400 is missing half\n // its surface.\n validateStatus: () => true,\n });\n });\n\n afterAll(async () => {\n await running?.close();\n running = undefined;\n client = undefined;\n });\n\n return {\n profile,\n get baseUrl() {\n return started().baseUrl;\n },\n get client() {\n started();\n return client as AxiosInstance;\n },\n };\n};\n"],"names":["axios","afterAll","beforeAll","requireLiveUrl","resolveE2eProfile","defineServiceE2e","liveUrlEnvVar","startMock","authorization","profile","running","client","started","undefined","Error","baseUrl","close","Promise","resolve","create","baseURL","headers","Authorization","validateStatus"],"mappings":"AAAA,OAAOA,WAAmC,QAAQ;AAClD,SAASC,QAAQ,EAAEC,SAAS,QAAQ,SAAS;AAE7C,SAEEC,cAAc,EACdC,iBAAiB,QACZ,wBAAwB;AA6C/B;;;;;;;;;CASC,GACD,OAAO,MAAMC,mBAAmB,CAAC,EAC/BC,aAAa,EACbC,SAAS,EACTC,aAAa,EACK;IAClB,MAAMC,UAAUL;IAChB,IAAIM;IACJ,IAAIC;IAEJ,MAAMC,UAAU;QACd,IAAIF,YAAYG,WAAW;YACzB,MAAM,IAAIC,MACR;QAEJ;QACA,OAAOJ;IACT;IAEAR,UAAU;QACRQ,UACED,YAAY,SACR,MAAMF,cACN;YACEQ,SAASZ,eAAeG;YACxB,2DAA2D;YAC3DU,OAAO,IAAMC,QAAQC,OAAO;QAC9B;QACNP,SAASX,MAAMmB,MAAM,CAAC;YACpBC,SAASV,QAAQK,OAAO;YACxBM,SACEb,kBAAkBK,YACdA,YACA;gBAAES,eAAe,MAAMd;YAAgB;YAC7C,oEAAoE;YACpE,uEAAuE;YACvE,eAAe;YACfe,gBAAgB,IAAM;QACxB;IACF;IAEAtB,SAAS;QACP,OAAMS,2BAAAA,QAASM,KAAK;QACpBN,UAAUG;QACVF,SAASE;IACX;IAEA,OAAO;QACLJ;QACA,IAAIM;YACF,OAAOH,UAAUG,OAAO;QAC1B;QACA,IAAIJ;YACFC;YACA,OAAOD;QACT;IACF;AACF,EAAE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@entifix/testing-e2e",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "End-to-end testing with one set of journeys and two profiles: mocked backends by default, real infrastructure on demand.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -67,9 +67,9 @@
|
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"@swc/helpers": "0.5.23",
|
|
70
|
-
"@entifix/business": "0.
|
|
71
|
-
"@entifix/
|
|
72
|
-
"@entifix/
|
|
70
|
+
"@entifix/business": "0.4.1",
|
|
71
|
+
"@entifix/core": "0.4.1",
|
|
72
|
+
"@entifix/testing-unit": "0.4.1"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"@nx/devkit": ">=23 <24",
|
|
@@ -77,11 +77,12 @@
|
|
|
77
77
|
"@playwright/test": "*",
|
|
78
78
|
"axios": "*",
|
|
79
79
|
"effect": "^4.0.5",
|
|
80
|
-
"msw": "
|
|
80
|
+
"msw": ">=3",
|
|
81
|
+
"@msw/playwright": ">=0.7",
|
|
81
82
|
"vitest": "*",
|
|
82
|
-
"@entifix/
|
|
83
|
-
"@entifix/mongo": "0.
|
|
84
|
-
"@entifix/
|
|
83
|
+
"@entifix/amqp": "0.4.1",
|
|
84
|
+
"@entifix/mongo": "0.4.1",
|
|
85
|
+
"@entifix/redis": "0.4.1"
|
|
85
86
|
},
|
|
86
87
|
"peerDependenciesMeta": {
|
|
87
88
|
"@msw/playwright": {
|
|
@@ -116,11 +117,11 @@
|
|
|
116
117
|
}
|
|
117
118
|
},
|
|
118
119
|
"devDependencies": {
|
|
119
|
-
"@nx/devkit": "23.0
|
|
120
|
-
"@nx/playwright": "23.0
|
|
120
|
+
"@nx/devkit": "23.3.0",
|
|
121
|
+
"@nx/playwright": "23.3.0",
|
|
121
122
|
"effect": "4.0.5",
|
|
122
|
-
"@entifix/amqp": "0.
|
|
123
|
-
"@entifix/mongo": "0.
|
|
124
|
-
"@entifix/redis": "0.
|
|
123
|
+
"@entifix/amqp": "0.4.1",
|
|
124
|
+
"@entifix/mongo": "0.4.1",
|
|
125
|
+
"@entifix/redis": "0.4.1"
|
|
125
126
|
}
|
|
126
127
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/playwright/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAKtC,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,qEAAqE;IACrE,OAAO,EAAE,cAAc,CAAC;IACxB,kEAAkE;IAClE,cAAc,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAeD;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,0RAUpB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAAI,oCAGlC,qBAA0B,kTAkCzB,CAAC;AAEL,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/playwright/test.ts"],"sourcesContent":["import { defineNetworkFixture, type NetworkFixture } from '@msw/playwright';\nimport { test as base } from '@playwright/test';\nimport type { AnyHandler } from 'msw';\n\nimport { isMockProfile } from '../profile/profile.js';\nimport { assertExpectedServerOnce } from './assert-expected-server.js';\n\nexport interface EntifixE2eFixtures {\n /** The handlers the mock profile starts from. Overridable per project. */\n handlers: AnyHandler[];\n /** The msw network, for per-test overrides in a `*.mock.spec.ts`. */\n network: NetworkFixture;\n /** Refuses a hermetic run against a reused development server. */\n expectedServer: void;\n}\n\nexport interface EntifixE2eTestOptions {\n /**\n * The mock backend. Ignored in the `live` profile, where the app talks to a\n * real service.\n */\n handlers?: AnyHandler[];\n /**\n * Origins whose unstubbed requests are allowed through — in practice the app\n * under test itself, which serves its own documents, RSC payloads and\n * dev-tooling endpoints.\n *\n * Everything else must be stubbed: a request to a *service* that nobody\n * handled fails the test rather than escaping to a machine that may not even\n * be running.\n */\n passthroughOrigins?: string[];\n}\n\n/**\n * In `live`, the network is untouched — so reaching for it is a mistake worth\n * reporting rather than a silent no-op that makes a spec assert nothing.\n */\nconst liveNetwork = (): NetworkFixture =>\n new Proxy({} as NetworkFixture, {\n get(_target, property) {\n throw new Error(\n `The network fixture is not available in the live profile (tried to use \"${String(property)}\"). Move this expectation into a *.mock.spec.ts file.`,\n );\n },\n });\n\n/**\n * Playwright's own `test`, plus the reused-server guard and nothing else.\n *\n * For a spec that wants no msw network and no seeded session — proving the\n * unauthenticated redirect, say. It exists so that \"this spec needs no\n * fixtures\" cannot quietly mean \"this spec is not checked against the artifact\n * it is running on\": importing `test` straight from `@playwright/test` is what\n * left the account journeys resolving a principal against a live auth-service\n * while claiming to be hermetic.\n */\nexport const baseTest = base.extend<Pick<EntifixE2eFixtures, 'expectedServer'>>(\n {\n expectedServer: [\n async ({ baseURL }, use) => {\n await assertExpectedServerOnce(baseURL);\n await use();\n },\n { auto: true },\n ],\n },\n);\n\n/**\n * Builds the `test` an entifix app e2e project imports.\n *\n * In `mock` it installs the msw handlers over Playwright's `page.route()`\n * (via `@msw/playwright`), so the browser talks to the fixture backend and the\n * app itself is untouched — no worker script, no `NEXT_PUBLIC_*` switch, no\n * mocking code shipped in the application bundle. In `live` the fixture stands\n * down and the same specs hit the real service.\n */\nexport const defineEntifixE2eTest = ({\n handlers = [],\n passthroughOrigins = [],\n}: EntifixE2eTestOptions = {}) =>\n baseTest.extend<EntifixE2eFixtures>({\n handlers: [handlers, { option: true }],\n\n network: [\n async ({ context, handlers: activeHandlers }, use) => {\n if (!isMockProfile()) {\n await use(liveNetwork());\n return;\n }\n\n const network = defineNetworkFixture({\n context,\n handlers: activeHandlers,\n // An unstubbed *service* request must fail the test rather than\n // escape to the network: a spec that passes because it silently\n // talked to nothing is worse than one that fails. The app's own\n // origin is exempt — it legitimately serves itself.\n onUnhandledRequest: (request, print) => {\n if (\n passthroughOrigins.some(origin => request.url.startsWith(origin))\n ) {\n return;\n }\n print.error();\n },\n });\n\n await network.enable();\n await use(network);\n await network.disable();\n },\n { auto: true },\n ],\n });\n\nexport type { NetworkFixture } from '@msw/playwright';\nexport { expect } from '@playwright/test';\n"],"names":["defineNetworkFixture","test","base","isMockProfile","assertExpectedServerOnce","liveNetwork","Proxy","get","_target","property","Error","String","baseTest","extend","expectedServer","baseURL","use","auto","defineEntifixE2eTest","handlers","passthroughOrigins","option","network","context","activeHandlers","onUnhandledRequest","request","print","some","origin","url","startsWith","error","enable","disable","expect"],"mappings":"AAAA,SAASA,oBAAoB,QAA6B,kBAAkB;AAC5E,SAASC,QAAQC,IAAI,QAAQ,mBAAmB;AAGhD,SAASC,aAAa,QAAQ,wBAAwB;AACtD,SAASC,wBAAwB,QAAQ,8BAA8B;AA6BvE;;;CAGC,GACD,MAAMC,cAAc,IAClB,IAAIC,MAAM,CAAC,GAAqB;QAC9BC,KAAIC,OAAO,EAAEC,QAAQ;YACnB,MAAM,IAAIC,MACR,CAAC,wEAAwE,EAAEC,OAAOF,UAAU,qDAAqD,CAAC;QAEtJ;IACF;AAEF;;;;;;;;;CASC,GACD,OAAO,MAAMG,WAAWV,KAAKW,MAAM,CACjC;IACEC,gBAAgB;QACd,OAAO,EAAEC,OAAO,EAAE,EAAEC;YAClB,MAAMZ,yBAAyBW;YAC/B,MAAMC;QACR;QACA;YAAEC,MAAM;QAAK;KACd;AACH,GACA;AAEF;;;;;;;;CAQC,GACD,OAAO,MAAMC,uBAAuB,CAAC,EACnCC,WAAW,EAAE,EACbC,qBAAqB,EAAE,EACD,GAAG,CAAC,CAAC,GAC3BR,SAASC,MAAM,CAAqB;QAClCM,UAAU;YAACA;YAAU;gBAAEE,QAAQ;YAAK;SAAE;QAEtCC,SAAS;YACP,OAAO,EAAEC,OAAO,EAAEJ,UAAUK,cAAc,EAAE,EAAER;gBAC5C,IAAI,CAACb,iBAAiB;oBACpB,MAAMa,IAAIX;oBACV;gBACF;gBAEA,MAAMiB,UAAUtB,qBAAqB;oBACnCuB;oBACAJ,UAAUK;oBACV,gEAAgE;oBAChE,gEAAgE;oBAChE,gEAAgE;oBAChE,oDAAoD;oBACpDC,oBAAoB,CAACC,SAASC;wBAC5B,IACEP,mBAAmBQ,IAAI,CAACC,CAAAA,SAAUH,QAAQI,GAAG,CAACC,UAAU,CAACF,UACzD;4BACA;wBACF;wBACAF,MAAMK,KAAK;oBACb;gBACF;gBAEA,MAAMV,QAAQW,MAAM;gBACpB,MAAMjB,IAAIM;gBACV,MAAMA,QAAQY,OAAO;YACvB;YACA;gBAAEjB,MAAM;YAAK;SACd;IACH,GAAG;AAGL,SAASkB,MAAM,QAAQ,mBAAmB"}
|