Files
admin-web/src/modules/overseas-master-data/pages/OverseasMasterDataViews.test.ts
T

112 lines
5.9 KiB
TypeScript

import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
function source(name: string) {
return readFileSync(resolve(process.cwd(), `src/modules/overseas-master-data/pages/${name}.vue`), 'utf8')
}
describe('overseas master data real contract pages', () => {
it('gives every list query toolbar a unique stable preference key', () => {
const expectedKeys = new Map([
['OverseasQuotesView', 'overseas-quotes-query'],
['ExchangeRatesView', 'overseas-exchange-rates-query'],
['VehiclesView', 'overseas-vehicles-query'],
])
const actualKeys: string[] = []
for (const [name, expectedKey] of expectedKeys) {
const view = source(name)
const toolbar = view.match(/<QueryToolbar\b[^>]*\/>/s)?.[0]
expect(toolbar, `${name} should render QueryToolbar`).toBeDefined()
expect(toolbar).toContain(`preference-key="${expectedKey}"`)
const actualKey = toolbar?.match(/preference-key="([^"]+)"/)?.[1]
expect(actualKey).toBe(expectedKey)
actualKeys.push(actualKey!)
}
expect(new Set(actualKeys).size).toBe(actualKeys.length)
})
it('keeps operation columns first and preserves the prototype fields', () => {
const quotes = source('OverseasQuotesView')
const exchangeRates = source('ExchangeRatesView')
const vehicles = source('VehiclesView')
expect(quotes.indexOf("key:'actions'")).toBeLessThan(quotes.indexOf("key:'name'"))
for (const label of ['报价名称', '海外仓', '服务商', '币种', '生效日期', '失效日期', '报价版本', '状态', '更新时间', '备注']) {
expect(quotes).toContain(`label:'${label}'`)
}
const exchangeColumns = exchangeRates.slice(exchangeRates.indexOf('const columns'))
expect(exchangeColumns.indexOf("key: 'actions'")).toBeLessThan(exchangeColumns.indexOf("key: 'month'"))
expect(vehicles.indexOf("key:'actions'")).toBeLessThan(vehicles.indexOf("key:'plateNumber'"))
for (const label of ['自有车辆', '外派车辆', '司机 / 外派单位']) expect(vehicles).toContain(label)
expect(vehicles).toContain("key:'region'")
expect(vehicles).toContain("placeholder:'全部区域'")
expect(vehicles).toContain('class="status-tabs density-status-tabs"')
expect(vehicles).toContain("'status-tab',{'is-active':ownership===tab[1]}")
expect(vehicles).not.toContain('<el-segmented')
expect(vehicles).not.toContain('aria-label="车辆区域"')
})
it('uses real API operations and canonical action permissions', () => {
for (const name of ['OverseasQuotesView', 'ExchangeRatesView', 'VehiclesView']) {
const view = source(name)
expect(view).toContain("from '../api/overseasMasterData'")
expect(view).toContain('access.can(permission.')
expect(view).toContain('ElMessage.success')
}
expect(source('OverseasQuotesView')).toContain('导出CSV')
expect(source('VehiclesView')).toContain('导出CSV')
expect(source('ExchangeRatesView')).toContain("'monthly-exchange-rates.csv'")
for (const name of ['OverseasQuotesView', 'ExchangeRatesView', 'VehiclesView']) {
expect(source(name)).not.toMatch(/deleteQuote|deleteExchangeRate|deleteVehicle/)
}
expect(source('OverseasQuotesView')).toContain('changeQuoteStatus(row.id,next,row.recordVersion)')
expect(source('ExchangeRatesView')).toContain('changeExchangeRateStatus(row.month, next, row.recordVersion, null)')
expect(source('VehiclesView')).toContain('changeVehicleStatus(row.id,statusTarget.value,row.recordVersion)')
for (const name of ['OverseasQuotesView', 'ExchangeRatesView', 'VehiclesView']) {
expect(source(name)).toContain("masterDataErrorMessage(")
expect(source(name)).toContain('saveCsv(await export')
}
})
it('uses an independent API-backed vehicle detail page without inventing fulfillment history', () => {
const detail = source('VehicleDetailView')
expect(detail).toContain('车辆信息')
expect(detail).toContain('派送订单明细')
expect(detail).toContain('派送更换记录')
expect(detail).toContain('getVehicle(')
expect(detail).toContain(':vehicle-id="detail.id" kind="deliveries"')
expect(detail).toContain(':vehicle-id="detail.id" kind="changes"')
expect(detail).not.toContain('车辆更换记录尚未接入')
expect(detail).not.toContain('AppDrawer')
expect(detail).not.toContain('const vehicle =')
})
it('records the prototype evidence before implementation', () => {
const matrix = readFileSync(resolve(process.cwd(), 'src/modules/overseas-master-data/PROTOTYPE_MATRIX.md'), 'utf8')
for (const id of ['gen-partner-warehouse', 'gen-overseas-quote', 'gen-exchange-rate', 'vehicle-detail']) expect(matrix).toContain(id)
for (const modal of ['modal-gen-overseas-quote-detail', 'modal-gen-overseas-quote', 'modal-exchange-rate-edit', 'modal-vehicle-edit']) expect(matrix).toContain(modal)
expect(matrix).toContain('旧版原型未定义的车辆文件预览、审核/确认流程不自行补充')
expect(matrix).toContain('新版车辆保养及加油接入矩阵')
expect(matrix).toContain('modal-vehicle-ops-record')
expect(matrix).toContain('target="_blank"')
})
it('records the real service boundary and remaining unsupported operations', () => {
const gaps = readFileSync(resolve(process.cwd(), 'src/modules/overseas-master-data/CONTRACT_GAPS.md'), 'utf8')
expect(gaps).toContain('/api/platform/v1/last-leg/master-data')
expect(gaps).toContain('/overseas-quotes/warehouse-options')
expect(gaps).toContain('浏览器不调用国内')
expect(gaps).toContain('没有删除端点')
expect(gaps).toContain('JSON 错误 Blob')
expect(gaps).not.toContain('尚无已确认')
expect(matrixSource()).not.toContain('写入口禁用')
expect(matrixSource()).not.toContain('等待查询接口')
})
})
function matrixSource() {
return readFileSync(resolve(process.cwd(), 'src/modules/overseas-master-data/PROTOTYPE_MATRIX.md'), 'utf8')
}