const assert = require("node:assert/strict"); const fs = require("node:fs"); const path = require("node:path"); const test = require("node:test"); const ts = require("../node_modules/typescript"); const filename = path.resolve( __dirname, "../src/components/creator/WorksGallery.tsx", ); const file = ts.createSourceFile( filename, fs.readFileSync(filename, "utf8"), ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX, ); const cover = file.statements.find( (node) => ts.isFunctionDeclaration(node) && node.name?.text === "WorkCover", ); const compiled = ts.transpileModule(cover.getText(file), { compilerOptions: { module: ts.ModuleKind.CommonJS, jsx: ts.JsxEmit.React }, }).outputText; function harness(fetch) { const state = []; const effects = []; const calls = []; const revoked = []; let cursor = 0; let effect; const react = { createElement: (type, props, ...children) => ({ type, props: { ...props, children }, }), }; const useState = (initial) => { const index = cursor++; if (!(index in state)) state[index] = initial; return [ state[index], (value) => { state[index] = value; }, ]; }; const useEffect = (fn, deps) => { const index = cursor++; if (!effects[index]) { effect = fn; effects[index] = { deps }; } }; const url = { createObjectURL: () => "blob:local-cover", revokeObjectURL: (value) => revoked.push(value), }; const Component = new Function( "exports", "React", "useState", "useEffect", "fetchCreatorBinary", "Flex", "Typography", "URL", compiled + "\nreturn exports.WorkCover;", )( {}, react, useState, useEffect, (endpoint) => { calls.push(endpoint); return fetch(); }, "Flex", { Text: "Text" }, url, ); return { calls, revoked, render(props) { cursor = 0; const tree = Component(props); if (effect) { effects[2].cleanup = effect(); effect = null; } return tree; }, cleanup() { effects[2]?.cleanup?.(); }, }; } const tick = async () => { for (let i = 0; i < 6; i++) await Promise.resolve(); }; test("comment thumbnails load only the cached local cover and release its image URL", async () => { const h = harness(async () => ({ cover: true })); const props = { workID: "work/id", title: "作品标题" }; const loading = h.render(props); assert.equal(loading.type, "Flex"); assert.equal(loading.props.children[0].props.children[0], "封面加载中"); await tick(); const image = h.render(props); assert.equal(image.type, "img"); assert.equal(image.props.src, "blob:local-cover"); assert.equal(image.props.alt, "作品标题"); assert.deepEqual(h.calls, ["/creator/works/work%2Fid/cover"]); h.cleanup(); assert.deepEqual(h.revoked, ["blob:local-cover"]); }); test("missing cached cover is explicit and never replaced by a remote image", async () => { const h = harness(async () => { throw new Error("作品封面尚未缓存"); }); const props = { workID: "missing-cover", title: "作品封面" }; h.render(props); await tick(); const missing = h.render(props); assert.equal(missing.type, "Flex"); assert.equal(missing.props.children[0].props.children[0], "封面未缓存"); assert.deepEqual(h.calls, ["/creator/works/missing-cover/cover"]); h.cleanup(); assert.deepEqual(h.revoked, []); });