From cea7ba513c6d623ef921fba07910e98cca71435b Mon Sep 17 00:00:00 2001 From: Sarah Yasonik Date: Tue, 16 Jul 2019 20:19:08 +0000 Subject: Rename Redactor classes to ReferenceRedactor --- spec/lib/banzai/filter/redactor_filter_spec.rb | 205 --------------------- .../filter/reference_redactor_filter_spec.rb | 205 +++++++++++++++++++++ spec/lib/banzai/object_renderer_spec.rb | 8 +- spec/lib/banzai/redactor_spec.rb | 182 ------------------ spec/lib/banzai/reference_redactor_spec.rb | 182 ++++++++++++++++++ 5 files changed, 391 insertions(+), 391 deletions(-) delete mode 100644 spec/lib/banzai/filter/redactor_filter_spec.rb create mode 100644 spec/lib/banzai/filter/reference_redactor_filter_spec.rb delete mode 100644 spec/lib/banzai/redactor_spec.rb create mode 100644 spec/lib/banzai/reference_redactor_spec.rb (limited to 'spec/lib') diff --git a/spec/lib/banzai/filter/redactor_filter_spec.rb b/spec/lib/banzai/filter/redactor_filter_spec.rb deleted file mode 100644 index 919825a6102..00000000000 --- a/spec/lib/banzai/filter/redactor_filter_spec.rb +++ /dev/null @@ -1,205 +0,0 @@ -require 'spec_helper' - -describe Banzai::Filter::RedactorFilter do - include ActionView::Helpers::UrlHelper - include FilterSpecHelper - - it 'ignores non-GFM links' do - html = %(See Google) - doc = filter(html, current_user: build(:user)) - - expect(doc.css('a').length).to eq 1 - end - - def reference_link(data) - link_to('text', '', class: 'gfm', data: data) - end - - it 'skips when the skip_redaction flag is set' do - user = create(:user) - project = create(:project) - - link = reference_link(project: project.id, reference_type: 'test') - doc = filter(link, current_user: user, skip_redaction: true) - - expect(doc.css('a').length).to eq 1 - end - - context 'with data-project' do - let(:parser_class) do - Class.new(Banzai::ReferenceParser::BaseParser) do - self.reference_type = :test - end - end - - before do - allow(Banzai::ReferenceParser).to receive(:[]) - .with('test') - .and_return(parser_class) - end - - context 'valid projects' do - before do - allow_any_instance_of(Banzai::ReferenceParser::BaseParser).to receive(:can_read_reference?).and_return(true) - end - - it 'allows permitted Project references' do - user = create(:user) - project = create(:project) - project.add_maintainer(user) - - link = reference_link(project: project.id, reference_type: 'test') - doc = filter(link, current_user: user) - - expect(doc.css('a').length).to eq 1 - end - end - - context 'invalid projects' do - before do - allow_any_instance_of(Banzai::ReferenceParser::BaseParser).to receive(:can_read_reference?).and_return(false) - end - - it 'removes unpermitted references' do - user = create(:user) - project = create(:project) - - link = reference_link(project: project.id, reference_type: 'test') - doc = filter(link, current_user: user) - - expect(doc.css('a').length).to eq 0 - end - - it 'handles invalid references' do - link = reference_link(project: 12345, reference_type: 'test') - - expect { filter(link) }.not_to raise_error - end - end - end - - context 'with data-issue' do - context 'for confidential issues' do - it 'removes references for non project members' do - non_member = create(:user) - project = create(:project, :public) - issue = create(:issue, :confidential, project: project) - - link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') - doc = filter(link, current_user: non_member) - - expect(doc.css('a').length).to eq 0 - end - - it 'removes references for project members with guest role' do - member = create(:user) - project = create(:project, :public) - project.add_guest(member) - issue = create(:issue, :confidential, project: project) - - link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') - doc = filter(link, current_user: member) - - expect(doc.css('a').length).to eq 0 - end - - it 'allows references for author' do - author = create(:user) - project = create(:project, :public) - issue = create(:issue, :confidential, project: project, author: author) - - link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') - doc = filter(link, current_user: author) - - expect(doc.css('a').length).to eq 1 - end - - it 'allows references for assignee' do - assignee = create(:user) - project = create(:project, :public) - issue = create(:issue, :confidential, project: project, assignees: [assignee]) - - link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') - doc = filter(link, current_user: assignee) - - expect(doc.css('a').length).to eq 1 - end - - it 'allows references for project members' do - member = create(:user) - project = create(:project, :public) - project.add_developer(member) - issue = create(:issue, :confidential, project: project) - - link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') - doc = filter(link, current_user: member) - - expect(doc.css('a').length).to eq 1 - end - - it 'allows references for admin' do - admin = create(:admin) - project = create(:project, :public) - issue = create(:issue, :confidential, project: project) - - link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') - doc = filter(link, current_user: admin) - - expect(doc.css('a').length).to eq 1 - end - end - - it 'allows references for non confidential issues' do - user = create(:user) - project = create(:project, :public) - issue = create(:issue, project: project) - - link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') - doc = filter(link, current_user: user) - - expect(doc.css('a').length).to eq 1 - end - end - - context "for user references" do - context 'with data-group' do - it 'removes unpermitted Group references' do - user = create(:user) - group = create(:group, :private) - - link = reference_link(group: group.id, reference_type: 'user') - 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, :private) - group.add_developer(user) - - link = reference_link(group: group.id, reference_type: 'user') - 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_type: 'user') - - 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_type: 'user') - doc = filter(link) - - expect(doc.css('a').length).to eq 1 - end - end - end -end diff --git a/spec/lib/banzai/filter/reference_redactor_filter_spec.rb b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb new file mode 100644 index 00000000000..e87440895e0 --- /dev/null +++ b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb @@ -0,0 +1,205 @@ +require 'spec_helper' + +describe Banzai::Filter::ReferenceRedactorFilter do + include ActionView::Helpers::UrlHelper + include FilterSpecHelper + + it 'ignores non-GFM links' do + html = %(See Google) + doc = filter(html, current_user: build(:user)) + + expect(doc.css('a').length).to eq 1 + end + + def reference_link(data) + link_to('text', '', class: 'gfm', data: data) + end + + it 'skips when the skip_redaction flag is set' do + user = create(:user) + project = create(:project) + + link = reference_link(project: project.id, reference_type: 'test') + doc = filter(link, current_user: user, skip_redaction: true) + + expect(doc.css('a').length).to eq 1 + end + + context 'with data-project' do + let(:parser_class) do + Class.new(Banzai::ReferenceParser::BaseParser) do + self.reference_type = :test + end + end + + before do + allow(Banzai::ReferenceParser).to receive(:[]) + .with('test') + .and_return(parser_class) + end + + context 'valid projects' do + before do + allow_any_instance_of(Banzai::ReferenceParser::BaseParser).to receive(:can_read_reference?).and_return(true) + end + + it 'allows permitted Project references' do + user = create(:user) + project = create(:project) + project.add_maintainer(user) + + link = reference_link(project: project.id, reference_type: 'test') + doc = filter(link, current_user: user) + + expect(doc.css('a').length).to eq 1 + end + end + + context 'invalid projects' do + before do + allow_any_instance_of(Banzai::ReferenceParser::BaseParser).to receive(:can_read_reference?).and_return(false) + end + + it 'removes unpermitted references' do + user = create(:user) + project = create(:project) + + link = reference_link(project: project.id, reference_type: 'test') + doc = filter(link, current_user: user) + + expect(doc.css('a').length).to eq 0 + end + + it 'handles invalid references' do + link = reference_link(project: 12345, reference_type: 'test') + + expect { filter(link) }.not_to raise_error + end + end + end + + context 'with data-issue' do + context 'for confidential issues' do + it 'removes references for non project members' do + non_member = create(:user) + project = create(:project, :public) + issue = create(:issue, :confidential, project: project) + + link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') + doc = filter(link, current_user: non_member) + + expect(doc.css('a').length).to eq 0 + end + + it 'removes references for project members with guest role' do + member = create(:user) + project = create(:project, :public) + project.add_guest(member) + issue = create(:issue, :confidential, project: project) + + link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') + doc = filter(link, current_user: member) + + expect(doc.css('a').length).to eq 0 + end + + it 'allows references for author' do + author = create(:user) + project = create(:project, :public) + issue = create(:issue, :confidential, project: project, author: author) + + link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') + doc = filter(link, current_user: author) + + expect(doc.css('a').length).to eq 1 + end + + it 'allows references for assignee' do + assignee = create(:user) + project = create(:project, :public) + issue = create(:issue, :confidential, project: project, assignees: [assignee]) + + link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') + doc = filter(link, current_user: assignee) + + expect(doc.css('a').length).to eq 1 + end + + it 'allows references for project members' do + member = create(:user) + project = create(:project, :public) + project.add_developer(member) + issue = create(:issue, :confidential, project: project) + + link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') + doc = filter(link, current_user: member) + + expect(doc.css('a').length).to eq 1 + end + + it 'allows references for admin' do + admin = create(:admin) + project = create(:project, :public) + issue = create(:issue, :confidential, project: project) + + link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') + doc = filter(link, current_user: admin) + + expect(doc.css('a').length).to eq 1 + end + end + + it 'allows references for non confidential issues' do + user = create(:user) + project = create(:project, :public) + issue = create(:issue, project: project) + + link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') + doc = filter(link, current_user: user) + + expect(doc.css('a').length).to eq 1 + end + end + + context "for user references" do + context 'with data-group' do + it 'removes unpermitted Group references' do + user = create(:user) + group = create(:group, :private) + + link = reference_link(group: group.id, reference_type: 'user') + 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, :private) + group.add_developer(user) + + link = reference_link(group: group.id, reference_type: 'user') + 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_type: 'user') + + 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_type: 'user') + doc = filter(link) + + expect(doc.css('a').length).to eq 1 + end + end + end +end diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb index 7b855251a74..e3e6e22568c 100644 --- a/spec/lib/banzai/object_renderer_spec.rb +++ b/spec/lib/banzai/object_renderer_spec.rb @@ -22,8 +22,8 @@ describe Banzai::ObjectRenderer do expect(object.user_visible_reference_count).to eq 0 end - it 'calls Banzai::Redactor to perform redaction' do - expect_any_instance_of(Banzai::Redactor).to receive(:redact).and_call_original + it 'calls Banzai::ReferenceRedactor to perform redaction' do + expect_any_instance_of(Banzai::ReferenceRedactor).to receive(:redact).and_call_original renderer.render([object], :note) end @@ -82,8 +82,8 @@ describe Banzai::ObjectRenderer do expect(cacheless_thing.redacted_title_html).to eq("Merge branch 'branch-merged' into 'master'") end - it 'calls Banzai::Redactor to perform redaction' do - expect_any_instance_of(Banzai::Redactor).to receive(:redact).and_call_original + it 'calls Banzai::ReferenceRedactor to perform redaction' do + expect_any_instance_of(Banzai::ReferenceRedactor).to receive(:redact).and_call_original renderer.render([cacheless_thing], :title) end diff --git a/spec/lib/banzai/redactor_spec.rb b/spec/lib/banzai/redactor_spec.rb deleted file mode 100644 index 718649e0e10..00000000000 --- a/spec/lib/banzai/redactor_spec.rb +++ /dev/null @@ -1,182 +0,0 @@ -require 'spec_helper' - -describe Banzai::Redactor do - let(:user) { create(:user) } - let(:project) { build(:project) } - let(:redactor) { described_class.new(Banzai::RenderContext.new(project, user)) } - - describe '#redact' do - context 'when reference not visible to user' do - before do - expect(redactor).to receive(:nodes_visible_to_user).and_return([]) - end - - it 'redacts an array of documents' do - doc1 = Nokogiri::HTML - .fragment('foo') - - doc2 = Nokogiri::HTML - .fragment('bar') - - redacted_data = redactor.redact([doc1, doc2]) - - expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2]) - expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([0, 0]) - expect(doc1.to_html).to eq('foo') - expect(doc2.to_html).to eq('bar') - end - - it 'replaces redacted reference with inner HTML' do - doc = Nokogiri::HTML.fragment("foo") - redactor.redact([doc]) - expect(doc.to_html).to eq('foo') - end - - context 'when data-original attribute provided' do - let(:original_content) { 'foo' } - it 'replaces redacted reference with original content' do - doc = Nokogiri::HTML.fragment("bar") - redactor.redact([doc]) - expect(doc.to_html).to eq(original_content) - end - - it 'does not replace redacted reference with original content if href is given' do - html = "Marge" - doc = Nokogiri::HTML.fragment(html) - redactor.redact([doc]) - expect(doc.to_html).to eq('Marge') - end - - it 'uses the original content as the link content if given' do - html = "Marge" - doc = Nokogiri::HTML.fragment(html) - redactor.redact([doc]) - expect(doc.to_html).to eq('Homer') - end - end - end - - context 'when project is in pending delete' do - let!(:issue) { create(:issue, project: project) } - let(:redactor) { described_class.new(Banzai::RenderContext.new(project, user)) } - - before do - project.update(pending_delete: true) - end - - it 'redacts an issue attached' do - doc = Nokogiri::HTML.fragment("foo") - - redactor.redact([doc]) - - expect(doc.to_html).to eq('foo') - end - - it 'redacts an external issue' do - doc = Nokogiri::HTML.fragment("foo") - - redactor.redact([doc]) - - expect(doc.to_html).to eq('foo') - end - end - - context 'when reference visible to user' do - it 'does not redact an array of documents' do - doc1_html = 'foo' - doc1 = Nokogiri::HTML.fragment(doc1_html) - - doc2_html = 'bar' - doc2 = Nokogiri::HTML.fragment(doc2_html) - - nodes = redactor.document_nodes([doc1, doc2]).map { |x| x[:nodes] } - expect(redactor).to receive(:nodes_visible_to_user).and_return(nodes.flatten) - - redacted_data = redactor.redact([doc1, doc2]) - - expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2]) - expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([1, 1]) - expect(doc1.to_html).to eq(doc1_html) - expect(doc2.to_html).to eq(doc2_html) - end - end - end - - context 'when the user cannot read cross project' do - include ActionView::Helpers::UrlHelper - let(:project) { create(:project) } - let(:other_project) { create(:project, :public) } - - def create_link(issuable) - type = issuable.class.name.underscore.downcase - link_to(issuable.to_reference, '', - class: 'gfm has-tooltip', - title: issuable.title, - data: { - reference_type: type, - "#{type}": issuable.id - }) - end - - before do - project.add_developer(user) - - allow(Ability).to receive(:allowed?).and_call_original - allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global) { false } - allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } - end - - it 'skips links to issues within the same project' do - issue = create(:issue, project: project) - link = create_link(issue) - doc = Nokogiri::HTML.fragment(link) - - redactor.redact([doc]) - result = doc.css('a').last - - expect(result['class']).to include('has-tooltip') - expect(result['title']).to eq(issue.title) - end - - it 'removes info from a cross project reference' do - issue = create(:issue, project: other_project) - link = create_link(issue) - doc = Nokogiri::HTML.fragment(link) - - redactor.redact([doc]) - result = doc.css('a').last - - expect(result['class']).not_to include('has-tooltip') - expect(result['title']).to be_empty - end - end - - describe '#redact_nodes' do - it 'redacts an Array of nodes' do - doc = Nokogiri::HTML.fragment('foo') - node = doc.children[0] - - expect(redactor).to receive(:nodes_visible_to_user) - .with([node]) - .and_return(Set.new) - - redactor.redact_document_nodes([{ document: doc, nodes: [node] }]) - - expect(doc.to_html).to eq('foo') - end - end - - describe '#nodes_visible_to_user' do - it 'returns a Set containing the visible nodes' do - doc = Nokogiri::HTML.fragment('') - node = doc.children[0] - - expect_any_instance_of(Banzai::ReferenceParser::IssueParser) - .to receive(:nodes_visible_to_user) - .with(user, [node]) - .and_return([node]) - - expect(redactor.nodes_visible_to_user([node])).to eq(Set.new([node])) - end - end -end diff --git a/spec/lib/banzai/reference_redactor_spec.rb b/spec/lib/banzai/reference_redactor_spec.rb new file mode 100644 index 00000000000..a3b47c4d826 --- /dev/null +++ b/spec/lib/banzai/reference_redactor_spec.rb @@ -0,0 +1,182 @@ +require 'spec_helper' + +describe Banzai::ReferenceRedactor do + let(:user) { create(:user) } + let(:project) { build(:project) } + let(:redactor) { described_class.new(Banzai::RenderContext.new(project, user)) } + + describe '#redact' do + context 'when reference not visible to user' do + before do + expect(redactor).to receive(:nodes_visible_to_user).and_return([]) + end + + it 'redacts an array of documents' do + doc1 = Nokogiri::HTML + .fragment('foo') + + doc2 = Nokogiri::HTML + .fragment('bar') + + redacted_data = redactor.redact([doc1, doc2]) + + expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2]) + expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([0, 0]) + expect(doc1.to_html).to eq('foo') + expect(doc2.to_html).to eq('bar') + end + + it 'replaces redacted reference with inner HTML' do + doc = Nokogiri::HTML.fragment("foo") + redactor.redact([doc]) + expect(doc.to_html).to eq('foo') + end + + context 'when data-original attribute provided' do + let(:original_content) { 'foo' } + it 'replaces redacted reference with original content' do + doc = Nokogiri::HTML.fragment("bar") + redactor.redact([doc]) + expect(doc.to_html).to eq(original_content) + end + + it 'does not replace redacted reference with original content if href is given' do + html = "Marge" + doc = Nokogiri::HTML.fragment(html) + redactor.redact([doc]) + expect(doc.to_html).to eq('Marge') + end + + it 'uses the original content as the link content if given' do + html = "Marge" + doc = Nokogiri::HTML.fragment(html) + redactor.redact([doc]) + expect(doc.to_html).to eq('Homer') + end + end + end + + context 'when project is in pending delete' do + let!(:issue) { create(:issue, project: project) } + let(:redactor) { described_class.new(Banzai::RenderContext.new(project, user)) } + + before do + project.update(pending_delete: true) + end + + it 'redacts an issue attached' do + doc = Nokogiri::HTML.fragment("foo") + + redactor.redact([doc]) + + expect(doc.to_html).to eq('foo') + end + + it 'redacts an external issue' do + doc = Nokogiri::HTML.fragment("foo") + + redactor.redact([doc]) + + expect(doc.to_html).to eq('foo') + end + end + + context 'when reference visible to user' do + it 'does not redact an array of documents' do + doc1_html = 'foo' + doc1 = Nokogiri::HTML.fragment(doc1_html) + + doc2_html = 'bar' + doc2 = Nokogiri::HTML.fragment(doc2_html) + + nodes = redactor.document_nodes([doc1, doc2]).map { |x| x[:nodes] } + expect(redactor).to receive(:nodes_visible_to_user).and_return(nodes.flatten) + + redacted_data = redactor.redact([doc1, doc2]) + + expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2]) + expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([1, 1]) + expect(doc1.to_html).to eq(doc1_html) + expect(doc2.to_html).to eq(doc2_html) + end + end + end + + context 'when the user cannot read cross project' do + include ActionView::Helpers::UrlHelper + let(:project) { create(:project) } + let(:other_project) { create(:project, :public) } + + def create_link(issuable) + type = issuable.class.name.underscore.downcase + link_to(issuable.to_reference, '', + class: 'gfm has-tooltip', + title: issuable.title, + data: { + reference_type: type, + "#{type}": issuable.id + }) + end + + before do + project.add_developer(user) + + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global) { false } + allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } + end + + it 'skips links to issues within the same project' do + issue = create(:issue, project: project) + link = create_link(issue) + doc = Nokogiri::HTML.fragment(link) + + redactor.redact([doc]) + result = doc.css('a').last + + expect(result['class']).to include('has-tooltip') + expect(result['title']).to eq(issue.title) + end + + it 'removes info from a cross project reference' do + issue = create(:issue, project: other_project) + link = create_link(issue) + doc = Nokogiri::HTML.fragment(link) + + redactor.redact([doc]) + result = doc.css('a').last + + expect(result['class']).not_to include('has-tooltip') + expect(result['title']).to be_empty + end + end + + describe '#redact_nodes' do + it 'redacts an Array of nodes' do + doc = Nokogiri::HTML.fragment('foo') + node = doc.children[0] + + expect(redactor).to receive(:nodes_visible_to_user) + .with([node]) + .and_return(Set.new) + + redactor.redact_document_nodes([{ document: doc, nodes: [node] }]) + + expect(doc.to_html).to eq('foo') + end + end + + describe '#nodes_visible_to_user' do + it 'returns a Set containing the visible nodes' do + doc = Nokogiri::HTML.fragment('') + node = doc.children[0] + + expect_any_instance_of(Banzai::ReferenceParser::IssueParser) + .to receive(:nodes_visible_to_user) + .with(user, [node]) + .and_return([node]) + + expect(redactor.nodes_visible_to_user([node])).to eq(Set.new([node])) + end + end +end -- cgit v1.2.3