Implantação da geração de mensagem de forma livre e mudança na engine de mensagem
This commit is contained in:
59
spec/jobs/detectar_mudancas_operacao_job_spec.rb
Normal file
59
spec/jobs/detectar_mudancas_operacao_job_spec.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe DetectarMudancasOperacaoJob do
|
||||
let(:tabela) { 'gade_entregas_teste' }
|
||||
|
||||
before do
|
||||
create(:evento_notificacao, gatilho: 'operacao_alterada', chave: 'operacao_alterada')
|
||||
allow(Operacao).to receive(:nomes_validos).and_return([tabela])
|
||||
allow(Operacao).to receive(:label).with(tabela).and_return('TESTE')
|
||||
allow(Notificacao::Gatilhos).to receive(:operacao_alterada)
|
||||
end
|
||||
|
||||
def com_numeros(total:, entregues:, nao_entregues:, pendentes:)
|
||||
allow(Analytics::OperacaoMetricas).to receive(:new).and_return(
|
||||
instance_double(Analytics::OperacaoMetricas, total: total, sucesso: entregues,
|
||||
recusas: nao_entregues, pendentes: pendentes)
|
||||
)
|
||||
end
|
||||
|
||||
# Sem retrato anterior toda operação pareceria "nova", e o primeiro deploy
|
||||
# dispararia uma mensagem por operação cadastrada.
|
||||
it 'primeira execução só grava o retrato, sem avisar' do
|
||||
com_numeros(total: 100, entregues: 90, nao_entregues: 8, pendentes: 2)
|
||||
|
||||
expect { described_class.perform_now }.to change(OperacaoSnapshot, :count).by(1)
|
||||
expect(Notificacao::Gatilhos).not_to have_received(:operacao_alterada)
|
||||
end
|
||||
|
||||
it 'não avisa quando nada mudou' do
|
||||
com_numeros(total: 100, entregues: 90, nao_entregues: 8, pendentes: 2)
|
||||
described_class.perform_now
|
||||
|
||||
described_class.perform_now
|
||||
|
||||
expect(Notificacao::Gatilhos).not_to have_received(:operacao_alterada)
|
||||
end
|
||||
|
||||
it 'descreve o que mudou entre os dois retratos' do
|
||||
com_numeros(total: 100, entregues: 90, nao_entregues: 8, pendentes: 2)
|
||||
described_class.perform_now
|
||||
|
||||
com_numeros(total: 103, entregues: 92, nao_entregues: 8, pendentes: 3)
|
||||
described_class.perform_now
|
||||
|
||||
expect(Notificacao::Gatilhos).to have_received(:operacao_alterada) do |args|
|
||||
expect(args[:operacao]).to eq('TESTE')
|
||||
expect(args[:o_que_mudou]).to include('3 notas na operação a mais')
|
||||
expect(args[:o_que_mudou]).to include('2 entregues a mais')
|
||||
end
|
||||
expect(OperacaoSnapshot.find_by(tabela: tabela).total_notas).to eq(103)
|
||||
end
|
||||
|
||||
it 'não varre nada quando nenhum evento usa esse gatilho' do
|
||||
EventoNotificacao.where(gatilho: 'operacao_alterada').destroy_all
|
||||
expect(Analytics::OperacaoMetricas).not_to receive(:new)
|
||||
|
||||
described_class.perform_now
|
||||
end
|
||||
end
|
||||
72
spec/jobs/disparar_eventos_agendados_job_spec.rb
Normal file
72
spec/jobs/disparar_eventos_agendados_job_spec.rb
Normal file
@@ -0,0 +1,72 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe DispararEventosAgendadosJob do
|
||||
let!(:evento) do
|
||||
create(:evento_notificacao, gatilho: 'agendado', frequencia: 'diaria', hora: 8, ativo: true)
|
||||
end
|
||||
let(:agora) { Time.zone.local(2026, 8, 24, 9, 0) }
|
||||
|
||||
let(:resumo) do
|
||||
instance_double(Analytics::ResumoOperacao, vazio?: false,
|
||||
numeros: { 'entregues' => '10', 'recusas' => '1', 'pendentes' => '0',
|
||||
'retentativas' => '0', 'fora_operacao' => '0' })
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Analytics::ResumoOperacao).to receive(:new).and_return(resumo)
|
||||
allow(Notificacao::Despachante).to receive(:disparar)
|
||||
end
|
||||
|
||||
it 'dispara o evento vencido e marca o disparo' do
|
||||
described_class.perform_now(agora)
|
||||
|
||||
expect(Notificacao::Despachante).to have_received(:disparar)
|
||||
expect(evento.reload.ultimo_disparo_em).to be_present
|
||||
end
|
||||
|
||||
# `vencido?` depende de ultimo_disparo_em; sem gravar, a varredura horária
|
||||
# mandaria a mesma mensagem a cada hora até o dia virar.
|
||||
it 'não repete no mesmo dia' do
|
||||
described_class.perform_now(agora)
|
||||
described_class.perform_now(agora + 1.hour)
|
||||
|
||||
expect(Notificacao::Despachante).to have_received(:disparar).once
|
||||
end
|
||||
|
||||
it 'não dispara antes da hora configurada' do
|
||||
described_class.perform_now(Time.zone.local(2026, 8, 24, 7, 0))
|
||||
expect(Notificacao::Despachante).not_to have_received(:disparar)
|
||||
end
|
||||
|
||||
it 'ignora evento desativado' do
|
||||
evento.update!(ativo: false)
|
||||
described_class.perform_now(agora)
|
||||
expect(Notificacao::Despachante).not_to have_received(:disparar)
|
||||
end
|
||||
|
||||
# Resumo zerado só treinaria o leitor a ignorar a mensagem — mas precisa
|
||||
# marcar como disparado, senão tenta de hora em hora.
|
||||
it 'período sem movimento: não envia, mas marca o disparo' do
|
||||
allow(resumo).to receive(:vazio?).and_return(true)
|
||||
|
||||
described_class.perform_now(agora)
|
||||
|
||||
expect(Notificacao::Despachante).not_to have_received(:disparar)
|
||||
expect(evento.reload.ultimo_disparo_em).to be_present
|
||||
end
|
||||
|
||||
describe 'janela do resumo (recortes FECHADOS, para o número não mudar depois de enviado)' do
|
||||
it 'diária cobre o dia anterior' do
|
||||
described_class.perform_now(agora)
|
||||
expect(Analytics::ResumoOperacao).to have_received(:new)
|
||||
.with(inicio: Date.new(2026, 8, 23), fim: Date.new(2026, 8, 23))
|
||||
end
|
||||
|
||||
it 'semanal cobre os 7 dias anteriores' do
|
||||
evento.update!(frequencia: 'semanal', dia_semana: agora.to_date.wday)
|
||||
described_class.perform_now(agora)
|
||||
expect(Analytics::ResumoOperacao).to have_received(:new)
|
||||
.with(inicio: Date.new(2026, 8, 17), fim: Date.new(2026, 8, 23))
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user