1# frozen_string_literal: true
2
3require 'spec_helper'
4
5RSpec.describe 'getting project information' do
6  include GraphqlHelpers
7
8  let_it_be(:group) { create(:group) }
9  let_it_be(:project, reload: true) { create(:project, :repository, group: group) }
10  let_it_be(:current_user) { create(:user) }
11
12  let(:project_fields) { all_graphql_fields_for('project'.to_s.classify, max_depth: 1) }
13
14  let(:query) do
15    graphql_query_for(:project, { full_path: project.full_path }, project_fields)
16  end
17
18  context 'when the user has full access to the project' do
19    before do
20      project.add_maintainer(current_user)
21    end
22
23    it 'includes the project', :use_clean_rails_memory_store_caching, :request_store do
24      post_graphql(query, current_user: current_user)
25
26      expect(graphql_data['project']).not_to be_nil
27    end
28  end
29
30  context 'when the user has access to the project', :use_clean_rails_memory_store_caching, :request_store do
31    before_all do
32      project.add_developer(current_user)
33    end
34
35    it 'includes the project' do
36      post_graphql(query, current_user: current_user)
37
38      expect(graphql_data['project']).not_to be_nil
39    end
40
41    it_behaves_like 'a working graphql query' do
42      before do
43        post_graphql(query, current_user: current_user)
44      end
45    end
46
47    context 'when there are pipelines present' do
48      let(:project_fields) { query_nodes(:pipelines) }
49
50      before do
51        create(:ci_pipeline, project: project)
52      end
53
54      it 'is included in the pipelines connection' do
55        post_graphql(query, current_user: current_user)
56
57        expect(graphql_data_at(:project, :pipelines, :nodes)).to contain_exactly(a_kind_of(Hash))
58      end
59    end
60
61    context 'topics' do
62      it 'includes empty topics array if no topics set' do
63        post_graphql(query, current_user: current_user)
64
65        expect(graphql_data_at(:project, :topics)).to match([])
66      end
67
68      it 'includes topics array' do
69        project.update!(topic_list: 'topic1, topic2, topic3')
70
71        post_graphql(query, current_user: current_user)
72
73        expect(graphql_data_at(:project, :topics)).to match(%w[topic1 topic2 topic3])
74      end
75    end
76
77    it 'includes inherited members in project_members' do
78      group_member = create(:group_member, group: group)
79      project_member = create(:project_member, project: project)
80      member_query = <<~GQL
81        query {
82          project(fullPath: "#{project.full_path}") {
83            projectMembers {
84              nodes {
85                id
86                user {
87                  username
88                }
89                ... on ProjectMember {
90                  project {
91                    id
92                  }
93                }
94                ... on GroupMember {
95                  group {
96                    id
97                  }
98                }
99              }
100            }
101          }
102        }
103      GQL
104
105      post_graphql(member_query, current_user: current_user)
106
107      member_ids = graphql_data.dig('project', 'projectMembers', 'nodes')
108      expect(member_ids).to include(
109        a_hash_including(
110          'id' => group_member.to_global_id.to_s,
111          'group' => { 'id' => group.to_global_id.to_s }
112        )
113      )
114      expect(member_ids).to include(
115        a_hash_including(
116          'id' => project_member.to_global_id.to_s,
117          'project' => { 'id' => project.to_global_id.to_s }
118        )
119      )
120    end
121  end
122
123  context 'when the user has reporter access to the project' do
124    let(:statistics_query) do
125      <<~GRAPHQL
126        {
127          project(fullPath: "#{project.full_path}") {
128            statistics { wikiSize }
129          }
130        }
131      GRAPHQL
132    end
133
134    before do
135      project.add_reporter(current_user)
136      create(:project_statistics, project: project, wiki_size: 100)
137    end
138
139    it 'allows fetching project statistics' do
140      post_graphql(statistics_query, current_user: current_user)
141
142      expect(graphql_data.dig('project', 'statistics')).to include('wikiSize' => 100.0)
143    end
144  end
145
146  context 'when the user has guest access' do
147    context 'when the project has public pipelines' do
148      before do
149        pipeline = create(:ci_pipeline, project: project)
150        create(:ci_build, project: project, pipeline: pipeline, name: 'a test job')
151        project.add_guest(current_user)
152      end
153
154      it 'shows all jobs' do
155        query = <<~GQL
156          query {
157            project(fullPath: "#{project.full_path}") {
158              jobs {
159                nodes {
160                  name
161                  stage {
162                    name
163                  }
164                }
165              }
166            }
167          }
168        GQL
169
170        post_graphql(query, current_user: current_user)
171
172        expect(graphql_data_at(:project, :jobs, :nodes)).to contain_exactly({
173          'name' => 'a test job',
174          'stage' => { 'name' => 'test' }
175        })
176      end
177    end
178  end
179
180  context 'when the user does not have access to the project' do
181    it 'returns an empty field' do
182      post_graphql(query, current_user: current_user)
183
184      expect(graphql_data['project']).to be_nil
185    end
186
187    it_behaves_like 'a working graphql query' do
188      before do
189        post_graphql(query, current_user: current_user)
190      end
191    end
192  end
193end
194