Refactoring: Migrate email-process unit sub-tests to RSpec.

This commit is contained in:
Ryan Lue 2019-03-11 08:28:18 +01:00 committed by Martin Edenhofer
parent 92d7ee95e0
commit b19ac485bf
8 changed files with 311 additions and 613 deletions

View file

@ -1,10 +1,15 @@
FactoryBot.define do
factory :ticket do
transient do
state_name 'new'
priority_name '2 normal'
end
title { 'Test Ticket' }
group
customer
state { Ticket::State.lookup(name: 'new') }
priority { Ticket::Priority.lookup(name: '2 normal') }
state { Ticket::State.lookup(name: state_name) }
priority { Ticket::Priority.lookup(name: priority_name) }
updated_by_id { 1 }
created_by_id { 1 }

View file

@ -0,0 +1,18 @@
require 'rails_helper'
RSpec.describe Mail::Encodings do
# Regression test for https://github.com/zammad/zammad/issues/2456
# (Mail lib was originally broken, so we patched it.
# Then, upstream was fixed, whereas our patch broke.)
describe '.value_decode' do
it 'decodes us-ascii encoded strings' do
expect(Mail::Encodings.value_decode('=?us-ascii?Q?Test?='))
.to eql('Test')
end
it 'decodes utf-8 encoded strings' do
expect(Mail::Encodings.value_decode('=?UTF-8?Q? Personal=C3=A4nderung?='))
.to eql(' Personaländerung')
end
end
end

View file

@ -1,50 +1,68 @@
require 'rails_helper'
RSpec.describe Channel::EmailParser, type: :model do
let(:subject) { described_class.new }
let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail001.box') }
let(:raw_mail) { File.read(mail_file) }
describe '#parse' do
# regression test for issue 2390 - Add a postmaster filter to not show emails with potential issue
describe 'handling HTML links in message content' do
context 'with under 5,000 links' do
it 'parses message content as normal' do
expect(described_class.new.parse(<<~RAW)[:body]).to start_with('<a href="https://zammad.com/"')
From: nicole.braun@zammad.com
Content-Type: text/html
describe '#process' do
let(:raw_mail) { File.read(mail_file).sub(/(?<=^Subject: ).*$/, test_string) }
let(:test_string) { Setting.get('ticket_hook') + Setting.get('ticket_hook_divider') + ticket.number }
let(:ticket) { create(:ticket) }
context 'for creating new users' do
context 'with one unrecognized email address' do
let(:raw_mail) { <<~RAW }
From: #{Faker::Internet.unique.email}
To: #{User.pluck(:email).reject(&:blank?).sample}
Subject: Foo bar
Lorem ipsum dolor
RAW
it 'creates one new user' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.to change { User.count }.by(1)
<html><body>
#{Array.new(10) { '<a href="https://zammad.com/">Dummy Link</a>' }.join(' ')}
</body></html>
RAW
end
end
context 'with a large number (42+) of unrecognized email addresses' do
let(:raw_mail) { <<~RAW }
From: #{Faker::Internet.unique.email}
To: #{Array.new(22) { Faker::Internet.unique.email }.join(', ')}
Cc: #{Array.new(22) { Faker::Internet.unique.email }.join(', ')}
Subject: test max sender identify
context 'with 5,000+ links' do
it 'replaces message content with error message' do
expect(described_class.new.parse(<<~RAW)).to include('body' => Channel::EmailParser::EXCESSIVE_LINKS_MSG)
From: nicole.braun@zammad.com
Content-Type: text/html
Some Text
RAW
<html><body>
#{Array.new(5001) { '<a href="https://zammad.com/">Dummy Link</a>' }.join(' ')}
</body></html>
RAW
end
end
end
end
it 'never creates more than 41 users per email' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.to change { User.count }.by(41)
describe '#process' do
let(:raw_mail) { File.read(mail_file) }
describe 'auto-creating new users' do
context 'with one unrecognized email address' do
it 'creates one new user' do
expect { Channel::EmailParser.new.process({}, <<~RAW) }.to change { User.count }.by(1)
From: #{Faker::Internet.unique.email}
RAW
end
end
context 'with a large number of unrecognized recipient addresses' do
it 'never creates more than 40 users' do
expect { Channel::EmailParser.new.process({}, <<~RAW) }.to change { User.count }.by(40)
From: nicole.braun@zammad.org
To: #{Array.new(20) { Faker::Internet.unique.email }.join(', ')}
Cc: #{Array.new(21) { Faker::Internet.unique.email }.join(', ')}
RAW
end
end
end
context 'for associating emails to tickets' do
describe 'associating emails to tickets' do
let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail001.box') }
let(:ticket_ref) { Setting.get('ticket_hook') + Setting.get('ticket_hook_divider') + ticket.number }
let(:ticket) { create(:ticket) }
context 'when email subject contains ticket reference' do
let(:raw_mail) { File.read(mail_file).sub(/(?<=^Subject: ).*$/, ticket_ref) }
it 'adds message to ticket' do
expect { described_class.new.process({}, raw_mail) }
.to change { ticket.articles.length }
@ -56,7 +74,7 @@ RSpec.describe Channel::EmailParser, type: :model do
context 'when body contains ticket reference' do
context 'in visible text' do
let(:raw_mail) { File.read(mail_file).sub(/Hallo =\nMartin,(?=<o:p>)/, test_string) }
let(:raw_mail) { File.read(mail_file).sub(/Hallo =\nMartin,(?=<o:p>)/, ticket_ref) }
it 'adds message to ticket' do
expect { described_class.new.process({}, raw_mail) }
@ -65,7 +83,7 @@ RSpec.describe Channel::EmailParser, type: :model do
end
context 'as part of a larger word' do
let(:raw_mail) { File.read(mail_file).sub(/(?<=Hallo) =\n(?=Martin,<o:p>)/, test_string) }
let(:raw_mail) { File.read(mail_file).sub(/(?<=Hallo) =\n(?=Martin,<o:p>)/, ticket_ref) }
it 'creates a separate ticket' do
expect { described_class.new.process({}, raw_mail) }
@ -74,7 +92,7 @@ RSpec.describe Channel::EmailParser, type: :model do
end
context 'in html attributes' do
let(:raw_mail) { File.read(mail_file).sub(%r{<a href.*?/a>}m, %(<table bgcolor="#{test_string}"> </table>)) }
let(:raw_mail) { File.read(mail_file).sub(%r{<a href.*?/a>}m, %(<table bgcolor="#{ticket_ref}"> </table>)) }
it 'creates a separate ticket' do
expect { described_class.new.process({}, raw_mail) }
@ -85,7 +103,7 @@ RSpec.describe Channel::EmailParser, type: :model do
end
end
context 'for sender/recipient address formatting' do
describe 'sender/recipient address formatting' do
# see https://github.com/zammad/zammad/issues/2198
context 'when sender address contains spaces (#2198)' do
let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail071.box') }
@ -93,7 +111,7 @@ RSpec.describe Channel::EmailParser, type: :model do
it 'removes them before creating a new user' do
expect { described_class.new.process({}, raw_mail) }
.to change { User.where(email: sender_email).count }.to(1)
.to change { User.exists?(email: sender_email) }
end
it 'marks new user email as invalid' do
@ -113,7 +131,7 @@ RSpec.describe Channel::EmailParser, type: :model do
it 'removes them before creating a new user' do
expect { described_class.new.process({}, raw_mail) }
.to change { User.where(email: sender_email).count }.to(1)
.to change { User.exists?(email: sender_email) }
end
it 'marks new user email as invalid' do
@ -127,7 +145,7 @@ RSpec.describe Channel::EmailParser, type: :model do
end
end
context 'for charset handling' do
describe 'charset handling' do
# see https://github.com/zammad/zammad/issues/2224
context 'when header specifies Windows-1258 charset (#2224)' do
let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail072.box') }
@ -139,46 +157,10 @@ RSpec.describe Channel::EmailParser, type: :model do
end
end
context 'mail with links' do
def mock_mail(number_of_links)
link = '<a href="https://zammad.com/">Dummy Link</a> '
mail = Mail.new
mail.html_part = "<html><body>#{link * number_of_links}</body></html>"
mail
end
let(:mail_10) { mock_mail(10).to_s }
let(:mail_5k) { mock_mail(5001).to_s }
# regression test for issue 2390 - Add a postmaster filter to not show emails with potential issue
it '(>5k links) are replaced by a warning message' do
expect( described_class.new.parse(mail_5k)[:body] )
.to eql( Channel::EmailParser::EXCESSIVE_LINKS_MSG )
end
it '(10 links) are not touched' do
expect( described_class.new.parse(mail_10)[:body] )
.to start_with( '<a href="https://zammad.com/"' )
end
end
context 'Mail::Encodings.value_decode' do
it 'decode us-ascii encoded strings' do
expect( Mail::Encodings.value_decode('=?us-ascii?Q?Test?=') ).to eql( 'Test' )
end
it 'decode utf-8 encoded strings' do
expect( Mail::Encodings.value_decode('=?UTF-8?Q? Personal=C3=A4nderung?=') ).to eql( ' Personaländerung' )
end
end
context 'when handling Content-Transfer-Encoding of attachments' do
context 'with x-uuencode' do
describe 'attachment handling' do
context 'with header "Content-Transfer-Encoding: x-uuencode"' do
let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail078-content_transfer_encoding_x_uuencode.box') }
let(:article) { described_class.new.process({}, raw_mail).second }
it 'does not raise RuntimeError' do
expect { described_class.new.process({}, raw_mail) }
@ -186,26 +168,115 @@ RSpec.describe Channel::EmailParser, type: :model do
end
it 'parses the content correctly' do
_ticket, article, _user, _mail = described_class.new.process({}, raw_mail)
expect(article.attachments.first.filename).to eq('PGP_Cmts_on_12-14-01_Pkg.txt')
expect(article.attachments.first.content).to eq('Hello Zammad')
end
end
end
context 'when mail contains image(s)' do
describe 'inline image handling' do
# see https://github.com/zammad/zammad/issues/2486
context 'when image is large but not resizable' do
let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail079.box') }
let(:attachment) { article.attachments.last }
let(:article) { described_class.new.process({}, raw_mail).second }
it "doesn't set resizable preference" do
_ticket, article = described_class.new.process({}, raw_mail)
attachment = article.attachments.last
expect(attachment.filename).to eq('a.jpg')
expect(attachment.preferences).not_to include('resizable' => true)
end
end
end
context 'for “delivery failed” notifications (a.k.a. bounce messages)' do
let(:ticket) { article.ticket }
let(:article) { create(:ticket_article, sender_name: 'Agent', message_id: message_id) }
let(:message_id) { raw_mail[/(?<=^(References|Message-ID): )\S*/] }
context 'with future retries (delayed)' do
let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail078.box') }
context 'on a closed ticket' do
before { ticket.update(state: Ticket::State.find_by(name: 'closed')) }
it 'sets #preferences on resulting ticket to { "send-auto-responses" => false, "is-auto-reponse" => true }' do
article = Channel::EmailParser.new.process({}, raw_mail).second
expect(article.preferences)
.to include('send-auto-response' => false, 'is-auto-response' => true)
end
it 'returns a Mail object with an x-zammad-out-of-office header' do
output_mail = Channel::EmailParser.new.process({}, raw_mail).last
expect(output_mail).to include('x-zammad-out-of-office': true)
end
it 'finds the article referenced in the bounce message headers, then adds the bounce message to its ticket' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.to change { ticket.articles.count }.by(1)
end
it 'does not re-open the ticket' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.not_to change { ticket.reload.state.name }.from('closed')
end
end
end
context 'with no future retries (undeliverable): sample input 1' do
let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail033-undelivered-mail-returned-to-sender.box') }
context 'for original message sent by Agent' do
it 'sets #preferences on resulting ticket to { "send-auto-responses" => false, "is-auto-reponse" => true }' do
article = Channel::EmailParser.new.process({}, raw_mail).second
expect(article.preferences)
.to include('send-auto-response' => false, 'is-auto-response' => true)
end
it 'finds the article referenced in the bounce message headers, then adds the bounce message to its ticket' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.to change { ticket.articles.count }.by(1)
end
it 'does not alter the ticket state' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.not_to change { ticket.reload.state.name }.from('open')
end
end
context 'for original message sent by Customer' do
let(:article) { create(:ticket_article, sender_name: 'Customer', message_id: message_id) }
it 'sets #preferences on resulting ticket to { "send-auto-responses" => false, "is-auto-reponse" => true }' do
article = Channel::EmailParser.new.process({}, raw_mail).second
expect(article.preferences)
.to include('send-auto-response' => false, 'is-auto-response' => true)
end
it 'finds the article referenced in the bounce message headers, then adds the bounce message to its ticket' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.to change { ticket.articles.count }.by(1)
end
it 'does not alter the ticket state' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.not_to change { ticket.reload.state.name }.from('new')
end
end
end
context 'with no future retries (undeliverable): sample input 2' do
let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail055.box') }
it 'finds the article referenced in the bounce message headers, then adds the bounce message to its ticket' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.to change { ticket.articles.count }.by(1)
end
it 'does not alter the ticket state' do
expect { Channel::EmailParser.new.process({}, raw_mail) }
.not_to change { ticket.reload.state.name }.from('open')
end
end
end
end
end

View file

@ -256,6 +256,18 @@ RSpec.describe Ticket, type: :model do
end
describe 'Attributes:' do
describe '#state' do
context 'for brand new tickets' do
context 'when a non-customer article is added' do
let(:article) { create(:ticket_article, ticket: ticket, sender_name: 'Agent') }
it 'switches to "open"' do
expect { article }.to change { ticket.state.name }.from('new').to('open')
end
end
end
end
describe '#pending_time' do
subject(:ticket) { create(:ticket, pending_time: Time.zone.now + 2.days) }

View file

@ -4,10 +4,10 @@ require 'models/application_model_examples'
RSpec.describe Trigger, type: :model do
it_behaves_like 'ApplicationModel', can_assets: { selectors: %i[condition perform] }
subject(:trigger) { create(:trigger) }
before { Trigger.destroy_all } # Default DB state includes three sample triggers
subject!(:trigger) { create(:trigger, condition: condition, perform: perform) }
describe '#assets (for supplying model data to front-end framework)' do
subject(:trigger) { create(:trigger, condition: condition, perform: perform) }
let(:condition) { { 'ticket.state_id' => { operator: 'is', value: 1 } } }
let(:perform) { { 'ticket.priority_id' => { value: 1 } } }
@ -17,4 +17,113 @@ RSpec.describe Trigger, type: :model do
.and include(Ticket::Priority.first.assets({}))
end
end
describe 'Send-email triggers' do
let(:perform) do
{
'notification.email' => {
'recipient' => 'ticket_customer',
'subject' => 'foo',
'body' => 'bar'
}
}
end
context 'for condition "ticket created"' do
let(:condition) do
{ 'ticket.action' => { 'operator' => 'is', 'value' => 'create' } }
end
context 'when ticket is created directly' do
let!(:ticket) { create(:ticket) }
it 'fires (without altering ticket state)' do
expect { Observer::Transaction.commit }
.to change { Ticket::Article.count }.by(1)
.and not_change { ticket.reload.state.name }.from('new')
end
end
context 'when ticket is created via Channel::EmailParser.process' do
before { create(:email_address, groups: [Group.first]) }
let(:raw_email) { File.read(Rails.root.join('test', 'data', 'mail', 'mail001.box')) }
it 'fires (without altering ticket state)' do
expect { Channel::EmailParser.new.process({}, raw_email) }
.to change { Ticket.count }.by(1)
.and change { Ticket::Article.count }.by(2)
expect(Ticket.last.state.name).to eq('new')
end
end
end
context 'for condition "ticket updated"' do
let(:condition) do
{ 'ticket.action' => { 'operator' => 'is', 'value' => 'update' } }
end
let!(:ticket) { create(:ticket).tap { Observer::Transaction.commit } }
context 'when new article is created directly' do
context 'with empty #preferences hash' do
let!(:article) { create(:ticket_article, ticket: ticket) }
it 'fires (without altering ticket state)' do
expect { Observer::Transaction.commit }
.to change { ticket.reload.articles.count }.by(1)
.and not_change { ticket.reload.state.name }.from('new')
end
end
context 'with #preferences { "send-auto-response" => false }' do
let!(:article) do
create(:ticket_article,
ticket: ticket,
preferences: { 'send-auto-response' => false })
end
it 'does not fire' do
expect { Observer::Transaction.commit }
.not_to change { ticket.reload.articles.count }
end
end
end
context 'when new article is created via Channel::EmailParser.process' do
context 'with a regular message' do
let!(:article) do
create(:ticket_article,
ticket: ticket,
message_id: raw_email[/(?<=^References: )\S*/],
subject: raw_email[/(?<=^Subject: Re: ).*$/])
end
let(:raw_email) { File.read(Rails.root.join('test', 'data', 'mail', 'mail005.box')) }
it 'fires (without altering ticket state)' do
expect { Channel::EmailParser.new.process({}, raw_email) }
.to not_change { Ticket.count }
.and change { ticket.reload.articles.count }.by(2)
.and not_change { ticket.reload.state.name }.from('new')
end
end
context 'with delivery-failed "bounce message"' do
let!(:article) do
create(:ticket_article,
ticket: ticket,
message_id: raw_email[/(?<=^Message-ID: )\S*/])
end
let(:raw_email) { File.read(Rails.root.join('test', 'data', 'mail', 'mail055.box')) }
it 'does not fire' do
expect { Channel::EmailParser.new.process({}, raw_email) }
.to change { ticket.reload.articles.count }.by(1)
end
end
end
end
end
end

View file

@ -1,52 +1,21 @@
require 'test_helper'
class EmailProcessBounceDeliveryTemporaryFailed < ActiveSupport::TestCase
test 'process with temp faild bounce email' do
ticket = Ticket.create!(
title: 'temp failed check - ms',
group: Group.lookup(name: 'Users'),
customer_id: 2,
state: Ticket::State.lookup(name: 'closed'),
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
article = Ticket::Article.create!(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'temp failed check',
message_id: '<20150830145601.30.608881@edenhofer.zammad.com>',
body: 'some message bounce check',
internal: false,
sender: Ticket::Article::Sender.lookup(name: 'Agent'),
type: Ticket::Article::Type.lookup(name: 'email'),
updated_by_id: 1,
created_by_id: 1,
)
travel 1.second
# temp faild bounce email
email_raw_string = "Content-Type: multipart/report; boundary=\"000000000000ca4a1a057417a375\"; report-type=delivery-status
Content-Type: multipart/report; boundary="000000000000ca4a1a057417a375"; report-type=delivery-status
From: Mail Delivery Subsystem <mailer-daemon@example.com>
To: service@example.de
Auto-Submitted: auto-replied
Subject: Delivery Status Notification (Delay)
References: #{article.message_id}
In-Reply-To: #{article.message_id}
References: <20150830145601.30.608881@example.com>
In-Reply-To: <20150830145601.30.608881@example.com>
Message-ID: <5b7e8af4.1c69fb81.3ac1b.e296.GMRIR@mx.example.com>
Date: Thu, 23 Aug 2018 03:22:44 -0700 (PDT)
--000000000000ca4a1a057417a375
Content-Type: multipart/related; boundary=\"000000000000ca53d4057417a37c\"
Content-Type: multipart/related; boundary="000000000000ca53d4057417a37c"
--000000000000ca53d4057417a37c
Content-Type: multipart/alternative; boundary=\"000000000000ca53de057417a37d\"
Content-Type: multipart/alternative; boundary="000000000000ca53de057417a37d"
--000000000000ca53de057417a37d
Content-Type: text/plain; charset=\"UTF-8\"
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
@ -72,7 +41,7 @@ Content-Type: message/delivery-status
Reporting-MTA: dns; example.com
Received-From-MTA: dns; service@example.de
Arrival-Date: Wed, 22 Aug 2018 02:00:03 -0700 (PDT)
X-Original-Message-ID: #{article.message_id}
X-Original-Message-ID: <20150830145601.30.608881@example.com>
Final-Recipient: rfc822; bob.smith@example.de
Action: delayed
@ -89,21 +58,10 @@ Content-Type: message/rfc822
Date: Wed, 22 Aug 2018 11:00:03 +0200
From: example Helpdesk <service@example.de>
To: bob.smith@example.de
Message-ID: #{article.message_id}
Message-ID: <20150830145601.30.608881@example.com>
Subject: Ihre Anfrage () [Ticket#638810]
Content-Type: text/plain; charset=UTF-8
ABC
--000000000000ca4a1a057417a375--
"
ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
assert_equal(true, mail['x-zammad-out-of-office'.to_sym])
ticket = Ticket.find(ticket.id)
assert_equal(ticket.id, ticket_p.id)
assert_equal('closed', ticket.state.name)
end
end

View file

@ -1,219 +0,0 @@
require 'test_helper'
class EmailProcessBounceDeliveryPermanentFailedTest < ActiveSupport::TestCase
test 'process with bounce trigger email loop check - article based blocker' do
roles = Role.where(name: %w[Customer])
customer1 = User.create_or_update(
login: 'ticket-bounce-trigger1@example.com',
firstname: 'Notification',
lastname: 'Customer1',
email: 'ticket-bounce-trigger1@example.com',
active: true,
roles: roles,
preferences: {},
updated_by_id: 1,
created_by_id: 1,
)
Trigger.create_or_update(
name: 'auto reply new ticket',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'ticket_customer',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
Trigger.create_or_update(
name: 'auto reply followup',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'update',
},
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'ticket_customer',
'subject' => 'Thanks for your follow up (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
ticket = Ticket.create!(
title: 'bounce check',
group: Group.lookup(name: 'Users'),
customer: customer1,
state: Ticket::State.lookup(name: 'new'),
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
article = Ticket::Article.create!(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'bounce check',
message_id: '<20150830145601.30.6088xx@edenhofer.zammad.com>',
body: 'some message bounce check',
internal: false,
sender: Ticket::Article::Sender.where(name: 'Agent').first,
type: Ticket::Article::Type.where(name: 'email').first,
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
assert_equal('new', ticket.state.name)
assert_equal(2, ticket.articles.count)
article = Ticket::Article.create!(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: customer1.email,
subject: 'bounce check 2',
message_id: '<20150830145601.30.608881@edenhofer.zammad.com>',
body: 'some message bounce check 2',
internal: false,
sender: Ticket::Article::Sender.where(name: 'Agent').first,
type: Ticket::Article::Type.where(name: 'email').first,
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
assert_equal(4, ticket.articles.count)
travel 1.second
email_raw_string = File.read(Rails.root.join('test', 'data', 'mail', 'mail033-undelivered-mail-returned-to-sender.box'))
ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string)
assert_equal(ticket.id, ticket_p.id)
assert_equal('open', ticket_p.state.name)
assert_equal(5, ticket_p.articles.count)
travel_back
ticket.destroy
end
test 'process with bounce trigger email loop check - bounce based blocker' do
roles = Role.where(name: %w[Customer])
customer2 = User.create_or_update(
login: 'ticket-bounce-trigger2@example.com',
firstname: 'Notification',
lastname: 'Customer2',
email: 'ticket-bounce-trigger2@example.com',
active: true,
roles: roles,
preferences: {},
updated_by_id: 1,
created_by_id: 1,
)
Trigger.create_or_update(
name: 'auto reply new ticket',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'ticket_customer',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
Trigger.create_or_update(
name: 'auto reply followup',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'update',
},
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'ticket_customer',
'subject' => 'Thanks for your follow up (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
ticket = Ticket.create!(
title: 'bounce check',
group: Group.lookup(name: 'Users'),
customer: customer2,
state: Ticket::State.lookup(name: 'new'),
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
article = Ticket::Article.create!(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'bounce check',
message_id: '<20150830145601.30.6088xx@edenhofer.zammad.com>',
body: 'some message bounce check',
internal: false,
sender: Ticket::Article::Sender.where(name: 'Agent').first,
type: Ticket::Article::Type.where(name: 'email').first,
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
assert_equal('new', ticket.state.name)
assert_equal(2, ticket.articles.count)
article = Ticket::Article.create!(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'bounce check 2',
message_id: '<20170526150141.232.13312@example.zammad.loc>',
body: 'some message bounce check 2',
internal: false,
sender: Ticket::Article::Sender.where(name: 'Agent').first,
type: Ticket::Article::Type.where(name: 'email').first,
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
assert_equal(4, ticket.articles.count)
travel 1.second
email_raw_string = File.read(Rails.root.join('test', 'data', 'mail', 'mail055.box'))
ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string)
assert_equal(ticket.id, ticket_p.id)
assert_equal('open', ticket_p.state.name)
assert_equal(5, ticket_p.articles.count)
travel_back
ticket.destroy
end
end

View file

@ -1,256 +0,0 @@
require 'test_helper'
class EmailProcessBounceFollowUpTest < ActiveSupport::TestCase
test 'process with bounce follow up check' do
ticket = Ticket.create(
title: 'bounce check',
group: Group.lookup(name: 'Users'),
customer_id: 2,
state: Ticket::State.lookup(name: 'new'),
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
article = Ticket::Article.create(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'bounce check',
message_id: '<20150830145601.30.608881@edenhofer.zammad.com>',
body: 'some message bounce check',
internal: false,
sender: Ticket::Article::Sender.where(name: 'Customer').first,
type: Ticket::Article::Type.where(name: 'email').first,
updated_by_id: 1,
created_by_id: 1,
)
travel 1.second
email_file_path = Rails.root.join('test', 'data', 'mail', 'mail033-undelivered-mail-returned-to-sender.box')
email_raw_string = File.read(email_file_path)
ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string)
assert_equal(ticket.id, ticket_p.id)
assert_equal('new', ticket_p.state.name)
travel_back
ticket.destroy
end
test 'process with bounce trigger email loop check - article based blocker' do
roles = Role.where(name: %w[Customer])
customer1 = User.create_or_update(
login: 'ticket-bounce-trigger1@example.com',
firstname: 'Notification',
lastname: 'Customer1',
email: 'ticket-bounce-trigger1@example.com',
active: true,
roles: roles,
preferences: {},
updated_by_id: 1,
created_by_id: 1,
)
Trigger.create_or_update(
name: 'auto reply new ticket',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'ticket_customer',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
Trigger.create_or_update(
name: 'auto reply followup',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'update',
},
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'ticket_customer',
'subject' => 'Thanks for your follow up (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
ticket = Ticket.create(
title: 'bounce check',
group: Group.lookup(name: 'Users'),
customer: customer1,
state: Ticket::State.lookup(name: 'new'),
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
article = Ticket::Article.create(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'bounce check',
message_id: '<20150830145601.30.6088xx@edenhofer.zammad.com>',
body: 'some message bounce check',
internal: false,
sender: Ticket::Article::Sender.where(name: 'Agent').first,
type: Ticket::Article::Type.where(name: 'email').first,
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
assert_equal('new', ticket.state.name)
assert_equal(2, ticket.articles.count)
article = Ticket::Article.create(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: customer1.email,
subject: 'bounce check 2',
message_id: '<20150830145601.30.608881@edenhofer.zammad.com>',
body: 'some message bounce check 2',
internal: false,
sender: Ticket::Article::Sender.where(name: 'Agent').first,
type: Ticket::Article::Type.where(name: 'email').first,
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
assert_equal(4, ticket.articles.count)
travel 1.second
email_file_path = Rails.root.join('test', 'data', 'mail', 'mail033-undelivered-mail-returned-to-sender.box')
email_raw_string = File.read(email_file_path)
ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string)
assert_equal(ticket.id, ticket_p.id)
assert_equal('open', ticket_p.state.name)
assert_equal(5, ticket_p.articles.count)
travel_back
ticket.destroy
end
test 'process with bounce trigger email loop check - bounce based blocker' do
roles = Role.where(name: %w[Customer])
customer2 = User.create_or_update(
login: 'ticket-bounce-trigger2@example.com',
firstname: 'Notification',
lastname: 'Customer2',
email: 'ticket-bounce-trigger2@example.com',
active: true,
roles: roles,
preferences: {},
updated_by_id: 1,
created_by_id: 1,
)
Trigger.create_or_update(
name: 'auto reply new ticket',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'ticket_customer',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
Trigger.create_or_update(
name: 'auto reply followup',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'update',
},
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'ticket_customer',
'subject' => 'Thanks for your follow up (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
ticket = Ticket.create(
title: 'bounce check',
group: Group.lookup(name: 'Users'),
customer: customer2,
state: Ticket::State.lookup(name: 'new'),
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
article = Ticket::Article.create(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'bounce check',
message_id: '<20150830145601.30.6088xx@edenhofer.zammad.com>',
body: 'some message bounce check',
internal: false,
sender: Ticket::Article::Sender.where(name: 'Agent').first,
type: Ticket::Article::Type.where(name: 'email').first,
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
assert_equal('new', ticket.state.name)
assert_equal(2, ticket.articles.count)
article = Ticket::Article.create(
ticket_id: ticket.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'bounce check 2',
message_id: '<20170526150141.232.13312@example.zammad.loc>',
body: 'some message bounce check 2',
internal: false,
sender: Ticket::Article::Sender.where(name: 'Agent').first,
type: Ticket::Article::Type.where(name: 'email').first,
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
assert_equal(4, ticket.articles.count)
travel 1.second
email_file_path = Rails.root.join('test', 'data', 'mail', 'mail055.box')
email_raw_string = File.read(email_file_path)
ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string)
assert_equal(ticket.id, ticket_p.id)
assert_equal('open', ticket_p.state.name)
assert_equal(5, ticket_p.articles.count)
travel_back
ticket.destroy
end
end