118 lines
4.1 KiB
JavaScript
118 lines
4.1 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,
|
|
verifyFreshWechatPageThumbnails,
|
|
} from './generated-thumbnail.mjs';
|
|
|
|
function generatedImageMessages({ jobId = 'job-1', htmlSrc = 'images/fresh.webp' } = {}) {
|
|
const result = {
|
|
ok: true,
|
|
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 });
|
|
}
|
|
});
|