@stratal/testing 0.0.0-canary-6cccfef → 0.0.0-canary-7f2772b

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.
Files changed (103) hide show
  1. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.mjs +9 -0
  2. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorateMetadata.mjs +6 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorateParam.mjs +8 -0
  4. package/dist/auth/acting-as.d.mts +25 -0
  5. package/dist/auth/acting-as.d.mts.map +1 -0
  6. package/dist/auth/acting-as.mjs +69 -0
  7. package/dist/auth/acting-as.mjs.map +1 -0
  8. package/dist/auth/index.d.mts +1 -0
  9. package/dist/auth/index.mjs +2 -0
  10. package/dist/core/env/index.d.mts +1 -0
  11. package/dist/core/env/index.mjs +2 -0
  12. package/dist/core/env/test-env.d.mts +13 -0
  13. package/dist/core/env/test-env.d.mts.map +1 -0
  14. package/dist/core/env/test-env.mjs +18 -0
  15. package/dist/core/env/test-env.mjs.map +1 -0
  16. package/dist/core/http/fetch-mock.types.d.mts +51 -0
  17. package/dist/core/http/fetch-mock.types.d.mts.map +1 -0
  18. package/dist/core/http/mock-fetch.d.mts +92 -0
  19. package/dist/core/http/mock-fetch.d.mts.map +1 -0
  20. package/dist/core/http/mock-fetch.mjs +117 -0
  21. package/dist/core/http/mock-fetch.mjs.map +1 -0
  22. package/dist/core/http/test-http-client.d.mts +58 -0
  23. package/dist/core/http/test-http-client.d.mts.map +1 -0
  24. package/dist/core/http/test-http-client.mjs +76 -0
  25. package/dist/core/http/test-http-client.mjs.map +1 -0
  26. package/dist/core/http/test-http-request.d.mts +64 -0
  27. package/dist/core/http/test-http-request.d.mts.map +1 -0
  28. package/dist/core/http/test-http-request.mjs +95 -0
  29. package/dist/core/http/test-http-request.mjs.map +1 -0
  30. package/dist/core/http/test-response.d.mts +164 -0
  31. package/dist/core/http/test-response.d.mts.map +1 -0
  32. package/dist/core/http/test-response.mjs +282 -0
  33. package/dist/core/http/test-response.mjs.map +1 -0
  34. package/dist/core/override/index.d.mts +1 -0
  35. package/dist/core/override/provider-override-builder.d.mts +82 -0
  36. package/dist/core/override/provider-override-builder.d.mts.map +1 -0
  37. package/dist/core/override/provider-override-builder.mjs +96 -0
  38. package/dist/core/override/provider-override-builder.mjs.map +1 -0
  39. package/dist/core/quarry/test-command-request.d.mts +36 -0
  40. package/dist/core/quarry/test-command-request.d.mts.map +1 -0
  41. package/dist/core/quarry/test-command-request.mjs +40 -0
  42. package/dist/core/quarry/test-command-request.mjs.map +1 -0
  43. package/dist/core/quarry/test-command-result.d.mts +34 -0
  44. package/dist/core/quarry/test-command-result.d.mts.map +1 -0
  45. package/dist/core/quarry/test-command-result.mjs +64 -0
  46. package/dist/core/quarry/test-command-result.mjs.map +1 -0
  47. package/dist/core/sse/test-sse-connection.d.mts +64 -0
  48. package/dist/core/sse/test-sse-connection.d.mts.map +1 -0
  49. package/dist/core/sse/test-sse-connection.mjs +198 -0
  50. package/dist/core/sse/test-sse-connection.mjs.map +1 -0
  51. package/dist/core/sse/test-sse-request.d.mts +46 -0
  52. package/dist/core/sse/test-sse-request.d.mts.map +1 -0
  53. package/dist/core/sse/test-sse-request.mjs +71 -0
  54. package/dist/core/sse/test-sse-request.mjs.map +1 -0
  55. package/dist/core/test.d.mts +52 -0
  56. package/dist/core/test.d.mts.map +1 -0
  57. package/dist/core/test.mjs +57 -0
  58. package/dist/core/test.mjs.map +1 -0
  59. package/dist/core/testing-module-builder.d.mts +61 -0
  60. package/dist/core/testing-module-builder.d.mts.map +1 -0
  61. package/dist/core/testing-module-builder.mjs +102 -0
  62. package/dist/core/testing-module-builder.mjs.map +1 -0
  63. package/dist/core/testing-module.d.mts +121 -0
  64. package/dist/core/testing-module.d.mts.map +1 -0
  65. package/dist/core/testing-module.mjs +170 -0
  66. package/dist/core/testing-module.mjs.map +1 -0
  67. package/dist/core/ws/test-ws-connection.d.mts +57 -0
  68. package/dist/core/ws/test-ws-connection.d.mts.map +1 -0
  69. package/dist/core/ws/test-ws-connection.mjs +111 -0
  70. package/dist/core/ws/test-ws-connection.mjs.map +1 -0
  71. package/dist/core/ws/test-ws-request.d.mts +47 -0
  72. package/dist/core/ws/test-ws-request.d.mts.map +1 -0
  73. package/dist/core/ws/test-ws-request.mjs +76 -0
  74. package/dist/core/ws/test-ws-request.mjs.map +1 -0
  75. package/dist/errors/setup-error.d.mts +13 -0
  76. package/dist/errors/setup-error.d.mts.map +1 -0
  77. package/dist/errors/setup-error.mjs +15 -0
  78. package/dist/errors/setup-error.mjs.map +1 -0
  79. package/dist/errors/test-error.d.mts +12 -0
  80. package/dist/errors/test-error.d.mts.map +1 -0
  81. package/dist/errors/test-error.mjs +17 -0
  82. package/dist/errors/test-error.mjs.map +1 -0
  83. package/dist/index.d.mts +21 -1016
  84. package/dist/index.mjs +21 -1588
  85. package/dist/{index-D-Q2cR2v.d.mts → storage/fake-storage.service.d.mts} +2 -2
  86. package/dist/storage/fake-storage.service.d.mts.map +1 -0
  87. package/dist/{storage-PcJUKxwp.mjs → storage/fake-storage.service.mjs} +5 -22
  88. package/dist/storage/fake-storage.service.mjs.map +1 -0
  89. package/dist/storage/index.d.mts +2 -2
  90. package/dist/storage/index.mjs +1 -1
  91. package/dist/vitest-plugin/index.d.mts +2 -50
  92. package/dist/vitest-plugin/index.mjs +1 -85
  93. package/dist/vitest-plugin/stratal-test.d.mts +50 -0
  94. package/dist/vitest-plugin/stratal-test.d.mts.map +1 -0
  95. package/dist/vitest-plugin/stratal-test.mjs +86 -0
  96. package/dist/vitest-plugin/stratal-test.mjs.map +1 -0
  97. package/package.json +3 -3
  98. package/dist/index-D-Q2cR2v.d.mts.map +0 -1
  99. package/dist/index.d.mts.map +0 -1
  100. package/dist/index.mjs.map +0 -1
  101. package/dist/storage-PcJUKxwp.mjs.map +0 -1
  102. package/dist/vitest-plugin/index.d.mts.map +0 -1
  103. package/dist/vitest-plugin/index.mjs.map +0 -1
@@ -0,0 +1,9 @@
1
+ //#region \0@oxc-project+runtime@0.115.0/helpers/decorate.js
2
+ function __decorate(decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ }
8
+ //#endregion
9
+ export { __decorate };
@@ -0,0 +1,6 @@
1
+ //#region \0@oxc-project+runtime@0.115.0/helpers/decorateMetadata.js
2
+ function __decorateMetadata(k, v) {
3
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4
+ }
5
+ //#endregion
6
+ export { __decorateMetadata };
@@ -0,0 +1,8 @@
1
+ //#region \0@oxc-project+runtime@0.115.0/helpers/decorateParam.js
2
+ function __decorateParam(paramIndex, decorator) {
3
+ return function(target, key) {
4
+ decorator(target, key, paramIndex);
5
+ };
6
+ }
7
+ //#endregion
8
+ export { __decorateParam };
@@ -0,0 +1,25 @@
1
+ import { AuthService } from "@stratal/framework/auth";
2
+
3
+ //#region src/auth/acting-as.d.ts
4
+ /**
5
+ * ActingAs
6
+ *
7
+ * Creates authentication sessions for testing.
8
+ * Uses Better Auth's internalAdapter to create real database sessions.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const actingAs = new ActingAs(authService)
13
+ * const headers = await actingAs.createSessionForUser({ id: 'user-123' })
14
+ * ```
15
+ */
16
+ declare class ActingAs {
17
+ private readonly authService;
18
+ constructor(authService: AuthService);
19
+ createSessionForUser(user: {
20
+ id: string;
21
+ }): Promise<Headers>;
22
+ }
23
+ //#endregion
24
+ export { ActingAs };
25
+ //# sourceMappingURL=acting-as.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acting-as.d.mts","names":[],"sources":["../../src/auth/acting-as.ts"],"mappings":";;;;;AAoCA;;;;;;;;;;cAAa,QAAA;EAAA,iBACkB,WAAA;cAAA,WAAA,EAAa,WAAA;EAEpC,oBAAA,CAAqB,IAAA;IAAQ,EAAA;EAAA,IAAe,OAAA,CAAQ,OAAA;AAAA"}
@@ -0,0 +1,69 @@
1
+ import { setSessionCookie } from "better-auth/cookies";
2
+ import { convertSetCookieToCookie } from "better-auth/test";
3
+ //#region src/auth/acting-as.ts
4
+ async function makeSignature(value, secret) {
5
+ const algorithm = {
6
+ name: "HMAC",
7
+ hash: "SHA-256"
8
+ };
9
+ const secretBuf = new TextEncoder().encode(secret);
10
+ const key = await crypto.subtle.importKey("raw", secretBuf, algorithm, false, ["sign"]);
11
+ const signature = await crypto.subtle.sign(algorithm.name, key, new TextEncoder().encode(value));
12
+ return btoa(String.fromCharCode(...new Uint8Array(signature)));
13
+ }
14
+ function buildCookieString(name, value, options = {}) {
15
+ let str = `${name}=${encodeURIComponent(value)}`;
16
+ if (options.path) str += `; Path=${options.path}`;
17
+ if (options.httpOnly) str += "; HttpOnly";
18
+ if (options.secure) str += "; Secure";
19
+ if (options.sameSite) str += `; SameSite=${options.sameSite}`;
20
+ if (options.maxAge !== void 0) str += `; Max-Age=${Math.floor(options.maxAge)}`;
21
+ return str;
22
+ }
23
+ /**
24
+ * ActingAs
25
+ *
26
+ * Creates authentication sessions for testing.
27
+ * Uses Better Auth's internalAdapter to create real database sessions.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const actingAs = new ActingAs(authService)
32
+ * const headers = await actingAs.createSessionForUser({ id: 'user-123' })
33
+ * ```
34
+ */
35
+ var ActingAs = class {
36
+ constructor(authService) {
37
+ this.authService = authService;
38
+ }
39
+ async createSessionForUser(user) {
40
+ const ctx = await this.authService.auth.$context;
41
+ const secret = ctx.secret;
42
+ const session = await ctx.internalAdapter.createSession(user.id, void 0, {
43
+ ipAddress: "127.0.0.1",
44
+ userAgent: "test-client"
45
+ });
46
+ const dbUser = await ctx.internalAdapter.findUserById(user.id);
47
+ if (!dbUser) throw new Error(`User not found: ${user.id}`);
48
+ const responseHeaders = new Headers();
49
+ await setSessionCookie({
50
+ context: ctx,
51
+ getSignedCookie: () => null,
52
+ setSignedCookie: async (name, value, _secret, options = {}) => {
53
+ const signedValue = `${value}.${await makeSignature(value, secret)}`;
54
+ responseHeaders.append("Set-Cookie", buildCookieString(name, signedValue, options));
55
+ },
56
+ setCookie: (name, value, options = {}) => {
57
+ responseHeaders.append("Set-Cookie", buildCookieString(name, value, options));
58
+ }
59
+ }, {
60
+ session,
61
+ user: dbUser
62
+ }, false);
63
+ return convertSetCookieToCookie(responseHeaders);
64
+ }
65
+ };
66
+ //#endregion
67
+ export { ActingAs };
68
+
69
+ //# sourceMappingURL=acting-as.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acting-as.mjs","names":[],"sources":["../../src/auth/acting-as.ts"],"sourcesContent":["import type { AuthService } from '@stratal/framework/auth'\nimport { type GenericEndpointContext } from 'better-auth'\nimport { setSessionCookie } from 'better-auth/cookies'\nimport { convertSetCookieToCookie } from 'better-auth/test'\n\nasync function makeSignature(value: string, secret: string): Promise<string> {\n const algorithm = { name: 'HMAC', hash: 'SHA-256' }\n const secretBuf = new TextEncoder().encode(secret)\n const key = await crypto.subtle.importKey('raw', secretBuf, algorithm, false, ['sign'])\n const signature = await crypto.subtle.sign(algorithm.name, key, new TextEncoder().encode(value))\n return btoa(String.fromCharCode(...new Uint8Array(signature)))\n}\n\nfunction buildCookieString(name: string, value: string, options: Record<string, unknown> = {}): string {\n const encodedValue = encodeURIComponent(value)\n let str = `${name}=${encodedValue}`\n if (options.path) str += `; Path=${options.path as string}`\n if (options.httpOnly) str += '; HttpOnly'\n if (options.secure) str += '; Secure'\n if (options.sameSite) str += `; SameSite=${options.sameSite as string}`\n if (options.maxAge !== undefined) str += `; Max-Age=${Math.floor(options.maxAge as number)}`\n return str\n}\n\n/**\n * ActingAs\n *\n * Creates authentication sessions for testing.\n * Uses Better Auth's internalAdapter to create real database sessions.\n *\n * @example\n * ```typescript\n * const actingAs = new ActingAs(authService)\n * const headers = await actingAs.createSessionForUser({ id: 'user-123' })\n * ```\n */\nexport class ActingAs {\n constructor(private readonly authService: AuthService) { }\n\n async createSessionForUser(user: { id: string }): Promise<Headers> {\n const auth = this.authService.auth\n const ctx = await auth.$context\n\n const secret = ctx.secret\n\n const session = await ctx.internalAdapter.createSession(\n user.id,\n undefined,\n { ipAddress: '127.0.0.1', userAgent: 'test-client' }\n )\n\n const dbUser = await ctx.internalAdapter.findUserById(user.id)\n if (!dbUser) {\n throw new Error(`User not found: ${user.id}`)\n }\n\n const responseHeaders = new Headers()\n const mockCtx = {\n context: ctx,\n getSignedCookie: () => null,\n setSignedCookie: async (name: string, value: string, _secret: string, options: Record<string, unknown> = {}) => {\n const signature = await makeSignature(value, secret)\n const signedValue = `${value}.${signature}`\n responseHeaders.append('Set-Cookie', buildCookieString(name, signedValue, options))\n },\n setCookie: (name: string, value: string, options: Record<string, unknown> = {}) => {\n responseHeaders.append('Set-Cookie', buildCookieString(name, value, options))\n },\n }\n\n await setSessionCookie(mockCtx as unknown as GenericEndpointContext, { session, user: dbUser }, false)\n return convertSetCookieToCookie(responseHeaders)\n }\n}\n"],"mappings":";;;AAKA,eAAe,cAAc,OAAe,QAAiC;CAC3E,MAAM,YAAY;EAAE,MAAM;EAAQ,MAAM;EAAW;CACnD,MAAM,YAAY,IAAI,aAAa,CAAC,OAAO,OAAO;CAClD,MAAM,MAAM,MAAM,OAAO,OAAO,UAAU,OAAO,WAAW,WAAW,OAAO,CAAC,OAAO,CAAC;CACvF,MAAM,YAAY,MAAM,OAAO,OAAO,KAAK,UAAU,MAAM,KAAK,IAAI,aAAa,CAAC,OAAO,MAAM,CAAC;AAChG,QAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAW,UAAU,CAAC,CAAC;;AAGhE,SAAS,kBAAkB,MAAc,OAAe,UAAmC,EAAE,EAAU;CAErG,IAAI,MAAM,GAAG,KAAK,GADG,mBAAmB,MAAM;AAE9C,KAAI,QAAQ,KAAM,QAAO,UAAU,QAAQ;AAC3C,KAAI,QAAQ,SAAU,QAAO;AAC7B,KAAI,QAAQ,OAAQ,QAAO;AAC3B,KAAI,QAAQ,SAAU,QAAO,cAAc,QAAQ;AACnD,KAAI,QAAQ,WAAW,KAAA,EAAW,QAAO,aAAa,KAAK,MAAM,QAAQ,OAAiB;AAC1F,QAAO;;;;;;;;;;;;;;AAeT,IAAa,WAAb,MAAsB;CACpB,YAAY,aAA2C;AAA1B,OAAA,cAAA;;CAE7B,MAAM,qBAAqB,MAAwC;EAEjE,MAAM,MAAM,MADC,KAAK,YAAY,KACP;EAEvB,MAAM,SAAS,IAAI;EAEnB,MAAM,UAAU,MAAM,IAAI,gBAAgB,cACxC,KAAK,IACL,KAAA,GACA;GAAE,WAAW;GAAa,WAAW;GAAe,CACrD;EAED,MAAM,SAAS,MAAM,IAAI,gBAAgB,aAAa,KAAK,GAAG;AAC9D,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,mBAAmB,KAAK,KAAK;EAG/C,MAAM,kBAAkB,IAAI,SAAS;AAcrC,QAAM,iBAbU;GACd,SAAS;GACT,uBAAuB;GACvB,iBAAiB,OAAO,MAAc,OAAe,SAAiB,UAAmC,EAAE,KAAK;IAE9G,MAAM,cAAc,GAAG,MAAM,GADX,MAAM,cAAc,OAAO,OAAO;AAEpD,oBAAgB,OAAO,cAAc,kBAAkB,MAAM,aAAa,QAAQ,CAAC;;GAErF,YAAY,MAAc,OAAe,UAAmC,EAAE,KAAK;AACjF,oBAAgB,OAAO,cAAc,kBAAkB,MAAM,OAAO,QAAQ,CAAC;;GAEhF,EAEoE;GAAE;GAAS,MAAM;GAAQ,EAAE,MAAM;AACtG,SAAO,yBAAyB,gBAAgB"}
@@ -0,0 +1 @@
1
+ import { ActingAs } from "./acting-as.mjs";
@@ -0,0 +1,2 @@
1
+ import "./acting-as.mjs";
2
+ export {};
@@ -0,0 +1 @@
1
+ import { getTestEnv } from "./test-env.mjs";
@@ -0,0 +1,2 @@
1
+ import "./test-env.mjs";
2
+ export {};
@@ -0,0 +1,13 @@
1
+ import { StratalEnv } from "stratal";
2
+
3
+ //#region src/core/env/test-env.d.ts
4
+ /**
5
+ * Get test environment with optional overrides
6
+ *
7
+ * @param overrides - Optional partial env to merge with cloudflare:test env
8
+ * @returns Complete Env object for testing
9
+ */
10
+ declare function getTestEnv(overrides?: Partial<StratalEnv>): StratalEnv;
11
+ //#endregion
12
+ export { getTestEnv };
13
+ //# sourceMappingURL=test-env.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-env.d.mts","names":[],"sources":["../../../src/core/env/test-env.ts"],"mappings":";;;;;AASA;;;;iBAAgB,UAAA,CAAW,SAAA,GAAY,OAAA,CAAQ,UAAA,IAAc,UAAA"}
@@ -0,0 +1,18 @@
1
+ import { env } from "cloudflare:workers";
2
+ //#region src/core/env/test-env.ts
3
+ /**
4
+ * Get test environment with optional overrides
5
+ *
6
+ * @param overrides - Optional partial env to merge with cloudflare:test env
7
+ * @returns Complete Env object for testing
8
+ */
9
+ function getTestEnv(overrides) {
10
+ return {
11
+ ...env,
12
+ ...overrides
13
+ };
14
+ }
15
+ //#endregion
16
+ export { getTestEnv };
17
+
18
+ //# sourceMappingURL=test-env.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-env.mjs","names":["cloudflareEnv"],"sources":["../../../src/core/env/test-env.ts"],"sourcesContent":["import { type StratalEnv } from 'stratal'\nimport { env as cloudflareEnv } from 'cloudflare:workers'\n\n/**\n * Get test environment with optional overrides\n *\n * @param overrides - Optional partial env to merge with cloudflare:test env\n * @returns Complete Env object for testing\n */\nexport function getTestEnv(overrides?: Partial<StratalEnv>): StratalEnv {\n return {\n ...cloudflareEnv,\n ...overrides,\n } as StratalEnv\n}\n"],"mappings":";;;;;;;;AASA,SAAgB,WAAW,WAA6C;AACtE,QAAO;EACL,GAAGA;EACH,GAAG;EACJ"}
@@ -0,0 +1,51 @@
1
+ //#region src/core/http/fetch-mock.types.d.ts
2
+ /**
3
+ * Options for mocking JSON responses
4
+ */
5
+ interface MockJsonOptions {
6
+ /**
7
+ * HTTP status code for the response
8
+ * @default 200
9
+ */
10
+ status?: number;
11
+ /**
12
+ * Custom headers to include in the response
13
+ */
14
+ headers?: Record<string, string>;
15
+ /**
16
+ * Delay in milliseconds before responding
17
+ */
18
+ delay?: number;
19
+ /**
20
+ * HTTP method to match (GET, POST, PUT, PATCH, DELETE, etc.)
21
+ * @default 'GET'
22
+ */
23
+ method?: string;
24
+ /**
25
+ * Specific path to override URL pathname
26
+ * If not provided, the pathname from the URL will be used
27
+ */
28
+ path?: string;
29
+ }
30
+ /**
31
+ * Options for mocking error responses
32
+ */
33
+ interface MockErrorOptions {
34
+ /**
35
+ * Custom headers to include in the error response
36
+ */
37
+ headers?: Record<string, string>;
38
+ /**
39
+ * HTTP method to match (GET, POST, PUT, PATCH, DELETE, etc.)
40
+ * @default 'GET'
41
+ */
42
+ method?: string;
43
+ /**
44
+ * Specific path to override URL pathname
45
+ * If not provided, the pathname from the URL will be used
46
+ */
47
+ path?: string;
48
+ }
49
+ //#endregion
50
+ export { MockErrorOptions, MockJsonOptions };
51
+ //# sourceMappingURL=fetch-mock.types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-mock.types.d.mts","names":[],"sources":["../../../src/core/http/fetch-mock.types.ts"],"mappings":";;AAGA;;UAAiB,eAAA;EAUA;;;;EALhB,MAAA;EAgBA;;;EAXA,OAAA,GAAU,MAAA;EAuBM;;;EAlBhB,KAAA;EAsBA;;;;EAhBA,MAAA;EA4BI;;;;EAtBJ,IAAA;AAAA;;;;UAMgB,gBAAA;;;;EAIhB,OAAA,GAAU,MAAA;;;;;EAMV,MAAA;;;;;EAMA,IAAA;AAAA"}
@@ -0,0 +1,92 @@
1
+ import { MockErrorOptions, MockJsonOptions } from "./fetch-mock.types.mjs";
2
+ import { RequestHandler } from "msw";
3
+
4
+ //#region src/core/http/mock-fetch.d.ts
5
+ /**
6
+ * MSW-based fetch mock for declarative HTTP mocking in tests.
7
+ *
8
+ * Replaces the old Cloudflare `fetchMock` (undici MockAgent) with MSW's `setupServer`.
9
+ * Works in both Node.js and workerd test environments.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { createMockFetch } from '@stratal/testing'
14
+ *
15
+ * const mock = createMockFetch()
16
+ *
17
+ * beforeAll(() => mock.listen())
18
+ * afterEach(() => mock.reset())
19
+ * afterAll(() => mock.close())
20
+ *
21
+ * it('should mock external API', async () => {
22
+ * mock.mockJsonResponse('https://api.example.com/data', { success: true })
23
+ *
24
+ * const response = await fetch('https://api.example.com/data')
25
+ * const json = await response.json()
26
+ *
27
+ * expect(json.success).toBe(true)
28
+ * })
29
+ * ```
30
+ */
31
+ declare class MockFetch {
32
+ private server;
33
+ constructor(handlers?: RequestHandler[]);
34
+ /** Start intercepting. Call in beforeAll/beforeEach. */
35
+ listen(): void;
36
+ /** Reset runtime handlers. Call in afterEach. */
37
+ reset(): void;
38
+ /** Stop intercepting. Call in afterAll. */
39
+ close(): void;
40
+ /** Add runtime handler(s) for a single test. */
41
+ use(...handlers: RequestHandler[]): void;
42
+ /**
43
+ * Mock a JSON response.
44
+ *
45
+ * @param url - Full URL to mock (e.g., 'https://api.example.com/users')
46
+ * @param data - JSON data to return
47
+ * @param options - HTTP method, status code, headers
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * mock.mockJsonResponse('https://api.example.com/users', { users: [] })
52
+ * mock.mockJsonResponse('https://api.example.com/users', { created: true }, { method: 'POST', status: 201 })
53
+ * ```
54
+ */
55
+ mockJsonResponse(url: string, data: Record<string, unknown> | unknown[], options?: MockJsonOptions): void;
56
+ /**
57
+ * Mock an error response.
58
+ *
59
+ * @param url - Full URL to mock
60
+ * @param status - HTTP error status code
61
+ * @param message - Optional error message
62
+ * @param options - HTTP method, headers
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * mock.mockError('https://api.example.com/fail', 401, 'Unauthorized')
67
+ * mock.mockError('https://api.example.com/fail', 500, 'Server Error', { method: 'POST' })
68
+ * ```
69
+ */
70
+ mockError(url: string, status: number, message?: string, options?: MockErrorOptions): void;
71
+ }
72
+ /**
73
+ * Factory function to create a new MockFetch instance
74
+ *
75
+ * @param handlers - Optional initial MSW request handlers
76
+ * @returns A new MockFetch instance
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * import { createMockFetch } from '@stratal/testing'
81
+ *
82
+ * const mock = createMockFetch()
83
+ *
84
+ * beforeAll(() => mock.listen())
85
+ * afterEach(() => mock.reset())
86
+ * afterAll(() => mock.close())
87
+ * ```
88
+ */
89
+ declare function createMockFetch(handlers?: RequestHandler[]): MockFetch;
90
+ //#endregion
91
+ export { MockFetch, createMockFetch };
92
+ //# sourceMappingURL=mock-fetch.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-fetch.d.mts","names":[],"sources":["../../../src/core/http/mock-fetch.ts"],"mappings":";;;;;;AAgCA;;;;;;;;;;;;;;;;;;;;;;;;cAAa,SAAA;EAAA,QACH,MAAA;cAEI,QAAA,GAAU,cAAA;EA8DZ;EAzDV,MAAA,CAAA;EAyDuC;EApDvC,KAAA,CAAA;EAoDyD;EA/CzD,KAAA,CAAA;EA+CuF;EA1CvF,GAAA,CAAA,GAAO,QAAA,EAAU,cAAA;EAsEY;;;;;;;;;;;;;EArD7B,gBAAA,CAAiB,GAAA,UAAa,IAAA,EAAM,MAAA,+BAAqC,OAAA,GAAS,eAAA;;;;;;;;;;;;;;;EAyBlF,SAAA,CAAU,GAAA,UAAa,MAAA,UAAgB,OAAA,WAAkB,OAAA,GAAS,gBAAA;AAAA;;;;;;;;;;;;;;;;;;iBA4BpD,eAAA,CAAgB,QAAA,GAAW,cAAA,KAAmB,SAAA"}
@@ -0,0 +1,117 @@
1
+ import { HttpResponse, http } from "msw";
2
+ import { setupServer } from "msw/node";
3
+ //#region src/core/http/mock-fetch.ts
4
+ /**
5
+ * MSW-based fetch mock for declarative HTTP mocking in tests.
6
+ *
7
+ * Replaces the old Cloudflare `fetchMock` (undici MockAgent) with MSW's `setupServer`.
8
+ * Works in both Node.js and workerd test environments.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { createMockFetch } from '@stratal/testing'
13
+ *
14
+ * const mock = createMockFetch()
15
+ *
16
+ * beforeAll(() => mock.listen())
17
+ * afterEach(() => mock.reset())
18
+ * afterAll(() => mock.close())
19
+ *
20
+ * it('should mock external API', async () => {
21
+ * mock.mockJsonResponse('https://api.example.com/data', { success: true })
22
+ *
23
+ * const response = await fetch('https://api.example.com/data')
24
+ * const json = await response.json()
25
+ *
26
+ * expect(json.success).toBe(true)
27
+ * })
28
+ * ```
29
+ */
30
+ var MockFetch = class {
31
+ server;
32
+ constructor(handlers = []) {
33
+ this.server = setupServer(...handlers);
34
+ }
35
+ /** Start intercepting. Call in beforeAll/beforeEach. */
36
+ listen() {
37
+ this.server.listen({ onUnhandledRequest: "error" });
38
+ }
39
+ /** Reset runtime handlers. Call in afterEach. */
40
+ reset() {
41
+ this.server.resetHandlers();
42
+ }
43
+ /** Stop intercepting. Call in afterAll. */
44
+ close() {
45
+ this.server.close();
46
+ }
47
+ /** Add runtime handler(s) for a single test. */
48
+ use(...handlers) {
49
+ this.server.use(...handlers);
50
+ }
51
+ /**
52
+ * Mock a JSON response.
53
+ *
54
+ * @param url - Full URL to mock (e.g., 'https://api.example.com/users')
55
+ * @param data - JSON data to return
56
+ * @param options - HTTP method, status code, headers
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * mock.mockJsonResponse('https://api.example.com/users', { users: [] })
61
+ * mock.mockJsonResponse('https://api.example.com/users', { created: true }, { method: 'POST', status: 201 })
62
+ * ```
63
+ */
64
+ mockJsonResponse(url, data, options = {}) {
65
+ const handler = http[(options.method ?? "GET").toLowerCase()](url, () => HttpResponse.json(data, {
66
+ status: options.status ?? 200,
67
+ headers: options.headers
68
+ }));
69
+ this.server.use(handler);
70
+ }
71
+ /**
72
+ * Mock an error response.
73
+ *
74
+ * @param url - Full URL to mock
75
+ * @param status - HTTP error status code
76
+ * @param message - Optional error message
77
+ * @param options - HTTP method, headers
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * mock.mockError('https://api.example.com/fail', 401, 'Unauthorized')
82
+ * mock.mockError('https://api.example.com/fail', 500, 'Server Error', { method: 'POST' })
83
+ * ```
84
+ */
85
+ mockError(url, status, message, options = {}) {
86
+ const method = (options.method ?? "GET").toLowerCase();
87
+ const body = message ? { error: message } : void 0;
88
+ this.server.use(http[method](url, () => HttpResponse.json(body, {
89
+ status,
90
+ headers: options.headers
91
+ })));
92
+ }
93
+ };
94
+ /**
95
+ * Factory function to create a new MockFetch instance
96
+ *
97
+ * @param handlers - Optional initial MSW request handlers
98
+ * @returns A new MockFetch instance
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * import { createMockFetch } from '@stratal/testing'
103
+ *
104
+ * const mock = createMockFetch()
105
+ *
106
+ * beforeAll(() => mock.listen())
107
+ * afterEach(() => mock.reset())
108
+ * afterAll(() => mock.close())
109
+ * ```
110
+ */
111
+ function createMockFetch(handlers) {
112
+ return new MockFetch(handlers);
113
+ }
114
+ //#endregion
115
+ export { MockFetch, createMockFetch };
116
+
117
+ //# sourceMappingURL=mock-fetch.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-fetch.mjs","names":[],"sources":["../../../src/core/http/mock-fetch.ts"],"sourcesContent":["import { http, HttpResponse, type RequestHandler } from 'msw'\nimport { setupServer, type SetupServer } from 'msw/node'\nimport type { MockErrorOptions, MockJsonOptions } from './fetch-mock.types'\n\ntype HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head' | 'options'\n\n/**\n * MSW-based fetch mock for declarative HTTP mocking in tests.\n *\n * Replaces the old Cloudflare `fetchMock` (undici MockAgent) with MSW's `setupServer`.\n * Works in both Node.js and workerd test environments.\n *\n * @example\n * ```typescript\n * import { createMockFetch } from '@stratal/testing'\n *\n * const mock = createMockFetch()\n *\n * beforeAll(() => mock.listen())\n * afterEach(() => mock.reset())\n * afterAll(() => mock.close())\n *\n * it('should mock external API', async () => {\n * mock.mockJsonResponse('https://api.example.com/data', { success: true })\n *\n * const response = await fetch('https://api.example.com/data')\n * const json = await response.json()\n *\n * expect(json.success).toBe(true)\n * })\n * ```\n */\nexport class MockFetch {\n private server: SetupServer\n\n constructor(handlers: RequestHandler[] = []) {\n this.server = setupServer(...handlers)\n }\n\n /** Start intercepting. Call in beforeAll/beforeEach. */\n listen() {\n this.server.listen({ onUnhandledRequest: 'error' })\n }\n\n /** Reset runtime handlers. Call in afterEach. */\n reset() {\n this.server.resetHandlers()\n }\n\n /** Stop intercepting. Call in afterAll. */\n close() {\n this.server.close()\n }\n\n /** Add runtime handler(s) for a single test. */\n use(...handlers: RequestHandler[]) {\n this.server.use(...handlers)\n }\n\n /**\n * Mock a JSON response.\n *\n * @param url - Full URL to mock (e.g., 'https://api.example.com/users')\n * @param data - JSON data to return\n * @param options - HTTP method, status code, headers\n *\n * @example\n * ```typescript\n * mock.mockJsonResponse('https://api.example.com/users', { users: [] })\n * mock.mockJsonResponse('https://api.example.com/users', { created: true }, { method: 'POST', status: 201 })\n * ```\n */\n mockJsonResponse(url: string, data: Record<string, unknown> | unknown[], options: MockJsonOptions = {}) {\n const method = (options.method ?? 'GET').toLowerCase() as HttpMethod\n const handler = http[method](url, () =>\n HttpResponse.json(data, {\n status: options.status ?? 200,\n headers: options.headers,\n }),\n )\n this.server.use(handler)\n }\n\n /**\n * Mock an error response.\n *\n * @param url - Full URL to mock\n * @param status - HTTP error status code\n * @param message - Optional error message\n * @param options - HTTP method, headers\n *\n * @example\n * ```typescript\n * mock.mockError('https://api.example.com/fail', 401, 'Unauthorized')\n * mock.mockError('https://api.example.com/fail', 500, 'Server Error', { method: 'POST' })\n * ```\n */\n mockError(url: string, status: number, message?: string, options: MockErrorOptions = {}) {\n const method = (options.method ?? 'GET').toLowerCase() as HttpMethod\n const body = message ? { error: message } : undefined\n this.server.use(\n http[method](url, () =>\n HttpResponse.json(body, { status, headers: options.headers }),\n ),\n )\n }\n}\n\n/**\n * Factory function to create a new MockFetch instance\n *\n * @param handlers - Optional initial MSW request handlers\n * @returns A new MockFetch instance\n *\n * @example\n * ```typescript\n * import { createMockFetch } from '@stratal/testing'\n *\n * const mock = createMockFetch()\n *\n * beforeAll(() => mock.listen())\n * afterEach(() => mock.reset())\n * afterAll(() => mock.close())\n * ```\n */\nexport function createMockFetch(handlers?: RequestHandler[]): MockFetch {\n return new MockFetch(handlers)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,YAAb,MAAuB;CACrB;CAEA,YAAY,WAA6B,EAAE,EAAE;AAC3C,OAAK,SAAS,YAAY,GAAG,SAAS;;;CAIxC,SAAS;AACP,OAAK,OAAO,OAAO,EAAE,oBAAoB,SAAS,CAAC;;;CAIrD,QAAQ;AACN,OAAK,OAAO,eAAe;;;CAI7B,QAAQ;AACN,OAAK,OAAO,OAAO;;;CAIrB,IAAI,GAAG,UAA4B;AACjC,OAAK,OAAO,IAAI,GAAG,SAAS;;;;;;;;;;;;;;;CAgB9B,iBAAiB,KAAa,MAA2C,UAA2B,EAAE,EAAE;EAEtG,MAAM,UAAU,MADA,QAAQ,UAAU,OAAO,aAAa,EACzB,WAC3B,aAAa,KAAK,MAAM;GACtB,QAAQ,QAAQ,UAAU;GAC1B,SAAS,QAAQ;GAClB,CAAC,CACH;AACD,OAAK,OAAO,IAAI,QAAQ;;;;;;;;;;;;;;;;CAiB1B,UAAU,KAAa,QAAgB,SAAkB,UAA4B,EAAE,EAAE;EACvF,MAAM,UAAU,QAAQ,UAAU,OAAO,aAAa;EACtD,MAAM,OAAO,UAAU,EAAE,OAAO,SAAS,GAAG,KAAA;AAC5C,OAAK,OAAO,IACV,KAAK,QAAQ,WACX,aAAa,KAAK,MAAM;GAAE;GAAQ,SAAS,QAAQ;GAAS,CAAC,CAC9D,CACF;;;;;;;;;;;;;;;;;;;;AAqBL,SAAgB,gBAAgB,UAAwC;AACtE,QAAO,IAAI,UAAU,SAAS"}
@@ -0,0 +1,58 @@
1
+ import { TestHttpRequest } from "./test-http-request.mjs";
2
+ import { TestingModule } from "../testing-module.mjs";
3
+
4
+ //#region src/core/http/test-http-client.d.ts
5
+ /**
6
+ * TestHttpClient
7
+ *
8
+ * Fluent HTTP client for making test requests.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const response = await module.http
13
+ * .forHost('example.com')
14
+ * .post('/api/v1/users')
15
+ * .withBody({ name: 'Test' })
16
+ * .send()
17
+ *
18
+ * response.assertCreated()
19
+ * ```
20
+ */
21
+ declare class TestHttpClient {
22
+ private readonly module;
23
+ private defaultHeaders;
24
+ private host;
25
+ constructor(module: TestingModule);
26
+ /**
27
+ * Set the host for the request
28
+ */
29
+ forHost(host: string): this;
30
+ /**
31
+ * Set default headers for all requests
32
+ */
33
+ withHeaders(headers: Record<string, string>): this;
34
+ /**
35
+ * Create a GET request
36
+ */
37
+ get(path: string): TestHttpRequest;
38
+ /**
39
+ * Create a POST request
40
+ */
41
+ post(path: string): TestHttpRequest;
42
+ /**
43
+ * Create a PUT request
44
+ */
45
+ put(path: string): TestHttpRequest;
46
+ /**
47
+ * Create a PATCH request
48
+ */
49
+ patch(path: string): TestHttpRequest;
50
+ /**
51
+ * Create a DELETE request
52
+ */
53
+ delete(path: string): TestHttpRequest;
54
+ private createRequest;
55
+ }
56
+ //#endregion
57
+ export { TestHttpClient };
58
+ //# sourceMappingURL=test-http-client.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-http-client.d.mts","names":[],"sources":["../../../src/core/http/test-http-client.ts"],"mappings":";;;;;;AAmBA;;;;;;;;;;;;;;cAAa,cAAA;EAAA,iBAIkB,MAAA;EAAA,QAHrB,cAAA;EAAA,QACA,IAAA;cAEqB,MAAA,EAAQ,aAAA;EAK7B;;;EAAR,OAAA,CAAQ,IAAA;EAkBR;;;EAVA,WAAA,CAAY,OAAA,EAAS,MAAA;EAiBhB;;;EAPL,GAAA,CAAI,IAAA,WAAe,eAAA;EAcA;;;EAPnB,IAAA,CAAK,IAAA,WAAe,eAAA;EAqBpB;;;EAdA,GAAA,CAAI,IAAA,WAAe,eAAA;EAkBE;;;EAXrB,KAAA,CAAM,IAAA,WAAe,eAAA;;;;EAOrB,MAAA,CAAO,IAAA,WAAe,eAAA;EAAA,QAId,aAAA;AAAA"}
@@ -0,0 +1,76 @@
1
+ import { TestHttpRequest } from "./test-http-request.mjs";
2
+ //#region src/core/http/test-http-client.ts
3
+ /**
4
+ * TestHttpClient
5
+ *
6
+ * Fluent HTTP client for making test requests.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const response = await module.http
11
+ * .forHost('example.com')
12
+ * .post('/api/v1/users')
13
+ * .withBody({ name: 'Test' })
14
+ * .send()
15
+ *
16
+ * response.assertCreated()
17
+ * ```
18
+ */
19
+ var TestHttpClient = class {
20
+ defaultHeaders = new Headers();
21
+ host = null;
22
+ constructor(module) {
23
+ this.module = module;
24
+ }
25
+ /**
26
+ * Set the host for the request
27
+ */
28
+ forHost(host) {
29
+ this.host = host;
30
+ return this;
31
+ }
32
+ /**
33
+ * Set default headers for all requests
34
+ */
35
+ withHeaders(headers) {
36
+ for (const [key, value] of Object.entries(headers)) this.defaultHeaders.set(key, value);
37
+ return this;
38
+ }
39
+ /**
40
+ * Create a GET request
41
+ */
42
+ get(path) {
43
+ return this.createRequest("GET", path);
44
+ }
45
+ /**
46
+ * Create a POST request
47
+ */
48
+ post(path) {
49
+ return this.createRequest("POST", path);
50
+ }
51
+ /**
52
+ * Create a PUT request
53
+ */
54
+ put(path) {
55
+ return this.createRequest("PUT", path);
56
+ }
57
+ /**
58
+ * Create a PATCH request
59
+ */
60
+ patch(path) {
61
+ return this.createRequest("PATCH", path);
62
+ }
63
+ /**
64
+ * Create a DELETE request
65
+ */
66
+ delete(path) {
67
+ return this.createRequest("DELETE", path);
68
+ }
69
+ createRequest(method, path) {
70
+ return new TestHttpRequest(method, path, this.defaultHeaders, this.module, this.host);
71
+ }
72
+ };
73
+ //#endregion
74
+ export { TestHttpClient };
75
+
76
+ //# sourceMappingURL=test-http-client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-http-client.mjs","names":[],"sources":["../../../src/core/http/test-http-client.ts"],"sourcesContent":["import type { TestingModule } from '../testing-module'\nimport { TestHttpRequest } from './test-http-request'\n\n/**\n * TestHttpClient\n *\n * Fluent HTTP client for making test requests.\n *\n * @example\n * ```typescript\n * const response = await module.http\n * .forHost('example.com')\n * .post('/api/v1/users')\n * .withBody({ name: 'Test' })\n * .send()\n *\n * response.assertCreated()\n * ```\n */\nexport class TestHttpClient {\n private defaultHeaders: Headers = new Headers()\n private host: string | null = null\n\n constructor(private readonly module: TestingModule) { }\n\n /**\n * Set the host for the request\n */\n forHost(host: string): this {\n this.host = host\n return this\n }\n\n /**\n * Set default headers for all requests\n */\n withHeaders(headers: Record<string, string>): this {\n for (const [key, value] of Object.entries(headers)) {\n this.defaultHeaders.set(key, value)\n }\n return this\n }\n\n /**\n * Create a GET request\n */\n get(path: string): TestHttpRequest {\n return this.createRequest('GET', path)\n }\n\n /**\n * Create a POST request\n */\n post(path: string): TestHttpRequest {\n return this.createRequest('POST', path)\n }\n\n /**\n * Create a PUT request\n */\n put(path: string): TestHttpRequest {\n return this.createRequest('PUT', path)\n }\n\n /**\n * Create a PATCH request\n */\n patch(path: string): TestHttpRequest {\n return this.createRequest('PATCH', path)\n }\n\n /**\n * Create a DELETE request\n */\n delete(path: string): TestHttpRequest {\n return this.createRequest('DELETE', path)\n }\n\n private createRequest(method: string, path: string): TestHttpRequest {\n return new TestHttpRequest(method, path, this.defaultHeaders, this.module, this.host)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,IAAa,iBAAb,MAA4B;CAC1B,iBAAkC,IAAI,SAAS;CAC/C,OAA8B;CAE9B,YAAY,QAAwC;AAAvB,OAAA,SAAA;;;;;CAK7B,QAAQ,MAAoB;AAC1B,OAAK,OAAO;AACZ,SAAO;;;;;CAMT,YAAY,SAAuC;AACjD,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,CAChD,MAAK,eAAe,IAAI,KAAK,MAAM;AAErC,SAAO;;;;;CAMT,IAAI,MAA+B;AACjC,SAAO,KAAK,cAAc,OAAO,KAAK;;;;;CAMxC,KAAK,MAA+B;AAClC,SAAO,KAAK,cAAc,QAAQ,KAAK;;;;;CAMzC,IAAI,MAA+B;AACjC,SAAO,KAAK,cAAc,OAAO,KAAK;;;;;CAMxC,MAAM,MAA+B;AACnC,SAAO,KAAK,cAAc,SAAS,KAAK;;;;;CAM1C,OAAO,MAA+B;AACpC,SAAO,KAAK,cAAc,UAAU,KAAK;;CAG3C,cAAsB,QAAgB,MAA+B;AACnE,SAAO,IAAI,gBAAgB,QAAQ,MAAM,KAAK,gBAAgB,KAAK,QAAQ,KAAK,KAAK"}