Review finding I1: the static-key-first resolution order protected the entire legacy fixture (image and labels), when only the hand-authored labels ever needed protecting -- ResolvedAsset carries no label fields, so nothing else could recover them, but a real descriptor's publicPath/width/height were never actually at risk of mismatching. Narrowed resolveWith so a resolved descriptor's data fields always win; the legacy registry only overlays triggerLabel/dialogLabel for keys it recognizes, and only supplies the full descriptor when nothing else resolves the key at all. A future backend asset colliding with the legacy key now degrades to a wrong caption, never a wrong image. Review finding I2: renamed and rewrote a test whose title claimed a READY-vs-QUARANTINED same-key guarantee its body never constructed. It now puts both a QUARANTINED and a READY entry under one assetKey and asserts the READY one wins. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
129 lines
4.0 KiB
TypeScript
129 lines
4.0 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { test } from "vitest";
|
|
|
|
import {
|
|
createAssetCatalogResolver,
|
|
createResolvedAssetResolver,
|
|
MISSING_EVIDENCE_ASSET,
|
|
} from "../../../src/features/tech-log/presentation/shared/public-render/asset-resolvers.ts";
|
|
|
|
const READY = {
|
|
id: "11111111-1111-4111-8111-111111111111",
|
|
assetKey: "boundary",
|
|
kind: "DIAGRAM",
|
|
mediaType: "image/svg+xml",
|
|
originalFilename: "b.svg",
|
|
byteSize: 10,
|
|
width: 1080,
|
|
height: 420,
|
|
altText: "경계",
|
|
decorative: false,
|
|
managementStatus: "READY",
|
|
publicPath: "/media/boundary.svg",
|
|
usageCount: 0,
|
|
version: 1,
|
|
createdAt: "2026-08-14T01:00:00.000Z",
|
|
updatedAt: "2026-08-14T01:00:00.000Z",
|
|
} as never;
|
|
|
|
test("resolves a backend asset key to its public path", () => {
|
|
const resolve = createAssetCatalogResolver([READY]);
|
|
const asset = resolve("boundary");
|
|
|
|
assert.equal(asset.src, "/media/boundary.svg");
|
|
assert.equal(asset.width, 1080);
|
|
assert.equal(asset.height, 420);
|
|
});
|
|
|
|
test("falls back to the static registry for the legacy hardcoded key", () => {
|
|
const resolve = createAssetCatalogResolver([]);
|
|
const asset = resolve("fetch-strategy-boundary");
|
|
|
|
assert.equal(asset.src, "/media/fetch-strategy-boundary.svg");
|
|
});
|
|
|
|
test("returns the placeholder instead of throwing on an unknown key", () => {
|
|
const resolve = createAssetCatalogResolver([]);
|
|
assert.deepEqual(resolve("does-not-exist"), MISSING_EVIDENCE_ASSET);
|
|
});
|
|
|
|
test("never resolves a QUARANTINED asset", () => {
|
|
const resolve = createAssetCatalogResolver([
|
|
{ ...(READY as object), managementStatus: "QUARANTINED" } as never,
|
|
]);
|
|
assert.deepEqual(resolve("boundary"), MISSING_EVIDENCE_ASSET);
|
|
});
|
|
|
|
test("resolves from the server render model blocks", () => {
|
|
const resolve = createResolvedAssetResolver([
|
|
{
|
|
type: "EVIDENCE_FIGURE",
|
|
key: "boundary",
|
|
asset: {
|
|
assetId: "11111111-1111-4111-8111-111111111111",
|
|
assetKey: "boundary",
|
|
mediaType: "image/svg+xml",
|
|
publicPath: "/media/boundary.svg",
|
|
width: 800,
|
|
height: 300,
|
|
decorative: false,
|
|
},
|
|
},
|
|
]);
|
|
|
|
assert.equal(resolve("boundary").src, "/media/boundary.svg");
|
|
assert.equal(resolve("boundary").width, 800);
|
|
});
|
|
|
|
test("a READY asset wins over a QUARANTINED asset sharing the same key", () => {
|
|
const resolve = createAssetCatalogResolver([
|
|
{ ...(READY as object), managementStatus: "QUARANTINED" } as never,
|
|
READY,
|
|
]);
|
|
assert.equal(resolve("boundary").src, "/media/boundary.svg");
|
|
});
|
|
|
|
test("keeps the legacy key's hand-authored labels when a server block resolves it via descriptor (today's real Preview/Snapshot path)", () => {
|
|
const resolve = createResolvedAssetResolver([
|
|
{
|
|
type: "EVIDENCE_FIGURE",
|
|
key: "fetch-strategy-boundary",
|
|
asset: {
|
|
assetId: "00000000-0000-4000-8000-000000000001",
|
|
assetKey: "fetch-strategy-boundary",
|
|
mediaType: "image/svg+xml",
|
|
publicPath: "/media/fetch-strategy-boundary.svg",
|
|
width: 1080,
|
|
height: 420,
|
|
decorative: false,
|
|
},
|
|
},
|
|
]);
|
|
assert.deepEqual(resolve("fetch-strategy-boundary"), {
|
|
src: "/media/fetch-strategy-boundary.svg",
|
|
width: 1080,
|
|
height: 420,
|
|
triggerLabel: "Fetch Join과 Batch Fetch 비교 다이어그램 크게 보기",
|
|
dialogLabel: "Fetch Join과 Batch Fetch의 페이징 경계 확대",
|
|
});
|
|
});
|
|
|
|
test("a colliding backend descriptor's publicPath wins over the legacy src, but the legacy labels still win", () => {
|
|
const resolve = createAssetCatalogResolver([
|
|
{
|
|
...(READY as object),
|
|
assetKey: "fetch-strategy-boundary",
|
|
publicPath: "/media/should-win.svg",
|
|
width: 999,
|
|
height: 111,
|
|
} as never,
|
|
]);
|
|
const asset = resolve("fetch-strategy-boundary");
|
|
|
|
assert.equal(asset.src, "/media/should-win.svg");
|
|
assert.equal(asset.width, 999);
|
|
assert.equal(asset.height, 111);
|
|
assert.equal(asset.triggerLabel, "Fetch Join과 Batch Fetch 비교 다이어그램 크게 보기");
|
|
assert.equal(asset.dialogLabel, "Fetch Join과 Batch Fetch의 페이징 경계 확대");
|
|
});
|