| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import assert from 'node:assert/strict'
- import test from 'node:test'
- import { readFileSync } from 'node:fs'
- import ts from 'typescript'
- function fn(path: string, name: string, context: Record<string, any> = {}) {
- const source = readFileSync(new URL(path, import.meta.url), 'utf8')
- const script = source.match(/<script[^>]*>([\s\S]*?)<\/script>/)?.[1] || source
- const ast = ts.createSourceFile('page.ts', script, ts.ScriptTarget.Latest, true)
- const node = ast.statements.find((s) => ts.isFunctionDeclaration(s) && s.name?.text === name)
- assert.ok(node, name)
- const js = ts.transpileModule(node.getText(ast), {
- compilerOptions: { target: ts.ScriptTarget.ES2022 }
- }).outputText
- return new Function(...Object.keys(context), `${js}; return ${name}`)(...Object.values(context))
- }
- const detail = {
- id: 'detail-a',
- expenseItemId: 'expense',
- amount: 10,
- remark: 'Reason',
- occurDate: '2026-01-01'
- }
- const webPage = '../src/views/bx/reimburse/apply/index.vue'
- const nativePage = '../../miniprogram/pages/bx/reimburse/apply.vue'
- for (const [editing, occurDate] of [[true, detail.occurDate], [false, detail.occurDate], [true, ''], [false, '']] as const) {
- test(`Web/H5 expense payload ${editing ? 'preserves edit ID' : 'clears source ID on create'} with ${occurDate || 'cleared date'}`, () => {
- const build = fn(webPage, 'buildAddPayload', {
- addForm: { details: [{ ...detail, occurDate }], remark: '', reimburseDate: '2026-01-01' },
- selectedInvoicePicks: { value: [] },
- editingId: { value: editing ? 'apply' : null },
- ElMessage: { warning() {} }
- })
- const row = build().details[0]
- assert.equal(row.id, editing ? 'detail-a' : undefined)
- assert.equal(row.remark, 'Reason')
- assert.equal(row.occurDate, occurDate || null)
- })
- test(`Native expense payload ${editing ? 'preserves edit ID' : 'clears source ID on create'} with ${occurDate || 'cleared date'}`, async () => {
- let payload: any
- const save = async (...args: any[]) => {
- payload = args.at(-1)
- return {
- data: {
- id: 'apply',
- details: [
- {
- id: 'server-detail',
- expenseId: 'expense',
- amount: 10,
- remark: 'Reason',
- occurDate: '2026-01-01'
- }
- ]
- }
- }
- }
- const context = {
- validateReimburseApplyForm: () => [{ ...detail, occurDate }],
- uploading: { value: false },
- submitting: { value: false },
- editId: { value: editing ? 'apply' : '' },
- savedId: { value: '' },
- buildInvoicePayload: () => ({}),
- form: { details: [{ ...detail }], title: '', remark: '', applicantId: '', reimburseDate: '' },
- reimburseApi: { update: save, create: save },
- bindNewAttachments: async () => {},
- uni: { showModal() {}, showToast() {} }
- }
- await fn(nativePage, 'onSubmit', context)()
- assert.ok(payload)
- assert.equal(payload.details[0].id, editing ? 'detail-a' : undefined)
- assert.equal(payload.details[0].occurDate, occurDate || null)
- assert.equal(
- context.form.details[0].id,
- 'server-detail',
- 'continued editing uses returned child ID'
- )
- })
- }
- for (const page of ['reimburse', 'advance']) {
- test(`${page} workflow payload retains node ID and action`, () => {
- const build = fn(`../src/views/bx/workflow/${page}/index.vue`, 'buildNodePayload')
- const [row] = build([{ id: 'node-a', nodeName: 'Review', actionType: 'disburse' }])
- assert.equal(row.id, 'node-a')
- assert.equal(row.actionType, 'disburse')
- })
- }
- test('Native workflow payload retains node ID and action', () => {
- const build = fn('../../miniprogram/components/bx-ui/bx-wf-config-page.vue', 'buildNodePayload')
- const [row] = build([{ id: 'node-a', nodeName: 'Review', actionType: 'disburse' }])
- assert.equal(row.id, 'node-a')
- assert.equal(row.actionType, 'disburse')
- })
- test('Web/H5 save response refreshes IDs before submit retry', async () => {
- const addForm: any = { details: [{ ...detail }] }
- const editingId = { value: null }
- const save = fn(webPage, 'saveAddForm', {
- addForm,
- editingId,
- pickBxData: (res: any) => res.data,
- reimburseApi: {
- create: async () => ({
- data: {
- id: 'apply',
- details: [
- {
- id: 'server-detail',
- expenseId: 'expense',
- amount: 10,
- remark: 'Reason',
- occurDate: '2026-01-01'
- }
- ]
- }
- })
- }
- })
- assert.equal(await save({}), 'apply')
- assert.equal(editingId.value, 'apply')
- assert.equal(addForm.details[0].id, 'server-detail')
- })
- test('Native edit loading retains detail identity', async () => {
- const form: any = {}
- const load = fn(nativePage, 'loadEditData', {
- form,
- reimburseApi: {
- getById: async () => ({
- data: { details: [{ id: 'detail-a', expenseId: 'expense', amount: 10 }] }
- })
- },
- userStore: { userInfo: { id: 'user' } },
- todayYmd: () => '2026-01-01',
- refreshWallet: async () => {},
- selectedInvoicePicks: { value: [] },
- kickAttachPreviewLoads() {},
- attachmentApi: { listByBiz: async () => ({ data: [] }) },
- files: { value: [] },
- uni: {
- showToast() {
- assert.fail('edit loading failed')
- }
- }
- })
- await load('apply')
- assert.equal(form.details[0].id, 'detail-a')
- })
- test('Web/H5 edit loading retains detail identity', async () => {
- const addForm: any = {}
- const load = fn(webPage, 'openEditDialog', {
- addForm,
- reimburseApi: {
- getById: async () => ({
- data: { details: [{ id: 'detail-a', expenseId: 'expense', amount: 10 }] }
- })
- },
- selectedInvoicePicks: { value: [] },
- applyAttachments: { value: [] },
- currentUserId: () => 'user',
- todayYmd: () => '2026-01-01',
- titleAutoLinked: { value: false },
- isAutoReimburseTitle: () => false,
- editingId: { value: null },
- dialogs: {},
- loadApplicantOptions: async () => {},
- refreshWalletBalance: async () => {},
- loadSelectedPicksFromInvoices: async () => {},
- loadBxAttachments: async () => [],
- ElMessage: {
- error() {
- assert.fail('edit loading failed')
- }
- }
- })
- await load({ id: 'apply' })
- assert.equal(addForm.details[0].id, 'detail-a')
- })
- test('Recharge workflow payload retains node ID for rename', () => {
- const build = fn('../src/views/pl/vehicle-recharge-workflow/index.vue', 'buildNodePayload')
- const [row] = build([{ id: 'node-a', nodeName: 'Renamed', actionType: 'disburse' }])
- assert.equal(row.id, 'node-a')
- assert.equal(row.actionType, 'disburse')
- })
|