diff options
Diffstat (limited to 'spec/lib/banzai')
5 files changed, 128 insertions, 12 deletions
diff --git a/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb index 7557b9a118d..d7bcebbbe34 100644 --- a/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb @@ -118,7 +118,7 @@ RSpec.describe Banzai::Filter::References::ExternalIssueReferenceFilter do end context "redmine project" do - let_it_be(:service) { create(:redmine_service, project: project) } + let_it_be(:integration) { create(:redmine_integration, project: project) } before do project.update!(issues_enabled: false) @@ -140,7 +140,9 @@ RSpec.describe Banzai::Filter::References::ExternalIssueReferenceFilter do end context "youtrack project" do - let_it_be(:service) { create(:youtrack_service, project: project) } + before_all do + create(:youtrack_integration, project: project) + end before do project.update!(issues_enabled: false) @@ -183,7 +185,7 @@ RSpec.describe Banzai::Filter::References::ExternalIssueReferenceFilter do end context "jira project" do - let_it_be(:service) { create(:jira_service, project: project) } + let_it_be(:service) { create(:jira_integration, project: project) } let(:reference) { issue.to_reference } @@ -215,8 +217,6 @@ RSpec.describe Banzai::Filter::References::ExternalIssueReferenceFilter do context "ewm project" do let_it_be(:integration) { create(:ewm_integration, project: project) } - let(:service) { integration } # TODO: remove when https://gitlab.com/gitlab-org/gitlab/-/issues/330300 is complete - before do project.update!(issues_enabled: false) end diff --git a/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb index dafdc71ce64..f8a00716680 100644 --- a/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb @@ -327,6 +327,7 @@ RSpec.describe Banzai::Filter::References::MilestoneReferenceFilter do it_behaves_like 'String-based single-word references' it_behaves_like 'String-based multi-word references in quotes' it_behaves_like 'referencing a milestone in a link href' + it_behaves_like 'linking to a milestone as the entire link' it_behaves_like 'cross-project / cross-namespace complete reference' it_behaves_like 'cross-project / same-namespace complete reference' it_behaves_like 'cross project shorthand reference' @@ -460,4 +461,76 @@ RSpec.describe Banzai::Filter::References::MilestoneReferenceFilter do include_context 'group milestones' end end + + context 'checking N+1' do + let_it_be(:group) { create(:group) } + let_it_be(:group2) { create(:group) } + let_it_be(:project) { create(:project, :public, namespace: group) } + let_it_be(:project2) { create(:project, :public, namespace: group2) } + let_it_be(:project3) { create(:project, :public) } + let_it_be(:project_milestone) { create(:milestone, project: project) } + let_it_be(:project_milestone2) { create(:milestone, project: project) } + let_it_be(:project2_milestone) { create(:milestone, project: project2) } + let_it_be(:group2_milestone) { create(:milestone, group: group2) } + let_it_be(:project_reference) { "#{project_milestone.to_reference}" } + let_it_be(:project_reference2) { "#{project_milestone2.to_reference}" } + let_it_be(:project2_reference) { "#{project2_milestone.to_reference(full: true)}" } + let_it_be(:group2_reference) { "#{project2.full_path}%\"#{group2_milestone.name}\"" } + + it 'does not have N+1 per multiple references per project', :use_sql_query_cache do + markdown = "#{project_reference}" + control_count = 4 + + expect do + reference_filter(markdown) + end.not_to exceed_all_query_limit(control_count) + + markdown = "#{project_reference} %qwert %werty %ertyu %rtyui #{project_reference2}" + + expect do + reference_filter(markdown) + end.not_to exceed_all_query_limit(control_count) + end + + it 'has N+1 for multiple unique project/group references', :use_sql_query_cache do + markdown = "#{project_reference}" + control_count = 4 + + expect do + reference_filter(markdown, project: project) + end.not_to exceed_all_query_limit(control_count) + + # Since we're not batching milestone queries across projects/groups, + # queries increase when a new project/group is added. + # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/330359 + markdown = "#{project_reference} #{group2_reference}" + control_count += 5 + + expect do + reference_filter(markdown) + end.not_to exceed_all_query_limit(control_count) + + # third reference to already queried project/namespace, nothing extra (no N+1 here) + markdown = "#{project_reference} #{group2_reference} #{project_reference2}" + + expect do + reference_filter(markdown) + end.not_to exceed_all_query_limit(control_count) + + # last reference needs additional queries + markdown = "#{project_reference} #{group2_reference} #{project2_reference} #{project3.full_path}%test_milestone" + control_count += 6 + + expect do + reference_filter(markdown) + end.not_to exceed_all_query_limit(control_count) + + # Use an iid instead of title reference + markdown = "#{project_reference} #{group2_reference} #{project2.full_path}%#{project2_milestone.iid} #{project3.full_path}%test_milestone" + + expect do + reference_filter(markdown) + end.not_to exceed_all_query_limit(control_count) + end + end end diff --git a/spec/lib/banzai/filter/upload_link_filter_spec.rb b/spec/lib/banzai/filter/upload_link_filter_spec.rb index 9ca499be665..eb45a8149c3 100644 --- a/spec/lib/banzai/filter/upload_link_filter_spec.rb +++ b/spec/lib/banzai/filter/upload_link_filter_spec.rb @@ -42,6 +42,12 @@ RSpec.describe Banzai::Filter::UploadLinkFilter do let(:upload_path) { '/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg' } let(:relative_path) { "/#{project.full_path}#{upload_path}" } + it 'preserves original url in data-canonical-src attribute' do + doc = filter(link(upload_path)) + + expect(doc.at_css('a')['data-canonical-src']).to eq(upload_path) + end + context 'to a project upload' do context 'with an absolute URL' do let(:absolute_path) { Gitlab.config.gitlab.url + relative_path } diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb index b5b5349946b..70c7c3c74fb 100644 --- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb +++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb @@ -22,6 +22,24 @@ RSpec.describe Banzai::Filter::WikiLinkFilter do expect(filtered_link.attribute('href').value).to eq('/uploads/a.test') end + describe 'when links are rewritable' do + it "stores original url in the data-canonical-src attribute" do + original_path = "#{repository_upload_folder}/a.jpg" + filtered_elements = filter("<a href='#{original_path}'><img src='#{original_path}'>example</img></a>", wiki: wiki) + + expect(filtered_elements.search('img').first.attribute('data-canonical-src').value).to eq(original_path) + expect(filtered_elements.search('a').first.attribute('data-canonical-src').value).to eq(original_path) + end + end + + describe 'when links are not rewritable' do + it "does not store original url in the data-canonical-src attribute" do + filtered_link = filter("<a href='/uploads/a.test'>Link</a>", wiki: wiki).children[0] + + expect(filtered_link.value?('data-canonical-src')).to eq(false) + end + end + describe 'when links point to the relative wiki path' do it 'does not rewrite links' do path = "#{wiki.wiki_base_path}/#{repository_upload_folder}/a.jpg" diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb index 18d8418ca23..095500cdc53 100644 --- a/spec/lib/banzai/reference_parser/base_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb @@ -78,12 +78,31 @@ RSpec.describe Banzai::ReferenceParser::BaseParser do describe '#referenced_by' do context 'when references_relation is implemented' do - it 'returns a collection of objects' do - links = Nokogiri::HTML.fragment("<a data-foo='#{user.id}'></a>") - .children + context 'and ids_only is set to false' do + it 'returns a collection of objects' do + links = Nokogiri::HTML.fragment("<a data-foo='#{user.id}'></a>") + .children - expect(subject).to receive(:references_relation).and_return(User) - expect(subject.referenced_by(links)).to eq([user]) + expect(subject).to receive(:references_relation).and_return(User) + expect(subject.referenced_by(links)).to eq([user]) + end + end + + context 'and ids_only is set to true' do + it 'returns a collection of id values without performing a db query' do + links = Nokogiri::HTML.fragment("<a data-foo='1'></a><a data-foo='2'></a>").children + + expect(subject).not_to receive(:references_relation) + expect(subject.referenced_by(links, ids_only: true)).to eq(%w(1 2)) + end + + context 'and the html fragment does not contain any attributes' do + it 'returns an empty array' do + links = Nokogiri::HTML.fragment("no links").children + + expect(subject.referenced_by(links, ids_only: true)).to eq([]) + end + end end end @@ -188,7 +207,7 @@ RSpec.describe Banzai::ReferenceParser::BaseParser do dummy = Class.new(described_class) do self.reference_type = :test - def gather_references(nodes) + def gather_references(nodes, ids_only: false) nodes end end @@ -222,7 +241,7 @@ RSpec.describe Banzai::ReferenceParser::BaseParser do nodes.select { |n| n.id > 5 } end - def referenced_by(nodes) + def referenced_by(nodes, ids_only: false) nodes.map(&:id) end end |