Files
tech-log-frontend/tests/features/tech-log/runtime-composition.test.ts
T

97 lines
3.4 KiB
TypeScript

import assert from "node:assert/strict";
import { test } from "vitest";
import type { ApplicationFeatureInputs } from "../../../src/application/ports/in/application-api.ts";
import { createInstalledFeatureInputs } from "../../../src/features/installed-feature-adapters.ts";
import { FIXTURE_IDS } from "../../../src/features/tech-log/adapters/mock/fixtures.ts";
import type { TechLogFeatureInput } from "../../../src/features/tech-log/application/tech-log-feature-input.ts";
import type { WorkingCopy } from "../../../src/features/tech-log/contracts/studio/contract.ts";
type Equal<Left, Right> =
(<Value>() => Value extends Left ? 1 : 2) extends <Value>() =>
Value extends Right ? 1 : 2
? true
: false;
type Expect<Value extends true> = Value;
type InstalledInputs = ReturnType<typeof createInstalledFeatureInputs>;
type _InstalledIdsAreExact = Expect<
Equal<keyof InstalledInputs, "reference-feature" | "tech-log">
>;
type _TechLogRegistryValueIsExact = Expect<
Equal<ApplicationFeatureInputs["tech-log"], TechLogFeatureInput>
>;
void (0 as unknown as _InstalledIdsAreExact);
void (0 as unknown as _TechLogRegistryValueIsExact);
function inputOf(document: WorkingCopy) {
const { id, version, updatedAt, ...input } = document;
void id;
void version;
void updatedAt;
return input;
}
function installedInputs(): InstalledInputs {
return createInstalledFeatureInputs({
contractOperations: {
async execute() {
throw new Error("reference executor is not used by composition tests");
},
},
});
}
test("installs TechLog beside the retained reference feature through application-facing inputs", () => {
const installed = installedInputs();
assert.deepEqual(Object.keys(installed), ["reference-feature", "tech-log"]);
assert.deepEqual(Object.keys(installed["tech-log"]).sort(), [
"createStudioGateway",
"publicContent",
]);
assert.equal(Object.isFrozen(installed), true);
assert.equal(Object.isFrozen(installed["tech-log"]), true);
assert.equal(Object.isFrozen(installed["tech-log"].publicContent), true);
assert.equal(
installed["tech-log"].publicContent.getRelease("0.1.0")?.title,
"TechLog Public·Studio 경계를 확정했습니다",
);
});
test("each createStudioGateway call owns an isolated mutable Studio session", async () => {
const installed = installedInputs();
const first = installed["tech-log"].createStudioGateway();
const second = installed["tech-log"].createStudioGateway();
assert.notEqual(first, second);
const firstBefore = await first.getDocument(FIXTURE_IDS.fetchJoinCase);
const secondBefore = await second.getDocument(FIXTURE_IDS.fetchJoinCase);
assert.equal(firstBefore.document.title, secondBefore.document.title);
const saved = await first.saveDocument(
firstBefore.document.id,
{
expectedVersion: firstBefore.document.version,
document: {
...inputOf(firstBefore.document),
title: "첫 번째 세션에서만 수정",
},
},
{ idempotencyKey: "session-isolation" },
);
assert.equal(saved.document.title, "첫 번째 세션에서만 수정");
assert.equal(
(await second.getDocument(FIXTURE_IDS.fetchJoinCase)).document.title,
secondBefore.document.title,
);
assert.equal(
installed["tech-log"].publicContent.getRecord(
"CASE",
"collection-fetch-join-pagination",
)?.title,
"컬렉션 Fetch Join과 페이징은 왜 충돌하는가",
);
});