| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- 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')
|