Files
shanxia2.0/web-admin/scripts/pl-plan-save-identity.test.ts
T

206 lines
7.1 KiB
TypeScript

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 { ref, nextTick } from 'vue'
import * as stops from '../src/utils/pl-plan-stop-form'
import * as persistence from '../src/views/m/pl/plan/mobilePlanPersistence'
// Evaluate current working-tree handlers, with only external APIs/UI services stubbed.
const source = parse(
readFileSync(
new URL('../src/components/business/pl-plan-form-dialog/index.vue', import.meta.url),
'utf8'
)
).descriptor.scriptSetup!.content
const tree = ts.createSourceFile('form.ts', source, ts.ScriptTarget.Latest, true)
const names = [
'loadPlanForEdit',
'loadPlanForCopy',
'applyStopsFromPlan',
'enrichStopFormsDisplayFromPlanProducts',
'bootstrapStopsFromPlanProducts',
'mirrorPlanProductsFromLoad',
'mapPlanProductToFormRow',
'mapPlanProductToCopyFormRow',
'mapProductsToSubmitPayload',
'buildPlanCommonPayload',
'handleSubmit'
]
const code = names
.map((name) => {
const node = tree.statements.find(
(node) => ts.isFunctionDeclaration(node) && node.name?.text === name
)
assert.ok(node, name)
return node.getText(tree)
})
.join('\n')
const clone = (value: any) => JSON.parse(JSON.stringify(value))
const line = {
productId: 'sku',
productNo: 'SKU',
productName: '产品',
unit: '吨',
packageSpec: '桶',
model: 'M',
planQty: 5,
quantity: 5
}
function harness(mobile: boolean) {
const noop = () => {},
yes = () => true,
identity = async (rows: any[]) => rows
let saved: any = {
id: 'plan',
mobileProductMetaVersion: 1,
products: [{ ...line, id: 'pp' }],
load: { id: 'load', products: [{ ...line, id: 'lp', planProductId: 'pp' }] },
deliveries: [{ id: 'delivery', seq: 1, products: [{ ...line, id: 'dp', planProductId: 'pp' }] }]
}
const writes: any[] = [],
events: any[] = []
const b: any = {
...stops,
...persistence,
nextTick,
isPageVariant: ref(mobile),
props: { planId: 'plan' },
isEdit: ref(true),
pageReady: ref(true),
pageLoadGeneration: 1,
assertPageLoadCurrent: noop,
isPageLoadCurrent: yes,
isPageSubmitCurrent: yes,
suppressAddressMutex: ref(false),
suppressStopProductSync: ref(false),
stopFormsReady: ref(false),
formData: { products: [] },
loadForm: ref(stops.createEmptyLoadForm()),
deliveryForms: ref([]),
resetForm: noop,
validateLoadedPagePlan: noop,
formatDate: () => '',
todayYmd: () => '2026-10-27',
resolveCurrentUserId: () => 'u',
resolveCurrentUserName: () => '',
syncCommittedPartyIds: noop,
loadedTransportStatus: ref(''),
loadedFollowStatus: ref(''),
loadedPlanSnapshot: ref(null),
enrichPlanProductsHazardFromCrm: identity,
enrichPlanProductLinesAlias: identity,
freightCalc: { resetFreightCalc: noop },
restoreFreightFromTransport: noop,
selectedDriverId: ref(''),
selectedEscortId: ref(''),
vehicleBundle: ref(null),
syncSelectedCustomerOptions: noop,
reapplyStopDibangByVehiclePlate: noop,
prepareLineAliasAndBrandForSubmit: noop,
resolveLineProductName: (name: string) => name,
buildTransportBlock: () => undefined,
mobileMetadata: { ready: yes },
mobileSavedPlanId: ref(''),
mobileCreateUncertain: ref(false),
submitLoading: ref(false),
basicFormRef: ref({ validate: async () => true }),
validateBusinessRules: yes,
prefetchStopContractProducts: noop,
validateSingleContractPerStop: yes,
validateContractPackageSpecs: yes,
validateStopContractsRequired: yes,
pickBxData: (x: any) => x,
showPlanSaveWarnings: noop,
ElMessage: { warning: noop, error: noop, success: noop },
innerVisible: ref(true),
emit: (...args: any[]) => events.push(args),
planApi: {
get: async () => clone(saved),
update: async (_id: string, payload: any) => {
writes.push(clone(payload))
// Server returns generated identities for genuinely new rows.
saved = { ...clone(payload), id: 'plan', mobileProductMetaVersion: 1 }
saved.products.forEach((row: any, i: number) => {
row.id ||= `pp-new-${i}`
})
const resolve = (row: any) =>
saved.products.find((pp: any) => pp.clientKey === row.planProductClientKey)?.id ||
row.planProductId
saved.load.id ||= 'load-new'
saved.load.products.forEach((row: any, i: number) => {
row.id ||= `lp-new-${i}`
row.planProductId = resolve(row)
})
saved.deliveries.forEach((stop: any, i: number) => {
stop.id ||= `delivery-new-${i}`
stop.products.forEach((row: any, j: number) => {
row.id ||= `dp-new-${i}-${j}`
row.planProductId = resolve(row)
})
})
return clone(saved)
}
}
}
const api = new Function(
...Object.keys(b),
ts.transpile(code, { target: ts.ScriptTarget.ESNext }) + `;return {${names.join(',')}}`
)(...Object.values(b))
return { b, api, writes, events, saved: () => saved }
}
for (const mobile of [false, true]) {
const platform = mobile ? 'H5' : 'Web'
test(`${platform} actual edit/save/reopen/save keeps all existing and freshly assigned child IDs`, async () => {
const h = harness(mobile)
await h.api.loadPlanForEdit('plan')
h.b.loadForm.value.products.push({
...line,
packageSpec: '袋',
id: undefined,
planProductId: undefined
})
h.b.deliveryForms.value.push({
...stops.createEmptyDeliveryForm(2),
products: [{ ...line, packageSpec: '袋' }]
})
await h.api.handleSubmit('save')
assert.equal(h.b.innerVisible.value, false)
assert.deepEqual(h.events.at(-1), ['success', { planId: 'plan', arranged: false }])
const saved = clone(h.saved())
await h.api.loadPlanForEdit('plan')
await h.api.handleSubmit('save')
const payload = h.writes[1]
assert.deepEqual(
payload.products.map((p: any) => p.id),
saved.products.map((p: any) => p.id)
)
assert.equal(payload.load.id, saved.load.id)
assert.deepEqual(
payload.load.products.map((p: any) => p.id),
saved.load.products.map((p: any) => p.id)
)
assert.deepEqual(
payload.deliveries.map((d: any) => [d.id, ...d.products.map((p: any) => p.id)]),
saved.deliveries.map((d: any) => [d.id, ...d.products.map((p: any) => p.id)])
)
assert.ok(payload.load.products.every((p: any) => p.planProductId))
assert.ok(payload.deliveries.every((d: any) => d.products.every((p: any) => p.planProductId)))
})
test(`${platform} actual copy handler strips source parent/product IDs from submit payload`, async () => {
const h = harness(mobile)
await h.api.loadPlanForCopy('plan')
const payload = h.api.buildPlanCommonPayload()
assert.equal(payload.load.id, undefined)
assert.ok(payload.products.every((p: any) => !p.id))
assert.ok(payload.load.products.every((p: any) => !p.id && !p.planProductId))
assert.ok(
payload.deliveries.every(
(d: any) => !d.id && d.products.every((p: any) => !p.id && !p.planProductId)
)
)
})
}