refactor: 프론트엔드 리펙토링
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import type {
|
||||
IndexedDbRepositoryPort,
|
||||
} from "../../../src/application/ports/browser-file-storage/index.ts";
|
||||
import type {
|
||||
InstalledHttpOperationExecutor,
|
||||
} from "../../../src/adapters/http/index.ts";
|
||||
import {
|
||||
composeFeatureAdapterInputs,
|
||||
defineFeatureAdapterContribution,
|
||||
type IndexedDbRepositoryProvider,
|
||||
} from "../../../src/features/feature-adapter-contribution.ts";
|
||||
import {
|
||||
LOCAL_DRAFT_FEATURE_ADAPTER_CONTRIBUTION,
|
||||
} from "../../../src/features/local-draft-feature/adapters/create-local-draft-feature-input.ts";
|
||||
import type { LocalDraft } from "../../../src/features/local-draft-feature/domain/local-draft.ts";
|
||||
|
||||
type TestHttpFeatureInput = Readonly<{
|
||||
ping(): Promise<"pong">;
|
||||
}>;
|
||||
|
||||
declare module "../../../src/application/ports/in/application-api.ts" {
|
||||
interface ApplicationFeatureInputs {
|
||||
"test-http-feature": TestHttpFeatureInput;
|
||||
}
|
||||
}
|
||||
|
||||
const TEST_HTTP_FEATURE_ADAPTER_CONTRIBUTION =
|
||||
defineFeatureAdapterContribution({
|
||||
featureId: "test-http-feature",
|
||||
needs: ["http"] as const,
|
||||
createInput() {
|
||||
return Object.freeze({
|
||||
featureId: "test-http-feature" as const,
|
||||
input: Object.freeze({
|
||||
async ping() {
|
||||
return "pong" as const;
|
||||
},
|
||||
}),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
function localDraftRepository() {
|
||||
let stored: Readonly<{ value: LocalDraft; revision: number }> | null = null;
|
||||
const repository = Object.freeze({
|
||||
async compareAndSwap(input: Readonly<{ value: LocalDraft }>) {
|
||||
stored = Object.freeze({ value: input.value, revision: 1 });
|
||||
return Object.freeze({
|
||||
ok: true as const,
|
||||
value: Object.freeze({ revision: 1 }),
|
||||
});
|
||||
},
|
||||
async read() {
|
||||
return Object.freeze({ ok: true as const, value: stored });
|
||||
},
|
||||
async remove() {
|
||||
stored = null;
|
||||
return Object.freeze({
|
||||
ok: true as const,
|
||||
value: Object.freeze({ revision: 2 }),
|
||||
});
|
||||
},
|
||||
}) as unknown as IndexedDbRepositoryPort<LocalDraft, never>;
|
||||
return repository;
|
||||
}
|
||||
|
||||
describe("feature adapter composition", () => {
|
||||
it("composes HTTP-only and IndexedDB-only concrete contributions together", async () => {
|
||||
const repository = localDraftRepository();
|
||||
const get = ((repositoryId: string) => {
|
||||
expect(repositoryId).toBe("local-draft");
|
||||
return repository;
|
||||
}) as unknown as IndexedDbRepositoryProvider["get"];
|
||||
|
||||
const indexedDb = Object.freeze({ get }) satisfies IndexedDbRepositoryProvider;
|
||||
const http = Object.freeze({
|
||||
execute: async () => {
|
||||
throw new Error("HTTP should not execute during composition");
|
||||
},
|
||||
}) as unknown as InstalledHttpOperationExecutor;
|
||||
|
||||
const inputs = composeFeatureAdapterInputs(
|
||||
Object.freeze([
|
||||
TEST_HTTP_FEATURE_ADAPTER_CONTRIBUTION,
|
||||
LOCAL_DRAFT_FEATURE_ADAPTER_CONTRIBUTION,
|
||||
] as const),
|
||||
Object.freeze(["test-http-feature", "local-draft"]),
|
||||
Object.freeze({ http, indexedDb }),
|
||||
);
|
||||
|
||||
expect(Object.keys(inputs).sort()).toEqual([
|
||||
"local-draft",
|
||||
"test-http-feature",
|
||||
]);
|
||||
|
||||
await expect(inputs["test-http-feature"]?.ping()).resolves.toBe("pong");
|
||||
|
||||
const localDraft = inputs["local-draft"];
|
||||
if (!localDraft) throw new Error("local-draft input was not composed");
|
||||
|
||||
const draft = Object.freeze({
|
||||
draftId: "draft-1",
|
||||
title: "Local draft",
|
||||
body: "Body",
|
||||
});
|
||||
|
||||
await expect(
|
||||
localDraft.saveDraft({
|
||||
draft,
|
||||
expectedRevision: null,
|
||||
idempotencyKey: "save-draft-1",
|
||||
}),
|
||||
).resolves.toEqual({ ok: true, value: { revision: 1 } });
|
||||
|
||||
await expect(localDraft.findDraft("draft-1")).resolves.toEqual({
|
||||
ok: true,
|
||||
value: { draft, revision: 1 },
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user