309598bfa6
- 在ApiClient中新增submitFeedback、myFeedback、helpArticles、helpArticleDetail、 siteArticles、promotions、vipPackages、createVipOrder、vipOrders等方法 - 添加帮助文章和站点资讯的参数验证逻辑 - 更新测试文件添加新的API方法测试用例 - 在HTML页面中添加反馈、帮助和VIP服务相关页面的脚本引用 - 更新加入家谱页面为完整的申请流程界面 - 修改资讯详情页面为站点资讯展示页面 - 更新AxiosRequestUtil中认证处理逻辑 - 添加世系树渲染的HTML生成函数用于页面复用 - 更新文档中的API契约说明和页面规划
190 lines
6.4 KiB
JavaScript
190 lines
6.4 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const test = require('node:test');
|
|
|
|
const JoinPages = require('../public/js/join-pages.js');
|
|
|
|
const genealogyId = '2062179707935264769';
|
|
const applyId = '2062179707935264770';
|
|
|
|
function read(relativePath) {
|
|
return fs.readFileSync(path.resolve(__dirname, '..', relativePath), 'utf8');
|
|
}
|
|
|
|
test('加入申请只构造 AppGenealogyJoinApplyBody 并裁剪可选文本', () => {
|
|
assert.deepEqual(JoinPages.buildJoinApplyBody({
|
|
applicantName: ' 叶子 ',
|
|
phone: ' 19181970173 ',
|
|
relationDesc: ' 族亲 ',
|
|
applyReason: ' 申请加入 ',
|
|
inviterUserId: 'must-drop',
|
|
genealogyId: 'must-drop'
|
|
}), {
|
|
applicantName: '叶子',
|
|
phone: '19181970173',
|
|
relationDesc: '族亲',
|
|
applyReason: '申请加入'
|
|
});
|
|
assert.deepEqual(JoinPages.buildJoinApplyBody({
|
|
applicantName: ' ',
|
|
phone: '',
|
|
relationDesc: null
|
|
}), {});
|
|
});
|
|
|
|
test('加入申请按后端长度约束校验四个可选字段', () => {
|
|
assert.equal(JoinPages.validateJoinApplyBody({ applicantName: '叶'.repeat(50) }), '');
|
|
assert.match(JoinPages.validateJoinApplyBody({ applicantName: '叶'.repeat(51) }), /50/);
|
|
assert.equal(JoinPages.validateJoinApplyBody({ phone: '1'.repeat(30) }), '');
|
|
assert.match(JoinPages.validateJoinApplyBody({ phone: '1'.repeat(31) }), /30/);
|
|
assert.equal(JoinPages.validateJoinApplyBody({ relationDesc: '亲'.repeat(100) }), '');
|
|
assert.match(JoinPages.validateJoinApplyBody({ relationDesc: '亲'.repeat(101) }), /100/);
|
|
assert.equal(JoinPages.validateJoinApplyBody({ applyReason: '因'.repeat(500) }), '');
|
|
assert.match(JoinPages.validateJoinApplyBody({ applyReason: '因'.repeat(501) }), /500/);
|
|
});
|
|
|
|
test('可申请家谱必须提供稳定字符串 ID、谱名和姓氏,并拒绝停用家谱', () => {
|
|
assert.deepEqual(JoinPages.normalizeJoinGenealogy({
|
|
genealogyId,
|
|
genealogyName: '叶氏家谱',
|
|
surname: '叶',
|
|
regionFullName: '四川省',
|
|
memberCount: 12,
|
|
joinMode: '0',
|
|
status: '0',
|
|
ownerUserId: 'must-drop'
|
|
}), {
|
|
genealogyId,
|
|
genealogyName: '叶氏家谱',
|
|
surname: '叶',
|
|
regionFullName: '四川省',
|
|
memberCount: 12,
|
|
joinMode: '0'
|
|
});
|
|
assert.equal(JoinPages.normalizeJoinGenealogy({
|
|
genealogyId: Number.MAX_SAFE_INTEGER + 1,
|
|
genealogyName: '叶氏家谱',
|
|
surname: '叶',
|
|
status: '0'
|
|
}), null);
|
|
assert.equal(JoinPages.normalizeJoinGenealogy({
|
|
genealogyId,
|
|
genealogyName: '叶氏家谱',
|
|
surname: '叶',
|
|
status: '1'
|
|
}), null);
|
|
});
|
|
|
|
test('我的申请只接收稳定 ID 和 0/1/2/3 状态', () => {
|
|
assert.deepEqual(JoinPages.normalizeJoinApply({
|
|
applyId,
|
|
genealogyId,
|
|
genealogyName: '叶氏家谱',
|
|
surname: '叶',
|
|
relationDesc: '族亲',
|
|
applyReason: '申请加入',
|
|
auditRemark: '已核实',
|
|
auditTime: '2026-07-29 12:00:00',
|
|
status: '1',
|
|
appUserId: 'must-drop',
|
|
inviterUserId: 'must-drop',
|
|
auditUserId: 'must-drop',
|
|
appUserPhone: 'must-drop'
|
|
}), {
|
|
applyId,
|
|
genealogyId,
|
|
genealogyName: '叶氏家谱',
|
|
surname: '叶',
|
|
relationDesc: '族亲',
|
|
applyReason: '申请加入',
|
|
auditRemark: '已核实',
|
|
auditTime: '2026-07-29 12:00:00',
|
|
status: '1'
|
|
});
|
|
assert.equal(JoinPages.normalizeJoinApply({
|
|
applyId: Number.MAX_SAFE_INTEGER + 1,
|
|
genealogyId,
|
|
genealogyName: '叶氏家谱',
|
|
status: '0'
|
|
}), null);
|
|
assert.equal(JoinPages.normalizeJoinApply({
|
|
applyId,
|
|
genealogyId,
|
|
genealogyName: '叶氏家谱',
|
|
status: '9'
|
|
}), null);
|
|
});
|
|
|
|
test('申请数组只要包含非法元素就整批拒绝', () => {
|
|
const valid = { applyId, genealogyId, genealogyName: '叶氏家谱', status: '0' };
|
|
|
|
assert.equal(JoinPages.normalizeJoinApplies([valid]).length, 1);
|
|
assert.deepEqual(JoinPages.normalizeJoinApplies([valid, { status: '0' }]), []);
|
|
assert.deepEqual(JoinPages.normalizeJoinApplies({ rows: [valid] }), []);
|
|
});
|
|
|
|
test('普通用户列表隐藏内部字段且只有待审核申请可以撤销', () => {
|
|
const html = JoinPages.renderMyJoinApplies([{
|
|
applyId,
|
|
genealogyId,
|
|
genealogyName: '<叶氏家谱>',
|
|
surname: '叶',
|
|
relationDesc: '族亲',
|
|
applyReason: '申请加入',
|
|
status: '0',
|
|
appUserId: 'secret-user',
|
|
inviterUserId: 'secret-inviter',
|
|
auditUserId: 'secret-auditor',
|
|
appUserPhone: 'secret-phone'
|
|
}]);
|
|
const approvedHtml = JoinPages.renderMyJoinApplies([{
|
|
applyId,
|
|
genealogyId,
|
|
genealogyName: '叶氏家谱',
|
|
status: '1'
|
|
}]);
|
|
|
|
assert.match(html, /<叶氏家谱>/);
|
|
assert.match(html, new RegExp('data-join-cancel-id="' + applyId + '"'));
|
|
assert.doesNotMatch(approvedHtml, /data-join-cancel-id/);
|
|
assert.doesNotMatch(html, /secret-user|secret-inviter|secret-auditor|secret-phone|must-drop/);
|
|
});
|
|
|
|
test('申请加入页由后端家谱选项驱动且不允许手填业务 ID 或邀请码', () => {
|
|
const source = read('join-genealogy.html');
|
|
|
|
assert.match(source, /data-join-apply-page/);
|
|
assert.match(source, /data-join-genealogy-search/);
|
|
assert.match(source, /data-join-genealogy-options/);
|
|
assert.match(source, /data-join-apply-form/);
|
|
assert.match(source, /name="applicantName"/);
|
|
assert.match(source, /name="phone"/);
|
|
assert.match(source, /name="relationDesc"/);
|
|
assert.match(source, /name="applyReason"/);
|
|
assert.match(source, /public\/js\/join-pages\.js/);
|
|
assert.doesNotMatch(source, /name="(?:genealogyId|applyId|inviterUserId|inviteCode)"/);
|
|
assert.doesNotMatch(source, /邀请码|分享码|手工.*ID|输入.*ID/);
|
|
});
|
|
|
|
test('我的加入申请页加载真实列表和刷新入口', () => {
|
|
const source = read('profile-join-family.html');
|
|
|
|
assert.doesNotMatch(source, /data-feature-status="pending"|pending-pages\.js/);
|
|
assert.match(source, /data-my-join-applies-page/);
|
|
assert.match(source, /data-join-apply-list="mine"/);
|
|
assert.match(source, /data-join-apply-refresh/);
|
|
assert.match(source, /public\/js\/join-pages\.js/);
|
|
assert.doesNotMatch(source, /邀请码|分享码|输入.*ID/);
|
|
});
|
|
|
|
test('加入申请运行时提交与撤销后都重新读取我的申请', () => {
|
|
const source = read('public/js/join-pages.js');
|
|
|
|
assert.match(source, /await api\.applyToGenealogy\(/);
|
|
assert.match(source, /await api\.myGenealogyJoinApplies\(\)/);
|
|
assert.match(source, /await api\.cancelGenealogyJoinApply\(/);
|
|
assert.match(source, /提交后无法读取同一申请/);
|
|
assert.match(source, /撤销后申请仍处于待审核状态/);
|
|
});
|