Files
memind/wechat/verify/generated-thumbnail.test.mjs
john cb62b36cd5
Memind CI / Test, build, and release guards (pull_request) Successful in 5m1s
fix: recover WeChat page thumbnail delivery
2026-07-22 11:51:48 +08:00

177 lines
6.9 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import test from 'node:test';
import {
collectWechatGeneratedImages,
extractMindspaceCoverPath,
repairUnambiguousFreshWechatPageThumbnail,
verifyFreshWechatPageThumbnails,
} from './generated-thumbnail.mjs';
function generatedImageMessages({ jobId = 'job-1', htmlSrc = 'images/fresh.webp' } = {}) {
const result = {
ok: true,
purpose: 'hero',
jobId,
source: { mimeType: 'image/webp' },
asset: {
id: `asset-${jobId}`,
htmlSrc,
publicUrl: `https://example.com/MindSpace/user/public/${htmlSrc}`,
workspaceRelativePath: `public/${htmlSrc}`,
},
};
return [{
role: 'assistant',
content: [
{
id: `call-${jobId}`,
type: 'toolRequest',
toolCall: { value: { name: 'sandbox-fs__generate_image', arguments: { purpose: 'hero' } } },
},
{
id: `call-${jobId}`,
type: 'toolResponse',
toolResult: {
status: 'success',
value: { content: [{ type: 'text', text: JSON.stringify(result) }] },
},
},
],
}];
}
test('fresh page thumbnail must reference a current-run generated image', () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'wechat-fresh-cover-'));
try {
const htmlPath = path.join(root, 'page.html');
fs.writeFileSync(
htmlPath,
'<meta name="mindspace-cover" content=\'{"cover":"images/fresh.webp"}\'>',
'utf8',
);
const images = collectWechatGeneratedImages(generatedImageMessages());
assert.equal(images.length, 1);
assert.equal(extractMindspaceCoverPath(fs.readFileSync(htmlPath, 'utf8')), 'images/fresh.webp');
const result = verifyFreshWechatPageThumbnails(
[{ localPath: htmlPath, relativePath: 'public/page.html' }],
images,
);
assert.equal(result.ok, true);
assert.equal(result.matches[0].image.jobId, 'job-1');
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
});
test('old cover path and sharing one generated image across two pages fail closed', () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'wechat-stale-cover-'));
try {
const first = path.join(root, 'one.html');
const second = path.join(root, 'two.html');
fs.writeFileSync(first, '<meta name="mindspace-cover" content=\'{"cover":"images/fresh.webp"}\'>');
fs.writeFileSync(second, '<meta name="mindspace-cover" content=\'{"cover":"images/fresh.webp"}\'>');
const images = collectWechatGeneratedImages(generatedImageMessages());
const reused = verifyFreshWechatPageThumbnails(
[
{ localPath: first, relativePath: 'public/one.html' },
{ localPath: second, relativePath: 'public/two.html' },
],
images,
);
assert.equal(reused.ok, false);
assert.equal(reused.reason, 'cover_not_from_current_run');
fs.writeFileSync(first, '<meta name="mindspace-cover" content=\'{"cover":"images/old.webp"}\'>');
const stale = verifyFreshWechatPageThumbnails(
[{ localPath: first, relativePath: 'public/one.html' }],
images,
);
assert.equal(stale.ok, false);
assert.equal(stale.reason, 'cover_not_from_current_run');
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
});
test('auxiliary admin pages do not require a separate generated thumbnail', () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'wechat-aux-cover-'));
try {
const front = path.join(root, 'survey.html');
const admin = path.join(root, 'survey-admin.html');
fs.writeFileSync(front, '<meta name="mindspace-cover" content=\'{"cover":"images/fresh.webp"}\'>');
fs.writeFileSync(admin, '<meta name="mindspace-page-role" content="auxiliary">');
const result = verifyFreshWechatPageThumbnails(
[
{ localPath: front, relativePath: 'public/survey.html' },
{ localPath: admin, relativePath: 'public/survey-admin.html' },
],
collectWechatGeneratedImages(generatedImageMessages()),
);
assert.equal(result.ok, true);
assert.equal(result.matches.length, 1);
assert.equal(result.skippedArtifacts.length, 1);
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
});
test('one current-run hero repairs one page from the current write snapshot and re-verifies', () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'wechat-repair-cover-'));
try {
const htmlPath = path.join(root, 'page.html');
const diskHtml = '<html><head><meta name="mindspace-cover" content=\'{"tag":"页面","subtitle":"磁盘旧副本"}\'></head><body>disk copy</body></html>';
const currentRunHtml = '<html><head><meta name="mindspace-cover" content=\'{"tag":"页面","subtitle":"本轮副本"}\'></head><body>current run copy</body></html>';
fs.writeFileSync(htmlPath, diskHtml, 'utf8');
const artifacts = [{ localPath: htmlPath, relativePath: 'public/page.html' }];
const images = collectWechatGeneratedImages(generatedImageMessages());
const failed = verifyFreshWechatPageThumbnails(artifacts, images);
assert.equal(failed.reason, 'missing_generated_cover');
const repaired = repairUnambiguousFreshWechatPageThumbnail({
artifacts,
images,
currentRunHtmlArtifacts: [{ relativePath: 'public/page.html', content: currentRunHtml }],
verificationReason: failed.reason,
});
assert.equal(repaired.ok, true);
assert.equal(repaired.restoredCurrentRunHtml, true);
const written = fs.readFileSync(htmlPath, 'utf8');
assert.match(written, /current run copy/);
assert.doesNotMatch(written, /disk copy/);
assert.equal(extractMindspaceCoverPath(written), 'images/fresh.webp');
assert.equal(verifyFreshWechatPageThumbnails(artifacts, images).ok, true);
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
});
test('thumbnail repair refuses an ambiguous page-to-image mapping without changing the page', () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'wechat-ambiguous-repair-'));
try {
const htmlPath = path.join(root, 'page.html');
const original = '<meta name="mindspace-cover" content=\'{"tag":"页面"}\'>';
fs.writeFileSync(htmlPath, original, 'utf8');
const artifacts = [{ localPath: htmlPath, relativePath: 'public/page.html' }];
const images = collectWechatGeneratedImages([
...generatedImageMessages({ jobId: 'job-1', htmlSrc: 'images/one.webp' }),
...generatedImageMessages({ jobId: 'job-2', htmlSrc: 'images/two.webp' }),
]);
const repaired = repairUnambiguousFreshWechatPageThumbnail({
artifacts,
images,
verificationReason: 'missing_generated_cover',
});
assert.equal(repaired.ok, false);
assert.equal(repaired.reason, 'ambiguous_page_image_mapping');
assert.equal(fs.readFileSync(htmlPath, 'utf8'), original);
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
});