test: execute the HTTP scenario catalog
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { delay, http, HttpResponse, type JsonBodyType } from "msw";
|
||||
|
||||
import type { HttpScenarioId } from "../scenarios/catalog.ts";
|
||||
import type {
|
||||
HttpScenarioId,
|
||||
HttpScenarioOperationId,
|
||||
} from "../scenarios/catalog.ts";
|
||||
import { assertOperationScenario } from "../scenarios/catalog.ts";
|
||||
|
||||
export type ReferenceResourceFixture = Readonly<{
|
||||
@@ -20,6 +23,11 @@ type ScenarioOptions = Readonly<{
|
||||
>
|
||||
>;
|
||||
resources?: ReferenceResourceFixture[];
|
||||
onAttempt?(attempt: Readonly<{
|
||||
operationId: HttpScenarioOperationId;
|
||||
scenarioId: HttpScenarioId;
|
||||
attempt: number;
|
||||
}>): void;
|
||||
onList?(search: string): void;
|
||||
onCreate?(body: Readonly<Record<string, unknown>>): void;
|
||||
}>;
|
||||
@@ -31,12 +39,15 @@ const DEFAULT_RESOURCE = Object.freeze({
|
||||
});
|
||||
|
||||
async function scenarioResponse(
|
||||
operationId: HttpScenarioOperationId,
|
||||
scenario: HttpScenarioId,
|
||||
payload: JsonBodyType,
|
||||
attempt: number,
|
||||
) {
|
||||
if (scenario === "slow") await delay(50);
|
||||
if (scenario === "timeout") await delay(30_000);
|
||||
if (scenario === "timeout" || scenario === "aborted") {
|
||||
await delay("infinite");
|
||||
}
|
||||
if (scenario === "network-error") return HttpResponse.error();
|
||||
if (scenario === "content-type-mismatch") {
|
||||
return new HttpResponse("<html>not json</html>", {
|
||||
@@ -55,8 +66,7 @@ async function scenarioResponse(
|
||||
return HttpResponse.json({ unexpected: true });
|
||||
}
|
||||
if (
|
||||
scenario === "auth-persistent-401" ||
|
||||
(scenario === "auth-recover-once" && attempt === 1)
|
||||
scenario === "unauthenticated-401"
|
||||
) {
|
||||
return HttpResponse.json(problem(401, "AUTH_REQUIRED"), {
|
||||
status: 401,
|
||||
@@ -84,13 +94,34 @@ async function scenarioResponse(
|
||||
});
|
||||
}
|
||||
if (
|
||||
scenario === "server-terminal-500" ||
|
||||
scenario === "server-terminal-503" ||
|
||||
(scenario === "server-retry-success" && attempt === 1)
|
||||
) {
|
||||
return HttpResponse.json(problem(503, "SERVER_FAILURE"), {
|
||||
status: 503,
|
||||
});
|
||||
}
|
||||
if (scenario === "response-too-large") {
|
||||
const ceiling =
|
||||
operationId === "LIST_REFERENCE_RESOURCES" ? 262_144 : 32_768;
|
||||
const bytes = new Uint8Array(ceiling + 1).fill(0x20);
|
||||
bytes[0] = 0x5b;
|
||||
bytes[bytes.length - 1] = 0x5d;
|
||||
return new HttpResponse(
|
||||
new ReadableStream<Uint8Array>({
|
||||
start(controller) {
|
||||
controller.enqueue(bytes);
|
||||
controller.close();
|
||||
},
|
||||
}),
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Length": String(bytes.byteLength),
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
return HttpResponse.json(payload);
|
||||
}
|
||||
|
||||
@@ -125,10 +156,17 @@ export function createReferenceScenarioHandlers(options: ScenarioOptions = {}) {
|
||||
options.onList?.(new URL(request.url).search);
|
||||
const scenario = scenarioFor("LIST_REFERENCE_RESOURCES");
|
||||
const payload = scenario === "empty" ? [] : resources;
|
||||
const attempt = nextAttempt("LIST_REFERENCE_RESOURCES");
|
||||
options.onAttempt?.({
|
||||
operationId: "LIST_REFERENCE_RESOURCES",
|
||||
scenarioId: scenario,
|
||||
attempt,
|
||||
});
|
||||
return scenarioResponse(
|
||||
"LIST_REFERENCE_RESOURCES",
|
||||
scenario,
|
||||
payload,
|
||||
nextAttempt("LIST_REFERENCE_RESOURCES"),
|
||||
attempt,
|
||||
);
|
||||
}),
|
||||
http.post(
|
||||
@@ -149,10 +187,17 @@ export function createReferenceScenarioHandlers(options: ScenarioOptions = {}) {
|
||||
createdAt: "2026-07-26T00:00:00.000Z",
|
||||
};
|
||||
if (scenario === "success") resources.push(created);
|
||||
const attempt = nextAttempt("CREATE_REFERENCE_RESOURCE");
|
||||
options.onAttempt?.({
|
||||
operationId: "CREATE_REFERENCE_RESOURCE",
|
||||
scenarioId: scenario,
|
||||
attempt,
|
||||
});
|
||||
return scenarioResponse(
|
||||
"CREATE_REFERENCE_RESOURCE",
|
||||
scenario,
|
||||
created,
|
||||
nextAttempt("CREATE_REFERENCE_RESOURCE"),
|
||||
attempt,
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -163,10 +208,17 @@ export function createReferenceScenarioHandlers(options: ScenarioOptions = {}) {
|
||||
const resource =
|
||||
resources.find((entry) => entry.id === params.resourceId) ??
|
||||
DEFAULT_RESOURCE;
|
||||
const attempt = nextAttempt("GET_REFERENCE_RESOURCE");
|
||||
options.onAttempt?.({
|
||||
operationId: "GET_REFERENCE_RESOURCE",
|
||||
scenarioId: scenario,
|
||||
attempt,
|
||||
});
|
||||
return scenarioResponse(
|
||||
"GET_REFERENCE_RESOURCE",
|
||||
scenario,
|
||||
resource,
|
||||
nextAttempt("GET_REFERENCE_RESOURCE"),
|
||||
attempt,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user