Previously, setCampaignStatus did not set semana_iniciada_em, causing
escalateWeeklyLimits to bail early (if (!campaign.semana_iniciada_em) continue).
Now when a campaign transitions to 'rodando' for the first time, semana_iniciada_em
is set to datetime('now'). Subsequent rodando transitions leave it unchanged
(using COALESCE to preserve first-run timestamp).
Regression tests confirm:
- First transition to 'rodando' stamps semana_iniciada_em
- Subsequent transitions do not reset the timestamp
- resumeCampaign continues to work correctly (pause/resume cycle)
- All 105 tests pass
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
128 lines
5.1 KiB
JavaScript
128 lines
5.1 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { openDb } from '../src/db.mjs';
|
|
import {
|
|
createCampaign, getCampaign, listCampaigns, setCampaignStatus, resumeCampaign,
|
|
escalateWeeklyLimits, isOptedOut, addOptOut, removeOptOut
|
|
} from '../src/outreach/campaign-store.mjs';
|
|
|
|
function campanhaBase(overrides = {}) {
|
|
return {
|
|
nome: 'ERP oficinas',
|
|
produto: 'ERP',
|
|
segmentos: ['oficinas_mecanicas', 'autopecas'],
|
|
variantes: [{ code: 'A', mensagem: 'Ola {empresa}' }, { code: 'B', mensagem: 'Oi {empresa}' }],
|
|
...overrides
|
|
};
|
|
}
|
|
|
|
test('createCampaign grava campanha, segmentos e variantes', () => {
|
|
const db = openDb(':memory:');
|
|
const campanha = createCampaign(db, campanhaBase());
|
|
assert.equal(campanha.status, 'rascunho');
|
|
assert.equal(campanha.produto, 'ERP');
|
|
assert.deepEqual(campanha.segmentos, ['oficinas_mecanicas', 'autopecas']);
|
|
assert.equal(campanha.variants.length, 2);
|
|
assert.equal(campanha.variants[0].code, 'A');
|
|
db.close();
|
|
});
|
|
|
|
test('listCampaigns retorna mais recente primeiro', () => {
|
|
const db = openDb(':memory:');
|
|
createCampaign(db, campanhaBase({ nome: 'Primeira' }));
|
|
createCampaign(db, campanhaBase({ nome: 'Segunda' }));
|
|
const campanhas = listCampaigns(db);
|
|
assert.equal(campanhas.length, 2);
|
|
assert.equal(campanhas[0].nome, 'Segunda');
|
|
db.close();
|
|
});
|
|
|
|
test('setCampaignStatus pausa e resumeCampaign retoma limpando o motivo', () => {
|
|
const db = openDb(':memory:');
|
|
const campanha = createCampaign(db, campanhaBase());
|
|
setCampaignStatus(db, campanha.id, 'rodando');
|
|
const pausada = setCampaignStatus(db, campanha.id, 'pausado', 'high_failure_rate');
|
|
assert.equal(pausada.status, 'pausado');
|
|
assert.equal(pausada.pause_reason, 'high_failure_rate');
|
|
const retomada = resumeCampaign(db, campanha.id);
|
|
assert.equal(retomada.status, 'rodando');
|
|
assert.equal(retomada.pause_reason, null);
|
|
db.close();
|
|
});
|
|
|
|
test('setCampaignStatus rodando stamps semana_iniciada_em on first transition', () => {
|
|
const db = openDb(':memory:');
|
|
const campanha = createCampaign(db, campanhaBase());
|
|
assert.equal(campanha.semana_iniciada_em, null);
|
|
|
|
const rodando = setCampaignStatus(db, campanha.id, 'rodando');
|
|
assert.notEqual(rodando.semana_iniciada_em, null, 'semana_iniciada_em should be set on first rodando transition');
|
|
db.close();
|
|
});
|
|
|
|
test('setCampaignStatus rodando does not reset already-set semana_iniciada_em', () => {
|
|
const db = openDb(':memory:');
|
|
const campanha = createCampaign(db, campanhaBase());
|
|
|
|
// Set to rodando first time, which stamps semana_iniciada_em
|
|
setCampaignStatus(db, campanha.id, 'rodando');
|
|
|
|
// Manually set to a known past value via raw SQL
|
|
const knownTime = '2026-07-15 10:00:00';
|
|
db.prepare(`UPDATE outreach_campaigns SET semana_iniciada_em = ? WHERE id = ?`).run(knownTime, campanha.id);
|
|
|
|
// Call setCampaignStatus again while already 'rodando'
|
|
const unchanged = setCampaignStatus(db, campanha.id, 'rodando');
|
|
|
|
// Verify semana_iniciada_em was not changed
|
|
assert.equal(unchanged.semana_iniciada_em, knownTime, 'semana_iniciada_em should not be reset on subsequent rodando calls');
|
|
db.close();
|
|
});
|
|
|
|
test('resumeCampaign nao faz nada se a campanha nao estiver pausada', () => {
|
|
const db = openDb(':memory:');
|
|
const campanha = createCampaign(db, campanhaBase());
|
|
const resultado = resumeCampaign(db, campanha.id);
|
|
assert.equal(resultado.status, 'rascunho');
|
|
db.close();
|
|
});
|
|
|
|
test('escalateWeeklyLimits dobra o limite apos 7 dias rodando, respeitando o teto', () => {
|
|
const db = openDb(':memory:');
|
|
const campanha = createCampaign(db, campanhaBase({ limiteDiarioInicial: 10, limiteDiarioTeto: 15 }));
|
|
setCampaignStatus(db, campanha.id, 'rodando');
|
|
db.prepare(`UPDATE outreach_campaigns SET semana_iniciada_em = datetime('now', '-8 days') WHERE id = ?`).run(campanha.id);
|
|
|
|
const escaladas = escalateWeeklyLimits(db);
|
|
assert.equal(escaladas, 1);
|
|
const atualizada = getCampaign(db, campanha.id);
|
|
assert.equal(atualizada.limite_diario_atual, 15); // dobraria pra 20, mas o teto e 15
|
|
db.close();
|
|
});
|
|
|
|
test('escalateWeeklyLimits nao avanca campanha pausada nem antes de 7 dias', () => {
|
|
const db = openDb(':memory:');
|
|
const rodando = createCampaign(db, campanhaBase({ nome: 'Rodando ha pouco' }));
|
|
setCampaignStatus(db, rodando.id, 'rodando');
|
|
db.prepare(`UPDATE outreach_campaigns SET semana_iniciada_em = datetime('now', '-2 days') WHERE id = ?`).run(rodando.id);
|
|
|
|
const pausada = createCampaign(db, campanhaBase({ nome: 'Pausada' }));
|
|
setCampaignStatus(db, pausada.id, 'rodando');
|
|
setCampaignStatus(db, pausada.id, 'pausado', 'manual');
|
|
db.prepare(`UPDATE outreach_campaigns SET semana_iniciada_em = datetime('now', '-10 days') WHERE id = ?`).run(pausada.id);
|
|
|
|
const escaladas = escalateWeeklyLimits(db);
|
|
assert.equal(escaladas, 0);
|
|
db.close();
|
|
});
|
|
|
|
test('opt-out: addOptOut bloqueia, removeOptOut libera', () => {
|
|
const db = openDb(':memory:');
|
|
assert.equal(isOptedOut(db, '5511999990001'), false);
|
|
addOptOut(db, '5511999990001', 'pediu pra parar');
|
|
assert.equal(isOptedOut(db, '5511999990001'), true);
|
|
removeOptOut(db, '5511999990001');
|
|
assert.equal(isOptedOut(db, '5511999990001'), false);
|
|
db.close();
|
|
});
|