ad6658e490
抽屉副标题/5 国家草稿与变更差异(空值→删除)纯逻辑, 保存走 PUT/DELETE
/api/admin/query-asins/{id}/countries/{country}, 9 个契约测试。
107 lines
4.6 KiB
TypeScript
107 lines
4.6 KiB
TypeScript
import test from 'node:test'
|
||
import assert from 'node:assert/strict'
|
||
import { readSource } from './helpers.ts'
|
||
import {
|
||
QUERY_ASIN_COUNTRY_LABELS,
|
||
queryAsinCountryLabel,
|
||
queryAsinDetailSubtitle,
|
||
queryAsinCountryDraftsOf,
|
||
diffQueryAsinCountryChanges,
|
||
type QueryAsinCountryChange,
|
||
} from '../src/pages/asin/query-asin-detail-model.ts'
|
||
import { toQueryAsinItem } from '../src/pages/asin/query-asin-model.ts'
|
||
|
||
test('test_task_074_query_asin_detail_subtitle_normal_primary_path', () => {
|
||
// 正常主路径:抽屉副标题 = 分组 / 店铺名。
|
||
const item = toQueryAsinItem({ id: 1, groupName: '华东组', shopName: 'BlueWave' })!
|
||
assert.equal(queryAsinDetailSubtitle(item), '华东组 / BlueWave')
|
||
})
|
||
|
||
test('test_task_074_query_asin_detail_subtitle_normal_variant_input', () => {
|
||
// 正常变体:无分组时仅店铺名;5 国家标签齐全。
|
||
const item = toQueryAsinItem({ id: 2, shopName: 'RedSun' })!
|
||
assert.equal(queryAsinDetailSubtitle(item), 'RedSun')
|
||
assert.deepEqual(QUERY_ASIN_COUNTRY_LABELS, {
|
||
DE: '德国', UK: '英国', FR: '法国', IT: '意大利', ES: '西班牙',
|
||
})
|
||
assert.equal(queryAsinCountryLabel('DE'), '德国')
|
||
assert.equal(queryAsinCountryLabel('FR'), '法国')
|
||
})
|
||
|
||
test('test_task_074_query_asin_detail_drafts_normal_primary', () => {
|
||
// 正常主路径:由行生成 5 国家草稿(trimmed 当前值)。
|
||
const item = toQueryAsinItem({ id: 3, shopName: 'S', asinDe: ' B0DE1 ', asinEs: 'B0ES1' })!
|
||
const drafts = queryAsinCountryDraftsOf(item)
|
||
assert.equal(drafts.length, 5)
|
||
assert.equal(drafts[0].code, 'DE')
|
||
assert.equal(drafts[0].value, 'B0DE1')
|
||
assert.equal(drafts[4].value, 'B0ES1')
|
||
assert.equal(drafts[1].value, '')
|
||
})
|
||
|
||
test('test_task_074_query_asin_detail_diff_normal_no_change', () => {
|
||
// 正常重复:值未变(大小写/空白归一后相等) → 无任何变更。
|
||
const item = toQueryAsinItem({ id: 4, shopName: 'S', asinDe: 'B0DE1' })!
|
||
const changes = diffQueryAsinCountryChanges(item, [
|
||
{ code: 'DE', value: ' b0de1 ' },
|
||
{ code: 'UK', value: '' },
|
||
])
|
||
assert.deepEqual(changes, [])
|
||
})
|
||
|
||
test('test_task_074_query_asin_detail_diff_boundary_empty_means_delete', () => {
|
||
// 边界空值:当前有值但草稿留空 → 删除该国家。
|
||
const item = toQueryAsinItem({ id: 5, shopName: 'S', asinUk: 'B0UK1', asinDe: 'B0DE1' })!
|
||
const changes = diffQueryAsinCountryChanges(item, [
|
||
{ code: 'UK', value: '' },
|
||
{ code: 'DE', value: 'B0DE1' },
|
||
])
|
||
assert.equal(changes.length, 1)
|
||
assert.equal(changes[0].kind, 'delete')
|
||
assert.equal(changes[0].code, 'UK')
|
||
})
|
||
|
||
test('test_task_074_query_asin_detail_diff_normal_update', () => {
|
||
// 正常主路径:值不同且非空 → update,ASIN 大写归一。
|
||
const item = toQueryAsinItem({ id: 6, shopName: 'S', asinFr: 'B0OLD' })!
|
||
const changes = diffQueryAsinCountryChanges(item, [{ code: 'FR', value: ' b0new1 ' }])
|
||
assert.equal(changes.length, 1)
|
||
assert.equal(changes[0].kind, 'update')
|
||
assert.equal(changes[0].asin, 'B0NEW1')
|
||
})
|
||
|
||
test('test_task_074_query_asin_detail_diff_invalid_input_rejected', () => {
|
||
// 异常输入:草稿含未知国家码被忽略;缺失国家草稿不产生变更(不会误删)。
|
||
const item = toQueryAsinItem({ id: 7, shopName: 'S', asinDe: 'B0DE1' })!
|
||
const changes = diffQueryAsinCountryChanges(item, [
|
||
{ code: 'XX', value: 'abc' },
|
||
{ code: 'DE', value: 'B0DE1' },
|
||
])
|
||
assert.deepEqual(changes, [])
|
||
})
|
||
|
||
test('test_task_074_query_asin_detail_diff_boundary_multi', () => {
|
||
// 边界/多变更:同批 update + delete 混合且顺序稳定(按支持国家序)。
|
||
const item = toQueryAsinItem({ id: 8, shopName: 'S', asinDe: 'D', asinIt: 'I', asinEs: 'E' })!
|
||
const changes: QueryAsinCountryChange[] = diffQueryAsinCountryChanges(item, [
|
||
{ code: 'IT', value: '' },
|
||
{ code: 'DE', value: 'NEWD' },
|
||
{ code: 'ES', value: 'E' },
|
||
])
|
||
assert.equal(changes.length, 2)
|
||
assert.deepEqual(changes.map((c) => `${c.kind}:${c.code}`), ['update:DE', 'delete:IT'])
|
||
})
|
||
|
||
test('test_task_074_query_asin_detail_dependency_failure_returns_actionable_message', () => {
|
||
// 依赖失败/保存走 adapter:PUT/DELETE /query-asins/{id}/countries/{country},页面不内联。
|
||
const api = readSource('src/pages/asin/query-asin-detail-api.ts')
|
||
assert.match(api, /query-asins/)
|
||
assert.match(api, /countries/)
|
||
assert.match(api, /http\.put/)
|
||
assert.match(api, /http\.delete/)
|
||
assert.match(api, /updateQueryAsinCountryAsin|saveQueryAsinCountry/)
|
||
assert.match(api, /deleteQueryAsinCountryAsin/)
|
||
const mod = readSource('src/pages/asin/query-asin-detail-model.ts')
|
||
assert.equal(/axios|http\./.test(mod), false, '详情抽屉模型保持纯逻辑')
|
||
})
|