diff options
Diffstat (limited to 'spec/requests/api/graphql/ci/jobs_spec.rb')
-rw-r--r-- | spec/requests/api/graphql/ci/jobs_spec.rb | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/spec/requests/api/graphql/ci/jobs_spec.rb b/spec/requests/api/graphql/ci/jobs_spec.rb index 674407c0a0e..0d5ac725edd 100644 --- a/spec/requests/api/graphql/ci/jobs_spec.rb +++ b/spec/requests/api/graphql/ci/jobs_spec.rb @@ -1,6 +1,130 @@ # frozen_string_literal: true require 'spec_helper' +RSpec.describe 'Query.jobs', feature_category: :continuous_integration do + include GraphqlHelpers + + let_it_be(:admin) { create(:admin) } + let_it_be(:project) { create(:project, :repository, :public) } + let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + let_it_be(:runner) { create(:ci_runner) } + let_it_be(:build) do + create(:ci_build, pipeline: pipeline, name: 'my test job', ref: 'HEAD', tag_list: %w[tag1 tag2], runner: runner) + end + + let(:query) do + %( + query { + jobs { + nodes { + id + #{fields.join(' ')} + } + } + } + ) + end + + let(:jobs_graphql_data) { graphql_data_at(:jobs, :nodes) } + + let(:fields) do + %w[commitPath refPath webPath browseArtifactsPath playPath tags runner{id}] + end + + it 'returns the paths in each job of a pipeline' do + post_graphql(query, current_user: admin) + + expect(jobs_graphql_data).to contain_exactly( + a_graphql_entity_for( + build, + commit_path: "/#{project.full_path}/-/commit/#{build.sha}", + ref_path: "/#{project.full_path}/-/commits/HEAD", + web_path: "/#{project.full_path}/-/jobs/#{build.id}", + browse_artifacts_path: "/#{project.full_path}/-/jobs/#{build.id}/artifacts/browse", + play_path: "/#{project.full_path}/-/jobs/#{build.id}/play", + tags: build.tag_list, + runner: a_graphql_entity_for(runner) + ) + ) + end + + context 'when requesting individual fields' do + using RSpec::Parameterized::TableSyntax + + let_it_be(:admin2) { create(:admin) } + let_it_be(:project2) { create(:project) } + let_it_be(:pipeline2) { create(:ci_pipeline, project: project2) } + + where(:field) { fields } + + with_them do + let(:fields) do + [field] + end + + it 'does not generate N+1 queries', :request_store, :use_sql_query_cache do + # warm-up cache and so on: + args = { current_user: admin } + args2 = { current_user: admin2 } + post_graphql(query, **args2) + + control = ActiveRecord::QueryRecorder.new(skip_cached: false) do + post_graphql(query, **args) + end + + create(:ci_build, pipeline: pipeline2, name: 'my test job2', ref: 'HEAD', tag_list: %w[tag3]) + post_graphql(query, **args) + + expect { post_graphql(query, **args) }.not_to exceed_all_query_limit(control) + end + end + end +end + +RSpec.describe 'Query.jobs.runner', feature_category: :continuous_integration do + include GraphqlHelpers + + let_it_be(:admin) { create(:admin) } + + let(:jobs_runner_graphql_data) { graphql_data_at(:jobs, :nodes, :runner) } + let(:query) do + %( + query { + jobs { + nodes { + runner{ + id + adminUrl + description + } + } + } + } + ) + end + + context 'when job has no runner' do + let_it_be(:build) { create(:ci_build) } + + it 'returns nil' do + post_graphql(query, current_user: admin) + + expect(jobs_runner_graphql_data).to eq([nil]) + end + end + + context 'when job has runner' do + let_it_be(:runner) { create(:ci_runner) } + let_it_be(:build_with_runner) { create(:ci_build, runner: runner) } + + it 'returns runner attributes' do + post_graphql(query, current_user: admin) + + expect(jobs_runner_graphql_data).to contain_exactly(a_graphql_entity_for(runner, :description, 'adminUrl' => "http://localhost/admin/runners/#{runner.id}")) + end + end +end + RSpec.describe 'Query.project.pipeline', feature_category: :continuous_integration do include GraphqlHelpers @@ -260,6 +384,68 @@ RSpec.describe 'Query.project.pipeline', feature_category: :continuous_integrati end end + describe '.jobs.runnerManager' do + let_it_be(:admin) { create(:admin) } + let_it_be(:runner_manager) { create(:ci_runner_machine, created_at: Time.current, contacted_at: Time.current) } + let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + let_it_be(:build) do + create(:ci_build, pipeline: pipeline, name: 'my test job', runner_manager: runner_manager) + end + + let(:query) do + %( + query { + project(fullPath: "#{project.full_path}") { + pipeline(iid: "#{pipeline.iid}") { + jobs { + nodes { + id + name + runnerManager { + #{all_graphql_fields_for('CiRunnerManager', excluded: [:runner], max_depth: 1)} + } + } + } + } + } + } + ) + end + + let(:jobs_graphql_data) { graphql_data_at(:project, :pipeline, :jobs, :nodes) } + + it 'returns the runner manager in each job of a pipeline' do + post_graphql(query, current_user: admin) + + expect(jobs_graphql_data).to contain_exactly( + a_graphql_entity_for( + build, + name: build.name, + runner_manager: a_graphql_entity_for( + runner_manager, + system_id: runner_manager.system_xid, + created_at: runner_manager.created_at.iso8601, + contacted_at: runner_manager.contacted_at.iso8601, + status: runner_manager.status.to_s.upcase + ) + ) + ) + end + + it 'does not generate N+1 queries', :request_store, :use_sql_query_cache do + admin2 = create(:admin) + + control = ActiveRecord::QueryRecorder.new(skip_cached: false) do + post_graphql(query, current_user: admin) + end + + runner_manager2 = create(:ci_runner_machine) + create(:ci_build, pipeline: pipeline, name: 'my test job2', runner_manager: runner_manager2) + + expect { post_graphql(query, current_user: admin2) }.not_to exceed_all_query_limit(control) + end + end + describe '.jobs.count' do let_it_be(:pipeline) { create(:ci_pipeline, project: project) } let_it_be(:successful_job) { create(:ci_build, :success, pipeline: pipeline) } |