Implantação da geração de mensagem de forma livre e mudança na engine de mensagem

This commit is contained in:
2026-08-24 17:32:16 -03:00
parent 94bbe7556f
commit 88f19dd8f5
77 changed files with 4650 additions and 25 deletions

View File

@@ -0,0 +1,134 @@
require 'rails_helper'
RSpec.describe Notificacao::Despachante do
let(:evento) { create(:evento_notificacao) }
let(:diretoria) { create(:grupo_contato) }
let(:config) { ConfiguracaoNotificacao.instancia }
before do
config.update_columns(whatsapp_ativo: true, whatsapp_provedor: 'baileys',
email_notificacoes_ativo: true, whatsapp_intervalo_segundos: 0)
# Nunca tocar a ponte de verdade no teste.
allow(Notificacao::Whatsapp).to receive(:enviar)
.and_return(Notificacao::ClienteWhatsapp::Resposta.new(ok: true))
allow(ConfiguracaoNotificacao).to receive(:instancia).and_return(config)
end
def despachar(envolvido: nil, dados: {})
described_class.new(evento.reload, dados: dados, assunto: 'Assunto',
corpo: 'Corpo', envolvido: envolvido).executar
end
it 'envia para os contatos dos grupos assinantes e registra cada envio' do
contato = create(:contato, grupo_contato: diretoria, telefone: '11 92005-1157', email: 'dir@reem.com')
create(:grupo_evento_assinatura, grupo_contato: diretoria, evento_notificacao: evento)
expect { despachar }.to change(NotificacaoEnvio, :count).by(2) # whatsapp + email
expect(Notificacao::Whatsapp).to have_received(:enviar)
.with(hash_including(para: contato.telefone))
expect(NotificacaoEnvio.where(canal: 'whatsapp').first).to be_enviado
end
# A mesma pessoa pode ser contato de um grupo E a envolvida no fato — sem
# dedup ela receberia a mensagem duas vezes.
it 'não manda duas vezes para o mesmo número' do
create(:contato, grupo_contato: diretoria, telefone: '11 92005-1157', email: nil)
create(:grupo_evento_assinatura, grupo_contato: diretoria, evento_notificacao: evento, canal: 'whatsapp')
motorista = create(:motorista, telefone: '(11) 92005-1157')
despachar(envolvido: motorista)
expect(NotificacaoEnvio.where(canal: 'whatsapp').count).to eq(1)
end
it 'inclui o envolvido que não é contato de nenhum grupo' do
create(:grupo_evento_assinatura, grupo_contato: diretoria, evento_notificacao: evento)
motorista = create(:motorista, telefone: '(11) 98888-7777')
despachar(envolvido: motorista)
expect(NotificacaoEnvio.where(canal: 'whatsapp').pluck(:destino)).to eq(['+5511988887777'])
end
it 'não avisa o envolvido quando o evento diz para não avisar' do
evento.update!(notificar_envolvido: false)
motorista = create(:motorista, telefone: '(11) 98888-7777')
despachar(envolvido: motorista)
expect(NotificacaoEnvio.where(canal: 'whatsapp')).to be_empty
end
it 'registra a falha em vez de levantar — envio não pode travar um fechamento' do
create(:contato, grupo_contato: diretoria, telefone: '11 92005-1157', email: nil)
create(:grupo_evento_assinatura, grupo_contato: diretoria, evento_notificacao: evento, canal: 'whatsapp')
allow(Notificacao::Whatsapp).to receive(:enviar)
.and_return(Notificacao::ClienteWhatsapp::Resposta.new(ok: false, erro: 'whatsapp desconectado'))
expect { despachar }.not_to raise_error
envio = NotificacaoEnvio.last
expect(envio).to be_falhou
expect(envio.erro).to include('desconectado')
end
# O editor de blocos vence o texto padrão — e o fallback existe para que ligar
# o editor não apague as notificações dos eventos que já funcionavam.
describe 'template de blocos' do
before do
create(:contato, grupo_contato: diretoria, telefone: '11 92005-1157', email: 'dir@reem.com')
create(:grupo_evento_assinatura, grupo_contato: diretoria, evento_notificacao: evento)
end
it 'sem template, usa o corpo passado pelo chamador' do
despachar
expect(NotificacaoEnvio.find_by(canal: 'whatsapp').corpo).to eq('Corpo')
end
it 'com template, o corpo sai renderizado por canal' do
MensagemTemplate.create!(evento_notificacao: evento, canal: 'whatsapp', ativo: true,
blocos: [{ 'tipo' => 'texto', 'texto' => 'Oi {{contato}}, {{valor}}' }])
MensagemTemplate.create!(evento_notificacao: evento, canal: 'email', ativo: true,
assunto: 'Fechamento de {{contato}}',
blocos: [{ 'tipo' => 'texto', 'texto' => 'Corpo do e-mail' }])
despachar(dados: { 'valor' => 'R$ 10,00' })
zap = NotificacaoEnvio.find_by(canal: 'whatsapp')
expect(zap.corpo).to include('R$ 10,00')
email = NotificacaoEnvio.find_by(canal: 'email')
expect(email.corpo).to include('<p') # HTML montado
expect(email.assunto).to include('Fechamento')
end
# {{contato}} é o primeiro nome de QUEM RECEBE: um render compartilhado
# mandaria o nome da primeira pessoa para todo mundo.
it 'renderiza {{contato}} por destinatário' do
create(:contato, grupo_contato: diretoria, nome: 'Ana Paula', telefone: '11 93005-1157', email: nil)
MensagemTemplate.create!(evento_notificacao: evento, canal: 'whatsapp', ativo: true,
blocos: [{ 'tipo' => 'texto', 'texto' => 'Olá {{contato}}' }])
despachar
corpos = NotificacaoEnvio.where(canal: 'whatsapp').pluck(:corpo)
expect(corpos).to include(a_string_including('Ana'))
expect(corpos.uniq.size).to eq(corpos.size)
end
it 'template ativo mas vazio não substitui o texto padrão' do
MensagemTemplate.create!(evento_notificacao: evento, canal: 'whatsapp', ativo: true, blocos: [])
despachar
expect(NotificacaoEnvio.find_by(canal: 'whatsapp').corpo).to eq('Corpo')
end
end
it 'não envia nada quando o canal está desligado na configuração' do
create(:contato, grupo_contato: diretoria, telefone: '11 92005-1157', email: 'dir@reem.com')
create(:grupo_evento_assinatura, grupo_contato: diretoria, evento_notificacao: evento)
config.update_columns(whatsapp_ativo: false, email_notificacoes_ativo: false)
expect { despachar }.not_to change(NotificacaoEnvio, :count)
end
end