gitlab-org--gitlab-foss/spec/graphql/resolvers/package_pipelines_resolver_spec.rb

209 lines
6.2 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::PackagePipelinesResolver do
include GraphqlHelpers
let_it_be_with_reload(:package) { create(:package) }
let_it_be(:pipelines) { create_list(:ci_pipeline, 3, project: package.project) }
let(:user) { package.project.first_owner }
describe '#resolve' do
let(:returned_pipeline_ids) { graphql_dig_at(subject, 'data', 'package', 'pipelines', 'nodes', 'id') }
let(:returned_errors) { graphql_dig_at(subject, 'errors', 'message') }
let(:pagination_args) { {} }
let(:query) do
pipelines_nodes = 'nodes { id }'
graphql_query_for(
:package,
{ id: global_id_of(package) },
query_graphql_field('pipelines', pagination_args, pipelines_nodes)
)
end
subject do
GitlabSchema.execute(query, context: { current_user: user })
end
before do
pipelines.each do |pipeline|
create(:package_build_info, package: package, pipeline: pipeline)
end
end
shared_examples 'returning the expected pipelines' do
it 'contains the expected pipelines' do
expect_to_contain_exactly(*pipelines)
end
context 'with valid after' do
let(:pagination_args) { { first: 1, after: encode_cursor(id: pipelines[1].id) } }
it 'contains the expected pipelines' do
expect_to_contain_exactly(pipelines[0])
end
end
context 'with valid before' do
let(:pagination_args) { { last: 1, before: encode_cursor(id: pipelines[1].id) } }
it 'contains the expected pipelines' do
expect_to_contain_exactly(pipelines[2])
end
end
context 'with invalid after' do
let(:pagination_args) { { first: 1, after: 'not_json_string' } }
it 'generates an argument error' do
expect(returned_errors).to include('Please provide a valid cursor')
end
end
context 'with invalid after key' do
let(:pagination_args) { { first: 1, after: encode_cursor(foo: 3) } }
it 'generates an argument error' do
expect(returned_errors).to include('Please provide a valid cursor')
end
end
context 'with invalid before' do
let(:pagination_args) { { last: 1, before: 'not_json_string' } }
it 'generates an argument error' do
expect(returned_errors).to include('Please provide a valid cursor')
end
end
context 'with invalid before key' do
let(:pagination_args) { { last: 1, before: encode_cursor(foo: 3) } }
it 'generates an argument error' do
expect(returned_errors).to include('Please provide a valid cursor')
end
end
context 'with unauthorized user' do
let_it_be(:user) { create(:user) }
it 'returns nothing' do
expect(returned_pipeline_ids).to eq(nil)
end
end
context 'with many packages' do
let_it_be_with_reload(:other_package) { create(:package, project: package.project) }
let_it_be(:other_pipelines) { create_list(:ci_pipeline, 3, project: package.project) }
let(:returned_pipeline_ids) do
graphql_dig_at(subject, 'data', 'project', 'packages', 'nodes', 'pipelines', 'nodes', 'id')
end
let(:query) do
pipelines_query = query_graphql_field('pipelines', pagination_args, 'nodes { id }')
<<~QUERY
{
project(fullPath: "#{package.project.full_path}") {
packages {
nodes { #{pipelines_query} }
}
}
}
QUERY
end
before do
other_pipelines.each do |pipeline|
create(:package_build_info, package: other_package, pipeline: pipeline)
end
end
it 'contains the expected pipelines' do
expect_to_contain_exactly(*(pipelines + other_pipelines))
end
it 'handles n+1 situations' do
control = ActiveRecord::QueryRecorder.new do
GitlabSchema.execute(query, context: { current_user: user })
end
create_package_with_pipelines(package.project)
expectation = expect { GitlabSchema.execute(query, context: { current_user: user }) }
if Feature.enabled?(:packages_graphql_pipelines_resolver)
expectation.not_to exceed_query_limit(control)
else
expectation.to exceed_query_limit(control)
end
end
def create_package_with_pipelines(project)
extra_package = create(:package, project: project)
create_list(:ci_pipeline, 3, project: project).each do |pipeline|
create(:package_build_info, package: extra_package, pipeline: pipeline)
end
end
end
end
context 'with packages_graphql_pipelines_resolver enabled' do
before do
expect_detect_mode([:new_finder])
end
it_behaves_like 'returning the expected pipelines'
end
context 'with packages_graphql_pipelines_resolver disabled' do
before do
stub_feature_flags(packages_graphql_pipelines_resolver: false)
expect_detect_mode([:old_finder, :object_field])
end
it_behaves_like 'returning the expected pipelines'
end
def encode_cursor(json)
GitlabSchema.cursor_encoder.encode(
Gitlab::Json.dump(json),
nonce: true
)
end
def expect_to_contain_exactly(*pipelines)
ids = pipelines.map { |pipeline| global_id_of(pipeline) }
expect(returned_pipeline_ids).to contain_exactly(*ids)
end
def expect_detect_mode(modes)
allow_next_instance_of(described_class) do |resolver|
detect_mode_method = resolver.method(:detect_mode)
allow(resolver).to receive(:detect_mode) do
result = detect_mode_method.call
expect(modes).to include(result)
result
end
end
end
end
describe '.field options' do
let(:field) do
field_options = described_class.field_options.merge(
owner: resolver_parent,
name: 'dummy_field'
)
::Types::BaseField.new(**field_options)
end
it 'sets them properly' do
expect(field).not_to be_connection
expect(field.extras).to match_array([:lookahead])
end
end
end