Files
crawler-plugin/admin-frontend-vue/tests/task-75.test.ts
T

178 lines
6.5 KiB
TypeScript
Raw 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 {
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 会把输入值转成 numbernormalizePriceInput 需兼容(修复 "(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<string, unknown>), false)
assert.equal('minimum_price_to' in (params as Record<string, unknown>), 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', () => {
// 依赖失败/加载走 adapterGET /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 列表解析保持纯逻辑')
})