| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- import assert from 'node:assert/strict'
- import { readFileSync } from 'node:fs'
- import test from 'node:test'
- import { parse } from '@vue/compiler-sfc'
- import ts from 'typescript'
- import * as navigation from '../src/utils/mp-webview'
- function handler(file: string, name: string, bindings: Record<string, any>) {
- const source = parse(readFileSync(new URL(`../src/${file}`, import.meta.url), 'utf8')).descriptor
- .scriptSetup!.content
- const ast = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true)
- const fn = ast.statements.find(
- (node) => ts.isFunctionDeclaration(node) && node.name?.text === name
- )
- assert.ok(fn, `${name} must exist`)
- return new Function(...Object.keys(bindings), ts.transpile(fn.getText(ast)) + `;return ${name}`)(
- ...Object.values(bindings)
- )
- }
- test('mobile quote validates freight, deposit and validity bounds before either save path', () => {
- const form = {
- value: {
- quoteType: 'sales',
- supplierId: 's',
- customerId: 'c',
- contactId: 'p',
- ownerUserId: 'u',
- quoteDate: '2026-10-24',
- validityDays: 30,
- freight: 0,
- barrelDeposit: 0
- } as Record<string, any>
- }
- const validate = handler('views/crm/quote/components/QuoteFormPanel.vue', 'pageMissingMessage', {
- form,
- isPageVariant: { value: true },
- quoteMeta: { blockingMessage: () => '' },
- basicLabels: { value: {} }
- })
- assert.equal(validate(), '')
- for (const field of ['freight', 'barrelDeposit']) {
- for (const invalid of [-1, '-0.01', 'invalid', Infinity]) {
- form.value[field] = invalid
- assert.notEqual(validate(), '', `${field}=${invalid} must fail`)
- }
- for (const valid of [0, '0', 1.25, '', null]) {
- form.value[field] = valid
- assert.equal(validate(), '')
- }
- form.value[field] = 0
- }
- for (const invalid of [0, 366, Infinity, 'invalid']) {
- form.value.validityDays = invalid
- assert.notEqual(validate(), '', `validity=${invalid} must fail`)
- }
- for (const valid of [1, 365]) {
- form.value.validityDays = valid
- assert.equal(validate(), '')
- }
- })
- test('quote customer navigation preserves approval and contract origins using fixed mobile routes', () => {
- const nav = navigation as Record<string, any>
- assert.equal(typeof nav.mpQuoteCustomerLocation, 'function')
- assert.equal(typeof nav.mpRelatedQuoteReturnLocation, 'function')
- for (const origin of [
- {},
- { from: 'approve' },
- {
- from: 'contract',
- returnContractId: 'K-1',
- originCustomerId: 'C-0'
- }
- ]) {
- const location = nav.mpQuoteCustomerLocation({ id: 'Q-1', customerId: 'C-1' }, origin)
- assert.equal(location.path, '/m/crm/customer/C-1')
- assert.deepEqual(nav.mpRelatedQuoteReturnLocation(location.query), {
- path: '/m/crm/quote/Q-1',
- query: origin
- })
- }
- assert.equal(nav.mpQuoteCustomerLocation({ id: 'Q', customerId: '../bad' }, {}), null)
- assert.equal(nav.mpRelatedQuoteReturnLocation({ from: 'quote', returnQuoteId: '//evil' }), null)
- })
- test('quote customer click is guarded and customer back uses the quote return destination', () => {
- const targets: any[] = []
- let ready = false
- const goCustomer = handler('views/m/crm/quote/detail.vue', 'goCustomer', {
- navigationReady: () => ready,
- quote: { value: { id: 'Q', customerId: 'C' } },
- route: { query: { from: 'approve' } },
- router: { push: (v: any) => targets.push(v) },
- mpQuoteCustomerLocation: (navigation as any).mpQuoteCustomerLocation
- })
- goCustomer()
- assert.equal(targets.length, 0)
- ready = true
- goCustomer()
- assert.equal(targets[0].path, '/m/crm/customer/C')
- const destination = { path: '/m/crm/quote/Q', query: { from: 'approve' } }
- const back = handler('views/m/crm/customer/detail.vue', 'back', {
- relatedContractReturn: { value: null },
- relatedQuoteReturn: { value: destination },
- router: { replace: (v: any) => targets.push(v) },
- CUSTOMER_PATH: '/m/crm/customer'
- })
- back()
- assert.deepEqual(targets[1], destination)
- })
|