test(mobile-oa-h5): expect JD-style presign status filter without reset
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
8dd816ee1d
commit
c767373a8f
1 file changed
+165
-17
@@ -84,7 +84,8 @@ test('protocol lists wire dual source tabs into listParams and create navigation
|
||||
assert.doesNotMatch(genericList, /bindNativeTabListeners/)
|
||||
assert.doesNotMatch(genericList, /installGlobalPointerProbe/)
|
||||
assert.doesNotMatch(genericList, /<van-tabs/)
|
||||
assert.match(genericList, /listParams\?\.\(\{\s*status:\s*listStatus\.value\s*\}\)/)
|
||||
assert.match(genericList, /buildListParams\(context\.value\.module, listFilters\.value\)/)
|
||||
assert.match(genericList, /createListFilters\('protocol', next\)/)
|
||||
assert.match(genericList, /source:\s*listStatus\.value/)
|
||||
assert.match(genericList, /usesSourceTabs/)
|
||||
assert.match(genericList, /module === 'protocol'/)
|
||||
@@ -94,6 +95,66 @@ test('protocol lists wire dual source tabs into listParams and create navigation
|
||||
assert.doesNotMatch(styles, /\.market-list__filters\s*\{[^}]*position:\s*sticky/)
|
||||
})
|
||||
|
||||
test('market lists expose a mobile filter sheet for web-equivalent conditions', () => {
|
||||
const genericList = source('../views/market/MarketModuleList.vue')
|
||||
const sheet = source('./components/MarketFilterSheet.vue')
|
||||
const styles = source('../styles/market.css')
|
||||
|
||||
assert.match(genericList, /<MarketFilterSheet/)
|
||||
assert.match(genericList, /activeFilterCount/)
|
||||
assert.match(genericList, /fetchMarketFormOptions/)
|
||||
assert.match(sheet, /field\.type === 'select'/)
|
||||
assert.match(sheet, /field\.type === 'date-range'/)
|
||||
assert.match(sheet, /type="date"/)
|
||||
assert.match(styles, /\.market-list__filter-button\s*\{/)
|
||||
assert.match(styles, /min-height:\s*44px/)
|
||||
})
|
||||
|
||||
test('dedicated presign list wires orderStatus dropdown without reset on mobile', () => {
|
||||
const presignList = source('../views/market/presign/PresignOrderList.vue')
|
||||
const styles = source('../styles/market.css')
|
||||
|
||||
assert.match(presignList, /v-model="orderStatus"/)
|
||||
assert.match(presignList, /buildPresignListParams/)
|
||||
assert.match(presignList, /orderStatusOptions/)
|
||||
assert.match(presignList, /van-dropdown-menu/)
|
||||
assert.doesNotMatch(presignList, /resetFilters/)
|
||||
assert.doesNotMatch(presignList, />重置</)
|
||||
assert.match(styles, /\.presign-order-page__filter-row\s*\{/)
|
||||
assert.match(styles, /\.presign-order-page__filter-row\s+\.van-dropdown-menu__bar/)
|
||||
assert.doesNotMatch(styles, /\.presign-order-page__filter-row\s+\.van-button\s*\{/)
|
||||
})
|
||||
|
||||
test('freight sample selector supports source filters, server paging and confirmations', () => {
|
||||
const form = source('../views/market/MarketModuleForm.vue')
|
||||
const styles = source('../styles/market.css')
|
||||
assert.match(form, /v-model="sampleSource"/)
|
||||
assert.match(form, /sampleOptionsPage/)
|
||||
assert.match(form, /sampleOptionsRequestPending/)
|
||||
assert.match(form, /loadMoreSampleOptions/)
|
||||
assert.match(form, /pageSize:\s*SAMPLE_OPTION_PAGE_SIZE/)
|
||||
assert.doesNotMatch(form, /page:\s*1,\s*pageSize:\s*100/)
|
||||
assert.match(form, /确认关联样本/)
|
||||
assert.match(form, /确认取消运费/)
|
||||
assert.match(styles, /\.market-sample-option\s*\{[\s\S]*?min-height:\s*44px;/)
|
||||
assert.match(styles, /\.market-sample-option\s*\{[\s\S]*?min-width:\s*0;/)
|
||||
assert.match(styles, /\.market-sample-option \.van-checkbox__label\s*\{[\s\S]*?overflow-wrap:\s*anywhere;/)
|
||||
})
|
||||
|
||||
test('protocol list exposes mobile batch selection and sequential authorized deletion', () => {
|
||||
const genericList = source('../views/market/MarketModuleList.vue')
|
||||
assert.match(genericList, /batchSelectionMode/)
|
||||
assert.match(genericList, /selectedRecordIds/)
|
||||
assert.match(genericList, /deleteMarketItemsSequentially/)
|
||||
assert.match(genericList, /批量删除/)
|
||||
assert.match(genericList, /未处理/)
|
||||
})
|
||||
|
||||
test('market detail contains no protocol audit interaction', () => {
|
||||
const detail = source('../views/market/MarketModuleDetail.vue')
|
||||
assert.doesNotMatch(detail, /auditSheetVisible|submitProtocolAudit|审核协议单/)
|
||||
})
|
||||
|
||||
test('all ten market list entries keep cards inside the horizontal content area', () => {
|
||||
const styles = source('../styles/market.css')
|
||||
const routes = source('./routes.js')
|
||||
@@ -129,12 +190,42 @@ test('market create and edit bottom actions are centered', () => {
|
||||
assert.match(styles, /\.presign-form-bottom\s*\{[\s\S]*?justify-content:\s*center;/)
|
||||
})
|
||||
|
||||
test('market retry and presign action targets are explicitly at least 44 by 44 pixels', () => {
|
||||
const styles = source('../styles/market.css')
|
||||
const orderCard = source('./components/PresignOrderCard.vue')
|
||||
const transferCard = source('./components/PresignTransferCard.vue')
|
||||
const presignList = source('../views/market/presign/PresignOrderList.vue')
|
||||
const presignForm = source('../views/market/presign/PresignOrderForm.vue')
|
||||
const genericList = source('../views/market/MarketModuleList.vue')
|
||||
const genericForm = source('../views/market/MarketModuleForm.vue')
|
||||
|
||||
assert.match(styles, /\.presign-order-card__actions \.van-button\s*\{[^}]*min-width:\s*(?:[4-9]\d|\d{3,})px;[^}]*min-height:\s*(?:[4-9]\d|\d{3,})px;/)
|
||||
assert.match(styles, /\.presign-order-list__error \.van-button\s*\{[^}]*min-width:\s*(?:[4-9]\d|\d{3,})px;[^}]*min-height:\s*(?:[4-9]\d|\d{3,})px;/)
|
||||
assert.match(styles, /\.presign-form-section__heading \.van-button\s*\{[^}]*min-width:\s*(?:[4-9]\d|\d{3,})px;[^}]*min-height:\s*(?:[4-9]\d|\d{3,})px;/)
|
||||
assert.match(styles, /\.market-state \.van-button\s*\{[^}]*min-width:\s*(?:[4-9]\d|\d{3,})px;[^}]*min-height:\s*(?:[4-9]\d|\d{3,})px;/)
|
||||
assert.match(transferCard, /\.presign-transfer-card__actions \.van-button\s*\{[^}]*min-width:\s*(?:[4-9]\d|\d{3,})px;[^}]*min-height:\s*(?:[4-9]\d|\d{3,})px;/)
|
||||
|
||||
assert.doesNotMatch(orderCard, /<van-button[\s\S]*?size="small"/)
|
||||
assert.doesNotMatch(transferCard, /<van-button[\s\S]*?size="small"/)
|
||||
assert.doesNotMatch(presignList, /presign-order-list__error[\s\S]*?<van-button[^>]*size="small"/)
|
||||
assert.doesNotMatch(presignForm, /presign-form-section__heading[\s\S]*?<van-button[^>]*size="small"/)
|
||||
assert.match(genericList, /class="market-state"[\s\S]*?<van-button[^>]*>重新加载<\/van-button>/)
|
||||
assert.doesNotMatch(genericList, /class="market-state"[\s\S]*?<van-button[^>]*size="small"/)
|
||||
assert.match(genericForm, /v-else-if="errorMessage" class="market-state"/)
|
||||
assert.doesNotMatch(genericForm, /v-else-if="errorMessage"[\s\S]*?<van-button[^>]*size="small"/)
|
||||
})
|
||||
|
||||
test('market attachments use the workflow thumbnail and file-icon contract', () => {
|
||||
const attachmentCards = source('./components/MarketAttachmentCards.vue')
|
||||
|
||||
assert.match(attachmentCards, /normalizeMarketAttachments/)
|
||||
assert.match(attachmentCards, /downloadAttachmentFile/)
|
||||
assert.match(attachmentCards, /fetchMarketAttachmentDownloadUrl/)
|
||||
assert.match(attachmentCards, /createAuthorizedImagePreviewResolver/)
|
||||
assert.match(attachmentCards, /:src="authorizedImageUrl\(file\)"/)
|
||||
assert.match(attachmentCards, /previewResolver\.resolve/)
|
||||
assert.match(attachmentCards, /showImagePreview\(\{ images: \[authorizedUrl\]/)
|
||||
assert.match(attachmentCards, /previewResolver\.dispose\(\)/)
|
||||
assert.match(attachmentCards, /showImagePreview/)
|
||||
assert.match(attachmentCards, /market-attachment-card__download-action/)
|
||||
assert.match(attachmentCards, /@click\.stop="downloadAttachment\(file\)"/)
|
||||
@@ -146,6 +237,8 @@ test('market attachments use the workflow thumbnail and file-icon contract', ()
|
||||
assert.match(attachmentCards, /market-attachment-card__main[\s\S]*?overflow:\s*hidden/)
|
||||
assert.match(attachmentCards, /\.market-attachment-card__download-action\s*\{[\s\S]*?width:\s*44px;[\s\S]*?height:\s*44px;/)
|
||||
assert.match(attachmentCards, /file\.explicitName\s*\?\s*file\.name\s*:\s*undefined/)
|
||||
assert.doesNotMatch(attachmentCards, /attachmentFullUrl/)
|
||||
assert.doesNotMatch(attachmentCards, /:src="fullUrl\(/)
|
||||
assert.doesNotMatch(attachmentCards, /#10b981/i)
|
||||
for (const kind of ['pdf', 'xls', 'doc', 'zip', 'other']) {
|
||||
assert.match(attachmentCards, new RegExp(`ft-${kind}`))
|
||||
@@ -199,7 +292,8 @@ test('payment detail presents every web field and nested transfer field with Chi
|
||||
transferAmount: '3000.00',
|
||||
transferTime: '2026-10-11 10:00:00',
|
||||
transferAttachments: 'proof.pdf',
|
||||
remark: '首笔'
|
||||
remark: '首笔',
|
||||
financeRemark: '财务已核对'
|
||||
}]
|
||||
}]
|
||||
})
|
||||
@@ -215,7 +309,7 @@ test('payment detail presents every web field and nested transfer field with Chi
|
||||
)
|
||||
assert.deepEqual(
|
||||
sections[1].cards[0].cards[0].fields.map((field) => field.label),
|
||||
['转账方式', '转账金额', '转账时间', '转账凭证', '备注']
|
||||
['转账方式', '转账金额', '转账时间', '转账凭证', '备注', '财务备注']
|
||||
)
|
||||
})
|
||||
|
||||
@@ -257,9 +351,9 @@ test('protocol cards expose the same business fields as the web list', async ()
|
||||
})
|
||||
|
||||
assert.deepEqual(card.fields.map((field) => field.label), [
|
||||
'状态', '登记日期', '母亲姓名', '母亲电话', '母亲身份证号', '父亲姓名',
|
||||
'状态', '协议编号', '登记日期', '母亲姓名', '母亲电话', '母亲身份证号', '父亲姓名',
|
||||
'新生儿性别', '分娩方式', '新生儿体重(克)', '采集地区', '采集医院',
|
||||
'采集专员', '市场专员', '样本采集时间', '创建时间'
|
||||
'采集专员', '市场专员', '样本采集时间', '样本编码', '创建时间'
|
||||
])
|
||||
assert.deepEqual(card.actions, ['view', 'edit', 'delete'])
|
||||
})
|
||||
@@ -270,7 +364,10 @@ test('protocol, freight and presign details define explicit Chinese nested cards
|
||||
basic: { protocolNo: 'P-1', protocolStatus: 'sxz' },
|
||||
customer: { motherName: '张三' },
|
||||
samples: [{ id: 's1', sampleCode: 'S-1', sampleTypeName: '脐带血' }],
|
||||
attachments: { protocolAttachments: 'a.pdf' }
|
||||
attachments: { protocolAttachments: 'a.pdf' },
|
||||
storageCert: { makeStatus: '0', certImageUrls: 'cert.jpg' },
|
||||
fullmoonTodo: { handled: false, insuranceAttachments: 'ins.pdf', handleTime: '2026-10-01' },
|
||||
audits: []
|
||||
})
|
||||
const freight = getMarketModule('freight').detailSections({
|
||||
freightNo: 'F-1', transportModeLabel: '冷链', freightAmount: '20',
|
||||
@@ -291,6 +388,15 @@ test('protocol, freight and presign details define explicit Chinese nested cards
|
||||
}
|
||||
}
|
||||
assert.ok(protocol.find((section) => section.key === 'samples').cards.length)
|
||||
const storageCert = protocol.find((section) => section.key === 'storageCert')
|
||||
const insurance = protocol.find((section) => section.key === 'insurance')
|
||||
assert.ok(storageCert)
|
||||
assert.ok(insurance)
|
||||
assert.ok(storageCert.fields.some((field) => field.type === 'attachments' && field.label === '储存证图片'))
|
||||
assert.ok(insurance.fields.some((field) => field.type === 'attachments' && field.label === '保险附件'))
|
||||
assert.ok(insurance.fields.some((field) => field.label === '办理时间'))
|
||||
assert.ok(protocol.find((section) => section.key === 'audits'))
|
||||
assert.ok(protocol.find((section) => section.key === 'statusChange'))
|
||||
assert.ok(freight.find((section) => section.key === 'items').cards.length)
|
||||
assert.ok(presign.find((section) => section.key === 'transfers').cards.length)
|
||||
})
|
||||
@@ -316,27 +422,69 @@ test('protocol create and edit forms expose every writable web business field',
|
||||
'newbornIdCard', 'deliveryMode', 'birthOrder', 'newbornWeightGram',
|
||||
'apgar1min', 'apgar5min', 'remark'
|
||||
])
|
||||
assert.deepEqual(bySection.samples, [
|
||||
'sampleTypeId', 'sampleCodeId', 'sampleCode', 'collectAmount', 'unitId',
|
||||
'price', 'originalPrice', 'storageYears', 'etaTime', 'isSpecial', 'specialRemark', 'remark'
|
||||
])
|
||||
assert.equal(bySection.samples, undefined)
|
||||
assert.deepEqual(bySection.attachments, [
|
||||
'protocolAttachments', 'consentFormUrls', 'healthSurveyFormUrls',
|
||||
'attachmentUrls', 'infectiousDiseaseReportUrls'
|
||||
])
|
||||
const customer = module.formSections.find((section) => section.key === 'customer')
|
||||
const samples = module.formSections.find((section) => section.key === 'samples')
|
||||
assert.deepEqual(
|
||||
customer.fields.find((field) => field.key === 'motherName'),
|
||||
{ key: 'motherName', label: '母亲姓名', type: 'customerSearch', role: 'mother', required: true }
|
||||
)
|
||||
assert.deepEqual(
|
||||
customer.fields.find((field) => field.key === 'fatherName'),
|
||||
{ key: 'fatherName', label: '父亲姓名', type: 'customerSearch', role: 'father' }
|
||||
)
|
||||
assert.deepEqual(
|
||||
customer.fields.find((field) => field.key === 'motherEthnic'),
|
||||
{ key: 'motherEthnic', label: '母亲民族', type: 'select', optionKey: 'ethnicities' }
|
||||
)
|
||||
assert.deepEqual(
|
||||
samples.fields.find((field) => field.key === 'sampleCodeId'),
|
||||
{ key: 'sampleCodeId', label: '样本编码记录', type: 'select', optionKey: 'sampleCodes' }
|
||||
)
|
||||
const form = source('../views/market/MarketModuleForm.vue')
|
||||
assert.match(form, /field\.key === 'sampleCodeId'/)
|
||||
assert.match(form, /sampleCode:\s*option\?\.sampleCode/)
|
||||
assert.match(form, /ProtocolSampleTransportPanel/)
|
||||
assert.match(form, /buildProtocolSamplesPayload/)
|
||||
assert.match(form, /handleCustomerSelect/)
|
||||
assert.match(form, /calcBirthYmFromIdCard/)
|
||||
assert.match(form, /fetchMarketProtocolCustomers/)
|
||||
assert.match(form, /protocolTotalFollowSamples/)
|
||||
assert.match(form, /syncProtocolTotalFromSamples/)
|
||||
assert.match(form, /sampleContractSum/)
|
||||
const samplePanel = source('../market/components/ProtocolSampleTransportPanel.vue')
|
||||
assert.match(samplePanel, /添加样本/)
|
||||
assert.match(samplePanel, /配置运费/)
|
||||
assert.match(samplePanel, /取消运费/)
|
||||
assert.match(samplePanel, /buildFreightUnlinkCandidates/)
|
||||
assert.match(samplePanel, /(共用)/)
|
||||
assert.match(samplePanel, /样本状态/)
|
||||
assert.match(samplePanel, /特殊说明/)
|
||||
assert.match(samplePanel, /showPrice/)
|
||||
assert.match(samplePanel, /autoGenerateCode/)
|
||||
const payPanel = source('../market/components/ProtocolSamplePaymentPanel.vue')
|
||||
assert.match(payPanel, /applyPreferentialPriceToPayment/)
|
||||
assert.match(payPanel, /lastPreferentialByCode/)
|
||||
assert.match(payPanel, /添加转账/)
|
||||
assert.match(payPanel, /提交财务确认/)
|
||||
assert.match(payPanel, /撤回/)
|
||||
assert.match(payPanel, /protocolId/)
|
||||
assert.match(payPanel, /canUseProtocolScheduleAction/)
|
||||
assert.match(payPanel, /canUseProtocolTransferAction/)
|
||||
assert.doesNotMatch(payPanel, /canManageTransfers/)
|
||||
assert.match(payPanel, /performMarketAction|register-transfer/)
|
||||
assert.match(payPanel, /module:\s*'payment'/)
|
||||
assert.doesNotMatch(payPanel, /module:\s*'protocol'[\s\S]*uploadTransferFile/)
|
||||
assert.match(form, /:protocol-id=/)
|
||||
assert.doesNotMatch(form, /:can-manage-transfers="true"/)
|
||||
assert.match(form, /presignDepositHint/)
|
||||
assert.match(form, /depositTransfers/)
|
||||
const protocolModule = source('../market/modules/protocol.js')
|
||||
assert.match(protocolModule, /意向金(关联预签约)/)
|
||||
assert.match(protocolModule, /储存证/)
|
||||
assert.match(protocolModule, /审核记录/)
|
||||
assert.match(protocolModule, /状态变更记录/)
|
||||
assert.match(protocolModule, /运输方式/)
|
||||
assert.match(protocolModule, /运费金额/)
|
||||
assert.match(form, /mergeProtocolCustomerLinks/)
|
||||
assert.match(form, /initLinkedCustomerNames/)
|
||||
})
|
||||
|
||||
test('presign delete action calls the delete API exactly once', () => {
|
||||
|
||||
Reference in new issue
Block a user