Refactoring: Migrate ticket_escalation_test to RSpec
This commit is contained in:
parent
48cccd186b
commit
74e1fa8722
3 changed files with 196 additions and 225 deletions
|
@ -4,6 +4,7 @@ FactoryBot.define do
|
||||||
timezone { 'Europe/Berlin' }
|
timezone { 'Europe/Berlin' }
|
||||||
default { true }
|
default { true }
|
||||||
ical_url { nil }
|
ical_url { nil }
|
||||||
|
|
||||||
business_hours do
|
business_hours do
|
||||||
{
|
{
|
||||||
mon: {
|
mon: {
|
||||||
|
@ -36,7 +37,43 @@ FactoryBot.define do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
created_by_id { 1 }
|
created_by_id { 1 }
|
||||||
updated_by_id { 1 }
|
updated_by_id { 1 }
|
||||||
|
|
||||||
|
trait :'24/7' do
|
||||||
|
business_hours do
|
||||||
|
{
|
||||||
|
mon: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
tue: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
wed: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
thu: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
fri: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
sat: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
sun: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -380,6 +380,165 @@ RSpec.describe Ticket, type: :model do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#escalation_at' do
|
||||||
|
before { travel_to(Time.current) } # freeze time
|
||||||
|
let(:sla) { create(:sla, calendar: calendar, first_response_time: 60, update_time: 180, solution_time: 240) }
|
||||||
|
let(:calendar) { create(:calendar, :'24/7') }
|
||||||
|
|
||||||
|
context 'with no SLAs in the system' do
|
||||||
|
it 'defaults to nil' do
|
||||||
|
expect(ticket.escalation_at).to be(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with an SLA in the system' do
|
||||||
|
before { sla } # create sla
|
||||||
|
|
||||||
|
it 'is set based on SLA’s #first_response_time' do
|
||||||
|
expect(ticket.escalation_at.to_i)
|
||||||
|
.to eq(1.hour.from_now.to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'after first agent’s response' do
|
||||||
|
before { ticket } # create ticket
|
||||||
|
let(:article) { create(:ticket_article, ticket: ticket, sender_name: 'Agent') }
|
||||||
|
|
||||||
|
it 'is updated based on the SLA’s #update_time' do
|
||||||
|
travel(1.minute) # time is frozen: if we don't travel forward, pre- and post-update values will be the same
|
||||||
|
|
||||||
|
expect { article }
|
||||||
|
.to change { ticket.reload.escalation_at.to_i }
|
||||||
|
.to eq(3.hours.from_now.to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when new #update_time is later than original #solution_time' do
|
||||||
|
it 'is updated based on the original #solution_time' do
|
||||||
|
travel(2.hours) # time is frozen: if we don't travel forward, pre- and post-update values will be the same
|
||||||
|
|
||||||
|
expect { article }
|
||||||
|
.to change { ticket.reload.escalation_at.to_i }
|
||||||
|
.to eq(4.hours.after(ticket.created_at).to_i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when updated after an SLA has been added to the system' do
|
||||||
|
before { ticket } # create ticket
|
||||||
|
before { sla } # create sla
|
||||||
|
|
||||||
|
it 'is updated based on the new SLA’s #first_response_time' do
|
||||||
|
expect { ticket.save! }
|
||||||
|
.to change { ticket.escalation_at.to_i }.from(0).to(1.hour.from_now.to_i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when updated after all SLAs have been removed from the system' do
|
||||||
|
before { sla } # create sla
|
||||||
|
before { ticket } # create ticket
|
||||||
|
before { sla.destroy }
|
||||||
|
|
||||||
|
it 'is set to nil' do
|
||||||
|
expect { ticket.save! }
|
||||||
|
.to change { ticket.escalation_at }.to(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#first_response_escalation_at' do
|
||||||
|
before { travel_to(Time.current) } # freeze time
|
||||||
|
let(:sla) { create(:sla, calendar: calendar, first_response_time: 60, update_time: 180, solution_time: 240) }
|
||||||
|
let(:calendar) { create(:calendar, :'24/7') }
|
||||||
|
|
||||||
|
context 'with no SLAs in the system' do
|
||||||
|
it 'defaults to nil' do
|
||||||
|
expect(ticket.first_response_escalation_at).to be(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with an SLA in the system' do
|
||||||
|
before { sla } # create sla
|
||||||
|
|
||||||
|
it 'is set based on SLA’s #first_response_time' do
|
||||||
|
expect(ticket.first_response_escalation_at.to_i)
|
||||||
|
.to eq(1.hour.from_now.to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'after first agent’s response' do
|
||||||
|
before { ticket } # create ticket
|
||||||
|
let(:article) { create(:ticket_article, ticket: ticket, sender_name: 'Agent') }
|
||||||
|
|
||||||
|
it 'does not change' do
|
||||||
|
expect { article }.not_to change { ticket.first_response_escalation_at }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#update_escalation_at' do
|
||||||
|
before { travel_to(Time.current) } # freeze time
|
||||||
|
let(:sla) { create(:sla, calendar: calendar, first_response_time: 60, update_time: 180, solution_time: 240) }
|
||||||
|
let(:calendar) { create(:calendar, :'24/7') }
|
||||||
|
|
||||||
|
context 'with no SLAs in the system' do
|
||||||
|
it 'defaults to nil' do
|
||||||
|
expect(ticket.update_escalation_at).to be(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with an SLA in the system' do
|
||||||
|
before { sla } # create sla
|
||||||
|
|
||||||
|
it 'is set based on SLA’s #update_time' do
|
||||||
|
expect(ticket.update_escalation_at.to_i)
|
||||||
|
.to eq(3.hours.from_now.to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'after first agent’s response' do
|
||||||
|
before { ticket } # create ticket
|
||||||
|
let(:article) { create(:ticket_article, ticket: ticket, sender_name: 'Agent') }
|
||||||
|
|
||||||
|
it 'is updated based on the SLA’s #update_time' do
|
||||||
|
travel(1.minute) # time is frozen: if we don't travel forward, pre- and post-update values will be the same
|
||||||
|
|
||||||
|
expect { article }
|
||||||
|
.to change { ticket.reload.update_escalation_at.to_i }
|
||||||
|
.to(3.hours.from_now.to_i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#close_escalation_at' do
|
||||||
|
before { travel_to(Time.current) } # freeze time
|
||||||
|
let(:sla) { create(:sla, calendar: calendar, first_response_time: 60, update_time: 180, solution_time: 240) }
|
||||||
|
let(:calendar) { create(:calendar, :'24/7') }
|
||||||
|
|
||||||
|
context 'with no SLAs in the system' do
|
||||||
|
it 'defaults to nil' do
|
||||||
|
expect(ticket.close_escalation_at).to be(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with an SLA in the system' do
|
||||||
|
before { sla } # create sla
|
||||||
|
|
||||||
|
it 'is set based on SLA’s #solution_time' do
|
||||||
|
expect(ticket.close_escalation_at.to_i)
|
||||||
|
.to eq(4.hours.from_now.to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'after first agent’s response' do
|
||||||
|
before { ticket } # create ticket
|
||||||
|
let(:article) { create(:ticket_article, ticket: ticket, sender_name: 'Agent') }
|
||||||
|
|
||||||
|
it 'does not change' do
|
||||||
|
expect { article }.not_to change { ticket.close_escalation_at }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'Associations:' do
|
describe 'Associations:' do
|
||||||
|
|
|
@ -1,225 +0,0 @@
|
||||||
require 'test_helper'
|
|
||||||
|
|
||||||
class TicketEscalationTest < ActiveSupport::TestCase
|
|
||||||
test 'ticket create' do
|
|
||||||
ticket = Ticket.new(
|
|
||||||
title: 'some value 123',
|
|
||||||
group: Group.lookup(name: 'Users'),
|
|
||||||
customer_id: 2,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
ticket.save!
|
|
||||||
assert(ticket, 'ticket created')
|
|
||||||
assert_not(ticket.escalation_at)
|
|
||||||
assert_not(ticket.has_changes_to_save?)
|
|
||||||
|
|
||||||
article = Ticket::Article.create!(
|
|
||||||
ticket_id: ticket.id,
|
|
||||||
type_id: Ticket::Article::Type.find_by(name: 'note').id,
|
|
||||||
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
|
|
||||||
body: 'some body',
|
|
||||||
internal: false,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
assert_not(article.has_changes_to_save?)
|
|
||||||
assert_not(ticket.has_changes_to_save?)
|
|
||||||
|
|
||||||
calendar = Calendar.create_or_update(
|
|
||||||
name: 'Escalation Test',
|
|
||||||
timezone: 'Europe/Berlin',
|
|
||||||
business_hours: {
|
|
||||||
mon: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
tue: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
wed: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
thu: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
fri: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
sat: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
sun: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: true,
|
|
||||||
ical_url: nil,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
|
|
||||||
sla = Sla.create_or_update(
|
|
||||||
name: 'test sla 1',
|
|
||||||
condition: {
|
|
||||||
'ticket.title' => {
|
|
||||||
operator: 'contains',
|
|
||||||
value: 'some value 123',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
first_response_time: 60,
|
|
||||||
update_time: 180,
|
|
||||||
solution_time: 240,
|
|
||||||
calendar_id: calendar.id,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
|
|
||||||
ticket = Ticket.new(
|
|
||||||
title: 'some value 123',
|
|
||||||
group: Group.lookup(name: 'Users'),
|
|
||||||
customer_id: 2,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
ticket.save!
|
|
||||||
assert(ticket, 'ticket created')
|
|
||||||
ticket_escalation_at = ticket.escalation_at
|
|
||||||
assert(ticket.escalation_at)
|
|
||||||
assert_not(ticket.has_changes_to_save?)
|
|
||||||
|
|
||||||
article = Ticket::Article.create!(
|
|
||||||
ticket_id: ticket.id,
|
|
||||||
type_id: Ticket::Article::Type.find_by(name: 'note').id,
|
|
||||||
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
|
|
||||||
body: 'some body',
|
|
||||||
internal: false,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
assert_not(article.has_changes_to_save?)
|
|
||||||
assert_not(ticket.has_changes_to_save?)
|
|
||||||
|
|
||||||
travel 1.second
|
|
||||||
|
|
||||||
sla.first_response_time = 30
|
|
||||||
sla.save!
|
|
||||||
|
|
||||||
ticket.save!
|
|
||||||
assert_not(ticket.has_changes_to_save?)
|
|
||||||
assert(ticket.escalation_at)
|
|
||||||
assert_in_delta((ticket_escalation_at - 30.minutes).to_i, ticket.escalation_at.to_i, 90)
|
|
||||||
|
|
||||||
sla.destroy!
|
|
||||||
calendar.destroy!
|
|
||||||
|
|
||||||
ticket.save!
|
|
||||||
assert_not(ticket.has_changes_to_save?)
|
|
||||||
assert_not(ticket.escalation_at)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
test 'email process and reply via email' do
|
|
||||||
|
|
||||||
calendar = Calendar.create_or_update(
|
|
||||||
name: 'Escalation Test',
|
|
||||||
timezone: 'Europe/Berlin',
|
|
||||||
business_hours: {
|
|
||||||
mon: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
tue: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
wed: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
thu: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
fri: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
sat: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
sun: {
|
|
||||||
active: true,
|
|
||||||
timeframes: [ ['00:00', '23:59'] ]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: true,
|
|
||||||
ical_url: nil,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
|
|
||||||
sla = Sla.create_or_update(
|
|
||||||
name: 'test sla 1',
|
|
||||||
condition: {
|
|
||||||
'ticket.title' => {
|
|
||||||
operator: 'contains',
|
|
||||||
value: 'some value 123',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
first_response_time: 60,
|
|
||||||
update_time: 180,
|
|
||||||
solution_time: 240,
|
|
||||||
calendar_id: calendar.id,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
|
|
||||||
email = "From: Bob Smith <customer@example.com>
|
|
||||||
To: zammad@example.com
|
|
||||||
Subject: some value 123
|
|
||||||
|
|
||||||
Some Text"
|
|
||||||
|
|
||||||
ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email)
|
|
||||||
ticket_p.reload
|
|
||||||
assert(ticket_p.escalation_at)
|
|
||||||
assert_in_delta(ticket_p.first_response_escalation_at.to_i, (ticket_p.created_at + 1.hour).to_i, 90)
|
|
||||||
assert_in_delta(ticket_p.update_escalation_at.to_i, (ticket_p.created_at + 3.hours).to_i, 90)
|
|
||||||
assert_in_delta(ticket_p.close_escalation_at.to_i, (ticket_p.created_at + 4.hours).to_i, 90)
|
|
||||||
assert_in_delta(ticket_p.escalation_at.to_i, (ticket_p.created_at + 1.hour).to_i, 90)
|
|
||||||
|
|
||||||
travel 3.hours
|
|
||||||
article = nil
|
|
||||||
|
|
||||||
ticket_p.with_lock do
|
|
||||||
article = Ticket::Article.create!(
|
|
||||||
ticket_id: ticket_p.id,
|
|
||||||
from: 'some_sender@example.com',
|
|
||||||
to: 'some_recipient@example.com',
|
|
||||||
subject: 'some subject',
|
|
||||||
message_id: 'some@id',
|
|
||||||
body: 'some message',
|
|
||||||
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,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
ticket_p.reload
|
|
||||||
assert_in_delta(ticket_p.first_response_escalation_at.to_i, (ticket_p.created_at + 1.hour).to_i, 90)
|
|
||||||
assert_in_delta(ticket_p.update_escalation_at.to_i, (ticket_p.last_contact_agent_at + 3.hours).to_i, 90)
|
|
||||||
assert_in_delta(ticket_p.close_escalation_at.to_i, (ticket_p.created_at + 4.hours).to_i, 90)
|
|
||||||
assert_in_delta(ticket_p.escalation_at.to_i, (ticket_p.created_at + 4.hours).to_i, 90)
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in a new issue