更新
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
const assert = require('node:assert/strict')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const test = require('node:test')
|
||||
const ts = require('typescript')
|
||||
const vue = require('vue')
|
||||
const { parse, compileScript, compileTemplate } = require('@vue/compiler-sfc')
|
||||
|
||||
const handlers = [
|
||||
'isDualAuditPassed', 'canQuickTrackRow', 'canShipRow', 'openQuickTrack',
|
||||
'submitQuickTrack', 'openShip', 'openEdit', 'submitEdit', 'resetEditOrderDialog'
|
||||
]
|
||||
const stateNames = [
|
||||
'quickTrackVisible', 'quickTrackSaving', 'quickTrackRowId', 'quickTrackForm',
|
||||
'shipVisible', 'shipRowId', 'shipForm', 'editVisible', 'editDialogLoading',
|
||||
'editSaving', 'editOrderStep', 'editOrderPrescription',
|
||||
'editFormRef', 'editForm', 'editDepositMin'
|
||||
]
|
||||
|
||||
for (const page of ['order_list.vue', 'order_list_h5.vue']) {
|
||||
const filename = path.join(__dirname, '../src/views/consumer/prescription', page)
|
||||
const { descriptor, errors } = parse(fs.readFileSync(filename, 'utf8'), { filename })
|
||||
assert.deepEqual(errors, [])
|
||||
const script = compileScript(descriptor, { id: page })
|
||||
const ast = ts.createSourceFile(filename + '.ts', descriptor.scriptSetup.content, ts.ScriptTarget.Latest, true)
|
||||
// Execute the actual order handlers with only network and unrelated UI dependencies stubbed.
|
||||
const declarations = new Map()
|
||||
for (const node of ast.statements) {
|
||||
if (ts.isFunctionDeclaration(node) && node.name) declarations.set(node.name.text, node.getText(ast))
|
||||
if (ts.isVariableStatement(node)) {
|
||||
for (const declaration of node.declarationList.declarations) {
|
||||
declarations.set(declaration.name.getText(ast), `const ${declaration.getText(ast)}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
const selected = [...handlers, ...stateNames]
|
||||
for (const name of selected) assert.ok(declarations.has(name), `${page}: missing ${name}`)
|
||||
const compiled = ts.transpileModule(selected.map(name => declarations.get(name)).join('\n'), {
|
||||
compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.CommonJS }
|
||||
}).outputText
|
||||
|
||||
function instance(detail = {}, saveTracking = async () => {}) {
|
||||
const warnings = []
|
||||
const errors = []
|
||||
const edits = []
|
||||
const tracks = []
|
||||
const globals = {
|
||||
ref: vue.ref, reactive: vue.reactive, nextTick: vue.nextTick,
|
||||
feedback: { msgWarning: message => warnings.push(message), msgError: message => errors.push(message), msgSuccess() {} },
|
||||
prescriptionOrderDetail: async () => ({ data: detail }),
|
||||
prescriptionOrderEdit: async payload => edits.push(payload),
|
||||
prescriptionOrderDdcode: async payload => { tracks.push(payload); await saveTracking(payload) },
|
||||
canEditRow: () => true,
|
||||
parseServicePackageValues: () => [],
|
||||
loadEditPaidOrders: async () => {},
|
||||
resolveShipModeForRow: row => row.ship_mode || 'gancao',
|
||||
editGancaoLogisticsOnlyMode: vue.ref(false),
|
||||
editGancaoDisplayNo: vue.ref(''),
|
||||
detailDrawerRef: vue.ref(null),
|
||||
detailVisible: vue.ref(false),
|
||||
getLists() {}
|
||||
}
|
||||
const state = new Function(...Object.keys(globals), `${compiled}\nreturn { ${selected.join(', ')} }`)(...Object.values(globals))
|
||||
state.editFormRef.value = { validate: async () => {}, clearValidate() {} }
|
||||
return { state, warnings, errors, edits, tracks }
|
||||
}
|
||||
|
||||
test(`${page}: only two approved audits unlock tracking, including legacy string statuses`, () => {
|
||||
const { state } = instance()
|
||||
for (const rx of [undefined, null, 0, 1, 2, '0', '1', '2']) {
|
||||
for (const pay of [undefined, null, 0, 1, 2, '0', '1', '2']) {
|
||||
const row = { prescription_audit_status: rx, payment_slip_audit_status: pay, fulfillment_status: 2 }
|
||||
const allowed = [1, '1'].includes(rx) && [1, '1'].includes(pay)
|
||||
assert.equal(state.canQuickTrackRow(row), allowed, `tracking: ${rx}/${pay}`)
|
||||
assert.equal(state.canShipRow(row), allowed, `shipping: ${rx}/${pay}`)
|
||||
}
|
||||
}
|
||||
for (const status of [1, 3, 4, 5, 6, 9]) {
|
||||
assert.equal(state.canShipRow({ prescription_audit_status: 1, payment_slip_audit_status: 1, fulfillment_status: status }), false)
|
||||
}
|
||||
})
|
||||
|
||||
test(`${page}: direct handler calls cannot open tracking or shipping before both approvals`, () => {
|
||||
for (const [rx, pay] of [[0, 0], [1, 0], [0, 1], [2, 1], [1, 2]]) {
|
||||
const { state, warnings } = instance()
|
||||
const row = { id: 42, prescription_audit_status: rx, payment_slip_audit_status: pay, fulfillment_status: 2 }
|
||||
state.openQuickTrack(row)
|
||||
state.openShip(row)
|
||||
assert.equal(state.quickTrackVisible.value, false)
|
||||
assert.equal(state.shipVisible.value, false)
|
||||
assert.equal(state.quickTrackRowId.value, 0)
|
||||
assert.equal(state.shipRowId.value, 0)
|
||||
assert.equal(warnings.length, 2)
|
||||
}
|
||||
})
|
||||
|
||||
test(`${page}: approved orders can fill or replace the number and preserve the carrier`, async () => {
|
||||
for (const oldNumber of ['', 'SF-OLD']) {
|
||||
const { state, tracks } = instance()
|
||||
const row = { id: 42, prescription_audit_status: 1, payment_slip_audit_status: 1, fulfillment_status: 2, express_company: 'sf', tracking_number: oldNumber }
|
||||
state.openQuickTrack(row)
|
||||
assert.equal(state.quickTrackVisible.value, true)
|
||||
assert.equal(state.quickTrackForm.tracking_number, oldNumber)
|
||||
state.quickTrackForm.tracking_number = ' SF-NEW '
|
||||
await state.submitQuickTrack()
|
||||
assert.deepEqual(tracks, [{ id: 42, express_company: 'sf', tracking_number: 'SF-NEW' }])
|
||||
assert.equal(state.quickTrackVisible.value, false)
|
||||
state.openShip(row)
|
||||
assert.equal(state.shipVisible.value, true)
|
||||
}
|
||||
})
|
||||
|
||||
test(`${page}: a server rejection after audit revocation retains the dialog and entered number`, async () => {
|
||||
const { state } = instance({}, async () => { throw new Error('audit revoked') })
|
||||
state.openQuickTrack({ id: 42, prescription_audit_status: 1, payment_slip_audit_status: 1 })
|
||||
state.quickTrackForm.tracking_number = 'SF-NEW'
|
||||
await state.submitQuickTrack()
|
||||
assert.equal(state.quickTrackVisible.value, true)
|
||||
assert.equal(state.quickTrackSaving.value, false)
|
||||
assert.equal(state.quickTrackForm.tracking_number, 'SF-NEW')
|
||||
})
|
||||
|
||||
test(`${page}: editing preserves the existing number while saving other fields before approval`, async () => {
|
||||
const { state, edits, errors } = instance({ id: 42, prescription_audit_status: 1, payment_slip_audit_status: 0, tracking_number: 'SF-EXISTING' })
|
||||
await state.openEdit({ id: 42, prescription_audit_status: 1, payment_slip_audit_status: 1 })
|
||||
assert.deepEqual(errors, [])
|
||||
assert.equal(state.editForm.tracking_number, 'SF-EXISTING')
|
||||
state.editForm.tracking_number = 'FORGED'
|
||||
state.editForm.recipient_name = '修改后的收货人'
|
||||
state.editOrderStep.value = 2
|
||||
await state.submitEdit()
|
||||
assert.equal(edits.length, 1)
|
||||
assert.equal(edits[0].recipient_name, '修改后的收货人')
|
||||
assert.equal(Object.hasOwn(edits[0], 'tracking_number'), false)
|
||||
})
|
||||
|
||||
test(`${page}: ordinary editing cannot change tracking while resetting an approved payment audit`, async () => {
|
||||
const { state, edits, errors } = instance({ id: 42, prescription_audit_status: '1', payment_slip_audit_status: '1' })
|
||||
await state.openEdit({ id: 42 })
|
||||
assert.deepEqual(errors, [])
|
||||
state.editForm.tracking_number = 'SF-NEW'
|
||||
state.editOrderStep.value = 2
|
||||
await state.submitEdit()
|
||||
assert.equal(edits.length, 1)
|
||||
assert.equal(Object.hasOwn(edits[0], 'tracking_number'), false)
|
||||
})
|
||||
|
||||
test(`${page}: template compiles with tracking controls bound to audit restrictions`, () => {
|
||||
const template = compileTemplate({ source: descriptor.template.content, filename, id: page, compilerOptions: { bindingMetadata: script.bindings } })
|
||||
assert.deepEqual(template.errors, [])
|
||||
const inputs = [...descriptor.template.content.matchAll(/<el-input\b[^>]*v-model="editForm\.tracking_number"[^>]*>/g)]
|
||||
assert.equal(inputs.length, page === 'order_list.vue' ? 2 : 1)
|
||||
for (const [input] of inputs) assert.match(input, /\sdisabled(?:\s|\/?>)/)
|
||||
assert.match(descriptor.template.content, /v-if="canQuickTrackRow\(row\)"/)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user