From f20ef2bfc7565996e14ca068096d0fcd8ac220ee Mon Sep 17 00:00:00 2001 From: iamsivin Date: Tue, 29 Apr 2025 15:41:42 +0530 Subject: [PATCH] chore: Adds spec --- .../forwarded_message_builder_spec.rb | 323 ++++++++++++++++++ .../builders/messages/message_builder_spec.rb | 160 +++++++++ 2 files changed, 483 insertions(+) create mode 100644 spec/builders/messages/forwarded_message_builder_spec.rb diff --git a/spec/builders/messages/forwarded_message_builder_spec.rb b/spec/builders/messages/forwarded_message_builder_spec.rb new file mode 100644 index 000000000..2babdd6e2 --- /dev/null +++ b/spec/builders/messages/forwarded_message_builder_spec.rb @@ -0,0 +1,323 @@ +require 'rails_helper' + +RSpec.describe Messages::ForwardedMessageBuilder do + let(:account) { create(:account) } + let(:inbox) { create(:inbox, account: account) } + let(:conversation) { create(:conversation, inbox: inbox, account: account) } + let(:user) { create(:user, account: account) } + + # Create a message with email data + let(:forwarded_message) do + create(:message, conversation: conversation, account: account, + content_attributes: { + email: { + 'from' => ['sender@example.com'], + 'to' => ['recipient@example.com'], + 'subject' => 'Test Subject', + 'date' => '2025-04-29T14:29:07+05:30', + 'html_content' => { + 'full' => '
HTML content
', + 'quoted' => 'HTML content', + 'reply' => 'HTML content' + }, + 'text_content' => { + 'full' => 'Text content', + 'quoted' => 'Text content', + 'reply' => 'Text content' + } + } + }) + end + + # Create a message with no email data + let(:regular_message) { create(:message, conversation: conversation, account: account) } + + describe '#perform' do + context 'when message_id is nil' do + it 'returns an empty hash' do + builder = described_class.new(nil) + expect(builder.perform).to eq({}) + end + end + + context 'when forwarded message is not found' do + it 'returns basic attributes' do + builder = described_class.new(999) + expect(builder.perform).to eq(content_attributes: { forwarded_message_id: 999 }) + end + end + + context 'when forwarded message has no email data' do + it 'returns basic attributes' do + builder = described_class.new(regular_message.id) + expect(builder.perform).to eq(content_attributes: { forwarded_message_id: regular_message.id }) + end + end + + context 'when forwarded message has email data' do + it 'returns forwarded attributes' do + builder = described_class.new(forwarded_message.id) + result = builder.perform + + expect(result).to be_a(Hash) + expect(result[:content_attributes]).to be_present + expect(result[:content_attributes][:forwarded_message_id]).to eq(forwarded_message.id) + expect(result[:content_attributes][:email]).to be_present + end + end + end + + describe '#formatted_content' do + context 'when forwarded message has no email data' do + it 'returns original content' do + builder = described_class.new(regular_message.id) + expect(builder.formatted_content('Original')).to eq('Original') + end + end + + context 'when forwarded message has email data' do + it 'returns formatted content with header and body' do + builder = described_class.new(forwarded_message.id) + result = builder.formatted_content('Original') + + expect(result).to include('Original') + expect(result).to include('---------- Forwarded message ---------') + expect(result).to include('From:') + expect(result).to include('Date:') + expect(result).to include('Subject: Test Subject') + expect(result).to include('Text content') # Should include the text content + end + end + end + + describe '#formatted_html_content' do + context 'when forwarded message has no email data' do + it 'returns original content' do + builder = described_class.new(regular_message.id) + expect(builder.formatted_html_content('Original')).to eq('Original') + end + end + + context 'when forwarded message has email data' do + it 'returns formatted HTML content with header and body' do + builder = described_class.new(forwarded_message.id) + result = builder.formatted_html_content('**Original**') + + expect(result).to include('Original') # Markdown converted to HTML + expect(result).to include('---------- Forwarded message ---------') + expect(result).to include('From:') + expect(result).to include('Date:') + expect(result).to include('Subject: Test Subject') + expect(result).to include('
HTML content
') # Should include the HTML content + end + end + end + + describe '#forwarded_email_data' do + context 'when forwarded message has no email data' do + it 'returns empty hash' do + builder = described_class.new(regular_message.id) + expect(builder.forwarded_email_data('Original')).to eq({}) + end + end + + context 'when forwarded message has email data' do + it 'returns complete email data structure' do + builder = described_class.new(forwarded_message.id) + result = builder.forwarded_email_data('**Original**') + + expect(result).to be_a(Hash) + expect(result['html_content']).to be_present + expect(result['text_content']).to be_present + + # Check HTML content + expect(result['html_content']['quoted']).to eq('Original') # Markdown stripped + expect(result['html_content']['full']).to include('Original') # HTML formatted + + # Check text content + expect(result['text_content']['quoted']).to eq('**Original**') # Original text preserved + expect(result['text_content']['full']).to include('---------- Forwarded message ---------') + end + end + + context 'when handling multipart emails' do + let(:multipart_message) do + create(:message, conversation: conversation, account: account, + content_attributes: { + email: { + 'from' => ['sender@example.com'], + 'to' => ['recipient@example.com'], + 'subject' => 'Multipart Test', + 'date' => '2025-04-29T14:29:07+05:30', + 'html_content' => { + 'full' => '
HTML formatted content
' + }, + 'text_content' => { + 'full' => 'Plain text content' + } + } + }) + end + + it 'preserves both HTML and text parts' do + builder = described_class.new(multipart_message.id) + result = builder.forwarded_email_data('New message') + + expect(result['html_content']['full']).to include('
HTML formatted content
') + expect(result['text_content']['full']).to include('Plain text content') + end + end + end + + describe '#convert_markdown_to_html' do + it 'converts bold markdown to HTML' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:convert_markdown_to_html, '**Bold Text**') + expect(result).to eq('Bold Text') + end + + it 'converts italic markdown to HTML' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:convert_markdown_to_html, '*Italic Text*') + expect(result).to eq('Italic Text') + end + + it 'converts underscore italic markdown to HTML' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:convert_markdown_to_html, '_Italic Text_') + expect(result).to eq('Italic Text') + end + + it 'handles empty text' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:convert_markdown_to_html, '') + expect(result).to eq('') + end + + it 'handles nil text' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:convert_markdown_to_html, nil) + expect(result).to eq('') + end + end + + describe '#strip_markdown' do + it 'strips bold markdown' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:strip_markdown, '**Bold Text**') + expect(result).to eq('Bold Text') + end + + it 'strips italic markdown' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:strip_markdown, '*Italic Text*') + expect(result).to eq('Italic Text') + end + + it 'strips underscore italic markdown' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:strip_markdown, '_Italic Text_') + expect(result).to eq('Italic Text') + end + + it 'handles empty text' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:strip_markdown, '') + expect(result).to eq('') + end + + it 'handles nil text' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:strip_markdown, nil) + expect(result).to eq('') + end + end + + describe '#extract_email' do + it 'extracts email from format "Name "' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:extract_email, 'John Doe ') + expect(result).to eq('john@example.com') + end + + it 'returns plain email as-is' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:extract_email, 'john@example.com') + expect(result).to eq('john@example.com') + end + + it 'handles empty string' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:extract_email, '') + expect(result).to eq('') + end + + it 'handles nil' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:extract_email, nil) + expect(result).to eq('') + end + end + + describe '#parse_from_field' do + it 'formats "Name " correctly' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:parse_from_field, 'John Doe ') + expect(result).to eq('John Doe ') + end + + it 'handles plain email' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:parse_from_field, 'john@example.com') + expect(result).to eq('john@example.com') + end + + it 'handles extra spaces' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:parse_from_field, 'John Doe < john@example.com >') + expect(result).to eq('John Doe ') + end + + it 'handles empty string' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:parse_from_field, '') + expect(result).to eq('') + end + + it 'handles nil' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:parse_from_field, nil) + expect(result).to eq('') + end + end + + describe '#format_date_string' do + it 'formats the date in a readable format' do + builder = described_class.new(forwarded_message.id) + # NOTE: We don't test the exact formatted output since it uses DateTime.now + # which would be different for each test run + result = builder.send(:format_date_string, '2025-04-29T14:29:07+05:30') + expect(result).to be_a(String) + expect(result).to match(/\w{3}, \w{3} \d+, \d{4} at \d+:\d+ [AP]M/) + end + + it 'handles empty string' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:format_date_string, '') + expect(result).to eq('') + end + + it 'handles nil' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:format_date_string, nil) + expect(result).to eq('') + end + + it 'returns current date formatted regardless of input' do + builder = described_class.new(forwarded_message.id) + result = builder.send(:format_date_string, 'Invalid Date') + + expect(result).to match(/\w{3}, \w{3} \d+, \d{4} at \d+:\d+ [AP]M/) + end + end +end diff --git a/spec/builders/messages/message_builder_spec.rb b/spec/builders/messages/message_builder_spec.rb index 891f8eb02..68e38f9c7 100644 --- a/spec/builders/messages/message_builder_spec.rb +++ b/spec/builders/messages/message_builder_spec.rb @@ -181,4 +181,164 @@ describe Messages::MessageBuilder do end end end + + describe '#perform with forwarded messages' do + let(:email_channel) { create(:channel_email, account: account) } + let(:email_inbox) { email_channel.inbox } + let(:email_conversation) { create(:conversation, inbox: email_inbox, account: account) } + + # Create a message with email data to be forwarded + let(:forwarded_message) do + create(:message, conversation: email_conversation, account: account, + content_attributes: { + email: { + 'from' => ['sender@example.com'], + 'to' => ['recipient@example.com'], + 'subject' => 'Test Subject', + 'date' => '2025-04-29T14:29:07+05:30', + 'html_content' => { + 'full' => '
HTML content
', + 'quoted' => 'HTML content', + 'reply' => 'HTML content' + }, + 'text_content' => { + 'full' => 'Text content', + 'quoted' => 'Text content', + 'reply' => 'Text content' + } + } + }) + end + + context 'when forwarding a message from a non-email inbox' do + let(:params) do + ActionController::Parameters.new({ + content: 'Forwarded message:', + content_attributes: { forwarded_message_id: forwarded_message.id } + }) + end + + it 'includes the forwarded message ID in content_attributes' do + message = described_class.new(user, conversation, params).perform + expect(message.content_attributes[:forwarded_message_id]).to eq(forwarded_message.id) + end + + it 'updates the content with the forwarded message text' do + message = described_class.new(user, conversation, params).perform + expect(message.content).to include('Forwarded message:') + expect(message.content).to include('---------- Forwarded message ---------') + end + end + + context 'when forwarding a message from an email inbox' do + let(:params) do + ActionController::Parameters.new({ + content: 'Forwarded message:', + content_attributes: { forwarded_message_id: forwarded_message.id } + }) + end + + let(:email_conversation_target) { create(:conversation, inbox: email_inbox, account: account) } + + it 'includes the forwarded email data in content_attributes' do + message = described_class.new(user, email_conversation_target, params).perform + + expect(message.content_attributes[:forwarded_message_id]).to eq(forwarded_message.id) + expect(message.content_attributes[:email]).to be_present + expect(message.content_attributes[:email]['html_content']).to be_present + expect(message.content_attributes[:email]['text_content']).to be_present + end + + it 'preserves the HTML content in the forwarded email' do + message = described_class.new(user, email_conversation_target, params).perform + + html_content = message.content_attributes[:email]['html_content']['full'] + expect(html_content).to include('
HTML content
') + end + + it 'preserves the text content in the forwarded email' do + message = described_class.new(user, email_conversation_target, params).perform + + text_content = message.content_attributes[:email]['text_content']['full'] + expect(text_content).to include('Text content') + end + end + + context 'when forwarding a message with markdown content' do + let(:params) do + ActionController::Parameters.new({ + content: '**Bold text** and _italic text_', + content_attributes: { forwarded_message_id: forwarded_message.id } + }) + end + + it 'converts markdown to HTML in the HTML content' do + message = described_class.new(user, email_conversation, params).perform + + html_content = message.content_attributes[:email]['html_content']['full'] + expect(html_content).to include('Bold text') + expect(html_content).to include('italic text') + end + + it 'preserves markdown in the text content' do + message = described_class.new(user, email_conversation, params).perform + + text_content = message.content_attributes[:email]['text_content']['full'] + expect(text_content).to include('**Bold text**') + expect(text_content).to include('_italic text_') + end + end + + context 'when forwarding a message with no email data' do + let(:regular_message) { create(:message, conversation: conversation, account: account) } + + let(:params) do + ActionController::Parameters.new({ + content: 'Forwarding a regular message:', + content_attributes: { forwarded_message_id: regular_message.id } + }) + end + + it 'includes the forwarded message ID and empty email data' do + message = described_class.new(user, email_conversation, params).perform + + expect(message.content_attributes[:forwarded_message_id]).to eq(regular_message.id) + expect(message.content_attributes[:email]).to eq({}) + end + end + + context 'with multipart email content' do + let(:multipart_message) do + create(:message, conversation: email_conversation, account: account, + content_attributes: { + email: { + 'from' => ['sender@example.com'], + 'to' => ['recipient@example.com'], + 'subject' => 'Multipart Test', + 'date' => '2025-04-29T14:29:07+05:30', + 'html_content' => { + 'full' => '
HTML formatted content
' + }, + 'text_content' => { + 'full' => 'Plain text content' + } + } + }) + end + + let(:params) do + ActionController::Parameters.new({ + content: 'Forwarding multipart email:', + content_attributes: { forwarded_message_id: multipart_message.id } + }) + end + + it 'preserves both HTML and text parts in the forwarded email' do + message = described_class.new(user, email_conversation, params).perform + + expect(message.content_attributes[:email]['html_content']['full']).to include('
HTML formatted content
') + expect(message.content_attributes[:email]['text_content']['full']).to include('Plain text content') + end + end + end end