Просмотр исходного кода

Refactoring: Migrate ticket_escalation_test to RSpec

Ryan Lue 6 лет назад
Родитель
Сommit
74e1fa8722
3 измененных файлов с 196 добавлено и 225 удалено
  1. 37 0
      spec/factories/calendar.rb
  2. 159 0
      spec/models/ticket_spec.rb
  3. 0 225
      test/unit/ticket_escalation_test.rb

+ 37 - 0
spec/factories/calendar.rb

@@ -4,6 +4,7 @@ FactoryBot.define do
     timezone        { 'Europe/Berlin' }
     default         { true }
     ical_url        { nil }
+
     business_hours do
       {
         mon: {
@@ -36,7 +37,43 @@ FactoryBot.define do
         }
       }
     end
+
     created_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

+ 159 - 0
spec/models/ticket_spec.rb

@@ -380,6 +380,165 @@ RSpec.describe Ticket, type: :model do
         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
 
   describe 'Associations:' do

+ 0 - 225
test/unit/ticket_escalation_test.rb

@@ -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