From 86008934963bb4e01e023fab67da608e52d01dec Mon Sep 17 00:00:00 2001 From: Gustavo Date: Sat, 1 Aug 2026 10:29:19 -0300 Subject: [PATCH] Add deterministic variant selection and message rendering --- src/outreach/campaign-messages.mjs | 14 ++++++++++++++ tests/campaign-messages.test.mjs | 27 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 src/outreach/campaign-messages.mjs create mode 100644 tests/campaign-messages.test.mjs diff --git a/src/outreach/campaign-messages.mjs b/src/outreach/campaign-messages.mjs new file mode 100644 index 0000000..a77c5b0 --- /dev/null +++ b/src/outreach/campaign-messages.mjs @@ -0,0 +1,14 @@ +import { renderTemplate } from './templates.mjs'; + +// Distribuicao deterministica por lead_id % variantes.length: o mesmo lead +// sempre cai na mesma variante mesmo que a fila seja regenerada depois, sem +// precisar guardar nenhum estado extra so pra isso. +export function variantForLead(variants, leadId) { + if (!variants.length) throw new Error('campanha sem variantes ativas'); + const index = Number(leadId) % variants.length; + return variants[index]; +} + +export function renderCampaignMessage(variant, lead) { + return renderTemplate(variant.mensagem, lead); +} diff --git a/tests/campaign-messages.test.mjs b/tests/campaign-messages.test.mjs new file mode 100644 index 0000000..fad8e65 --- /dev/null +++ b/tests/campaign-messages.test.mjs @@ -0,0 +1,27 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { variantForLead, renderCampaignMessage } from '../src/outreach/campaign-messages.mjs'; + +const variants = [{ id: 1, code: 'A', mensagem: 'Ola A' }, { id: 2, code: 'B', mensagem: 'Ola B' }, { id: 3, code: 'C', mensagem: 'Ola C' }]; + +test('variantForLead e deterministico (mesmo lead sempre cai na mesma variante)', () => { + const primeira = variantForLead(variants, 42); + const segunda = variantForLead(variants, 42); + assert.equal(primeira.code, segunda.code); +}); + +test('variantForLead distribui entre variantes diferentes conforme o id', () => { + assert.equal(variantForLead(variants, 0).code, 'A'); + assert.equal(variantForLead(variants, 1).code, 'B'); + assert.equal(variantForLead(variants, 2).code, 'C'); + assert.equal(variantForLead(variants, 3).code, 'A'); +}); + +test('variantForLead lanca erro sem variantes ativas', () => { + assert.throws(() => variantForLead([], 1), /sem variantes/); +}); + +test('renderCampaignMessage substitui variaveis do lead', () => { + const texto = renderCampaignMessage({ mensagem: 'Ola {empresa}, sobre {produto}' }, { empresa: 'Oficina do Ze', produto: 'ERP' }); + assert.equal(texto, 'Ola Oficina do Ze, sobre ERP'); +});