diff options
Diffstat (limited to 'spec/graphql')
70 files changed, 784 insertions, 276 deletions
diff --git a/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb b/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb index aaa74fa78aa..0dcfaa9b8ac 100644 --- a/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb +++ b/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::Ci::Runner::BulkDelete, feature_category: :runner_fleet do +RSpec.describe Mutations::Ci::Runner::BulkDelete, feature_category: :fleet_visibility do include GraphqlHelpers let_it_be(:admin_user) { create(:user, :admin) } diff --git a/spec/graphql/mutations/ci/runner/delete_spec.rb b/spec/graphql/mutations/ci/runner/delete_spec.rb index beff18e1dfd..3617c751165 100644 --- a/spec/graphql/mutations/ci/runner/delete_spec.rb +++ b/spec/graphql/mutations/ci/runner/delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::Ci::Runner::Delete, feature_category: :runner_fleet do +RSpec.describe Mutations::Ci::Runner::Delete, feature_category: :fleet_visibility do include GraphqlHelpers let_it_be(:runner) { create(:ci_runner) } diff --git a/spec/graphql/mutations/ci/runner/update_spec.rb b/spec/graphql/mutations/ci/runner/update_spec.rb index 03bfd4d738b..32c4e6952e4 100644 --- a/spec/graphql/mutations/ci/runner/update_spec.rb +++ b/spec/graphql/mutations/ci/runner/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::Ci::Runner::Update, feature_category: :runner_fleet do +RSpec.describe Mutations::Ci::Runner::Update, feature_category: :fleet_visibility do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/graphql/mutations/design_management/delete_spec.rb b/spec/graphql/mutations/design_management/delete_spec.rb index 1b78529fbc7..7f499301543 100644 --- a/spec/graphql/mutations/design_management/delete_spec.rb +++ b/spec/graphql/mutations/design_management/delete_spec.rb @@ -86,46 +86,47 @@ RSpec.describe Mutations::DesignManagement::Delete do end end - it 'runs no more than 31 queries' do + it 'runs no more than 34 queries' do allow(Gitlab::Tracking).to receive(:event) # rubocop:disable RSpec/ExpectGitlabTracking filenames.each(&:present?) # ignore setup - # Queries: as of 2022-09-08 + # Queries: as of 2022-12-01 # ------------- - # 01. routing query - # 02. policy query: find namespace by type and id - # 03. policy query: find namespace by id - # 04. policy query: project.project_feature - # 05,06. project.authorizations for user (same query twice) - # 07. find issue by iid - # 08. find project by id - # 09. find namespace by id - # 10. find group namespace by id - # 11. policy query: find namespace by id (same query as 3) - # 12. project.authorizations for user (same query as 5) - # 13. find user by id - # 14. project.project_features (same query as 3) - # 15. project.authorizations for user (same query as 5) - # 16. current designs by filename and issue - # 17, 18 project.authorizations for user (same query as 5) - # 19. find design_management_repository for project - # 20. find route by id and source_type + # 01. for routes to find routes.source_id of projects matching paths + # 02. Find projects with the above source id. + # 03. preload routes of the above projects + # 04. policy query: find namespace by type and id + # 05. policy query: namespace_bans + # 06. policy query: project.project_feature + # 07,08. project.authorizations for user (same query twice) + # 09. find issue by iid + # 10. find project by id + # 11. find namespace by id + # 12. policy query: find namespace by type and id (same query as 4) + # 13. project.authorizations for user (same query as 7) + # 14. find user by id + # 15. project.project_features (same query as 6) + # 16. project.authorizations for user (same query as 7) + # 17. current designs by filename and issue + # 18, 19 project.authorizations for user (same query as 7) + # 20. find design_management_repository for project + # 21. find route by source_id and source_type # ------------- our queries are below: - # 21. start transaction - # 22. create version with sha and issue - # 23. create design-version links - # 24. validate version.actions.present? - # 25. validate version.sha is unique - # 26. validate version.issue.present? - # 27. leave transaction - # 28. find project by id (same query as 8) - # 29. find namespace by id (same query as 9) - # 30. find project by id (same query as 8) - # 31. find project by id (same query as 8) - # 32. create event - # 33. find plan for standard context + # 22. start transaction + # 23. create version with sha and issue + # 24. create design-version links + # 25. validate version.actions.present? + # 26. validate version.sha is unique + # 27. validate version.issue.present? + # 28. leave transaction + # 29. find project by id (same query as 10) + # 30. find namespace by id (same query as 11) + # 31. find project by id (same query as 10) + # 32. find project by id (same query as 10) + # 33. create event + # 34. find plan for standard context # - expect { run_mutation }.not_to exceed_query_limit(33) + expect { run_mutation }.not_to exceed_query_limit(34) end end diff --git a/spec/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/graphql/mutations/namespace/package_settings/update_spec.rb index f4e79481d44..b184baaca3e 100644 --- a/spec/graphql/mutations/namespace/package_settings/update_spec.rb +++ b/spec/graphql/mutations/namespace/package_settings/update_spec.rb @@ -38,7 +38,8 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update, feature_category: npm_package_requests_forwarding: nil, lock_npm_package_requests_forwarding: false, pypi_package_requests_forwarding: nil, - lock_pypi_package_requests_forwarding: false + lock_pypi_package_requests_forwarding: false, + nuget_symbol_server_enabled: false }, to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE', @@ -51,7 +52,8 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update, feature_category: npm_package_requests_forwarding: true, lock_npm_package_requests_forwarding: true, pypi_package_requests_forwarding: true, - lock_pypi_package_requests_forwarding: true + lock_pypi_package_requests_forwarding: true, + nuget_symbol_server_enabled: true } it_behaves_like 'returning a success' @@ -106,7 +108,8 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update, feature_category: npm_package_requests_forwarding: true, lock_npm_package_requests_forwarding: true, pypi_package_requests_forwarding: true, - lock_pypi_package_requests_forwarding: true + lock_pypi_package_requests_forwarding: true, + nuget_symbol_server_enabled: true } end diff --git a/spec/graphql/mutations/projects/star_spec.rb b/spec/graphql/mutations/projects/star_spec.rb new file mode 100644 index 00000000000..6b1811dcd39 --- /dev/null +++ b/spec/graphql/mutations/projects/star_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Projects::Star, feature_category: :groups_and_projects do + describe '#resolve' do + let_it_be(:user, freeze: true) { create(:user) } + + subject(:mutation) do + described_class + .new(object: nil, context: { current_user: user }, field: nil) + .resolve(project_id: project.to_global_id, starred: starred) + end + + context 'when the user has read access to the project' do + let_it_be_with_reload(:project) { create(:project, :public) } + + context 'and the project is not starred' do + context 'and the user stars the project' do + let(:starred) { true } + + it 'stars the project for the current user' do + expect(mutation).to include(count: 1) + expect(project.reset.starrers).to include(user) + end + end + + context 'and the user unstars the project' do + let(:starred) { false } + + it 'does not raise an error or change the number of stars' do + expect(mutation).to include(count: 0) + expect(project.reset.starrers).not_to include(user) + end + end + end + + context 'and the project is starred' do + before do + user.toggle_star(project) + end + + context 'and the user stars the project' do + let(:starred) { true } + + it 'does not raise an error or change the number of stars' do + expect(mutation).to include(count: 1) + expect(project.reset.starrers).to include(user) + end + end + + context 'and the user unstars the project' do + let(:starred) { false } + + it 'unstars the project for the current user' do + expect(mutation).to include(count: 0) + expect(project.reset.starrers).not_to include(user) + end + end + end + end + + context 'when the user does not have read access to the project' do + let_it_be(:project, freeze: true) { create(:project, :private) } + let(:starred) { true } + + it 'raises an error' do + expect { mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + expect(project.starrers).not_to include(user) + end + end + end +end diff --git a/spec/graphql/resolvers/blame_resolver_spec.rb b/spec/graphql/resolvers/blame_resolver_spec.rb index a3344132928..ff6bfa97def 100644 --- a/spec/graphql/resolvers/blame_resolver_spec.rb +++ b/spec/graphql/resolvers/blame_resolver_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Resolvers::BlameResolver, feature_category: :source_code_manageme let(:path) { 'files/ruby/popen.rb' } let(:commit) { project.commit('master') } let(:blob) { project.repository.blob_at(commit.id, path) } - let(:args) { { from_line: 1, to_line: 2 } } + let(:args) { { from_line: 1, to_line: 100 } } subject(:resolve_blame) { resolve(described_class, obj: blob, args: args, ctx: { current_user: user }) } @@ -39,10 +39,10 @@ RSpec.describe Resolvers::BlameResolver, feature_category: :source_code_manageme end end - shared_examples 'argument error' do + shared_examples 'argument error' do |error_message| it 'raises an ArgumentError' do expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, - '`from_line` and `to_line` must be greater than or equal to 1') do + error_message) do resolve_blame end end @@ -52,23 +52,33 @@ RSpec.describe Resolvers::BlameResolver, feature_category: :source_code_manageme context 'when from_line is below 1' do let(:args) { { from_line: 0, to_line: 2 } } - it_behaves_like 'argument error' + it_behaves_like 'argument error', '`from_line` and `to_line` must be greater than or equal to 1' end context 'when to_line is below 1' do let(:args) { { from_line: 1, to_line: 0 } } - it_behaves_like 'argument error' + it_behaves_like 'argument error', '`from_line` and `to_line` must be greater than or equal to 1' end context 'when to_line less than from_line' do let(:args) { { from_line: 3, to_line: 1 } } + it_behaves_like 'argument error', '`to_line` must be greater than or equal to `from_line`' + end + + context 'when difference between to_line and from_line is greater then 99' do + let(:args) { { from_line: 3, to_line: 103 } } + + it_behaves_like 'argument error', + '`to_line` must be greater than or equal to `from_line` and smaller than `from_line` + 100' + end + + context 'when to_line and from_line are the same' do + let(:args) { { from_line: 1, to_line: 1 } } + it 'returns blame object' do - expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, - '`to_line` must be greater than or equal to `from_line`') do - resolve_blame - end + expect(resolve_blame).to be_an_instance_of(Gitlab::Blame) end end diff --git a/spec/graphql/resolvers/ci/catalog/resource_resolver_spec.rb b/spec/graphql/resolvers/ci/catalog/resource_resolver_spec.rb index 19fc0c7fc4c..313d1d337da 100644 --- a/spec/graphql/resolvers/ci/catalog/resource_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/catalog/resource_resolver_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Resolvers::Ci::Catalog::ResourceResolver, feature_category: :pipe let_it_be(:namespace) { create(:group) } let_it_be(:project) { create(:project, :private, namespace: namespace) } - let_it_be(:resource) { create(:ci_catalog_resource, project: project) } + let_it_be(:resource) { create(:ci_catalog_resource, :published, project: project) } let_it_be(:user) { create(:user) } describe '#resolve' do @@ -20,7 +20,7 @@ RSpec.describe Resolvers::Ci::Catalog::ResourceResolver, feature_category: :pipe context 'when resource is found' do it 'returns a single CI/CD Catalog resource' do result = resolve(described_class, ctx: { current_user: user }, - args: { id: resource.to_global_id.to_s }) + args: { id: resource.to_global_id }) expect(result.id).to eq(resource.id) expect(result.class).to eq(Ci::Catalog::Resource) @@ -30,7 +30,9 @@ RSpec.describe Resolvers::Ci::Catalog::ResourceResolver, feature_category: :pipe context 'when resource is not found' do it 'raises ResourceNotAvailable error' do result = resolve(described_class, ctx: { current_user: user }, - args: { id: "gid://gitlab/Ci::Catalog::Resource/not-a-real-id" }) + args: { id: GlobalID.new( + ::Gitlab::GlobalId.build(model_name: '::Ci::Catalog::Resource', id: "not-a-real-id") + ) }) expect(result).to be_a(::Gitlab::Graphql::Errors::ResourceNotAvailable) end @@ -40,7 +42,7 @@ RSpec.describe Resolvers::Ci::Catalog::ResourceResolver, feature_category: :pipe context 'when user is not authorised to view the resource' do it 'raises ResourceNotAvailable error' do result = resolve(described_class, ctx: { current_user: user }, - args: { id: resource.to_global_id.to_s }) + args: { id: resource.to_global_id }) expect(result).to be_a(::Gitlab::Graphql::Errors::ResourceNotAvailable) end @@ -115,7 +117,7 @@ RSpec.describe Resolvers::Ci::Catalog::ResourceResolver, feature_category: :pipe expect_graphql_error_to_be_created(::Gitlab::Graphql::Errors::ArgumentError, "Exactly one of 'id' or 'full_path' arguments is required.") do resolve(described_class, ctx: { current_user: user }, - args: { full_path: resource.project.full_path, id: resource.to_global_id.to_s }) + args: { full_path: resource.project.full_path, id: resource.to_global_id }) end end end diff --git a/spec/graphql/resolvers/ci/catalog/resources/versions_resolver_spec.rb b/spec/graphql/resolvers/ci/catalog/resources/versions_resolver_spec.rb new file mode 100644 index 00000000000..1ce0e91765f --- /dev/null +++ b/spec/graphql/resolvers/ci/catalog/resources/versions_resolver_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::Ci::Catalog::Resources::VersionsResolver, feature_category: :pipeline_composition do + include GraphqlHelpers + + include_context 'when there are catalog resources with versions' + + let(:sort) { nil } + let(:args) { { sort: sort }.compact } + let(:ctx) { { current_user: current_user } } + + subject(:result) { resolve(described_class, ctx: ctx, obj: resource1, args: args) } + + describe '#resolve' do + context 'when the user is authorized to read project releases' do + before_all do + resource1.project.add_guest(current_user) + end + + context 'when sort argument is not provided' do + it 'returns versions ordered by released_at descending' do + expect(result.items).to eq([v1_1, v1_0]) + end + end + + context 'when sort argument is provided' do + context 'when sort is CREATED_ASC' do + let(:sort) { 'CREATED_ASC' } + + it 'returns versions ordered by created_at ascending' do + expect(result.items.to_a).to eq([v1_1, v1_0]) + end + end + + context 'when sort is CREATED_DESC' do + let(:sort) { 'CREATED_DESC' } + + it 'returns versions ordered by created_at descending' do + expect(result.items).to eq([v1_0, v1_1]) + end + end + + context 'when sort is RELEASED_AT_ASC' do + let(:sort) { 'RELEASED_AT_ASC' } + + it 'returns versions ordered by released_at ascending' do + expect(result.items).to eq([v1_0, v1_1]) + end + end + + context 'when sort is RELEASED_AT_DESC' do + let(:sort) { 'RELEASED_AT_DESC' } + + it 'returns versions ordered by released_at descending' do + expect(result.items).to eq([v1_1, v1_0]) + end + end + end + end + + context 'when the user is not authorized to read project releases' do + it 'returns empty response' do + expect(result).to be_empty + end + end + end +end diff --git a/spec/graphql/resolvers/ci/catalog/resources_resolver_spec.rb b/spec/graphql/resolvers/ci/catalog/resources_resolver_spec.rb index 97105db686f..a55724b5611 100644 --- a/spec/graphql/resolvers/ci/catalog/resources_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/catalog/resources_resolver_spec.rb @@ -6,23 +6,31 @@ RSpec.describe Resolvers::Ci::Catalog::ResourcesResolver, feature_category: :pip include GraphqlHelpers let_it_be(:namespace) { create(:group) } - let_it_be(:project_1) { create(:project, name: 'Z', namespace: namespace) } - let_it_be(:project_2) { create(:project, name: 'A_Test', namespace: namespace) } - let_it_be(:project_3) { create(:project, name: 'L', description: 'Test', namespace: namespace) } - let_it_be(:resource_1) { create(:ci_catalog_resource, project: project_1) } - let_it_be(:resource_2) { create(:ci_catalog_resource, project: project_2) } - let_it_be(:resource_3) { create(:ci_catalog_resource, project: project_3) } + let_it_be(:private_namespace_project) { create(:project, :private, name: 'z private test', namespace: namespace) } + let_it_be(:private_namespace_project_2) { create(:project, :private, name: 'a private test', namespace: namespace) } + let_it_be(:public_namespace_project) do + create(:project, :public, name: 'public', description: 'Test', namespace: namespace) + end + + let_it_be(:internal_project) { create(:project, :internal, name: 'internal') } + let_it_be(:private_resource) { create(:ci_catalog_resource, :published, project: private_namespace_project) } + let_it_be(:private_resource_2) { create(:ci_catalog_resource, project: private_namespace_project_2) } + let_it_be(:public_resource) { create(:ci_catalog_resource, :published, project: public_namespace_project) } + let_it_be(:internal_resource) { create(:ci_catalog_resource, :published, project: internal_project) } let_it_be(:user) { create(:user) } let(:ctx) { { current_user: user } } let(:search) { nil } let(:sort) { nil } + let(:scope) { nil } + let(:project_path) { nil } let(:args) do { - project_path: project_1.full_path, + project_path: project_path, sort: sort, - search: search + search: search, + scope: scope }.compact end @@ -31,40 +39,89 @@ RSpec.describe Resolvers::Ci::Catalog::ResourcesResolver, feature_category: :pip describe '#resolve' do context 'with an authorized user' do before_all do - namespace.add_owner(user) + namespace.add_reporter(user) + internal_project.add_reporter(user) end - it 'returns all catalog resources visible to the current user in the namespace' do - expect(result.items.count).to be(3) - expect(result.items.pluck(:name)).to contain_exactly('Z', 'A_Test', 'L') + context 'when the project path argument is provided' do + let(:project_path) { private_namespace_project.full_path } + + it 'returns all catalog resources visible to the current user in the namespace' do + expect(result.items.count).to be(2) + expect(result.items.pluck(:name)).to contain_exactly('z private test', 'public') + end end - context 'when the sort parameter is not provided' do + context 'when sort argument is not provided' do it 'returns all catalog resources sorted by descending created date' do - expect(result.items.pluck(:name)).to eq(%w[L A_Test Z]) + expect(result.items.pluck(:name)).to eq(['internal', 'public', 'z private test']) end end - context 'when the sort parameter is provided' do + context 'when the sort argument is provided' do let(:sort) { 'NAME_DESC' } - it 'returns all catalog resources sorted by descending name' do - expect(result.items.pluck(:name)).to eq(%w[Z L A_Test]) + it 'returns all published catalog resources sorted by descending name' do + expect(result.items.pluck(:name)).to eq(['z private test', 'public', 'internal']) end end - context 'when the search parameter is provided' do + context 'when the search argument is provided' do let(:search) { 'test' } - it 'returns the catalog resources that match the search term' do - expect(result.items.pluck(:name)).to contain_exactly('A_Test', 'L') + it 'returns published catalog resources that match the search term' do + expect(result.items.pluck(:name)).to contain_exactly('z private test', 'public') + end + end + + context 'with scope argument' do + it 'defaults to :all and returns all catalog resources' do + expect(result.items.count).to be(3) + expect(result.items.pluck(:name)).to contain_exactly('public', 'internal', 'z private test') + end + + context 'when the scope argument is :namespaces' do + let(:scope) { 'NAMESPACES' } + + it 'returns projects of the namespaces the user is a member of' do + namespace = create(:namespace, owner: user) + internal_public_project = create(:project, :internal, name: 'internal public', namespace: namespace) + create(:ci_catalog_resource, :published, project: internal_public_project) + + expect(result.items.count).to be(4) + expect(result.items.pluck(:name)).to contain_exactly('public', 'internal public', 'internal', + 'z private test') + end + end + + context 'and the ci_guard_for_catalog_resource_scope FF is disabled' do + before do + stub_feature_flags(ci_guard_for_catalog_resource_scope: false) + end + + it 'returns all the catalog resources' do + expect(result.items.count).to be(3) + expect(result.items.pluck(:name)).to contain_exactly('public', 'internal', 'z private test') + end + end + + context 'when the scope is invalid' do + let(:scope) { 'INVALID' } + + it 'defaults to :all and returns all catalog resources' do + expect(result.items.count).to be(3) + expect(result.items.pluck(:name)).to contain_exactly('public', 'internal', 'z private test') + end end end end - context 'when the current user cannot read the namespace catalog' do - it 'returns empty response' do - expect(result).to be_empty + context 'when the user is anonymous' do + let_it_be(:user) { nil } + + it 'returns only public projects' do + expect(result.items.count).to be(1) + expect(result.items.pluck(:name)).to contain_exactly('public') end end end diff --git a/spec/graphql/resolvers/ci/catalog/versions_resolver_spec.rb b/spec/graphql/resolvers/ci/catalog/versions_resolver_spec.rb deleted file mode 100644 index 02fb3dfaee4..00000000000 --- a/spec/graphql/resolvers/ci/catalog/versions_resolver_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -# In this context, a `version` is equivalent to a `release` -RSpec.describe Resolvers::Ci::Catalog::VersionsResolver, feature_category: :pipeline_composition do - include GraphqlHelpers - - 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, :private) } - # rubocop: disable Layout/LineLength - let_it_be(:version1) { create(:release, project: project, tag: 'v1.0.0', released_at: yesterday, created_at: tomorrow) } - let_it_be(:version2) { create(:release, project: project, tag: 'v2.0.0', released_at: today, created_at: yesterday) } - let_it_be(:version3) { create(:release, project: project, tag: 'v3.0.0', released_at: tomorrow, created_at: today) } - # rubocop: enable Layout/LineLength - let_it_be(:developer) { create(:user) } - let_it_be(:public_user) { create(:user) } - - let(:args) { { sort: :released_at_desc } } - let(:all_releases) { [version1, version2, version3] } - - before_all do - project.add_developer(developer) - end - - describe '#resolve' do - it_behaves_like 'releases and group releases resolver' - - describe 'when order_by is created_at' do - let(:current_user) { developer } - - context 'with sort: desc' do - let(:args) { { sort: :created_desc } } - - it 'returns the releases ordered by created_at in descending order' do - expect(resolve_releases.to_a) - .to match_array(all_releases) - .and be_sorted(:created_at, :desc) - end - end - - context 'with sort: asc' do - let(:args) { { sort: :created_asc } } - - it 'returns the releases ordered by created_at in ascending order' do - expect(resolve_releases.to_a) - .to match_array(all_releases) - .and be_sorted(:created_at, :asc) - end - end - end - end - - private - - def resolve_versions - context = { current_user: current_user } - resolve(described_class, obj: project, args: args, ctx: context, arg_style: :internal) - end - - # Required for shared examples - alias_method :resolve_releases, :resolve_versions -end diff --git a/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb b/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb index e0fc3b96b93..d1eec0baeea 100644 --- a/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::GroupRunnersResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::GroupRunnersResolver, feature_category: :fleet_visibility do include GraphqlHelpers describe '#resolve' do diff --git a/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb b/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb index 9d9f0fee04a..85b55521174 100644 --- a/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::ProjectRunnersResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::ProjectRunnersResolver, feature_category: :fleet_visibility do include GraphqlHelpers describe '#resolve' do diff --git a/spec/graphql/resolvers/ci/runner_groups_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_groups_resolver_spec.rb index 9272689ef0b..f535f6e415d 100644 --- a/spec/graphql/resolvers/ci/runner_groups_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runner_groups_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::RunnerGroupsResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::RunnerGroupsResolver, feature_category: :fleet_visibility do include GraphqlHelpers let_it_be(:group1) { create(:group) } diff --git a/spec/graphql/resolvers/ci/runner_job_count_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_job_count_resolver_spec.rb index 6336ea883f7..18501d4add5 100644 --- a/spec/graphql/resolvers/ci/runner_job_count_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runner_job_count_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::RunnerJobCountResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::RunnerJobCountResolver, feature_category: :fleet_visibility do include GraphqlHelpers let_it_be(:project) { create(:project, :repository) } diff --git a/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb index 322bead0d3c..4af87b6882f 100644 --- a/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::RunnerJobsResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::RunnerJobsResolver, feature_category: :fleet_visibility do include GraphqlHelpers let_it_be(:project) { create(:project, :repository) } diff --git a/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb index da6a84cec44..e6238c41445 100644 --- a/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::RunnerPlatformsResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::RunnerPlatformsResolver, feature_category: :fleet_visibility do include GraphqlHelpers describe '#resolve' do diff --git a/spec/graphql/resolvers/ci/runner_projects_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_projects_resolver_spec.rb index 44203fb2912..c75d7fb831c 100644 --- a/spec/graphql/resolvers/ci/runner_projects_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runner_projects_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::RunnerProjectsResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::RunnerProjectsResolver, feature_category: :fleet_visibility do include GraphqlHelpers let_it_be(:project1) { create(:project, description: 'Project1.1') } diff --git a/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb index 734337f7c92..1724623e5c4 100644 --- a/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::RunnerSetupResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::RunnerSetupResolver, feature_category: :fleet_visibility do include GraphqlHelpers describe '#resolve' do diff --git a/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb index 97a10a7da33..d541bbddfe5 100644 --- a/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::RunnerStatusResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::RunnerStatusResolver, feature_category: :fleet_visibility do include GraphqlHelpers describe '#resolve' do diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb index 7d37d13366c..85a90924384 100644 --- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet do +RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :fleet_visibility do include GraphqlHelpers describe '#resolve' do diff --git a/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb b/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb index 48be1c29184..5f12e8649b7 100644 --- a/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb +++ b/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb @@ -114,14 +114,6 @@ RSpec.describe Resolvers::ContainerRepositoryTagsResolver, feature_category: :co expect(resolver(args)).is_a? Gitlab::Graphql::ExternallyPaginatedArray end - - context 'when feature use_repository_list_tags_on_graphql is disabled' do - before do - stub_feature_flags(use_repository_list_tags_on_graphql: false) - end - - it_behaves_like 'fetching via tags and filter in place' - end end context 'when Gitlab API is not supported' do diff --git a/spec/graphql/resolvers/group_milestones_resolver_spec.rb b/spec/graphql/resolvers/group_milestones_resolver_spec.rb index b9b8ef1870b..e9caf91ecb7 100644 --- a/spec/graphql/resolvers/group_milestones_resolver_spec.rb +++ b/spec/graphql/resolvers/group_milestones_resolver_spec.rb @@ -102,76 +102,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver, feature_category: :team_plann end end - context 'when including descendant milestones in a public group' do - let_it_be(:group) { create(:group, :public) } - - let(:args) { { include_descendants: true } } - - it 'finds milestones only in accessible projects and groups' do - accessible_group = create(:group, :private, parent: group) - accessible_project = create(:project, group: accessible_group) - accessible_group.add_developer(current_user) - inaccessible_group = create(:group, :private, parent: group) - inaccessible_project = create(:project, :private, group: group) - milestone1 = create(:milestone, group: group) - milestone2 = create(:milestone, group: accessible_group) - milestone3 = create(:milestone, project: accessible_project) - create(:milestone, group: inaccessible_group) - create(:milestone, project: inaccessible_project) - - expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3]) - end - end - - describe 'include_descendants and include_ancestors' do - let_it_be(:parent_group) { create(:group, :public) } - let_it_be(:group) { create(:group, :public, parent: parent_group) } - let_it_be(:accessible_group) { create(:group, :private, parent: group) } - let_it_be(:accessible_project) { create(:project, group: accessible_group) } - let_it_be(:inaccessible_group) { create(:group, :private, parent: group) } - let_it_be(:inaccessible_project) { create(:project, :private, group: group) } - let_it_be(:milestone1) { create(:milestone, group: group) } - let_it_be(:milestone2) { create(:milestone, group: accessible_group) } - let_it_be(:milestone3) { create(:milestone, project: accessible_project) } - let_it_be(:milestone4) { create(:milestone, group: inaccessible_group) } - let_it_be(:milestone5) { create(:milestone, project: inaccessible_project) } - let_it_be(:milestone6) { create(:milestone, group: parent_group) } - - before do - accessible_group.add_developer(current_user) - end - - context 'when including neither ancestor or descendant milestones in a public group' do - let(:args) { {} } - - it 'finds milestones only in accessible projects and groups' do - expect(resolve_group_milestones(args: args)).to match_array([milestone1]) - end - end - - context 'when including descendant milestones in a public group' do - let(:args) { { include_descendants: true } } - - it 'finds milestones only in accessible projects and groups' do - expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3]) - end - end - - context 'when including ancestor milestones in a public group' do - let(:args) { { include_ancestors: true } } - - it 'finds milestones only in accessible projects and groups' do - expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone6]) - end - end - - context 'when including both ancestor or descendant milestones in a public group' do - let(:args) { { include_descendants: true, include_ancestors: true } } - - it 'finds milestones only in accessible projects and groups' do - expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3, milestone6]) - end - end - end + # testing for include_descendants and include_ancestors moved into + # `spec/requests/api/graphql/milestone_spec.rb` end end diff --git a/spec/graphql/resolvers/group_resolver_spec.rb b/spec/graphql/resolvers/group_resolver_spec.rb index ed406d14772..c04961b4804 100644 --- a/spec/graphql/resolvers/group_resolver_spec.rb +++ b/spec/graphql/resolvers/group_resolver_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Resolvers::GroupResolver do it 'batch-resolves groups by full path' do paths = [group1.full_path, group2.full_path] - result = batch_sync(max_queries: 1) do + result = batch_sync(max_queries: 3) do paths.map { |path| resolve_group(path) } end diff --git a/spec/graphql/resolvers/kas/agent_connections_resolver_spec.rb b/spec/graphql/resolvers/kas/agent_connections_resolver_spec.rb index fe6509bcb3c..58333037e4c 100644 --- a/spec/graphql/resolvers/kas/agent_connections_resolver_spec.rb +++ b/spec/graphql/resolvers/kas/agent_connections_resolver_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Resolvers::Kas::AgentConnectionsResolver do let(:connection2) { double(agent_id: agent1.id) } let(:connection3) { double(agent_id: agent2.id) } let(:connected_agents) { [connection1, connection2, connection3] } - let(:kas_client) { instance_double(Gitlab::Kas::Client, get_connected_agents: connected_agents) } + let(:kas_client) { instance_double(Gitlab::Kas::Client, get_connected_agents_by_agent_ids: connected_agents) } subject do batch_sync do @@ -37,7 +37,7 @@ RSpec.describe Resolvers::Kas::AgentConnectionsResolver do end it 'queries KAS once when multiple agents are requested' do - expect(kas_client).to receive(:get_connected_agents).once + expect(kas_client).to receive(:get_connected_agents_by_agent_ids).once response = batch_sync do resolve(described_class, obj: agent1, ctx: ctx) @@ -49,7 +49,7 @@ RSpec.describe Resolvers::Kas::AgentConnectionsResolver do context 'an error is returned from the KAS client' do before do - allow(kas_client).to receive(:get_connected_agents).and_raise(GRPC::DeadlineExceeded) + allow(kas_client).to receive(:get_connected_agents_by_agent_ids).and_raise(GRPC::DeadlineExceeded) end it 'raises a graphql error' do diff --git a/spec/graphql/resolvers/ml/model_detail_resolver_spec.rb b/spec/graphql/resolvers/ml/model_detail_resolver_spec.rb new file mode 100644 index 00000000000..1da208eb4d8 --- /dev/null +++ b/spec/graphql/resolvers/ml/model_detail_resolver_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::Ml::ModelDetailResolver, feature_category: :mlops do + include GraphqlHelpers + + describe '#resolve' do + let_it_be(:project) { create(:project) } + let_it_be(:model) { create(:ml_models, project: project) } + let_it_be(:user) { project.owner } + + let(:args) { { id: global_id_of(model) } } + let(:read_model_registry) { true } + + before do + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?) + .with(user, :read_model_registry, project) + .and_return(read_model_registry) + end + + subject { force(resolve(described_class, ctx: { current_user: user }, args: args)) } + + context 'when user is allowed and model exists' do + it { is_expected.to eq(model) } + end + + context 'when user does not have permission' do + let(:read_model_registry) { false } + + it { is_expected.to be_nil } + end + + context 'when model does not exist' do + let(:args) { { id: global_id_of(id: non_existing_record_id, model_name: 'Ml::Model') } } + + it { is_expected.to be_nil } + end + end +end diff --git a/spec/graphql/resolvers/project_resolver_spec.rb b/spec/graphql/resolvers/project_resolver_spec.rb index dec9d4701e1..03febc75d3f 100644 --- a/spec/graphql/resolvers/project_resolver_spec.rb +++ b/spec/graphql/resolvers/project_resolver_spec.rb @@ -13,7 +13,7 @@ RSpec.describe Resolvers::ProjectResolver do it 'batch-resolves projects by full path' do paths = [project1.full_path, project2.full_path] - result = batch_sync(max_queries: 1) do + result = batch_sync(max_queries: 3) do paths.map { |path| resolve_project(path) } end diff --git a/spec/graphql/resolvers/timelog_resolver_spec.rb b/spec/graphql/resolvers/timelog_resolver_spec.rb index 798d8a56cf5..c4253f4b9bc 100644 --- a/spec/graphql/resolvers/timelog_resolver_spec.rb +++ b/spec/graphql/resolvers/timelog_resolver_spec.rb @@ -29,6 +29,14 @@ RSpec.describe Resolvers::TimelogResolver, feature_category: :team_planning do expect(timelogs).to contain_exactly(timelog1) end + context 'when the project does not exist' do + let(:extra_args) { { project_id: "gid://gitlab/Project/#{non_existing_record_id}" } } + + it 'returns an empty set' do + expect(timelogs).to be_empty + end + end + context 'when no dates specified' do let(:args) { {} } @@ -137,6 +145,20 @@ RSpec.describe Resolvers::TimelogResolver, feature_category: :team_planning do expect(timelogs).to contain_exactly(timelog1) end + context 'when the group does not exist' do + let_it_be(:error_class) { Gitlab::Graphql::Errors::ResourceNotAvailable } + + let(:extra_args) { { group_id: "gid://gitlab/Group/#{non_existing_record_id}" } } + + it 'returns an error' do + expect_graphql_error_to_be_created(error_class, + "The resource that you are attempting to access does not exist or " \ + "you don't have permission to perform this action") do + timelogs + end + end + end + context 'when only start_date is present' do let(:args) { { start_date: short_time_ago } } diff --git a/spec/graphql/types/analytics/cycle_analytics/value_stream_type_spec.rb b/spec/graphql/types/analytics/cycle_analytics/value_stream_type_spec.rb index 5e2638210d3..1d5a8dbebd6 100644 --- a/spec/graphql/types/analytics/cycle_analytics/value_stream_type_spec.rb +++ b/spec/graphql/types/analytics/cycle_analytics/value_stream_type_spec.rb @@ -7,5 +7,5 @@ RSpec.describe Types::Analytics::CycleAnalytics::ValueStreamType, feature_catego specify { expect(described_class).to require_graphql_authorizations(:read_cycle_analytics) } - specify { expect(described_class).to have_graphql_fields(:id, :name, :namespace, :project) } + specify { expect(described_class).to have_graphql_fields(:id, :name, :namespace, :project, :stages) } end diff --git a/spec/graphql/types/analytics/cycle_analytics/value_streams/stage_type_spec.rb b/spec/graphql/types/analytics/cycle_analytics/value_streams/stage_type_spec.rb new file mode 100644 index 00000000000..92276647e1b --- /dev/null +++ b/spec/graphql/types/analytics/cycle_analytics/value_streams/stage_type_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::Analytics::CycleAnalytics::ValueStreams::StageType, feature_category: :value_stream_management do + let(:fields) do + %i[ + name start_event_identifier + end_event_identifier hidden custom + ] + end + + specify { expect(described_class.graphql_name).to eq('ValueStreamStage') } + specify { expect(described_class).to have_graphql_fields(fields).at_least } +end diff --git a/spec/graphql/types/ci/catalog/resource_type_spec.rb b/spec/graphql/types/ci/catalog/resource_type_spec.rb index 5f5732c5237..7e15efca644 100644 --- a/spec/graphql/types/ci/catalog/resource_type_spec.rb +++ b/spec/graphql/types/ci/catalog/resource_type_spec.rb @@ -16,8 +16,6 @@ RSpec.describe Types::Ci::Catalog::ResourceType, feature_category: :pipeline_com latest_version latest_released_at star_count - forks_count - root_namespace readme_html open_issues_count open_merge_requests_count diff --git a/spec/graphql/types/ci/catalog/resources/component_type_spec.rb b/spec/graphql/types/ci/catalog/resources/component_type_spec.rb new file mode 100644 index 00000000000..93ab926d406 --- /dev/null +++ b/spec/graphql/types/ci/catalog/resources/component_type_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::Ci::Catalog::Resources::ComponentType, feature_category: :pipeline_composition do + specify { expect(described_class.graphql_name).to eq('CiCatalogResourceComponent') } + + it 'exposes the expected fields' do + expected_fields = %i[ + id + inputs + name + path + ] + + expect(described_class).to have_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/ci/catalog/resources/components/input_type_spec.rb b/spec/graphql/types/ci/catalog/resources/components/input_type_spec.rb new file mode 100644 index 00000000000..cb716cfff8c --- /dev/null +++ b/spec/graphql/types/ci/catalog/resources/components/input_type_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::Ci::Catalog::Resources::Components::InputType, feature_category: :pipeline_composition do + specify { expect(described_class.graphql_name).to eq('CiCatalogResourceComponentInput') } + + it 'exposes the expected fields' do + expected_fields = %i[ + name + default + required + ] + + expect(described_class).to have_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/ci/catalog/resources/version_sort_enum_spec.rb b/spec/graphql/types/ci/catalog/resources/version_sort_enum_spec.rb new file mode 100644 index 00000000000..fd0f1a1e553 --- /dev/null +++ b/spec/graphql/types/ci/catalog/resources/version_sort_enum_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['CiCatalogResourceVersionSort'], feature_category: :pipeline_composition do + it { expect(described_class.graphql_name).to eq('CiCatalogResourceVersionSort') } + + it 'exposes all the existing catalog resource version sort options' do + expect(described_class.values.keys).to include( + *%w[RELEASED_AT_ASC RELEASED_AT_DESC CREATED_ASC CREATED_DESC] + ) + end +end diff --git a/spec/graphql/types/ci/catalog/resources/version_type_spec.rb b/spec/graphql/types/ci/catalog/resources/version_type_spec.rb new file mode 100644 index 00000000000..088973cf8f7 --- /dev/null +++ b/spec/graphql/types/ci/catalog/resources/version_type_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::Ci::Catalog::Resources::VersionType, feature_category: :pipeline_composition do + specify { expect(described_class.graphql_name).to eq('CiCatalogResourceVersion') } + + it 'exposes the expected fields' do + expected_fields = %i[ + id + created_at + released_at + tag_name + tag_path + author + commit + components + ] + + expect(described_class).to have_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/ci/job_base_field_spec.rb b/spec/graphql/types/ci/job_base_field_spec.rb index ec7d2a7d33a..c2bf73526d2 100644 --- a/spec/graphql/types/ci/job_base_field_spec.rb +++ b/spec/graphql/types/ci/job_base_field_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Types::Ci::JobBaseField, feature_category: :runner_fleet do +RSpec.describe Types::Ci::JobBaseField, feature_category: :fleet_visibility do describe 'authorized?' do let_it_be(:current_user) { create(:user) } diff --git a/spec/graphql/types/ci/runner_countable_connection_type_spec.rb b/spec/graphql/types/ci/runner_countable_connection_type_spec.rb index 49254ed0f93..9f24909e110 100644 --- a/spec/graphql/types/ci/runner_countable_connection_type_spec.rb +++ b/spec/graphql/types/ci/runner_countable_connection_type_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Types::Ci::RunnerCountableConnectionType, feature_category: :runner_fleet do +RSpec.describe Types::Ci::RunnerCountableConnectionType, feature_category: :fleet_visibility do it 'contains attributes related to a runner connection' do expected_fields = %w[count] diff --git a/spec/graphql/types/ci/runner_manager_type_spec.rb b/spec/graphql/types/ci/runner_manager_type_spec.rb index ff7297b0a0e..ce55d6fee03 100644 --- a/spec/graphql/types/ci/runner_manager_type_spec.rb +++ b/spec/graphql/types/ci/runner_manager_type_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GitlabSchema.types['CiRunnerManager'], feature_category: :runner_fleet do +RSpec.describe GitlabSchema.types['CiRunnerManager'], feature_category: :fleet_visibility do specify { expect(described_class.graphql_name).to eq('CiRunnerManager') } specify { expect(described_class).to require_graphql_authorizations(:read_runner_manager) } diff --git a/spec/graphql/types/ci/runner_platform_type_spec.rb b/spec/graphql/types/ci/runner_platform_type_spec.rb index 1b0f5a5ec71..f4acfc1f8ca 100644 --- a/spec/graphql/types/ci/runner_platform_type_spec.rb +++ b/spec/graphql/types/ci/runner_platform_type_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Types::Ci::RunnerPlatformType, feature_category: :runner_fleet do +RSpec.describe Types::Ci::RunnerPlatformType, feature_category: :fleet_visibility do specify { expect(described_class.graphql_name).to eq('RunnerPlatform') } it 'exposes the expected fields' do diff --git a/spec/graphql/types/ci/runner_setup_type_spec.rb b/spec/graphql/types/ci/runner_setup_type_spec.rb index d3e47b52a80..66469a35a94 100644 --- a/spec/graphql/types/ci/runner_setup_type_spec.rb +++ b/spec/graphql/types/ci/runner_setup_type_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Types::Ci::RunnerSetupType, feature_category: :runner_fleet do +RSpec.describe Types::Ci::RunnerSetupType, feature_category: :fleet_visibility do specify { expect(described_class.graphql_name).to eq('RunnerSetup') } it 'exposes the expected fields' do diff --git a/spec/graphql/types/ci/runner_upgrade_status_enum_spec.rb b/spec/graphql/types/ci/runner_upgrade_status_enum_spec.rb index 4aa9ad094a6..3f6a867de39 100644 --- a/spec/graphql/types/ci/runner_upgrade_status_enum_spec.rb +++ b/spec/graphql/types/ci/runner_upgrade_status_enum_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Types::Ci::RunnerUpgradeStatusEnum, feature_category: :runner_fleet do +RSpec.describe Types::Ci::RunnerUpgradeStatusEnum, feature_category: :fleet_visibility do let(:model_only_enum_values) { %w[not_processed] } let(:expected_graphql_source_values) do Ci::RunnerVersion.statuses.keys - model_only_enum_values diff --git a/spec/graphql/types/ci/runner_web_url_edge_spec.rb b/spec/graphql/types/ci/runner_web_url_edge_spec.rb index 07a9655b3e1..fc4e5428360 100644 --- a/spec/graphql/types/ci/runner_web_url_edge_spec.rb +++ b/spec/graphql/types/ci/runner_web_url_edge_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Types::Ci::RunnerWebUrlEdge, feature_category: :runner_fleet do +RSpec.describe Types::Ci::RunnerWebUrlEdge, feature_category: :fleet_visibility do specify { expect(described_class.graphql_name).to eq('RunnerWebUrlEdge') } it 'contains URL attributes' do diff --git a/spec/graphql/types/container_registry/protection/rule_type_spec.rb b/spec/graphql/types/container_registry/protection/rule_type_spec.rb index 58b53af80fb..40a45609345 100644 --- a/spec/graphql/types/container_registry/protection/rule_type_spec.rb +++ b/spec/graphql/types/container_registry/protection/rule_type_spec.rb @@ -15,8 +15,8 @@ RSpec.describe GitlabSchema.types['ContainerRegistryProtectionRule'], feature_ca it { is_expected.to have_non_null_graphql_type(::Types::GlobalIDType[::ContainerRegistry::Protection::Rule]) } end - describe 'container_path_pattern' do - subject { described_class.fields['containerPathPattern'] } + describe 'repository_path_pattern' do + subject { described_class.fields['repositoryPathPattern'] } it { is_expected.to have_non_null_graphql_type(GraphQL::Types::String) } end diff --git a/spec/graphql/types/container_repository_details_type_spec.rb b/spec/graphql/types/container_repository_details_type_spec.rb index 62e72089e09..2253b07f5c8 100644 --- a/spec/graphql/types/container_repository_details_type_spec.rb +++ b/spec/graphql/types/container_repository_details_type_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['ContainerRepositoryDetails'] do fields = %i[id name path location created_at updated_at expiration_policy_started_at status tags_count can_delete expiration_policy_cleanup_status tags size - project migration_state last_cleanup_deleted_tags_count] + project migration_state last_cleanup_deleted_tags_count userPermissions] it { expect(described_class.graphql_name).to eq('ContainerRepositoryDetails') } diff --git a/spec/graphql/types/container_repository_tag_type_spec.rb b/spec/graphql/types/container_repository_tag_type_spec.rb index 1d1a76d6916..596a221b5c0 100644 --- a/spec/graphql/types/container_repository_tag_type_spec.rb +++ b/spec/graphql/types/container_repository_tag_type_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' -RSpec.describe GitlabSchema.types['ContainerRepositoryTag'] do - fields = %i[name path location digest revision short_revision total_size created_at can_delete] +RSpec.describe GitlabSchema.types['ContainerRepositoryTag'], feature_category: :container_registry do + fields = %i[name path location digest revision short_revision total_size created_at can_delete user_permissions] it { expect(described_class.graphql_name).to eq('ContainerRepositoryTag') } @@ -12,4 +12,6 @@ RSpec.describe GitlabSchema.types['ContainerRepositoryTag'] do it { expect(described_class).to require_graphql_authorizations(:read_container_image) } it { expect(described_class).to have_graphql_fields(fields) } + + it { expect(described_class).to expose_permissions_using(Types::PermissionTypes::ContainerRepositoryTag) } end diff --git a/spec/graphql/types/container_repository_type_spec.rb b/spec/graphql/types/container_repository_type_spec.rb index bc92fa24050..0c7879c3f2a 100644 --- a/spec/graphql/types/container_repository_type_spec.rb +++ b/spec/graphql/types/container_repository_type_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' -RSpec.describe GitlabSchema.types['ContainerRepository'] do +RSpec.describe GitlabSchema.types['ContainerRepository'], feature_category: :container_registry do fields = %i[id name path location created_at updated_at expiration_policy_started_at status tags_count can_delete expiration_policy_cleanup_status project - migration_state last_cleanup_deleted_tags_count] + migration_state last_cleanup_deleted_tags_count user_permissions] it { expect(described_class.graphql_name).to eq('ContainerRepository') } @@ -15,6 +15,8 @@ RSpec.describe GitlabSchema.types['ContainerRepository'] do it { expect(described_class).to have_graphql_fields(fields) } + it { expect(described_class).to expose_permissions_using(Types::PermissionTypes::ContainerRepository) } + describe 'status field' do subject { described_class.fields['status'] } diff --git a/spec/graphql/types/current_user_type_spec.rb b/spec/graphql/types/current_user_type_spec.rb new file mode 100644 index 00000000000..ff7a529a057 --- /dev/null +++ b/spec/graphql/types/current_user_type_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['CurrentUser'], feature_category: :user_profile do + specify { expect(described_class.graphql_name).to eq('CurrentUser') } + + it "inherits authorization policies from the UserType superclass" do + expect(described_class).to require_graphql_authorizations(:read_user) + end +end diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb index 6622551f063..d3f9053faf3 100644 --- a/spec/graphql/types/group_type_spec.rb +++ b/spec/graphql/types/group_type_spec.rb @@ -125,4 +125,37 @@ RSpec.describe GitlabSchema.types['Group'] do expect { clean_state_query }.not_to exceed_all_query_limit(control) end end + + describe 'custom emoji' do + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } + let_it_be(:subgroup) { create(:group, parent: group) } + let_it_be(:custom_emoji) { create(:custom_emoji, group: group) } + let_it_be(:custom_emoji_subgroup) { create(:custom_emoji, group: subgroup) } + let(:query) do + %( + query { + group(fullPath: "#{subgroup.full_path}") { + customEmoji(includeAncestorGroups: true) { + nodes { + id + } + } + } + } + ) + end + + before_all do + group.add_reporter(user) + end + + describe 'when includeAncestorGroups is true' do + it 'returns emoji from ancestor groups' do + result = GitlabSchema.execute(query, context: { current_user: user }).as_json + + expect(result.dig('data', 'group', 'customEmoji', 'nodes').count).to eq(2) + end + end + end end diff --git a/spec/graphql/types/issue_type_enum_spec.rb b/spec/graphql/types/issue_type_enum_spec.rb index 5b1bc9c3d9c..f0370e275cd 100644 --- a/spec/graphql/types/issue_type_enum_spec.rb +++ b/spec/graphql/types/issue_type_enum_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Types::IssueTypeEnum, feature_category: :team_planning do it 'exposes all the existing issue type values except epic' do expect(described_class.values.keys).to match_array( - %w[ISSUE INCIDENT TEST_CASE REQUIREMENT TASK OBJECTIVE KEY_RESULT] + %w[ISSUE INCIDENT TEST_CASE REQUIREMENT TASK OBJECTIVE KEY_RESULT EPIC] ) end end diff --git a/spec/graphql/types/ml/candidate_links_type_spec.rb b/spec/graphql/types/ml/candidate_links_type_spec.rb new file mode 100644 index 00000000000..489079cc717 --- /dev/null +++ b/spec/graphql/types/ml/candidate_links_type_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['MLCandidateLinks'], feature_category: :mlops do + it 'has the expected fields' do + expected_fields = %w[showPath artifact_path] + + expect(described_class).to include_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/ml/candidate_type_spec.rb b/spec/graphql/types/ml/candidate_type_spec.rb new file mode 100644 index 00000000000..e000ada1309 --- /dev/null +++ b/spec/graphql/types/ml/candidate_type_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['MlCandidate'], feature_category: :mlops do + specify { expect(described_class.description).to eq('Candidate for a model version in the model registry') } + + it 'includes all the package fields' do + expected_fields = %w[id name created_at _links] + + expect(described_class).to include_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/ml/model_type_spec.rb b/spec/graphql/types/ml/model_type_spec.rb new file mode 100644 index 00000000000..ee0473ccafe --- /dev/null +++ b/spec/graphql/types/ml/model_type_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['MlModel'], feature_category: :mlops do + specify { expect(described_class.description).to eq('Machine learning model in the model registry') } + + it 'includes all the package fields' do + expected_fields = %w[id name versions candidates] + + expect(described_class).to include_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/ml/model_version_links_type_spec.rb b/spec/graphql/types/ml/model_version_links_type_spec.rb new file mode 100644 index 00000000000..d2a11643c35 --- /dev/null +++ b/spec/graphql/types/ml/model_version_links_type_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['MLModelVersionLinks'], feature_category: :mlops do + it 'has the expected fields' do + expected_fields = %w[showPath] + + expect(described_class).to include_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/ml/model_version_type_spec.rb b/spec/graphql/types/ml/model_version_type_spec.rb new file mode 100644 index 00000000000..03652c55e20 --- /dev/null +++ b/spec/graphql/types/ml/model_version_type_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['MlModelVersion'], feature_category: :mlops do + specify { expect(described_class.description).to eq('Version of a machine learning model') } + + it 'includes all the package fields' do + expected_fields = %w[id version created_at _links] + + expect(described_class).to include_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/namespace/package_settings_type_spec.rb b/spec/graphql/types/namespace/package_settings_type_spec.rb index d823f2017b6..0e731c1e2bf 100644 --- a/spec/graphql/types/namespace/package_settings_type_spec.rb +++ b/spec/graphql/types/namespace/package_settings_type_spec.rb @@ -32,6 +32,7 @@ RSpec.describe GitlabSchema.types['PackageSettings'], feature_category: :package maven_package_requests_forwarding_locked npm_package_requests_forwarding_locked pypi_package_requests_forwarding_locked + nuget_symbol_server_enabled ] expect(described_class).to include_graphql_fields(*expected_fields) diff --git a/spec/graphql/types/organizations/organization_type_spec.rb b/spec/graphql/types/organizations/organization_type_spec.rb index 62787ad220d..6bc4bac6ba2 100644 --- a/spec/graphql/types/organizations/organization_type_spec.rb +++ b/spec/graphql/types/organizations/organization_type_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['Organization'], feature_category: :cell do - let(:expected_fields) { %w[groups id name organization_users path web_url] } + let(:expected_fields) { %w[avatar_url description description_html groups id name organization_users path web_url] } specify { expect(described_class.graphql_name).to eq('Organization') } specify { expect(described_class).to require_graphql_authorizations(:read_organization) } diff --git a/spec/graphql/types/permission_types/abuse_report_spec.rb b/spec/graphql/types/permission_types/abuse_report_spec.rb deleted file mode 100644 index 399df137a78..00000000000 --- a/spec/graphql/types/permission_types/abuse_report_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Types::PermissionTypes::AbuseReport, feature_category: :insider_threat do - it do - expected_permissions = [ - :read_abuse_report, :create_note - ] - - expected_permissions.each do |permission| - expect(described_class).to have_graphql_field(permission) - end - end -end diff --git a/spec/graphql/types/permission_types/container_repository_spec.rb b/spec/graphql/types/permission_types/container_repository_spec.rb new file mode 100644 index 00000000000..1d8d9e994ed --- /dev/null +++ b/spec/graphql/types/permission_types/container_repository_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['ContainerRepositoryPermissions'], feature_category: :container_registry do + it 'has the expected fields' do + expected_permissions = [:destroy_container_repository] + + expect(described_class).to have_graphql_fields(expected_permissions).only + end +end diff --git a/spec/graphql/types/permission_types/container_repository_tag_spec.rb b/spec/graphql/types/permission_types/container_repository_tag_spec.rb new file mode 100644 index 00000000000..69d60ba621b --- /dev/null +++ b/spec/graphql/types/permission_types/container_repository_tag_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['ContainerRepositoryTagPermissions'], feature_category: :container_registry do + it 'has the expected fields' do + expected_permissions = [:destroy_container_repository_tag] + + expect(described_class).to have_graphql_fields(expected_permissions).only + end +end diff --git a/spec/graphql/types/project_feature_access_level_enum_spec.rb b/spec/graphql/types/project_feature_access_level_enum_spec.rb new file mode 100644 index 00000000000..a13b3be3f8f --- /dev/null +++ b/spec/graphql/types/project_feature_access_level_enum_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['ProjectFeatureAccessLevel'], feature_category: :groups_and_projects do + specify { expect(described_class.graphql_name).to eq('ProjectFeatureAccessLevel') } + + it 'exposes all the existing access levels' do + expect(described_class.values.keys).to include(*%w[DISABLED PRIVATE ENABLED]) + end +end diff --git a/spec/graphql/types/project_feature_access_level_type_spec.rb b/spec/graphql/types/project_feature_access_level_type_spec.rb new file mode 100644 index 00000000000..fae9de63d93 --- /dev/null +++ b/spec/graphql/types/project_feature_access_level_type_spec.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['ProjectFeatureAccess'], feature_category: :groups_and_projects do + specify { expect(described_class.graphql_name).to eq('ProjectFeatureAccess') } + specify { expect(described_class).to require_graphql_authorizations(nil) } + + it 'has expected fields' do + expected_fields = [:integer_value, :string_value] + + expect(described_class).to have_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index 7b4bcf4b1b0..3965312316b 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -2,9 +2,10 @@ require 'spec_helper' -RSpec.describe GitlabSchema.types['Project'] do +RSpec.describe GitlabSchema.types['Project'], feature_category: :groups_and_projects do include GraphqlHelpers include ProjectForksHelper + using RSpec::Parameterized::TableSyntax specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Project) } @@ -21,7 +22,8 @@ RSpec.describe GitlabSchema.types['Project'] do container_registry_enabled shared_runners_enabled lfs_enabled merge_requests_ff_only_enabled avatar_url issues_enabled merge_requests_enabled wiki_enabled - snippets_enabled jobs_enabled public_jobs open_issues_count import_status + forking_access_level issues_access_level merge_requests_access_level + snippets_enabled jobs_enabled public_jobs open_issues_count open_merge_requests_count import_status only_allow_merge_if_pipeline_succeeds request_access_enabled only_allow_merge_if_all_discussions_are_resolved printing_merge_request_link_enabled namespace group statistics statistics_details_paths repository merge_requests merge_request issues @@ -39,7 +41,7 @@ RSpec.describe GitlabSchema.types['Project'] do recent_issue_boards ci_config_path_or_default packages_cleanup_policy ci_variables timelog_categories fork_targets branch_rules ci_config_variables pipeline_schedules languages incident_management_timeline_event_tags visible_forks inherited_ci_variables autocomplete_users - ci_cd_settings detailed_import_status + ci_cd_settings detailed_import_status value_streams ] expect(described_class).to include_graphql_fields(*expected_fields) @@ -704,6 +706,63 @@ RSpec.describe GitlabSchema.types['Project'] do end end + describe 'project features access level' do + let_it_be(:project) { create(:project, :public) } + + where(project_feature: %w[forkingAccessLevel issuesAccessLevel mergeRequestsAccessLevel]) + + with_them do + let(:query) do + %( + query { + project(fullPath: "#{project.full_path}") { + #{project_feature} { + integerValue + stringValue + } + } + } + ) + end + + subject { GitlabSchema.execute(query).as_json.dig('data', 'project', project_feature) } + + it { is_expected.to eq({ "integerValue" => ProjectFeature::ENABLED, "stringValue" => "ENABLED" }) } + end + end + + describe 'open_merge_requests_count' do + let_it_be(:project, reload: true) { create(:project, :public) } + let_it_be(:open_merge_request) { create(:merge_request, source_project: project) } + let_it_be(:closed_merge_request) { create(:merge_request, :closed, source_project: project) } + + let(:query) do + %( + query { + project(fullPath: "#{project.full_path}") { + openMergeRequestsCount + } + } + ) + end + + subject(:open_merge_requests_count) do + GitlabSchema.execute(query).as_json.dig('data', 'project', 'openMergeRequestsCount') + end + + context 'when the user can access merge requests' do + it { is_expected.to eq(1) } + end + + context 'when the user cannot access merge requests' do + before do + project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE) + end + + it { is_expected.to be_nil } + end + end + describe 'branch_rules' do let_it_be(:user) { create(:user) } let_it_be(:project, reload: true) { create(:project, :public) } diff --git a/spec/graphql/types/projects/service_type_enum_spec.rb b/spec/graphql/types/projects/service_type_enum_spec.rb index a5b1ba24a44..40376afc7f7 100644 --- a/spec/graphql/types/projects/service_type_enum_spec.rb +++ b/spec/graphql/types/projects/service_type_enum_spec.rb @@ -38,7 +38,6 @@ RSpec.describe GitlabSchema.types['ServiceType'] do PUMBLE_SERVICE PUSHOVER_SERVICE REDMINE_SERVICE - SHIMO_SERVICE SLACK_SERVICE SLACK_SLASH_COMMANDS_SERVICE TEAMCITY_SERVICE diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb index 8bda738751d..0b5739be9a1 100644 --- a/spec/graphql/types/query_type_spec.rb +++ b/spec/graphql/types/query_type_spec.rb @@ -13,6 +13,14 @@ RSpec.describe GitlabSchema.types['Query'], feature_category: :shared do expect(described_class).to have_graphql_fields(*expected_foss_fields).at_least end + describe 'current_user field' do + subject { described_class.fields['currentUser'] } + + it 'returns current user' do + is_expected.to have_graphql_type(Types::CurrentUserType) + end + end + describe 'namespace field' do subject { described_class.fields['namespace'] } @@ -137,4 +145,14 @@ RSpec.describe GitlabSchema.types['Query'], feature_category: :shared do is_expected.to have_graphql_resolver(Resolvers::BoardListResolver) end end + + describe 'mlModel field' do + subject { described_class.fields['mlModel'] } + + it 'returns metadata', :aggregate_failures do + is_expected.to have_graphql_type(Types::Ml::ModelType) + is_expected.to have_graphql_arguments(:id) + is_expected.to have_graphql_resolver(Resolvers::Ml::ModelDetailResolver) + end + end end diff --git a/spec/graphql/types/root_storage_statistics_type_spec.rb b/spec/graphql/types/root_storage_statistics_type_spec.rb index 00f4092baf4..8ac3b32948f 100644 --- a/spec/graphql/types/root_storage_statistics_type_spec.rb +++ b/spec/graphql/types/root_storage_statistics_type_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GitlabSchema.types['RootStorageStatistics'] do +RSpec.describe GitlabSchema.types['RootStorageStatistics'], feature_category: :consumables_cost_management do specify { expect(described_class.graphql_name).to eq('RootStorageStatistics') } it 'has the expected fields' do diff --git a/spec/graphql/types/user_preferences_type_spec.rb b/spec/graphql/types/user_preferences_type_spec.rb index 06749dda239..87fac17a5ba 100644 --- a/spec/graphql/types/user_preferences_type_spec.rb +++ b/spec/graphql/types/user_preferences_type_spec.rb @@ -9,6 +9,7 @@ RSpec.describe Types::UserPreferencesType, feature_category: :user_profile do expected_fields = %i[ issues_sort visibility_pipeline_id_type + use_web_ide_extension_marketplace ] expect(described_class).to have_graphql_fields(*expected_fields) diff --git a/spec/graphql/types/work_item_state_counts_type_spec.rb b/spec/graphql/types/work_item_state_counts_type_spec.rb new file mode 100644 index 00000000000..bab2e124222 --- /dev/null +++ b/spec/graphql/types/work_item_state_counts_type_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['WorkItemStateCountsType'], feature_category: :portfolio_management do + specify { expect(described_class.graphql_name).to eq('WorkItemStateCountsType') } + + it 'exposes the expected fields' do + expected_fields = %i[all opened closed] + expect(described_class).to have_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/work_items/widget_definition_interface_spec.rb b/spec/graphql/types/work_items/widget_definition_interface_spec.rb new file mode 100644 index 00000000000..59320a75eba --- /dev/null +++ b/spec/graphql/types/work_items/widget_definition_interface_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::WorkItems::WidgetDefinitionInterface, feature_category: :team_planning do + it 'exposes the expected fields' do + expected_fields = %i[ + type + ] + + expect(described_class).to have_graphql_fields(*expected_fields) + end + + describe '.resolve_type' do + subject { described_class.resolve_type(object, {}) } + + context 'for assignees widget' do + let(:object) { WorkItems::Widgets::Assignees } + + it { is_expected.to eq(Types::WorkItems::WidgetDefinitions::AssigneesType) } + end + + context 'for hierarchy widget' do + let(:object) { WorkItems::Widgets::Hierarchy } + + it { is_expected.to eq(Types::WorkItems::WidgetDefinitions::HierarchyType) } + end + + context 'for other widgets' do + let(:object) { WorkItems::Widgets::Description } + + it { is_expected.to eq(Types::WorkItems::WidgetDefinitions::GenericType) } + end + end +end diff --git a/spec/graphql/types/work_items/widget_definitions/assignees_type_spec.rb b/spec/graphql/types/work_items/widget_definitions/assignees_type_spec.rb new file mode 100644 index 00000000000..3a1feee960c --- /dev/null +++ b/spec/graphql/types/work_items/widget_definitions/assignees_type_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::WorkItems::WidgetDefinitions::AssigneesType, feature_category: :team_planning do + it 'exposes the expected fields' do + expected_fields = %i[type can_invite_members] + + expected_fields.each do |field| + expect(described_class).to have_graphql_field(field) + end + end +end diff --git a/spec/graphql/types/work_items/widget_definitions/generic_type_spec.rb b/spec/graphql/types/work_items/widget_definitions/generic_type_spec.rb new file mode 100644 index 00000000000..19e962e71fd --- /dev/null +++ b/spec/graphql/types/work_items/widget_definitions/generic_type_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::WorkItems::WidgetDefinitions::GenericType, feature_category: :team_planning do + it 'exposes the expected fields' do + expected_fields = %i[type] + + expect(described_class).to have_graphql_fields(*expected_fields) + end +end |