diff options
author | Lin Jen-Shin <godfat@godfat.org> | 2016-12-06 20:53:07 +0800 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2016-12-06 20:53:07 +0800 |
commit | d6287ab230d1507893895397e759eaf38377cb18 (patch) | |
tree | 76030a4c6599c04245b1d13ed062dd299a568a01 /spec/lib | |
parent | 28102ec28e1ef3d3203db3d05aa89ab3da234e70 (diff) | |
parent | e27fa5bc14382abb4383ad5df2867f23bf9f1092 (diff) | |
download | gitlab-ce-d6287ab230d1507893895397e759eaf38377cb18.tar.gz |
Merge remote-tracking branch 'upstream/master' into feature/1376-allow-write-access-deploy-keys
* upstream/master: (488 commits)
Merge branch 'issue_25064' into 'security'
It's secret variables, not secure
Fix dead links, add example of debug trace output, simplify titles
Authorize users into imported GitLab project
Document button secondary states. Update icons and color section
Remove unused votes.scss
Remove unused errors css
Fixed MR widget content wrapping for XS viewports
NIGNX -> Nginx
Use pry-byebug instead byebug
Fixed influence from other specs.
Accept `issue new` as command to create an issue
Update paranoia from 2.1.4 to 2.2.0.
Use the pagination helper in the API
Added changelog for #25221
Fixed top margin for Builds page status header information
Satisfied eslint
Fix compatibility with Internet Explorer 11 for merge requests
change the date label to match the date used
fix gfm doc typo about two spaces for next line transfer
...
Diffstat (limited to 'spec/lib')
29 files changed, 1043 insertions, 208 deletions
diff --git a/spec/lib/banzai/filter/abstract_link_filter_spec.rb b/spec/lib/banzai/filter/abstract_link_filter_spec.rb index 1ee31a603e4..70a87fbc01e 100644 --- a/spec/lib/banzai/filter/abstract_link_filter_spec.rb +++ b/spec/lib/banzai/filter/abstract_link_filter_spec.rb @@ -5,7 +5,7 @@ describe Banzai::Filter::AbstractReferenceFilter do describe '#references_per_project' do it 'returns a Hash containing references grouped per project paths' do - doc = Nokogiri::HTML.fragment("#1 #{project.to_reference}#2") + doc = Nokogiri::HTML.fragment("#1 #{project.path_with_namespace}#2") filter = described_class.new(doc, project: project) expect(filter).to receive(:object_class).exactly(4).times.and_return(Issue) @@ -14,7 +14,7 @@ describe Banzai::Filter::AbstractReferenceFilter do refs = filter.references_per_project expect(refs).to be_an_instance_of(Hash) - expect(refs[project.to_reference]).to eq(Set.new(%w[1 2])) + expect(refs[project.path_with_namespace]).to eq(Set.new(%w[1 2])) end end diff --git a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb index e6c90ad87ee..9703e2315b8 100644 --- a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb @@ -59,9 +59,7 @@ describe Banzai::Filter::CommitRangeReferenceFilter, lib: true do it 'ignores invalid commit IDs' do exp = act = "See #{commit1.id.reverse}...#{commit2.id}" - expect(project).to receive(:valid_repo?).and_return(true) - expect(project.repository).to receive(:commit).with(commit1.id.reverse) - expect(project.repository).to receive(:commit).with(commit2.id) + allow(project.repository).to receive(:commit).with(commit1.id.reverse) expect(reference_filter(act).to_html).to eq exp end @@ -100,14 +98,44 @@ describe Banzai::Filter::CommitRangeReferenceFilter, lib: true do end end - context 'cross-project reference' do - let(:namespace) { create(:namespace, name: 'cross-reference') } - let(:project2) { create(:project, :public, namespace: namespace) } - let(:reference) { range.to_reference(project) } + context 'cross-project / cross-namespace complete reference' do + let(:project2) { create(:project, :public) } + let(:reference) { "#{project2.path_with_namespace}@#{commit1.id}...#{commit2.id}" } - before do - range.project = project2 + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_compare_url(project2.namespace, project2, range.to_param) + end + + it 'link has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.css('a').first.text). + to eql("#{project2.path_with_namespace}@#{commit1.short_id}...#{commit2.short_id}") + end + + it 'has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.text).to eql("Fixed (#{project2.path_with_namespace}@#{commit1.short_id}...#{commit2.short_id}.)") + end + + it 'ignores invalid commit IDs on the referenced project' do + exp = act = "Fixed #{project2.path_with_namespace}@#{commit1.id.reverse}...#{commit2.id}" + expect(reference_filter(act).to_html).to eq exp + + exp = act = "Fixed #{project2.path_with_namespace}@#{commit1.id}...#{commit2.id.reverse}" + expect(reference_filter(act).to_html).to eq exp end + end + + context 'cross-project / same-namespace complete reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:project, :public, namespace: namespace) } + let(:project2) { create(:project, :public, path: "same-namespace", namespace: namespace) } + let(:reference) { "#{project2.path}@#{commit1.id}...#{commit2.id}" } it 'links to a valid reference' do doc = reference_filter("See #{reference}") @@ -116,24 +144,65 @@ describe Banzai::Filter::CommitRangeReferenceFilter, lib: true do to eq urls.namespace_project_compare_url(project2.namespace, project2, range.to_param) end - it 'links with adjacent text' do + it 'link has valid text' do doc = reference_filter("Fixed (#{reference}.)") - exp = Regexp.escape("#{project2.to_reference}@#{range.reference_link_text}") - expect(doc.to_html).to match(/\(<a.+>#{exp}<\/a>\.\)/) + expect(doc.css('a').first.text). + to eql("#{project2.path}@#{commit1.short_id}...#{commit2.short_id}") + end + + it 'has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.text).to eql("Fixed (#{project2.path}@#{commit1.short_id}...#{commit2.short_id}.)") end it 'ignores invalid commit IDs on the referenced project' do - exp = act = "Fixed #{project2.to_reference}@#{commit1.id.reverse}...#{commit2.id}" + exp = act = "Fixed #{project2.path}@#{commit1.id.reverse}...#{commit2.id}" expect(reference_filter(act).to_html).to eq exp - exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}" + exp = act = "Fixed #{project2.path}@#{commit1.id}...#{commit2.id.reverse}" + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'cross-project shorthand reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:project, :public, namespace: namespace) } + let(:project2) { create(:project, :public, path: "same-namespace", namespace: namespace) } + let(:reference) { "#{project2.path}@#{commit1.id}...#{commit2.id}" } + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_compare_url(project2.namespace, project2, range.to_param) + end + + it 'link has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.css('a').first.text). + to eql("#{project2.path}@#{commit1.short_id}...#{commit2.short_id}") + end + + it 'has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.text).to eql("Fixed (#{project2.path}@#{commit1.short_id}...#{commit2.short_id}.)") + end + + it 'ignores invalid commit IDs on the referenced project' do + exp = act = "Fixed #{project2.path}@#{commit1.id.reverse}...#{commit2.id}" + expect(reference_filter(act).to_html).to eq exp + + exp = act = "Fixed #{project2.path}@#{commit1.id}...#{commit2.id.reverse}" expect(reference_filter(act).to_html).to eq exp end end context 'cross-project URL reference' do - let(:namespace) { create(:namespace, name: 'cross-reference') } + let(:namespace) { create(:namespace) } let(:project2) { create(:project, :public, namespace: namespace) } let(:range) { CommitRange.new("#{commit1.id}...master", project) } let(:reference) { urls.namespace_project_compare_url(project2.namespace, project2, from: commit1.id, to: 'master') } diff --git a/spec/lib/banzai/filter/commit_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_reference_filter_spec.rb index e0f08282551..2e6dcc3a434 100644 --- a/spec/lib/banzai/filter/commit_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/commit_reference_filter_spec.rb @@ -41,6 +41,7 @@ describe Banzai::Filter::CommitReferenceFilter, lib: true do it 'links with adjacent text' do doc = reference_filter("See (#{reference}.)") + expect(doc.to_html).to match(/\(<a.+>#{commit.short_id}<\/a>\.\)/) end @@ -48,8 +49,6 @@ describe Banzai::Filter::CommitReferenceFilter, lib: true do invalid = invalidate_reference(reference) exp = act = "See #{invalid}" - expect(project).to receive(:valid_repo?).and_return(true) - expect(project.repository).to receive(:commit).with(invalid) expect(reference_filter(act).to_html).to eq exp end @@ -95,34 +94,85 @@ describe Banzai::Filter::CommitReferenceFilter, lib: true do end end - context 'cross-project reference' do - let(:namespace) { create(:namespace, name: 'cross-reference') } + context 'cross-project / cross-namespace complete reference' do + let(:namespace) { create(:namespace) } let(:project2) { create(:project, :public, namespace: namespace) } let(:commit) { project2.commit } - let(:reference) { commit.to_reference(project) } + let(:reference) { "#{project2.path_with_namespace}@#{commit.short_id}" } - it 'links to a valid reference' do - doc = reference_filter("See #{reference}") + it 'link has valid text' do + doc = reference_filter("See (#{reference}.)") - expect(doc.css('a').first.attr('href')). - to eq urls.namespace_project_commit_url(project2.namespace, project2, commit.id) + expect(doc.css('a').first.text).to eql("#{project2.path_with_namespace}@#{commit.short_id}") end - it 'links with adjacent text' do - doc = reference_filter("Fixed (#{reference}.)") + it 'has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.text).to eql("See (#{project2.path_with_namespace}@#{commit.short_id}.)") + end + + it 'ignores invalid commit IDs on the referenced project' do + exp = act = "Committed #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'cross-project / same-namespace complete reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, namespace: namespace) } + let(:project2) { create(:project, :public, namespace: namespace) } + let(:commit) { project2.commit } + let(:reference) { "#{project2.path_with_namespace}@#{commit.short_id}" } + + it 'link has valid text' do + doc = reference_filter("See (#{reference}.)") - exp = Regexp.escape(project2.to_reference) - expect(doc.to_html).to match(/\(<a.+>#{exp}@#{commit.short_id}<\/a>\.\)/) + expect(doc.css('a').first.text).to eql("#{project2.path}@#{commit.short_id}") + end + + it 'has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.text).to eql("See (#{project2.path}@#{commit.short_id}.)") end it 'ignores invalid commit IDs on the referenced project' do exp = act = "Committed #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'cross-project shorthand reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, namespace: namespace) } + let(:project2) { create(:project, :public, namespace: namespace) } + let(:commit) { project2.commit } + let(:reference) { "#{project2.path_with_namespace}@#{commit.short_id}" } + + it 'link has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.css('a').first.text).to eql("#{project2.path}@#{commit.short_id}") + end + + it 'has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.text).to eql("See (#{project2.path}@#{commit.short_id}.)") + end + + it 'ignores invalid commit IDs on the referenced project' do + exp = act = "Committed #{invalidate_reference(reference)}" + expect(reference_filter(act).to_html).to eq exp end end context 'cross-project URL reference' do - let(:namespace) { create(:namespace, name: 'cross-reference') } + let(:namespace) { create(:namespace) } let(:project2) { create(:project, :public, namespace: namespace) } let(:commit) { project2.commit } let(:reference) { urls.namespace_project_commit_url(project2.namespace, project2, commit.id) } diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb index 8f0b2db3e8e..456dbac0698 100644 --- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb @@ -8,7 +8,7 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do end let(:project) { create(:empty_project, :public) } - let(:issue) { create(:issue, project: project) } + let(:issue) { create(:issue, project: project) } it 'requires project context' do expect { described_class.call('') }.to raise_error(ArgumentError, /:project/) @@ -24,7 +24,7 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do context 'internal reference' do it_behaves_like 'a reference containing an element node' - let(:reference) { issue.to_reference } + let(:reference) { "##{issue.iid}" } it 'ignores valid references when using non-default tracker' do allow(project).to receive(:default_issues_tracker?).and_return(false) @@ -42,7 +42,7 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do it 'links with adjacent text' do doc = reference_filter("Fixed (#{reference}.)") - expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) + expect(doc.text).to eql("Fixed (#{reference}.)") end it 'ignores invalid issue IDs' do @@ -116,13 +116,56 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do end end - context 'cross-project reference' do + context 'cross-project / cross-namespace complete reference' do it_behaves_like 'a reference containing an element node' - let(:namespace) { create(:namespace, name: 'cross-reference') } + let(:project2) { create(:empty_project, :public) } + let(:issue) { create(:issue, project: project2) } + let(:reference) { "#{project2.path_with_namespace}##{issue.iid}" } + + it 'ignores valid references when cross-reference project uses external tracker' do + expect_any_instance_of(described_class).to receive(:find_object). + with(project2, issue.iid). + and_return(nil) + + exp = act = "Issue #{reference}" + expect(reference_filter(act).to_html).to eq exp + end + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')). + to eq helper.url_for_issue(issue.iid, project2) + end + + it 'link has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.css('a').first.text).to eql("#{project2.path_with_namespace}##{issue.iid}") + end + + it 'has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.text).to eq("Fixed (#{project2.path_with_namespace}##{issue.iid}.)") + end + + it 'ignores invalid issue IDs on the referenced project' do + exp = act = "Fixed #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'cross-project / same-namespace complete reference' do + it_behaves_like 'a reference containing an element node' + + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, :public, namespace: namespace) } let(:project2) { create(:empty_project, :public, namespace: namespace) } let(:issue) { create(:issue, project: project2) } - let(:reference) { issue.to_reference(project) } + let(:reference) { "#{project2.path_with_namespace}##{issue.iid}" } it 'ignores valid references when cross-reference project uses external tracker' do expect_any_instance_of(described_class).to receive(:find_object). @@ -140,9 +183,16 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do to eq helper.url_for_issue(issue.iid, project2) end - it 'links with adjacent text' do + it 'link has valid text' do doc = reference_filter("Fixed (#{reference}.)") - expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) + + expect(doc.css('a').first.text).to eql("#{project2.path}##{issue.iid}") + end + + it 'has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.text).to eq("Fixed (#{project2.path}##{issue.iid}.)") end it 'ignores invalid issue IDs on the referenced project' do @@ -150,9 +200,47 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do expect(reference_filter(act).to_html).to eq exp end + end + + context 'cross-project shorthand reference' do + it_behaves_like 'a reference containing an element node' - it 'ignores out-of-bounds issue IDs on the referenced project' do - exp = act = "Fixed ##{Gitlab::Database::MAX_INT_VALUE + 1}" + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, :public, namespace: namespace) } + let(:project2) { create(:empty_project, :public, namespace: namespace) } + let(:issue) { create(:issue, project: project2) } + let(:reference) { "#{project2.path}##{issue.iid}" } + + it 'ignores valid references when cross-reference project uses external tracker' do + expect_any_instance_of(described_class).to receive(:find_object). + with(project2, issue.iid). + and_return(nil) + + exp = act = "Issue #{reference}" + expect(reference_filter(act).to_html).to eq exp + end + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')). + to eq helper.url_for_issue(issue.iid, project2) + end + + it 'link has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.css('a').first.text).to eql("#{project2.path}##{issue.iid}") + end + + it 'has valid text' do + doc = reference_filter("Fixed (#{reference}.)") + + expect(doc.text).to eq("Fixed (#{project2.path}##{issue.iid}.)") + end + + it 'ignores invalid issue IDs on the referenced project' do + exp = act = "Fixed #{invalidate_reference(reference)}" expect(reference_filter(act).to_html).to eq exp end diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb index 9c09f00ae8a..284641fb20a 100644 --- a/spec/lib/banzai/filter/label_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb @@ -4,7 +4,7 @@ require 'html/pipeline' describe Banzai::Filter::LabelReferenceFilter, lib: true do include FilterSpecHelper - let(:project) { create(:empty_project, :public) } + let(:project) { create(:empty_project, :public, name: 'sample-project') } let(:label) { create(:label, project: project) } let(:reference) { label.to_reference } @@ -48,6 +48,14 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do expect(link).to eq urls.namespace_project_issues_path(project.namespace, project, label_name: label.name) end + context 'project that does not exist referenced' do + let(:result) { reference_filter('aaa/bbb~ccc') } + + it 'does not link reference' do + expect(result.to_html).to eq 'aaa/bbb~ccc' + end + end + describe 'label span element' do it 'includes default classes' do doc = reference_filter("Label #{reference}") @@ -334,14 +342,14 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do end context 'with project reference' do - let(:reference) { project.to_reference + group_label.to_reference(format: :name) } + let(:reference) { "#{project.to_reference}#{group_label.to_reference(format: :name)}" } it 'links to a valid reference' do doc = reference_filter("See #{reference}", project: project) expect(doc.css('a').first.attr('href')).to eq urls. namespace_project_issues_url(project.namespace, project, label_name: group_label.name) - expect(doc.text).to eq 'See gfm references' + expect(doc.text).to eq "See gfm references" end it 'links with adjacent text' do @@ -357,68 +365,247 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do end end - describe 'cross project label references' do - context 'valid project referenced' do - let(:another_project) { create(:empty_project, :public) } - let(:project_name) { another_project.name_with_namespace } - let(:label) { create(:label, project: another_project, color: '#00ff00') } - let(:reference) { label.to_reference(project) } + describe 'cross-project / cross-namespace complete reference' do + let(:project2) { create(:empty_project) } + let(:label) { create(:label, project: project2, color: '#00ff00') } + let(:reference) { "#{project2.path_with_namespace}~#{label.name}" } + let!(:result) { reference_filter("See #{reference}") } - let!(:result) { reference_filter("See #{reference}") } + it 'links to a valid reference' do + expect(result.css('a').first.attr('href')) + .to eq urls.namespace_project_issues_url(project2.namespace, + project2, + label_name: label.name) + end - it 'points to referenced project issues page' do - expect(result.css('a').first.attr('href')) - .to eq urls.namespace_project_issues_url(another_project.namespace, - another_project, - label_name: label.name) - end + it 'has valid color' do + expect(result.css('a span').first.attr('style')).to match /background-color: #00ff00/ + end - it 'has valid color' do - expect(result.css('a span').first.attr('style')) - .to match /background-color: #00ff00/ - end + it 'has valid link text' do + expect(result.css('a').first.text).to eq "#{label.name} in #{project2.name_with_namespace}" + end - it 'contains cross project content' do - expect(result.css('a').first.text).to eq "#{label.name} in #{project_name}" - end + it 'has valid text' do + expect(result.text).to eq "See #{label.name} in #{project2.name_with_namespace}" end - context 'project that does not exist referenced' do - let(:result) { reference_filter('aaa/bbb~ccc') } + it 'ignores invalid IDs on the referenced label' do + exp = act = "See #{invalidate_reference(reference)}" - it 'does not link reference' do - expect(result.to_html).to eq 'aaa/bbb~ccc' - end + expect(reference_filter(act).to_html).to eq exp + end + end + + describe 'cross-project / same-namespace complete reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, namespace: namespace) } + let(:project2) { create(:empty_project, namespace: namespace) } + let(:label) { create(:label, project: project2, color: '#00ff00') } + let(:reference) { "#{project2.path_with_namespace}~#{label.name}" } + let!(:result) { reference_filter("See #{reference}") } + + it 'links to a valid reference' do + expect(result.css('a').first.attr('href')) + .to eq urls.namespace_project_issues_url(project2.namespace, + project2, + label_name: label.name) + end + + it 'has valid color' do + expect(result.css('a span').first.attr('style')).to match /background-color: #00ff00/ + end + + it 'has valid link text' do + expect(result.css('a').first.text).to eq "#{label.name} in #{project2.name}" + end + + it 'has valid text' do + expect(result.text).to eq "See #{label.name} in #{project2.name}" + end + + it 'ignores invalid IDs on the referenced label' do + exp = act = "See #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + describe 'cross-project shorthand reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, namespace: namespace) } + let(:project2) { create(:empty_project, namespace: namespace) } + let(:label) { create(:label, project: project2, color: '#00ff00') } + let(:reference) { "#{project2.path}~#{label.name}" } + let!(:result) { reference_filter("See #{reference}") } + + it 'links to a valid reference' do + expect(result.css('a').first.attr('href')) + .to eq urls.namespace_project_issues_url(project2.namespace, + project2, + label_name: label.name) + end + + it 'has valid color' do + expect(result.css('a span').first.attr('style')). + to match /background-color: #00ff00/ + end + + it 'has valid link text' do + expect(result.css('a').first.text).to eq "#{label.name} in #{project2.name}" + end + + it 'has valid text' do + expect(result.text).to eq "See #{label.name} in #{project2.name}" + end + + it 'ignores invalid IDs on the referenced label' do + exp = act = "See #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp end end describe 'cross group label references' do - context 'valid project referenced' do - let(:group) { create(:group) } - let(:project) { create(:empty_project, :public, namespace: group) } - let(:another_group) { create(:group) } - let(:another_project) { create(:empty_project, :public, namespace: another_group) } - let(:project_name) { another_project.name_with_namespace } - let(:group_label) { create(:group_label, group: another_group, color: '#00ff00') } - let(:reference) { another_project.to_reference + group_label.to_reference } - - let!(:result) { reference_filter("See #{reference}", project: project) } - - it 'points to referenced project issues page' do - expect(result.css('a').first.attr('href')) - .to eq urls.namespace_project_issues_url(another_project.namespace, - another_project, - label_name: group_label.name) - end + let(:group) { create(:group) } + let(:project) { create(:empty_project, :public, namespace: group) } + let(:another_group) { create(:group) } + let(:another_project) { create(:empty_project, :public, namespace: another_group) } + let(:group_label) { create(:group_label, group: another_group, color: '#00ff00') } + let(:reference) { "#{another_project.path_with_namespace}~#{group_label.name}" } + let!(:result) { reference_filter("See #{reference}", project: project) } - it 'has valid color' do - expect(result.css('a span').first.attr('style')) - .to match /background-color: #00ff00/ - end + it 'points to referenced project issues page' do + expect(result.css('a').first.attr('href')) + .to eq urls.namespace_project_issues_url(another_project.namespace, + another_project, + label_name: group_label.name) + end - it 'contains cross project content' do - expect(result.css('a').first.text).to eq "#{group_label.name} in #{project_name}" - end + it 'has valid color' do + expect(result.css('a span').first.attr('style')). + to match /background-color: #00ff00/ + end + + it 'has valid link text' do + expect(result.css('a').first.text). + to eq "#{group_label.name} in #{another_project.name_with_namespace}" + end + + it 'has valid text' do + expect(result.text). + to eq "See #{group_label.name} in #{another_project.name_with_namespace}" + end + + it 'ignores invalid IDs on the referenced label' do + exp = act = "See #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + describe 'cross-project / same-group_label complete reference' do + let(:group) { create(:group) } + let(:project) { create(:empty_project, :public, namespace: group) } + let(:another_project) { create(:empty_project, :public, namespace: group) } + let(:group_label) { create(:group_label, group: group, color: '#00ff00') } + let(:reference) { "#{another_project.path_with_namespace}~#{group_label.name}" } + let!(:result) { reference_filter("See #{reference}", project: project) } + + it 'points to referenced project issues page' do + expect(result.css('a').first.attr('href')). + to eq urls.namespace_project_issues_url(another_project.namespace, + another_project, + label_name: group_label.name) + end + + it 'has valid color' do + expect(result.css('a span').first.attr('style')). + to match /background-color: #00ff00/ + end + + it 'has valid link text' do + expect(result.css('a').first.text). + to eq "#{group_label.name} in #{another_project.name}" + end + + it 'has valid text' do + expect(result.text). + to eq "See #{group_label.name} in #{another_project.name}" + end + + it 'ignores invalid IDs on the referenced label' do + exp = act = "See #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + describe 'same project / same group_label complete reference' do + let(:group) { create(:group) } + let(:project) { create(:empty_project, :public, namespace: group) } + let(:group_label) { create(:group_label, group: group, color: '#00ff00') } + let(:reference) { "#{project.path_with_namespace}~#{group_label.name}" } + let!(:result) { reference_filter("See #{reference}", project: project) } + + it 'points to referenced project issues page' do + expect(result.css('a').first.attr('href')) + .to eq urls.namespace_project_issues_url(project.namespace, + project, + label_name: group_label.name) + end + + it 'has valid color' do + expect(result.css('a span').first.attr('style')) + .to match /background-color: #00ff00/ + end + + it 'has valid link text' do + expect(result.css('a').first.text).to eq group_label.name + end + + it 'has valid text' do + expect(result.text).to eq "See #{group_label.name}" + end + + it 'ignores invalid IDs on the referenced label' do + exp = act = "See #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + describe 'same project / same group_label shorthand reference' do + let(:group) { create(:group) } + let(:project) { create(:empty_project, :public, namespace: group) } + let(:group_label) { create(:group_label, group: group, color: '#00ff00') } + let(:reference) { "#{project.path}~#{group_label.name}" } + let!(:result) { reference_filter("See #{reference}", project: project) } + + it 'points to referenced project issues page' do + expect(result.css('a').first.attr('href')) + .to eq urls.namespace_project_issues_url(project.namespace, + project, + label_name: group_label.name) + end + + it 'has valid color' do + expect(result.css('a span').first.attr('style')). + to match /background-color: #00ff00/ + end + + it 'has valid link text' do + expect(result.css('a').first.text).to eq group_label.name + end + + it 'has valid text' do + expect(result.text).to eq "See #{group_label.name}" + end + + it 'ignores invalid IDs on the referenced label' do + exp = act = "See #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp end end end diff --git a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb b/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb index 274258a045c..275010c1a2c 100644 --- a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Banzai::Filter::MergeRequestReferenceFilter, lib: true do include FilterSpecHelper - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public) } let(:merge) { create(:merge_request, source_project: project) } it 'requires project context' do @@ -86,23 +86,97 @@ describe Banzai::Filter::MergeRequestReferenceFilter, lib: true do end end - context 'cross-project reference' do - let(:namespace) { create(:namespace, name: 'cross-reference') } - let(:project2) { create(:project, :public, namespace: namespace) } - let(:merge) { create(:merge_request, source_project: project2) } - let(:reference) { merge.to_reference(project) } + context 'cross-project / cross-namespace complete reference' do + let(:project2) { create(:empty_project, :public) } + let(:merge) { create(:merge_request, source_project: project2) } + let(:reference) { "#{project2.path_with_namespace}!#{merge.iid}" } it 'links to a valid reference' do doc = reference_filter("See #{reference}") expect(doc.css('a').first.attr('href')). to eq urls.namespace_project_merge_request_url(project2.namespace, - project, merge) + project2, merge) end - it 'links with adjacent text' do + it 'link has valid text' do doc = reference_filter("Merge (#{reference}.)") - expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) + + expect(doc.css('a').first.text).to eq(reference) + end + + it 'has valid text' do + doc = reference_filter("Merge (#{reference}.)") + + expect(doc.text).to eq("Merge (#{reference}.)") + end + + it 'ignores invalid merge IDs on the referenced project' do + exp = act = "Merge #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'cross-project / same-namespace complete reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, :public, namespace: namespace) } + let(:project2) { create(:empty_project, :public, namespace: namespace) } + let!(:merge) { create(:merge_request, source_project: project2) } + let(:reference) { "#{project2.path_with_namespace}!#{merge.iid}" } + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_merge_request_url(project2.namespace, + project2, merge) + end + + it 'link has valid text' do + doc = reference_filter("Merge (#{reference}.)") + + expect(doc.css('a').first.text).to eq("#{project2.path}!#{merge.iid}") + end + + it 'has valid text' do + doc = reference_filter("Merge (#{reference}.)") + + expect(doc.text).to eq("Merge (#{project2.path}!#{merge.iid}.)") + end + + it 'ignores invalid merge IDs on the referenced project' do + exp = act = "Merge #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'cross-project shorthand reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, :public, namespace: namespace) } + let(:project2) { create(:empty_project, :public, namespace: namespace) } + let!(:merge) { create(:merge_request, source_project: project2) } + let(:reference) { "#{project2.path}!#{merge.iid}" } + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_merge_request_url(project2.namespace, + project2, merge) + end + + it 'link has valid text' do + doc = reference_filter("Merge (#{reference}.)") + + expect(doc.css('a').first.text).to eq("#{project2.path}!#{merge.iid}") + end + + it 'has valid text' do + doc = reference_filter("Merge (#{reference}.)") + + expect(doc.text).to eq("Merge (#{project2.path}!#{merge.iid}.)") end it 'ignores invalid merge IDs on the referenced project' do diff --git a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb index 7419863d848..73b5edb99b3 100644 --- a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb @@ -148,13 +148,51 @@ describe Banzai::Filter::MilestoneReferenceFilter, lib: true do end end - describe 'cross project milestone references' do - let(:another_project) { create(:empty_project, :public) } - let(:project_path) { another_project.path_with_namespace } - let(:milestone) { create(:milestone, project: another_project) } - let(:reference) { milestone.to_reference(project) } + describe 'cross-project / cross-namespace complete reference' do + let(:namespace) { create(:namespace) } + let(:another_project) { create(:empty_project, :public, namespace: namespace) } + let(:milestone) { create(:milestone, project: another_project) } + let(:reference) { "#{another_project.path_with_namespace}%#{milestone.iid}" } + let!(:result) { reference_filter("See #{reference}") } - let!(:result) { reference_filter("See #{reference}") } + it 'points to referenced project milestone page' do + expect(result.css('a').first.attr('href')).to eq urls. + namespace_project_milestone_url(another_project.namespace, + another_project, + milestone) + end + + it 'link has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.css('a').first.text). + to eq("#{milestone.name} in #{another_project.path_with_namespace}") + end + + it 'has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.text). + to eq("See (#{milestone.name} in #{another_project.path_with_namespace}.)") + end + + it 'escapes the name attribute' do + allow_any_instance_of(Milestone).to receive(:title).and_return(%{"></a>whatever<a title="}) + + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.text). + to eq "#{milestone.name} in #{another_project.path_with_namespace}" + end + end + + describe 'cross-project / same-namespace complete reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, :public, namespace: namespace) } + let(:another_project) { create(:empty_project, :public, namespace: namespace) } + let(:milestone) { create(:milestone, project: another_project) } + let(:reference) { "#{another_project.path_with_namespace}%#{milestone.iid}" } + let!(:result) { reference_filter("See #{reference}") } it 'points to referenced project milestone page' do expect(result.css('a').first.attr('href')).to eq urls. @@ -163,14 +201,66 @@ describe Banzai::Filter::MilestoneReferenceFilter, lib: true do milestone) end - it 'contains cross project content' do - expect(result.css('a').first.text).to eq "#{milestone.name} in #{project_path}" + it 'link has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.css('a').first.text). + to eq("#{milestone.name} in #{another_project.path}") + end + + it 'has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.text). + to eq("See (#{milestone.name} in #{another_project.path}.)") end it 'escapes the name attribute' do allow_any_instance_of(Milestone).to receive(:title).and_return(%{"></a>whatever<a title="}) + + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.text). + to eq "#{milestone.name} in #{another_project.path}" + end + end + + describe 'cross project shorthand reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, :public, namespace: namespace) } + let(:another_project) { create(:empty_project, :public, namespace: namespace) } + let(:milestone) { create(:milestone, project: another_project) } + let(:reference) { "#{another_project.path}%#{milestone.iid}" } + let!(:result) { reference_filter("See #{reference}") } + + it 'points to referenced project milestone page' do + expect(result.css('a').first.attr('href')).to eq urls. + namespace_project_milestone_url(another_project.namespace, + another_project, + milestone) + end + + it 'link has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.css('a').first.text). + to eq("#{milestone.name} in #{another_project.path}") + end + + it 'has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.text). + to eq("See (#{milestone.name} in #{another_project.path}.)") + end + + it 'escapes the name attribute' do + allow_any_instance_of(Milestone).to receive(:title).and_return(%{"></a>whatever<a title="}) + doc = reference_filter("See #{reference}") - expect(doc.css('a').first.text).to eq "#{milestone.name} in #{project_path}" + + expect(doc.css('a').first.text). + to eq "#{milestone.name} in #{another_project.path}" end end end diff --git a/spec/lib/banzai/filter/snippet_reference_filter_spec.rb b/spec/lib/banzai/filter/snippet_reference_filter_spec.rb index 9b92d1a3926..e036514d283 100644 --- a/spec/lib/banzai/filter/snippet_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/snippet_reference_filter_spec.rb @@ -79,11 +79,11 @@ describe Banzai::Filter::SnippetReferenceFilter, lib: true do end end - context 'cross-project reference' do - let(:namespace) { create(:namespace, name: 'cross-reference') } + context 'cross-project / cross-namespace complete reference' do + let(:namespace) { create(:namespace) } let(:project2) { create(:empty_project, :public, namespace: namespace) } - let(:snippet) { create(:project_snippet, project: project2) } - let(:reference) { snippet.to_reference(project) } + let!(:snippet) { create(:project_snippet, project: project2) } + let(:reference) { "#{project2.path_with_namespace}$#{snippet.id}" } it 'links to a valid reference' do doc = reference_filter("See #{reference}") @@ -92,9 +92,82 @@ describe Banzai::Filter::SnippetReferenceFilter, lib: true do to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet) end - it 'links with adjacent text' do + it 'link has valid text' do doc = reference_filter("See (#{reference}.)") - expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) + + expect(doc.css('a').first.text).to eql(reference) + end + + it 'has valid text' do + doc = reference_filter("See (#{reference}.)") + + expect(doc.text).to eql("See (#{reference}.)") + end + + it 'ignores invalid snippet IDs on the referenced project' do + exp = act = "See #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'cross-project / same-namespace complete reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, :public, namespace: namespace) } + let(:project2) { create(:empty_project, :public, namespace: namespace) } + let!(:snippet) { create(:project_snippet, project: project2) } + let(:reference) { "#{project2.path_with_namespace}$#{snippet.id}" } + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet) + end + + it 'link has valid text' do + doc = reference_filter("See (#{project2.path}$#{snippet.id}.)") + + expect(doc.css('a').first.text).to eql("#{project2.path}$#{snippet.id}") + end + + it 'has valid text' do + doc = reference_filter("See (#{project2.path}$#{snippet.id}.)") + + expect(doc.text).to eql("See (#{project2.path}$#{snippet.id}.)") + end + + it 'ignores invalid snippet IDs on the referenced project' do + exp = act = "See #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'cross-project shorthand reference' do + let(:namespace) { create(:namespace) } + let(:project) { create(:empty_project, :public, namespace: namespace) } + let(:project2) { create(:empty_project, :public, namespace: namespace) } + let!(:snippet) { create(:project_snippet, project: project2) } + let(:reference) { "#{project2.path}$#{snippet.id}" } + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet) + end + + it 'link has valid text' do + doc = reference_filter("See (#{project2.path}$#{snippet.id}.)") + + expect(doc.css('a').first.text).to eql("#{project2.path}$#{snippet.id}") + end + + it 'has valid text' do + doc = reference_filter("See (#{project2.path}$#{snippet.id}.)") + + expect(doc.text).to eql("See (#{project2.path}$#{snippet.id}.)") end it 'ignores invalid snippet IDs on the referenced project' do diff --git a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb index 356dd01a03a..70b31f3a880 100644 --- a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb +++ b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb @@ -22,7 +22,7 @@ describe Banzai::Filter::TableOfContentsFilter, lib: true do html = header(i, "Header #{i}") doc = filter(html) - expect(doc.css("h#{i} a").first.attr('id')).to eq "header-#{i}" + expect(doc.css("h#{i} a").first.attr('id')).to eq "user-content-header-#{i}" end end @@ -32,7 +32,12 @@ describe Banzai::Filter::TableOfContentsFilter, lib: true do expect(doc.css('h1 a').first.attr('class')).to eq 'anchor' end - it 'links to the id' do + it 'has a namespaced id' do + doc = filter(header(1, 'Header')) + expect(doc.css('h1 a').first.attr('id')).to eq 'user-content-header' + end + + it 'links to the non-namespaced id' do doc = filter(header(1, 'Header')) expect(doc.css('h1 a').first.attr('href')).to eq '#header' end @@ -40,29 +45,29 @@ describe Banzai::Filter::TableOfContentsFilter, lib: true do describe 'generated IDs' do it 'translates spaces to dashes' do doc = filter(header(1, 'This header has spaces in it')) - expect(doc.css('h1 a').first.attr('id')).to eq 'this-header-has-spaces-in-it' + expect(doc.css('h1 a').first.attr('href')).to eq '#this-header-has-spaces-in-it' end it 'squeezes multiple spaces and dashes' do doc = filter(header(1, 'This---header is poorly-formatted')) - expect(doc.css('h1 a').first.attr('id')).to eq 'this-header-is-poorly-formatted' + expect(doc.css('h1 a').first.attr('href')).to eq '#this-header-is-poorly-formatted' end it 'removes punctuation' do doc = filter(header(1, "This, header! is, filled. with @ punctuation?")) - expect(doc.css('h1 a').first.attr('id')).to eq 'this-header-is-filled-with-punctuation' + expect(doc.css('h1 a').first.attr('href')).to eq '#this-header-is-filled-with-punctuation' end it 'appends a unique number to duplicates' do doc = filter(header(1, 'One') + header(2, 'One')) - expect(doc.css('h1 a').first.attr('id')).to eq 'one' - expect(doc.css('h2 a').first.attr('id')).to eq 'one-1' + expect(doc.css('h1 a').first.attr('href')).to eq '#one' + expect(doc.css('h2 a').first.attr('href')).to eq '#one-1' end it 'supports Unicode' do doc = filter(header(1, '한글')) - expect(doc.css('h1 a').first.attr('id')).to eq '한글' + expect(doc.css('h1 a').first.attr('id')).to eq 'user-content-한글' expect(doc.css('h1 a').first.attr('href')).to eq '#한글' end end diff --git a/spec/lib/constraints/constrainer_helper_spec.rb b/spec/lib/constraints/constrainer_helper_spec.rb deleted file mode 100644 index 27c8d72aefc..00000000000 --- a/spec/lib/constraints/constrainer_helper_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'spec_helper' - -describe ConstrainerHelper, lib: true do - include ConstrainerHelper - - describe '#extract_resource_path' do - it { expect(extract_resource_path('/gitlab/')).to eq('gitlab') } - it { expect(extract_resource_path('///gitlab//')).to eq('gitlab') } - it { expect(extract_resource_path('/gitlab.atom')).to eq('gitlab') } - - context 'relative url' do - before do - allow(Gitlab::Application.config).to receive(:relative_url_root) { '/gitlab' } - end - - it { expect(extract_resource_path('/gitlab/foo')).to eq('foo') } - it { expect(extract_resource_path('/foo/bar')).to eq('foo/bar') } - end - end -end diff --git a/spec/lib/constraints/group_url_constrainer_spec.rb b/spec/lib/constraints/group_url_constrainer_spec.rb index 42299b17c2b..892554f2870 100644 --- a/spec/lib/constraints/group_url_constrainer_spec.rb +++ b/spec/lib/constraints/group_url_constrainer_spec.rb @@ -4,16 +4,20 @@ describe GroupUrlConstrainer, lib: true do let!(:group) { create(:group, path: 'gitlab') } describe '#matches?' do - context 'root group' do - it { expect(subject.matches?(request '/gitlab')).to be_truthy } - it { expect(subject.matches?(request '/gitlab.atom')).to be_truthy } - it { expect(subject.matches?(request '/gitlab/edit')).to be_falsey } - it { expect(subject.matches?(request '/gitlab-ce')).to be_falsey } - it { expect(subject.matches?(request '/.gitlab')).to be_falsey } + context 'valid request' do + let(:request) { build_request(group.path) } + + it { expect(subject.matches?(request)).to be_truthy } + end + + context 'invalid request' do + let(:request) { build_request('foo') } + + it { expect(subject.matches?(request)).to be_falsey } end end - def request(path) - double(:request, path: path) + def build_request(path) + double(:request, params: { id: path }) end end diff --git a/spec/lib/constraints/project_url_constrainer_spec.rb b/spec/lib/constraints/project_url_constrainer_spec.rb new file mode 100644 index 00000000000..94266f6653b --- /dev/null +++ b/spec/lib/constraints/project_url_constrainer_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe ProjectUrlConstrainer, lib: true do + let!(:project) { create(:project) } + let!(:namespace) { project.namespace } + + describe '#matches?' do + context 'valid request' do + let(:request) { build_request(namespace.path, project.path) } + + it { expect(subject.matches?(request)).to be_truthy } + end + + context 'invalid request' do + context "non-existing project" do + let(:request) { build_request('foo', 'bar') } + + it { expect(subject.matches?(request)).to be_falsey } + end + + context "project id ending with .git" do + let(:request) { build_request(namespace.path, project.path + '.git') } + + it { expect(subject.matches?(request)).to be_falsey } + end + end + end + + def build_request(namespace, project) + double(:request, params: { namespace_id: namespace, id: project }) + end +end diff --git a/spec/lib/constraints/user_url_constrainer_spec.rb b/spec/lib/constraints/user_url_constrainer_spec.rb index b3f8530c609..207b6fe6c9e 100644 --- a/spec/lib/constraints/user_url_constrainer_spec.rb +++ b/spec/lib/constraints/user_url_constrainer_spec.rb @@ -1,16 +1,23 @@ require 'spec_helper' describe UserUrlConstrainer, lib: true do - let!(:username) { create(:user, username: 'dz') } + let!(:user) { create(:user, username: 'dz') } describe '#matches?' do - it { expect(subject.matches?(request '/dz')).to be_truthy } - it { expect(subject.matches?(request '/dz.atom')).to be_truthy } - it { expect(subject.matches?(request '/dz/projects')).to be_falsey } - it { expect(subject.matches?(request '/gitlab')).to be_falsey } + context 'valid request' do + let(:request) { build_request(user.username) } + + it { expect(subject.matches?(request)).to be_truthy } + end + + context 'invalid request' do + let(:request) { build_request('foo') } + + it { expect(subject.matches?(request)).to be_falsey } + end end - def request(path) - double(:request, path: path) + def build_request(username) + double(:request, params: { username: username }) end end diff --git a/spec/lib/gitlab/chat_commands/issue_create_spec.rb b/spec/lib/gitlab/chat_commands/issue_create_spec.rb index df0c317ccea..6c71e79ff6d 100644 --- a/spec/lib/gitlab/chat_commands/issue_create_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_create_spec.rb @@ -32,6 +32,15 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do expect(Issue.last.description).to eq(description) end end + + context "with more newlines between the title and the description" do + let(:description) { "Surfin bird" } + let(:regex_match) { described_class.match("issue create bird is the word\n\n#{description}\n") } + + it 'creates the issue' do + expect { subject }.to change { project.issues.count }.by(1) + end + end end describe '.match' do @@ -48,5 +57,12 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do expect(match[:title]).to eq('my title') expect(match[:description]).to eq('description') end + + it 'matches the alias new' do + match = described_class.match("issue new my title") + + expect(match).not_to be_nil + expect(match[:title]).to eq('my title') + end end end diff --git a/spec/lib/gitlab/chat_commands/issue_search_spec.rb b/spec/lib/gitlab/chat_commands/issue_search_spec.rb new file mode 100644 index 00000000000..24c06a967fa --- /dev/null +++ b/spec/lib/gitlab/chat_commands/issue_search_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::IssueSearch, service: true do + describe '#execute' do + let!(:issue) { create(:issue, title: 'find me') } + let!(:confidential) { create(:issue, :confidential, project: project, title: 'mepmep find') } + let(:project) { issue.project } + let(:user) { issue.author } + let(:regex_match) { described_class.match("issue search find") } + + subject do + described_class.new(project, user).execute(regex_match) + end + + context 'when the user has no access' do + it 'only returns the open issues' do + expect(subject).not_to include(confidential) + end + end + + context 'the user has access' do + before do + project.team << [user, :master] + end + + it 'returns all results' do + expect(subject).to include(confidential, issue) + end + end + + context 'without hits on the query' do + it 'returns an empty collection' do + expect(subject).to be_empty + end + end + end + + describe 'self.match' do + let(:query) { "my search keywords" } + it 'matches the query' do + match = described_class.match("issue search #{query}") + + expect(match[:query]).to eq(query) + end + end +end diff --git a/spec/lib/gitlab/chat_commands/issue_show_spec.rb b/spec/lib/gitlab/chat_commands/issue_show_spec.rb index 331a4604e9b..2eab73e49e5 100644 --- a/spec/lib/gitlab/chat_commands/issue_show_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_show_spec.rb @@ -19,6 +19,14 @@ describe Gitlab::ChatCommands::IssueShow, service: true do it 'returns the issue' do expect(subject.iid).to be issue.iid end + + context 'when its reference is given' do + let(:regex_match) { described_class.match("issue show #{issue.to_reference}") } + + it 'shows the issue' do + expect(subject.iid).to be issue.iid + end + end end context 'the issue does not exist' do diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb index 5e5c5dcc385..e64c8d46bd8 100644 --- a/spec/lib/gitlab/ci/config/entry/global_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb @@ -13,7 +13,7 @@ describe Gitlab::Ci::Config::Entry::Global do end end - context 'when hash is valid' do + context 'when configuration is valid' do context 'when some entries defined' do let(:hash) do { before_script: ['ls', 'pwd'], @@ -225,29 +225,44 @@ describe Gitlab::Ci::Config::Entry::Global do end end - context 'when hash is not valid' do + context 'when configuration is not valid' do before { global.compose! } - let(:hash) do - { before_script: 'ls' } - end + context 'when before script is not an array' do + let(:hash) do + { before_script: 'ls' } + end - describe '#valid?' do - it 'is not valid' do - expect(global).not_to be_valid + describe '#valid?' do + it 'is not valid' do + expect(global).not_to be_valid + end end - end - describe '#errors' do - it 'reports errors from child nodes' do - expect(global.errors) - .to include 'before_script config should be an array of strings' + describe '#errors' do + it 'reports errors from child nodes' do + expect(global.errors) + .to include 'before_script config should be an array of strings' + end + end + + describe '#before_script_value' do + it 'returns nil' do + expect(global.before_script_value).to be_nil + end end end - describe '#before_script_value' do - it 'returns nil' do - expect(global.before_script_value).to be_nil + context 'when job does not have commands' do + let(:hash) do + { before_script: ['echo 123'], rspec: { stage: 'test' } } + end + + describe '#errors' do + it 'reports errors about missing script' do + expect(global.errors) + .to include "jobs:rspec script can't be blank" + end end end end @@ -281,7 +296,7 @@ describe Gitlab::Ci::Config::Entry::Global do { cache: { key: 'a' }, rspec: { script: 'ls' } } end - context 'when node exists' do + context 'when entry exists' do it 'returns correct entry' do expect(global[:cache]) .to be_an_instance_of Gitlab::Ci::Config::Entry::Cache @@ -289,7 +304,7 @@ describe Gitlab::Ci::Config::Entry::Global do end end - context 'when node does not exist' do + context 'when entry does not exist' do it 'always return unspecified node' do expect(global[:some][:unknown][:node]) .not_to be_specified diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 9aeaa6b3ee8..6062e7af4f5 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -321,6 +321,6 @@ describe Gitlab::CycleAnalytics::Events do context.update(milestone: milestone) mr = create_merge_request_closing_issue(context) - ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.sha) + ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.to_hash) end end diff --git a/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb index d76a255acf5..4a5604115ec 100644 --- a/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb @@ -6,5 +6,13 @@ describe Gitlab::CycleAnalytics::PlanEvent do it 'has the default order' do expect(event.order).to eq(event.start_time_attrs) end + + context 'no commits' do + it 'does not blow up if there are no commits' do + allow_any_instance_of(Gitlab::CycleAnalytics::EventsQuery).to receive(:execute).and_return([{}]) + + expect { event.fetch }.not_to raise_error + end + end end end diff --git a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb new file mode 100644 index 00000000000..2a680f03476 --- /dev/null +++ b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe Gitlab::Diff::FileCollection::MergeRequestDiff do + let(:merge_request) { create :merge_request } + + it 'does not hightlight binary files' do + allow_any_instance_of(Gitlab::Diff::File).to receive(:blob).and_return(double("text?" => false)) + + expect_any_instance_of(Gitlab::Diff::File).not_to receive(:highlighted_diff_lines) + + described_class.new(merge_request.merge_request_diff, diff_options: nil).diff_files + end + + it 'does not hightlight file if blob is not accessable' do + allow_any_instance_of(Gitlab::Diff::File).to receive(:blob).and_return(nil) + + expect_any_instance_of(Gitlab::Diff::File).not_to receive(:highlighted_diff_lines) + + described_class.new(merge_request.merge_request_diff, diff_options: nil).diff_files + end +end diff --git a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb index 6b3dfebd85d..d619e401897 100644 --- a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb +++ b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb @@ -64,7 +64,7 @@ describe Gitlab::Gfm::ReferenceRewriter do context 'description with project labels' do let!(:label) { create(:label, id: 123, name: 'test', project: old_project) } - let(:project_ref) { old_project.to_reference } + let(:project_ref) { old_project.to_reference(new_project) } context 'label referenced by id' do let(:text) { '#1 and ~123' } @@ -80,7 +80,7 @@ describe Gitlab::Gfm::ReferenceRewriter do context 'description with group labels' do let(:old_group) { create(:group) } let!(:group_label) { create(:group_label, id: 321, name: 'group label', group: old_group) } - let(:project_ref) { old_project.to_reference } + let(:project_ref) { old_project.to_reference(new_project) } before do old_project.update(namespace: old_group) diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb index 576aa5c366f..578db51631e 100644 --- a/spec/lib/gitlab/git_access_wiki_spec.rb +++ b/spec/lib/gitlab/git_access_wiki_spec.rb @@ -26,4 +26,29 @@ describe Gitlab::GitAccessWiki, lib: true do def changes ['6f6d7e7ed 570e7b2ab refs/heads/master'] end + + describe '#download_access_check' do + subject { access.check('git-upload-pack', '_any') } + + before do + project.team << [user, :developer] + end + + context 'when wiki feature is enabled' do + it 'give access to download wiki code' do + project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::ENABLED) + + expect(subject.allowed?).to be_truthy + end + end + + context 'when wiki feature is disabled' do + it 'does not give access to download wiki code' do + project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED) + + expect(subject.allowed?).to be_falsey + expect(subject.message).to match(/You are not allowed to download code/) + end + end + end end diff --git a/spec/lib/gitlab/github_import/branch_formatter_spec.rb b/spec/lib/gitlab/github_import/branch_formatter_spec.rb index e5300dbba1e..462caa5b5fe 100644 --- a/spec/lib/gitlab/github_import/branch_formatter_spec.rb +++ b/spec/lib/gitlab/github_import/branch_formatter_spec.rb @@ -49,14 +49,20 @@ describe Gitlab::GithubImport::BranchFormatter, lib: true do end describe '#valid?' do - it 'returns true when raw repo is present' do + it 'returns true when raw sha and ref are present' do branch = described_class.new(project, double(raw)) expect(branch.valid?).to eq true end - it 'returns false when raw repo is blank' do - branch = described_class.new(project, double(raw.merge(repo: nil))) + it 'returns false when raw sha is blank' do + branch = described_class.new(project, double(raw.merge(sha: nil))) + + expect(branch.valid?).to eq false + end + + it 'returns false when raw ref is blank' do + branch = described_class.new(project, double(raw.merge(ref: nil))) expect(branch.valid?).to eq false end diff --git a/spec/lib/gitlab/identifier_spec.rb b/spec/lib/gitlab/identifier_spec.rb index 47d6f1007d1..bb758a8a202 100644 --- a/spec/lib/gitlab/identifier_spec.rb +++ b/spec/lib/gitlab/identifier_spec.rb @@ -40,7 +40,7 @@ describe Gitlab::Identifier do describe '#identify_using_commit' do it "returns the User for an existing commit author's Email address" do - commit = double(:commit, author_email: user.email) + commit = double(:commit, author: user, author_email: user.email) expect(project).to receive(:commit).with('123').and_return(commit) @@ -62,10 +62,9 @@ describe Gitlab::Identifier do end it 'caches the found users per Email' do - commit = double(:commit, author_email: user.email) + commit = double(:commit, author: user, author_email: user.email) expect(project).to receive(:commit).with('123').twice.and_return(commit) - expect(User).to receive(:find_by).once.and_call_original 2.times do expect(identifier.identify_using_commit(project, '123')).to eq(user) diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index fe3c39e38db..7e00e214c6e 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -186,6 +186,8 @@ project: - environments - deployments - project_feature +- authorized_users +- project_authorizations award_emoji: - awardable - user diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb index 770e8b0c2f4..1cb02f8e318 100644 --- a/spec/lib/gitlab/import_export/members_mapper_spec.rb +++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' describe Gitlab::ImportExport::MembersMapper, services: true do describe 'map members' do - let(:user) { create(:user) } + let(:user) { create(:user, authorized_projects_populated: true) } let(:project) { create(:project, :public, name: 'searchable_project') } - let(:user2) { create(:user) } + let(:user2) { create(:user, authorized_projects_populated: true) } let(:exported_user_id) { 99 } let(:exported_members) do [{ @@ -67,5 +67,12 @@ describe Gitlab::ImportExport::MembersMapper, services: true do expect(ProjectMember.find_by_invite_email('invite@test.com')).not_to be_nil end + + it 'authorizes the users to the project' do + members_mapper.map + + expect(user.authorized_project?(project)).to be true + expect(user2.authorized_project?(project)).to be true + end end end diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index f8531bf715b..ac26c831fd0 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -78,6 +78,7 @@ Milestone: - project_id - description - due_date +- start_date - created_at - updated_at - state diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb index a0fdad87eee..3cd9863ec6a 100644 --- a/spec/lib/gitlab/project_search_results_spec.rb +++ b/spec/lib/gitlab/project_search_results_spec.rb @@ -65,6 +65,14 @@ describe Gitlab::ProjectSearchResults, lib: true do end end + it 'does not list issues on private projects' do + issue = create(:issue, project: project) + + results = described_class.new(user, project, issue.title) + + expect(results.objects('issues')).not_to include issue + end + describe 'confidential issues' do let(:query) { 'issue' } let(:author) { create(:user) } @@ -72,6 +80,7 @@ describe Gitlab::ProjectSearchResults, lib: true do let(:non_member) { create(:user) } let(:member) { create(:user) } let(:admin) { create(:admin) } + let(:project) { create(:empty_project, :internal) } let!(:issue) { create(:issue, project: project, title: 'Issue 1') } let!(:security_issue_1) { create(:issue, :confidential, project: project, title: 'Security issue 1', author: author) } let!(:security_issue_2) { create(:issue, :confidential, title: 'Security issue 2', project: project, assignee: assignee) } diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb index dfbefad6367..f23e3522625 100644 --- a/spec/lib/gitlab/search_results_spec.rb +++ b/spec/lib/gitlab/search_results_spec.rb @@ -12,35 +12,48 @@ describe Gitlab::SearchResults do let!(:milestone) { create(:milestone, project: project, title: 'foo') } let(:results) { described_class.new(user, Project.all, 'foo') } - describe '#projects_count' do - it 'returns the total amount of projects' do - expect(results.projects_count).to eq(1) + context 'as a user with access' do + before do + project.team << [user, :developer] end - end - describe '#issues_count' do - it 'returns the total amount of issues' do - expect(results.issues_count).to eq(1) + describe '#projects_count' do + it 'returns the total amount of projects' do + expect(results.projects_count).to eq(1) + end end - end - describe '#merge_requests_count' do - it 'returns the total amount of merge requests' do - expect(results.merge_requests_count).to eq(1) + describe '#issues_count' do + it 'returns the total amount of issues' do + expect(results.issues_count).to eq(1) + end + end + + describe '#merge_requests_count' do + it 'returns the total amount of merge requests' do + expect(results.merge_requests_count).to eq(1) + end end - end - describe '#milestones_count' do - it 'returns the total amount of milestones' do - expect(results.milestones_count).to eq(1) + describe '#milestones_count' do + it 'returns the total amount of milestones' do + expect(results.milestones_count).to eq(1) + end end end + it 'does not list issues on private projects' do + private_project = create(:empty_project, :private) + issue = create(:issue, project: private_project, title: 'foo') + + expect(results.objects('issues')).not_to include issue + end + describe 'confidential issues' do - let(:project_1) { create(:empty_project) } - let(:project_2) { create(:empty_project) } - let(:project_3) { create(:empty_project) } - let(:project_4) { create(:empty_project) } + let(:project_1) { create(:empty_project, :internal) } + let(:project_2) { create(:empty_project, :internal) } + let(:project_3) { create(:empty_project, :internal) } + let(:project_4) { create(:empty_project, :internal) } let(:query) { 'issue' } let(:limit_projects) { Project.where(id: [project_1.id, project_2.id, project_3.id]) } let(:author) { create(:user) } |