Welcome to mirror list, hosted at ThFree Co, Russian Federation.

project_reference_filter_spec.rb « references « filter « banzai « lib « spec - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d88e262883f40d093938756d79d720d053170d13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Banzai::Filter::References::ProjectReferenceFilter do
  include FilterSpecHelper

  def invalidate_reference(reference)
    "#{reference.reverse}"
  end

  def get_reference(project)
    project.to_reference
  end

  let(:project) { create(:project, :public) }
  subject { project }

  let(:subject_name) { "project" }
  let(:reference) { get_reference(project) }

  it_behaves_like 'user reference or project reference'

  it 'ignores invalid projects' do
    exp = act = "Hey #{invalidate_reference(reference)}"

    expect(reference_filter(act).to_html).to eq(CGI.escapeHTML(exp))
  end

  context 'when invalid reference strings are very long' do
    shared_examples_for 'fails fast' do |ref_string|
      it 'fails fast for long strings' do
        # took well under 1 second in CI https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/3267#note_172824
        expect do
          Timeout.timeout(3.seconds) { reference_filter(ref_string).to_html }
        end.not_to raise_error
      end
    end

    it_behaves_like 'fails fast', 'A' * 50000
    it_behaves_like 'fails fast', '/a' * 50000
  end

  it 'allows references with text after the > character' do
    doc = reference_filter("Hey #{reference}foo")
    expect(doc.css('a').first.attr('href')).to eq urls.project_url(subject)
  end

  %w(pre code a style).each do |elem|
    it "ignores valid references contained inside '#{elem}' element" do
      exp = act = "<#{elem}>Hey #{CGI.escapeHTML(reference)}</#{elem}>"
      expect(reference_filter(act).to_html).to eq exp
    end
  end

  it 'includes default classes' do
    doc = reference_filter("Hey #{reference}")
    expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project has-tooltip'
  end

  context 'in group context' do
    let(:group) { create(:group) }
    let(:project) { create(:project, group: group) }

    let(:nested_group) { create(:group, :nested) }
    let(:nested_project) { create(:project, group: nested_group) }

    it 'supports mentioning a project' do
      reference = get_reference(project)
      doc = reference_filter("Hey #{reference}")

      expect(doc.css('a').first.attr('href')).to eq urls.project_url(project)
    end

    it 'supports mentioning a project in a nested group' do
      reference = get_reference(nested_project)
      doc = reference_filter("Hey #{reference}")

      expect(doc.css('a').first.attr('href')).to eq urls.project_url(nested_project)
    end
  end

  describe '#projects_hash' do
    it 'returns a Hash containing all Projects' do
      document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
      filter = described_class.new(document, project: project)

      expect(filter.send(:projects_hash)).to eq({ project.full_path => project })
    end
  end

  describe '#projects' do
    it 'returns the projects mentioned in a document' do
      document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
      filter = described_class.new(document, project: project)

      expect(filter.send(:projects)).to eq([project.full_path])
    end
  end

  context 'checking N+1' do
    let_it_be(:normal_project)           { create(:project, :public) }
    let_it_be(:group)                    { create(:group) }
    let_it_be(:group_project)            { create(:project, group: group) }
    let_it_be(:nested_group)             { create(:group, :nested) }
    let_it_be(:nested_project)           { create(:project, group: nested_group) }
    let_it_be(:normal_project_reference) { get_reference(normal_project) }
    let_it_be(:group_project_reference)  { get_reference(group_project) }
    let_it_be(:nested_project_reference) { get_reference(nested_project) }

    it 'does not have N+1 per multiple project references', :use_sql_query_cache do
      markdown = "#{normal_project_reference}"

      # warm up first
      reference_filter(markdown)

      max_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
        reference_filter(markdown)
      end.count

      expect(max_count).to eq 1

      markdown = "#{normal_project_reference} #{invalidate_reference(normal_project_reference)} #{group_project_reference} #{nested_project_reference}"

      expect do
        reference_filter(markdown)
      end.not_to exceed_all_query_limit(max_count)
    end
  end
end