@stratal/testing 0.0.2 → 0.0.5

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 (106) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/dist/auth/acting-as.d.ts +21 -0
  3. package/dist/auth/acting-as.d.ts.map +1 -0
  4. package/dist/auth/acting-as.js +68 -0
  5. package/dist/auth/acting-as.js.map +1 -0
  6. package/dist/auth/index.d.ts +2 -0
  7. package/dist/auth/index.d.ts.map +1 -0
  8. package/dist/auth/index.js +2 -0
  9. package/dist/auth/index.js.map +1 -0
  10. package/dist/core/env/index.d.ts +2 -0
  11. package/dist/core/env/index.d.ts.map +1 -0
  12. package/dist/core/env/index.js +2 -0
  13. package/dist/core/env/index.js.map +1 -0
  14. package/dist/core/env/test-env.d.ts +9 -0
  15. package/dist/core/env/test-env.d.ts.map +1 -0
  16. package/dist/core/env/test-env.js +14 -0
  17. package/dist/core/env/test-env.js.map +1 -0
  18. package/dist/core/http/fetch-mock.d.ts +236 -0
  19. package/dist/core/http/fetch-mock.d.ts.map +1 -0
  20. package/dist/core/http/fetch-mock.js +290 -0
  21. package/dist/core/http/fetch-mock.js.map +1 -0
  22. package/dist/core/http/fetch-mock.types.d.ts +48 -0
  23. package/dist/core/http/fetch-mock.types.d.ts.map +1 -0
  24. package/dist/core/http/fetch-mock.types.js +2 -0
  25. package/dist/core/http/fetch-mock.types.js.map +1 -0
  26. package/dist/core/http/index.d.ts +6 -0
  27. package/dist/core/http/index.d.ts.map +1 -0
  28. package/dist/core/http/index.js +5 -0
  29. package/dist/core/http/index.js.map +1 -0
  30. package/dist/core/http/test-http-client.d.ts +54 -0
  31. package/dist/core/http/test-http-client.d.ts.map +1 -0
  32. package/dist/core/http/test-http-client.js +75 -0
  33. package/dist/core/http/test-http-client.js.map +1 -0
  34. package/dist/core/http/test-http-request.d.ts +60 -0
  35. package/dist/core/http/test-http-request.d.ts.map +1 -0
  36. package/dist/core/http/test-http-request.js +106 -0
  37. package/dist/core/http/test-http-request.js.map +1 -0
  38. package/dist/core/http/test-response.d.ts +161 -0
  39. package/dist/core/http/test-response.d.ts.map +1 -0
  40. package/dist/core/http/test-response.js +309 -0
  41. package/dist/core/http/test-response.js.map +1 -0
  42. package/dist/core/index.d.ts +7 -0
  43. package/dist/core/index.d.ts.map +1 -0
  44. package/dist/core/index.js +7 -0
  45. package/dist/core/index.js.map +1 -0
  46. package/dist/core/override/index.d.ts +2 -0
  47. package/dist/core/override/index.d.ts.map +1 -0
  48. package/dist/core/override/index.js +2 -0
  49. package/dist/core/override/index.js.map +1 -0
  50. package/dist/core/override/provider-override-builder.d.ts +77 -0
  51. package/dist/core/override/provider-override-builder.d.ts.map +1 -0
  52. package/dist/core/override/provider-override-builder.js +94 -0
  53. package/dist/core/override/provider-override-builder.js.map +1 -0
  54. package/dist/core/test.d.ts +48 -0
  55. package/dist/core/test.d.ts.map +1 -0
  56. package/dist/core/test.js +53 -0
  57. package/dist/core/test.js.map +1 -0
  58. package/dist/core/testing-module-builder.d.ts +99 -0
  59. package/dist/core/testing-module-builder.d.ts.map +1 -0
  60. package/dist/core/testing-module-builder.js +156 -0
  61. package/dist/core/testing-module-builder.js.map +1 -0
  62. package/dist/core/testing-module.d.ts +101 -0
  63. package/dist/core/testing-module.d.ts.map +1 -0
  64. package/dist/core/testing-module.js +178 -0
  65. package/dist/core/testing-module.js.map +1 -0
  66. package/dist/errors/index.d.ts +3 -0
  67. package/dist/errors/index.d.ts.map +1 -0
  68. package/dist/errors/index.js +3 -0
  69. package/dist/errors/index.js.map +1 -0
  70. package/dist/errors/setup-error.d.ts +9 -0
  71. package/dist/errors/setup-error.d.ts.map +1 -0
  72. package/dist/errors/setup-error.js +11 -0
  73. package/dist/errors/setup-error.js.map +1 -0
  74. package/dist/errors/test-error.d.ts +9 -0
  75. package/dist/errors/test-error.d.ts.map +1 -0
  76. package/dist/errors/test-error.js +15 -0
  77. package/dist/errors/test-error.js.map +1 -0
  78. package/dist/index.d.ts +15 -0
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +6 -3
  81. package/dist/index.js.map +1 -1
  82. package/dist/mocks/index.d.ts +3 -0
  83. package/dist/mocks/index.d.ts.map +1 -0
  84. package/dist/mocks/index.js +3 -0
  85. package/dist/mocks/index.js.map +1 -0
  86. package/dist/mocks/nodemailer.d.ts +10 -0
  87. package/dist/mocks/nodemailer.d.ts.map +1 -0
  88. package/dist/mocks/nodemailer.js +9 -0
  89. package/dist/mocks/nodemailer.js.map +1 -0
  90. package/dist/mocks/zenstack-language.d.ts +46 -0
  91. package/dist/mocks/zenstack-language.d.ts.map +1 -0
  92. package/dist/mocks/zenstack-language.js +47 -0
  93. package/dist/mocks/zenstack-language.js.map +1 -0
  94. package/dist/storage/fake-storage.service.d.ts +114 -0
  95. package/dist/storage/fake-storage.service.d.ts.map +1 -0
  96. package/dist/storage/fake-storage.service.js +233 -0
  97. package/dist/storage/fake-storage.service.js.map +1 -0
  98. package/dist/storage/index.d.ts +2 -0
  99. package/dist/storage/index.d.ts.map +1 -0
  100. package/dist/storage/index.js +2 -0
  101. package/dist/storage/index.js.map +1 -0
  102. package/dist/types.d.ts +5 -0
  103. package/dist/types.d.ts.map +1 -0
  104. package/dist/types.js +3 -0
  105. package/dist/types.js.map +1 -0
  106. package/package.json +27 -10
package/CHANGELOG.md ADDED
@@ -0,0 +1,117 @@
1
+ # @stratal/testing
2
+
3
+ ## 0.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [#66](https://github.com/strataljs/stratal/pull/66) [`c8ea964`](https://github.com/strataljs/stratal/commit/c8ea964e272b09ebc6619843e77d2b51178f9423) Thanks [@adesege](https://github.com/adesege)! - Add `actingAs` auth test helper, `TestHttpRequest` builder, ZenStack language mock, and enhanced `TestingModule` utilities with new exports and types.
8
+
9
+ - Updated dependencies [[`c8ea964`](https://github.com/strataljs/stratal/commit/c8ea964e272b09ebc6619843e77d2b51178f9423), [`c8ea964`](https://github.com/strataljs/stratal/commit/c8ea964e272b09ebc6619843e77d2b51178f9423)]:
10
+ - stratal@0.0.5
11
+ - @stratal/framework@0.0.5
12
+
13
+ ## 0.0.4
14
+
15
+ ### Patch Changes
16
+
17
+ - **Build cleanup** — Removed redundant polyfills export and cleaned up the build configuration.
18
+ - **Relaxed vitest version** — Loosened the vitest peer dependency version constraint.
19
+
20
+ - Updated dependencies []:
21
+ - stratal@0.0.4
22
+
23
+ ## 0.0.3
24
+
25
+ ### Patch Changes
26
+
27
+ - - **Build cleanup** — Removed redundant polyfills export and cleaned up the build configuration.
28
+ - **Relaxed vitest version** — Loosened the vitest peer dependency version constraint.
29
+ - Updated dependencies []:
30
+ - stratal@0.0.3
31
+
32
+ ## 0.0.2
33
+
34
+ ### Patch Changes
35
+
36
+ #### `stratal` (core)
37
+
38
+ ##### Breaking Changes
39
+
40
+ - **`withRoot`/`withRootAsync` renamed to `forRoot`/`forRootAsync`** — All dynamic module configuration methods have been renamed for consistency. Update every `SomeModule.withRoot(...)` call to `SomeModule.forRoot(...)` and `SomeModule.withRootAsync(...)` to `SomeModule.forRootAsync(...)`. ([`152913a`](https://github.com/strataljs/stratal/commit/152913a))
41
+
42
+ - **Barrel export removed — use sub-path imports** — The top-level `stratal` barrel export has been removed. Consumers must now import from sub-paths (`stratal/di`, `stratal/router`, `stratal/cache`, `stratal/validation`, etc.). ([`af073d8`](https://github.com/strataljs/stratal/commit/af073d8))
43
+
44
+ ##### Features
45
+
46
+ - **DOM polyfill for Cloudflare Workers** — Added a DOM polyfill to support AWS SDK v3 XML parsing in Cloudflare Workers environments. ([`f3b2cb9`](https://github.com/strataljs/stratal/commit/f3b2cb9))
47
+
48
+ - **Benchmark suite** — Added benchmark functionality for measuring framework performa30438`](https://github.com/strataljs/stratal/commit/7230438))
49
+
50
+ ##### Security
51
+
52
+ - **ConfigService blocks prototype pollution** — `ConfigService` now rejects dangerous keys (`__proto__`, `constructor`, `prototype`) to prevent prototype pollution attacks. ([`567139c`](https://github.com/strataljs/stratal/commit/567139c), [`e64b4e7`](https://github.com/strataljs/stratal/commit/e64b4e7))
53
+
54
+ ##### Bug Fixes
55
+
56
+ - **`reflect-metadata` import moved to vitest setup** — Removed unused `reflect-metadata` imports from example files and centralized the import in `vitest.setup.ts`. ([`f3b2cb9`](https://github.com/strataljs/stratal/commit/f3b2cb9))
57
+
58
+ ---
59
+
60
+ #### `@stratal/testing`
61
+
62
+ ##### Breaking Changes
63
+
64
+ - **Import paths updated** — Import paths updated to match the new core sub-path exports (e.g. `stratal/di` instead of the barrel `stratal`). ([`af073d8`](https://github.com/strataljs/stratal/commit/af073d8))
65
+
66
+ - Updated dependencies []:
67
+ - @stratal/testing@0.0.2
68
+
69
+ ## 0.0.1
70
+
71
+ ### Patch Changes
72
+
73
+ - Initial release of the Stratal framework — a modular Cloudflare Workers framework built on Hono and tsyringe.
74
+
75
+ **Core Infrastructure**
76
+
77
+ - NestJS-style module system with `@Module()` decorator, dynamic modules (`forRoot`, `forRootAsync`), and lifecycle hooks (`OnInitialize`, `OnShutdown`)
78
+ - Two-tier dependency injection container (global singletons + request-scoped) powered by tsyringe with conditional registration and service decoration
79
+ - `StratalWorker` entry point extending Cloudflare's `WorkerEntrypoint` for HTTP fetch, queue batches, and scheduled cron triggers
80
+
81
+ **Routing & API**
82
+
83
+ - Hono-based routing with `@Controller()` and `@Route()` decorators, automatic controller discovery, and route guards via `@UseGuards()`
84
+ - OpenAPI schema generation with `@hono/zod-openapi` and Scalar API reference integration
85
+ - NestJS-like middleware configuration with route-specific application and exclusion
86
+
87
+ **Background Processing**
88
+
89
+ - Queue consumerfor Cloudflare Queues with `@Consumer()` and `@QueueJob()` decorators and batch processing
90
+ - Cron job scheduling via `CronManager` integrated with Cloudflare's scheduled events
91
+
92
+ **Services & Integrations**
93
+
94
+ - Email module with pluggable providers (Nodemailer, Resend) and queue-based sending
95
+ - Storage module with AWS S3 / Cloudflare R2 support, multipart uploads, presigned URLs, and TUS resumable uploads
96
+ - Internationalization (i18n) module with locale detection, message compilation, and request-scoped translations
97
+ - Cache module with pluggable providers and Cloudflare KV integration
98
+ - Configuration module with `registerAs()` namespaces and Zod-based validation
99
+ - Structured logging with JSON and pretty formatters
100
+
101
+ **Developer Experience**
102
+
103
+ - Zod-powered request/response validation with type inference
104
+ - Custom `ApplicationError` class with HTTP status mapping
105
+ - ESM-only with full TypeScript decorator support (`emitDecoratorMetadata`)
106
+ - Sub-path exports for tree-shakeable imports (`stratal/di`, `stratal/router`, `stratal/cache`, etc.)
107
+
108
+ - `TestingModule` and `TestingModuleBuilder` for bootstrapping isolated module environments in tests
109
+ - `TestHttpClient` with request builder and response wrapper for integration testing
110
+ - `FetchMock` for mocking HTTP fetch calls
111
+ - `FakeStorageService` for in-memory storage testing without S3/R2
112
+ - `ProviderOverrideBuilder` for replacing providers with test doubles
113
+ - Nodemailer mock for email testing
114
+ - Test environment utilities via `getTestEnv()`
115
+
116
+ - Updated dependencies []:
117
+ - stratal@0.0.1
@@ -0,0 +1,21 @@
1
+ import type { AuthService } from '@stratal/framework/auth';
2
+ /**
3
+ * ActingAs
4
+ *
5
+ * Creates authentication sessions for testing.
6
+ * Uses Better Auth's internalAdapter to create real database sessions.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const actingAs = new ActingAs(authService)
11
+ * const headers = await actingAs.createSessionForUser({ id: 'user-123' })
12
+ * ```
13
+ */
14
+ export declare class ActingAs {
15
+ private readonly authService;
16
+ constructor(authService: AuthService);
17
+ createSessionForUser(user: {
18
+ id: string;
19
+ }): Promise<Headers>;
20
+ }
21
+ //# sourceMappingURL=acting-as.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acting-as.d.ts","sourceRoot":"","sources":["../../src/auth/acting-as.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAwB1D;;;;;;;;;;;GAWG;AACH,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,WAAW;IAE/C,oBAAoB,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;CAkCnE"}
@@ -0,0 +1,68 @@
1
+ import { setSessionCookie } from 'better-auth/cookies';
2
+ import { convertSetCookieToCookie } from 'better-auth/test';
3
+ async function makeSignature(value, secret) {
4
+ const algorithm = { name: 'HMAC', hash: 'SHA-256' };
5
+ const secretBuf = new TextEncoder().encode(secret);
6
+ const key = await crypto.subtle.importKey('raw', secretBuf, algorithm, false, ['sign']);
7
+ const signature = await crypto.subtle.sign(algorithm.name, key, new TextEncoder().encode(value));
8
+ return btoa(String.fromCharCode(...new Uint8Array(signature)));
9
+ }
10
+ function buildCookieString(name, value, options = {}) {
11
+ const encodedValue = encodeURIComponent(value);
12
+ let str = `${name}=${encodedValue}`;
13
+ if (options.path)
14
+ str += `; Path=${options.path}`;
15
+ if (options.httpOnly)
16
+ str += '; HttpOnly';
17
+ if (options.secure)
18
+ str += '; Secure';
19
+ if (options.sameSite)
20
+ str += `; SameSite=${options.sameSite}`;
21
+ if (options.maxAge !== undefined)
22
+ str += `; Max-Age=${Math.floor(options.maxAge)}`;
23
+ return str;
24
+ }
25
+ /**
26
+ * ActingAs
27
+ *
28
+ * Creates authentication sessions for testing.
29
+ * Uses Better Auth's internalAdapter to create real database sessions.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const actingAs = new ActingAs(authService)
34
+ * const headers = await actingAs.createSessionForUser({ id: 'user-123' })
35
+ * ```
36
+ */
37
+ export class ActingAs {
38
+ authService;
39
+ constructor(authService) {
40
+ this.authService = authService;
41
+ }
42
+ async createSessionForUser(user) {
43
+ const auth = this.authService.auth;
44
+ const ctx = await auth.$context;
45
+ const secret = ctx.secret;
46
+ const session = await ctx.internalAdapter.createSession(user.id, undefined, { ipAddress: '127.0.0.1', userAgent: 'test-client' });
47
+ const dbUser = await ctx.internalAdapter.findUserById(user.id);
48
+ if (!dbUser) {
49
+ throw new Error(`User not found: ${user.id}`);
50
+ }
51
+ const responseHeaders = new Headers();
52
+ const mockCtx = {
53
+ context: ctx,
54
+ getSignedCookie: () => null,
55
+ setSignedCookie: async (name, value, _secret, options = {}) => {
56
+ const signature = await makeSignature(value, secret);
57
+ const signedValue = `${value}.${signature}`;
58
+ responseHeaders.append('Set-Cookie', buildCookieString(name, signedValue, options));
59
+ },
60
+ setCookie: (name, value, options = {}) => {
61
+ responseHeaders.append('Set-Cookie', buildCookieString(name, value, options));
62
+ },
63
+ };
64
+ await setSessionCookie(mockCtx, { session, user: dbUser }, false);
65
+ return convertSetCookieToCookie(responseHeaders);
66
+ }
67
+ }
68
+ //# sourceMappingURL=acting-as.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acting-as.js","sourceRoot":"","sources":["../../src/auth/acting-as.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { ActingAs } from './acting-as';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { ActingAs } from './acting-as';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { getTestEnv } from './test-env';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/env/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { getTestEnv } from './test-env';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/env/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type StratalEnv } from 'stratal';
2
+ /**
3
+ * Get test environment with optional overrides
4
+ *
5
+ * @param overrides - Optional partial env to merge with cloudflare:test env
6
+ * @returns Complete Env object for testing
7
+ */
8
+ export declare function getTestEnv(overrides?: Partial<StratalEnv>): StratalEnv;
9
+ //# sourceMappingURL=test-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-env.d.ts","sourceRoot":"","sources":["../../../src/core/env/test-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAA;AAGzC;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAKtE"}
@@ -0,0 +1,14 @@
1
+ import { env as cloudflareEnv } from 'cloudflare:test';
2
+ /**
3
+ * Get test environment with optional overrides
4
+ *
5
+ * @param overrides - Optional partial env to merge with cloudflare:test env
6
+ * @returns Complete Env object for testing
7
+ */
8
+ export function getTestEnv(overrides) {
9
+ return {
10
+ ...cloudflareEnv,
11
+ ...overrides,
12
+ };
13
+ }
14
+ //# sourceMappingURL=test-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-env.js","sourceRoot":"","sources":["../../../src/core/env/test-env.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,SAA+B;IACxD,OAAO;QACL,GAAG,aAAa;QAChB,GAAG,SAAS;KACC,CAAA;AACjB,CAAC"}
@@ -0,0 +1,236 @@
1
+ import type { MockJsonOptions, MockErrorOptions } from './fetch-mock.types';
2
+ /**
3
+ * Wrapper around Cloudflare's fetchMock for declarative fetch mocking in tests
4
+ *
5
+ * Based on undici's MockAgent, fetchMock.get(origin) returns a MockPool for that origin.
6
+ * The MockPool's intercept() method is used to define which requests to mock.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createFetchMock } from '@stratal/testing'
11
+ *
12
+ * const mock = createFetchMock()
13
+ *
14
+ * beforeEach(() => {
15
+ * mock.activate()
16
+ * mock.disableNetConnect()
17
+ * })
18
+ *
19
+ * afterEach(() => {
20
+ * mock.reset()
21
+ * })
22
+ *
23
+ * it('should mock external API', async () => {
24
+ * // Using helper method
25
+ * mock.mockJsonResponse('https://api.example.com/data', { success: true })
26
+ *
27
+ * // Or using direct API
28
+ * mock.get('https://api.example.com')
29
+ * .intercept({ path: '/users', method: 'POST' })
30
+ * .reply(201, JSON.stringify({ created: true }))
31
+ *
32
+ * const response = await fetch('https://api.example.com/data')
33
+ * const json = await response.json()
34
+ *
35
+ * expect(json.success).toBe(true)
36
+ * mock.assertNoPendingInterceptors()
37
+ * })
38
+ * ```
39
+ */
40
+ export declare class FetchMock {
41
+ /**
42
+ * Get a MockPool for the specified origin
43
+ *
44
+ * This is the underlying fetchMock.get() method that returns a MockPool
45
+ * for mocking requests to the specified origin.
46
+ *
47
+ * @param origin - The origin URL (e.g., 'https://api.example.com')
48
+ * @returns MockPool for chaining .intercept() and .reply()
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * // Mock a GET request
53
+ * mock.get('https://api.example.com')
54
+ * .intercept({ path: '/users', method: 'GET' })
55
+ * .reply(200, JSON.stringify({ users: [] }))
56
+ *
57
+ * // Mock a POST request with body matching
58
+ * mock.get('https://api.example.com')
59
+ * .intercept({
60
+ * path: '/users',
61
+ * method: 'POST',
62
+ * body: (body) => body.includes('test')
63
+ * })
64
+ * .reply(201, JSON.stringify({ created: true }))
65
+ * ```
66
+ */
67
+ get(origin: string): import("cloudflare:test").Interceptable;
68
+ /**
69
+ * Activate fetch mocking for the current test
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * beforeEach(() => {
74
+ * mock.activate()
75
+ * })
76
+ * ```
77
+ */
78
+ activate(): void;
79
+ /**
80
+ * Deactivate fetch mocking
81
+ */
82
+ deactivate(): void;
83
+ /**
84
+ * Disable all network connections, forcing all requests to use mocks
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * beforeEach(() => {
89
+ * mock.activate()
90
+ * mock.disableNetConnect() // Ensure all requests are mocked
91
+ * })
92
+ * ```
93
+ */
94
+ disableNetConnect(): void;
95
+ /**
96
+ * Enable network connections for specific hosts
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * mock.enableNetConnect('localhost')
101
+ * mock.enableNetConnect(/^https:\/\/trusted\.com/)
102
+ * ```
103
+ */
104
+ enableNetConnect(host?: string | RegExp): void;
105
+ /**
106
+ * Assert that all defined interceptors were called
107
+ *
108
+ * @throws {Error} If there are pending interceptors that weren't matched
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * it('should call all mocked endpoints', async () => {
113
+ * mock.mockJsonResponse('https://api.example.com/data', { data: [] })
114
+ *
115
+ * await fetch('https://api.example.com/data')
116
+ *
117
+ * mock.assertNoPendingInterceptors() // Pass
118
+ * })
119
+ * ```
120
+ */
121
+ assertNoPendingInterceptors(): void;
122
+ /**
123
+ * Reset all mocks and interceptors
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * afterEach(() => {
128
+ * mock.reset()
129
+ * })
130
+ * ```
131
+ */
132
+ reset(): void;
133
+ /**
134
+ * Helper method to mock JSON responses
135
+ *
136
+ * Automatically parses the URL into origin and path, and sets up the mock.
137
+ *
138
+ * @param url - Full URL to mock (e.g., 'https://api.example.com/users')
139
+ * @param data - JSON data to return
140
+ * @param options - Additional options for the mock
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * // Mock a GET request
145
+ * mock.mockJsonResponse('https://api.example.com/users', { users: [] })
146
+ *
147
+ * // Mock a POST request
148
+ * mock.mockJsonResponse(
149
+ * 'https://api.example.com/users',
150
+ * { created: true },
151
+ * { method: 'POST', status: 201 }
152
+ * )
153
+ *
154
+ * // With custom headers and delay
155
+ * mock.mockJsonResponse(
156
+ * 'https://api.example.com/users',
157
+ * { users: [] },
158
+ * {
159
+ * status: 200,
160
+ * method: 'GET',
161
+ * headers: { 'X-Custom': 'value' },
162
+ * delay: 100
163
+ * }
164
+ * )
165
+ * ```
166
+ */
167
+ mockJsonResponse(url: string, data: unknown, options?: MockJsonOptions): import("cloudflare:test").MockScope<object>;
168
+ /**
169
+ * Helper method to mock error responses
170
+ *
171
+ * @param url - Full URL to mock
172
+ * @param status - HTTP error status code
173
+ * @param message - Optional error message
174
+ * @param options - Additional options for the error mock
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * // Mock a 401 error
179
+ * mock.mockError('https://api.example.com/fail', 401, 'Unauthorized')
180
+ *
181
+ * // Mock a 500 error with custom method
182
+ * mock.mockError(
183
+ * 'https://api.example.com/fail',
184
+ * 500,
185
+ * 'Server Error',
186
+ * { method: 'POST' }
187
+ * )
188
+ * ```
189
+ */
190
+ mockError(url: string, status: number, message?: string, options?: MockErrorOptions): import("cloudflare:test").MockScope<object>;
191
+ /**
192
+ * Generic helper to mock any HTTP request
193
+ *
194
+ * @param origin - The origin URL (e.g., 'https://api.example.com')
195
+ * @param options - Request matching and response options
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * mock.mockRequest('https://api.example.com', {
200
+ * path: '/users',
201
+ * method: 'PUT',
202
+ * status: 200,
203
+ * body: { updated: true }
204
+ * })
205
+ * ```
206
+ */
207
+ mockRequest(origin: string, options: {
208
+ path: string;
209
+ method?: string;
210
+ status?: number;
211
+ body?: unknown;
212
+ }): import("cloudflare:test").MockScope<object>;
213
+ }
214
+ /**
215
+ * Factory function to create a new FetchMock instance
216
+ *
217
+ * @returns A new FetchMock instance
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * import { createFetchMock } from '@stratal/testing'
222
+ *
223
+ * const mock = createFetchMock()
224
+ *
225
+ * beforeEach(() => {
226
+ * mock.activate()
227
+ * mock.disableNetConnect()
228
+ * })
229
+ *
230
+ * afterEach(() => {
231
+ * mock.reset()
232
+ * })
233
+ * ```
234
+ */
235
+ export declare function createFetchMock(): FetchMock;
236
+ //# sourceMappingURL=fetch-mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-mock.d.ts","sourceRoot":"","sources":["../../../src/core/http/fetch-mock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,qBAAa,SAAS;IACrB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM;IAIlB;;;;;;;;;OASG;IACH,QAAQ;IAIR;;OAEG;IACH,UAAU;IAIV;;;;;;;;;;OAUG;IACH,iBAAiB;IAIjB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAOvC;;;;;;;;;;;;;;;OAeG;IACH,2BAA2B;IAI3B;;;;;;;;;OASG;IACH,KAAK;IAKL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB;IAwB1E;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAkBvF;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CACV,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE;CAS5E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAE3C"}