cangku/backend/test/presaleTaskService.test.js

90 lines
3.0 KiB
JavaScript

'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const {
listPresaleTasks,
_test: { getActionType, normalizeInput, normalizeRunDate },
} = require('../src/services/presaleTaskService');
test('presale task input requires a DingTalk user and validates run date', () => {
assert.throws(() => normalizeInput({}), /dingtalkUserId|dingtalkUserName/);
assert.throws(() => normalizeRunDate('2026-02-30'), /有效日期/);
assert.equal(normalizeRunDate('2026-07-29'), '2026-07-29');
});
test('presale action type distinguishes create, extend, cancel and no action', () => {
assert.equal(getActionType({ notice_remark: '新增预售' }), 'CREATE_PRESALE');
assert.equal(getActionType({ notice_remark: '延长预售' }), 'EXTEND_PRESALE');
assert.equal(getActionType({ presale_policy: '取消预售' }), 'CANCEL_PRESALE');
assert.equal(getActionType({ notice_remark: '2026-07-23 已通知' }), 'NO_ACTION');
});
test('presale task query returns the standard paged external API payload', async () => {
const calls = [];
const query = async (sql, params) => {
calls.push({ sql, params });
if (sql.includes('MAX(run_date)')) return [{ run_date: '2026-07-29' }];
if (sql.includes('COUNT(*) AS total_rows')) {
return [{
total_rows: 16,
product_count: 9,
actionable_rows: 8,
create_presale_rows: 1,
extend_presale_rows: 5,
cancel_presale_rows: 2,
no_action_rows: 8,
}];
}
return [{
run_date: '2026-07-29',
notice_time: '2026-07-29 11:08:52',
notice_remark: '延长预售',
ider: '香茗',
ider_userid: 'ding-user-id',
shopname: '拼多多-亿家木家具旗舰店',
shop_i_id: '972878614785',
shop_sku_id: '1926066156590',
sku_id: 'SZ015911N851V01',
presale_policy: '预售',
presale_deadline: '2026-08-01 00:00:00',
}];
};
const result = await listPresaleTasks(
{ dingtalkUserName: '香茗', pageSize: 20 },
{ query }
);
assert.equal(result.runDate, '2026-07-29');
assert.deepEqual(result.recipient, {
dingtalkUserId: 'ding-user-id',
dingtalkUserName: '香茗',
});
assert.equal(result.summary.totalRows, 16);
assert.equal(result.summary.actionableRows, 8);
assert.equal(result.pagination.totalPages, 1);
assert.equal(result.items[0].actionType, 'EXTEND_PRESALE');
assert.equal(result.items[0].requiresAction, true);
assert.equal(calls.length, 3);
assert.equal(calls[0].params.dingtalkUserName, '香茗');
assert.equal(calls[2].params.pageSize, 20);
});
test('actionableOnly is applied to both summary and item queries', async () => {
const calls = [];
const query = async (sql) => {
calls.push(sql);
if (sql.includes('COUNT(*) AS total_rows')) return [{ total_rows: 0 }];
return [];
};
await listPresaleTasks(
{ dingtalkUserId: 'ding-user-id', runDate: '2026-07-29', actionableOnly: true },
{ query }
);
assert.equal(calls.length, 2);
assert.ok(calls.every((sql) => sql.includes('notice_remark IN')));
});