const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const CeremonyPages = require('../public/js/ceremony-pages.js');
test('我的邀请响应保留完整展示字段并保持业务 ID 为字符串', () => {
assert.deepEqual(CeremonyPages.normalizeInvitation({
invitationId: '2060000000000000001',
genealogyId: '2060000000000000002',
ceremonyId: '2060000000000000003',
inviteeUserId: '2060000000000000004',
inviteStatus: 'PENDING',
inviteVersion: 2,
deliveredTime: '2026-07-29T09:00:00+08:00',
readTime: null,
responseTime: null,
ceremonyTitle: '家族答谢宴',
ceremonyTime: '2026-08-08T18:00:00+08:00',
location: '锦江厅',
locationAddress: '成都市锦江区示例路 8 号',
longitude: 104.0668,
latitude: 30.5728
}), {
invitationId: '2060000000000000001',
genealogyId: '2060000000000000002',
ceremonyId: '2060000000000000003',
inviteeUserId: '2060000000000000004',
inviteStatus: 'PENDING',
inviteVersion: 2,
deliveredTime: '2026-07-29T09:00:00+08:00',
readTime: '',
responseTime: '',
ceremonyTitle: '家族答谢宴',
ceremonyTime: '2026-08-08T18:00:00+08:00',
location: '锦江厅',
locationAddress: '成都市锦江区示例路 8 号',
longitude: 104.0668,
latitude: 30.5728
});
});
test('邀请响应拒绝缺少稳定 ID、非法状态和不安全数字长 ID', () => {
assert.equal(CeremonyPages.normalizeInvitation({
invitationId: '1',
genealogyId: '2',
inviteeUserId: '4',
inviteStatus: 'PENDING'
}), null);
assert.equal(CeremonyPages.normalizeInvitation({
invitationId: '1',
genealogyId: '2',
ceremonyId: '3',
inviteeUserId: '4',
inviteStatus: 'UNKNOWN'
}), null);
assert.equal(CeremonyPages.normalizeInvitation({
invitationId: Number('2060000000000000001'),
genealogyId: '2',
ceremonyId: '3',
inviteeUserId: '4',
inviteStatus: 'PENDING'
}), null);
});
test('YAML 未声明必返的 inviteeUserId 缺失时仍可用活动上下文响应', () => {
const invitation = CeremonyPages.normalizeInvitation({
invitationId: '1',
genealogyId: '2',
ceremonyId: '3',
inviteStatus: 'PENDING'
});
assert.notEqual(invitation, null);
assert.equal(invitation.inviteeUserId, undefined);
assert.equal(CeremonyPages.canRespondToInvitation(invitation), true);
});
test('响应邀请只允许提交 YAML 定义的 inviteStatus 字段', () => {
assert.deepEqual(CeremonyPages.buildInvitationResponseBody({
inviteStatus: 'ACCEPTED',
invitationId: '2060000000000000001',
inviteVersion: 2
}), {
inviteStatus: 'ACCEPTED'
});
assert.deepEqual(CeremonyPages.buildInvitationResponseBody({ inviteStatus: 'DECLINED' }), {
inviteStatus: 'DECLINED'
});
assert.equal(CeremonyPages.validateInvitationResponseBody({ inviteStatus: 'PENDING' }), '邀请只能选择接受或拒绝');
});
test('只有待响应邀请显示接受和拒绝动作', () => {
assert.equal(CeremonyPages.canRespondToInvitation({ inviteStatus: 'PENDING' }), true);
assert.equal(CeremonyPages.canRespondToInvitation({ inviteStatus: 'ACCEPTED' }), false);
assert.equal(CeremonyPages.canRespondToInvitation({ inviteStatus: 'DECLINED' }), false);
assert.equal(CeremonyPages.canRespondToInvitation({ inviteStatus: 'CANCELED' }), false);
});
test('邀请列表渲染转义内容、展示详情但不直接暴露内部 ID 和坐标', () => {
const invitation = CeremonyPages.normalizeInvitation({
invitationId: '2060000000000000001',
genealogyId: '2060000000000000002',
ceremonyId: '2060000000000000003',
inviteeUserId: '2060000000000000004',
inviteStatus: 'PENDING',
inviteVersion: 1,
ceremonyTitle: '',
ceremonyTime: '2026-08-08T18:00:00+08:00',
location: '锦江厅',
locationAddress: '成都市锦江区示例路 8 号',
longitude: 104.0668,
latitude: 30.5728
});
const row = CeremonyPages.renderInvitationRow(invitation);
const detail = CeremonyPages.renderInvitationDetail(invitation);
assert.doesNotMatch(row, /