diff options
author | Douwe Maan <douwe@gitlab.com> | 2015-10-17 11:55:55 +0000 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2015-10-17 11:55:55 +0000 |
commit | 5ad3a274b3404286bb32b695c8f2b7bdd21e4953 (patch) | |
tree | 2b3fd69c3a8cfd064d11cb90ed8e5c7a1ab6f803 /spec | |
parent | 5d010ecd8a3ed6e0a83b3c050c7bdfff833f77e1 (diff) | |
parent | 34148d15764898579cc44ea02f439e8359e01233 (diff) | |
download | gitlab-ce-5ad3a274b3404286bb32b695c8f2b7bdd21e4953.tar.gz |
Merge branch 'rs-redactor-filter' into 'master'
Separate rendering of Markdown reference links from redacting those the user doesn't have access to and extracting referenced objects
Related: !1014
See merge request !1090
Diffstat (limited to 'spec')
17 files changed, 426 insertions, 315 deletions
diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index c557a1061af..fdd8cf07b12 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -220,7 +220,7 @@ describe 'GitLab Markdown', feature: true do end end - # `markdown` calls these two methods + # Fake a `current_user` helper def current_user @feat.user end diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 20ae29e2bd3..762ec25c4f5 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -11,12 +11,15 @@ describe GitlabMarkdownHelper do let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let(:snippet) { create(:project_snippet, project: project) } - # Helper expects a current_user method. - let(:current_user) { user } - before do + # Ensure the generated reference links aren't redacted + project.team << [user, :master] + # Helper expects a @project instance variable - @project = project + helper.instance_variable_set(:@project, project) + + # Stub the `current_user` helper + allow(helper).to receive(:current_user).and_return(user) end describe "#markdown" do @@ -25,23 +28,23 @@ describe GitlabMarkdownHelper do it "should link to the merge request" do expected = namespace_project_merge_request_path(project.namespace, project, merge_request) - expect(markdown(actual)).to match(expected) + expect(helper.markdown(actual)).to match(expected) end it "should link to the commit" do expected = namespace_project_commit_path(project.namespace, project, commit) - expect(markdown(actual)).to match(expected) + expect(helper.markdown(actual)).to match(expected) end it "should link to the issue" do expected = namespace_project_issue_path(project.namespace, project, issue) - expect(markdown(actual)).to match(expected) + expect(helper.markdown(actual)).to match(expected) end end describe "override default project" do let(:actual) { issue.to_reference } - let(:second_project) { create(:project) } + let(:second_project) { create(:project, :public) } let(:second_issue) { create(:issue, project: second_project) } it 'should link to the issue' do @@ -56,7 +59,7 @@ describe GitlabMarkdownHelper do let(:issues) { create_list(:issue, 2, project: project) } it 'should handle references nested in links with all the text' do - actual = link_to_gfm("This should finally fix #{issues[0].to_reference} and #{issues[1].to_reference} for real", commit_path) + actual = helper.link_to_gfm("This should finally fix #{issues[0].to_reference} and #{issues[1].to_reference} for real", commit_path) doc = Nokogiri::HTML.parse(actual) # Make sure we didn't create invalid markup @@ -86,7 +89,7 @@ describe GitlabMarkdownHelper do end it 'should forward HTML options' do - actual = link_to_gfm("Fixed in #{commit.id}", commit_path, class: 'foo') + actual = helper.link_to_gfm("Fixed in #{commit.id}", commit_path, class: 'foo') doc = Nokogiri::HTML.parse(actual) expect(doc.css('a')).to satisfy do |v| @@ -97,13 +100,13 @@ describe GitlabMarkdownHelper do it "escapes HTML passed in as the body" do actual = "This is a <h1>test</h1> - see #{issues[0].to_reference}" - expect(link_to_gfm(actual, commit_path)). + expect(helper.link_to_gfm(actual, commit_path)). to match('<h1>test</h1>') end it 'ignores reference links when they are the entire body' do text = issues[0].to_reference - act = link_to_gfm(text, '/foo') + act = helper.link_to_gfm(text, '/foo') expect(act).to eq %Q(<a href="/foo">#{issues[0].to_reference}</a>) end diff --git a/spec/lib/gitlab/closing_issue_extractor_spec.rb b/spec/lib/gitlab/closing_issue_extractor_spec.rb index 5d7ff4f6122..21254f778d3 100644 --- a/spec/lib/gitlab/closing_issue_extractor_spec.rb +++ b/spec/lib/gitlab/closing_issue_extractor_spec.rb @@ -140,28 +140,28 @@ describe Gitlab::ClosingIssueExtractor do message = "Closes #{reference} and fix #{reference2}" expect(subject.closed_by_message(message)). - to eq([issue, other_issue]) + to match_array([issue, other_issue]) end it 'fetches comma-separated issues references in single line message' do message = "Closes #{reference}, closes #{reference2}" expect(subject.closed_by_message(message)). - to eq([issue, other_issue]) + to match_array([issue, other_issue]) end it 'fetches comma-separated issues numbers in single line message' do message = "Closes #{reference}, #{reference2} and #{reference3}" expect(subject.closed_by_message(message)). - to eq([issue, other_issue, third_issue]) + to match_array([issue, other_issue, third_issue]) end it 'fetches issues in multi-line message' do message = "Awesome commit (closes #{reference})\nAlso fixes #{reference2}" expect(subject.closed_by_message(message)). - to eq([issue, other_issue]) + to match_array([issue, other_issue]) end it 'fetches issues in hybrid message' do @@ -169,7 +169,7 @@ describe Gitlab::ClosingIssueExtractor do "Also fixing issues #{reference2}, #{reference3} and #4" expect(subject.closed_by_message(message)). - to eq([issue, other_issue, third_issue]) + to match_array([issue, other_issue, third_issue]) end end end diff --git a/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb b/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb index 3c6c84a0416..e5b8d723fe5 100644 --- a/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb @@ -4,7 +4,7 @@ module Gitlab::Markdown describe CommitRangeReferenceFilter do include FilterSpecHelper - let(:project) { create(:project) } + let(:project) { create(:project, :public) } let(:commit1) { project.commit } let(:commit2) { project.commit("HEAD~2") } @@ -75,12 +75,20 @@ module Gitlab::Markdown expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit_range' end - it 'includes a data-project-id attribute' do + it 'includes a data-project attribute' do doc = filter("See #{reference}") link = doc.css('a').first - expect(link).to have_attribute('data-project-id') - expect(link.attr('data-project-id')).to eq project.id.to_s + expect(link).to have_attribute('data-project') + expect(link.attr('data-project')).to eq project.id.to_s + end + + it 'includes a data-commit-range attribute' do + doc = filter("See #{reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-commit-range') + expect(link.attr('data-commit-range')).to eq range.to_reference end it 'supports an :only_path option' do @@ -92,59 +100,45 @@ module Gitlab::Markdown end it 'adds to the results hash' do - result = pipeline_result("See #{reference}") + result = reference_pipeline_result("See #{reference}") expect(result[:references][:commit_range]).not_to be_empty end end context 'cross-project reference' do let(:namespace) { create(:namespace, name: 'cross-reference') } - let(:project2) { create(:project, namespace: namespace) } + let(:project2) { create(:project, :public, namespace: namespace) } let(:reference) { range.to_reference(project) } before do range.project = project2 end - context 'when user can access reference' do - before { allow_cross_reference! } - - it 'links to a valid reference' do - doc = 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 'links with adjacent text' do - doc = filter("Fixed (#{reference}.)") - - exp = Regexp.escape("#{project2.to_reference}@#{range.to_s}") - expect(doc.to_html).to match(/\(<a.+>#{exp}<\/a>\.\)/) - end + it 'links to a valid reference' do + doc = filter("See #{reference}") - it 'ignores invalid commit IDs on the referenced project' do - exp = act = "Fixed #{project2.to_reference}@#{commit1.id.reverse}...#{commit2.id}" - expect(filter(act).to_html).to eq exp + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_compare_url(project2.namespace, project2, range.to_param) + end - exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}" - expect(filter(act).to_html).to eq exp - end + it 'links with adjacent text' do + doc = filter("Fixed (#{reference}.)") - it 'adds to the results hash' do - result = pipeline_result("See #{reference}") - expect(result[:references][:commit_range]).not_to be_empty - end + exp = Regexp.escape("#{project2.to_reference}@#{range.to_s}") + expect(doc.to_html).to match(/\(<a.+>#{exp}<\/a>\.\)/) end - context 'when user cannot access reference' do - before { disallow_cross_reference! } + it 'ignores invalid commit IDs on the referenced project' do + exp = act = "Fixed #{project2.to_reference}@#{commit1.id.reverse}...#{commit2.id}" + expect(filter(act).to_html).to eq exp - it 'ignores valid references' do - exp = act = "See #{reference}" + exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}" + expect(filter(act).to_html).to eq exp + end - expect(filter(act).to_html).to eq exp - end + it 'adds to the results hash' do + result = reference_pipeline_result("See #{reference}") + expect(result[:references][:commit_range]).not_to be_empty end end end diff --git a/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb b/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb index 9ed438252b3..d080efbf3d4 100644 --- a/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb @@ -4,7 +4,7 @@ module Gitlab::Markdown describe CommitReferenceFilter do include FilterSpecHelper - let(:project) { create(:project) } + let(:project) { create(:project, :public) } let(:commit) { project.commit } it 'requires project context' do @@ -71,12 +71,20 @@ module Gitlab::Markdown expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit' end - it 'includes a data-project-id attribute' do + it 'includes a data-project attribute' do doc = filter("See #{reference}") link = doc.css('a').first - expect(link).to have_attribute('data-project-id') - expect(link.attr('data-project-id')).to eq project.id.to_s + expect(link).to have_attribute('data-project') + expect(link.attr('data-project')).to eq project.id.to_s + end + + it 'includes a data-commit attribute' do + doc = filter("See #{reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-commit') + expect(link.attr('data-commit')).to eq commit.id end it 'supports an :only_path context' do @@ -88,53 +96,39 @@ module Gitlab::Markdown end it 'adds to the results hash' do - result = pipeline_result("See #{reference}") + result = reference_pipeline_result("See #{reference}") expect(result[:references][:commit]).not_to be_empty end end context 'cross-project reference' do let(:namespace) { create(:namespace, name: 'cross-reference') } - let(:project2) { create(:project, namespace: namespace) } + let(:project2) { create(:project, :public, namespace: namespace) } let(:commit) { project2.commit } let(:reference) { commit.to_reference(project) } - context 'when user can access reference' do - before { allow_cross_reference! } - - it 'links to a valid reference' do - doc = filter("See #{reference}") - - expect(doc.css('a').first.attr('href')). - to eq urls.namespace_project_commit_url(project2.namespace, project2, commit.id) - end - - it 'links with adjacent text' do - doc = filter("Fixed (#{reference}.)") + it 'links to a valid reference' do + doc = filter("See #{reference}") - exp = Regexp.escape(project2.to_reference) - expect(doc.to_html).to match(/\(<a.+>#{exp}@#{commit.short_id}<\/a>\.\)/) - end + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_commit_url(project2.namespace, project2, commit.id) + end - it 'ignores invalid commit IDs on the referenced project' do - exp = act = "Committed #{invalidate_reference(reference)}" - expect(filter(act).to_html).to eq exp - end + it 'links with adjacent text' do + doc = filter("Fixed (#{reference}.)") - it 'adds to the results hash' do - result = pipeline_result("See #{reference}") - expect(result[:references][:commit]).not_to be_empty - end + exp = Regexp.escape(project2.to_reference) + expect(doc.to_html).to match(/\(<a.+>#{exp}@#{commit.short_id}<\/a>\.\)/) end - context 'when user cannot access reference' do - before { disallow_cross_reference! } - - it 'ignores valid references' do - exp = act = "See #{reference}" + it 'ignores invalid commit IDs on the referenced project' do + exp = act = "Committed #{invalidate_reference(reference)}" + expect(filter(act).to_html).to eq exp + end - expect(filter(act).to_html).to eq exp - end + it 'adds to the results hash' do + result = reference_pipeline_result("See #{reference}") + expect(result[:references][:commit]).not_to be_empty end end end diff --git a/spec/lib/gitlab/markdown/cross_project_reference_spec.rb b/spec/lib/gitlab/markdown/cross_project_reference_spec.rb index 4698d6138c2..8d4f9e403a6 100644 --- a/spec/lib/gitlab/markdown/cross_project_reference_spec.rb +++ b/spec/lib/gitlab/markdown/cross_project_reference_spec.rb @@ -2,20 +2,16 @@ require 'spec_helper' module Gitlab::Markdown describe CrossProjectReference do - # context in the html-pipeline sense, not in the rspec sense - let(:context) do - { - current_user: double('user'), - project: double('project') - } - end - include described_class describe '#project_from_ref' do context 'when no project was referenced' do it 'returns the project from context' do - expect(project_from_ref(nil)).to eq context[:project] + project = double + + allow(self).to receive(:context).and_return({ project: project }) + + expect(project_from_ref(nil)).to eq project end end @@ -26,29 +22,13 @@ module Gitlab::Markdown end context 'when referenced project exists' do - let(:project2) { double('referenced project') } + it 'returns the referenced project' do + project2 = double('referenced project') - before do expect(Project).to receive(:find_with_namespace). with('cross/reference').and_return(project2) - end - - context 'and the user has permission to read it' do - it 'returns the referenced project' do - expect(self).to receive(:user_can_reference_project?). - with(project2).and_return(true) - - expect(project_from_ref('cross/reference')).to eq project2 - end - end - - context 'and the user does not have permission to read it' do - it 'returns nil' do - expect(self).to receive(:user_can_reference_project?). - with(project2).and_return(false) - expect(project_from_ref('cross/reference')).to be_nil - end + expect(project_from_ref('cross/reference')).to eq project2 end end end diff --git a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb index 1dd54f58588..94c80ae6611 100644 --- a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb @@ -8,7 +8,7 @@ module Gitlab::Markdown IssuesHelper end - let(:project) { create(:empty_project) } + let(:project) { create(:empty_project, :public) } let(:issue) { create(:issue, project: project) } it 'requires project context' do @@ -68,12 +68,20 @@ module Gitlab::Markdown expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue' end - it 'includes a data-project-id attribute' do + it 'includes a data-project attribute' do doc = filter("Issue #{reference}") link = doc.css('a').first - expect(link).to have_attribute('data-project-id') - expect(link.attr('data-project-id')).to eq project.id.to_s + expect(link).to have_attribute('data-project') + expect(link.attr('data-project')).to eq project.id.to_s + end + + it 'includes a data-issue attribute' do + doc = filter("See #{reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-issue') + expect(link.attr('data-issue')).to eq issue.id.to_s end it 'supports an :only_path context' do @@ -85,60 +93,46 @@ module Gitlab::Markdown end it 'adds to the results hash' do - result = pipeline_result("Fixed #{reference}") + result = reference_pipeline_result("Fixed #{reference}") expect(result[:references][:issue]).to eq [issue] end end context 'cross-project reference' do let(:namespace) { create(:namespace, name: 'cross-reference') } - let(:project2) { create(:empty_project, namespace: namespace) } + let(:project2) { create(:empty_project, :public, namespace: namespace) } let(:issue) { create(:issue, project: project2) } let(:reference) { issue.to_reference(project) } - context 'when user can access reference' do - before { allow_cross_reference! } - - it 'ignores valid references when cross-reference project uses external tracker' do - expect_any_instance_of(Project).to receive(:get_issue). - with(issue.iid).and_return(nil) - - exp = act = "Issue #{reference}" - expect(filter(act).to_html).to eq exp - end + it 'ignores valid references when cross-reference project uses external tracker' do + expect_any_instance_of(Project).to receive(:get_issue). + with(issue.iid).and_return(nil) - it 'links to a valid reference' do - doc = filter("See #{reference}") - - expect(doc.css('a').first.attr('href')). - to eq helper.url_for_issue(issue.iid, project2) - end - - it 'links with adjacent text' do - doc = filter("Fixed (#{reference}.)") - expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) - end + exp = act = "Issue #{reference}" + expect(filter(act).to_html).to eq exp + end - it 'ignores invalid issue IDs on the referenced project' do - exp = act = "Fixed #{invalidate_reference(reference)}" + it 'links to a valid reference' do + doc = filter("See #{reference}") - expect(filter(act).to_html).to eq exp - end + expect(doc.css('a').first.attr('href')). + to eq helper.url_for_issue(issue.iid, project2) + end - it 'adds to the results hash' do - result = pipeline_result("Fixed #{reference}") - expect(result[:references][:issue]).to eq [issue] - end + it 'links with adjacent text' do + doc = filter("Fixed (#{reference}.)") + expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) end - context 'when user cannot access reference' do - before { disallow_cross_reference! } + it 'ignores invalid issue IDs on the referenced project' do + exp = act = "Fixed #{invalidate_reference(reference)}" - it 'ignores valid references' do - exp = act = "See #{reference}" + expect(filter(act).to_html).to eq exp + end - expect(filter(act).to_html).to eq exp - end + it 'adds to the results hash' do + result = reference_pipeline_result("Fixed #{reference}") + expect(result[:references][:issue]).to eq [issue] end end end diff --git a/spec/lib/gitlab/markdown/label_reference_filter_spec.rb b/spec/lib/gitlab/markdown/label_reference_filter_spec.rb index e32089de376..fc21b65a843 100644 --- a/spec/lib/gitlab/markdown/label_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/label_reference_filter_spec.rb @@ -5,7 +5,7 @@ module Gitlab::Markdown describe LabelReferenceFilter do include FilterSpecHelper - let(:project) { create(:empty_project) } + let(:project) { create(:empty_project, :public) } let(:label) { create(:label, project: project) } let(:reference) { label.to_reference } @@ -25,12 +25,20 @@ module Gitlab::Markdown expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-label' end - it 'includes a data-project-id attribute' do + it 'includes a data-project attribute' do doc = filter("Label #{reference}") link = doc.css('a').first - expect(link).to have_attribute('data-project-id') - expect(link.attr('data-project-id')).to eq project.id.to_s + expect(link).to have_attribute('data-project') + expect(link.attr('data-project')).to eq project.id.to_s + end + + it 'includes a data-label attribute' do + doc = filter("See #{reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-label') + expect(link.attr('data-label')).to eq label.id.to_s end it 'supports an :only_path context' do @@ -42,7 +50,7 @@ module Gitlab::Markdown end it 'adds to the results hash' do - result = pipeline_result("Label #{reference}") + result = reference_pipeline_result("Label #{reference}") expect(result[:references][:label]).to eq [label] end diff --git a/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb b/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb index 66616b93368..3ef6cdfff33 100644 --- a/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb @@ -4,7 +4,7 @@ module Gitlab::Markdown describe MergeRequestReferenceFilter do include FilterSpecHelper - let(:project) { create(:project) } + let(:project) { create(:project, :public) } let(:merge) { create(:merge_request, source_project: project) } it 'requires project context' do @@ -56,12 +56,20 @@ module Gitlab::Markdown expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-merge_request' end - it 'includes a data-project-id attribute' do + it 'includes a data-project attribute' do doc = filter("Merge #{reference}") link = doc.css('a').first - expect(link).to have_attribute('data-project-id') - expect(link.attr('data-project-id')).to eq project.id.to_s + expect(link).to have_attribute('data-project') + expect(link.attr('data-project')).to eq project.id.to_s + end + + it 'includes a data-merge-request attribute' do + doc = filter("See #{reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-merge-request') + expect(link.attr('data-merge-request')).to eq merge.id.to_s end it 'supports an :only_path context' do @@ -73,53 +81,39 @@ module Gitlab::Markdown end it 'adds to the results hash' do - result = pipeline_result("Merge #{reference}") + result = reference_pipeline_result("Merge #{reference}") expect(result[:references][:merge_request]).to eq [merge] end end context 'cross-project reference' do let(:namespace) { create(:namespace, name: 'cross-reference') } - let(:project2) { create(:project, namespace: namespace) } + let(:project2) { create(:project, :public, namespace: namespace) } let(:merge) { create(:merge_request, source_project: project2) } let(:reference) { merge.to_reference(project) } - context 'when user can access reference' do - before { allow_cross_reference! } - - it 'links to a valid reference' do - doc = filter("See #{reference}") - - expect(doc.css('a').first.attr('href')). - to eq urls.namespace_project_merge_request_url(project2.namespace, - project, merge) - end - - it 'links with adjacent text' do - doc = filter("Merge (#{reference}.)") - expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) - end - - it 'ignores invalid merge IDs on the referenced project' do - exp = act = "Merge #{invalidate_reference(reference)}" + it 'links to a valid reference' do + doc = filter("See #{reference}") - expect(filter(act).to_html).to eq exp - end + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_merge_request_url(project2.namespace, + project, merge) + end - it 'adds to the results hash' do - result = pipeline_result("Merge #{reference}") - expect(result[:references][:merge_request]).to eq [merge] - end + it 'links with adjacent text' do + doc = filter("Merge (#{reference}.)") + expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) end - context 'when user cannot access reference' do - before { disallow_cross_reference! } + it 'ignores invalid merge IDs on the referenced project' do + exp = act = "Merge #{invalidate_reference(reference)}" - it 'ignores valid references' do - exp = act = "See #{reference}" + expect(filter(act).to_html).to eq exp + end - expect(filter(act).to_html).to eq exp - end + it 'adds to the results hash' do + result = reference_pipeline_result("Merge #{reference}") + expect(result[:references][:merge_request]).to eq [merge] end end end diff --git a/spec/lib/gitlab/markdown/redactor_filter_spec.rb b/spec/lib/gitlab/markdown/redactor_filter_spec.rb new file mode 100644 index 00000000000..eea3f1cf370 --- /dev/null +++ b/spec/lib/gitlab/markdown/redactor_filter_spec.rb @@ -0,0 +1,91 @@ +require 'spec_helper' + +module Gitlab::Markdown + describe RedactorFilter do + include ActionView::Helpers::UrlHelper + include FilterSpecHelper + + it 'ignores non-GFM links' do + html = %(See <a href="https://google.com/">Google</a>) + doc = filter(html, current_user: double) + + expect(doc.css('a').length).to eq 1 + end + + def reference_link(data) + link_to('text', '', class: 'gfm', data: data) + end + + context 'with data-project' do + it 'removes unpermitted Project references' do + user = create(:user) + project = create(:empty_project) + + link = reference_link(project: project.id, reference_filter: Gitlab::Markdown::ReferenceFilter.name) + doc = filter(link, current_user: user) + + expect(doc.css('a').length).to eq 0 + end + + it 'allows permitted Project references' do + user = create(:user) + project = create(:empty_project) + project.team << [user, :master] + + link = reference_link(project: project.id, reference_filter: Gitlab::Markdown::ReferenceFilter.name) + doc = filter(link, current_user: user) + + expect(doc.css('a').length).to eq 1 + end + + it 'handles invalid Project references' do + link = reference_link(project: 12345, reference_filter: Gitlab::Markdown::ReferenceFilter.name) + + expect { filter(link) }.not_to raise_error + end + end + + context "for user references" do + + context 'with data-group' do + it 'removes unpermitted Group references' do + user = create(:user) + group = create(:group) + + link = reference_link(group: group.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name) + doc = filter(link, current_user: user) + + expect(doc.css('a').length).to eq 0 + end + + it 'allows permitted Group references' do + user = create(:user) + group = create(:group) + group.add_developer(user) + + link = reference_link(group: group.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name) + doc = filter(link, current_user: user) + + expect(doc.css('a').length).to eq 1 + end + + it 'handles invalid Group references' do + link = reference_link(group: 12345, reference_filter: Gitlab::Markdown::UserReferenceFilter.name) + + expect { filter(link) }.not_to raise_error + end + end + + context 'with data-user' do + it 'allows any User reference' do + user = create(:user) + + link = reference_link(user: user.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name) + doc = filter(link) + + expect(doc.css('a').length).to eq 1 + end + end + end + end +end diff --git a/spec/lib/gitlab/markdown/reference_gatherer_filter_spec.rb b/spec/lib/gitlab/markdown/reference_gatherer_filter_spec.rb new file mode 100644 index 00000000000..4fa473ad191 --- /dev/null +++ b/spec/lib/gitlab/markdown/reference_gatherer_filter_spec.rb @@ -0,0 +1,89 @@ +require 'spec_helper' + +module Gitlab::Markdown + describe ReferenceGathererFilter do + include ActionView::Helpers::UrlHelper + include FilterSpecHelper + + def reference_link(data) + link_to('text', '', class: 'gfm', data: data) + end + + context "for issue references" do + + context 'with data-project' do + it 'removes unpermitted Project references' do + user = create(:user) + project = create(:empty_project) + issue = create(:issue, project: project) + + link = reference_link(project: project.id, issue: issue.id, reference_filter: Gitlab::Markdown::IssueReferenceFilter.name) + result = pipeline_result(link, current_user: user) + + expect(result[:references][:issue]).to be_empty + end + + it 'allows permitted Project references' do + user = create(:user) + project = create(:empty_project) + issue = create(:issue, project: project) + project.team << [user, :master] + + link = reference_link(project: project.id, issue: issue.id, reference_filter: Gitlab::Markdown::IssueReferenceFilter.name) + result = pipeline_result(link, current_user: user) + + expect(result[:references][:issue]).to eq([issue]) + end + + it 'handles invalid Project references' do + link = reference_link(project: 12345, issue: 12345, reference_filter: Gitlab::Markdown::IssueReferenceFilter.name) + + expect { pipeline_result(link) }.not_to raise_error + end + end + end + + context "for user references" do + + context 'with data-group' do + it 'removes unpermitted Group references' do + user = create(:user) + group = create(:group) + + link = reference_link(group: group.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name) + result = pipeline_result(link, current_user: user) + + expect(result[:references][:user]).to be_empty + end + + it 'allows permitted Group references' do + user = create(:user) + group = create(:group) + group.add_developer(user) + + link = reference_link(group: group.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name) + result = pipeline_result(link, current_user: user) + + expect(result[:references][:user]).to eq([user]) + end + + it 'handles invalid Group references' do + link = reference_link(group: 12345, reference_filter: Gitlab::Markdown::UserReferenceFilter.name) + + expect { pipeline_result(link) }.not_to raise_error + end + end + + context 'with data-user' do + it 'allows any User reference' do + user = create(:user) + + link = reference_link(user: user.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name) + result = pipeline_result(link) + + expect(result[:references][:user]).to eq([user]) + end + end + end + end +end diff --git a/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb b/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb index fd3f0d20fad..9d9652dba46 100644 --- a/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb @@ -4,7 +4,7 @@ module Gitlab::Markdown describe SnippetReferenceFilter do include FilterSpecHelper - let(:project) { create(:empty_project) } + let(:project) { create(:empty_project, :public) } let(:snippet) { create(:project_snippet, project: project) } let(:reference) { snippet.to_reference } @@ -55,12 +55,20 @@ module Gitlab::Markdown expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-snippet' end - it 'includes a data-project-id attribute' do + it 'includes a data-project attribute' do doc = filter("Snippet #{reference}") link = doc.css('a').first - expect(link).to have_attribute('data-project-id') - expect(link.attr('data-project-id')).to eq project.id.to_s + expect(link).to have_attribute('data-project') + expect(link.attr('data-project')).to eq project.id.to_s + end + + it 'includes a data-snippet attribute' do + doc = filter("See #{reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-snippet') + expect(link.attr('data-snippet')).to eq snippet.id.to_s end it 'supports an :only_path context' do @@ -72,52 +80,38 @@ module Gitlab::Markdown end it 'adds to the results hash' do - result = pipeline_result("Snippet #{reference}") + result = reference_pipeline_result("Snippet #{reference}") expect(result[:references][:snippet]).to eq [snippet] end end context 'cross-project reference' do let(:namespace) { create(:namespace, name: 'cross-reference') } - let(:project2) { create(:empty_project, namespace: namespace) } + let(:project2) { create(:empty_project, :public, namespace: namespace) } let(:snippet) { create(:project_snippet, project: project2) } let(:reference) { snippet.to_reference(project) } - context 'when user can access reference' do - before { allow_cross_reference! } - - it 'links to a valid reference' do - doc = filter("See #{reference}") - - expect(doc.css('a').first.attr('href')). - to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet) - end - - it 'links with adjacent text' do - doc = filter("See (#{reference}.)") - expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) - end - - it 'ignores invalid snippet IDs on the referenced project' do - exp = act = "See #{invalidate_reference(reference)}" + it 'links to a valid reference' do + doc = filter("See #{reference}") - expect(filter(act).to_html).to eq exp - end + expect(doc.css('a').first.attr('href')). + to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet) + end - it 'adds to the results hash' do - result = pipeline_result("Snippet #{reference}") - expect(result[:references][:snippet]).to eq [snippet] - end + it 'links with adjacent text' do + doc = filter("See (#{reference}.)") + expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/) end - context 'when user cannot access reference' do - before { disallow_cross_reference! } + it 'ignores invalid snippet IDs on the referenced project' do + exp = act = "See #{invalidate_reference(reference)}" - it 'ignores valid references' do - exp = act = "See #{reference}" + expect(filter(act).to_html).to eq exp + end - expect(filter(act).to_html).to eq exp - end + it 'adds to the results hash' do + result = reference_pipeline_result("Snippet #{reference}") + expect(result[:references][:snippet]).to eq [snippet] end end end diff --git a/spec/lib/gitlab/markdown/user_reference_filter_spec.rb b/spec/lib/gitlab/markdown/user_reference_filter_spec.rb index b2155fab59b..d9e0d7c42db 100644 --- a/spec/lib/gitlab/markdown/user_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/user_reference_filter_spec.rb @@ -4,7 +4,7 @@ module Gitlab::Markdown describe UserReferenceFilter do include FilterSpecHelper - let(:project) { create(:empty_project) } + let(:project) { create(:empty_project, :public) } let(:user) { create(:user) } let(:reference) { user.to_reference } @@ -39,7 +39,7 @@ module Gitlab::Markdown end it 'adds to the results hash' do - result = pipeline_result("Hey #{reference}") + result = reference_pipeline_result("Hey #{reference}") expect(result[:references][:user]).to eq [project.creator] end end @@ -64,59 +64,40 @@ module Gitlab::Markdown expect(doc.css('a').length).to eq 1 end - it 'includes a data-user-id attribute' do + it 'includes a data-user attribute' do doc = filter("Hey #{reference}") link = doc.css('a').first - expect(link).to have_attribute('data-user-id') - expect(link.attr('data-user-id')).to eq user.namespace.owner_id.to_s + expect(link).to have_attribute('data-user') + expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s end it 'adds to the results hash' do - result = pipeline_result("Hey #{reference}") + result = reference_pipeline_result("Hey #{reference}") expect(result[:references][:user]).to eq [user] end end context 'mentioning a group' do let(:group) { create(:group) } - let(:user) { create(:user) } let(:reference) { group.to_reference } - context 'that the current user can read' do - before do - group.add_developer(user) - end - - it 'links to the Group' do - doc = filter("Hey #{reference}", current_user: user) - expect(doc.css('a').first.attr('href')).to eq urls.group_url(group) - end - - it 'includes a data-group-id attribute' do - doc = filter("Hey #{reference}", current_user: user) - link = doc.css('a').first + it 'links to the Group' do + doc = filter("Hey #{reference}") + expect(doc.css('a').first.attr('href')).to eq urls.group_url(group) + end - expect(link).to have_attribute('data-group-id') - expect(link.attr('data-group-id')).to eq group.id.to_s - end + it 'includes a data-group attribute' do + doc = filter("Hey #{reference}") + link = doc.css('a').first - it 'adds to the results hash' do - result = pipeline_result("Hey #{reference}", current_user: user) - expect(result[:references][:user]).to eq group.users - end + expect(link).to have_attribute('data-group') + expect(link.attr('data-group')).to eq group.id.to_s end - context 'that the current user cannot read' do - it 'ignores references to the Group' do - doc = filter("Hey #{reference}", current_user: user) - expect(doc.to_html).to eq "Hey #{reference}" - end - - it 'does not add to the results hash' do - result = pipeline_result("Hey #{reference}", current_user: user) - expect(result[:references][:user]).to eq [] - end + it 'adds to the results hash' do + result = reference_pipeline_result("Hey #{reference}") + expect(result[:references][:user]).to eq group.users end end diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb index 088e34f050c..ad84d2274e8 100644 --- a/spec/lib/gitlab/reference_extractor_spec.rb +++ b/spec/lib/gitlab/reference_extractor_spec.rb @@ -13,7 +13,7 @@ describe Gitlab::ReferenceExtractor do project.team << [@u_bar, :guest] subject.analyze('@foo, @baduser, @bar, and @offteam') - expect(subject.users).to eq([@u_foo, @u_bar, @u_offteam]) + expect(subject.users).to match_array([@u_foo, @u_bar, @u_offteam]) end it 'ignores user mentions inside specific elements' do @@ -37,7 +37,7 @@ describe Gitlab::ReferenceExtractor do > @offteam }) - expect(subject.users).to eq([]) + expect(subject.users).to match_array([]) end it 'accesses valid issue objects' do @@ -45,7 +45,7 @@ describe Gitlab::ReferenceExtractor do @i1 = create(:issue, project: project) subject.analyze("#{@i0.to_reference}, #{@i1.to_reference}, and #{Issue.reference_prefix}999.") - expect(subject.issues).to eq([@i0, @i1]) + expect(subject.issues).to match_array([@i0, @i1]) end it 'accesses valid merge requests' do @@ -53,7 +53,7 @@ describe Gitlab::ReferenceExtractor do @m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'feature_conflict') subject.analyze("!999, !#{@m1.iid}, and !#{@m0.iid}.") - expect(subject.merge_requests).to eq([@m1, @m0]) + expect(subject.merge_requests).to match_array([@m1, @m0]) end it 'accesses valid labels' do @@ -62,7 +62,7 @@ describe Gitlab::ReferenceExtractor do @l2 = create(:label) subject.analyze("~#{@l0.id}, ~999, ~#{@l2.id}, ~#{@l1.id}") - expect(subject.labels).to eq([@l0, @l1]) + expect(subject.labels).to match_array([@l0, @l1]) end it 'accesses valid snippets' do @@ -71,7 +71,7 @@ describe Gitlab::ReferenceExtractor do @s2 = create(:project_snippet) subject.analyze("$#{@s0.id}, $999, $#{@s2.id}, $#{@s1.id}") - expect(subject.snippets).to eq([@s0, @s1]) + expect(subject.snippets).to match_array([@s0, @s1]) end it 'accesses valid commits' do @@ -109,7 +109,7 @@ describe Gitlab::ReferenceExtractor do subject.analyze("this refers issue #{issue.to_reference(project)}") extracted = subject.issues expect(extracted.size).to eq(1) - expect(extracted).to eq([issue]) + expect(extracted).to match_array([issue]) end end end diff --git a/spec/support/filter_spec_helper.rb b/spec/support/filter_spec_helper.rb index 203117aee70..97e5c270a59 100644 --- a/spec/support/filter_spec_helper.rb +++ b/spec/support/filter_spec_helper.rb @@ -29,12 +29,19 @@ module FilterSpecHelper # # Returns the Hash def pipeline_result(body, contexts = {}) - contexts.reverse_merge!(project: project) + contexts.reverse_merge!(project: project) if defined?(project) pipeline = HTML::Pipeline.new([described_class], contexts) pipeline.call(body) end + def reference_pipeline_result(body, contexts = {}) + contexts.reverse_merge!(project: project) if defined?(project) + + pipeline = HTML::Pipeline.new([described_class, Gitlab::Markdown::ReferenceGathererFilter], contexts) + pipeline.call(body) + end + # Modify a String reference to make it invalid # # Commit SHAs get reversed, IDs get incremented by 1, all other Strings get @@ -55,20 +62,6 @@ module FilterSpecHelper end end - # Stub CrossProjectReference#user_can_reference_project? to return true for - # the current test - def allow_cross_reference! - allow_any_instance_of(described_class). - to receive(:user_can_reference_project?).and_return(true) - end - - # Stub CrossProjectReference#user_can_reference_project? to return false for - # the current test - def disallow_cross_reference! - allow_any_instance_of(described_class). - to receive(:user_can_reference_project?).and_return(false) - end - # Shortcut to Rails' auto-generated routes helpers, to avoid including the # module def urls diff --git a/spec/support/markdown_feature.rb b/spec/support/markdown_feature.rb index 39a64391460..bedc1a7f1db 100644 --- a/spec/support/markdown_feature.rb +++ b/spec/support/markdown_feature.rb @@ -15,18 +15,17 @@ class MarkdownFeature end def group - unless @group - @group = create(:group) - @group.add_developer(user) + @group ||= create(:group).tap do |group| + group.add_developer(user) end - - @group end # Direct references ---------------------------------------------------------- def project - @project ||= create(:project) + @project ||= create(:project).tap do |project| + project.team << [user, :master] + end end def issue @@ -46,12 +45,10 @@ class MarkdownFeature end def commit_range - unless @commit_range + @commit_range ||= begin commit2 = project.commit('HEAD~3') - @commit_range = CommitRange.new("#{commit.id}...#{commit2.id}", project) + CommitRange.new("#{commit.id}...#{commit2.id}", project) end - - @commit_range end def simple_label @@ -65,13 +62,12 @@ class MarkdownFeature # Cross-references ----------------------------------------------------------- def xproject - unless @xproject + @xproject ||= begin namespace = create(:namespace, name: 'cross-reference') - @xproject = create(:project, namespace: namespace) - @xproject.team << [user, :developer] + create(:project, namespace: namespace) do |project| + project.team << [user, :developer] + end end - - @xproject end def xissue @@ -91,12 +87,10 @@ class MarkdownFeature end def xcommit_range - unless @xcommit_range + @xcommit_range ||= begin xcommit2 = xproject.commit('HEAD~2') - @xcommit_range = CommitRange.new("#{xcommit.id}...#{xcommit2.id}", xproject) + CommitRange.new("#{xcommit.id}...#{xcommit2.id}", xproject) end - - @xcommit_range end def raw_markdown diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb index f584904845e..3bb568f4d49 100644 --- a/spec/support/mentionable_shared_examples.rb +++ b/spec/support/mentionable_shared_examples.rb @@ -50,6 +50,8 @@ def common_mentionable_setup } extra_commits.each { |c| commitmap[c.short_id] = c } + allow(Project).to receive(:find).and_call_original + allow(Project).to receive(:find).with(project.id.to_s).and_return(project) allow(project.repository).to receive(:commit) { |sha| commitmap[sha] } set_mentionable_text.call(ref_string) |