Files
huangzd1997 61b2d7152d task-115(任务与重复分析中心): 实现重复检查总览指标
新增 duplicate-model.ts(总览/店铺分布/明细项/出现记录 snake 解析) 与
duplicate-api.ts(fetchDuplicateOverview GET /duplicate-check-overview)。

TDD: task-115.test.ts 8 用例先 RED 后 GREEN。
2026-09-05 17:23:12 +08:00

90 lines
3.7 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 { parseDuplicateOverview, parseDuplicateShop } from '../src/pages/tasks/duplicate-model.ts'
test('test_task_115_duplicate_overview_normal_primary_path', () => {
// 正常主路径:撞款总览(snake summary + shops)解析为类型化指标。
const overview = parseDuplicateOverview({
success: true,
data: {
pending: false,
scanned_at: '2026-01-02 10:00:00',
summary: {
shop_count: 8,
asin_total: 1200,
record_total: 3400,
duplicate_asin_total: 45,
duplicate_shop_count: 6,
site_count: 5,
asin_per_shop: 150,
source: 'Excel',
},
shops: [
{ shop_name: 'BlueWave', group_name: '华东组', country_codes: ['DE', 'UK'], asin_count: 30, record_count: 90 },
],
},
})
assert.equal(overview.pending, false)
assert.equal(overview.summary!.asinTotal, 1200)
assert.equal(overview.summary!.duplicateAsinTotal, 45)
assert.equal(overview.summary!.duplicateShopCount, 6)
assert.equal(overview.summary!.siteCount, 5)
assert.equal(overview.shops.length, 1)
assert.equal(overview.shops[0].shopName, 'BlueWave')
assert.deepEqual(overview.shops[0].countryCodes, ['DE', 'UK'])
})
test('test_task_115_duplicate_overview_normal_variant_input', () => {
// 正常变体:无扫描结果 pending 空态。
const overview = parseDuplicateOverview({ data: { pending: true, scanned_at: '', summary: {}, shops: [] } })
assert.equal(overview.pending, true)
assert.equal(overview.summary, null)
assert.deepEqual(overview.shops, [])
})
test('test_task_115_duplicate_overview_repeated_is_idempotent', () => {
// 正常重复:解析稳定、不改输入。
const payload = { data: { pending: false, summary: { asin_total: 3 }, shops: [] } }
assert.deepEqual(parseDuplicateOverview(payload), parseDuplicateOverview(payload))
})
test('test_task_115_duplicate_overview_boundary_empty_input', () => {
// 边界空值:空负载回默认空态。
const overview = parseDuplicateOverview({})
assert.equal(overview.pending, true)
assert.equal(overview.summary, null)
assert.deepEqual(overview.shops, [])
})
test('test_task_115_duplicate_overview_boundary_single_item', () => {
// 边界单元素:单店铺分布解析完整。
const shop = parseDuplicateShop({ shop_name: 'S', group_name: 'G', country_codes: ['DE'], asin_count: 1, record_count: 2 })
assert.ok(shop)
assert.equal(shop.asinCount, 1)
})
test('test_task_115_duplicate_overview_boundary_limit_or_missing_field', () => {
// 边界上限/缺字段:缺省数值回 0;缺国家回空数组。
const shop = parseDuplicateShop({ shop_name: 'S' })
assert.ok(shop)
assert.equal(shop.asinCount, 0)
assert.deepEqual(shop.countryCodes, [])
assert.equal(shop.groupName, '')
})
test('test_task_115_duplicate_overview_invalid_input_rejected', () => {
// 异常输入:success=false 抛后端 message;非对象店铺行忽略。
assert.throws(() => parseDuplicateOverview({ success: false, message: '无权访问重复检查' }), /无权访问/)
assert.equal(parseDuplicateShop('garbage'), null)
})
test('test_task_115_duplicate_overview_dependency_failure_returns_actionable_message', () => {
// 依赖失败/加载走 adapterGET /api/admin/shop-data-crawl/duplicate-check-overview。
const api = readSource('src/pages/tasks/duplicate-api.ts')
assert.match(api, /\/duplicate-check-overview/)
assert.match(api, /fetchDuplicateOverview/)
const model = readSource('src/pages/tasks/duplicate-model.ts')
assert.equal(/axios|http\./.test(model), false, '总览解析保持纯逻辑')
})