167 lines
5.4 KiB
TypeScript
167 lines
5.4 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
|
|
import {
|
|
buildRouteUrl,
|
|
parseRouteInput,
|
|
} from "../../../src/presentation/routes/route-codecs.ts";
|
|
import {
|
|
mapReferenceOperation,
|
|
toReferenceView,
|
|
} from "../../../src/features/reference-feature/contracts/reference-mapper.ts";
|
|
import {
|
|
validateReferencePayload,
|
|
validateReferenceRequest,
|
|
} from "../../../src/features/reference-feature/contracts/reference-schemas.ts";
|
|
import {
|
|
REFERENCE_FEATURE_CONTRACT,
|
|
REFERENCE_FEATURE_ID,
|
|
referenceQueryKeys,
|
|
} from "../../../src/features/reference-feature/contracts/reference-feature-contract.ts";
|
|
import type { ReferenceFeatureInput } from "../../../src/features/reference-feature/application/reference-feature-api.ts";
|
|
import { createTestApplication } from "../../helpers/create-test-application.ts";
|
|
import { createReferenceFeatureInstalledInput } from "../../../src/features/reference-feature/adapters/create-reference-feature-input.ts";
|
|
|
|
describe("reference feature boundary contracts", () => {
|
|
it("propagates uncertain command effect certainty into the application failure", async () => {
|
|
const execute = vi.fn(async () => ({
|
|
kind: "CONTRACT_VIOLATION" as const,
|
|
violation: {
|
|
kind: "SUCCESS_SCHEMA_INVALID" as const,
|
|
operation: "VALIDATION" as const,
|
|
},
|
|
effect: "MAYBE_APPLIED" as const,
|
|
}));
|
|
const installed = createReferenceFeatureInstalledInput({
|
|
contractOperations: { execute },
|
|
});
|
|
|
|
await expect(
|
|
installed.input.createResource({ name: "uncertain" }),
|
|
).resolves.toMatchObject({
|
|
ok: false,
|
|
error: {
|
|
effect: "MAYBE_APPLIED",
|
|
retryable: false,
|
|
action: "contact-support",
|
|
},
|
|
});
|
|
});
|
|
|
|
it("round-trips one canonical filter through URL and query identity", () => {
|
|
const filters = {
|
|
tags: ["open", "new"],
|
|
cursor: "a/b",
|
|
limit: 5,
|
|
};
|
|
const url = buildRouteUrl("REFERENCE_RESOURCE_LIST", { search: filters });
|
|
expect(url).toBe(
|
|
"/examples/reference-resources?cursor=a%2Fb&limit=5&tags=open&tags=new",
|
|
);
|
|
const parsed = parseRouteInput(
|
|
"REFERENCE_RESOURCE_LIST",
|
|
{},
|
|
new URL(url, "https://app.test").searchParams,
|
|
);
|
|
expect(parsed).toMatchObject({
|
|
success: true,
|
|
data: { search: filters },
|
|
});
|
|
expect(referenceQueryKeys.list(filters).at(-1)).toEqual(filters);
|
|
});
|
|
|
|
it("rejects unknown search and malformed DTO before mapping", () => {
|
|
expect(
|
|
parseRouteInput(
|
|
"REFERENCE_RESOURCE_LIST",
|
|
{},
|
|
new URLSearchParams("unknown=value"),
|
|
),
|
|
).toEqual({ success: false, code: "ROUTE_SEARCH_INVALID" });
|
|
expect(
|
|
validateReferencePayload("ReferenceResourceListPayload", [
|
|
{ id: "unsafe", name: 42 },
|
|
]),
|
|
).toMatchObject({ success: false });
|
|
expect(
|
|
mapReferenceOperation("LIST_REFERENCE_RESOURCES", [
|
|
{ id: "unsafe", name: 42 },
|
|
]),
|
|
).toMatchObject({ ok: false });
|
|
});
|
|
|
|
it("normalizes request input and maps only owned domain fields", () => {
|
|
expect(
|
|
validateReferenceRequest("CreateReferenceResourceCommand", {
|
|
name: " Example ",
|
|
}),
|
|
).toMatchObject({ success: true, data: { name: "Example" } });
|
|
const model = mapReferenceOperation("CREATE_REFERENCE_RESOURCE", {
|
|
id: "reference-1",
|
|
name: "Example",
|
|
createdAt: "2026-07-26T00:00:00.000Z",
|
|
});
|
|
if (!model.ok || !("id" in model.value)) {
|
|
throw new Error("expected one model");
|
|
}
|
|
expect(toReferenceView(model.value)).toEqual({
|
|
resourceId: "reference-1",
|
|
title: "Example",
|
|
createdAt: "2026-07-26T00:00:00.000Z",
|
|
});
|
|
});
|
|
|
|
it("owns route, operation and query contributions in one removable contract", () => {
|
|
expect(Object.keys(REFERENCE_FEATURE_CONTRACT.routes)).toEqual([
|
|
"REFERENCE_RESOURCE_LIST",
|
|
"REFERENCE_RESOURCE_DETAIL",
|
|
"REFERENCE_RESOURCE_FORM",
|
|
"REFERENCE_RESOURCE_STATUS",
|
|
]);
|
|
expect(Object.keys(REFERENCE_FEATURE_CONTRACT.apiOperations)).toEqual([
|
|
"LIST_REFERENCE_RESOURCES",
|
|
"CREATE_REFERENCE_RESOURCE",
|
|
"GET_REFERENCE_RESOURCE",
|
|
]);
|
|
expect(
|
|
REFERENCE_FEATURE_CONTRACT.apiOperations.GET_REFERENCE_RESOURCE,
|
|
).toMatchObject({
|
|
pathSchema: "ReferenceResourceParams",
|
|
pathParameterNames: ["resourceId"],
|
|
providerId: "PRIMARY_API",
|
|
authProfileId: "REFERENCE_EXTERNAL_BEARER",
|
|
csrfProfileId: "NO_CSRF_BEARER",
|
|
});
|
|
expect(Object.keys(REFERENCE_FEATURE_CONTRACT.queryRegistry)).toEqual([
|
|
"REFERENCE_RESOURCE",
|
|
]);
|
|
});
|
|
|
|
it("returns the installed input through the typed application registry", () => {
|
|
const featureInput = {
|
|
listResources: async () => ({ ok: true as const, value: [] }),
|
|
createResource: async ({ name }) => ({
|
|
ok: true as const,
|
|
value: {
|
|
resourceId: "created",
|
|
title: name,
|
|
createdAt: null,
|
|
},
|
|
}),
|
|
getResource: async (resourceId) => ({
|
|
ok: true as const,
|
|
value: {
|
|
resourceId,
|
|
title: "Reference",
|
|
createdAt: null,
|
|
},
|
|
}),
|
|
} satisfies ReferenceFeatureInput;
|
|
const application = createTestApplication({
|
|
featureInputs: { [REFERENCE_FEATURE_ID]: featureInput },
|
|
});
|
|
|
|
expect(application.features.has(REFERENCE_FEATURE_ID)).toBe(true);
|
|
expect(application.features.get(REFERENCE_FEATURE_ID)).toBe(featureInput);
|
|
});
|
|
});
|