summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/graphql/docs/renderer_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/graphql/docs/renderer_spec.rb')
-rw-r--r--spec/lib/gitlab/graphql/docs/renderer_spec.rb639
1 files changed, 0 insertions, 639 deletions
diff --git a/spec/lib/gitlab/graphql/docs/renderer_spec.rb b/spec/lib/gitlab/graphql/docs/renderer_spec.rb
deleted file mode 100644
index 14db51deb88..00000000000
--- a/spec/lib/gitlab/graphql/docs/renderer_spec.rb
+++ /dev/null
@@ -1,639 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Graphql::Docs::Renderer do
- describe '#contents' do
- shared_examples 'renders correctly as GraphQL documentation' do
- it 'contains the expected section' do
- # duplicative - but much better error messages!
- section.lines.each { |line| expect(contents).to include(line) }
- expect(contents).to include(section)
- end
- end
-
- let(:template) { Rails.root.join('lib/gitlab/graphql/docs/templates/default.md.haml') }
- let(:field_description) { 'List of objects.' }
- let(:type) { ::GraphQL::INT_TYPE }
-
- let(:query_type) do
- Class.new(Types::BaseObject) { graphql_name 'Query' }.tap do |t|
- # this keeps type and field_description in scope.
- t.field :foo, type, null: true, description: field_description do
- argument :id, GraphQL::ID_TYPE, required: false, description: 'ID of the object.'
- end
- end
- end
-
- let(:mutation_root) do
- Class.new(::Types::BaseObject) do
- include ::Gitlab::Graphql::MountMutation
- graphql_name 'Mutation'
- end
- end
-
- let(:mock_schema) do
- Class.new(GraphQL::Schema) do
- def resolve_type(obj, ctx)
- raise 'Not a real schema'
- end
- end
- end
-
- subject(:contents) do
- mock_schema.query(query_type)
- mock_schema.mutation(mutation_root) if mutation_root.fields.any?
-
- described_class.new(
- mock_schema,
- output_dir: nil,
- template: template
- ).contents
- end
-
- describe 'headings' do
- it 'contains the expected sections' do
- expect(contents.lines.map(&:chomp)).to include(
- '## `Query` type',
- '## `Mutation` type',
- '## Connections',
- '## Object types',
- '## Enumeration types',
- '## Scalar types',
- '## Abstract types',
- '### Unions',
- '### Interfaces',
- '## Input types'
- )
- end
- end
-
- context 'when a field has a list type' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'ArrayTest'
-
- field :foo, [GraphQL::STRING_TYPE], null: false, description: 'A description.'
- end
- end
-
- specify do
- type_name = '[String!]!'
- inner_type = 'string'
- expectation = <<~DOC
- ### `ArrayTest`
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="arraytestfoo"></a>`foo` | [`#{type_name}`](##{inner_type}) | A description. |
- DOC
-
- is_expected.to include(expectation)
- end
-
- describe 'a top level query field' do
- let(:expectation) do
- <<~DOC
- ### `Query.foo`
-
- List of objects.
-
- Returns [`ArrayTest`](#arraytest).
-
- #### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="queryfooid"></a>`id` | [`ID`](#id) | ID of the object. |
- DOC
- end
-
- it 'generates the query with arguments' do
- expect(subject).to include(expectation)
- end
-
- context 'when description does not end with `.`' do
- let(:field_description) { 'List of objects' }
-
- it 'adds the `.` to the end' do
- expect(subject).to include(expectation)
- end
- end
- end
- end
-
- describe 'when fields are not defined in alphabetical order' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'OrderingTest'
-
- field :foo, GraphQL::STRING_TYPE, null: false, description: 'A description of foo field.'
- field :bar, GraphQL::STRING_TYPE, null: false, description: 'A description of bar field.'
- end
- end
-
- it 'lists the fields in alphabetical order' do
- expectation = <<~DOC
- ### `OrderingTest`
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="orderingtestbar"></a>`bar` | [`String!`](#string) | A description of bar field. |
- | <a id="orderingtestfoo"></a>`foo` | [`String!`](#string) | A description of foo field. |
- DOC
-
- is_expected.to include(expectation)
- end
- end
-
- context 'when a field has a documentation reference' do
- let(:type) do
- wibble = Class.new(::Types::BaseObject) do
- graphql_name 'Wibble'
- field :x, ::GraphQL::INT_TYPE, null: false
- end
-
- Class.new(Types::BaseObject) do
- graphql_name 'DocRefSpec'
- description 'Testing doc refs'
-
- field :foo,
- type: GraphQL::STRING_TYPE,
- null: false,
- description: 'The foo.',
- see: { 'A list of foos' => 'https://example.com/foos' }
- field :bar,
- type: GraphQL::STRING_TYPE,
- null: false,
- description: 'The bar.',
- see: { 'A list of bars' => 'https://example.com/bars' } do
- argument :barity, ::GraphQL::INT_TYPE, required: false, description: '?'
- end
- field :wibbles,
- type: wibble.connection_type,
- null: true,
- description: 'The wibbles',
- see: { 'wibblance' => 'https://example.com/wibbles' }
- end
- end
-
- let(:section) do
- <<~DOC
- ### `DocRefSpec`
-
- Testing doc refs.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="docrefspecfoo"></a>`foo` | [`String!`](#string) | The foo. See [A list of foos](https://example.com/foos). |
- | <a id="docrefspecwibbles"></a>`wibbles` | [`WibbleConnection`](#wibbleconnection) | The wibbles. See [wibblance](https://example.com/wibbles). (see [Connections](#connections)) |
-
- #### Fields with arguments
-
- ##### `DocRefSpec.bar`
-
- The bar. See [A list of bars](https://example.com/bars).
-
- Returns [`String!`](#string).
-
- ###### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="docrefspecbarbarity"></a>`barity` | [`Int`](#int) | ?. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when an argument is deprecated' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'DeprecatedTest'
- description 'A thing we used to use, but no longer support'
-
- field :foo,
- type: GraphQL::STRING_TYPE,
- null: false,
- description: 'A description.' do
- argument :foo_arg, GraphQL::STRING_TYPE,
- required: false,
- description: 'The argument.',
- deprecated: { reason: 'Bad argument', milestone: '101.2' }
- end
- end
- end
-
- let(:section) do
- <<~DOC
- ##### `DeprecatedTest.foo`
-
- A description.
-
- Returns [`String!`](#string).
-
- ###### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="deprecatedtestfoofooarg"></a>`fooArg` **{warning-solid}** | [`String`](#string) | **Deprecated** in 101.2. Bad argument. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when a field is deprecated' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'DeprecatedTest'
- description 'A thing we used to use, but no longer support'
-
- field :foo,
- type: GraphQL::STRING_TYPE,
- null: false,
- deprecated: { reason: 'This is deprecated', milestone: '1.10' },
- description: 'A description.'
- field :foo_with_args,
- type: GraphQL::STRING_TYPE,
- null: false,
- deprecated: { reason: 'Do not use', milestone: '1.10', replacement: 'X.y' },
- description: 'A description.' do
- argument :arg, GraphQL::INT_TYPE, required: false, description: 'Argity'
- end
- field :bar,
- type: GraphQL::STRING_TYPE,
- null: false,
- description: 'A description.',
- deprecated: {
- reason: :renamed,
- milestone: '1.10',
- replacement: 'Query.boom'
- }
- end
- end
-
- let(:section) do
- <<~DOC
- ### `DeprecatedTest`
-
- A thing we used to use, but no longer support.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="deprecatedtestbar"></a>`bar` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This was renamed. Use: [`Query.boom`](#queryboom). |
- | <a id="deprecatedtestfoo"></a>`foo` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This is deprecated. |
-
- #### Fields with arguments
-
- ##### `DeprecatedTest.fooWithArgs`
-
- A description.
-
- WARNING:
- **Deprecated** in 1.10.
- Do not use.
- Use: [`X.y`](#xy).
-
- Returns [`String!`](#string).
-
- ###### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="deprecatedtestfoowithargsarg"></a>`arg` | [`Int`](#int) | Argity. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when a Query.field is deprecated' do
- before do
- query_type.field(
- name: :bar,
- type: type,
- null: true,
- description: 'A bar',
- deprecated: { reason: :renamed, milestone: '10.11', replacement: 'Query.foo' }
- )
- end
-
- let(:type) { ::GraphQL::INT_TYPE }
- let(:section) do
- <<~DOC
- ### `Query.bar`
-
- A bar.
-
- WARNING:
- **Deprecated** in 10.11.
- This was renamed.
- Use: [`Query.foo`](#queryfoo).
-
- Returns [`Int`](#int).
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when a field has an Enumeration type' do
- let(:type) do
- enum_type = Class.new(Types::BaseEnum) do
- graphql_name 'MyEnum'
- description 'A test of an enum.'
-
- value 'BAZ',
- description: 'A description of BAZ.'
- value 'BAR',
- description: 'A description of BAR.',
- deprecated: { reason: 'This is deprecated', milestone: '1.10' }
- end
-
- Class.new(Types::BaseObject) do
- graphql_name 'EnumTest'
-
- field :foo, enum_type, null: false, description: 'A description of foo field.'
- end
- end
-
- let(:section) do
- <<~DOC
- ### `MyEnum`
-
- A test of an enum.
-
- | Value | Description |
- | ----- | ----------- |
- | <a id="myenumbar"></a>`BAR` **{warning-solid}** | **Deprecated:** This is deprecated. Deprecated in 1.10. |
- | <a id="myenumbaz"></a>`BAZ` | A description of BAZ. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when a field has a global ID type' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'IDTest'
- description 'A test for rendering IDs.'
-
- field :foo, ::Types::GlobalIDType[::User], null: true, description: 'A user foo.'
- end
- end
-
- describe 'section for IDTest' do
- let(:section) do
- <<~DOC
- ### `IDTest`
-
- A test for rendering IDs.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="idtestfoo"></a>`foo` | [`UserID`](#userid) | A user foo. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- describe 'section for UserID' do
- let(:section) do
- <<~DOC
- ### `UserID`
-
- A `UserID` is a global ID. It is encoded as a string.
-
- An example `UserID` is: `"gid://gitlab/User/1"`.
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
- end
-
- context 'when there is a mutation' do
- let(:mutation) do
- mutation = Class.new(::Mutations::BaseMutation)
-
- mutation.graphql_name 'MakeItPretty'
- mutation.description 'Make everything very pretty.'
-
- mutation.argument :prettiness_factor,
- type: GraphQL::FLOAT_TYPE,
- required: true,
- description: 'How much prettier?'
-
- mutation.argument :pulchritude,
- type: GraphQL::FLOAT_TYPE,
- required: false,
- description: 'How much prettier?',
- deprecated: {
- reason: :renamed,
- replacement: 'prettinessFactor',
- milestone: '72.34'
- }
-
- mutation.field :everything,
- type: GraphQL::STRING_TYPE,
- null: true,
- description: 'What we made prettier.'
-
- mutation.field :omnis,
- type: GraphQL::STRING_TYPE,
- null: true,
- description: 'What we made prettier.',
- deprecated: {
- reason: :renamed,
- replacement: 'everything',
- milestone: '72.34'
- }
-
- mutation
- end
-
- before do
- mutation_root.mount_mutation mutation
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation' do
- let(:section) do
- <<~DOC
- ### `Mutation.makeItPretty`
-
- Make everything very pretty.
-
- Input type: `MakeItPrettyInput`
-
- #### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="mutationmakeitprettyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
- | <a id="mutationmakeitprettyprettinessfactor"></a>`prettinessFactor` | [`Float!`](#float) | How much prettier?. |
- | <a id="mutationmakeitprettypulchritude"></a>`pulchritude` **{warning-solid}** | [`Float`](#float) | **Deprecated:** This was renamed. Please use `prettinessFactor`. Deprecated in 72.34. |
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="mutationmakeitprettyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
- | <a id="mutationmakeitprettyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
- | <a id="mutationmakeitprettyeverything"></a>`everything` | [`String`](#string) | What we made prettier. |
- | <a id="mutationmakeitprettyomnis"></a>`omnis` **{warning-solid}** | [`String`](#string) | **Deprecated:** This was renamed. Please use `everything`. Deprecated in 72.34. |
- DOC
- end
- end
-
- it 'does not render the automatically generated payload type' do
- expect(contents).not_to include('MakeItPrettyPayload')
- end
-
- it 'does not render the automatically generated input type as its own section' do
- expect(contents).not_to include('# `MakeItPrettyInput`')
- end
- end
-
- context 'when there is an input type' do
- let(:type) do
- Class.new(::Types::BaseObject) do
- graphql_name 'Foo'
- field :wibble, type: ::GraphQL::INT_TYPE, null: true do
- argument :date_range,
- type: ::Types::TimeframeInputType,
- required: true,
- description: 'When the foo happened.'
- end
- end
- end
-
- let(:section) do
- <<~DOC
- ### `Timeframe`
-
- A time-frame defined as a closed inclusive range of two dates.
-
- #### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="timeframeend"></a>`end` | [`Date!`](#date) | The end of the range. |
- | <a id="timeframestart"></a>`start` | [`Date!`](#date) | The start of the range. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when there is an interface and a union' do
- let(:type) do
- user = Class.new(::Types::BaseObject)
- user.graphql_name 'User'
- user.field :user_field, ::GraphQL::STRING_TYPE, null: true
- group = Class.new(::Types::BaseObject)
- group.graphql_name 'Group'
- group.field :group_field, ::GraphQL::STRING_TYPE, null: true
-
- union = Class.new(::Types::BaseUnion)
- union.graphql_name 'UserOrGroup'
- union.description 'Either a user or a group.'
- union.possible_types user, group
-
- interface = Module.new
- interface.include(::Types::BaseInterface)
- interface.graphql_name 'Flying'
- interface.description 'Something that can fly.'
- interface.field :flight_speed, GraphQL::INT_TYPE, null: true, description: 'Speed in mph.'
-
- african_swallow = Class.new(::Types::BaseObject)
- african_swallow.graphql_name 'AfricanSwallow'
- african_swallow.description 'A swallow from Africa.'
- african_swallow.implements interface
- interface.orphan_types african_swallow
-
- Class.new(::Types::BaseObject) do
- graphql_name 'AbstractTypeTest'
- description 'A test for abstract types.'
-
- field :foo, union, null: true, description: 'The foo.'
- field :flying, interface, null: true, description: 'A flying thing.'
- end
- end
-
- it 'lists the fields correctly, and includes descriptions of all the types' do
- type_section = <<~DOC
- ### `AbstractTypeTest`
-
- A test for abstract types.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="abstracttypetestflying"></a>`flying` | [`Flying`](#flying) | A flying thing. |
- | <a id="abstracttypetestfoo"></a>`foo` | [`UserOrGroup`](#userorgroup) | The foo. |
- DOC
-
- union_section = <<~DOC
- #### `UserOrGroup`
-
- Either a user or a group.
-
- One of:
-
- - [`Group`](#group)
- - [`User`](#user)
- DOC
-
- interface_section = <<~DOC
- #### `Flying`
-
- Something that can fly.
-
- Implementations:
-
- - [`AfricanSwallow`](#africanswallow)
-
- ##### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="flyingflightspeed"></a>`flightSpeed` | [`Int`](#int) | Speed in mph. |
- DOC
-
- implementation_section = <<~DOC
- ### `AfricanSwallow`
-
- A swallow from Africa.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="africanswallowflightspeed"></a>`flightSpeed` | [`Int`](#int) | Speed in mph. |
- DOC
-
- is_expected.to include(
- type_section,
- union_section,
- interface_section,
- implementation_section
- )
- end
- end
- end
-end