cangku/backend/test/pddOpenPlatformDraftPublisher.test.js

256 lines
8.3 KiB
JavaScript

'use strict';
const assert = require('node:assert/strict');
const test = require('node:test');
const fs = require('node:fs');
const path = require('node:path');
const {
buildSkuDraftRows,
getSourceDimensions,
normalizeDraftResponse,
publishPddGoodsDraft,
validateGoodsProperties,
validateSpecMappings,
} = require('../src/services/pddOpenPlatformDraftPublisher');
function createTwoDimensionItem() {
return {
id: 7,
skuSceneImages: { selectedSkuCodes: ['SOURCE-RED-80', 'SOURCE-BLUE-100'] },
metadata: {
sourceRow: {
product: {
skuDimensions: [
{ name: '颜色', values: ['红色', '蓝色', '未选颜色'] },
{ name: '尺寸', values: ['80cm', '100cm'] },
],
},
},
},
skuSnapshot: {
rows: [
{
skuCode: 'SOURCE-RED-80',
raw: { specs: [{ name: '颜色', value: '红色' }, { name: '尺寸', value: '80cm' }] },
},
{
skuCode: 'SOURCE-BLUE-100',
raw: { specs: [{ name: '颜色', value: '蓝色' }, { name: '尺寸', value: '100cm' }] },
},
],
},
pricingRows: [
{
skuCode: 'SOURCE-RED-80',
internalProductCode: 'COMPANY-RED-80',
generatedImageUrl: 'https://img.example/red.jpg',
finalPrice: 109,
groupPrice: 99,
},
{
skuCode: 'SOURCE-BLUE-100',
internalProductCode: 'COMPANY-BLUE-100',
generatedImageUrl: 'https://img.example/blue.jpg',
finalPrice: 119,
groupPrice: 109,
},
],
activityPricingRows: [
{ skuCode: 'SOURCE-RED-80', finalGroupPrice: 95 },
{ skuCode: 'SOURCE-BLUE-100', finalGroupPrice: 105 },
],
};
}
test('selected 1688 SKU rows retain two-dimensional coordinates', () => {
const item = createTwoDimensionItem();
const dimensions = getSourceDimensions(item);
assert.deepEqual(dimensions, [
{ name: '颜色', values: ['红色', '蓝色'] },
{ name: '尺寸', values: ['80cm', '100cm'] },
]);
const mappings = [
{ sourceDimensionName: '颜色', parentSpecId: 1215 },
{ sourceDimensionName: '尺寸', parentSpecId: 1216 },
];
const mappingByName = validateSpecMappings(dimensions, mappings, [
{ parentSpecId: 1215, name: '颜色' },
{ parentSpecId: 1216, name: '尺寸' },
]);
const specIds = new Map([
['颜色\u0000红色', 101],
['颜色\u0000蓝色', 102],
['尺寸\u000080cm', 201],
['尺寸\u0000100cm', 202],
]);
const images = new Map([
['SOURCE-RED-80', 'https://img.example/red.jpg'],
['SOURCE-BLUE-100', 'https://img.example/blue.jpg'],
]);
const rows = buildSkuDraftRows(item, {
quantity: 20,
weight: 12_000,
limitQuantity: 999,
}, dimensions, mappingByName, specIds, images);
assert.equal(rows.length, 2);
assert.deepEqual(rows[0].spec_id_list, [101, 201]);
assert.deepEqual(rows[1].spec_id_list, [102, 202]);
assert.equal(rows[0].multi_price, 9500);
assert.equal(rows[0].price, 10900);
assert.equal(rows[0].out_sku_sn, 'COMPANY-RED-80');
assert.equal(rows[1].quantity, 20);
assert.equal(rows[1].weight, 12_000);
});
test('dynamic category properties enforce required enum values', () => {
const rule = {
properties: [{
refPid: 310,
name: '品牌',
required: true,
chooseMaxNum: 1,
values: [{ vid: 8825, value: '卓禾' }],
}],
};
assert.throws(
() => validateGoodsProperties([], rule),
(error) => error.code === 'PDD_DRAFT_PROPERTY_REQUIRED'
);
assert.throws(
() => validateGoodsProperties([{ ref_pid: 310, vid: 9999, value: '无效' }], rule),
(error) => error.code === 'PDD_DRAFT_PROPERTY_INVALID'
);
assert.doesNotThrow(
() => validateGoodsProperties([{ ref_pid: 310, vid: 8825, value: '卓禾' }], rule)
);
});
test('draft response requires both goods ID and commit ID', () => {
assert.deepEqual(normalizeDraftResponse({
goods_update_response: {
goods_id: 989294315918,
goods_commit_id: 198258372338,
},
}), {
goodsId: '989294315918',
goodsCommitId: '198258372338',
});
assert.throws(
() => normalizeDraftResponse({ goods_update_response: { goods_id: 1 } }),
(error) => error.code === 'PDD_DRAFT_RESULT_UNKNOWN' && error.resultUnknown === true
);
});
test('1688 keeps the legacy server publisher available but uses the shared desktop queue', () => {
const serviceFile = path.join(__dirname, '../src/services/planningSelectionFissionService.js');
const source = fs.readFileSync(serviceFile, 'utf8');
assert.doesNotMatch(source, /if \(plan\.workflowProfile === ALIBABA_1688_PENDING_PROFILE\) \{\s*return saveAlibaba1688PddDrafts/);
assert.match(source, /async function saveAlibaba1688PddDrafts/);
assert.match(source, /const clientId = normalizeText\(input\.clientId/);
assert.match(source, /const supportedShopIds = new Set/);
assert.match(source, /publishMode: 'pdd_open_platform_draft'/);
});
test('complete publisher writes one draft commit and never calls submit or goods.add', async () => {
const calls = [];
let savedPayload;
const client = {
getAuthorizedCategories: async (parentCatId) => {
calls.push(['categories', parentCatId]);
return {
goods_auth_cats_get_response: {
goods_cats_list: Number(parentCatId) === 0
? [{ cat_id: 9324, cat_name: '住宅家具', leaf: false }]
: [{ cat_id: 10607, cat_name: '普通餐桌', leaf: true }],
},
};
},
getCategoryRule: async () => ({
cat_rule_get_response: {
goods_properties_rule: {
properties: [{
ref_pid: 310,
name: '品牌',
required: true,
values: [{ vid: 8825, value: '卓禾' }],
}],
},
},
}),
getCategorySpecs: async () => ({
goods_spec_get_response: {
goods_spec_list: [
{ parent_spec_id: 1215, parent_spec_name: '颜色' },
{ parent_spec_id: 1216, parent_spec_name: '尺寸' },
],
},
}),
getLogisticsTemplates: async () => ({
goods_logistics_template_get_response: {
logistics_template_list: [{
template_id: 303351846671360,
template_name: '内地包邮默认模板',
cost_type: 0,
}],
},
}),
getOrCreateSpecId: async (parentSpecId, specName) => {
calls.push(['spec', parentSpecId, specName]);
const ids = { '红色': 101, '蓝色': 102, '80cm': 201, '100cm': 202 };
return { goods_spec_id_get_response: { spec_id: ids[specName] } };
},
saveGoodsDraft: async (payload) => {
calls.push(['pdd.goods.edit.goods.commit']);
savedPayload = payload;
return {
goods_update_response: {
goods_id: 989294315918,
goods_commit_id: 198258372338,
},
};
},
};
const item = createTwoDimensionItem();
item.marketItemId = '1073252781818';
item.selectedProductTitle = '现代简约实木餐桌';
item.title = item.selectedProductTitle;
item.metadata.sourceRow.product.mainImages = ['https://img.example/main.jpg'];
item.metadata.sourceRow.product.detailImages = ['https://img.example/detail.jpg'];
const result = await publishPddGoodsDraft(
{ id: 9, schemeCode: 'FB-TEST' },
item,
{
catId: 10607,
categoryPath: [9324, 10607],
costTemplateId: 303351846671360,
goodsProperties: [{ refPid: 310, vid: 8825, value: '卓禾' }],
specMappings: [
{ sourceDimensionName: '颜色', parentSpecId: 1215 },
{ sourceDimensionName: '尺寸', parentSpecId: 1216 },
],
quantity: 20,
weight: 12_000,
twoPiecesDiscount: 95,
},
{ shopId: 'shop-1', shopName: '卓禾旗舰店' },
{
client,
uploadImage: async (url, kind) => `https://pdd.example/${kind}/${encodeURIComponent(url)}.jpg`,
}
);
assert.equal(result.goodsId, '989294315918');
assert.equal(result.goodsCommitId, '198258372338');
assert.equal(savedPayload.cat_id, 10607);
assert.equal(savedPayload.sku_list.length, 2);
assert.equal(savedPayload.carousel_gallery.length, 1);
assert.equal(savedPayload.detail_gallery.length, 1);
assert.deepEqual(calls.filter((row) => row[0] === 'pdd.goods.edit.goods.commit'), [
['pdd.goods.edit.goods.commit'],
]);
assert.equal(calls.some((row) => row[0] === 'pdd.goods.add'), false);
assert.equal(calls.some((row) => row[0] === 'pdd.goods.submit.goods.commit'), false);
});