190 lines
7.0 KiB
Ruby
190 lines
7.0 KiB
Ruby
require 'rails_helper'
|
|
|
|
RSpec.describe ConfiguracaoNotificacao do
|
|
# Preenchimento mínimo para os toggles passarem nas validações condicionais.
|
|
def config_smtp(extras = {})
|
|
described_class.new({
|
|
smtp_ativo: true, smtp_address: 'smtp.gmail.com', smtp_port: 587,
|
|
smtp_username: 'sistema@reem.com.br', smtp_password: 'segredo123'
|
|
}.merge(extras))
|
|
end
|
|
|
|
def config_whats(extras = {})
|
|
described_class.new({
|
|
whatsapp_ativo: true, twilio_account_sid: 'AC123',
|
|
twilio_auth_token: 'tok123', twilio_from: '+14155238886'
|
|
}.merge(extras))
|
|
end
|
|
|
|
describe '.instancia' do
|
|
it 'devolve sempre a mesma linha' do
|
|
primeira = described_class.instancia
|
|
expect(described_class.instancia.id).to eq(primeira.id)
|
|
expect(described_class.count).to eq(1)
|
|
end
|
|
end
|
|
|
|
describe '.normalizar_telefone' do
|
|
{
|
|
'11 920051157' => '+5511920051157',
|
|
'(11) 92005-1157' => '+5511920051157',
|
|
'011 92005-1157' => '+5511920051157',
|
|
'+55 11 92005-1157' => '+5511920051157',
|
|
'whatsapp:+5511920051157' => '+5511920051157',
|
|
'1132224444' => '+551132224444',
|
|
# DDD 55 (Santa Maria/RS): o "55" inicial é o DDD, não o país.
|
|
'55991234567' => '+5555991234567'
|
|
}.each do |entrada, esperado|
|
|
it "converte #{entrada.inspect} em #{esperado}" do
|
|
expect(described_class.normalizar_telefone(entrada)).to eq(esperado)
|
|
end
|
|
end
|
|
|
|
it 'devolve nil para vazio ou número curto demais' do
|
|
expect(described_class.normalizar_telefone(nil)).to be_nil
|
|
expect(described_class.normalizar_telefone('')).to be_nil
|
|
expect(described_class.normalizar_telefone('920051157')).to be_nil
|
|
end
|
|
end
|
|
|
|
describe '.canal' do
|
|
it 'prefixa whatsapp:' do
|
|
expect(described_class.canal('11 920051157')).to eq('whatsapp:+5511920051157')
|
|
end
|
|
|
|
it 'devolve nil quando o número é inválido' do
|
|
expect(described_class.canal('abc')).to be_nil
|
|
end
|
|
end
|
|
|
|
describe 'atributos cifrados' do
|
|
# A tabela é singleton (índice único em singleton_guard) e a migration já
|
|
# cria a linha — por isso os testes que persistem usam `.instancia`.
|
|
it 'grava criptografado e lê de volta em claro' do
|
|
cfg = described_class.instancia
|
|
cfg.update!(smtp_password: 'minha-senha', twilio_auth_token: 'meu-token')
|
|
cfg.reload
|
|
|
|
expect(cfg.smtp_password).to eq('minha-senha')
|
|
expect(cfg.twilio_auth_token).to eq('meu-token')
|
|
expect(cfg.smtp_password_cifrado).to be_present
|
|
expect(cfg.smtp_password_cifrado).not_to include('minha-senha')
|
|
end
|
|
|
|
it 'não marca o registro como alterado ao reatribuir o mesmo valor' do
|
|
cfg = described_class.instancia
|
|
cfg.update!(smtp_password: 'igual')
|
|
|
|
cfg.smtp_password = 'igual'
|
|
expect(cfg).not_to be_changed
|
|
end
|
|
|
|
it 'trata segredo ilegível como ausente, sem estourar' do
|
|
cfg = described_class.instancia
|
|
cfg.update!(smtp_password: 'x')
|
|
cfg.update_column(:smtp_password_cifrado, 'lixo-que-nao-decifra')
|
|
|
|
expect(cfg.reload.smtp_password).to be_nil
|
|
expect(cfg.smtp_password?).to be(false)
|
|
end
|
|
end
|
|
|
|
describe 'validações' do
|
|
it 'não exige SMTP enquanto o envio de e-mail está desligado' do
|
|
expect(described_class.new).to be_valid
|
|
end
|
|
|
|
it 'exige servidor, usuário e senha quando o e-mail é ativado' do
|
|
cfg = described_class.new(smtp_ativo: true)
|
|
expect(cfg).not_to be_valid
|
|
expect(cfg.errors.attribute_names).to include(:smtp_address, :smtp_username, :smtp_password)
|
|
end
|
|
|
|
it 'exige credenciais do Twilio quando o WhatsApp é ativado' do
|
|
cfg = described_class.new(whatsapp_ativo: true)
|
|
expect(cfg).not_to be_valid
|
|
expect(cfg.errors.attribute_names).to include(:twilio_account_sid, :twilio_auth_token, :twilio_from)
|
|
end
|
|
|
|
it 'rejeita e-mail administrativo malformado' do
|
|
expect(described_class.new(email_admin: 'sem-arroba')).not_to be_valid
|
|
end
|
|
|
|
it 'rejeita porta fora da faixa' do
|
|
expect(described_class.new(smtp_port: 0)).not_to be_valid
|
|
expect(described_class.new(smtp_port: 70_000)).not_to be_valid
|
|
end
|
|
|
|
it 'normaliza os telefones antes de salvar' do
|
|
cfg = described_class.instancia
|
|
cfg.update!(whatsapp_admin: '(11) 92005-1157')
|
|
expect(cfg.reload.whatsapp_admin).to eq('+5511920051157')
|
|
end
|
|
end
|
|
|
|
describe '#smtp_settings' do
|
|
it 'devolve nil quando não está pronto, para o .env continuar valendo' do
|
|
expect(described_class.new.smtp_settings).to be_nil
|
|
expect(config_smtp(smtp_ativo: false).smtp_settings).to be_nil
|
|
end
|
|
|
|
it 'usa STARTTLS na 587' do
|
|
settings = config_smtp.smtp_settings
|
|
expect(settings[:enable_starttls_auto]).to be(true)
|
|
expect(settings).not_to have_key(:ssl)
|
|
expect(settings[:password]).to eq('segredo123')
|
|
expect(settings[:authentication]).to eq(:plain)
|
|
end
|
|
|
|
it 'usa SSL direto na 465' do
|
|
settings = config_smtp(smtp_port: 465).smtp_settings
|
|
expect(settings[:ssl]).to be(true)
|
|
expect(settings).not_to have_key(:enable_starttls_auto)
|
|
end
|
|
|
|
it 'deriva o domínio do remetente quando não informado' do
|
|
expect(config_smtp.smtp_settings[:domain]).to eq('reem.com.br')
|
|
end
|
|
end
|
|
|
|
describe '#remetente_formatado' do
|
|
it 'monta "Nome" <email> quando há nome' do
|
|
cfg = config_smtp(remetente_email: 'nao-responda@reem.com.br', remetente_nome: 'Reem Transporte')
|
|
expect(cfg.remetente_formatado).to eq('"Reem Transporte" <nao-responda@reem.com.br>')
|
|
end
|
|
|
|
it 'cai no usuário do SMTP quando não há remetente próprio' do
|
|
expect(config_smtp.remetente_formatado).to eq('sistema@reem.com.br')
|
|
end
|
|
end
|
|
|
|
describe '#credenciais_whatsapp' do
|
|
it 'usa o banco quando está completo' do
|
|
creds = config_whats.credenciais_whatsapp
|
|
expect(creds[:sid]).to eq('AC123')
|
|
expect(creds[:from]).to eq('whatsapp:+14155238886')
|
|
end
|
|
|
|
it 'cai no .env quando o banco está incompleto' do
|
|
allow(ENV).to receive(:[]).and_call_original
|
|
allow(ENV).to receive(:[]).with('TWILIO_ACCOUNT_SID').and_return('AC_env')
|
|
allow(ENV).to receive(:[]).with('TWILIO_AUTH_TOKEN').and_return('tok_env')
|
|
allow(ENV).to receive(:[]).with('TWILIO_WHATSAPP_FROM').and_return('+14155238886')
|
|
|
|
expect(described_class.new.credenciais_whatsapp[:sid]).to eq('AC_env')
|
|
end
|
|
|
|
it 'não mistura SID do banco com token do .env' do
|
|
allow(ENV).to receive(:[]).and_call_original
|
|
allow(ENV).to receive(:[]).with('TWILIO_ACCOUNT_SID').and_return('AC_env')
|
|
allow(ENV).to receive(:[]).with('TWILIO_AUTH_TOKEN').and_return('tok_env')
|
|
allow(ENV).to receive(:[]).with('TWILIO_WHATSAPP_FROM').and_return('+14155238886')
|
|
|
|
# SID no banco mas sem token → whatsapp_pronto? é false → vai inteiro pro ENV
|
|
cfg = described_class.new(whatsapp_ativo: true, twilio_account_sid: 'AC_banco')
|
|
expect(cfg.credenciais_whatsapp[:sid]).to eq('AC_env')
|
|
expect(cfg.credenciais_whatsapp[:token]).to eq('tok_env')
|
|
end
|
|
end
|
|
end
|