diff options
author | Bob Van Landuyt <bob@gitlab.com> | 2019-06-20 11:02:33 +0300 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2019-06-20 11:02:33 +0300 |
commit | 406808583c2392a0b57f68f98b2418e9d23b23ab (patch) | |
tree | 98613723a6caf6dc152f9ff431e75906ebe2c5ca /spec/lib/gitlab/graphql | |
parent | adeccba13676b831335e2f12f779f77602298b31 (diff) |
Render GFM html in GraphQL
This adds a `markdown_field` to our types.
Using this helper will render a model's markdown field using the
existing `MarkupHelper` with the context of the GraphQL query
available to the helper.
Having the context available to the helper is needed for redacting
links to resources that the current user is not allowed to see.
Because rendering the HTML can cause queries, the complexity of a
these fields is raised by 5 above the default.
The markdown field helper can be used as follows:
```
markdown_field :note_html, null: false
```
This would generate a field that will render the markdown field `note`
of the model. This could be overridden by adding the `method:`
argument. Passing a symbol for the method name:
```
markdown_field :body_html, null: false, method: :note
```
It will have this description by default:
> The GitLab Flavored Markdown rendering of `note`
This could be overridden by passing a `description:` argument.
The type of a `markdown_field` is always `GraphQL::STRING_TYPE`.
Diffstat (limited to 'spec/lib/gitlab/graphql')
-rw-r--r-- | spec/lib/gitlab/graphql/markdown_field/resolver_spec.rb | 33 | ||||
-rw-r--r-- | spec/lib/gitlab/graphql/markdown_field_spec.rb | 55 |
2 files changed, 88 insertions, 0 deletions
diff --git a/spec/lib/gitlab/graphql/markdown_field/resolver_spec.rb b/spec/lib/gitlab/graphql/markdown_field/resolver_spec.rb new file mode 100644 index 00000000000..b95bcdef188 --- /dev/null +++ b/spec/lib/gitlab/graphql/markdown_field/resolver_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Gitlab::Graphql::MarkdownField::Resolver do + include Gitlab::Routing + let(:resolver) { described_class.new(:note) } + + describe '#proc' do + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, project: project) } + let(:note) do + create(:note, + note: "Referencing #{issue.to_reference(full: true)}") + end + + it 'renders markdown correctly' do + expect(resolver.proc.call(note, {}, {})).to include(issue_path(issue)) + end + + context 'when the issue is not publicly accessible' do + let(:project) { create(:project, :private) } + + it 'hides the references from users that are not allowed to see the reference' do + expect(resolver.proc.call(note, {}, {})).not_to include(issue_path(issue)) + end + + it 'shows the reference to users that are allowed to see it' do + expect(resolver.proc.call(note, {}, { current_user: project.owner })) + .to include(issue_path(issue)) + end + end + end +end diff --git a/spec/lib/gitlab/graphql/markdown_field_spec.rb b/spec/lib/gitlab/graphql/markdown_field_spec.rb new file mode 100644 index 00000000000..a8566aa8e1c --- /dev/null +++ b/spec/lib/gitlab/graphql/markdown_field_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Gitlab::Graphql::MarkdownField do + describe '.markdown_field' do + it 'creates the field with some default attributes' do + field = class_with_markdown_field(:test_html, null: true, method: :hello).fields['testHtml'] + + expect(field.name).to eq('testHtml') + expect(field.description).to eq('The GitLab Flavored Markdown rendering of `hello`') + expect(field.type).to eq(GraphQL::STRING_TYPE) + expect(field.to_graphql.complexity).to eq(5) + end + + context 'developer warnings' do + let(:expected_error) { /Only `method` is allowed to specify the markdown field/ } + + it 'raises when passing a resolver' do + expect { class_with_markdown_field(:test_html, null: true, resolver: 'not really') } + .to raise_error(expected_error) + end + + it 'raises when passing a resolve block' do + expect { class_with_markdown_field(:test_html, null: true, resolve: -> (_, _, _) { 'not really' } ) } + .to raise_error(expected_error) + end + end + + context 'resolving markdown' do + let(:note) { build(:note, note: '# Markdown!') } + let(:thing_with_markdown) { double('markdown thing', object: note) } + let(:expected_markdown) { '<h1 data-sourcepos="1:1-1:11" dir="auto">Markdown!</h1>' } + + it 'renders markdown from the same property as the field name without the `_html` suffix' do + field = class_with_markdown_field(:note_html, null: false).fields['noteHtml'] + + expect(field.to_graphql.resolve(thing_with_markdown, {}, {})).to eq(expected_markdown) + end + + it 'renders markdown from a specific property when a `method` argument is passed' do + field = class_with_markdown_field(:test_html, null: false, method: :note).fields['testHtml'] + + expect(field.to_graphql.resolve(thing_with_markdown, {}, {})).to eq(expected_markdown) + end + end + end + + def class_with_markdown_field(name, **args) + Class.new(GraphQL::Schema::Object) do + prepend Gitlab::Graphql::MarkdownField + + markdown_field name, **args + end + end +end |