import { readFileSync } from 'node:fs' import { join } from 'node:path' import { describe, expect, it } from 'vitest' const source = readFileSync(join(process.cwd(), 'src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.vue'), 'utf8') const detailSource = readFileSync(join(process.cwd(), 'src/modules/fba-pricing/carrier-rates/pages/CarrierRateDetailView.vue'), 'utf8') const routeSource = readFileSync(join(process.cwd(), 'src/modules/fba-pricing/routes.ts'), 'utf8') const queryToolbarSource = readFileSync(join(process.cwd(), 'src/shared/components/QueryToolbar.vue'), 'utf8') describe('CarrierRatesView price-book source contract', () => { it('keeps the operation column first and presents version-level history', () => { expect(source.indexOf("key: 'actions'")).toBeLessThan(source.indexOf("key: 'version'")) for (const label of ['价格表版本', '原始文件', '解析结果', '校验结果', '上传时间', '实际生效区间']) { expect(source).toContain(label) } expect(source).toContain('formatEffectivePeriod') expect(source).toContain('PENDING_CONFIRMATION') expect(source).toContain('SUPERSEDED') expect(source).not.toContain('ID {{ (row as PlatformPriceBookVersion).id }}') expect(source).toContain("key: 'originalFileName', prop: 'originalFileName', label: '原始文件', minWidth: 250, showOverflowTooltip: true, defaultVisible: false") }) it('uses only the parsed price-book workflow instead of legacy carrier-rate editing', () => { const workflowSource = `${source}\n${detailSource}` for (const capability of [ 'listPlatformPriceBooks', 'getPlatformPriceBook', 'uploadPlatformPriceBook', 'publishPlatformPriceBook', 'downloadPlatformPriceBookSource', ]) expect(workflowSource).toContain(capability) for (const legacyCapability of [ 'createPlatformCarrierRateVersion', 'listPlatformCarrierRates', 'retirePlatformCarrierRate', '新增价格版本', '编辑价格', '有效期', '生效日期', ]) expect(workflowSource).not.toContain(legacyCapability) }) it('opens a formal detail route and keeps uploaded prices immutable', () => { expect(source).toContain('上传并解析') expect(source).toContain('查看并确认') expect(source).toContain("name: 'fba-carrier-rate-detail'") expect(routeSource).toContain("path: 'first-leg-pricing/carrier-rates/:versionId'") expect(routeSource).toContain("import('./carrier-rates/pages/CarrierRateDetailView.vue')") expect(detailSource).toContain('返回列表') expect(detailSource).toContain('确认并立即生效') expect(detailSource).toContain('价格行不可在页面内修改') expect(detailSource).toContain('confirmPriceBook') expect(detailSource).toContain('publishPlatformPriceBook') expect(`${source}\n${detailSource}`).not.toContain('草稿') }) it('shows all source-backed prototype price metadata without inventing cost breakdowns', () => { for (const label of ['渠道', '参考时效', '最晚进仓时间', '船期', '附加费', '备注', '生效状态']) { expect(detailSource).toContain(`label="${label}"`) } for (const field of ['referenceTransit', 'latestWarehouseEntry', 'estimatedDepartureText', 'surchargeDescription', 'remark']) { expect(detailSource).toContain(`selectedChannel?.${field}`) } expect(detailSource).not.toContain('AMS+换单费') expect(detailSource).not.toContain('建议报价') }) it('maps only active platform public domestic and overseas warehouses before confirmation', () => { expect(detailSource).toContain('listAllPlatformWarehouses()') expect(detailSource).toContain("warehouse.warehouseType === 'DOMESTIC'") expect(detailSource).toContain("warehouse.warehouseType === 'OVERSEAS'") expect(detailSource).toContain('起运仓映射') expect(detailSource).toContain('海外仓映射') expect(detailSource).toContain('originWarehouseCode') expect(detailSource).toContain('sourceDestinationName') expect(detailSource).toContain('autoSelectExactWarehouseMappings') expect(detailSource).toContain("'DUPLICATE_RATE'") expect(detailSource).toContain('.channel-tabs { width: 100%; min-width: 0;') expect(detailSource).toContain('.channel-preview :deep(.el-table) { width: 100%; max-width: 100%; min-width: 0; }') expect(detailSource).not.toContain('tenantId') }) it('supports public and customer-specific price-book scopes without exposing technical ids', () => { expect(source).toContain('listPlatformTenants') expect(source).toContain("customerId: '0'") expect(source).toContain('平台公共报价') expect(source).toContain('客户专属') expect(source).toContain('uploadPlatformPriceBook(file, uploadCustomerId.value)') expect(source).toContain('只替换同一报价范围') expect(detailSource).not.toContain('{{ detail.version.customerId }}') }) it('shows parsing blockers and a channel-tabbed, read-only preview', () => { expect(detailSource).toContain('nonMappingBlockingIssues') expect(detailSource).toContain('解析与校验') expect(detailSource).toContain('按渠道预览') expect(detailSource).toContain('') expect(detailSource).toContain('') expect(detailSource).not.toContain('detail.issues" size="small" max-height="280" border stripe') }) it('accepts only xlsx uploads and retains original-file download', () => { expect(source).toContain('accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"') expect(source).toContain("endsWith('.xlsx')") expect(source).toContain('10 * 1024 * 1024') expect(source).toContain('downloadSource') expect(source).toContain('saveBlob') }) it('uses the shared query and table primitives with mobile layout handling', () => { expect(source).toContain("import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'") expect(source).toContain("import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'") expect(source).toContain('LoadErrorState') expect(queryToolbarSource).toContain('flex-wrap: wrap') expect(source).toContain('@media (max-width: 720px)') expect(source).toContain('.table-actions :deep(.el-button) { min-height: 40px; }') expect(detailSource).toContain('@media (max-width: 720px)') expect(detailSource).toContain('.detail-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }') }) it('uses bordered striped tables and explicit semantic business buttons', () => { expect(source).toContain('确认并立即生效') expect(detailSource).toContain('class="density-detail-header"') expect(source).not.toContain('') expect(source).toContain('') expect(source).toContain('