feat: centralize application framework primitives
Quality / quality (ubuntu-latest) (push) Failing after 14m38s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-22 23:07:46 +05:30
parent 96e082b943
commit a3ddd39b7b
73 changed files with 1429 additions and 84 deletions
+47 -1
View File
@@ -3,6 +3,9 @@ import { createContext, type Context, type ProblemDetails } from "@wrnexus/core"
export interface TestRequestOptions extends Omit<RequestInit, "body"> {
body?: BodyInit | Record<string, unknown> | URLSearchParams | FormData | null;
baseUrl?: string;
params?: Record<string, string>;
user?: unknown;
locals?: Record<string, unknown>;
}
/** Build a web-standard Request with convenient JSON/FormData handling. */
@@ -31,7 +34,50 @@ export function testRequest(path = "/", options: TestRequestOptions = {}): Reque
/** Create a complete Context suitable for middleware and route unit tests. */
export function testContext(path = "/", options: TestRequestOptions = {}): Context {
const request = testRequest(path, options);
return createContext(request, new URL(request.url));
const ctx = createContext(request, new URL(request.url));
ctx.params = { ...options.params };
ctx.user = options.user;
ctx.locals = { ...options.locals };
return ctx;
}
/** Preferred descriptive alias for testContext(). */
export const createTestContext = testContext;
/** Fluent, Bun-compatible fetch mock (including Bun.fetch.preconnect). */
export type FetchMock = typeof fetch & {
readonly calls: ReadonlyArray<{ input: string | URL | Request; init?: RequestInit }>;
respondOnce(response: Response | (() => Response | Promise<Response>)): FetchMock;
reset(): void;
};
export function createFetchMock(): FetchMock {
const responses: Array<Response | (() => Response | Promise<Response>)> = [];
const calls: Array<{ input: string | URL | Request; init?: RequestInit }> = [];
const implementation = async (input: string | URL | Request, init?: RequestInit) => {
calls.push({ input, init });
const next = responses.shift();
if (!next) throw new Error("WRN-TEST-FETCH: no response was queued for this request");
return typeof next === "function" ? next() : next.clone();
};
const mock = implementation as FetchMock;
Object.defineProperties(mock, {
calls: { get: () => calls },
respondOnce: {
value(response: Response | (() => Response | Promise<Response>)) {
responses.push(response);
return mock;
},
},
reset: {
value() {
responses.length = 0;
calls.length = 0;
},
},
preconnect: { value: () => undefined },
});
return mock;
}
export interface JsonResponse<T> {
+12 -1
View File
@@ -181,15 +181,26 @@ export async function createHarness(
};
}
/** Preferred full-stack name; retained alongside createHarness for compatibility. */
export const createTestApp = createHarness;
export {
testRequest,
testContext,
createTestContext,
readJsonResponse,
expectProblem,
deferred,
waitFor,
MemoryCookieJar,
createFetchMock,
} from "./advanced.ts";
export type {
TestRequestOptions,
JsonResponse,
Deferred,
WaitForOptions,
FetchMock,
} from "./advanced.ts";
export type { TestRequestOptions, JsonResponse, Deferred, WaitForOptions } from "./advanced.ts";
export { withDatabaseRollback, createFactory, captureBrowserArtifacts } from "./platform.ts";
export type { TransactionalDatabase, BrowserArtifactPage } from "./platform.ts";