1# frozen_string_literal: true
2
3require 'spec_helper'
4
5RSpec.describe 'Query.project(fullPath).issue(iid)' do
6  include GraphqlHelpers
7
8  let_it_be(:project) { create(:project) }
9  let_it_be(:issue) { create(:issue, project: project) }
10  let_it_be(:issue_b) { create(:issue, project: project) }
11  let_it_be(:developer) { create(:user) }
12  let(:current_user) { developer }
13
14  let_it_be(:project_params) { { 'fullPath' => project.full_path } }
15  let_it_be(:issue_params) { { 'iid' => issue.iid.to_s } }
16  let_it_be(:issue_fields) { 'title' }
17
18  let(:query) do
19    graphql_query_for('project', project_params, project_fields)
20  end
21
22  let(:project_fields) do
23    query_graphql_field(:issue, issue_params, issue_fields)
24  end
25
26  shared_examples 'being able to fetch a design-like object by ID' do
27    let(:design) { design_a }
28    let(:path) { %w[project issue designCollection] + [GraphqlHelpers.fieldnamerize(object_field_name)] }
29
30    let(:design_fields) do
31      [
32        :filename,
33        query_graphql_field(:project, :id)
34      ]
35    end
36
37    let(:design_collection_fields) do
38      query_graphql_field(object_field_name, object_params, object_fields)
39    end
40
41    let(:object_fields) { design_fields }
42
43    context 'the ID is passed' do
44      let(:object_params) { { id: global_id_of(object) } }
45      let(:result_fields) { {} }
46
47      let(:expected_fields) do
48        result_fields.merge({ 'filename' => design.filename, 'project' => id_hash(project) })
49      end
50
51      it 'retrieves the object' do
52        post_query
53
54        data = graphql_data.dig(*path)
55
56        expect(data).to match(a_hash_including(expected_fields))
57      end
58
59      context 'the user is unauthorized' do
60        let(:current_user) { create(:user) }
61
62        it_behaves_like 'a failure to find anything'
63      end
64    end
65
66    context 'without parameters' do
67      let(:object_params) { nil }
68
69      it 'raises an error' do
70        post_query
71
72        expect(graphql_errors).to include(no_argument_error)
73      end
74    end
75
76    context 'attempting to retrieve an object from a different issue' do
77      let(:object_params) { { id: global_id_of(object_on_other_issue) } }
78
79      it_behaves_like 'a failure to find anything'
80    end
81  end
82
83  before do
84    project.add_developer(developer)
85  end
86
87  let(:post_query) { post_graphql(query, current_user: current_user) }
88
89  describe '.designCollection' do
90    include DesignManagementTestHelpers
91
92    let_it_be(:design_a) { create(:design, issue: issue) }
93    let_it_be(:version_a) { create(:design_version, issue: issue, created_designs: [design_a]) }
94
95    let(:issue_fields) do
96      query_graphql_field(:design_collection, dc_params, design_collection_fields)
97    end
98
99    let(:dc_params) { nil }
100    let(:design_collection_fields) { nil }
101
102    before do
103      enable_design_management
104    end
105
106    describe '.design' do
107      let(:object) { design }
108      let(:object_field_name) { :design }
109
110      let(:no_argument_error) do
111        custom_graphql_error(path, a_string_matching(%r/id or filename/))
112      end
113
114      let_it_be(:object_on_other_issue) { create(:design, issue: issue_b) }
115
116      it_behaves_like 'being able to fetch a design-like object by ID'
117
118      it_behaves_like 'being able to fetch a design-like object by ID' do
119        let(:object_params) { { filename: design.filename } }
120      end
121    end
122
123    describe '.version' do
124      let(:version) { version_a }
125      let(:path) { %w[project issue designCollection version] }
126
127      let(:design_collection_fields) do
128        query_graphql_field(:version, version_params, 'id sha')
129      end
130
131      context 'no parameters' do
132        let(:version_params) { nil }
133
134        it 'raises an error' do
135          post_query
136
137          expect(graphql_errors).to include(custom_graphql_error(path, a_string_matching(%r/id or sha/)))
138        end
139      end
140
141      shared_examples 'a successful query for a version' do
142        it 'finds the version' do
143          post_query
144
145          data = graphql_data.dig(*path)
146
147          expect(data).to match(
148            a_hash_including('id' => global_id_of(version),
149                             'sha' => version.sha)
150          )
151        end
152      end
153
154      context '(sha: STRING_TYPE)' do
155        let(:version_params) { { sha: version.sha } }
156
157        it_behaves_like 'a successful query for a version'
158      end
159
160      context '(id: ID_TYPE)' do
161        let(:version_params) { { id: global_id_of(version) } }
162
163        it_behaves_like 'a successful query for a version'
164      end
165    end
166
167    describe '.designAtVersion' do
168      it_behaves_like 'being able to fetch a design-like object by ID' do
169        let(:object) { build(:design_at_version, design: design, version: version) }
170        let(:object_field_name) { :design_at_version }
171
172        let(:version) { version_a }
173
174        let(:result_fields) { { 'version' => id_hash(version) } }
175        let(:object_fields) do
176          design_fields + [query_graphql_field(:version, :id)]
177        end
178
179        let(:no_argument_error) { missing_required_argument(path, :id) }
180
181        let(:object_on_other_issue) { build(:design_at_version, issue: issue_b) }
182      end
183    end
184  end
185
186  def id_hash(object)
187    a_hash_including('id' => global_id_of(object))
188  end
189end
190