chore: import maquina-comercial-pessoal history via subtree
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> git-subtree-dir: maquina-comercial-pessoal git-subtree-mainline:f5af038e19git-subtree-split:a9ef4d776d
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { generateDailySchedule } from '../src/outreach/campaign-schedule.mjs';
|
||||
|
||||
const WINDOWS = [
|
||||
{ start: '09:30', end: '11:30' },
|
||||
{ start: '14:00', end: '17:00' }
|
||||
];
|
||||
const MIN_MS = 12 * 60 * 1000;
|
||||
const MAX_MS = 25 * 60 * 1000;
|
||||
|
||||
function schedule(overrides = {}) {
|
||||
return generateDailySchedule({
|
||||
date: '2026-07-27',
|
||||
count: 18,
|
||||
windows: WINDOWS,
|
||||
minMs: MIN_MS,
|
||||
maxMs: MAX_MS,
|
||||
hourlyLimit: 4,
|
||||
random: () => 0,
|
||||
...overrides
|
||||
});
|
||||
}
|
||||
|
||||
test('gera somente em dia util e preserva a data civil local', () => {
|
||||
assert.deepEqual(schedule({ date: '2026-07-25' }), []);
|
||||
assert.deepEqual(schedule({ date: '2026-07-26' }), []);
|
||||
|
||||
const slots = schedule({ date: '2026-07-27', count: 2 });
|
||||
assert.equal(slots.length, 2);
|
||||
assert.deepEqual(slots.map((slot) => [
|
||||
slot.getFullYear(), slot.getMonth() + 1, slot.getDate(), slot.getHours(), slot.getMinutes()
|
||||
]), [
|
||||
[2026, 7, 27, 9, 30],
|
||||
[2026, 7, 27, 9, 42]
|
||||
]);
|
||||
});
|
||||
|
||||
test('usa random injetado para espacamento inclusivo entre 12 e 25 minutos', () => {
|
||||
const minimum = schedule({ count: 3, random: () => 0 });
|
||||
assert.deepEqual(minimum.map((slot) => `${slot.getHours()}:${String(slot.getMinutes()).padStart(2, '0')}`), [
|
||||
'9:30', '9:42', '9:54'
|
||||
]);
|
||||
|
||||
const maximum = schedule({ count: 3, random: () => 1 });
|
||||
assert.deepEqual(maximum.map((slot) => `${slot.getHours()}:${String(slot.getMinutes()).padStart(2, '0')}`), [
|
||||
'9:30', '9:55', '10:20'
|
||||
]);
|
||||
});
|
||||
|
||||
test('respeita no maximo quatro slots em qualquer hora rolante, incluindo o limite exato', () => {
|
||||
const slots = schedule({ count: 8, minMs: 1, maxMs: 1 });
|
||||
assert.deepEqual(slots.slice(0, 5).map((slot) => slot.getTime() - slots[0].getTime()), [
|
||||
0, 1, 2, 3, 60 * 60 * 1000
|
||||
]);
|
||||
for (let index = 4; index < slots.length; index += 1) {
|
||||
assert.ok(slots[index].getTime() - slots[index - 4].getTime() >= 60 * 60 * 1000);
|
||||
}
|
||||
});
|
||||
|
||||
test('nao agenda durante almoco, fora das janelas ou em outra data', () => {
|
||||
const slots = schedule({ count: 18 });
|
||||
assert.ok(slots.length > 0);
|
||||
for (const slot of slots) {
|
||||
const minutes = slot.getHours() * 60 + slot.getMinutes();
|
||||
assert.equal(slot.getDate(), 27);
|
||||
assert.ok((minutes >= 570 && minutes <= 690) || (minutes >= 840 && minutes <= 1020));
|
||||
assert.ok(minutes <= 690 || minutes >= 840);
|
||||
}
|
||||
});
|
||||
|
||||
test('limita a 18 e retorna menos quando as janelas nao comportam a quantidade', () => {
|
||||
assert.equal(schedule({ count: 99 }).length, 18);
|
||||
const short = schedule({
|
||||
count: 18,
|
||||
windows: [{ start: '09:30', end: '09:50' }],
|
||||
minMs: 12 * 60 * 1000,
|
||||
maxMs: 12 * 60 * 1000
|
||||
});
|
||||
assert.deepEqual(short.map((slot) => [slot.getHours(), slot.getMinutes()]), [[9, 30], [9, 42]]);
|
||||
});
|
||||
|
||||
test('rejeita parametros inseguros sem produzir datas invalidas', () => {
|
||||
assert.throws(() => schedule({ date: '2026-02-30' }), /data/i);
|
||||
assert.throws(() => schedule({ windows: [{ start: '11:30', end: '09:30' }] }), /janela/i);
|
||||
assert.throws(() => schedule({ random: () => 1.1 }), /random/i);
|
||||
});
|
||||
Reference in New Issue
Block a user