| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- import { mobileStopIdentity } from '../src/views/m/pl/plan/mobileStopIdentity'
- import assert from 'node:assert/strict'
- import { existsSync, readFileSync } from 'node:fs'
- import test from 'node:test'
- import { computed, ref } from 'vue'
- import * as vue from 'vue'
- import { renderToString } from 'vue/server-renderer'
- import { compileScript, parse } from '@vue/compiler-sfc'
- import ts from 'typescript'
- const parentPath = new URL(
- '../src/components/business/pl-plan-form-dialog/index.vue',
- import.meta.url
- )
- const sheetPath = new URL('../src/views/m/pl/plan/ContractLinePickerSheet.vue', import.meta.url)
- const parent = readFileSync(parentPath, 'utf8')
- const sheet = existsSync(sheetPath) ? readFileSync(sheetPath, 'utf8') : ''
- function execute(source: string, names: string[], bindings: Record<string, any>) {
- const ast = ts.createSourceFile(
- 'component.ts',
- parse(source).descriptor.scriptSetup?.content || '',
- ts.ScriptTarget.Latest,
- true
- )
- const code = names
- .map((name) => {
- const node = ast.statements.find(
- (node) =>
- (ts.isFunctionDeclaration(node) && node.name?.text === name) ||
- (ts.isVariableStatement(node) &&
- node.declarationList.declarations.some((d) => d.name.getText(ast) === name))
- )
- assert.ok(node, `production declaration ${name} must exist`)
- return node.getText(ast)
- })
- .join('\n')
- return new Function(
- ...Object.keys(bindings),
- ts.transpile(code, { target: ts.ScriptTarget.ESNext }) + `;return {${names.join(',')}}`
- )(...Object.values(bindings))
- }
- const rows = [
- {
- id: 'line-a',
- contractId: 'a',
- contractNo: 'HT-A',
- productId: 'same',
- productName: '长名称液体',
- standardProductName: '标准名称',
- productNo: 'P001',
- model: 'M-A',
- brandName: '品牌甲',
- aliasName: '别名甲',
- quantity: 0,
- remainingQty: 0,
- taxRate: 0
- },
- {
- id: 'line-b',
- contractId: 'b',
- contractNo: 'HT-B',
- productId: 'same',
- productName: '液体乙',
- productNo: 'P002',
- productModel: 'M-B'
- }
- ]
- function sheetHarness() {
- const events: any[] = []
- const props = { rows, busy: false, loading: false }
- return {
- props,
- events,
- ...execute(
- sheet,
- [
- 'keyword',
- 'selectedRows',
- 'filteredRows',
- 'rowKey',
- 'isSelected',
- 'toggleRow',
- 'resetSelection',
- 'confirmSelection',
- 'displayNumber'
- ],
- { ref, computed, props, emit: (...args: any[]) => events.push(args) }
- )
- }
- }
- test('mobile picker replaces desktop dialog only for page variant', () => {
- assert.match(parent, /<ContractLinePickerSheet\s+v-if="isPageVariant"/)
- assert.match(parent, /<el-dialog\s+v-else\s+v-model="linePickerVisible"/)
- assert.doesNotMatch(sheet, /el-table|el-dialog/)
- })
- test('search trims and ignores case across product, contract, model, brand and alias', () => {
- const h = sheetHarness()
- for (const query of [' 标准名称 ', '长名称', ' p001 ', 'm-a', 'ht-a', '品牌甲', '别名甲']) {
- h.keyword.value = query
- assert.deepEqual(h.filteredRows.value, [rows[0]], query)
- }
- h.keyword.value = 'm-b'
- assert.deepEqual(h.filteredRows.value, [rows[1]])
- })
- test('selection survives search and keeps same product across distinct contract lines', () => {
- const h = sheetHarness()
- h.toggleRow(rows[0])
- h.keyword.value = 'HT-B'
- h.toggleRow(rows[1])
- assert.equal(h.selectedRows.value.length, 2)
- assert.notEqual(h.rowKey(rows[0]), h.rowKey(rows[1]))
- h.confirmSelection()
- assert.equal(h.events[0][0], 'confirm')
- assert.deepEqual(h.events[0][1], rows)
- h.resetSelection()
- assert.equal(h.keyword.value, '')
- assert.deepEqual(h.selectedRows.value, [])
- h.confirmSelection()
- assert.equal(h.events.length, 1)
- })
- test('zero quantities and tax are visible, missing numbers are placeholders', () => {
- const h = sheetHarness()
- assert.equal(h.displayNumber(0), '0')
- for (const value of [undefined, null, '', NaN]) assert.equal(h.displayNumber(value), '—')
- })
- const detail = readFileSync(new URL('../src/views/m/pl/plan/detail.vue', import.meta.url), 'utf8')
- function scrollHarness({ y = 600, height = 1200, locked = false, missingLast = false } = {}) {
- const activeTab = ref('hazard')
- const sections: Record<string, number> = { base: -600, hazard: -30, remark: 500 }
- const h = execute(detail, ['syncActiveTabFromScroll'], {
- activeTab,
- scrollLockUntil: locked ? Date.now() + 10000 : 0,
- plan: ref({}),
- scrollMargin: ref(100),
- detailTabs: Object.keys(sections).map((key) => ({ key, anchor: key })),
- window: { innerHeight: 600, scrollY: y },
- document: {
- scrollingElement: { scrollHeight: height },
- getElementById: (key: string) =>
- missingLast && key === 'remark'
- ? null
- : { getBoundingClientRect: () => ({ top: sections[key] - (y - 600) }) }
- }
- })
- return { ...h, activeTab }
- }
- test('short final remark remains highlighted at document bottom', () => {
- const h = scrollHarness()
- h.syncActiveTabFromScroll()
- assert.equal(h.activeTab.value, 'remark')
- })
- for (const [name, options, expected] of [
- ['Home restores base', { y: 0 }, 'base'],
- ['short unscrolled page avoids bottom override', { y: 0, height: 500 }, 'base'],
- ['click lock is respected', { locked: true }, 'hazard'],
- ['missing last section falls back to top probe', { missingLast: true }, 'hazard']
- ] as const)
- test(name, () => {
- const h = scrollHarness(options)
- h.syncActiveTabFromScroll()
- assert.equal(h.activeTab.value, expected)
- })
- function deferred() {
- let resolve!: (value: any) => void
- const promise = new Promise((yes) => {
- resolve = yes
- })
- return { resolve, promise }
- }
- function parentHarness({
- enrich = async (rows: any) => rows,
- fetch = async () => {},
- page = true
- } = {}) {
- const loadForm = ref({
- customerName: '客户甲',
- contracts: [{ contractId: 'a' }],
- products: [] as any[]
- })
- const deliveryForms = ref([
- { customerName: '客户乙', contracts: [{ contractId: 'b' }], products: [] as any[] },
- { customerName: '客户丙', contracts: [{ contractId: 'c' }], products: [] as any[] }
- ])
- const bindings = {
- mobileStopIdentity,
- initLineBrandMetaFromProduct: () => ({}),
- packageSpecsForProduct: () => [],
- normalizePackageSpec: (value: any) => String(value || '').trim(),
- productPackageKey: (id: any, pkg: any) => `${id}::${pkg || ''}`,
- unionContractProductRows: () => [],
- loadContractProductRows: ref([]),
- contractProductRowsCache: ref({}),
- ref,
- isPageVariant: ref(page),
- loadForm,
- deliveryForms,
- productSelectorTarget: ref({ side: 'load', deliveryIndex: 0 }),
- productSelectorVisible: ref(false),
- isPlInternalCustomerName: () => false,
- collectStopContractIds: (contracts: any[]) => contracts.map((row) => row.contractId),
- fetchContractProductIds: fetch,
- enrichContractLinesForPicker: async (rows: any) => rows,
- enrichPlanProductsHazardFromCrm: enrich,
- enrichPlanProductLinesAlias: async (rows: any) => rows,
- createStopProductsFromPlanProducts: (rows: any) => rows.map((row: any) => ({ ...row })),
- ElMessage: { warning() {}, info() {}, error() {} },
- freightCalc: { resetFreightCalc() {} }
- }
- const h = execute(
- parent,
- [
- 'pageReady',
- 'pageDisposed',
- 'pageLoadGeneration',
- 'isPageLoadCurrent',
- 'isPageSubmitCurrent',
- 'invalidatePageLoad',
- 'linePickerVisible',
- 'linePickerRows',
- 'linePickerSelected',
- 'contractLinesCache',
- 'mobileLinePickerSession',
- 'mobileLinePickerGeneration',
- 'mobileLinePickerBusy',
- 'mobileLinePickerLoading',
- 'mobileLinePickerError',
- 'setMobileLinePickerVisible',
- 'handleMobileLinePickerConfirm',
- 'openProductSelector',
- 'handleLinePickerConfirm',
- 'handleProductConfirm'
- ],
- bindings
- )
- h.pageReady.value = true
- h.contractLinesCache.value = {
- a: [rows[0]],
- b: [rows[1]],
- c: [{ ...rows[1], id: 'line-c', contractId: 'c' }]
- }
- return { ...bindings, ...h }
- }
- test('parent delivers exact selected contract line identities into requested delivery segment', async () => {
- const h = parentHarness()
- await h.openProductSelector('delivery', 1)
- await h.handleMobileLinePickerConfirm([rows[0], rows[1]])
- assert.equal(h.deliveryForms.value[0].products.length, 0)
- assert.deepEqual(
- h.deliveryForms.value[1].products.map((r: any) => [r.contractId, r.contractProductId]),
- [
- ['a', 'line-a'],
- ['b', 'line-b']
- ]
- )
- assert.equal(h.loadForm.value.products.length, 0)
- })
- test('parent busy gate prevents a double confirm while enrichment is pending', async () => {
- const d = deferred()
- let calls = 0
- const h = parentHarness({
- enrich: async (rows: any) => {
- calls++
- await d.promise
- return rows
- }
- })
- await h.openProductSelector('load')
- const first = h.handleMobileLinePickerConfirm([rows[0]])
- assert.equal(h.mobileLinePickerBusy.value, true)
- await h.handleMobileLinePickerConfirm([rows[0]])
- assert.equal(calls, 1)
- d.resolve(null)
- await first
- assert.equal(h.loadForm.value.products.length, 1)
- })
- for (const action of ['close', 'switch', 'unmount'] as const)
- test(`old confirm cannot append after ${action}`, async () => {
- const d = deferred()
- const h = parentHarness({
- enrich: async (rows: any) => {
- await d.promise
- return rows
- }
- })
- await h.openProductSelector('load')
- const pending = h.handleMobileLinePickerConfirm([rows[0]])
- if (action === 'close') {
- h.setMobileLinePickerVisible(false)
- await h.openProductSelector('load')
- }
- if (action === 'switch') await h.openProductSelector('delivery', 1)
- if (action === 'unmount') h.invalidatePageLoad()
- d.resolve(null)
- await pending
- assert.equal(h.loadForm.value.products.length, 0)
- assert.equal(h.deliveryForms.value[1].products.length, 0)
- if (action !== 'unmount') assert.equal(h.linePickerVisible.value, true)
- })
- test('out-of-order opening does not apply old rows to a new segment', async () => {
- const d = deferred()
- const h = parentHarness({
- fetch: async (id?: string) => {
- if (id === 'a') await d.promise
- }
- })
- const old = h.openProductSelector('load')
- await h.openProductSelector('delivery', 1)
- d.resolve(null)
- await old
- assert.equal(h.linePickerRows.value[0].contractId, 'c')
- assert.equal(h.productSelectorTarget.value.deliveryIndex, 1)
- })
- test('desktop confirm remains usable without mobile page readiness or sheet state', async () => {
- const h = parentHarness({ page: false })
- h.pageReady.value = false
- h.linePickerSelected.value = [rows[0]]
- await h.handleLinePickerConfirm()
- assert.equal(h.loadForm.value.products[0].contractProductId, 'line-a')
- })
- test('mobile confirmation deduplicates by contract plus line id, not line id alone', async () => {
- const h = parentHarness()
- await h.openProductSelector('load')
- await h.handleMobileLinePickerConfirm([rows[0], { ...rows[1], id: rows[0].id }])
- assert.equal(h.loadForm.value.products.length, 2)
- })
- test('failed mobile opening remains visible with retry and clears loading', async () => {
- let fail = true
- const h = parentHarness({
- fetch: async () => {
- if (fail) throw new Error('offline')
- }
- })
- await h.openProductSelector('load')
- assert.equal(h.linePickerVisible.value, true)
- assert.equal(h.mobileLinePickerLoading.value, false)
- assert.match(h.mobileLinePickerError.value, /重新加载/)
- fail = false
- await h.openProductSelector('load')
- assert.equal(h.mobileLinePickerError.value, '')
- assert.equal(h.linePickerRows.value.length, 1)
- })
- test('cancel pending opening cannot reopen or populate the closed sheet', async () => {
- const d = deferred()
- const h = parentHarness({
- fetch: async () => {
- await d.promise
- }
- })
- const pending = h.openProductSelector('load')
- h.setMobileLinePickerVisible(false)
- d.resolve(null)
- await pending
- assert.equal(h.linePickerVisible.value, false)
- assert.equal(h.linePickerRows.value.length, 0)
- })
- test('old confirm finally cannot clear a new session busy flag', async () => {
- const old = deferred()
- const fresh = deferred()
- let count = 0
- const h = parentHarness({
- enrich: async (rows: any) => {
- await (++count === 1 ? old.promise : fresh.promise)
- return rows
- }
- })
- await h.openProductSelector('load')
- const first = h.handleMobileLinePickerConfirm([rows[0]])
- h.setMobileLinePickerVisible(false)
- await h.openProductSelector('delivery', 1)
- const second = h.handleMobileLinePickerConfirm([rows[1]])
- old.resolve(null)
- await first
- assert.equal(h.mobileLinePickerBusy.value, true)
- fresh.resolve(null)
- await second
- assert.equal(h.mobileLinePickerBusy.value, false)
- assert.equal(h.deliveryForms.value[1].products.length, 1)
- })
- test('sheet session records the page generation and rejects confirmation from an older page', async () => {
- const h = parentHarness()
- await h.openProductSelector('load')
- h.mobileLinePickerGeneration.value -= 1
- await h.handleMobileLinePickerConfirm([rows[0]])
- assert.equal(h.loadForm.value.products.length, 0)
- })
- function compiledSheet() {
- const script = compileScript(parse(sheet).descriptor, { id: 'picker-test', inlineTemplate: true })
- const code = ts.transpile(script.content, {
- target: ts.ScriptTarget.ESNext,
- module: ts.ModuleKind.ESNext
- })
- const ast = ts.createSourceFile('sheet.js', code, ts.ScriptTarget.Latest, true)
- const bindings: Record<string, any> = Object.fromEntries(
- Object.entries(vue).filter(([name]) => /^[a-zA-Z_$][\w$]*$/.test(name) && name !== 'default')
- )
- const statements: string[] = []
- for (const node of ast.statements) {
- if (ts.isImportDeclaration(node)) {
- const imports = node.importClause?.namedBindings
- if (imports && ts.isNamedImports(imports))
- for (const item of imports.elements) {
- bindings[item.name.text] = (vue as any)[item.propertyName?.text || item.name.text]
- }
- } else statements.push(node.getText(ast))
- }
- return new Function(
- ...Object.keys(bindings),
- statements.join('\n').replace('export default', 'return')
- )(...Object.values(bindings))
- }
- test('real sheet renderer keeps all card fields, formatter results, zero values and no desktop table', async () => {
- const app = vue.createSSRApp(compiledSheet(), {
- modelValue: true,
- rows,
- busy: false,
- loading: false,
- error: '',
- formatPackage: () => '字典包装',
- formatBrand: () => '品牌规则结果',
- formatRemaining: (n: any) => (n == null ? '—' : String(n)),
- dictLabel: (_type: string, value: string) => '字典-' + value,
- dictTagType: () => 'success'
- })
- app.component('van-popup', {
- setup:
- (_props: any, { slots }: any) =>
- () =>
- vue.h('section', slots.default?.())
- })
- app.component('el-tag', {
- setup:
- (_props: any, { slots }: any) =>
- () =>
- vue.h('span', slots.default?.())
- })
- const html = await renderToString(app)
- for (const text of [
- '标准名称',
- 'HT-A',
- 'HT-B',
- 'P001',
- 'M-A',
- '字典包装',
- '品牌规则结果',
- '别名甲',
- '0%',
- '合同数量',
- '剩余数量',
- '计量单位',
- '状态'
- ])
- assert.ok(html.includes(text), text)
- assert.match(html, /<small>合同数量<\/small><span>0<\/span>/)
- assert.match(html, /<small>剩余数量<\/small><span>0<\/span>/)
- assert.match(html, /确认添加/)
- assert.match(html, /disabled/)
- assert.doesNotMatch(html, /<table|el-dialog/)
- })
- test('production visibility watcher resets search and temporary selection on close and reopen', () => {
- const h = sheetHarness()
- const props = vue.reactive({ modelValue: true })
- const ast = ts.createSourceFile(
- 'sheet.ts',
- parse(sheet).descriptor.scriptSetup!.content,
- ts.ScriptTarget.Latest,
- true
- )
- const watcher = ast.statements.find(
- (node) => ts.isExpressionStatement(node) && node.getText(ast).startsWith('watch(')
- )
- assert.ok(watcher)
- const scope = vue.effectScope()
- scope.run(() =>
- new Function('watch', 'props', 'resetSelection', ts.transpile(watcher.getText(ast)))(
- vue.watch,
- props,
- h.resetSelection
- )
- )
- h.keyword.value = 'HT-A'
- h.toggleRow(rows[0])
- props.modelValue = false
- assert.equal(h.keyword.value, '')
- assert.equal(h.selectedRows.value.length, 0)
- props.modelValue = true
- assert.equal(h.selectedRows.value.length, 0)
- assert.equal(h.events.length, 0)
- scope.stop()
- })
- function realFetchHarness(
- read: (id: string) => Promise<any> = async () => {
- throw new Error('offline')
- }
- ) {
- const h = parentHarness({ fetch: (...args: any[]) => fetchReal(...args) })
- const pageLoadError = ref('')
- const prod = execute(
- parent,
- ['fetchContractProductIds', 'assertPageLoadCurrent', 'failPageLoad', 'pageLoadErrorMessage'],
- {
- ...h,
- pageLoadGeneration: 0,
- pageLoadError,
- footerMoreOpen: ref(false),
- props: {},
- contractProductIdsCache: ref({}),
- contractProductRowsCache: ref({}),
- getContractDetailCached: read,
- invalidateContractDetailCache() {},
- collectContractProductRows: (rows: any) => rows,
- collectContractProductIds: (rows: any) => rows.map((row: any) => row.productId)
- }
- )
- const fetchReal = prod.fetchContractProductIds
- return { ...h, pageLoadError }
- }
- test('real contract failure blocks the page, releases loading and closes the sheet for page retry', async () => {
- const h = realFetchHarness()
- await h.openProductSelector('load')
- assert.equal(h.pageReady.value, false)
- assert.ok(h.pageLoadError.value)
- assert.equal(h.mobileLinePickerLoading.value, false)
- assert.match(h.mobileLinePickerError.value, /重新加载/)
- assert.equal(h.linePickerVisible.value, false)
- })
- for (const side of ['load', 'delivery'] as const)
- test(`${side} stop replacement by the contract watcher releases loading and closes only its current sheet`, async () => {
- const d = deferred()
- const h = realFetchHarness(async (id) => {
- await d.promise
- return { id, products: rows }
- })
- const pending = h.openProductSelector(side)
- if (side === 'load') h.loadForm.value = { ...h.loadForm.value, products: [] }
- else h.deliveryForms.value = h.deliveryForms.value.map((stop) => ({ ...stop, products: [] }))
- d.resolve(null)
- await pending
- assert.equal(h.mobileLinePickerLoading.value, false)
- assert.equal(h.linePickerVisible.value, false)
- assert.equal(h.pageReady.value, true, 'obsolete selection must not invalidate the ready page')
- })
- for (const failure of [true, false])
- test(`old real fetch ${failure ? 'failure' : 'success'} cannot fail the page or close/reset a newer loading sheet`, async () => {
- const old = deferred(),
- fresh = deferred()
- const h = realFetchHarness(async (id) => {
- await (id === 'a' ? old.promise : fresh.promise)
- if (id === 'a' && failure) throw new Error('old request failed')
- return { id, products: id === 'a' ? [rows[0]] : [rows[1]] }
- })
- const previous = h.openProductSelector('load')
- const current = h.openProductSelector('delivery')
- old.resolve(null)
- await previous
- assert.equal(h.pageReady.value, true)
- assert.equal(h.linePickerVisible.value, true)
- assert.equal(h.mobileLinePickerLoading.value, true)
- assert.equal(h.mobileLinePickerError.value, '')
- fresh.resolve(null)
- await current
- assert.equal(h.mobileLinePickerLoading.value, false)
- assert.equal(h.linePickerVisible.value, true)
- assert.equal(h.linePickerRows.value[0].contractId, 'b')
- })
- test('mobile opened line picker follows segment identity through reorder before confirm',async()=>{
- const h=parentHarness()
- await h.openProductSelector('delivery',0)
- const identity=mobileStopIdentity(h.deliveryForms.value[0])
- h.deliveryForms.value=[{...h.deliveryForms.value[1]},{...h.deliveryForms.value[0]}]
- await h.handleMobileLinePickerConfirm([rows[0]])
- assert.equal(h.deliveryForms.value[0].products.length,0)
- assert.equal(mobileStopIdentity(h.deliveryForms.value[1]),identity)
- assert.equal(h.deliveryForms.value[1].products.length,1)
- })
- test('mobile opened line picker discards confirmation after target segment deletion',async()=>{
- const h=parentHarness()
- await h.openProductSelector('delivery',0)
- h.deliveryForms.value=[h.deliveryForms.value[1]]
- await h.handleMobileLinePickerConfirm([rows[0]])
- assert.equal(h.deliveryForms.value[0].products.length,0)
- })
- test('mobile pending line enrichment follows original segment after reorder',async()=>{
- const pending=deferred()
- const h=parentHarness({enrich:async(input:any)=>{await pending.promise;return input}})
- await h.openProductSelector('delivery',0)
- const task=h.handleMobileLinePickerConfirm([rows[0]])
- h.deliveryForms.value=[{...h.deliveryForms.value[1]},{...h.deliveryForms.value[0]}]
- pending.resolve();await task
- assert.equal(h.deliveryForms.value[0].products.length,0)
- assert.equal(h.deliveryForms.value[1].products.length,1)
- })
- test('mobile pending internal catalog enrichment follows original segment after reorder',async()=>{
- const pending=deferred()
- const h=parentHarness({enrich:async(input:any)=>{await pending.promise;return input}})
- await h.openProductSelector('delivery',0)
- const task=h.handleProductConfirm([{id:'catalog-product',productName:'目录产品'}])
- h.deliveryForms.value=[{...h.deliveryForms.value[1]},{...h.deliveryForms.value[0]}]
- pending.resolve();await task
- assert.equal(h.deliveryForms.value[0].products.length,0)
- assert.equal(h.deliveryForms.value[1].products[0].productId,'catalog-product')
- })
- test('mobile pending contract list opening follows original segment after reorder',async()=>{
- const pending=deferred()
- const h=parentHarness({fetch:async()=>{await pending.promise;return []}})
- const task=h.openProductSelector('delivery',0)
- h.deliveryForms.value=[{...h.deliveryForms.value[1]},{...h.deliveryForms.value[0]}]
- pending.resolve();await task
- assert.equal(h.linePickerVisible.value,true)
- await h.handleMobileLinePickerConfirm([rows[0]])
- assert.equal(h.deliveryForms.value[0].products.length,0)
- assert.equal(h.deliveryForms.value[1].products.length,1)
- })
|