@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.
- package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.mjs +9 -0
- package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorateMetadata.mjs +6 -0
- package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorateParam.mjs +8 -0
- package/dist/auth/acting-as.d.mts +25 -0
- package/dist/auth/acting-as.d.mts.map +1 -0
- package/dist/auth/acting-as.mjs +69 -0
- package/dist/auth/acting-as.mjs.map +1 -0
- package/dist/auth/index.d.mts +1 -0
- package/dist/auth/index.mjs +2 -0
- package/dist/core/env/index.d.mts +1 -0
- package/dist/core/env/index.mjs +2 -0
- package/dist/core/env/test-env.d.mts +13 -0
- package/dist/core/env/test-env.d.mts.map +1 -0
- package/dist/core/env/test-env.mjs +18 -0
- package/dist/core/env/test-env.mjs.map +1 -0
- package/dist/core/http/fetch-mock.types.d.mts +51 -0
- package/dist/core/http/fetch-mock.types.d.mts.map +1 -0
- package/dist/core/http/mock-fetch.d.mts +92 -0
- package/dist/core/http/mock-fetch.d.mts.map +1 -0
- package/dist/core/http/mock-fetch.mjs +117 -0
- package/dist/core/http/mock-fetch.mjs.map +1 -0
- package/dist/core/http/test-http-client.d.mts +58 -0
- package/dist/core/http/test-http-client.d.mts.map +1 -0
- package/dist/core/http/test-http-client.mjs +76 -0
- package/dist/core/http/test-http-client.mjs.map +1 -0
- package/dist/core/http/test-http-request.d.mts +64 -0
- package/dist/core/http/test-http-request.d.mts.map +1 -0
- package/dist/core/http/test-http-request.mjs +95 -0
- package/dist/core/http/test-http-request.mjs.map +1 -0
- package/dist/core/http/test-response.d.mts +164 -0
- package/dist/core/http/test-response.d.mts.map +1 -0
- package/dist/core/http/test-response.mjs +282 -0
- package/dist/core/http/test-response.mjs.map +1 -0
- package/dist/core/override/index.d.mts +1 -0
- package/dist/core/override/provider-override-builder.d.mts +82 -0
- package/dist/core/override/provider-override-builder.d.mts.map +1 -0
- package/dist/core/override/provider-override-builder.mjs +96 -0
- package/dist/core/override/provider-override-builder.mjs.map +1 -0
- package/dist/core/quarry/test-command-request.d.mts +36 -0
- package/dist/core/quarry/test-command-request.d.mts.map +1 -0
- package/dist/core/quarry/test-command-request.mjs +40 -0
- package/dist/core/quarry/test-command-request.mjs.map +1 -0
- package/dist/core/quarry/test-command-result.d.mts +34 -0
- package/dist/core/quarry/test-command-result.d.mts.map +1 -0
- package/dist/core/quarry/test-command-result.mjs +64 -0
- package/dist/core/quarry/test-command-result.mjs.map +1 -0
- package/dist/core/sse/test-sse-connection.d.mts +64 -0
- package/dist/core/sse/test-sse-connection.d.mts.map +1 -0
- package/dist/core/sse/test-sse-connection.mjs +198 -0
- package/dist/core/sse/test-sse-connection.mjs.map +1 -0
- package/dist/core/sse/test-sse-request.d.mts +46 -0
- package/dist/core/sse/test-sse-request.d.mts.map +1 -0
- package/dist/core/sse/test-sse-request.mjs +71 -0
- package/dist/core/sse/test-sse-request.mjs.map +1 -0
- package/dist/core/test.d.mts +52 -0
- package/dist/core/test.d.mts.map +1 -0
- package/dist/core/test.mjs +57 -0
- package/dist/core/test.mjs.map +1 -0
- package/dist/core/testing-module-builder.d.mts +61 -0
- package/dist/core/testing-module-builder.d.mts.map +1 -0
- package/dist/core/testing-module-builder.mjs +102 -0
- package/dist/core/testing-module-builder.mjs.map +1 -0
- package/dist/core/testing-module.d.mts +121 -0
- package/dist/core/testing-module.d.mts.map +1 -0
- package/dist/core/testing-module.mjs +170 -0
- package/dist/core/testing-module.mjs.map +1 -0
- package/dist/core/ws/test-ws-connection.d.mts +57 -0
- package/dist/core/ws/test-ws-connection.d.mts.map +1 -0
- package/dist/core/ws/test-ws-connection.mjs +111 -0
- package/dist/core/ws/test-ws-connection.mjs.map +1 -0
- package/dist/core/ws/test-ws-request.d.mts +47 -0
- package/dist/core/ws/test-ws-request.d.mts.map +1 -0
- package/dist/core/ws/test-ws-request.mjs +76 -0
- package/dist/core/ws/test-ws-request.mjs.map +1 -0
- package/dist/errors/setup-error.d.mts +13 -0
- package/dist/errors/setup-error.d.mts.map +1 -0
- package/dist/errors/setup-error.mjs +15 -0
- package/dist/errors/setup-error.mjs.map +1 -0
- package/dist/errors/test-error.d.mts +12 -0
- package/dist/errors/test-error.d.mts.map +1 -0
- package/dist/errors/test-error.mjs +17 -0
- package/dist/errors/test-error.mjs.map +1 -0
- package/dist/index.d.mts +21 -1016
- package/dist/index.mjs +21 -1588
- package/dist/{index-D-Q2cR2v.d.mts → storage/fake-storage.service.d.mts} +2 -2
- package/dist/storage/fake-storage.service.d.mts.map +1 -0
- package/dist/{storage-PcJUKxwp.mjs → storage/fake-storage.service.mjs} +5 -22
- package/dist/storage/fake-storage.service.mjs.map +1 -0
- package/dist/storage/index.d.mts +2 -2
- package/dist/storage/index.mjs +1 -1
- package/dist/vitest-plugin/index.d.mts +2 -50
- package/dist/vitest-plugin/index.mjs +1 -85
- package/dist/vitest-plugin/stratal-test.d.mts +50 -0
- package/dist/vitest-plugin/stratal-test.d.mts.map +1 -0
- package/dist/vitest-plugin/stratal-test.mjs +86 -0
- package/dist/vitest-plugin/stratal-test.mjs.map +1 -0
- package/package.json +3 -3
- package/dist/index-D-Q2cR2v.d.mts.map +0 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/storage-PcJUKxwp.mjs.map +0 -1
- package/dist/vitest-plugin/index.d.mts.map +0 -1
- 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,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 @@
|
|
|
1
|
+
import { getTestEnv } from "./test-env.mjs";
|
|
@@ -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"}
|