Files
huangzd1997 ad6658e490 task-74(ASIN 数据中心): 实现查询 ASIN 详情抽屉
抽屉副标题/5 国家草稿与变更差异(空值→删除)纯逻辑, 保存走 PUT/DELETE
/api/admin/query-asins/{id}/countries/{country}, 9 个契约测试。
2026-09-05 16:09:31 +08:00

107 lines
4.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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', () => {
// 依赖失败/保存走 adapterPUT/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, '详情抽屉模型保持纯逻辑')
})