feat: resolve evidence figures from backend asset descriptors
Public Preview and Publication Snapshot now resolve evidence figures from the ResolvedAsset descriptor the server already attaches to each EVIDENCE_FIGURE block, instead of a local literal that only knew one hardcoded key and threw on anything else. Instant Preview gains an `assets` prop (defaults to `[]`, unwired until the Asset Picker task) and stops throwing when a key has no catalog match yet. Builds on Task 1's existing seam (resolveCaseEvidenceAssets / ResolveEvidenceAsset) via a new asset-resolvers.ts rather than a parallel path. Kept out of adapters/ (presentation may not import it) by carrying a small local copy of the one legacy fixture entry, checked before any descriptor match so the pre-existing key keeps rendering byte-identically across surfaces during the migration window. Non-READY assets never resolve; unresolvable keys return a placeholder instead of throwing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0c071aaabc
commit
9d91001a31
@@ -0,0 +1,94 @@
|
||||
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 QUARANTINED asset never wins over the placeholder even when a READY asset with the same key exists later", () => {
|
||||
const resolve = createAssetCatalogResolver([
|
||||
{ ...(READY as object), managementStatus: "QUARANTINED" } as never,
|
||||
]);
|
||||
assert.equal(resolve("boundary").src, "");
|
||||
});
|
||||
|
||||
test("does not let a real backend asset shadow the legacy static key's byte-identical output", () => {
|
||||
const resolve = createAssetCatalogResolver([
|
||||
{
|
||||
...(READY as object),
|
||||
assetKey: "fetch-strategy-boundary",
|
||||
publicPath: "/media/should-not-win.svg",
|
||||
} as never,
|
||||
]);
|
||||
assert.equal(resolve("fetch-strategy-boundary").src, "/media/fetch-strategy-boundary.svg");
|
||||
});
|
||||
Reference in New Issue
Block a user