diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb index d6d7eddf25533ef64060c8fe6464f4ed52aaff46..0c618aa55a6fbed754576eb654ea0abd23560d5e 100644 --- a/app/graphql/resolvers/projects_resolver.rb +++ b/app/graphql/resolvers/projects_resolver.rb @@ -23,6 +23,10 @@ class ProjectsResolver < BaseResolver required: false, description: "Return only projects with merge requests enabled." + argument :archived, ::Types::Projects::ArchivedEnum, + required: false, + description: 'Filter projects by archived status.' + def resolve_with_lookahead(**args) validate_args!(args) @@ -64,7 +68,8 @@ def finder_params(args) **project_finder_params(args), with_issues_enabled: args[:with_issues_enabled], with_merge_requests_enabled: args[:with_merge_requests_enabled], - full_paths: args[:full_paths] + full_paths: args[:full_paths], + archived: args[:archived] } end diff --git a/app/graphql/types/projects/archived_enum.rb b/app/graphql/types/projects/archived_enum.rb new file mode 100644 index 0000000000000000000000000000000000000000..774f008466ec9fead1ee99ab9b36c58cc10395fa --- /dev/null +++ b/app/graphql/types/projects/archived_enum.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Types + module Projects + class ArchivedEnum < BaseEnum + graphql_name 'ProjectArchived' + description 'Values for the archived argument' + + value 'ONLY', 'Only archived projects.', value: 'only' + value 'INCLUDE', 'Include archvied projects.', value: true + value 'EXCLUDE', 'Exclude archived projects.', value: false + end + end +end diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 8ce3026624ba8a18f7d954998fb2ee64890c18a3..973a4dbdfcf6f79b408676a9a033479b69b7c0cf 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -909,6 +909,7 @@ four standard [pagination arguments](#pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | | `aimedForDeletion` | [`Boolean`](#boolean) | Return only projects marked for deletion. | +| `archived` | [`ProjectArchived`](#projectarchived) | Filter projects by archived status. | | `fullPaths` | [`[String!]`](#string) | Filter projects by full paths. You cannot provide more than 50 full paths. | | `ids` | [`[ID!]`](#id) | Filter projects by IDs. | | `includeHidden` | [`Boolean`](#boolean) | Include hidden projects. | @@ -27596,6 +27597,7 @@ four standard [pagination arguments](#pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | | `aimedForDeletion` | [`Boolean`](#boolean) | Return only projects marked for deletion. | +| `archived` | [`ProjectArchived`](#projectarchived) | Filter projects by archived status. | | `fullPaths` | [`[String!]`](#string) | Filter projects by full paths. You cannot provide more than 50 full paths. | | `ids` | [`[ID!]`](#id) | Filter projects by IDs. | | `includeHidden` | [`Boolean`](#boolean) | Include hidden projects. | @@ -36816,6 +36818,16 @@ Current state of the product analytics stack. | `LOADING_INSTANCE` | Stack is currently initializing. | | `WAITING_FOR_EVENTS` | Stack is waiting for events from users. | +### `ProjectArchived` + +Values for the archived argument. + +| Value | Description | +| ----- | ----------- | +| `EXCLUDE` | Exclude archived projects. | +| `INCLUDE` | Include archvied projects. | +| `ONLY` | Only archived projects. | + ### `ProjectFeatureAccessLevel` Access level of a project feature. diff --git a/spec/requests/api/graphql/projects/projects_spec.rb b/spec/requests/api/graphql/projects/projects_spec.rb index 9dcf4020ed063df81914d4a86666df83740935a1..78acb5e9dc504be07d4c6c653804f2b720fc3934 100644 --- a/spec/requests/api/graphql/projects/projects_spec.rb +++ b/spec/requests/api/graphql/projects/projects_spec.rb @@ -9,6 +9,7 @@ let_it_be(:group) { create(:group, name: 'public-group', developers: current_user) } let_it_be(:projects) { create_list(:project, 5, :public, group: group) } let_it_be(:other_project) { create(:project, :public, group: group) } + let_it_be(:archived_project) { create(:project, :archived, group: group) } let(:filters) { {} } @@ -20,6 +21,46 @@ ) end + context 'when archived argument is ONLY' do + let(:filters) { { archived: :ONLY } } + + it 'returns only archived projects' do + post_graphql(query, current_user: current_user) + + expect(graphql_data_at(:projects, :nodes)) + .to contain_exactly(a_graphql_entity_for(archived_project)) + end + end + + context 'when archived argument is INCLUDE' do + let(:filters) { { archived: :INCLUDE } } + + it 'returns archived and non-archived projects' do + post_graphql(query, current_user: current_user) + + expect(graphql_data_at(:projects, :nodes)) + .to contain_exactly( + *projects.map { |project| a_graphql_entity_for(project) }, + a_graphql_entity_for(other_project), + a_graphql_entity_for(archived_project) + ) + end + end + + context 'when archived argument is EXCLUDE' do + let(:filters) { { archived: :EXCLUDE } } + + it 'returns only non-archived projects' do + post_graphql(query, current_user: current_user) + + expect(graphql_data_at(:projects, :nodes)) + .to contain_exactly( + *projects.map { |project| a_graphql_entity_for(project) }, + a_graphql_entity_for(other_project) + ) + end + end + context 'when providing full_paths filter' do let(:project_full_paths) { projects.map(&:full_path) } let(:filters) { { full_paths: project_full_paths } }