96 lines
5.7 KiB
TypeScript
96 lines
5.7 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
||
import { readFileSync } from 'node:fs'
|
||
import { resolve } from 'node:path'
|
||
|
||
const source = readFileSync(resolve(process.cwd(), 'src/modules/suppliers/pages/SuppliersView.vue'), 'utf8')
|
||
const formSource = readFileSync(resolve(process.cwd(), 'src/modules/suppliers/pages/SupplierFormView.vue'), 'utf8')
|
||
const detailSource = readFileSync(resolve(process.cwd(), 'src/modules/suppliers/pages/SupplierDetailView.vue'), 'utf8')
|
||
const routesSource = readFileSync(resolve(process.cwd(), 'src/modules/suppliers/routes.ts'), 'utf8')
|
||
|
||
describe('supplier formal pages', () => {
|
||
it('clamps long supplier and represented-carrier names with the shared component', () => {
|
||
expect(source).toContain("LineClampText from '@/shared/components/LineClampText.vue'")
|
||
expect(source).toContain('<template #name="{ row }"><LineClampText :content="row.name" /></template>')
|
||
expect(source).toContain('<template #carrierCodes="{ row }"><LineClampText')
|
||
expect(source).not.toContain('class="supplier-name"')
|
||
})
|
||
|
||
it('keeps actions first and fixed left while guarding all operations with backend permissions', () => {
|
||
expect(source).toContain("{ key: 'actions', label: '操作', width: 260, fixed: 'left'")
|
||
expect(source).toContain("access.can('platform:supplier:create')")
|
||
expect(source).toContain("access.can('platform:supplier:edit')")
|
||
expect(source).toContain("access.can('platform:supplier:status')")
|
||
expect(source).toContain("access.can('platform:supplier:list')")
|
||
expect(source).toContain('class="density-action"')
|
||
expect(source).toContain('class="row-actions density-actions admin-text-actions"')
|
||
expect(source).toContain("statusLabels[supplierRow(row).status] ?? '—'")
|
||
})
|
||
|
||
it('matches the prototype statistics, category tabs and search sequence', () => {
|
||
expect(source).toContain('class="supplier-list-top"')
|
||
expect(source).toContain('class="supplier-query-panel integrated-query-group"')
|
||
expect(source).toContain('class="supplier-query-toolbar"')
|
||
expect(source).toContain('class="supplier-tabs density-status-tabs workbench-list-tabs"')
|
||
const toolbar = source.match(/<template #toolbar-start>([\s\S]*?)<\/template>/)?.[1]
|
||
const filters = source.match(/<template #filters>([\s\S]*?)<\/template>/)?.[1]
|
||
expect(toolbar).toContain('aria-label="供应商分类统计"')
|
||
expect(toolbar).toContain('({{ item.value }})')
|
||
expect(filters).toContain('<QueryToolbar')
|
||
expect(filters).not.toContain('role="tablist"')
|
||
expect(source).toContain('({{ item.value }})')
|
||
expect(source).not.toContain('class="supplier-metrics"')
|
||
expect(source).toContain('@click="switchCategory(item.category)"')
|
||
expect(source).not.toContain('订舱范围')
|
||
expect(source).not.toContain('国内/国外')
|
||
expect(formSource).not.toContain('form.scope')
|
||
expect(formSource).not.toContain('prop="scope"')
|
||
expect(detailSource).not.toContain('国内/国外')
|
||
})
|
||
|
||
it('uses independent routes for list, detail, create and edit', () => {
|
||
expect(routesSource).toContain("path: 'suppliers/new'")
|
||
expect(routesSource).toContain("path: 'suppliers/:id'")
|
||
expect(routesSource).toContain("path: 'suppliers/:id/edit'")
|
||
expect(routesSource).toContain("permission: 'platform:supplier:create'")
|
||
expect(routesSource).toContain("permission: 'platform:supplier:edit'")
|
||
expect(routesSource).toContain("permission: 'platform:supplier:list'")
|
||
expect(routesSource).not.toContain('platform:supplier:view')
|
||
expect(detailSource).toContain('供应商详情')
|
||
})
|
||
|
||
it('does not simulate supplier data or license upload and retains API errors', () => {
|
||
expect(source).not.toContain('supplierData')
|
||
expect(formSource).not.toContain('type="file"')
|
||
expect(formSource).toContain('暂不支持上传或替换资质文件。')
|
||
expect(formSource).toContain('<ApiErrorMeta')
|
||
expect(detailSource).toContain('<ApiErrorMeta')
|
||
})
|
||
|
||
it('uses a fixed multi-select for booking supplier carrier codes and sends no legacy scalar', () => {
|
||
expect(formSource).toContain('v-if="form.category === \'BOOKING\'"')
|
||
expect(formSource).toContain('v-for="option in carrierCodeOptions"')
|
||
expect(formSource).toContain('v-model="form.carrierCodes" multiple')
|
||
expect(formSource).toContain("if (category !== 'BOOKING') form.carrierCodes = []")
|
||
expect(formSource).toContain("carrierCodes: [...(carrierCodes || [])]")
|
||
expect(formSource).not.toMatch(/form\.carrierCode(?!s)/)
|
||
expect(source).toContain("label: '可代理船公司'")
|
||
expect(source).toContain("carrierCode: activeCategory.value === 'BOOKING' ? applied.value.carrierCode || undefined : undefined")
|
||
expect(detailSource).toContain("['可代理船公司', supplier.value.category === 'BOOKING' ? formatCarrierCodes(supplier.value.carrierCodes) : '—']")
|
||
})
|
||
|
||
it('reloads detail data when the reused route id changes and protects the newer request', () => {
|
||
expect(detailSource).toContain("watch(supplierId, () => { void load() }, { immediate: true })")
|
||
expect(detailSource).toContain('const requestedId = supplierId.value')
|
||
expect(detailSource).toContain('if (sequence !== loadSequence || requestedId !== supplierId.value) return')
|
||
expect(detailSource).toContain("params: { id: supplier.id }")
|
||
})
|
||
|
||
it('refreshes cached lists and resets cached create forms on activation', () => {
|
||
expect(source).toContain('onMounted(load)')
|
||
expect(source).toContain('if (activatedOnce) void load()')
|
||
expect(formSource).toContain('if (activatedOnce) void load()')
|
||
expect(formSource).toContain('onDeactivated(() => { active = false })')
|
||
expect(formSource).toContain("watch(supplierId, () => { if (active) void load() }, { immediate: true })")
|
||
})
|
||
})
|