const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const SiteNewsPages = require('../public/js/site-news-pages.js');
const newsPage = fs.readFileSync(path.resolve(__dirname, '../news.html'), 'utf8');
const detailPage = fs.readFileSync(path.resolve(__dirname, '../article-detail.html'), 'utf8');
const articleId = '2062179707935264769';
function articleFixture(overrides) {
return Object.assign({
articleId,
articleType: 'notice',
articleTitle: '平台公告',
articleSummary: '公告摘要',
articleContent: '第一行\n第二行',
coverOssId: '2062179707935264701',
externalUrl: 'https://example.com/notice',
publishTime: '2026-07-30 09:00:00',
sortOrder: 1,
status: '0',
remark: 'internal-only'
}, overrides);
}
test('站点文章只保留完整 SiteArticleVo 的安全展示字段和字符串长 ID', () => {
assert.deepEqual(SiteNewsPages.normalizeArticle(articleFixture()), {
articleId,
articleType: 'notice',
articleTitle: '平台公告',
articleSummary: '公告摘要',
articleContent: '第一行\n第二行',
externalUrl: 'https://example.com/notice',
publishTime: '2026-07-30 09:00:00'
});
assert.equal(SiteNewsPages.normalizeArticle(articleFixture({
articleId: Number.MAX_SAFE_INTEGER + 1
})), null);
assert.equal(SiteNewsPages.normalizeArticle(articleFixture({ articleId: '0' })), null);
});
test('站点文章拒绝 SQL 字典外类型、停用记录和空标题', () => {
assert.equal(SiteNewsPages.normalizeArticle(articleFixture({ articleType: 'culture' })), null);
assert.equal(SiteNewsPages.normalizeArticle(articleFixture({ status: '1' })), null);
assert.equal(SiteNewsPages.normalizeArticle(articleFixture({ articleTitle: ' ' })), null);
assert.equal(SiteNewsPages.normalizeArticleType('news'), 'news');
assert.equal(SiteNewsPages.normalizeArticleType('notice'), 'notice');
assert.equal(SiteNewsPages.normalizeArticleType('download'), 'download');
assert.equal(SiteNewsPages.normalizeArticleType('culture'), '');
});
test('站点文章列表只接受直接数组且任一非法元素使整批失败', () => {
assert.equal(SiteNewsPages.normalizeArticleList([articleFixture()]).length, 1);
assert.deepEqual(SiteNewsPages.normalizeArticleList([]), []);
assert.deepEqual(SiteNewsPages.normalizeArticleList({ rows: [articleFixture()] }), []);
assert.deepEqual(SiteNewsPages.normalizeArticleList([
articleFixture(),
articleFixture({ articleId: '' })
]), []);
});
test('站点资讯列表使用响应 ID 生成详情链接并隐藏内部字段', () => {
const html = SiteNewsPages.renderArticleList([articleFixture({
articleTitle: '',
articleSummary: '
',
coverOssId: 'secret-oss',
remark: 'secret-remark'
})]);
assert.match(html, /article-detail\.html\?articleId=2062179707935264769/);
assert.match(html, /公告/);
assert.match(html, /<script>/);
assert.match(html, /<img src=x>/);
assert.doesNotMatch(html, /\n第二行'
}));
assert.match(html, /<script>alert\(1\)<\/script>
第二行/);
assert.match(html, /href="https:\/\/example\.com\/notice"/);
assert.match(html, /target="_blank"/);
assert.match(html, /rel="noopener noreferrer"/);
assert.doesNotMatch(html, /