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,73 @@
require 'rails_helper'
RSpec.describe Notificacao::Renderizador do
let(:dados) { { 'contato' => 'Carlos', 'valor' => 'R$ 5.060,00', 'entregas' => '280' } }
def render(blocos) = described_class.new(blocos, dados)
describe 'as duas saídas do mesmo template' do
let(:blocos) do
[
{ 'tipo' => 'cabecalho', 'titulo' => 'Pagamento fechado', 'subtitulo' => 'UBS Norte' },
{ 'tipo' => 'texto', 'texto' => 'Olá {{contato}}!' },
{ 'tipo' => 'tabela', 'linhas' => [{ 'rotulo' => 'Entregas', 'valor' => '{{entregas}}' },
{ 'rotulo' => 'Valor', 'valor' => '{{valor}}' }] },
{ 'tipo' => 'botao', 'rotulo' => 'Ver extrato', 'url' => 'https://app.reem.com.br/motorista' }
]
end
it 'monta o texto do WhatsApp com negrito e bullets' do
texto = render(blocos).texto
expect(texto).to include('*Pagamento fechado*')
expect(texto).to include('Olá Carlos!')
expect(texto).to include('• Entregas: 280')
expect(texto).to include('Ver extrato: https://app.reem.com.br/motorista')
end
it 'monta o HTML do e-mail com estilo inline' do
html = render(blocos).html
expect(html).to include('<h1')
expect(html).to include('style=') # cliente de e-mail não lê CSS externo
expect(html).to include('Olá Carlos!')
expect(html).to include('R$ 5.060,00')
expect(html).to include('<a href="https://app.reem.com.br/motorista"')
end
end
it 'variável sem valor vira vazio, não fica "{{cru}}" na mensagem' do
texto = render([{ 'tipo' => 'texto', 'texto' => 'Oi {{inexistente}}!' }]).texto
expect(texto).to eq('Oi !')
end
# O corpo é digitado numa tela e o preview usa este mesmo renderizador — um
# escape faltando atingiria primeiro o próprio admin.
it 'escapa HTML do texto digitado e do valor da variável' do
r = described_class.new(
[{ 'tipo' => 'texto', 'texto' => '<script>alert(1)</script> {{contato}}' }],
{ 'contato' => '<img src=x onerror=alert(2)>' }
)
html = r.html
expect(html).not_to include('<script>')
expect(html).not_to include('<img src=x')
expect(html).to include('&lt;script&gt;')
end
# href montado na tela com `javascript:` seria clique armado dentro do e-mail.
it 'ignora botão cuja URL não é http(s)' do
html = render([{ 'tipo' => 'botao', 'rotulo' => 'Clique', 'url' => 'javascript:alert(1)' }]).html
expect(html).not_to include('javascript:')
expect(html).not_to include('<a ')
end
it 'descarta bloco de tipo desconhecido' do
r = render([{ 'tipo' => 'malicioso', 'texto' => 'nada' },
{ 'tipo' => 'texto', 'texto' => 'ok' }])
expect(r.texto).to eq('ok')
end
it 'não deixa bloco vazio virar linha em branco na mensagem' do
texto = render([{ 'tipo' => 'texto', 'texto' => '' },
{ 'tipo' => 'texto', 'texto' => 'único' }]).texto
expect(texto).to eq('único')
end
end