修改完成待测试
This commit is contained in:
@@ -16,9 +16,17 @@ const listPageSources = (directory = 'pages') => fs.readdirSync(path.join(worksp
|
||||
})
|
||||
|
||||
const signIn = read('pages/auth/sign-in.vue')
|
||||
const loginAdvertisement = read('components/auth/LoginAdvertisement.vue')
|
||||
const register = read('pages/auth/register.vue')
|
||||
const routes = read('utils/navigation/routes.js')
|
||||
const genealogyHome = read('pages/genealogy/my-genealogies.vue')
|
||||
const profileHomePage = read('pages/profile/home.vue')
|
||||
const homeAdvertisementPanel = read('components/genealogy/HomeAdvertisementPanel.vue')
|
||||
const genealogyOverview = read('pages/genealogy/overview.vue')
|
||||
const genealogyCard = read('components/genealogy/Card.vue')
|
||||
const familyFeedPage = read('pages/family/feed.vue')
|
||||
const siteHomePage = read('pages/family/site-home.vue')
|
||||
const siteContentContract = read('services/api/site-content-contract.js')
|
||||
const invitationManager = read('components/genealogy/InvitationManager.vue')
|
||||
const pedigree = read('pages/tree/pedigree.vue')
|
||||
const treeOverview = read('pages/tree/overview.vue')
|
||||
@@ -26,6 +34,7 @@ const moduleBackground = read('components/ModulePageBackground.vue')
|
||||
const genealogyBackground = read('components/genealogy/PageBackground.vue')
|
||||
const vipPage = read('pages/profile/vip.vue')
|
||||
const promotionsPage = read('pages/profile/promotions.vue')
|
||||
const referralQrCode = read('components/ReferralQrCode.vue')
|
||||
const helpPage = read('pages/profile/help.vue')
|
||||
const editProfilePage = read('pages/profile/edit-profile.vue')
|
||||
const genealogySettingsPage = read('pages/genealogy/settings.vue')
|
||||
@@ -45,6 +54,12 @@ const changePhonePage = read('pages/profile/change-phone.vue')
|
||||
const changePasswordPage = read('pages/profile/change-password.vue')
|
||||
const platformVideosPage = read('pages/family/platform-videos.vue')
|
||||
const familyMediaContract = read('services/api/family-media-contract.js')
|
||||
const batchDeletionComposable = read('composables/use-batch-deletion.js')
|
||||
const batchManagementBar = read('components/BatchManagementBar.vue')
|
||||
const batchSelectionMark = read('components/BatchSelectionMark.vue')
|
||||
const familyArticleService = read('services/api/family-article-service.js')
|
||||
const familyArticleContract = read('services/api/family-article-contract.js')
|
||||
const lifeRecordService = read('services/api/life-record-service.js')
|
||||
const dialogPages = [
|
||||
'pages/tree/pedigree.vue',
|
||||
'pages/family/album-detail.vue',
|
||||
@@ -63,7 +78,6 @@ const memberDirectoryPage = read('pages/tree/member-directory.vue')
|
||||
const peoplePage = read('pages/records/people.vue')
|
||||
const idValidatedPages = [
|
||||
'pages/tree/add-relative.vue',
|
||||
'pages/tree/member-rank.vue',
|
||||
'pages/tree/member-profile.vue',
|
||||
'pages/tree/member-states.vue',
|
||||
'pages/genealogy/generation-poems.vue',
|
||||
@@ -92,7 +106,6 @@ const genealogyContract = read('services/api/genealogy-contract.js')
|
||||
const genealogySearchPage = read('pages/genealogy/search.vue')
|
||||
const generationPoemService = read('services/api/generation-poem-service.js')
|
||||
const genealogyMemberService = read('services/api/genealogy-member-service.js')
|
||||
const lifeRecordService = read('services/api/life-record-service.js')
|
||||
const personDocumentService = read('services/api/person-document-service.js')
|
||||
const mediaUpload = read('utils/media-upload.js')
|
||||
const businessFileContract = read('services/api/business-file-contract.js')
|
||||
@@ -119,6 +132,29 @@ expect(!signIn.includes('协议页面准备中'), '登录页仍使用协议占
|
||||
expect(!register.includes('协议页面准备中'), '注册页仍使用协议占位提示')
|
||||
expect(signIn.includes('openComplianceDocument'), '登录页没有接入协议正文导航')
|
||||
expect(register.includes('openComplianceDocument'), '注册页没有接入协议正文导航')
|
||||
expect(
|
||||
signIn.includes('<LoginAdvertisement') &&
|
||||
loginAdvertisement.includes('placement: "home_banner"') &&
|
||||
loginAdvertisement.includes('promotion.coverFile.accessUrl') &&
|
||||
loginAdvertisement.includes('home-ad-heritage-hall.png') &&
|
||||
!loginAdvertisement.includes('点击查看更多内容'),
|
||||
'登录页没有在注册入口上方显示单张祠堂山水图,或仍带有查看更多文案',
|
||||
)
|
||||
expect(
|
||||
signIn.includes('justify-content: flex-start') &&
|
||||
signIn.includes('color: #5d493b') &&
|
||||
signIn.includes('color: #766c63'),
|
||||
'登录页仍使用自动撑开的旧布局,或次要文字颜色没有加深',
|
||||
)
|
||||
expect(
|
||||
/\.login-page\s*\{[^}]*height:\s*var\(--app-viewport-height\)[^}]*max-height:\s*var\(--app-viewport-height\)[^}]*overflow:\s*hidden/.test(signIn) &&
|
||||
/\.login-page\s+:deep\(\.auth-shell__paper\)\s*\{[^}]*min-height:\s*0[^}]*overflow:\s*hidden/.test(signIn),
|
||||
'登录页没有锁定动态 100vh,新增广告后仍可能产生页面级滚动',
|
||||
)
|
||||
expect(
|
||||
/getPromotions[\s\S]*?authenticated:\s*false/.test(siteContentService),
|
||||
'公开广告接口仍会携带登录态,登录页无法安全读取 home_banner',
|
||||
)
|
||||
expect(
|
||||
/getComplianceDocument[\s\S]*?authenticated:\s*false/.test(siteContentService),
|
||||
'协议正文请求仍依赖登录状态',
|
||||
@@ -128,13 +164,15 @@ const complianceRoute = routes.match(/M13: defineRoute\(\{[\s\S]*?^\s{2}\}\),/m)
|
||||
expect(complianceRoute.includes('"A01"'), '协议正文路由不允许从登录页进入')
|
||||
expect(complianceRoute.includes('"A04"'), '协议正文路由不允许从注册页进入')
|
||||
const membersRoute = routes.match(/G13: defineRoute\(\{[\s\S]*?^\s{2}\}\),/m)?.[0] || ''
|
||||
expect(membersRoute.includes('"G01"'), '成员页路由不允许从家谱首页进入')
|
||||
expect(!membersRoute.includes('"G01"'), '成员页仍允许从家谱首页旧入口进入')
|
||||
expect(
|
||||
/members:\s*\(\)\s*=>\s*openPage\("G13"/.test(genealogyHome),
|
||||
'家谱首页“成员”没有直达成员列表',
|
||||
genealogyOverview.includes('openPage("G13"') &&
|
||||
!genealogyHome.includes('shortcut-grid') &&
|
||||
!genealogyHome.includes('openShortcut'),
|
||||
'家谱快捷导航没有完整迁移到家谱详情页',
|
||||
)
|
||||
const platformVideosRoute = routes.match(/F11: defineRoute\(\{[\s\S]*?^\s{2}\}\),/m)?.[0] || ''
|
||||
expect(platformVideosRoute.includes('"G01"'), '宣传视频路由不允许从家谱首页进入')
|
||||
expect(!platformVideosRoute.includes('"G01"') && platformVideosRoute.includes('"F10"'), '宣传视频没有迁回原视频导航')
|
||||
expect(platformVideosRoute.includes('"videoId"'), '宣传视频路由不能携带指定视频 ID')
|
||||
expect(
|
||||
familyMediaContract.includes("HOME_FEATURED: 'home_featured'") &&
|
||||
@@ -142,10 +180,72 @@ expect(
|
||||
familyMediaContract.includes("PROFILE_FEATURED: 'profile_featured'"),
|
||||
'平台视频契约没有完整覆盖后端三个投放位',
|
||||
)
|
||||
expect(genealogyHome.includes('featured-media-grid'), '家谱首页没有宣传视频封面预览')
|
||||
expect(
|
||||
genealogyHome.includes('PLATFORM_VIDEO_PLACEMENT.HOME_FEATURED'),
|
||||
'家谱首页没有读取首页推荐视频投放位',
|
||||
!genealogyHome.includes('featured-media-grid') &&
|
||||
!genealogyHome.includes('PLATFORM_VIDEO_PLACEMENT.HOME_FEATURED'),
|
||||
'家谱首页仍保留已经迁出的宣传视频',
|
||||
)
|
||||
expect(
|
||||
!genealogyHome.includes('genealogy-create-button') &&
|
||||
!genealogyHome.includes('新建家谱') &&
|
||||
genealogyHome.includes('class="create-action"') &&
|
||||
genealogyHome.includes('添加家谱'),
|
||||
'家谱首页仍在顶部显示误加的新建按钮,或列表末尾缺少原有添加入口',
|
||||
)
|
||||
expect(
|
||||
genealogyHome.indexOf('class="genealogy-list-scroll"') <
|
||||
genealogyHome.indexOf('class="genealogy-list-toolbar"') &&
|
||||
!genealogyHome.includes('genealogy-fixed-zone'),
|
||||
'家谱分组标题仍被固定在第 7 条标注的滚动区域之外',
|
||||
)
|
||||
expect(
|
||||
siteContentContract.includes("news: '资讯'") &&
|
||||
siteContentContract.includes("notice: '公告'") &&
|
||||
siteHomePage.includes('article.typeLabel'),
|
||||
'官网文章类型仍直接暴露后端英文编码',
|
||||
)
|
||||
expect(
|
||||
genealogyHome.includes('<HomeAdvertisementPanel') &&
|
||||
homeAdvertisementPanel.includes('home-ad-heritage-hall.png') &&
|
||||
homeAdvertisementPanel.includes('home-ad-family-tree.png') &&
|
||||
homeAdvertisementPanel.includes('点击查看更多内容') &&
|
||||
!genealogyHome.includes('home-news-card') &&
|
||||
!genealogyHome.includes('<AppPromotionStrip'),
|
||||
'首页底部固定区域没有按参考图显示两张并排图片,或仍使用错误的文字/横向广告卡',
|
||||
)
|
||||
expect(
|
||||
genealogyCard.includes('创建于 {{ formatGenealogyDate(genealogy.createTime) }}') &&
|
||||
!genealogyCard.includes('加入于 {{ formatGenealogyDate(genealogy.joinTime) }}'),
|
||||
'家谱卡片没有按后端真实 createTime 显示创建日期',
|
||||
)
|
||||
expect(
|
||||
genealogyOverview.includes('familyContentGroups') &&
|
||||
genealogyOverview.includes('openFamilySection') &&
|
||||
!familyFeedPage.includes('feed-shortcuts'),
|
||||
'家族内容导航没有迁入家谱详情并完成归类',
|
||||
)
|
||||
expect(
|
||||
siteHomePage.includes('siteContentApi.getSiteArticles') &&
|
||||
siteHomePage.includes('<AppTabbar v-if="!subpageMode" active="family"') &&
|
||||
!familyFeedPage.includes('<AppTabbar'),
|
||||
'消息根页没有继续承载公共新闻资讯,或家谱动态仍占用根导航',
|
||||
)
|
||||
expect(read('components/AppTabbar.vue').includes('label: "消息"'), '底部中间导航没有改为消息')
|
||||
expect(
|
||||
fs.existsSync(path.join(workspace, 'pages/family/site-article-list.vue')) &&
|
||||
read('pages/family/site-article-list.vue').includes('subpage-mode'),
|
||||
'公共资讯子列表没有与消息根页复用同一实现',
|
||||
)
|
||||
expect(routes.includes('path: "/pages/family/site-home"') && !routes.includes('path: "/pages/notification/message-home"') && !routes.includes('path: "/pages/profile/message-home"'), '消息根页没有指向原新闻资讯页面')
|
||||
expect(!profileHomePage.includes('isMessagePortal'), '我的页面仍混入消息页变体逻辑')
|
||||
expect(!profileHomePage.includes('class="profile-metadata"'), '我的页面仍显示应删除的性别、生日和邮箱摘要卡')
|
||||
expect(profileHomePage.includes('家谱新闻列表(图文)') && profileHomePage.includes('家谱系列文章(图文)'), '我的菜单没有按标注图补齐')
|
||||
expect(
|
||||
profileHomePage.includes('<HomeAdvertisementPanel') &&
|
||||
profileHomePage.includes('class="profile-home-advertisements"') &&
|
||||
!profileHomePage.includes('广告位列表') &&
|
||||
!routes.includes('F14: defineRoute'),
|
||||
'我的页面底部没有直接复用首页图片广告,或仍保留错误的广告位列表入口',
|
||||
)
|
||||
expect(
|
||||
platformVideosPage.includes('video-card__cover-button') &&
|
||||
@@ -157,6 +257,10 @@ expect(
|
||||
genealogyHome.includes('getRequestErrorMessage'),
|
||||
'家谱首页仍会隐藏家谱列表的真实失败类型',
|
||||
)
|
||||
expect(
|
||||
/import\s*\{[^}]*normalizeOptionalNumericId[^}]*\}\s*from '\.\/response-normalizers\.js'/.test(genealogyContract),
|
||||
'家谱响应契约使用 normalizeOptionalNumericId 时没有从响应归一化模块导入',
|
||||
)
|
||||
expect(
|
||||
articleListPage.includes('articleCategoryError') &&
|
||||
articleListPage.includes('getRequestErrorMessage'),
|
||||
@@ -240,6 +344,11 @@ expect(
|
||||
/promotion-card__actions[^>]*@click\.stop/.test(promotionsPage),
|
||||
'推广操作按钮会继续触发卡片跳转',
|
||||
)
|
||||
expect(
|
||||
promotionsPage.includes('<ReferralQrCode :value="referralProfile.shareUrl"') &&
|
||||
referralQrCode.includes('class="referral-qr-code"'),
|
||||
'推广页没有根据后端 shareUrl 展示推荐二维码',
|
||||
)
|
||||
expect(
|
||||
/\.help-article-list\s*\{[^}]*margin-top:\s*18rpx/.test(helpPage),
|
||||
'帮助中心分类栏与首条问答之间缺少间距',
|
||||
@@ -273,6 +382,13 @@ for (const field of ['withdrawalNo', 'auditRemark', 'payoutReference', 'paidAt']
|
||||
expect(earningsPage.includes(`withdrawal.${field}`), `提现记录没有显示 ${field}`)
|
||||
}
|
||||
expect(relativeRecordsPage.includes('item.mediaFiles?.[0]?.accessUrl'), '贺礼簿列表没有显示首图')
|
||||
expect(meritRecordsPage.includes('item.mediaFiles?.[0]?.accessUrl'), '功德记录列表没有显示首图')
|
||||
expect(memoPage.includes('item.mediaFiles?.[0]?.accessUrl'), '备忘录和恩人录列表没有显示首图')
|
||||
expect(
|
||||
platformVideosPage.includes('video-card__cover-placeholder') &&
|
||||
!/<video\s+v-else[\s\S]*?class="video-card__player"/.test(platformVideosPage),
|
||||
'宣传视频列表无封面时仍直接铺设播放器',
|
||||
)
|
||||
expect(growthJournalPage.includes('field !== "lineagePersonId"'), '成长记录仍把自动带入人物直接判为用户修改')
|
||||
const joinApplicationRoute = routes.match(/G08: defineRoute\(\{[\s\S]*?^\s{2}\}\),/m)?.[0] || ''
|
||||
expect(joinApplicationRoute.includes('"genealogyName"'), '公开家谱申请页路由仍拒绝谱名参数')
|
||||
@@ -353,9 +469,10 @@ for (const [pageName, pageSource] of [
|
||||
for (const pagePath of idValidatedPages) {
|
||||
expect(read(pagePath).includes('/^[1-9]\\d*$/.test(genealogyId.value)'), `${pagePath} 没有校验家谱 ID`)
|
||||
}
|
||||
expect(memberRankPage.includes('createDiscardConfirmation'), '成员排行页缺少未保存修改确认')
|
||||
expect(memberRankPage.includes('dirty: isDirty.value'), '成员排行页返回守卫未检查排序修改')
|
||||
expect(memberRankPage.includes('sortOrderBaseline.value = normalizedSortOrder'), '成员排行保存成功后没有更新草稿基准')
|
||||
expect(memberRankPage.includes('returnTo("T05", { genealogyId, personId })'), '旧成员排行页没有统一转入成员编辑页')
|
||||
expect(!memberRankPage.includes('lineageApi.updatePerson'), '旧成员排行页仍保留独立保存逻辑')
|
||||
expect(!memberRankPage.includes('<text>排序值</text>'), '独立排行页仍要求普通用户手填排序值')
|
||||
expect(!memberRankPage.includes('updatePersonSortOrder'), '独立排行页仍会提交手工排序值')
|
||||
expect(editProfilePage.includes('original[field] = payload[field]'), '编辑资料保存成功后没有更新草稿基准')
|
||||
expect(meritRecordsPage.includes('/^(?:0|[1-9]\\d{0,9})(?:\\.\\d{1,2})?$/'), '功德记录页面没有限制金额精度和范围')
|
||||
expect(lifeRecordContract.includes("normalizeOptionalCurrencyNumber(payload.amount, '功德金额')"), '功德记录 API 契约没有限制金额精度和范围')
|
||||
@@ -369,6 +486,21 @@ expect(
|
||||
editMemberPage.match(/\/\^\[1-9\]\\d\*\$\/.test/g)?.length >= 4,
|
||||
'修改成员页没有完整校验家谱和人物 ID',
|
||||
)
|
||||
expect(editMemberPage.includes('lineageApi.getRankOptions'), '修改成员页没有读取排行称谓选项')
|
||||
expect(editMemberPage.includes('rankId: editForm.rankId'), '修改成员页没有提交所选排行称谓')
|
||||
expect(editMemberPage.includes('暂无可选排行'), '修改成员页没有展示排行配置缺失状态')
|
||||
expect(!editMemberPage.includes('<text>排序值</text>'), '修改成员页仍要求普通用户手填排序值')
|
||||
expect(addRelativePage.includes('lineageApi.getRankOptions'), '新增亲属页没有读取排行称谓选项')
|
||||
expect(addRelativePage.includes('{ rankId: addForm.rankId }'), '新增亲属页没有提交所选排行称谓')
|
||||
expect(!addRelativePage.includes('<text>排序值</text>'), '新增亲属页仍要求普通用户手填排序值')
|
||||
expect(addRelativePage.includes('MemberDatePickerSheet'), '新增亲属页没有复用成员日期选择器')
|
||||
expect(!addRelativePage.includes('mode="date"'), '新增亲属页仍在使用可选择未来年份的系统日期控件')
|
||||
expect(addRelativePage.includes('不能晚于今天'), '新增亲属页没有在提交前拦截未来日期')
|
||||
expect(!treeOverview.includes('writing-mode: vertical-rl'), '树状图世代信息仍被强制逐字竖排')
|
||||
expect(treeOverview.includes('-webkit-line-clamp: 2'), '树状图长姓名仍会被单行省略号截断')
|
||||
expect(!editMemberPage.includes('`${name}(${personOptionId})`'), '修改成员页仍向用户暴露人物内部 ID')
|
||||
expect(editMemberPage.includes('sortOrder: editForm.sortOrder'), '隐藏排序值后修改成员会把原顺序重置为零')
|
||||
expect(!treeOverview.includes('@click="toRank"') && !treeOverview.includes('ADJUST_RANK'), '树状图仍保留重复的独立排行入口')
|
||||
expect(
|
||||
/v-if="feed\.canDelete"[\s\S]*?label="删除动态"/.test(feedDetailPage),
|
||||
'动态详情向无删除权限用户显示删除按钮',
|
||||
@@ -420,6 +552,38 @@ expect(memoPage.includes('memo.memoType === memoType.value'), '家族恩人列
|
||||
for (const contractSource of [lifeRecordContract, familyMediaContract, read('services/api/ceremony-contract.js')]) {
|
||||
expect(contractSource.includes('createTime:'), '资源响应契约没有保留后端 createTime')
|
||||
}
|
||||
expect(batchDeletionComposable.includes('for (const id of pendingIds)') && batchDeletionComposable.includes('break'), '批量删除没有按顺序执行或遇到失败后停止')
|
||||
expect(batchDeletionComposable.includes('selectedIds.value = selectedIds.value.filter'), '批量删除成功后没有移除已完成选择')
|
||||
expect(batchManagementBar.includes('仅可选择有删除权限的内容'), '批量管理没有说明权限边界')
|
||||
expect(batchSelectionMark.includes('role="checkbox"') && batchSelectionMark.includes(':aria-checked="selected"'), '批量选择控件缺少复选语义')
|
||||
for (const [pageSource, resourceName] of [
|
||||
[articleListPage, '谱文'],
|
||||
[familyVideosPage, '视频'],
|
||||
[ceremonyListPage, '礼仪活动'],
|
||||
[meritRecordsPage, '功德记录'],
|
||||
[relativeRecordsPage, '往来记录'],
|
||||
[memoPage, '家族备忘/恩人'],
|
||||
[growthJournalPage, '成长记录'],
|
||||
[personDocumentDialog, '重要证件'],
|
||||
]) {
|
||||
expect(pageSource.includes('useBatchDeletion'), `${resourceName}没有接入统一批量删除状态`)
|
||||
expect(pageSource.includes('BatchManagementBar') && pageSource.includes('BatchSelectionMark'), `${resourceName}缺少批量管理入口或选择控件`)
|
||||
}
|
||||
expect(/createArticle[\s\S]*?normalizeAppArticle\(article, normalizedGenealogyId\)/.test(familyArticleService), '谱文创建响应没有规范化,无法可靠继续设置密码')
|
||||
expect(/createGrowthRecord[\s\S]*?normalizeAppGrowthRecord\(growthRecord, normalizedGenealogyId\)/.test(lifeRecordService), '成长记录创建响应没有规范化,无法可靠继续设置密码')
|
||||
expect(/genealogyNo:\s*normalizeGenealogyResponseText\(item\.genealogyNo/.test(genealogyContract), '我的家谱响应没有保留后端返回的稳定家谱编号')
|
||||
expect(genealogyContract.includes("createTime: normalizeGenealogyResponseText(item.createTime, 'createTime')"), '我的家谱响应没有保留后端真实创建时间')
|
||||
expect(genealogyContract.includes('createTime: genealogy.createTime'), '我的家谱列表规范化时丢弃了真实创建时间')
|
||||
expect(familyArticleContract.includes("'mediaOssIds'") && familyArticleContract.includes('normalizedPayload.mediaOssIds'), '谱文请求契约没有提交正文图片标识')
|
||||
expect(familyArticleContract.includes('mediaFiles: normalizeBusinessFileAccessRows'), '谱文响应契约没有保留正文图片')
|
||||
expect(articleEditorPage.includes('mediaReceipts') && articleEditorPage.includes('mediaOssIds') && articleEditorPage.includes('removeArticleMedia'), '谱文编辑页没有完整支持正文多图新增、回显和移除')
|
||||
expect(articleDetailPage.includes(':files="article.mediaFiles"'), '谱文详情没有按后端顺序显示正文图片')
|
||||
expect(/createArticle[\s\S]*?setArticlePassword/.test(articleEditorPage), '新建谱文没有在创建成功后继续设置内容密码')
|
||||
expect(/createGrowthRecord[\s\S]*?setGrowthRecordPassword/.test(growthJournalPage), '新建成长记录没有在创建成功后继续设置内容密码')
|
||||
expect(/createPersonDocument[\s\S]*?setPersonDocumentPassword/.test(personDocumentDialog), '新建重要证件没有在创建成功后继续设置内容密码')
|
||||
for (const protectedCreateSource of [articleEditorPage, growthJournalPage, personDocumentDialog]) {
|
||||
expect(protectedCreateSource.includes('可能尚未受到密码保护'), '两阶段创建没有明确提示密码设置失败后的未保护风险')
|
||||
}
|
||||
expect(permissionContract.includes('item.code'), '权限目录仍读取旧版 permissionCode 字段')
|
||||
expect(permissionContract.includes('item.groupName'), '权限目录没有接入后端权限分组')
|
||||
expect(genealogyCapabilityService.includes('/comments/page`'), '家族视频根评论仍调用旧列表路径')
|
||||
|
||||
Reference in New Issue
Block a user