# frozen_string_literal: true require 'spec_helper' RSpec.describe Banzai::Filter::References::AlertReferenceFilter, feature_category: :team_planning do include FilterSpecHelper let_it_be(:project) { create(:project, :public) } let_it_be(:alert) { create(:alert_management_alert, project: project) } let_it_be(:reference) { alert.to_reference } it 'requires project context' do expect { described_class.call('') }.to raise_error(ArgumentError, /:project/) end %w[pre code a style].each do |elem| it "ignores valid references contained inside '#{elem}' element" do exp = act = "<#{elem}>Alert #{reference}" expect(reference_filter(act).to_html).to eq exp end end context 'internal reference' do it 'links to a valid reference' do doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')).to eq alert.details_url end it 'links with adjacent text' do doc = reference_filter("Alert (#{reference}.)") expect(doc.to_html).to match(%r{\(#{Regexp.escape(reference)}\.\)}) end it 'ignores invalid alert IDs' do exp = act = "Alert #{invalidate_reference(reference)}" expect(reference_filter(act).to_html).to eq exp end it 'includes a title attribute' do doc = reference_filter("Alert #{reference}") expect(doc.css('a').first.attr('title')).to eq alert.title end it 'escapes the title attribute' do allow(alert).to receive(:title).and_return(%(">whatever#{Regexp.escape(alert.to_reference(project))}\.\)}) end it 'ignores invalid alert IDs on the referenced project' do act = "See #{invalidate_reference(reference)}" expect(reference_filter(act).to_html).to match(%r{#{Regexp.escape(invalidate_reference(reference))}}) end end context 'group context' do let_it_be(:group) { create(:group) } it 'links to a valid reference' do reference = "#{project.full_path}^alert##{alert.iid}" result = reference_filter("See #{reference}", { project: nil, group: group } ) expect(result.css('a').first.attr('href')).to eq(alert.details_url) end it 'ignores internal references' do exp = act = "See ^alert##{alert.iid}" expect(reference_filter(act, project: nil, group: group).to_html).to eq exp end end context 'checking N+1' do let(:namespace) { create(:namespace) } let(:project2) { create(:project, :public, namespace: namespace) } let(:alert2) { create(:alert_management_alert, project: project2) } let(:alert_reference) { alert.to_reference } let(:alert2_reference) { alert2.to_reference(full: true) } it 'does not have N+1 per multiple references per project', :use_sql_query_cache do markdown = alert_reference.to_s max_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do reference_filter(markdown) end.count expect(max_count).to eq 1 markdown = "#{alert_reference} ^alert#2 ^alert#3 ^alert#4 #{alert2_reference}" # Since we're not batching alert queries across projects, # we have to account for that. # 1 for both projects, 1 for alerts in each project == 3 # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/330359 max_count += 2 expect do reference_filter(markdown) end.not_to exceed_all_query_limit(max_count) end end end