|
|
@@ -0,0 +1,105 @@
|
|
|
+/**
|
|
|
+ * Contract tests for capability key `family.invite.joinRequestCardInfo`
|
|
|
+ * (spec: docs/superpowers/specs/2026-11-07-family-join-required-info.md §5 WI-4)
|
|
|
+ *
|
|
|
+ * AC4.1 待审批卡片显示申请人真实姓名、出生日期、性别。
|
|
|
+ * AC4.2 任一字段缺失时优雅回退(不报错、不显示乱码)。
|
|
|
+ *
|
|
|
+ * TDD phase: RED. These tests target the REAL `family-members.vue` join-request
|
|
|
+ * card. The current implementation only renders the requester's name
|
|
|
+ * (`requesterRealName || requesterNickname`); it does NOT render the applicant's
|
|
|
+ * birthday or gender. Therefore the AC4.1 assertions are expected to FAIL until
|
|
|
+ * WI-4 is implemented (approval card shows birthday + gender).
|
|
|
+ *
|
|
|
+ * Note: `@jest-environment jsdom` is required because @vue/test-utils `mount`
|
|
|
+ * needs a DOM; the default `node` env does not provide one.
|
|
|
+ *
|
|
|
+ * @jest-environment jsdom
|
|
|
+ */
|
|
|
+import { mount } from '@vue/test-utils'
|
|
|
+import FamilyMembers from '@/pages/profile-extra/family-members.vue'
|
|
|
+
|
|
|
+// A fully-populated pending join request (FamilyJoinRequestDTO shape).
|
|
|
+const fullRequest = {
|
|
|
+ id: 1001,
|
|
|
+ requesterUserId: 200,
|
|
|
+ requesterRealName: '张三',
|
|
|
+ requesterNickname: 'zhangsan',
|
|
|
+ requesterBirthday: '1990-01-01',
|
|
|
+ requesterGender: 'male',
|
|
|
+ requesterAvatar: '/static/avatar.jpg'
|
|
|
+}
|
|
|
+
|
|
|
+async function mountWithRequests(requests) {
|
|
|
+ const wrapper = mount(FamilyMembers, {
|
|
|
+ stubs: { 'generation-picker': true }
|
|
|
+ })
|
|
|
+ wrapper.setData({ joinRequests: requests || [] })
|
|
|
+ await wrapper.vm.$nextTick()
|
|
|
+ return wrapper
|
|
|
+}
|
|
|
+
|
|
|
+describe('family.invite.joinRequestCardInfo (WI-4 审批卡片展示三项信息)', () => {
|
|
|
+ it('AC4.1: 审批卡片显示申请人真实姓名、出生日期、性别', async () => {
|
|
|
+ const wrapper = await mountWithRequests([fullRequest])
|
|
|
+
|
|
|
+ const section = wrapper.find('.join-request-section')
|
|
|
+ expect(section.exists()).toBe(true)
|
|
|
+
|
|
|
+ const text = section.text()
|
|
|
+ // 真实姓名(AC4.1 第一项)
|
|
|
+ expect(text).toContain('张三')
|
|
|
+ // 出生日期(AC4.1 第二项)
|
|
|
+ expect(text).toContain('1990-01-01')
|
|
|
+ // 性别(AC4.1 第三项):male/female 或其中文标签 男/女 均可
|
|
|
+ expect(text).toMatch(/(male|female|男|女)/)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('AC4.1: 性别为 female 时卡片仍展示性别信息', async () => {
|
|
|
+ const wrapper = await mountWithRequests([
|
|
|
+ Object.assign({}, fullRequest, { requesterGender: 'female', requesterRealName: '李四', requesterBirthday: '1985-06-15' })
|
|
|
+ ])
|
|
|
+ const text = wrapper.find('.join-request-section').text()
|
|
|
+ expect(text).toContain('李四')
|
|
|
+ expect(text).toContain('1985-06-15')
|
|
|
+ expect(text).toMatch(/(female|男|女)/)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('AC4.2: 出生日期/性别缺失时不报错、不显示 undefined/null 乱码,且真实姓名仍展示', async () => {
|
|
|
+ const partialRequest = {
|
|
|
+ id: 1002,
|
|
|
+ requesterUserId: 201,
|
|
|
+ requesterRealName: '王五',
|
|
|
+ requesterNickname: 'wangwu'
|
|
|
+ // requesterBirthday / requesterGender 缺失(null/undefined)
|
|
|
+ }
|
|
|
+ // 组件应正常挂载渲染(抛错即失败)
|
|
|
+ const wrapper = await mountWithRequests([partialRequest])
|
|
|
+
|
|
|
+ const text = wrapper.find('.join-request-section').text()
|
|
|
+ expect(text).toContain('王五')
|
|
|
+ // 优雅回退:不允许把缺失值渲染成字面 'undefined' / 'null'
|
|
|
+ expect(text).not.toContain('undefined')
|
|
|
+ expect(text).not.toContain('null')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('AC4.2: 真实姓名缺失时回退展示昵称(不显示空白/乱码)', async () => {
|
|
|
+ const noRealName = {
|
|
|
+ id: 1003,
|
|
|
+ requesterUserId: 202,
|
|
|
+ requesterRealName: '',
|
|
|
+ requesterNickname: 'nick_fallback',
|
|
|
+ requesterBirthday: '2000-12-31',
|
|
|
+ requesterGender: 'female'
|
|
|
+ }
|
|
|
+ const wrapper = await mountWithRequests([noRealName])
|
|
|
+ const text = wrapper.find('.join-request-section').text()
|
|
|
+ expect(text).toContain('nick_fallback')
|
|
|
+ expect(text).not.toContain('undefined')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('边界: 无待处理加入申请时不渲染审批卡片区块', async () => {
|
|
|
+ const wrapper = await mountWithRequests([])
|
|
|
+ expect(wrapper.find('.join-request-section').exists()).toBe(false)
|
|
|
+ })
|
|
|
+})
|