Files
shanxia2.0/web-admin/scripts/test-mp-crm-product-dom.mjs
2026-10-19 18:28:02 +08:00

77 lines
3.5 KiB
JavaScript

import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
const root = new URL('../src/views/m/crm/product/', import.meta.url)
const list = await readFile(new URL('index.vue', root), 'utf8')
const detail = await readFile(new URL('detail.vue', root), 'utf8')
const form = await readFile(new URL('form.vue', root), 'utf8')
const formDialog = await readFile(
new URL('../src/components/business/product-form-dialog/index.vue', import.meta.url),
'utf8'
)
const order = ['<MpBusinessHeader', '<MpStatusTabs', '<MpThreeColumnFilters', '<MpExpenseCard'].map(
(token) => list.indexOf(token)
)
assert.ok(
order.every((index) => index >= 0),
'产品列表必须使用四个共享展示原语'
)
assert.deepEqual(
[...order].sort((a, b) => a - b),
order,
'列表必须依次为搜索、Tab、三栏筛选、卡片'
)
assert.match(list, /<template #actions>/, '产品卡必须提供虚线操作底栏')
assert.match(list, /编辑/, '产品卡必须提供编辑动作')
assert.match(list, /上架|下架/, '产品卡必须提供上下架动作')
assert.match(list, /删除/, '产品卡必须保留删除动作')
assert.equal(
(list.match(/class="mp-wv-speed-item/g) || []).length,
2,
'Speed Dial 必须保留分类和新增双入口'
)
assert.match(list, /requestSeq/, '列表必须用请求序号隔离过期响应')
assert.match(list, /requestSnapshot/, '列表必须用查询快照隔离过期响应')
assert.match(list, /fetchProductColumnFacetValues/, '型号快捷筛选必须来自完整列值接口')
assert.match(list, /role="alert"/, '分页失败必须显示可见错误')
assert.match(list, /categoryRequestSeq/, '分类树加载必须隔离过期响应')
assert.match(
list,
/categoryMapLoaded\.value\s*=\s*false|categoryMapLoaded\s*=\s*false/,
'分类失败必须允许重试'
)
assert.match(
list,
/\.mp-wv-speed-item[\s\S]*min-height:\s*44px/,
'Speed Dial 项命中高度不得小于 44px'
)
assert.doesNotMatch(
list,
/from 'vue'|from 'vue-router'|from 'element-plus'/,
'不得手工导入自动导入项'
)
assert.match(detail, /title="产品详情"/, '详情顶栏必须使用固定标题')
assert.doesNotMatch(detail, /\{\{\s*headerTitle\s*\}\}/, '详情顶栏不得使用记录标题')
assert.doesNotMatch(detail, /mp-wv-header__sub/, '详情顶栏不得展示副标题')
assert.match(detail, /class="mp-product-detail-tabs"/, '详情必须提供业务 Tab')
assert.match(detail, /mp-wv-fab-bar[\s\S]*mp-wv-touch-target/, '详情底栏按钮必须使用 44px 触达类')
assert.match(detail, /preview-src-list/, '详情必须保留图片预览')
assert.match(detail, /canDeleteByCreator/, '详情必须保留创建人删除权限')
assert.match(detail, /requestSeq/, '详情必须隔离过期详情响应')
assert.match(detail, /requestedId[\s\S]*route\.params\.id/, '详情必须校验 ID 查询快照')
assert.match(detail, /categoryRequestSeq/, '详情分类树必须隔离过期响应')
assert.match(detail, /status-tag--/, '详情状态必须使用 WebView 浅底语义标签')
assert.doesNotMatch(
detail,
/from 'vue'|from 'vue-router'|from 'element-plus'/,
'不得手工导入自动导入项'
)
assert.match(form, /<MpBusinessHeader/, '产品表单必须使用标准头并保留返回入口')
assert.match(formDialog, /72px/, '移动产品图片必须使用约 72×72 宫格')
assert.match(formDialog, /min-height:\s*44px/, '产品表单返回、底栏和上传操作命中高度不得小于 44px')
console.log('product DOM contract: PASS')