136 lines
3.8 KiB
TypeScript
136 lines
3.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
createFeatureHttpBinding,
|
|
type InstalledHttpOperationExecutor,
|
|
} from "../../../src/adapters/http/index.ts";
|
|
import {
|
|
createReferenceHttpGateway,
|
|
REFERENCE_HTTP_OPERATIONS,
|
|
} from "../../../src/features/reference-feature/adapters/reference-http-gateway.ts";
|
|
|
|
function executorReturning(
|
|
outcome: Readonly<Record<string, unknown>>,
|
|
): InstalledHttpOperationExecutor {
|
|
const execute = (async () => outcome) as unknown as
|
|
InstalledHttpOperationExecutor["execute"];
|
|
return Object.freeze({ execute });
|
|
}
|
|
|
|
describe("reference HTTP business problem mapping", () => {
|
|
it("maps a typed 409 reference problem to the feature-owned business code", async () => {
|
|
const executor = executorReturning(
|
|
Object.freeze({
|
|
kind: "PROBLEM",
|
|
problem: Object.freeze({
|
|
type: "https://example.test/problems/reference-conflict",
|
|
title: "Reference conflict",
|
|
status: 409,
|
|
code: "REFERENCE_NAME_ALREADY_EXISTS",
|
|
}),
|
|
metadata: Object.freeze({ status: 409 }),
|
|
effect: "NOT_APPLIED",
|
|
}),
|
|
);
|
|
const gateway = createReferenceHttpGateway(
|
|
createFeatureHttpBinding(executor, REFERENCE_HTTP_OPERATIONS),
|
|
);
|
|
|
|
await expect(
|
|
gateway.create({ name: "duplicate" }),
|
|
).resolves.toMatchObject({
|
|
ok: false,
|
|
error: {
|
|
kind: "CONFLICT",
|
|
code: "REFERENCE_NAME_ALREADY_EXISTS",
|
|
httpStatus: 409,
|
|
},
|
|
});
|
|
});
|
|
|
|
it.each([
|
|
{
|
|
status: 409,
|
|
code: undefined,
|
|
expectedKind: "CONFLICT",
|
|
expectedCode: "REFERENCE_RESOURCE_CONFLICT",
|
|
},
|
|
{
|
|
status: 422,
|
|
code: "REFERENCE_NAME_REJECTED",
|
|
expectedKind: "VALIDATION_REJECTED",
|
|
expectedCode: "REFERENCE_NAME_REJECTED",
|
|
},
|
|
{
|
|
status: 422,
|
|
code: undefined,
|
|
expectedKind: "VALIDATION_REJECTED",
|
|
expectedCode: "REFERENCE_RESOURCE_REJECTED",
|
|
},
|
|
{
|
|
status: 400,
|
|
code: "REFERENCE_BAD_REQUEST",
|
|
expectedKind: "UNKNOWN_CLIENT_FAILURE",
|
|
expectedCode: "CONTRACT_PROBLEM",
|
|
},
|
|
] as const)(
|
|
"projects create problem status $status through the feature-owned mapper/fallback",
|
|
async ({ status, code, expectedKind, expectedCode }) => {
|
|
const executor = executorReturning(
|
|
Object.freeze({
|
|
kind: "PROBLEM",
|
|
problem: Object.freeze({
|
|
type: "https://example.test/problems/reference-" + status,
|
|
title: "Reference request rejected",
|
|
status,
|
|
...(code === undefined ? {} : { code }),
|
|
}),
|
|
metadata: Object.freeze({ status }),
|
|
effect: "NOT_APPLIED",
|
|
}),
|
|
);
|
|
const gateway = createReferenceHttpGateway(
|
|
createFeatureHttpBinding(executor, REFERENCE_HTTP_OPERATIONS),
|
|
);
|
|
|
|
await expect(
|
|
gateway.create({ name: "rejected" }),
|
|
).resolves.toMatchObject({
|
|
ok: false,
|
|
error: {
|
|
kind: expectedKind,
|
|
code: expectedCode,
|
|
httpStatus: status,
|
|
},
|
|
});
|
|
},
|
|
);
|
|
|
|
it("keeps the platform status fallback when the operation has no problem mapper", async () => {
|
|
const executor = executorReturning(
|
|
Object.freeze({
|
|
kind: "PROBLEM",
|
|
problem: Object.freeze({
|
|
type: "https://example.test/problems/not-found",
|
|
title: "Not found",
|
|
status: 404,
|
|
}),
|
|
metadata: Object.freeze({ status: 404 }),
|
|
effect: "NOT_APPLIED",
|
|
}),
|
|
);
|
|
const gateway = createReferenceHttpGateway(
|
|
createFeatureHttpBinding(executor, REFERENCE_HTTP_OPERATIONS),
|
|
);
|
|
|
|
await expect(gateway.get("missing")).resolves.toMatchObject({
|
|
ok: false,
|
|
error: {
|
|
kind: "NOT_FOUND",
|
|
code: "CONTRACT_PROBLEM",
|
|
httpStatus: 404,
|
|
},
|
|
});
|
|
});
|
|
});
|