Files
jiapu/tests/profile-pages.test.js
T
2026-08-03 16:49:38 +08:00

203 lines
8.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const ProfilePages = require('../public/js/profile-pages.js');
const RegionPages = require('../public/js/region-pages.js');
const UploadPages = require('../public/js/upload-pages.js');
test('profile view reads only the documented profile fields', () => {
assert.deepEqual(ProfilePages.buildProfileView({
nickName: '小林',
realName: '林某',
phone: '13800000000',
birthday: '1990-01-01',
userName: '不应读取',
mobile: '不应读取'
}), {
displayName: '小林',
realName: '林某',
avatarText: '小',
avatarStatus: '未设置',
phone: '13800000000',
sex: '待填写',
birthday: '1990-01-01',
email: '待填写',
regionText: '当前资料接口未提供'
});
assert.deepEqual(ProfilePages.buildProfileView({
userName: '不应读取',
phonenumber: '不应读取',
mobile: '不应读取'
}), {
displayName: '未设置昵称',
realName: '待填写',
avatarText: '家',
avatarStatus: '未设置',
phone: '未绑定',
sex: '待填写',
birthday: '待填写',
email: '待填写',
regionText: '当前资料接口未提供'
});
});
test('profile loading failure has an explicit non-demo view', () => {
assert.deepEqual(ProfilePages.buildUnavailableProfileView(), {
displayName: '账户资料暂时无法读取',
realName: '暂无数据',
avatarText: '',
avatarStatus: '暂无数据',
phone: '暂无数据',
birthday: '暂无数据',
email: '暂无数据',
sex: '暂无数据',
regionText: '暂无数据'
});
});
test('profile update emits only the six fields defined by ProfileUpdateBody', () => {
assert.deepEqual(ProfilePages.buildProfileUpdateBody({
nickName: '小林',
realName: '林某',
avatar: '',
sex: '0',
birthday: '1990-01-01',
email: 'lin@example.com',
avatarOssId: 'legacy-avatar',
provinceCode: '11'
}), {
nickName: '小林',
realName: '林某',
sex: '0',
birthday: '1990-01-01',
email: 'lin@example.com'
});
assert.deepEqual(ProfilePages.buildProfileUpdateBody({ avatar: '123' }), { avatar: '123' });
assert.deepEqual(
ProfilePages.buildProfileUpdateBody({ avatar: '2060000000000000001' }),
{ avatar: '2060000000000000001' }
);
assert.throws(() => ProfilePages.buildProfileUpdateBody({ avatar: 'not-an-id' }), /头像 OSS ID 必须是整数/);
assert.equal(UploadPages.normalizeUploadResult({ ossId: '2060000000000000000' }).ossId, '2060000000000000000');
});
test('个人中心概览不读取资料接口未声明的地区字段', () => {
const source = fs.readFileSync(path.join(__dirname, '..', 'public', 'js', 'profile-pages.js'), 'utf8');
assert.match(source, /regionText: '当前资料接口未提供'/);
assert.doesNotMatch(source, /provinceCode|cityCode|districtCode|regionPath|applyProfileRegionSelection/);
});
test('profile update rejects an empty payload and an invalid email before requesting the PC API', () => {
assert.equal(ProfilePages.validateProfileUpdateBody({}), '请至少填写一项资料');
assert.equal(ProfilePages.validateProfileUpdateBody({ email: 'invalid-email' }), '请输入正确的邮箱地址');
assert.equal(ProfilePages.validateProfileUpdateBody({ nickName: '小林' }), '');
});
test('region selector accepts only documented region fields and levels', () => {
assert.deepEqual(RegionPages.normalizeList({ data: [{ regionCode: '11' }] }), []);
assert.equal(RegionPages.getRegionCode({ value: '11' }), '');
assert.equal(RegionPages.getRegionName({ label: '北京市' }), '未命名地区');
assert.equal(RegionPages.getRegionLevel({ regionCode: '110101' }), 0);
assert.deepEqual(RegionPages.buildRegionSelection([
{ regionCode: '11', regionName: '北京市', regionLevel: 1 },
{ regionCode: '1101', regionName: '市辖区', regionLevel: 2 },
{ regionCode: '110101', regionName: '东城区', regionLevel: 3 }
]), {
provinceCode: '11',
cityCode: '1101',
districtCode: '110101'
});
});
test('profile data page exposes every editable ProfileUpdateBody field without a manual OSS ID input', () => {
const source = fs.readFileSync(path.join(__dirname, '..', 'profile-data.html'), 'utf8');
assert.match(source, /data-profile-form novalidate/);
assert.match(source, /data-profile-form/);
assert.match(source, /data-profile-text="realName"/);
assert.match(source, /name="nickName"/);
assert.match(source, /name="realName"/);
assert.match(source, /name="avatar"/);
assert.match(source, /name="sex"[\s\S]*<option value="2">未知<\/option>/);
assert.match(source, /name="birthday"/);
assert.match(source, /name="email"/);
assert.doesNotMatch(source, /name="avatarOssId"/);
assert.match(source, /name="avatar"[\s\S]*type="hidden"|type="hidden"[\s\S]*name="avatar"/);
assert.doesNotMatch(source, /data-region-profile-form/);
assert.doesNotMatch(source, /data-region-profile-status/);
assert.match(source, /role="group" aria-labelledby="profile-region-heading" aria-describedby="profile-region-contract-note profile-region-picker-status"/);
assert.match(source, /<label for="profileProvinceCode">省/);
assert.match(source, /<label for="profileCityCode">市/);
assert.match(source, /<label for="profileDistrictCode">区县/);
assert.match(source, /id="profile-region-contract-note"/);
assert.match(source, /id="profile-region-picker-status"[^>]*data-region-picker-status role="status" aria-live="polite"/);
assert.match(source, /data-region-search-form[^>]*novalidate/);
assert.match(source, /id="profileRegionKeyword"[^>]*aria-describedby="profile-region-search-status"[^>]*required/);
assert.match(source, /data-region-search-status role="status" aria-live="polite"/);
assert.match(source, /src="public\/js\/upload-pages\.js"/);
assert.match(source, /src="public\/js\/region-pages\.js"/);
assert.match(source, /data-profile-load-status/);
assert.match(source, /data-profile-status[^>]*role="status"/);
assert.match(source, /data-genealogy-context-link/);
assert.doesNotMatch(source, /第二代 顺字辈|微信 \/ QQ|学历 \/ 职业|父亲<\/span><b>某某/);
});
test('地区搜索复用统一状态组件并区分空结果、失败和无权限', () => {
const source = fs.readFileSync(path.join(__dirname, '..', 'public', 'js', 'region-pages.js'), 'utf8');
assert.match(source, /root\.ProfileUI && root\.ProfileUI\.setApiState/);
assert.match(source, /setApiState\(results, 'loading', '正在搜索地区…'\)/);
assert.match(source, /setApiState\(container, 'empty', '未找到匹配地区'\)/);
assert.match(source, /当前账号无权搜索地区。/);
assert.match(source, /当前账号无权定位地区。/);
assert.match(source, /当前账号无权读取地区数据。/);
assert.match(source, /setPickerState\(picker, 'loading', '正在加载省…'\)/);
assert.match(source, /setPickerState\(picker, 'loading', '正在加载市…'\)/);
assert.match(source, /setPickerState\(picker, 'loading', '正在加载区县…'\)/);
assert.equal(RegionPages.isForbidden({ status: 403 }), true);
assert.equal(RegionPages.isForbidden({ status: 401 }), false);
});
test('个人资料页不伪造亲属数据,并明确指向当前家谱的成员管理', () => {
const source = fs.readFileSync(path.join(__dirname, '..', 'profile-data.html'), 'utf8');
assert.match(source, /当前 PC 资料接口未提供个人亲属关系列表/);
assert.match(source, /href="profile-family-admin\.html"[^>]*data-genealogy-context-link/);
assert.match(source, /api-state--empty/);
assert.doesNotMatch(source, /张三|父亲 · 已绑定成员资料|邀请激活/);
});
test('个人中心以桌面服务面板承接 APP 的账户功能,并隔离家谱业务入口', () => {
const source = fs.readFileSync(path.join(__dirname, '..', 'profile.html'), 'utf8');
const main = source.slice(0, source.indexOf('</main>'));
assert.match(main, /<h2>账户与服务<\/h2>/);
[
'profile-messages.html',
'profile-data.html',
'profile-security.html',
'profile-services.html',
'profile-feedback.html',
'app.html'
].forEach((href) => {
assert.match(main, new RegExp('href="' + href.replace('.', '\\.') + '"'));
});
assert.doesNotMatch(main, /href="profile-(?:article|album|video|merit|gift|join-review)\.html"/);
});
test('个人中心首页概览只展示已声明的账户资料字段', () => {
const source = fs.readFileSync(path.join(__dirname, '..', 'profile.html'), 'utf8');
['phone', 'displayName', 'realName', 'sex', 'birthday', 'email'].forEach((field) => {
assert.match(source, new RegExp('data-profile-text="' + field + '"'));
});
assert.doesNotMatch(source, /data-profile-text="regionText"/);
assert.match(source, /<div class="profile-load-status" data-profile-load-status role="status" aria-live="polite">/);
});