Files
huangzd1997 8c6088bdc9 task-82(店铺中心): 实现店铺密钥列表加载
新增 shop-key-model.ts(ShopKeyPageVo camel 解析、白名单状态归一、snake
兜底) 与 shop-key-api.ts(GET /api/admin/shop-keys 加载适配);纯逻辑解析、
页面不内联请求。

TDD: task-82.test.ts 8 用例先 RED 后 GREEN。
2026-09-05 16:34:26 +08:00

117 lines
4.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 { parseShopKeyPage, toShopKeyItem } from '../src/pages/shop/shop-key-model.ts'
test('test_task_082_shop_key_list_load_normal_primary_path', () => {
// 正常主路径:Java ShopKeyPageVo(camel) 封包解析为前端密钥分页结果。
const page = parseShopKeyPage({
success: true,
data: {
items: [
{
id: 9,
remarkName: '主店',
ziniaoAccountName: 'blue_agent',
ziniaoToken: 'token-secret-001',
ipWhitelistStatus: 'BLOCKED',
ipWhitelistCheckedAt: '2026-02-01T09:00:00',
ipWhitelistMessage: 'IP 不在白名单',
createdAt: '2026-01-01T10:00:00',
updatedAt: '2026-01-02T11:00:00',
},
],
total: 1,
page: 1,
pageSize: 15,
},
})
assert.equal(page.items.length, 1)
const item = page.items[0]
assert.equal(item.id, 9)
assert.equal(item.remarkName, '主店')
assert.equal(item.ziniaoAccountName, 'blue_agent')
assert.equal(item.ziniaoToken, 'token-secret-001')
assert.equal(item.ipWhitelistStatus, 'BLOCKED')
assert.equal(item.ipWhitelistCheckedAt, '2026-02-01T09:00:00')
assert.equal(item.ipWhitelistMessage, 'IP 不在白名单')
assert.equal(item.createdAt, '2026-01-01T10:00:00')
assert.equal(page.total, 1)
assert.equal(page.page, 1)
assert.equal(page.pageSize, 15)
})
test('test_task_082_shop_key_list_load_normal_variant_input', () => {
// 正常变体:已解包 VO 直传;snake 兜底(remark_name);小写状态归一大写。
const page = parseShopKeyPage({
items: [{ id: 12, remark_name: '副店', ziniao_token: 't2', ip_whitelist_status: 'allowed' }],
total: 3,
page: 2,
pageSize: 20,
})
const item = page.items[0]
assert.equal(item.id, 12)
assert.equal(item.remarkName, '副店')
assert.equal(item.ziniaoToken, 't2')
assert.equal(item.ipWhitelistStatus, 'ALLOWED')
assert.equal(item.ipWhitelistCheckedAt, undefined)
assert.equal(item.ipWhitelistMessage, '')
assert.equal(page.page, 2)
assert.equal(page.pageSize, 20)
})
test('test_task_082_shop_key_list_load_repeated_is_idempotent', () => {
// 正常重复:解析同一负载结果稳定、不改输入。
const payload = { data: { items: [{ id: 1, remarkName: 'A', ziniaoToken: 'x' }], total: 1, page: 1, pageSize: 15 } }
assert.deepEqual(parseShopKeyPage(payload), parseShopKeyPage(payload))
assert.equal((payload as { data: { items: unknown[] } }).data.items.length, 1)
})
test('test_task_082_shop_key_list_load_boundary_empty_input', () => {
// 边界空值:空负载回默认分页结果(空列表/total 0/page 1/页大小 15)。
const page = parseShopKeyPage({})
assert.deepEqual(page.items, [])
assert.equal(page.total, 0)
assert.equal(page.page, 1)
assert.equal(page.pageSize, 15)
})
test('test_task_082_shop_key_list_load_boundary_single_item', () => {
// 边界单元素:单条记录;缺 id 的行被过滤。
const page = parseShopKeyPage({
data: { items: [{ id: 7, remarkName: 'Z', ziniaoToken: 'z' }, { remarkName: 'no-id' }], total: 2, page: 1, pageSize: 15 },
})
assert.equal(page.items.length, 1)
assert.equal(page.items[0].id, 7)
})
test('test_task_082_shop_key_list_load_boundary_limit_or_missing_field', () => {
// 边界上限/缺字段:缺省字段回默认值;未知/缺白名单状态回 UNKNOWN;最小行可用。
const minimal = toShopKeyItem({ id: 3 })
assert.ok(minimal)
assert.equal(minimal.id, 3)
assert.equal(minimal.remarkName, '')
assert.equal(minimal.ziniaoToken, '')
assert.equal(minimal.ipWhitelistStatus, 'UNKNOWN')
assert.equal(minimal.createdAt, undefined)
const unknownStatus = toShopKeyItem({ id: 4, ziniaoToken: 't', ipWhitelistStatus: 'WEIRD' })
assert.equal(unknownStatus!.ipWhitelistStatus, 'UNKNOWN')
})
test('test_task_082_shop_key_list_load_invalid_input_rejected', () => {
// 异常输入:success=false 抛后端 message;非对象/非数字 id 行不入列表。
assert.throws(() => parseShopKeyPage({ success: false, message: '无权访问店铺密钥' }), /无权访问/)
assert.equal(toShopKeyItem('garbage'), null)
assert.equal(toShopKeyItem({ remarkName: 'no id' }), null)
})
test('test_task_082_shop_key_list_load_dependency_failure_returns_actionable_message', () => {
// 依赖失败/加载走 adapterGET /api/admin/shop-keys + http.get + 解析,页面不内联。
const api = readSource('src/pages/shop/shop-key-api.ts')
assert.match(api, /\/api\/admin\/shop-keys/)
assert.match(api, /http\.get/)
assert.match(api, /parseShopKeyPage/)
const model = readSource('src/pages/shop/shop-key-model.ts')
assert.equal(/axios|http\./.test(model), false, '店铺密钥列表解析保持纯逻辑')
})