diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
commit | aee0a117a889461ce8ced6fcf73207fe017f1d99 (patch) | |
tree | 891d9ef189227a8445d83f35c1b0fc99573f4380 /spec/graphql/resolvers | |
parent | 8d46af3258650d305f53b819eabf7ab18d22f59e (diff) |
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'spec/graphql/resolvers')
7 files changed, 308 insertions, 1 deletions
diff --git a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb index 53d2c8a853c..6907c55bd48 100644 --- a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb +++ b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb @@ -25,7 +25,7 @@ RSpec.describe Resolvers::BoardListIssuesResolver do let(:wildcard_started) { 'STARTED' } let(:filters) { { milestone_title: ["started"], milestone_wildcard_id: wildcard_started } } - it 'raises a mutually exclusive filter error when milstone wildcard and title are provided' do + it 'raises a mutually exclusive filter error when milestone wildcard and title are provided' do expect do resolve_board_list_issues(args: { filters: filters }) end.to raise_error(Gitlab::Graphql::Errors::ArgumentError) @@ -80,6 +80,16 @@ RSpec.describe Resolvers::BoardListIssuesResolver do expect(result).to match_array([]) end + + context 'when filtering by confidential' do + let(:confidential_issue) { create(:issue, project: project, labels: [label], relative_position: nil, confidential: true) } + + it 'returns matching issue' do + result = resolve_board_list_issues(args: { filters: { confidential: true } }) + + expect(result).to contain_exactly(confidential_issue) + end + end end end diff --git a/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb new file mode 100644 index 00000000000..fbef07b72e6 --- /dev/null +++ b/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::Ci::RunnerStatusResolver do + include GraphqlHelpers + + describe '#resolve' do + let(:user) { build(:user) } + let(:runner) { build(:ci_runner) } + + subject(:resolve_subject) { resolve(described_class, ctx: { current_user: user }, obj: runner, args: args) } + + context 'with legacy_mode' do + context 'set to 14.5' do + let(:args) do + { legacy_mode: '14.5' } + end + + it 'calls runner.status with specified legacy_mode' do + expect(runner).to receive(:status).with('14.5').once.and_return(:online) + + expect(resolve_subject).to eq(:online) + end + end + + context 'set to nil' do + let(:args) do + { legacy_mode: nil } + end + + it 'calls runner.status with specified legacy_mode' do + expect(runner).to receive(:status).with(nil).once.and_return(:stale) + + expect(resolve_subject).to eq(:stale) + end + end + end + end +end diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb index bb8dadeca40..df6490df915 100644 --- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb @@ -45,6 +45,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver do let(:finder) { instance_double(::Ci::RunnersFinder) } let(:args) do { + active: true, status: 'active', type: :instance_type, tag_list: ['active_runner'], @@ -55,6 +56,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver do let(:expected_params) do { + active: true, status_status: 'active', type_type: :instance_type, tag_name: ['active_runner'], diff --git a/spec/graphql/resolvers/clusters/agent_activity_events_resolver_spec.rb b/spec/graphql/resolvers/clusters/agent_activity_events_resolver_spec.rb new file mode 100644 index 00000000000..5a6b27e43a5 --- /dev/null +++ b/spec/graphql/resolvers/clusters/agent_activity_events_resolver_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::Clusters::AgentActivityEventsResolver do + include GraphqlHelpers + + it { expect(described_class.type).to eq(Types::Clusters::AgentActivityEventType) } + it { expect(described_class.null).to be_truthy } + + describe '#resolve' do + let_it_be(:agent) { create(:cluster_agent) } + + let(:user) { create(:user, maintainer_projects: [agent.project]) } + let(:ctx) { { current_user: user } } + let(:events) { double } + + before do + allow(agent).to receive(:activity_events).and_return(events) + end + + subject { resolve(described_class, obj: agent, ctx: ctx) } + + it 'returns events associated with the agent' do + expect(subject).to eq(events) + end + + context 'user does not have permission' do + let(:user) { create(:user, developer_projects: [agent.project]) } + + it { is_expected.to be_empty } + end + end +end diff --git a/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb b/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb new file mode 100644 index 00000000000..4e7ea253c87 --- /dev/null +++ b/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::ContainerRepositoryTagsResolver do + include GraphqlHelpers + + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :public) } + let_it_be_with_reload(:repository) { create(:container_repository, project: project) } + + let(:args) { { sort: nil } } + + describe '#resolve' do + let(:resolver) { resolve(described_class, ctx: { current_user: user }, obj: repository, args: args) } + + before do + stub_container_registry_config(enabled: true) + end + + context 'by name' do + subject { resolver.map(&:name) } + + before do + stub_container_registry_tags(repository: repository.path, tags: %w(aaa bab bbb ccc 123), with_manifest: false) + end + + context 'without sort' do + # order is not guaranteed + it { is_expected.to contain_exactly('aaa', 'bab', 'bbb', 'ccc', '123') } + end + + context 'with sorting and filtering' do + context "name_asc" do + let(:args) { { sort: :name_asc } } + + it { is_expected.to eq(%w(123 aaa bab bbb ccc)) } + end + + context "name_desc" do + let(:args) { { sort: :name_desc } } + + it { is_expected.to eq(%w(ccc bbb bab aaa 123)) } + end + + context 'filter by name' do + let(:args) { { sort: :name_desc, name: 'b' } } + + it { is_expected.to eq(%w(bbb bab)) } + end + end + end + end +end diff --git a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb new file mode 100644 index 00000000000..d48d4d8ae01 --- /dev/null +++ b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb @@ -0,0 +1,84 @@ +# 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.owner } + let(:args) { {} } + + describe '#resolve' do + subject { resolve(described_class, obj: package, args: args, ctx: { current_user: user }) } + + before do + package.pipelines = pipelines + package.save! + end + + it { is_expected.to contain_exactly(*pipelines) } + + context 'with invalid after' do + let(:args) { { first: 1, after: 'not_json_string' } } + + it 'raises argument error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + end + end + + context 'with invalid after key' do + let(:args) { { first: 1, after: encode_cursor(foo: 3) } } + + it 'raises argument error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + end + end + + context 'with invalid before' do + let(:args) { { last: 1, before: 'not_json_string' } } + + it 'raises argument error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + end + end + + context 'with invalid before key' do + let(:args) { { last: 1, before: encode_cursor(foo: 3) } } + + it 'raises argument error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + end + end + + context '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 + + context 'with unauthorized user' do + let_it_be(:user) { create(:user) } + + it { is_expected.to be_nil } + end + + def encode_cursor(json) + GitlabSchema.cursor_encoder.encode( + Gitlab::Json.dump(json), + nonce: true + ) + end + end +end diff --git a/spec/graphql/resolvers/users/participants_resolver_spec.rb b/spec/graphql/resolvers/users/participants_resolver_spec.rb new file mode 100644 index 00000000000..3f04d157410 --- /dev/null +++ b/spec/graphql/resolvers/users/participants_resolver_spec.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::Users::ParticipantsResolver do + include GraphqlHelpers + + describe '#resolve' do + let_it_be(:user) { create(:user) } + let_it_be(:guest) { create(:user) } + let_it_be(:project) { create(:project, :public) } + let_it_be(:issue) { create(:issue, project: project) } + let_it_be(:note) do + create( + :note, + :system, + :confidential, + project: project, + noteable: issue, + author: create(:user) + ) + end + + let_it_be(:note_metadata) { create(:system_note_metadata, note: note) } + + subject(:resolved_items) { resolve(described_class, args: {}, ctx: { current_user: current_user }, obj: issue)&.items } + + before do + project.add_guest(guest) + project.add_developer(user) + end + + context 'when current user is not set' do + let(:current_user) { nil } + + it 'returns only publicly visible participants for this user' do + is_expected.to match_array([issue.author]) + end + end + + context 'when current user does not have enough permissions' do + let(:current_user) { guest } + + it 'returns only publicly visible participants for this user' do + is_expected.to match_array([issue.author]) + end + end + + context 'when current user has access to confidential notes' do + let(:current_user) { user } + + it 'returns all participants for this user' do + is_expected.to match_array([issue.author, note.author]) + end + + context 'N+1 queries' do + let(:query) { -> { resolve(described_class, args: {}, ctx: { current_user: current_user }, obj: issue)&.items } } + + before do + # warm-up + query.call + end + + it 'does not execute N+1 for project relation' do + control_count = ActiveRecord::QueryRecorder.new { query.call } + + create(:note, :confidential, project: project, noteable: issue, author: create(:user)) + + expect { query.call }.not_to exceed_query_limit(control_count) + end + + it 'does not execute N+1 for system note metadata relation' do + control_count = ActiveRecord::QueryRecorder.new { query.call } + + new_note = create(:note, :system, project: project, noteable: issue, author: create(:user)) + create(:system_note_metadata, note: new_note) + + expect { query.call }.not_to exceed_query_limit(control_count) + end + end + end + end +end |