cangku/backend/test/planningSelectionFissionWorkflowState.test.js

121 lines
4.1 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const {
_test: {
COMPANY_TASK_WORKFLOW_STEPS,
buildPreferredMarketReferenceSeed,
buildSelectionFissionPlanListSummary,
buildWorkflowSummary,
getSelectionFissionItemNodeState,
isRetryableAlibaba1688ImageSearchFailure,
},
} = require('../src/services/planningSelectionFissionService');
test('1688 sourcing keeps the selected market result as the later image reference', () => {
const seeded = buildPreferredMarketReferenceSeed({
marketItemId: '897171229570',
channelName: '淘宝',
title: '市场参考商品',
imageUrl: 'https://example.com/reference.jpg',
detailUrl: 'https://item.taobao.com/item.htm?id=897171229570',
});
assert.equal(seeded.candidate.marketItemId, '897171229570');
assert.equal(seeded.candidate.imageUrl, 'https://example.com/reference.jpg');
assert.equal(seeded.batch.source, 'alibaba_1688_sourcing_context');
assert.deepEqual(seeded.batch.candidates, [seeded.candidate]);
});
test('1688 sourcing does not seed an incomplete market image reference', () => {
assert.deepEqual(buildPreferredMarketReferenceSeed({ marketItemId: '897171229570' }), {
candidate: null,
batch: null,
});
});
test('1688 sourcing retries only transient upstream failures', () => {
assert.equal(isRetryableAlibaba1688ImageSearchFailure({
status: 502,
message: '后端服务调用失败',
}), true);
assert.equal(isRetryableAlibaba1688ImageSearchFailure({
response: { status: 504, data: { message: 'Gateway Timeout' } },
}), true);
assert.equal(isRetryableAlibaba1688ImageSearchFailure({
status: 502,
message: 'AccessKey已被禁用',
}), false);
assert.equal(isRetryableAlibaba1688ImageSearchFailure({
response: { status: 400, data: { message: '参数错误' } },
}), false);
});
test('company product workflow restores pricing before image generation', () => {
assert.deepEqual(COMPANY_TASK_WORKFLOW_STEPS, [8, 3, 4, 6, 7]);
const task = {
selectedSpuCode: 'SPU-1',
selectedMainSkuImageUrl: 'https://example.com/sku.jpg',
whiteBackgroundAssets: { rows: [{ skuCode: 'SKU-1' }] },
skuSnapshot: { rows: [{ skuCode: 'SKU-1' }] },
skuSceneImages: {},
pricingRows: [],
activityPricingRows: [],
};
assert.equal(getSelectionFissionItemNodeState(task).step, 8);
task.pricingRows = [{ skuCode: 'SKU-1' }];
task.activityPricingRows = [{ skuCode: 'SKU-1' }];
task.pricingTableSavedAt = '2026-08-20T00:00:00.000Z';
assert.equal(getSelectionFissionItemNodeState(task).step, 3);
});
test('selection plan list summary excludes heavy workflow payloads', () => {
const summary = buildSelectionFissionPlanListSummary({
id: 7,
sourceItems: [{ id: 11, sourceItemId: 11, marketItemId: 'm-1', workflowStatus: 'running' }],
listingTasks: [{ id: 12, selectedSpuCode: 'SPU-1', listingStatus: 'draft' }],
items: [{ id: 12, pricingRows: Array.from({ length: 100 }, () => ({ skuCode: 'sku' })) }],
});
assert.equal(summary.detailLoaded, false);
assert.equal(summary.items.length, 0);
assert.deepEqual(summary.sourceItems[0], {
id: 11,
sourceItemId: 11,
slotNo: undefined,
marketItemId: 'm-1',
channelName: undefined,
title: undefined,
mainImageUrl: undefined,
workflowStep: undefined,
workflowStatus: 'running',
workflowErrorMessage: undefined,
});
assert.equal(summary.listingTasks[0].selectedSpuCode, 'SPU-1');
assert.equal(summary.listingTasks[0].pricingRows, undefined);
});
test('workflow summary exposes a failed child node immediately', () => {
const summary = buildWorkflowSummary({
workflowStatus: 'waiting',
workflowStep: 2,
workflowProgress: 20,
items: [{
id: 101,
sourceItemId: 101,
slotNo: 1,
variantNo: 0,
selectedSpuCode: '',
workflowStatus: 'failed',
workflowStep: 2,
workflowErrorMessage: '公司 SPU 匹配服务不可用',
}],
});
assert.equal(summary.status, 'failed');
assert.equal(summary.currentStep, 2);
assert.equal(summary.errorMessage, '公司 SPU 匹配服务不可用');
assert.equal(summary.requiresUser, false);
});