| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- import assert from 'node:assert/strict'
- import test from 'node:test'
- import { readFileSync } from 'node:fs'
- import { parse } from '@vue/compiler-sfc'
- import ts from 'typescript'
- import { computed, effectScope, ref, watch, nextTick } from 'vue'
- import { useMobilePlanListDetails } from '../src/views/m/pl/plan/mobileListDetails'
- import { formatBrandConstraintLabel } from '../src/utils/crm-product-brand'
- import { getPlanProductActualQuantity } from '../src/utils/pl-display'
- function card(plan: any) {
- const ast = ts.createSourceFile(
- 'card.ts',
- parse(
- readFileSync(new URL('../src/views/m/pl/plan-cert/PlanCard.vue', import.meta.url), 'utf8')
- ).descriptor.scriptSetup!.content,
- ts.ScriptTarget.Latest,
- true
- )
- const code = ast.statements
- .filter(
- (n) =>
- ts.isVariableStatement(n) &&
- n.declarationList.declarations.some((d) => d.name.getText(ast) === 'productNameLabel')
- )
- .map((n) => n.getText(ast))
- .join('\n')
- const shared = ts.createSourceFile(
- 'shared.ts',
- readFileSync(new URL('../src/utils/mp-pl-plan-card.ts', import.meta.url), 'utf8'),
- ts.ScriptTarget.Latest,
- true
- )
- const productCode = shared.statements
- .filter(
- (node) =>
- ts.isFunctionDeclaration(node) &&
- [
- 'formatStopProductLine',
- 'resolveLinkedPlanProduct',
- 'formatQty',
- 'resolveUnitLabel'
- ].includes(node.name!.text)
- )
- .map((node) => node.getText(shared))
- .join('\n')
- const env = {
- props: { plan },
- computed,
- formatBrandConstraintLabel,
- getPlanProductActualQuantity,
- resolveProductHazardFlags: () => ({ isToxic: false, isExplosive: false }),
- resolveMpPackageSpecLabel: (value: string) => value || '—',
- resolveMpProductUnitLabel: (value: string) => value || '—'
- }
- return new Function(
- ...Object.keys(env),
- `${ts.transpile(code + '\n' + productCode, { target: ts.ScriptTarget.ESNext })}; return {productNameLabel,productLine: (product, kind) => formatStopProductLine(props.plan, { kind }, product)}`
- )(...Object.values(env))
- }
- test('certificate expanded card joins list standard names, preserves segment empty brands and actual quantities', async () => {
- const scope = effectScope()
- const detail = {
- id: 'A',
- products: [
- {
- id: 'p',
- productName: '根别名',
- brandMode: 'required',
- brandName: '根品牌',
- aliasName: '根别名'
- }
- ]
- }
- const api = scope.run(() =>
- useMobilePlanListDetails({ scope: () => 'query/account', load: async () => detail })
- )!
- await api.ensure('A')
- const displayed = api.cardPlan({
- id: 'A',
- products: [{ id: 'p', productName: '标准产品' }]
- } as any)
- const h = card(displayed)
- const row = {
- planProductId: 'p',
- productName: '根别名',
- model: '99%',
- unit: '吨',
- planQty: 3,
- inboundQty: 8,
- outboundQty: 0,
- mobileProductMeta: { brandMode: 'any', brandName: '', aliasName: '送货别名' }
- }
- assert.equal(h.productNameLabel.value, '标准产品')
- const renderProduct = h.productLine
- const delivery = renderProduct(row, 'delivery')
- assert.equal(delivery.name, '标准产品')
- assert.equal(delivery.brand, '—')
- assert.equal(delivery.alias, '送货别名')
- assert.equal(delivery.actualQty, '0')
- assert.equal(renderProduct({ ...row, outboundQty: undefined }, 'delivery').actualQty, '—')
- assert.equal(renderProduct(row, 'load').actualQty, '8')
- scope.stop()
- })
- test('actual certificate list expands only the requested card and fetches mobile segment metadata', async () => {
- const source = parse(
- readFileSync(new URL('../src/views/m/pl/plan-cert/index.vue', import.meta.url), 'utf8')
- ).descriptor.scriptSetup!.content
- const ast = ts.createSourceFile('list.ts', source, ts.ScriptTarget.Latest, true)
- const code = ast.statements
- .filter(
- (n) =>
- (ts.isVariableStatement(n) &&
- n.declarationList.declarations.some((d) => d.name.getText(ast) === 'planDetails')) ||
- (ts.isFunctionDeclaration(n) && n.name?.text === 'toggleExpanded') ||
- (ts.isExpressionStatement(n) &&
- ts.isCallExpression(n.expression) &&
- n.expression.expression.getText(ast) === 'watch' &&
- n.expression.arguments[0]?.getText(ast) === 'expandedIds')
- )
- .map((n) => n.getText(ast))
- .join('\n')
- const calls: any[] = []
- const env = {
- useMobilePlanListDetails,
- watch,
- expandedIds: ref(new Set()),
- requestKey: () => 'scope',
- planApi: {
- get: (id: string, mobile: boolean) =>
- new Promise((resolve) => calls.push({ id, mobile, resolve }))
- }
- }
- const scope = effectScope()
- const api = scope.run(() =>
- new Function(
- ...Object.keys(env),
- `${ts.transpile(code, { target: ts.ScriptTarget.ESNext })};return {planDetails,toggleExpanded}`
- )(...Object.values(env))
- )
- assert.equal(calls.length, 0)
- api.toggleExpanded('A', true)
- await nextTick()
- assert.deepEqual(
- calls.map(({ id, mobile }) => [id, mobile]),
- [['A', true]]
- )
- assert.equal(api.planDetails.records.A.plan, null)
- calls[0].resolve({
- id: 'A',
- products: [{ id: 'p', productName: '根别名' }],
- deliveries: [
- {
- products: [
- {
- planProductId: 'p',
- mobileProductMeta: { aliasName: '段次别名', brandMode: 'any', brandName: '' }
- }
- ]
- }
- ]
- })
- await api.planDetails.ensure('A')
- const plan = api.planDetails.cardPlan({
- id: 'A',
- products: [{ id: 'p', productName: '标准产品' }]
- })
- const rendered = card(plan)
- assert.equal(rendered.productNameLabel.value, '标准产品')
- assert.equal(rendered.productLine(plan.deliveries[0].products[0], 'delivery').alias, '段次别名')
- api.toggleExpanded('A', false)
- api.toggleExpanded('A', true)
- await nextTick()
- assert.equal(calls.length, 1)
- scope.stop()
- })
|