Commit 4b40a5da authored by Mario Celi's avatar Mario Celi

Add missing iteration filter for issues

- Add wildcard iteration filter for IssueResolver
- Add negated wildcard iteration filter for issue resolver
- Add negated iteration filter (Array) for IssueResolver
parent c4ab6953
......@@ -8224,6 +8224,14 @@ Values for sorting projects.
| `SIMILARITY` | Most similar to the search query. |
| `STORAGE` | Sort by storage size. |
### `NegatedIterationWildcardId`
Negated Iteration ID wildcard values.
| Value | Description |
| ----- | ----------- |
| `CURRENT` | Current iteration. |
### `OncallRotationUnitEnum`
Rotation length unit of an on-call rotation.
......
......@@ -110,8 +110,10 @@ module EE
if not_params.filter_by_current_iteration?
items.not_in_iterations(get_current_iteration)
else
elsif not_params.filter_by_iteration_title?
items.without_iteration_title(not_params[:iteration_title])
else
items.not_in_iterations(not_params[:iteration_id])
end
end
......
......@@ -10,6 +10,9 @@ module EE
argument :iteration_id, [::GraphQL::ID_TYPE, null: true],
required: false,
description: 'List of iteration Global IDs applied to the issue.'
argument :iteration_wildcard_id, ::Types::IterationWildcardIdEnum,
required: false,
description: 'Filter by iteration ID wildcard.'
argument :epic_id, GraphQL::STRING_TYPE,
required: false,
description: 'ID of an epic associated with the issues, "none" and "any" values are supported.'
......@@ -21,6 +24,17 @@ module EE
override :resolve_with_lookahead
def resolve_with_lookahead(**args)
args[:iteration_id] = iteration_ids_from_args(args) if args[:iteration_id].present?
args[:not][:iteration_id] = iteration_ids_from_args(args[:not]) if args.dig(:not, :iteration_id).present?
prepare_iteration_wildcard_params(args)
super
end
def ready?(**args)
if iteration_params_not_mutaully_exclusive?(args) || iteration_params_not_mutaully_exclusive?(args.fetch(:not, {}))
arg_str = mutually_exclusive_iteration_args.map { |x| x.to_s.camelize(:lower) }.join(', ')
raise ::Gitlab::Graphql::Errors::ArgumentError, "only one of [#{arg_str}] arguments is allowed at the same time."
end
super
end
......@@ -37,6 +51,19 @@ module EE
end
end
def prepare_iteration_wildcard_params(args)
args[:iteration_id] = args.delete(:iteration_wildcard_id) if args[:iteration_wildcard_id].present?
args[:not][:iteration_id] = args[:not].delete(:iteration_wildcard_id) if args.dig(:not, :iteration_wildcard_id).present?
end
def iteration_params_not_mutaully_exclusive?(args)
args.slice(*mutually_exclusive_iteration_args).compact.size > 1
end
def mutually_exclusive_iteration_args
[:iteration_id, :iteration_wildcard_id]
end
override :preloads
def preloads
super.merge(
......
......@@ -12,7 +12,7 @@ module EE
required: false,
description: 'Filter by epic ID wildcard. Incompatible with epicId.'
argument :iteration_wildcard_id, ::Types::Boards::IterationWildcardIdEnum,
argument :iteration_wildcard_id, ::Types::IterationWildcardIdEnum,
required: false,
description: 'Filter by iteration ID wildcard.'
end
......
......@@ -7,7 +7,7 @@ module EE
extend ActiveSupport::Concern
prepended do
argument :iteration_wildcard_id, ::Types::Boards::NegatedIterationWildcardIdEnum,
argument :iteration_wildcard_id, ::Types::NegatedIterationWildcardIdEnum,
required: false,
description: 'Filter by iteration ID wildcard.'
end
......
......@@ -13,6 +13,12 @@ module EE
argument :weight, GraphQL::STRING_TYPE,
required: false,
description: 'Weight not applied to the issue.'
argument :iteration_id, [::GraphQL::ID_TYPE],
required: false,
description: 'List of iteration Global IDs not applied to the issue.'
argument :iteration_wildcard_id, ::Types::IterationWildcardIdEnum,
required: false,
description: 'Filter by negated iteration ID wildcard.'
end
end
end
......
# frozen_string_literal: true
module Types
module Boards
class IterationWildcardIdEnum < BaseEnum
graphql_name 'IterationWildcardId'
description 'Iteration ID wildcard values'
value 'NONE', 'No iteration is assigned.'
value 'ANY', 'An iteration is assigned.'
value 'CURRENT', 'Current iteration.'
end
end
end
# frozen_string_literal: true
module Types
module Boards
class NegatedIterationWildcardIdEnum < BaseEnum
graphql_name 'NegatedIterationWildcardId'
description 'Negated Iteration ID wildcard values'
value 'CURRENT', 'Current iteration.'
end
end
end
# frozen_string_literal: true
module Types
class IterationWildcardIdEnum < BaseEnum
graphql_name 'IterationWildcardId'
description 'Iteration ID wildcard values'
value 'NONE', 'No iteration is assigned.'
value 'ANY', 'An iteration is assigned.'
value 'CURRENT', 'Current iteration.'
end
end
# frozen_string_literal: true
module Types
class NegatedIterationWildcardIdEnum < BaseEnum
graphql_name 'NegatedIterationWildcardId'
description 'Negated Iteration ID wildcard values'
value 'CURRENT', 'Current iteration.'
end
end
---
title: GraphQL issue filters support 'current' iteration.
Board issue filters support negated 'current' iteration
merge_request: 59325
author:
type: added
......@@ -92,6 +92,26 @@ RSpec.describe Resolvers::IssuesResolver do
end
end
describe 'filtering by iteration wildcard' do
it 'returns issues with current iteration' do
expect(resolve_issues(iteration_wildcard_id: 'CURRENT')).to contain_exactly(issue3)
end
it 'returns issues with any iteration' do
expect(resolve_issues(iteration_wildcard_id: 'ANY')).to contain_exactly(issue1, issue3)
end
it 'returns issues with no iteration' do
expect(resolve_issues(iteration_wildcard_id: 'NONE')).to contain_exactly(issue2, issue4)
end
it 'raises a mutually exclusive filter error when wildcard and list are provided' do
expect do
resolve_issues(iteration_id: [iteration1.to_global_id], iteration_wildcard_id: 'CURRENT')
end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [iterationId, iterationWildcardId] arguments is allowed at the same time.')
end
end
describe 'filter by epic' do
it 'returns issues without epic when epic_id is "none"' do
expect(resolve_issues(epic_id: 'none')).to contain_exactly(issue4, issue3)
......@@ -138,6 +158,28 @@ RSpec.describe Resolvers::IssuesResolver do
expect(resolve_issues(not: { weight: '3' })).to contain_exactly(issue1, issue2, issue4)
end
end
describe 'filtering by negated iteration' do
it 'returns issues without iteration using RAW id' do
expect(resolve_issues(not: { iteration_id: [iteration1.id.to_s] })).to contain_exactly(issue2, issue3, issue4)
end
it 'works with global IDs' do
expect(resolve_issues(not: { iteration_id: [iteration1.to_global_id] })).to contain_exactly(issue2, issue3, issue4)
end
it 'raises a mutually exclusive filter error when wildcard and list are provided' do
expect do
resolve_issues(not: { iteration_id: [iteration1.to_global_id], iteration_wildcard_id: 'CURRENT' })
end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [iterationId, iterationWildcardId] arguments is allowed at the same time.')
end
end
describe 'filtering by negated iteration wildcard' do
it 'returns issues not in the current iteration' do
expect(resolve_issues(not: { iteration_wildcard_id: 'CURRENT' })).to contain_exactly(issue1, issue2, issue4)
end
end
end
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment