Commit bc4a96a0 authored by Jan Provaznik's avatar Jan Provaznik

Merge branch 'ajk-design-references-features-spec' into 'master'

Add Design Parser

Closes #199475

See merge request gitlab-org/gitlab!24001
parents 691b83eb 3396e92d
---
title: Fix rendering of design management references
merge_request: 24001
author:
type: fixed
...@@ -7,6 +7,8 @@ module Banzai ...@@ -7,6 +7,8 @@ module Banzai
Identifier = Struct.new(:issue_iid, :filename, keyword_init: true) Identifier = Struct.new(:issue_iid, :filename, keyword_init: true)
self.reference_type = :design
# This filter must be enabled by setting the following flags: # This filter must be enabled by setting the following flags:
# - design_management # - design_management
# - design_management_reference_filter_gfm_pipeline # - design_management_reference_filter_gfm_pipeline
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class DesignParser < BaseParser
self.reference_type = :design
def references_relation
DesignManagement::Design
end
def nodes_visible_to_user(user, nodes)
issues = issues_for_nodes(nodes)
issue_attr = 'data-issue'
nodes.select do |node|
if node.has_attribute?(issue_attr)
can?(user, :read_design, issues[node])
else
true
end
end
end
def issues_for_nodes(nodes)
relation = Issue.includes(project: [:project_feature])
grouped_objects_for_nodes(nodes, relation, 'data-issue')
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe 'viewing issues with design references' do
include DesignManagementTestHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project_empty_repo, :public) }
let_it_be(:design_issue) { create(:issue, project: project) }
let_it_be(:design_a) { create(:design, :with_file, issue: design_issue) }
let_it_be(:design_b) { create(:design, :with_file, issue: design_issue) }
let(:issue) { create(:issue, project: project, description: description) }
let(:description) do
<<~MD
Designs:
* #{design_a.to_reference(project)}
* #{design_b.to_reference(project)}
MD
end
before do
project.add_developer(user)
sign_in(user)
end
context 'design management is enabled' do
before do
enable_design_management
end
it 'shows the issue description' do
visit project_issue_path(project, issue)
expect(page).to have_link(design_a.to_reference)
expect(page).to have_link(design_b.to_reference)
end
end
context 'design management is disabled' do
before do
enable_design_management(false, false)
end
it 'shows the issue description' do
visit project_issue_path(project, issue)
expect(page).to have_link(issue.to_reference)
expect(page).not_to have_link(design_a.to_reference)
expect(page).not_to have_link(design_b.to_reference)
end
end
end
...@@ -55,6 +55,7 @@ describe Banzai::Filter::DesignReferenceFilter do ...@@ -55,6 +55,7 @@ describe Banzai::Filter::DesignReferenceFilter do
expect(link.attr('data-project')).to eq(project.id.to_s) expect(link.attr('data-project')).to eq(project.id.to_s)
expect(link.attr('data-issue')).to eq(issue.id.to_s) expect(link.attr('data-issue')).to eq(issue.id.to_s)
expect(link.attr('data-original')).to eq(reference) expect(link.attr('data-original')).to eq(reference)
expect(link.attr('data-reference-type')).to eq('design')
expect(link.text).to eq(design.to_reference) expect(link.text).to eq(design.to_reference)
end end
end end
...@@ -65,6 +66,18 @@ describe Banzai::Filter::DesignReferenceFilter do ...@@ -65,6 +66,18 @@ describe Banzai::Filter::DesignReferenceFilter do
end end
end end
describe 'support for redaction' do
before do
enable_design_management
end
it 'supports the reference redactor' do
res = reference_pipeline(redact: true).to_document(input_text)
expect(res.css('a').first).to be_present
end
end
describe '#call' do describe '#call' do
describe 'feature flags' do describe 'feature flags' do
context 'design management is not enabled' do context 'design management is not enabled' do
......
# frozen_string_literal: true
require 'spec_helper'
describe Banzai::ReferenceParser::DesignParser do
include ReferenceParserHelpers
include DesignManagementTestHelpers
let_it_be(:issue) { create(:issue) }
let_it_be(:design) { create(:design, :with_versions, issue: issue) }
let_it_be(:user) { create(:user, developer_projects: [issue.project]) }
subject(:instance) { described_class.new(Banzai::RenderContext.new(issue.project, user)) }
let(:link) { design_link(design) }
before do
enable_design_management
end
describe '#nodes_visible_to_user' do
it_behaves_like 'referenced feature visibility', 'issues' do
let(:project) { issue.project }
end
describe 'specific states' do
let_it_be(:public_project) { create(:project, :public) }
let_it_be(:other_project_link) do
design_link(create(:design, :with_versions))
end
let_it_be(:public_link) do
design_link(create(:design, :with_versions, issue: create(:issue, project: public_project)))
end
let_it_be(:public_but_confidential_link) do
design_link(create(:design, :with_versions, issue: create(:issue, :confidential, project: public_project)))
end
subject(:visible_nodes) do
nodes = [link,
other_project_link,
public_link,
public_but_confidential_link]
instance.nodes_visible_to_user(user, nodes)
end
it 'redacts links we should not have access to' do
expect(visible_nodes).to contain_exactly(link, public_link)
end
context 'design management is not available' do
before do
enable_design_management(false)
end
it 'redacts all nodes' do
expect(visible_nodes).to be_empty
end
end
end
end
describe '#process' do
it 'returns the correct designs' do
frag = document([design, create(:design, :with_versions)])
expect(subject.process([frag])).to contain_exactly(design)
end
end
def design_link(design)
node = empty_html_link
node['class'] = 'gfm'
node['data-reference-type'] = 'design'
node['data-project'] = design.project.id.to_s
node['data-issue'] = design.issue.id.to_s
node['data-design'] = design.id.to_s
node
end
def document(designs)
frag = Nokogiri::HTML.fragment('')
designs.each do |design|
frag.add_child(design_link(design))
end
frag
end
end
...@@ -33,12 +33,15 @@ module FilterSpecHelper ...@@ -33,12 +33,15 @@ module FilterSpecHelper
# Use this for testing instance methods, but remember to test the result of # Use this for testing instance methods, but remember to test the result of
# the full pipeline by calling #call using the other methods in this helper. # the full pipeline by calling #call using the other methods in this helper.
def filter_instance def filter_instance
render_context = Banzai::RenderContext.new(project, current_user)
context = { project: project, current_user: current_user, render_context: render_context } context = { project: project, current_user: current_user, render_context: render_context }
described_class.new(input_text, context) described_class.new(input_text, context)
end end
def render_context
Banzai::RenderContext.new(project, current_user)
end
# Run text through HTML::Pipeline with the current filter and return the # Run text through HTML::Pipeline with the current filter and return the
# result Hash # result Hash
# #
...@@ -62,6 +65,9 @@ module FilterSpecHelper ...@@ -62,6 +65,9 @@ module FilterSpecHelper
described_class described_class
] ]
redact = context.delete(:redact)
filters.push(Banzai::Filter::ReferenceRedactorFilter) if redact
HTML::Pipeline.new(filters, context) HTML::Pipeline.new(filters, context)
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment