gitlab-org--gitlab-foss/spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb

247 lines
6.5 KiB
Ruby

# frozen_string_literal: true
RSpec.shared_examples 'a model including Escalatable' do
# rubocop:disable Rails/SaveBang -- Usage of factory symbol as argument causes a false-positive
let_it_be(:escalatable_factory) { factory_from_class(described_class) }
let_it_be(:triggered_escalatable, reload: true) { create(escalatable_factory, :triggered) }
let_it_be(:acknowledged_escalatable, reload: true) { create(escalatable_factory, :acknowledged) }
let_it_be(:resolved_escalatable, reload: true) { create(escalatable_factory, :resolved) }
let_it_be(:ignored_escalatable, reload: true) { create(escalatable_factory, :ignored) }
context 'validations' do
it { is_expected.to validate_presence_of(:status) }
context 'when status is triggered' do
subject { triggered_escalatable }
context 'when resolved_at is blank' do
it { is_expected.to be_valid }
end
context 'when resolved_at is present' do
before do
triggered_escalatable.resolved_at = Time.current
end
it { is_expected.to be_invalid }
end
end
context 'when status is acknowledged' do
subject { acknowledged_escalatable }
context 'when resolved_at is blank' do
it { is_expected.to be_valid }
end
context 'when resolved_at is present' do
before do
acknowledged_escalatable.resolved_at = Time.current
end
it { is_expected.to be_invalid }
end
end
context 'when status is resolved' do
subject { resolved_escalatable }
context 'when resolved_at is blank' do
before do
resolved_escalatable.resolved_at = nil
end
it { is_expected.to be_invalid }
end
context 'when resolved_at is present' do
it { is_expected.to be_valid }
end
end
context 'when status is ignored' do
subject { ignored_escalatable }
context 'when resolved_at is blank' do
it { is_expected.to be_valid }
end
context 'when resolved_at is present' do
before do
ignored_escalatable.resolved_at = Time.current
end
it { is_expected.to be_invalid }
end
end
end
context 'scopes' do
let(:all_escalatables) { described_class.where(id: [triggered_escalatable, acknowledged_escalatable, ignored_escalatable, resolved_escalatable])}
describe '.order_status' do
subject { all_escalatables.order_status(order) }
context 'descending' do
let(:order) { :desc }
# Downward arrow in UI always corresponds to default sort
it { is_expected.to eq([triggered_escalatable, acknowledged_escalatable, resolved_escalatable, ignored_escalatable]) }
end
context 'ascending' do
let(:order) { :asc }
it { is_expected.to eq([ignored_escalatable, resolved_escalatable, acknowledged_escalatable, triggered_escalatable]) }
end
end
end
describe '.status_value' do
using RSpec::Parameterized::TableSyntax
where(:status, :status_value) do
:triggered | 0
:acknowledged | 1
:resolved | 2
:ignored | 3
:unknown | nil
end
with_them do
it 'returns status value by its name' do
expect(described_class.status_value(status)).to eq(status_value)
end
end
end
describe '.status_name' do
using RSpec::Parameterized::TableSyntax
where(:raw_status, :status) do
0 | :triggered
1 | :acknowledged
2 | :resolved
3 | :ignored
-1 | nil
end
with_them do
it 'returns status name by its values' do
expect(described_class.status_name(raw_status)).to eq(status)
end
end
end
describe '#trigger' do
subject { escalatable.trigger }
context 'when escalatable is in triggered state' do
let(:escalatable) { triggered_escalatable }
it 'does not change the escalatable status' do
expect { subject }.not_to change { escalatable.reload.status }
end
end
context 'when escalatable is not in triggered state' do
let(:escalatable) { resolved_escalatable }
it 'changes the escalatable status to triggered' do
expect { subject }.to change { escalatable.triggered? }.to(true)
end
it 'resets resolved at' do
expect { subject }.to change { escalatable.reload.resolved_at }.to nil
end
end
end
describe '#acknowledge' do
subject { escalatable.acknowledge }
let(:escalatable) { resolved_escalatable }
it 'changes the escalatable status to acknowledged' do
expect { subject }.to change { escalatable.acknowledged? }.to(true)
end
it 'resets ended at' do
expect { subject }.to change { escalatable.reload.resolved_at }.to nil
end
end
describe '#resolve' do
let!(:resolved_at) { Time.current }
subject do
escalatable.resolved_at = resolved_at
escalatable.resolve
end
context 'when escalatable is already resolved' do
let(:escalatable) { resolved_escalatable }
it 'does not change the escalatable status' do
expect { subject }.not_to change { resolved_escalatable.reload.status }
end
end
context 'when escalatable is not resolved' do
let(:escalatable) { triggered_escalatable }
it 'changes escalatable status to "resolved"' do
expect { subject }.to change { escalatable.resolved? }.to(true)
end
end
end
describe '#ignore' do
subject { escalatable.ignore }
let(:escalatable) { resolved_escalatable }
it 'changes the escalatable status to ignored' do
expect { subject }.to change { escalatable.ignored? }.to(true)
end
it 'resets ended at' do
expect { subject }.to change { escalatable.reload.resolved_at }.to nil
end
end
describe '#status_event_for' do
using RSpec::Parameterized::TableSyntax
where(:for_status, :event) do
:triggered | :trigger
'triggered' | :trigger
:acknowledged | :acknowledge
'acknowledged' | :acknowledge
:resolved | :resolve
'resolved' | :resolve
:ignored | :ignore
'ignored' | :ignore
:unknown | nil
nil | nil
'' | nil
1 | nil
end
with_them do
let(:escalatable) { build(escalatable_factory) }
it 'returns event by status name' do
expect(escalatable.status_event_for(for_status)).to eq(event)
end
end
end
private
def factory_from_class(klass)
klass.name.underscore.tr('/', '_')
end
end
# rubocop:enable Rails/SaveBang