import test from 'node:test' import assert from 'node:assert/strict' import { readSource } from './helpers.ts' import { parseSkipPricePage, toSkipPriceItem, skipPriceAsin, skipPriceMinimum, type SkipPriceItem, } from '../src/pages/asin/skip-price-model.ts' import { ASIN_COUNTRY_CODES, asinCountryLabel } from '../src/pages/asin/asin-country.ts' import { normalizePriceInput, skipPriceFilterActive, toSkipPriceParams, toSkipPriceQuery, type SkipPriceFilterState, } from '../src/pages/asin/skip-price-filter.ts' test('test_task_075_skip_price_list_normal_primary_path', () => { // 正常主路径:SkipPriceAsinPageVo(camel) 宽行(每店铺 5 国家 ASIN+最低价)解析。 const page = parseSkipPricePage({ success: true, data: { items: [ { id: 11, groupId: 3, groupName: '华东组', shopName: 'BlueWave', asinDe: 'B0DE001', minimumPriceDe: 12.5, asinUk: 'B0UK001', minimumPriceUk: 8, asinFr: '', minimumPriceFr: null, asinIt: '', minimumPriceIt: null, asinEs: '', minimumPriceEs: null, }, ], total: 1, page: 1, pageSize: 15, }, }) assert.equal(page.items.length, 1) const item = page.items[0] assert.equal(item.shopName, 'BlueWave') assert.equal(item.asinDe, 'B0DE001') assert.equal(item.minimumPriceDe, 12.5) assert.equal(item.minimumPriceUk, 8) assert.equal(item.minimumPriceFr, null) assert.equal(page.total, 1) assert.equal(page.pageSize, 15) }) test('test_task_075_skip_price_list_normal_variant_input', () => { // 正常变体:蛇形字段兜底;缺国家价格留空;价格支持数字字符串。 const item = toSkipPriceItem({ id: 12, shopName: 'RedSun', asin_de: 'B0DE2', minimum_price_de: '9.99', })! assert.equal(item.asinDe, 'B0DE2') assert.equal(item.minimumPriceDe, 9.99) assert.equal(item.groupId, null) assert.equal(item.groupName, '') assert.equal(item.minimumPriceUk, null) }) test('test_task_075_skip_price_list_normal_repeated_operation_is_idempotent', () => { // 正常重复:解析不改输入、结果稳定。 const payload = { data: { items: [{ id: 13, shopName: 'A', asinDe: 'X', minimumPriceDe: 1 }], total: 1, page: 1, pageSize: 15 }, } assert.deepEqual(parseSkipPricePage(payload), parseSkipPricePage(payload)) }) test('test_task_075_skip_price_list_boundary_empty_input', () => { // 边界空值:空负载回默认分页结果。 const page = parseSkipPricePage({}) assert.deepEqual(page.items, []) assert.equal(page.total, 0) assert.equal(page.page, 1) assert.equal(page.pageSize, 10) }) test('test_task_075_skip_price_list_boundary_single_item', () => { // 边界单元素:缺 id 行被过滤;国家访问器/标签齐全。 const page = parseSkipPricePage({ data: { items: [{ id: 7, shopName: 'Z' }, { shopName: 'no-id' }], total: 2, page: 1, pageSize: 15 }, }) assert.equal(page.items.length, 1) const item: SkipPriceItem = page.items[0] assert.equal(skipPriceAsin(item, 'DE'), '') assert.equal(skipPriceMinimum(item, 'DE'), null) assert.equal(ASIN_COUNTRY_CODES.length, 5) assert.equal(asinCountryLabel('DE'), '德国') assert.equal(asinCountryLabel('XX'), 'XX') }) test('test_task_075_skip_price_list_boundary_limit_or_missing_field', () => { // 边界上限/缺字段:页码下限 1、页大小上限 100 对齐后端;空格/非法分组/国家不下发。 const state: SkipPriceFilterState = { groupId: 0, shopName: ' ', asin: '', country: 'XX', minimumPriceFrom: '', minimumPriceTo: '' } const query = toSkipPriceQuery(toSkipPriceParams(state, 0, 999)) assert.equal(query.page, 1) assert.equal(query.page_size, 100) assert.equal('group_id' in query, false) assert.equal('shop_name' in query, false) assert.equal('country' in query, false) assert.equal(skipPriceFilterActive(state), false) }) test('test_task_075_skip_price_filter_normal_primary_and_price', () => { // 正常主路径:分组/店铺/ASIN/国家 + 价格上下限以 snake 参数下发;空值不下发。 const state: SkipPriceFilterState = { groupId: 5, shopName: ' 蓝店 ', asin: 'B0X', country: 'de', minimumPriceFrom: ' 1.5 ', minimumPriceTo: '99', } const query = toSkipPriceQuery(toSkipPriceParams(state, 3, 25)) assert.deepEqual(query, { page: 3, page_size: 25, group_id: 5, shop_name: '蓝店', asin: 'B0X', country: 'DE', minimum_price_from: 1.5, minimum_price_to: 99, }) }) test('test_task_075_skip_price_filter_number_input_compat', () => { // 原生 number input v-model 会把输入值转成 number;normalizePriceInput 需兼容(修复 "(value||'').trim is not a function")。 const state: SkipPriceFilterState = { groupId: null, shopName: '', asin: '', country: '', minimumPriceFrom: 12.34, minimumPriceTo: 56.78 } const query = toSkipPriceQuery(toSkipPriceParams(state, 1, 15)) assert.equal(query.minimum_price_from, 12.34) assert.equal(query.minimum_price_to, 56.78) assert.equal(normalizePriceInput(0), 0) assert.equal(normalizePriceInput(-5), null) assert.equal(normalizePriceInput(null as unknown as string), null) }) test('test_task_075_skip_price_filter_invalid_input_rejected', () => { // 异常输入:非法价格/负数/非数值价格丢弃;success=false 抛 message;垃圾行不入列表。 const state: SkipPriceFilterState = { groupId: null, shopName: '', asin: '', country: '', minimumPriceFrom: '-1', minimumPriceTo: 'abc', } const params = toSkipPriceParams(state, 1, 15) assert.equal('minimum_price_from' in (params as Record), false) assert.equal('minimum_price_to' in (params as Record), false) assert.throws(() => parseSkipPricePage({ success: false, message: '无权访问跳过跟价 ASIN' }), /无权/) assert.equal(toSkipPriceItem('garbage'), null) assert.equal(toSkipPriceItem({ shopName: 'no id' }), null) }) test('test_task_075_skip_price_list_dependency_failure_returns_actionable_message', () => { // 依赖失败/加载走 adapter:GET /api/admin/skip-price-asins + http.get + 解析。 const api = readSource('src/pages/asin/skip-price-api.ts') assert.match(api, /skip-price-asins/) assert.match(api, /http\.get/) assert.match(api, /parseSkipPricePage/) const model = readSource('src/pages/asin/skip-price-model.ts') assert.equal(/axios|http\./.test(model), false, '最低价 ASIN 列表解析保持纯逻辑') })