Restructure omni services and add Chatwoot research snapshot

This commit is contained in:
Ruslan Bakiev
2026-02-21 11:11:27 +07:00
parent edea7a0034
commit b73babbbf6
7732 changed files with 978203 additions and 32 deletions

View File

@@ -0,0 +1,34 @@
require 'rails_helper'
RSpec.describe AdministratorNotifications::AccountComplianceMailer do
let(:account) do
create(:account, custom_attributes: { 'marked_for_deletion_at' => 1.day.ago.iso8601, 'marked_for_deletion_reason' => 'user_requested' })
end
let(:soft_deleted_users) do
[
{ id: 1, original_email: 'user1@example.com' },
{ id: 2, original_email: 'user2@example.com' }
]
end
describe 'account_deleted' do
it 'has the right subject format' do
subject = described_class.new.send(:subject_for, account)
expect(subject).to eq("Account Deletion Notice for #{account.id} - #{account.name}")
end
it 'includes soft deleted users in meta when provided' do
mailer_instance = described_class.new
allow(mailer_instance).to receive(:params).and_return(
{ soft_deleted_users: soft_deleted_users }
)
meta = mailer_instance.send(:build_meta, account)
expect(meta['deleted_user_count']).to eq(2)
expect(meta['soft_deleted_users'].size).to eq(2)
expect(meta['soft_deleted_users'].first['user_id']).to eq('1')
expect(meta['soft_deleted_users'].first['user_email']).to eq('user1@example.com')
end
end
end

View File

@@ -0,0 +1,46 @@
require 'rails_helper'
RSpec.describe AdministratorNotifications::AccountNotificationMailer do
let(:account) { create(:account, name: 'Test Account') }
let(:mailer) { described_class.with(account: account) }
let(:class_instance) { described_class.new }
before do
allow(described_class).to receive(:new).and_return(class_instance)
allow(class_instance).to receive(:smtp_config_set_or_development?).and_return(true)
account.custom_attributes['marked_for_deletion_at'] = 7.days.from_now.iso8601
account.save!
end
describe '#account_deletion_user_initiated' do
it 'sets the correct subject for user-initiated deletion' do
mail = mailer.account_deletion_user_initiated(account, 'manual_deletion')
expect(mail.subject).to eq('Your Chatwoot account deletion has been scheduled')
end
end
describe '#account_deletion_for_inactivity' do
it 'sets the correct subject for system-initiated deletion' do
mail = mailer.account_deletion_for_inactivity(account, 'Account Inactive')
expect(mail.subject).to eq('Your Chatwoot account is scheduled for deletion due to inactivity')
end
end
describe '#format_deletion_date' do
it 'formats a valid date string' do
date_str = '2024-12-31T12:00:00Z'
formatted = described_class.new.send(:format_deletion_date, date_str)
expect(formatted).to eq('December 31, 2024')
end
it 'handles blank dates' do
formatted = described_class.new.send(:format_deletion_date, nil)
expect(formatted).to eq('Unknown')
end
it 'handles invalid dates' do
formatted = described_class.new.send(:format_deletion_date, 'invalid-date')
expect(formatted).to eq('Unknown')
end
end
end

View File

@@ -0,0 +1,74 @@
require 'rails_helper'
RSpec.describe AdministratorNotifications::BaseMailer do
let!(:account) { create(:account) }
let!(:admin1) { create(:user, account: account, role: :administrator) }
let!(:admin2) { create(:user, account: account, role: :administrator) }
let!(:agent) { create(:user, account: account, role: :agent) }
let(:mailer) { described_class.new }
let!(:inbox) { create(:inbox, account: account) }
before do
Current.account = account
end
describe 'admin_emails' do
it 'returns emails of all administrators' do
# Call the private method
admin_emails = mailer.send(:admin_emails)
expect(admin_emails).to contain_exactly(admin1.email, admin2.email)
expect(admin_emails).not_to include(agent.email)
end
end
describe 'helper methods' do
it 'generates correct inbox URL' do
url = mailer.inbox_url(inbox)
expected_url = "#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/#{account.id}/settings/inboxes/#{inbox.id}"
expect(url).to eq(expected_url)
end
it 'generates correct settings URL' do
url = mailer.settings_url('automation/list')
expected_url = "#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/#{account.id}/settings/automation/list"
expect(url).to eq(expected_url)
end
end
describe 'send_notification' do
before do
allow(mailer).to receive(:smtp_config_set_or_development?).and_return(true)
end
it 'sends email with correct parameters' do
subject = 'Test Subject'
action_url = 'https://example.com'
meta = { 'key' => 'value' }
# Mock the send_mail_with_liquid method
expect(mailer).to receive(:send_mail_with_liquid).with(
to: contain_exactly(admin1.email, admin2.email),
subject: subject
).and_return(true)
mailer.send_notification(subject, action_url: action_url, meta: meta)
# Check that instance variables are set correctly
expect(mailer.instance_variable_get(:@action_url)).to eq(action_url)
expect(mailer.instance_variable_get(:@meta)).to eq(meta)
end
it 'uses provided email addresses when specified' do
subject = 'Test Subject'
custom_email = 'custom@example.com'
expect(mailer).to receive(:send_mail_with_liquid).with(
to: custom_email,
subject: subject
).and_return(true)
mailer.send_notification(subject, to: custom_email)
end
end
end

View File

@@ -0,0 +1,62 @@
# frozen_string_literal: true
require 'rails_helper'
require Rails.root.join 'spec/mailers/administrator_notifications/shared/smtp_config_shared.rb'
RSpec.describe AdministratorNotifications::ChannelNotificationsMailer do
include_context 'with smtp config'
let(:class_instance) { described_class.new }
let!(:account) { create(:account) }
let!(:administrator) { create(:user, :administrator, email: 'agent1@example.com', account: account) }
let!(:another_administrator) { create(:user, :administrator, email: 'agent2@example.com', account: account) }
describe 'facebook_disconnect' do
before do
stub_request(:post, /graph.facebook.com/)
end
let!(:facebook_channel) { create(:channel_facebook_page, account: account) }
let!(:facebook_inbox) { create(:inbox, channel: facebook_channel, account: account) }
context 'when sending the actual email' do
let(:mail) { described_class.with(account: account).facebook_disconnect(facebook_inbox).deliver_now }
it 'renders the subject' do
expect(mail.subject).to eq('Your Facebook page connection has expired')
end
it 'renders the receiver email' do
expect(mail.to).to contain_exactly(administrator.email, another_administrator.email)
end
end
end
describe 'whatsapp_disconnect' do
let!(:whatsapp_channel) { create(:channel_whatsapp, provider: 'whatsapp_cloud', sync_templates: false, validate_provider_config: false) }
let!(:whatsapp_inbox) { create(:inbox, channel: whatsapp_channel, account: account) }
let(:mail) { described_class.with(account: account).whatsapp_disconnect(whatsapp_inbox).deliver_now }
it 'renders the subject' do
expect(mail.subject).to eq('Your Whatsapp connection has expired')
end
it 'renders the receiver email' do
expect(mail.to).to contain_exactly(administrator.email, another_administrator.email)
end
end
describe 'instagram_disconnect' do
let!(:instagram_channel) { create(:channel_instagram, account: account) }
let!(:instagram_inbox) { create(:inbox, channel: instagram_channel, account: account) }
let(:mail) { described_class.with(account: account).instagram_disconnect(instagram_inbox).deliver_now }
it 'renders the subject' do
expect(mail.subject).to eq('Your Instagram connection has expired')
end
it 'renders the receiver email' do
expect(mail.to).to contain_exactly(administrator.email, another_administrator.email)
end
end
end

View File

@@ -0,0 +1,42 @@
require 'rails_helper'
require Rails.root.join 'spec/mailers/administrator_notifications/shared/smtp_config_shared.rb'
RSpec.describe AdministratorNotifications::IntegrationsNotificationMailer do
include_context 'with smtp config'
let!(:account) { create(:account) }
let!(:administrator) { create(:user, :administrator, email: 'admin@example.com', account: account) }
let!(:another_administrator) { create(:user, :administrator, email: 'owner@example.com', account: account) }
describe 'slack_disconnect' do
let(:mail) { described_class.with(account: account).slack_disconnect.deliver_now }
it 'renders the subject' do
expect(mail.subject).to eq('Your Slack integration has expired')
end
it 'renders the receiver email' do
expect(mail.to).to contain_exactly(administrator.email, another_administrator.email)
end
it 'includes reconnect instructions in the body' do
expect(mail.body.encoded).to include('To continue receiving messages on Slack, please delete the integration and connect your workspace again')
end
end
describe 'dialogflow_disconnect' do
let(:mail) { described_class.with(account: account).dialogflow_disconnect.deliver_now }
it 'renders the subject' do
expect(mail.subject).to eq('Your Dialogflow integration was disconnected')
end
it 'renders the content' do
expect(mail.body.encoded).to include('Your Dialogflow integration was disconnected because of permission issues')
end
it 'renders the receiver email' do
expect(mail.to).to contain_exactly(administrator.email, another_administrator.email)
end
end
end

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
RSpec.shared_context 'with smtp config' do
before do
# We need to use allow_any_instance_of here because smtp_config_set_or_development?
# is defined in ApplicationMailer and needs to be stubbed for all mailer instances
# rubocop:disable RSpec/AnyInstance
allow_any_instance_of(ApplicationMailer).to receive(:smtp_config_set_or_development?).and_return(true)
# rubocop:enable RSpec/AnyInstance
end
end