Files
jiapu/tests/family-home-pages.test.js
T
fizzleaf 309598bfa6 feat(api): 添加帮助中心反馈系统和VIP服务功能
- 在ApiClient中新增submitFeedback、myFeedback、helpArticles、helpArticleDetail、
  siteArticles、promotions、vipPackages、createVipOrder、vipOrders等方法
- 添加帮助文章和站点资讯的参数验证逻辑
- 更新测试文件添加新的API方法测试用例
- 在HTML页面中添加反馈、帮助和VIP服务相关页面的脚本引用
- 更新加入家谱页面为完整的申请流程界面
- 修改资讯详情页面为站点资讯展示页面
- 更新AxiosRequestUtil中认证处理逻辑
- 添加世系树渲染的HTML生成函数用于页面复用
- 更新文档中的API契约说明和页面规划
2026-07-30 16:04:48 +08:00

187 lines
5.8 KiB
JavaScript

const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const FamilyHomePages = require('../public/js/family-home-pages.js');
const genealogyId = '2062179707935264769';
const root = path.resolve(__dirname, '..');
function overviewFixture(overrides) {
return Object.assign({
genealogyId,
genealogyNo: 'G20260729001',
genealogyName: '叶氏家谱',
surname: '叶',
ancestralHall: '南阳堂',
originPlace: '四川成都',
regionCode: '510100',
regionName: '成都市',
regionFullName: '四川省 成都市',
addressDetail: '高新区',
coverOssId: '2062179707935264700',
intro: '叶氏源流',
ownerUserId: '2062179707935264701',
visibility: '1',
joinMode: '1',
memberCount: 12,
personCount: 36,
status: '0',
roleType: 'owner',
canManage: true,
canEditContent: true,
memberStatus: '0',
joinTime: '2026-07-29 12:00:00'
}, overrides);
}
test('家谱主页只保留 AppGenealogyVo 的安全展示字段并匹配当前上下文', () => {
assert.deepEqual(FamilyHomePages.normalizeFamilyOverview(
overviewFixture(),
genealogyId
), {
genealogyId,
genealogyNo: 'G20260729001',
genealogyName: '叶氏家谱',
surname: '叶',
ancestralHall: '南阳堂',
originPlace: '四川成都',
regionFullName: '四川省 成都市',
memberCount: 12,
personCount: 36,
canManage: true,
canEditContent: true
});
assert.equal(FamilyHomePages.normalizeFamilyOverview(
overviewFixture({ genealogyId: '2062179707935264770' }),
genealogyId
), null);
assert.equal(FamilyHomePages.normalizeFamilyOverview(
overviewFixture({ genealogyId: Number.MAX_SAFE_INTEGER + 1 }),
genealogyId
), null);
});
test('家谱主页拒绝停用、空名称和非法计数响应', () => {
assert.equal(FamilyHomePages.normalizeFamilyOverview(
overviewFixture({ status: '1' }),
genealogyId
), null);
assert.equal(FamilyHomePages.normalizeFamilyOverview(
overviewFixture({ genealogyName: '' }),
genealogyId
), null);
assert.equal(FamilyHomePages.normalizeFamilyOverview(
overviewFixture({ memberCount: -1 }),
genealogyId
), null);
assert.equal(FamilyHomePages.normalizeFamilyOverview(
overviewFixture({ personCount: Number.MAX_SAFE_INTEGER + 1 }),
genealogyId
), null);
});
test('家谱概览渲染转义文本并隐藏内部用户与文件编号', () => {
const overview = FamilyHomePages.normalizeFamilyOverview(
overviewFixture({
genealogyName: '<叶氏家谱>',
ancestralHall: '<南阳堂>'
}),
genealogyId
);
const html = FamilyHomePages.renderFamilyOverview(overview);
assert.match(html, /&lt;叶氏家谱&gt;/);
assert.match(html, /&lt;南阳堂&gt;/);
assert.match(html, /成员 12 人/);
assert.match(html, /世系人物 36 人/);
assert.doesNotMatch(html, /ownerUserId|coverOssId|206217970793526470[01]/);
});
test('家谱管理入口只接受后端布尔能力字段', () => {
assert.equal(FamilyHomePages.shouldShowFamilyManagement(
FamilyHomePages.normalizeFamilyOverview(overviewFixture({ canManage: true }), genealogyId)
), true);
assert.equal(FamilyHomePages.shouldShowFamilyManagement(
FamilyHomePages.normalizeFamilyOverview(overviewFixture({ canManage: 'true' }), genealogyId)
), false);
});
test('家谱主页只把缺失登录态和 401 视为登录失效', () => {
assert.equal(FamilyHomePages.shouldRedirectToLogin({
getToken() { return 'token'; }
}, { status: 403 }), false);
assert.equal(FamilyHomePages.shouldRedirectToLogin({
getToken() { return 'token'; }
}, { status: 401 }), true);
assert.equal(FamilyHomePages.shouldRedirectToLogin({
getToken() { return ''; }
}), true);
});
test('家谱主页只读取当前家谱概览和世系树', async () => {
const calls = [];
const tree = [{
personId: '2062179707935264770',
genealogyId,
name: '始祖',
spouses: [],
children: []
}];
const result = await FamilyHomePages.loadFamilyHome({
genealogyOverview(receivedId) {
calls.push(['overview', receivedId]);
return Promise.resolve(overviewFixture());
},
lineageTree(receivedId) {
calls.push(['tree', receivedId]);
return Promise.resolve(tree);
}
}, genealogyId);
assert.deepEqual(calls, [
['overview', genealogyId],
['tree', genealogyId]
]);
assert.deepEqual(result.overview, FamilyHomePages.normalizeFamilyOverview(
overviewFixture(),
genealogyId
));
assert.deepEqual(result.tree, tree);
});
test('家谱主页开放真实只读概览且不制造邀请或聚合统计入口', () => {
const source = fs.readFileSync(path.join(root, 'profile-family-home.html'), 'utf8');
assert.doesNotMatch(source, /data-feature-status="pending"|pending-pages\.js/);
assert.doesNotMatch(source, /四川武胜汤氏族/);
assert.doesNotMatch(source, /href="profile-invite\.html"/);
assert.match(source, /PC 暂未开放邀请/);
assert.match(source, /data-family-home-title/);
assert.match(source, /data-family-home-overview/);
assert.match(source, /data-family-home-member-count/);
assert.match(source, /data-family-home-person-count/);
assert.match(source, /data-family-home-management/);
assert.match(source, /data-lineage-home-tree/);
assert.match(source, /src="public\/js\/lineage-pages\.js"/);
assert.match(source, /src="public\/js\/family-home-pages\.js"/);
[
'profile-feed.html',
'profile-tree.html',
'profile-article.html',
'profile-album.html',
'profile-video.html',
'profile-merit.html',
'profile-ceremony.html'
].forEach((href) => {
assert.match(
source,
new RegExp('href="' + href.replace('.', '\\.') + '"[^>]*data-genealogy-context-link'),
`${href} 缺少家谱上下文`
);
});
});