62bf4f005d
invalid-asin-form-model.ts 纯模型:createEmptyInvalidAsinForm/invalidAsinFormFromItem 回填、 validateInvalidAsinForm 镜像后端(ASIN 必填<=128/品牌<=128/manual 必选分组)、toCreate 请求(camel)、 toUpdate 请求(自动导入默认不迁组);invalid-asin-api.ts 增 createInvalidAsin POST 与 updateInvalidAsin PUT /api/admin/invalid-asin-data。8 用例全过,507 单测 + build 绿。
80 lines
3.6 KiB
TypeScript
80 lines
3.6 KiB
TypeScript
import test from 'node:test'
|
||
import assert from 'node:assert/strict'
|
||
import { readSource } from './helpers.ts'
|
||
import {
|
||
createEmptyInvalidAsinForm,
|
||
invalidAsinFormFromItem,
|
||
toInvalidAsinCreateRequest,
|
||
toInvalidAsinUpdateRequest,
|
||
validateInvalidAsinForm,
|
||
} from '../src/pages/invalidasin/invalid-asin-form-model.ts'
|
||
import { toInvalidAsinItem } from '../src/pages/invalidasin/invalid-asin-model.ts'
|
||
|
||
test('test_task_069_brand_db_form_normal_primary_path', () => {
|
||
// 正常主路径:手动新增校验通过并序列化 create 请求(含分组)。
|
||
const form = { ...createEmptyInvalidAsinForm(), dataValue: 'B0ABC', brand: '苹果', groupId: 3 }
|
||
const result = validateInvalidAsinForm(form, { requireGroup: true })
|
||
assert.equal(result.valid, true)
|
||
const req = toInvalidAsinCreateRequest(form)
|
||
assert.equal(req.dataValue, 'B0ABC')
|
||
assert.equal(req.groupId, 3)
|
||
})
|
||
|
||
test('test_task_069_brand_db_form_normal_variant_input', () => {
|
||
// 正常变体:回填 AUTO 记录更新请求不含分组(自动导入不迁组)。
|
||
const item = toInvalidAsinItem({ id: 5, dataValue: 'X', brand: 'b', recordSource: 'AUTO', groupId: 1 })!
|
||
const form = invalidAsinFormFromItem(item)
|
||
assert.equal(form.dataValue, 'X')
|
||
assert.equal(form.brand, 'b')
|
||
const req = toInvalidAsinUpdateRequest(form)
|
||
assert.equal('groupId' in req, false)
|
||
})
|
||
|
||
test('test_task_069_brand_db_form_normal_repeated_operation_is_idempotent', () => {
|
||
// 正常重复:工厂与序列化稳定、不改输入。
|
||
assert.deepEqual(createEmptyInvalidAsinForm(), createEmptyInvalidAsinForm())
|
||
const form = { dataValue: 'A', brand: '', groupId: 1 }
|
||
assert.deepEqual(toInvalidAsinCreateRequest(form), toInvalidAsinCreateRequest(form))
|
||
})
|
||
|
||
test('test_task_069_brand_db_form_boundary_empty_input', () => {
|
||
// 边界空值:空表单缺 ASIN/分组给出可读错误。
|
||
const result = validateInvalidAsinForm(createEmptyInvalidAsinForm(), { requireGroup: true })
|
||
assert.equal(result.valid, false)
|
||
assert.ok(result.errors.dataValue)
|
||
assert.ok(result.errors.groupId)
|
||
})
|
||
|
||
test('test_task_069_brand_db_form_boundary_single_item', () => {
|
||
// 边界单元素:brand 可空通过校验。
|
||
const result = validateInvalidAsinForm({ ...createEmptyInvalidAsinForm(), dataValue: 'B', groupId: 1 }, { requireGroup: true })
|
||
assert.equal(result.valid, true)
|
||
})
|
||
|
||
test('test_task_069_brand_db_form_boundary_limit_or_missing_field', () => {
|
||
// 边界上限:ASIN/品牌超 128 拒绝并提示;数据两侧去空格。
|
||
const long = 'x'.repeat(129)
|
||
const result = validateInvalidAsinForm(
|
||
{ ...createEmptyInvalidAsinForm(), dataValue: ` ${long} `, brand: long, groupId: 1 },
|
||
{ requireGroup: true },
|
||
)
|
||
assert.equal(result.valid, false)
|
||
assert.ok(result.errors.dataValue)
|
||
assert.ok(result.errors.brand)
|
||
})
|
||
|
||
test('test_task_069_brand_db_form_invalid_input_rejected', () => {
|
||
// 异常输入:手动来源缺少分组被拒;update 请求缺 ASIN 时校验拦截。
|
||
assert.equal(validateInvalidAsinForm({ ...createEmptyInvalidAsinForm(), dataValue: 'ok' }, { requireGroup: true }).valid, false)
|
||
})
|
||
|
||
test('test_task_069_brand_db_form_dependency_failure_returns_actionable_message', () => {
|
||
// 依赖失败/表单提交走 adapter:POST/PUT /invalid-asin-data;表单模型纯逻辑不带 http。
|
||
const api = readSource('src/pages/invalidasin/invalid-asin-api.ts')
|
||
assert.match(api, /createInvalidAsin|saveInvalidAsin/)
|
||
assert.match(api, /updateInvalidAsin/)
|
||
assert.match(api, /invalid-asin-data/)
|
||
const mod = readSource('src/pages/invalidasin/invalid-asin-form-model.ts')
|
||
assert.equal(/axios|http\.|vue/.test(mod), false, '品牌数据库表单模型保持纯逻辑')
|
||
})
|