# frozen_string_literal: true require 'spec_helper' describe Gitlab::Alerting::Alert do let_it_be(:project) { create(:project) } let(:alert) { build(:alerting_alert, project: project, payload: payload) } let(:payload) { {} } shared_context 'gitlab alert' do let(:gitlab_alert_id) { gitlab_alert.prometheus_metric_id.to_s } let!(:gitlab_alert) { create(:prometheus_alert, project: project) } before do payload['labels'] = { 'gitlab_alert_id' => gitlab_alert_id } end end shared_examples 'invalid alert' do it 'is invalid' do expect(alert).not_to be_valid end end shared_examples 'parse payload' do |*pairs| context 'without payload' do it { is_expected.to be_nil } end pairs.each do |pair| context "with #{pair}" do let(:value) { 'some value' } before do section, name = pair.split('/') payload[section] = { name => value } end it { is_expected.to eq(value) } end end end describe '#gitlab_alert' do subject { alert.gitlab_alert } context 'without payload' do it { is_expected.to be_nil } end context 'with gitlab alert' do include_context 'gitlab alert' it { is_expected.to eq(gitlab_alert) } end context 'with unknown gitlab alert' do include_context 'gitlab alert' do let(:gitlab_alert_id) { 'unknown' } end it { is_expected.to be_nil } end end describe '#title' do subject { alert.title } it_behaves_like 'parse payload', 'annotations/title', 'annotations/summary', 'labels/alertname' context 'with gitlab alert' do include_context 'gitlab alert' context 'with annotations/title' do let(:value) { 'annotation title' } before do payload['annotations'] = { 'title' => value } end it { is_expected.to eq(gitlab_alert.title) } end end end describe '#description' do subject { alert.description } it_behaves_like 'parse payload', 'annotations/description' end describe '#annotations' do subject { alert.annotations } context 'without payload' do it { is_expected.to eq([]) } end context 'with payload' do before do payload['annotations'] = { 'foo' => 'value1', 'bar' => 'value2' } end it 'parses annotations' do expect(subject.size).to eq(2) expect(subject.map(&:label)).to eq(%w[foo bar]) expect(subject.map(&:value)).to eq(%w[value1 value2]) end end end describe '#environment' do subject { alert.environment } context 'without gitlab_alert' do it { is_expected.to be_nil } end context 'with gitlab alert' do include_context 'gitlab alert' it { is_expected.to eq(gitlab_alert.environment) } end end describe '#starts_at' do subject { alert.starts_at } context 'with empty startsAt' do before do payload['startsAt'] = nil end it { is_expected.to be_nil } end context 'with invalid startsAt' do before do payload['startsAt'] = 'invalid' end it { is_expected.to be_nil } end context 'with payload' do let(:time) { Time.now.change(usec: 0) } before do payload['startsAt'] = time.rfc3339 end it { is_expected.to eq(time) } end end describe '#full_query' do using RSpec::Parameterized::TableSyntax subject { alert.full_query } where(:generator_url, :expected_query) do nil | nil 'http://localhost' | nil 'invalid url' | nil 'http://localhost:9090/graph?g1.expr=vector%281%29' | nil 'http://localhost:9090/graph?g0.expr=vector%281%29' | 'vector(1)' end with_them do before do payload['generatorURL'] = generator_url end it { is_expected.to eq(expected_query) } end context 'with gitlab alert' do include_context 'gitlab alert' before do payload['generatorURL'] = 'http://localhost:9090/graph?g0.expr=vector%281%29' end it { is_expected.to eq(gitlab_alert.full_query) } end end describe '#alert_markdown' do subject { alert.alert_markdown } it_behaves_like 'parse payload', 'annotations/gitlab_incident_markdown' end describe '#valid?' do before do payload.update( 'annotations' => { 'title' => 'some title' }, 'startsAt' => Time.now.rfc3339 ) end subject { alert } it { is_expected.to be_valid } context 'without project' do # Redefine to prevent: # project is a NilClass - rspec-set works with ActiveRecord models only let(:alert) { build(:alerting_alert, project: nil, payload: payload) } it { is_expected.not_to be_valid } end context 'without starts_at' do before do payload['startsAt'] = nil end it { is_expected.not_to be_valid } end end end