feat(ai-edit): 开发 AI 填报功能
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test } from 'node:test';
|
||||
import { makeModel, validateCopy, validatePackage } from '../src/product-ai.ts';
|
||||
|
||||
test('同一商品模型只由类目和稳定商品 ID 确定', () => {
|
||||
const category = { name: '手办', path: '玩具 / 手办' };
|
||||
const first = makeModel(category, 'abcdef12-0000-4000-8000-000000000000');
|
||||
const second = makeModel(category, 'abcdef12-0000-4000-8000-000000000000');
|
||||
assert.equal(first, second);
|
||||
assert.match(first, /^FIG-MIX-[A-F0-9]{5}$/);
|
||||
assert.ok(first.length <= 32);
|
||||
assert.equal((first.match(/-/g) ?? []).length, 2);
|
||||
});
|
||||
|
||||
test('文案只保留成对且含俄文字符的字段', () => {
|
||||
assert.deepEqual(
|
||||
validateCopy({
|
||||
title: { ru: 'Фигурка героя', zh: '角色手办' },
|
||||
tags: [
|
||||
{ ru: 'Коллекционная', zh: '收藏' },
|
||||
{ ru: 'invalid', zh: '无效' },
|
||||
],
|
||||
description: { ru: 'Сделано из золота', zh: '' },
|
||||
}),
|
||||
{
|
||||
title: { ru: 'Фигурка героя', zh: '角色手办' },
|
||||
tags: [{ ru: 'Коллекционная', zh: '收藏' }],
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('俄文标题、标签和描述中的汉字不会进入回填结果', () => {
|
||||
assert.deepEqual(
|
||||
validateCopy({
|
||||
title: { ru: 'Бейсболка ANTA/安踏', zh: '安踏棒球帽' },
|
||||
tags: [
|
||||
{ ru: 'Спортивная кепка', zh: '运动帽' },
|
||||
{ ru: 'Цвет 运动红-1', zh: '运动红-1' },
|
||||
],
|
||||
description: {
|
||||
ru: 'Бейсболка унисекс. Размер: 均码.',
|
||||
zh: '中性棒球帽。尺码:均码。',
|
||||
},
|
||||
}),
|
||||
{ tags: [{ ru: 'Спортивная кепка', zh: '运动帽' }] },
|
||||
);
|
||||
});
|
||||
|
||||
test('单行多句产品描述会保留为易读的段落', () => {
|
||||
const copy = validateCopy({
|
||||
description: {
|
||||
ru: 'Коллекционная фигурка из ПВХ. Размер упаковки: 180 × 120 × 250 мм.',
|
||||
zh: 'PVC 收藏手办。包装尺寸为 180 × 120 × 250 mm。',
|
||||
},
|
||||
});
|
||||
assert.equal(
|
||||
copy.description?.ru,
|
||||
'Коллекционная фигурка из ПВХ.\n\nРазмер упаковки: 180 × 120 × 250 мм.',
|
||||
);
|
||||
assert.equal(
|
||||
copy.description?.zh,
|
||||
'PVC 收藏手办。\n\n包装尺寸为 180 × 120 × 250 mm。',
|
||||
);
|
||||
});
|
||||
|
||||
test('中文对照中的通用段落标题会规范为中文', () => {
|
||||
const copy = validateCopy({
|
||||
description: {
|
||||
ru: 'Фигурка.\n\nХарактеристики:\n• Материал: ПВХ',
|
||||
zh: '收藏手办。\n\nХарактеристики:\n• 材质:PVC',
|
||||
},
|
||||
});
|
||||
assert.match(copy.description?.zh ?? '', /\n\n产品信息:\n• 材质:PVC$/);
|
||||
});
|
||||
|
||||
test('包装建议必须有采集证据,且尺寸重量为有效正数', () => {
|
||||
const source = {
|
||||
description: '包装尺寸 10 × 20 × 30 mm,包装重量 400 g',
|
||||
attributes: [],
|
||||
};
|
||||
const proposal = {
|
||||
length_mm: '10',
|
||||
width_mm: '20',
|
||||
height_mm: '30',
|
||||
shipping_weight_g: '400',
|
||||
evidence: '包装尺寸 10 × 20 × 30 mm,包装重量 400 g',
|
||||
};
|
||||
assert.equal(validatePackage(proposal, source)?.shipping_weight_g, '400');
|
||||
assert.equal(
|
||||
validatePackage({ ...proposal, evidence: '模型凭空猜测' }, source),
|
||||
null,
|
||||
);
|
||||
assert.equal(
|
||||
validatePackage({ ...proposal, shipping_weight_g: '0' }, source),
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
test('包装字段名称可作为 1688 分离尺寸和重量证据', () => {
|
||||
const source = {
|
||||
description: null,
|
||||
attributes: [
|
||||
{ key: 'size', name: '包装尺寸', value: '10 × 20 × 30 mm' },
|
||||
{ key: 'weight', name: '包装重量', value: '400 g' },
|
||||
],
|
||||
};
|
||||
const proposal = {
|
||||
length_mm: '10',
|
||||
width_mm: '20',
|
||||
height_mm: '30',
|
||||
shipping_weight_g: '400',
|
||||
evidence: '10 × 20 × 30 mm\n400 g',
|
||||
};
|
||||
assert.equal(validatePackage(proposal, source)?.height_mm, '30');
|
||||
});
|
||||
Reference in New Issue
Block a user