diff options
Diffstat (limited to 'spec/requests/api/graphql/project')
14 files changed, 487 insertions, 23 deletions
diff --git a/spec/requests/api/graphql/project/alert_management/integrations_spec.rb b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb new file mode 100644 index 00000000000..b13805a61ce --- /dev/null +++ b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe 'getting Alert Management Integrations' do + include ::Gitlab::Routing + include GraphqlHelpers + + let_it_be(:project) { create(:project, :repository) } + let_it_be(:current_user) { create(:user) } + let_it_be(:prometheus_service) { create(:prometheus_service, project: project) } + let_it_be(:project_alerting_setting) { create(:project_alerting_setting, project: project) } + let_it_be(:active_http_integration) { create(:alert_management_http_integration, project: project) } + let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) } + let_it_be(:other_project_http_integration) { create(:alert_management_http_integration) } + + let(:fields) do + <<~QUERY + nodes { + #{all_graphql_fields_for('AlertManagementIntegration')} + } + QUERY + end + + let(:query) do + graphql_query_for( + 'project', + { 'fullPath' => project.full_path }, + query_graphql_field('alertManagementIntegrations', {}, fields) + ) + end + + context 'with integrations' do + let(:integrations) { graphql_data.dig('project', 'alertManagementIntegrations', 'nodes') } + + context 'without project permissions' do + let(:user) { create(:user) } + + before do + post_graphql(query, current_user: current_user) + end + + it_behaves_like 'a working graphql query' + + it { expect(integrations).to be_nil } + end + + context 'with project permissions' do + before do + project.add_maintainer(current_user) + post_graphql(query, current_user: current_user) + end + + let(:http_integration) { integrations.first } + let(:prometheus_integration) { integrations.second } + + it_behaves_like 'a working graphql query' + + it { expect(integrations.size).to eq(2) } + + it 'returns the correct properties of the integrations' do + expect(http_integration).to include( + 'id' => GitlabSchema.id_from_object(active_http_integration).to_s, + 'type' => 'HTTP', + 'name' => active_http_integration.name, + 'active' => active_http_integration.active, + 'token' => active_http_integration.token, + 'url' => active_http_integration.url, + 'apiUrl' => nil + ) + + expect(prometheus_integration).to include( + 'id' => GitlabSchema.id_from_object(prometheus_service).to_s, + 'type' => 'PROMETHEUS', + 'name' => 'Prometheus', + 'active' => prometheus_service.manual_configuration?, + 'token' => project_alerting_setting.token, + 'url' => "http://localhost/#{project.full_path}/prometheus/alerts/notify.json", + 'apiUrl' => prometheus_service.api_url + ) + end + end + end +end diff --git a/spec/requests/api/graphql/project/container_repositories_spec.rb b/spec/requests/api/graphql/project/container_repositories_spec.rb new file mode 100644 index 00000000000..7e32f54bf1d --- /dev/null +++ b/spec/requests/api/graphql/project/container_repositories_spec.rb @@ -0,0 +1,145 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe 'getting container repositories in a project' do + using RSpec::Parameterized::TableSyntax + include GraphqlHelpers + + let_it_be_with_reload(:project) { create(:project, :private) } + let_it_be(:container_repository) { create(:container_repository, project: project) } + let_it_be(:container_repositories_delete_scheduled) { create_list(:container_repository, 2, :status_delete_scheduled, project: project) } + let_it_be(:container_repositories_delete_failed) { create_list(:container_repository, 2, :status_delete_failed, project: project) } + let_it_be(:container_repositories) { [container_repository, container_repositories_delete_scheduled, container_repositories_delete_failed].flatten } + let_it_be(:container_expiration_policy) { project.container_expiration_policy } + + let(:fields) do + <<~GQL + edges { + node { + #{all_graphql_fields_for('container_repositories'.classify)} + } + } + GQL + end + + let(:query) do + graphql_query_for( + 'project', + { 'fullPath' => project.full_path }, + query_graphql_field('container_repositories', {}, fields) + ) + end + + let(:user) { project.owner } + let(:variables) { {} } + let(:container_repositories_response) { graphql_data.dig('project', 'containerRepositories', 'edges') } + + before do + stub_container_registry_config(enabled: true) + container_repositories.each do |repository| + stub_container_registry_tags(repository: repository.path, tags: %w(tag1 tag2 tag3), with_manifest: false) + end + end + + subject { post_graphql(query, current_user: user, variables: variables) } + + it_behaves_like 'a working graphql query' do + before do + subject + end + + it 'matches the JSON schema' do + expect(container_repositories_response).to match_schema('graphql/container_repositories') + end + end + + context 'with different permissions' do + let_it_be(:user) { create(:user) } + + where(:project_visibility, :role, :access_granted, :can_delete) do + :private | :maintainer | true | true + :private | :developer | true | true + :private | :reporter | true | false + :private | :guest | false | false + :private | :anonymous | false | false + :public | :maintainer | true | true + :public | :developer | true | true + :public | :reporter | true | false + :public | :guest | true | false + :public | :anonymous | true | false + end + + with_them do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility.to_s.upcase, false)) + project.add_user(user, role) unless role == :anonymous + end + + it 'return the proper response' do + subject + + if access_granted + expect(container_repositories_response.size).to eq(container_repositories.size) + container_repositories_response.each do |repository_response| + expect(repository_response.dig('node', 'canDelete')).to eq(can_delete) + end + else + expect(container_repositories_response).to eq(nil) + end + end + end + end + + context 'limiting the number of repositories' do + let(:limit) { 1 } + let(:variables) do + { path: project.full_path, n: limit } + end + + let(:query) do + <<~GQL + query($path: ID!, $n: Int) { + project(fullPath: $path) { + containerRepositories(first: $n) { #{fields} } + } + } + GQL + end + + it 'only returns N repositories' do + subject + + expect(container_repositories_response.size).to eq(limit) + end + end + + context 'filter by name' do + let_it_be(:container_repository) { create(:container_repository, name: 'fooBar', project: project) } + + let(:name) { 'ooba' } + let(:query) do + <<~GQL + query($path: ID!, $name: String) { + project(fullPath: $path) { + containerRepositories(name: $name) { #{fields} } + } + } + GQL + end + + let(:variables) do + { path: project.full_path, name: name } + end + + before do + stub_container_registry_tags(repository: container_repository.path, tags: %w(tag4 tag5 tag6), with_manifest: false) + end + + it 'returns the searched container repository' do + subject + + expect(container_repositories_response.size).to eq(1) + expect(container_repositories_response.first.dig('node', 'id')).to eq(container_repository.to_global_id.to_s) + end + end +end diff --git a/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb b/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb index cd84ce9cb96..c7d327a62af 100644 --- a/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb +++ b/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb @@ -29,10 +29,12 @@ RSpec.describe 'sentry errors requests' do let(:error_data) { graphql_data.dig('project', 'sentryErrors', 'detailedError') } - it_behaves_like 'a working graphql query' do - before do - post_graphql(query, current_user: current_user) - end + it 'returns a successful response', :aggregate_failures, :quarantine do + post_graphql(query, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(graphql_errors).to be_nil + expect(json_response.keys).to include('data') end context 'when data is loading via reactive cache' do @@ -191,7 +193,7 @@ RSpec.describe 'sentry errors requests' do describe 'getting a stack trace' do let_it_be(:sentry_stack_trace) { build(:error_tracking_error_event) } - let(:sentry_gid) { Gitlab::ErrorTracking::DetailedError.new(id: 1).to_global_id.to_s } + let(:sentry_gid) { global_id_of(Gitlab::ErrorTracking::DetailedError.new(id: 1)) } let(:stack_trace_fields) do all_graphql_fields_for('SentryErrorStackTrace'.classify) diff --git a/spec/requests/api/graphql/project/grafana_integration_spec.rb b/spec/requests/api/graphql/project/grafana_integration_spec.rb index 688959e622d..9b24698f40c 100644 --- a/spec/requests/api/graphql/project/grafana_integration_spec.rb +++ b/spec/requests/api/graphql/project/grafana_integration_spec.rb @@ -45,7 +45,6 @@ RSpec.describe 'Getting Grafana Integration' do it_behaves_like 'a working graphql query' - specify { expect(integration_data['token']).to eql grafana_integration.masked_token } specify { expect(integration_data['grafanaUrl']).to eql grafana_integration.grafana_url } specify do diff --git a/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb b/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb index 1b654e660e3..4bce3c7fe0f 100644 --- a/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb +++ b/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb @@ -14,6 +14,7 @@ RSpec.describe 'Query.project(fullPath).issue(iid).designCollection.version(sha) create(:design_version, issue: issue, created_designs: create_list(:design, 3, issue: issue)) end + let_it_be(:version) do create(:design_version, issue: issue, modified_designs: old_version.designs, diff --git a/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb b/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb index 640ac95cd86..ee0085718b3 100644 --- a/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb +++ b/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb @@ -11,12 +11,15 @@ RSpec.describe 'Getting versions related to an issue' do let_it_be(:version_a) do create(:design_version, issue: issue) end + let_it_be(:version_b) do create(:design_version, issue: issue) end + let_it_be(:version_c) do create(:design_version, issue: issue) end + let_it_be(:version_d) do create(:design_version, issue: issue) end diff --git a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb index e25453510d5..a671ddc7ab1 100644 --- a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb +++ b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb @@ -30,7 +30,7 @@ RSpec.describe 'Getting designs related to an issue' do post_graphql(query(note_fields), current_user: nil) - designs_data = graphql_data['project']['issue']['designs']['designs'] + designs_data = graphql_data['project']['issue']['designCollection']['designs'] design_data = designs_data['nodes'].first note_data = design_data['notes']['nodes'].first @@ -56,7 +56,7 @@ RSpec.describe 'Getting designs related to an issue' do 'issue', { iid: design.issue.iid.to_s }, query_graphql_field( - 'designs', {}, design_node + 'designCollection', {}, design_node ) ) ) diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb index 40fec6ba068..4f27f08bf98 100644 --- a/spec/requests/api/graphql/project/issues_spec.rb +++ b/spec/requests/api/graphql/project/issues_spec.rb @@ -9,10 +9,9 @@ RSpec.describe 'getting an issue list for a project' do let_it_be(:project) { create(:project, :repository, :public) } let_it_be(:current_user) { create(:user) } - let_it_be(:issues, reload: true) do - [create(:issue, project: project, discussion_locked: true), - create(:issue, :with_alert, project: project)] - end + let_it_be(:issue_a, reload: true) { create(:issue, project: project, discussion_locked: true) } + let_it_be(:issue_b, reload: true) { create(:issue, :with_alert, project: project) } + let_it_be(:issues, reload: true) { [issue_a, issue_b] } let(:fields) do <<~QUERY @@ -414,4 +413,42 @@ RSpec.describe 'getting an issue list for a project' do expect(response_assignee_ids(issues_data)).to match_array(assignees_as_global_ids(new_issues)) end end + + describe 'N+1 query checks' do + let(:extra_iid_for_second_query) { issue_b.iid.to_s } + let(:search_params) { { iids: [issue_a.iid.to_s] } } + + def execute_query + query = graphql_query_for( + :project, + { full_path: project.full_path }, + query_graphql_field(:issues, search_params, [ + query_graphql_field(:nodes, nil, requested_fields) + ]) + ) + post_graphql(query, current_user: current_user) + end + + context 'when requesting `user_notes_count`' do + let(:requested_fields) { [:user_notes_count] } + + before do + create_list(:note_on_issue, 2, noteable: issue_a, project: project) + create(:note_on_issue, noteable: issue_b, project: project) + end + + include_examples 'N+1 query check' + end + + context 'when requesting `user_discussions_count`' do + let(:requested_fields) { [:user_discussions_count] } + + before do + create_list(:note_on_issue, 2, noteable: issue_a, project: project) + create(:note_on_issue, noteable: issue_b, project: project) + end + + include_examples 'N+1 query check' + end + end end diff --git a/spec/requests/api/graphql/project/jira_import_spec.rb b/spec/requests/api/graphql/project/jira_import_spec.rb index 1cc30b95162..98a3f08baa6 100644 --- a/spec/requests/api/graphql/project/jira_import_spec.rb +++ b/spec/requests/api/graphql/project/jira_import_spec.rb @@ -19,6 +19,7 @@ RSpec.describe 'query Jira import data' do total_issue_count: 4 ) end + let_it_be(:jira_import2) do create( :jira_import_state, :finished, @@ -31,6 +32,7 @@ RSpec.describe 'query Jira import data' do total_issue_count: 3 ) end + let(:query) do %( query { diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb index c737e0b8caf..2b8d537f9fc 100644 --- a/spec/requests/api/graphql/project/merge_requests_spec.rb +++ b/spec/requests/api/graphql/project/merge_requests_spec.rb @@ -243,6 +243,17 @@ RSpec.describe 'getting merge request listings nested in a project' do include_examples 'N+1 query check' end + + context 'when requesting `user_discussions_count`' do + let(:requested_fields) { [:user_discussions_count] } + + before do + create_list(:note_on_merge_request, 2, noteable: merge_request_a, project: project) + create(:note_on_merge_request, noteable: merge_request_c, project: project) + end + + include_examples 'N+1 query check' + end end describe 'sorting and pagination' do diff --git a/spec/requests/api/graphql/project/project_statistics_spec.rb b/spec/requests/api/graphql/project/project_statistics_spec.rb index c226b10ab51..b57c594c64f 100644 --- a/spec/requests/api/graphql/project/project_statistics_spec.rb +++ b/spec/requests/api/graphql/project/project_statistics_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'rendering project statistics' do include GraphqlHelpers let(:project) { create(:project) } - let!(:project_statistics) { create(:project_statistics, project: project, packages_size: 5.gigabytes) } + let!(:project_statistics) { create(:project_statistics, project: project, packages_size: 5.gigabytes, uploads_size: 3.gigabytes) } let(:user) { create(:user) } let(:query) do @@ -31,6 +31,12 @@ RSpec.describe 'rendering project statistics' do expect(graphql_data['project']['statistics']['packagesSize']).to eq(5.gigabytes) end + it 'includes uploads size if the user can read the statistics' do + post_graphql(query, current_user: user) + + expect(graphql_data_at(:project, :statistics, :uploadsSize)).to eq(3.gigabytes) + end + context 'when the project is public' do let(:project) { create(:project, :public) } diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb index 8fce29d0dc6..57dbe258ce4 100644 --- a/spec/requests/api/graphql/project/release_spec.rb +++ b/spec/requests/api/graphql/project/release_spec.rb @@ -13,7 +13,11 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do let_it_be(:link_filepath) { '/direct/asset/link/path' } let_it_be(:released_at) { Time.now - 1.day } - let(:params_for_issues_and_mrs) { { scope: 'all', state: 'opened', release_tag: release.tag } } + let(:base_url_params) { { scope: 'all', release_tag: release.tag } } + let(:opened_url_params) { { state: 'opened', **base_url_params } } + let(:merged_url_params) { { state: 'merged', **base_url_params } } + let(:closed_url_params) { { state: 'closed', **base_url_params } } + let(:post_query) { post_graphql(query, current_user: current_user) } let(:path_prefix) { %w[project release] } let(:data) { graphql_data.dig(*path) } @@ -143,7 +147,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do 'name' => link.name, 'url' => link.url, 'external' => link.external?, - 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << link.filepath : link.url + 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << "/downloads#{link.filepath}" : link.url } end @@ -180,8 +184,11 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do let(:release_fields) do query_graphql_field(:links, nil, %{ selfUrl - mergeRequestsUrl - issuesUrl + openedMergeRequestsUrl + mergedMergeRequestsUrl + closedMergeRequestsUrl + openedIssuesUrl + closedIssuesUrl }) end @@ -190,8 +197,11 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do expect(data).to eq( 'selfUrl' => project_release_url(project, release), - 'mergeRequestsUrl' => project_merge_requests_url(project, params_for_issues_and_mrs), - 'issuesUrl' => project_issues_url(project, params_for_issues_and_mrs) + 'openedMergeRequestsUrl' => project_merge_requests_url(project, opened_url_params), + 'mergedMergeRequestsUrl' => project_merge_requests_url(project, merged_url_params), + 'closedMergeRequestsUrl' => project_merge_requests_url(project, closed_url_params), + 'openedIssuesUrl' => project_issues_url(project, opened_url_params), + 'closedIssuesUrl' => project_issues_url(project, closed_url_params) ) end end diff --git a/spec/requests/api/graphql/project/releases_spec.rb b/spec/requests/api/graphql/project/releases_spec.rb index 7c57c0e9177..6e364c7d7b5 100644 --- a/spec/requests/api/graphql/project/releases_spec.rb +++ b/spec/requests/api/graphql/project/releases_spec.rb @@ -10,6 +10,11 @@ RSpec.describe 'Query.project(fullPath).releases()' do let_it_be(:reporter) { create(:user) } let_it_be(:developer) { create(:user) } + let(:base_url_params) { { scope: 'all', release_tag: release.tag } } + let(:opened_url_params) { { state: 'opened', **base_url_params } } + let(:merged_url_params) { { state: 'merged', **base_url_params } } + let(:closed_url_params) { { state: 'closed', **base_url_params } } + let(:query) do graphql_query_for(:project, { fullPath: project.full_path }, %{ @@ -37,8 +42,11 @@ RSpec.describe 'Query.project(fullPath).releases()' do } links { selfUrl - mergeRequestsUrl - issuesUrl + openedMergeRequestsUrl + mergedMergeRequestsUrl + closedMergeRequestsUrl + openedIssuesUrl + closedIssuesUrl } } } @@ -101,8 +109,11 @@ RSpec.describe 'Query.project(fullPath).releases()' do }, 'links' => { 'selfUrl' => project_release_url(project, release), - 'mergeRequestsUrl' => project_merge_requests_url(project, params_for_issues_and_mrs), - 'issuesUrl' => project_issues_url(project, params_for_issues_and_mrs) + 'openedMergeRequestsUrl' => project_merge_requests_url(project, opened_url_params), + 'mergedMergeRequestsUrl' => project_merge_requests_url(project, merged_url_params), + 'closedMergeRequestsUrl' => project_merge_requests_url(project, closed_url_params), + 'openedIssuesUrl' => project_issues_url(project, opened_url_params), + 'closedIssuesUrl' => project_issues_url(project, closed_url_params) } ) end @@ -300,4 +311,77 @@ RSpec.describe 'Query.project(fullPath).releases()' do it_behaves_like 'no access to any release data' end end + + describe 'sorting behavior' do + let_it_be(:today) { Time.now } + let_it_be(:yesterday) { today - 1.day } + let_it_be(:tomorrow) { today + 1.day } + + let_it_be(:project) { create(:project, :repository, :public) } + + let_it_be(:release_v1) { create(:release, project: project, tag: 'v1', released_at: yesterday, created_at: tomorrow) } + let_it_be(:release_v2) { create(:release, project: project, tag: 'v2', released_at: today, created_at: yesterday) } + let_it_be(:release_v3) { create(:release, project: project, tag: 'v3', released_at: tomorrow, created_at: today) } + + let(:current_user) { developer } + + let(:params) { nil } + + let(:sorted_tags) do + graphql_data.dig('project', 'releases', 'nodes').map { |release| release['tagName'] } + end + + let(:query) do + graphql_query_for(:project, { fullPath: project.full_path }, + %{ + releases#{params ? "(#{params})" : ""} { + nodes { + tagName + } + } + }) + end + + before do + post_query + end + + context 'when no sort: parameter is provided' do + it 'returns the results with the default sort applied (sort: RELEASED_AT_DESC)' do + expect(sorted_tags).to eq(%w(v3 v2 v1)) + end + end + + context 'with sort: RELEASED_AT_DESC' do + let(:params) { 'sort: RELEASED_AT_DESC' } + + it 'returns the releases ordered by released_at in descending order' do + expect(sorted_tags).to eq(%w(v3 v2 v1)) + end + end + + context 'with sort: RELEASED_AT_ASC' do + let(:params) { 'sort: RELEASED_AT_ASC' } + + it 'returns the releases ordered by released_at in ascending order' do + expect(sorted_tags).to eq(%w(v1 v2 v3)) + end + end + + context 'with sort: CREATED_DESC' do + let(:params) { 'sort: CREATED_DESC' } + + it 'returns the releases ordered by created_at in descending order' do + expect(sorted_tags).to eq(%w(v1 v3 v2)) + end + end + + context 'with sort: CREATED_ASC' do + let(:params) { 'sort: CREATED_ASC' } + + it 'returns the releases ordered by created_at in ascending order' do + expect(sorted_tags).to eq(%w(v2 v3 v1)) + end + end + end end diff --git a/spec/requests/api/graphql/project/terraform/states_spec.rb b/spec/requests/api/graphql/project/terraform/states_spec.rb new file mode 100644 index 00000000000..8b67b549efa --- /dev/null +++ b/spec/requests/api/graphql/project/terraform/states_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'query terraform states' do + include GraphqlHelpers + + let_it_be(:project) { create(:project) } + let_it_be(:terraform_state) { create(:terraform_state, :with_version, :locked, project: project) } + let_it_be(:latest_version) { terraform_state.latest_version } + + let(:query) do + graphql_query_for(:project, { fullPath: project.full_path }, + %{ + terraformStates { + count + nodes { + id + name + lockedAt + createdAt + updatedAt + + latestVersion { + id + createdAt + updatedAt + + createdByUser { + id + } + + job { + name + } + } + + lockedByUser { + id + } + } + } + }) + end + + let(:current_user) { project.creator } + let(:data) { graphql_data.dig('project', 'terraformStates') } + + before do + post_graphql(query, current_user: current_user) + end + + it 'returns terraform state data', :aggregate_failures do + state = data.dig('nodes', 0) + version = state['latestVersion'] + + expect(state['id']).to eq(terraform_state.to_global_id.to_s) + expect(state['name']).to eq(terraform_state.name) + expect(state['lockedAt']).to eq(terraform_state.locked_at.iso8601) + expect(state['createdAt']).to eq(terraform_state.created_at.iso8601) + expect(state['updatedAt']).to eq(terraform_state.updated_at.iso8601) + expect(state.dig('lockedByUser', 'id')).to eq(terraform_state.locked_by_user.to_global_id.to_s) + + expect(version['id']).to eq(latest_version.to_global_id.to_s) + expect(version['createdAt']).to eq(latest_version.created_at.iso8601) + expect(version['updatedAt']).to eq(latest_version.updated_at.iso8601) + expect(version.dig('createdByUser', 'id')).to eq(latest_version.created_by_user.to_global_id.to_s) + expect(version.dig('job', 'name')).to eq(latest_version.build.name) + end + + it 'returns count of terraform states' do + count = data.dig('count') + expect(count).to be(project.terraform_states.size) + end + + context 'unauthorized users' do + let(:current_user) { nil } + + it { expect(data).to be_nil } + end +end |