Files
memind/mindspace-og-tags.test.mjs
T
john 9b4a25799f Add smart ACK provider for WeChat MP replies
Replace fixed ackText with a rule-based AckProvider that picks
response templates by message type and intent (translate, summary,
rewrite, poster, ppt, mindmap, code, search, schedule). Pure sync,
zero I/O, auto-falls back to config.ackText on any error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 15:19:03 +08:00

71 lines
3.6 KiB
JavaScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { injectOgTags } from './mindspace-og-tags.mjs';
const ctx = {
origin: 'https://m.tkmind.cn',
pageUrl: 'https://m.tkmind.cn/MindSpace/john/public/space.html',
pageDirUrl: 'https://m.tkmind.cn/MindSpace/john/public/',
};
test('injects og/twitter tags with absolute image from a relative cover', () => {
const html = `<html><head><title>🚀 太空小勇士 - 闯关大冒险</title>` +
`<meta name="description" content="一起闯关大冒险">` +
`<meta name="mindspace-cover" content='{"tag":"游戏","cover":"assets/hero.jpg"}'></head><body></body></html>`;
const out = injectOgTags(html, ctx);
assert.match(out, /<meta property="og:title" content="🚀 太空小勇士 - 闯关大冒险">/);
assert.match(out, /<meta property="og:description" content="一起闯关大冒险">/);
assert.match(out, /<meta property="og:image" content="https:\/\/g2\.tkmind\.cn\/MindSpace\/john\/public\/assets\/hero\.jpg">/);
assert.match(out, /<meta name="twitter:card" content="summary_large_image">/);
// injected before </head>
assert.ok(out.indexOf('og:image') < out.indexOf('</head>'));
});
test('falls back to the thumbnail png when the page has no cover of its own', () => {
const html = `<head><title>纯文字页面</title></head>`;
const out = injectOgTags(html, {
...ctx,
fallbackImageUrl: 'https://m.tkmind.cn/MindSpace/john/public/space.thumbnail.png',
});
assert.match(out, /<meta property="og:image" content="https:\/\/g2\.tkmind\.cn\/MindSpace\/john\/public\/space\.thumbnail\.png">/);
assert.match(out, /<meta name="twitter:card" content="summary_large_image">/);
});
test('prefers the page cover over the thumbnail fallback', () => {
const html = `<head><title>X</title><meta name="mindspace-cover" content='{"cover":"assets/hero.jpg"}'></head>`;
const out = injectOgTags(html, { ...ctx, fallbackImageUrl: 'https://m.tkmind.cn/x.thumbnail.png' });
assert.match(out, /og:image" content="https:\/\/g2\.tkmind\.cn\/MindSpace\/john\/public\/assets\/hero\.jpg"/);
assert.doesNotMatch(out, /thumbnail\.png/);
});
test('keeps an author-provided og:image and does not duplicate', () => {
const html = `<head><title>T</title><meta property="og:image" content="https://x/y.png"></head>`;
const out = injectOgTags(html, ctx);
assert.equal((out.match(/og:image/g) ?? []).length, 1);
});
test('skips og:image for svg-only cover, falls back to summary card', () => {
const html = `<head><title>仅SVG</title><meta name="mindspace-cover" content='{"cover":"foo.svg"}'></head>`;
const out = injectOgTags(html, ctx);
assert.doesNotMatch(out, /og:image/);
assert.match(out, /<meta name="twitter:card" content="summary">/);
});
test('passes through a full https cover url unchanged', () => {
const html = `<head><title>X</title><meta name="mindspace-cover" content='{"cover":"https://cdn.example.com/a.png"}'></head>`;
const out = injectOgTags(html, ctx);
assert.match(out, /<meta property="og:image" content="https:\/\/cdn\.example\.com\/a\.png">/);
});
test('resolves a root-absolute cover against the origin', () => {
const html = `<head><title>X</title><meta name="mindspace-cover" content='{"cover":"/shared/cover.jpg"}'></head>`;
const out = injectOgTags(html, ctx);
assert.match(out, /<meta property="og:image" content="https:\/\/g2\.tkmind\.cn\/shared\/cover\.jpg">/);
});
test('escapes quotes and ampersands in title to keep the meta tag well-formed', () => {
const html = `<head><title>say "hi" & bye</title></head>`;
const out = injectOgTags(html, ctx);
assert.match(out, /<meta property="og:title" content="say &quot;hi&quot; &amp; bye">/);
});