cangku/backend/test/desktopExecutionTaskService.test.js

117 lines
4.0 KiB
JavaScript

const assert = require('node:assert/strict');
const test = require('node:test');
const {
DesktopExecutionTaskError,
buildAutoListingDesktopTaskInputs,
buildTaskCode,
mapTask,
normalizeProgress,
normalizeTaskType,
} = require('../src/services/desktopExecutionTaskService');
test('desktop task types are normalized and unknown executors are rejected', () => {
assert.equal(normalizeTaskType('product-test'), 'product_test');
assert.equal(normalizeTaskType('presale'), 'presale');
assert.throws(
() => normalizeTaskType('unknown-action'),
(error) => error instanceof DesktopExecutionTaskError && error.code === 'DESKTOP_TASK_TYPE_INVALID'
);
});
test('desktop task codes are time ordered and collision resistant', () => {
const code = buildTaskCode(new Date('2026-08-23T08:09:10.000Z'), () => Buffer.from('01020304', 'hex'));
assert.equal(code, 'DT2026082308091001020304');
});
test('desktop task progress derives a bounded percentage', () => {
assert.deepEqual(normalizeProgress({ stage: 'shop', current: 3, total: 4, message: '处理中' }), {
stage: 'shop', current: 3, total: 4, percent: 75, message: '处理中',
});
assert.equal(normalizeProgress({ current: 8, total: 4 }).percent, 100);
assert.equal(normalizeProgress({ percent: -3 }).percent, 0);
});
test('stored task rows expose stable camelCase snapshots', () => {
const task = mapTask({
id: 7,
task_code: 'DT1',
task_type: 'presale',
source_type: 'selection_fission_item',
source_id: '17',
source_code: 'SF-17',
assigned_user_id: 9,
status: 'running',
input_json: '{"runDate":"2026-08-23"}',
progress_current: 2,
progress_total: 5,
progress_percent: 40,
});
assert.equal(task.id, 7);
assert.equal(task.assignedUserId, 9);
assert.equal(task.input.runDate, '2026-08-23');
assert.equal(task.sourceType, 'selection_fission_item');
assert.equal(task.sourceId, '17');
assert.equal(task.sourceCode, 'SF-17');
assert.deepEqual(task.progress, { stage: '', current: 2, total: 5, percent: 40, message: '' });
});
test('automatic listing wrappers preserve the original child task identity and target shop', () => {
const tasks = buildAutoListingDesktopTaskInputs({
id: 3,
schemeCode: 'PLAN-3',
listingShopId: 'shop-9',
listingShopName: '旗舰店',
listingTasks: [
{
id: 17,
taskCode: 'SF-17',
listingStatus: 'pending',
selectedSpuCode: 'SPU001',
selectedSpuName: '桌子',
selectedProductTitle: '实木桌子',
},
{ id: 18, taskCode: 'SF-18', listingStatus: 'listed', listedItemId: 'PDD18', selectedSpuCode: 'SPU002' },
],
}, { id: 9, name: '陆南亭', username: 'ln亭' });
assert.equal(tasks.length, 1);
assert.equal(tasks[0].taskType, 'auto_listing');
assert.equal(tasks[0].sourceId, '17');
assert.equal(tasks[0].sourceCode, 'SF-17');
assert.equal(tasks[0].input.sourceTaskCode, 'SF-17');
assert.equal(tasks[0].targetShopId, 'shop-9');
assert.equal(tasks[0].assignedUserId, 9);
});
test('automatic listing wrappers assign delegated work to the selected user and device', () => {
const tasks = buildAutoListingDesktopTaskInputs({
id: 3,
schemeCode: 'PLAN-3',
listingShopId: 'shop-9',
listingShopName: '旗舰店',
listingShopSnapshot: {
sessionId: '27',
routingMode: 'delegated',
executorUserId: 12,
executorUserName: '同事甲',
executorUsername: 'peer',
executorClientId: 'device-12',
},
listingTasks: [{
id: 17,
taskCode: 'SF-17',
listingStatus: 'pending',
selectedSpuCode: 'SPU001',
selectedProductTitle: '实木桌子',
}],
}, { id: 9, name: '发起人', username: 'requester' });
assert.equal(tasks[0].assignedUserId, 12);
assert.equal(tasks[0].assignedUserName, '同事甲');
assert.equal(tasks[0].input.executorClientId, 'device-12');
assert.equal(tasks[0].input.executorSessionId, '27');
assert.equal(tasks[0].input.routingMode, 'delegated');
assert.equal(tasks[0].input.requestedByUserId, 9);
});