feat: compose TechLog static and mock adapters
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
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과 페이징은 왜 충돌하는가",
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user