require 'rails_helper'
RSpec.describe WebsiteBrandingService do
describe '#perform' do
let(:email) { 'user@example.com' }
let(:url) { 'https://example.com' }
let(:html_body) do
<<~HTML
Acme Corp | HomeFacebookInstagram
HTML
end
before do
stub_request(:get, url).to_return(status: 200, body: html_body, headers: { 'content-type' => 'text/html' })
end
it 'extracts basic brand info' do
result = described_class.new(email).perform
expect(result).to include(domain: 'example.com', title: 'Acme Corp', email: email,
description: nil, slogan: nil, is_nsfw: false, industries: [])
end
it 'extracts colors, logos, and socials' do
result = described_class.new(email).perform
expect(result[:colors]).to eq([{ hex: '#FF5733', name: nil }])
expect(result[:logos].first[:url]).to eq('https://example.com/favicon.ico')
expect(result[:socials].map { |s| s[:type] }).to contain_exactly('facebook', 'instagram', 'whatsapp', 'telegram', 'tiktok')
end
context 'when og:site_name is missing' do
let(:html_body) do
<<~HTML
Mon Entreprise - Bienvenue
HTML
end
it 'falls back to the first segment of the title' do
result = described_class.new(email).perform
expect(result[:title]).to eq('Mon Entreprise')
end
end
context 'when the page fails to load' do
before { stub_request(:get, url).to_return(status: 500, body: '') }
it 'returns nil and sets http_status' do
service = described_class.new(email)
expect(service.perform).to be_nil
expect(service.http_status).to eq(500)
end
end
context 'when a network error occurs' do
before { stub_request(:get, url).to_raise(StandardError.new('connection refused')) }
it 'logs the error and returns nil' do
expect(Rails.logger).to receive(:error).with(/connection refused/)
expect(described_class.new(email).perform).to be_nil
end
end
context 'when WhatsApp link uses api.whatsapp.com format' do
let(:html_body) do
<<~HTML
TestChat
HTML
end
it 'extracts phone from query param' do
result = described_class.new(email).perform
whatsapp = result[:socials].find { |s| s[:type] == 'whatsapp' }
expect(whatsapp[:url]).to eq('https://wa.me/5511999999999')
end
end
context 'when links contain lookalike domains' do
let(:html_body) do
<<~HTML
TestNot FBNot IG
HTML
end
it 'does not match lookalike domains' do
result = described_class.new(email).perform
types = result[:socials].map { |s| s[:type] }
expect(types).not_to include('facebook')
expect(types).not_to include('instagram')
end
end
context 'when favicon uses a relative path without leading slash' do
let(:html_body) do
<<~HTML
Test
HTML
end
it 'resolves the relative favicon URL' do
result = described_class.new(email).perform
expect(result[:logos].first[:url]).to eq('https://example.com/favicon.ico')
end
end
end
end