Commit b05478a4 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch '300115-more-filters-issue-resolver-boards' into 'master'

Add missing issue filters to board queries

See merge request gitlab-org/gitlab!59703
parents 371d4f7e 58a7d971
...@@ -4,6 +4,10 @@ module Types ...@@ -4,6 +4,10 @@ module Types
module Boards module Boards
# rubocop: disable Graphql/AuthorizeTypes # rubocop: disable Graphql/AuthorizeTypes
class BoardIssueInputBaseType < BoardIssuableInputBaseType class BoardIssueInputBaseType < BoardIssuableInputBaseType
argument :iids, [GraphQL::STRING_TYPE],
required: false,
description: 'List of IIDs of issues. For example ["1", "2"].'
argument :milestone_title, GraphQL::STRING_TYPE, argument :milestone_title, GraphQL::STRING_TYPE,
required: false, required: false,
description: 'Filter by milestone title.' description: 'Filter by milestone title.'
......
---
title: Support board issue filtering by iids in GraphQL
merge_request: 59703
author:
type: added
...@@ -8756,6 +8756,15 @@ The state of the vulnerability. ...@@ -8756,6 +8756,15 @@ The state of the vulnerability.
| `DISMISSED` | | | `DISMISSED` | |
| `RESOLVED` | | | `RESOLVED` | |
### `WeightWildcardId`
Weight ID wildcard values.
| Value | Description |
| ----- | ----------- |
| `ANY` | Weight is assigned. |
| `NONE` | No weight is assigned. |
## Scalar types ## Scalar types
Scalar values are atomic values, and do not have fields of their own. Scalar values are atomic values, and do not have fields of their own.
......
...@@ -10,6 +10,7 @@ module EE ...@@ -10,6 +10,7 @@ module EE
def set_filter_values(filters) def set_filter_values(filters)
filter_by_epic(filters) filter_by_epic(filters)
filter_by_iteration(filters) filter_by_iteration(filters)
filter_by_weight(filters)
super super
end end
...@@ -38,6 +39,17 @@ module EE ...@@ -38,6 +39,17 @@ module EE
filters[:iteration_id] = iteration_wildcard_id filters[:iteration_id] = iteration_wildcard_id
end end
end end
def filter_by_weight(filters)
weight = filters[:weight]
weight_wildcard = filters.delete(:weight_wildcard_id)
if weight && weight_wildcard
raise ::Gitlab::Graphql::Errors::ArgumentError, 'Incompatible arguments: weight, weightWildcardId.'
end
filters[:weight] = weight_wildcard if weight_wildcard
end
end end
end end
end end
...@@ -18,6 +18,10 @@ module EE ...@@ -18,6 +18,10 @@ module EE
argument :weight, GraphQL::STRING_TYPE, argument :weight, GraphQL::STRING_TYPE,
required: false, required: false,
description: 'Filter by weight.' description: 'Filter by weight.'
argument :iteration_id, [::Types::GlobalIDType[::Iteration]],
required: false,
description: 'Filter by a list of iteration IDs. Incompatible with iterationWildcardId.'
end end
end end
end end
......
...@@ -15,6 +15,10 @@ module EE ...@@ -15,6 +15,10 @@ module EE
argument :iteration_wildcard_id, ::Types::IterationWildcardIdEnum, argument :iteration_wildcard_id, ::Types::IterationWildcardIdEnum,
required: false, required: false,
description: 'Filter by iteration ID wildcard.' description: 'Filter by iteration ID wildcard.'
argument :weight_wildcard_id, ::Types::Boards::WeightWildcardIdEnum,
required: false,
description: 'Filter by weight ID wildcard. Incompatible with weight.'
end end
end end
end end
......
# frozen_string_literal: true
module Types
module Boards
class WeightWildcardIdEnum < BaseEnum
graphql_name 'WeightWildcardId'
description 'Weight ID wildcard values'
value 'NONE', 'No weight is assigned.'
value 'ANY', 'Weight is assigned.'
end
end
end
---
title: Support board issue filtering by weight and iteration_id in GraphQL
merge_request: 59703
author:
type: added
...@@ -12,63 +12,122 @@ RSpec.describe Resolvers::BoardListIssuesResolver do ...@@ -12,63 +12,122 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
let_it_be(:label) { create(:label, project: project) } let_it_be(:label) { create(:label, project: project) }
let_it_be(:list) { create(:list, board: board, label: label) } let_it_be(:list) { create(:list, board: board, label: label) }
let_it_be(:epic) { create(:epic, group: group) }
let_it_be(:iteration) { create(:iteration, group: group, start_date: 1.week.ago, due_date: 2.days.ago) }
let_it_be(:current_iteration) { create(:iteration, :started, group: group, start_date: Date.today, due_date: 1.day.from_now) }
let_it_be(:issue1) { create(:issue, project: project, labels: [label], weight: 3) }
let_it_be(:issue2) { create(:issue, project: project, labels: [label], iteration: iteration) }
let_it_be(:issue3) { create(:issue, project: project, labels: [label]) }
let_it_be(:issue4) { create(:issue, project: project, labels: [label], iteration: current_iteration, weight: 1) }
let_it_be(:epic_issue) { create(:epic_issue, epic: epic, issue: issue1) }
before_all do before_all do
group.add_developer(user) group.add_developer(user)
end end
shared_examples 'raises error on mutually exclusive arguments' do
it 'raises an exception if mutually exclusive arguments are present' do
expect do
resolve_board_list_issues({ filters: filters })
end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
end
describe '#resolve' do describe '#resolve' do
context 'filtering by epic' do context 'filtering by epic' do
let_it_be(:issue) { create(:issue, project: project, labels: [label]) }
let_it_be(:epic) { create(:epic, group: group) }
let_it_be(:epic_issue) { create(:epic_issue, epic: epic, issue: issue) }
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
end end
it 'raises an exception if both epic_id and epic_wildcard_id are present' do context 'when providing mutually exclusive filters' do
expect do let(:filters) { { epic_id: epic.to_global_id, epic_wildcard_id: 'NONE' } }
resolve_board_list_issues({ filters: { epic_id: epic.to_global_id, epic_wildcard_id: 'NONE' } })
end.to raise_error(Gitlab::Graphql::Errors::ArgumentError) it_behaves_like 'raises error on mutually exclusive arguments'
end end
it 'accepts epic global id' do it 'accepts epic global id' do
result = resolve_board_list_issues({ filters: { epic_id: epic.to_global_id } }) result = resolve_board_list_issues({ filters: { epic_id: epic.to_global_id } })
expect(result).to match_array([issue]) expect(result).to contain_exactly(issue1)
end end
it 'accepts epic wildcard id' do it 'accepts epic wildcard id' do
result = resolve_board_list_issues({ filters: { epic_wildcard_id: 'NONE' } }) result = resolve_board_list_issues({ filters: { epic_wildcard_id: 'NONE' } })
expect(result).to match_array([]) expect(result).to contain_exactly(issue2, issue3, issue4)
end end
end end
context 'filtering by iteration' do context 'filtering by weight' do
let_it_be(:iteration) { create(:iteration, group: group, start_date: 1.week.ago, due_date: 2.days.ago) } it 'accepts weight wildcard id none' do
let_it_be(:current_iteration) { create(:iteration, :started, group: group, start_date: Date.today, due_date: 1.day.from_now) } result = resolve_board_list_issues({ filters: { weight_wildcard_id: 'NONE' } })
let_it_be(:issue_with_iteration) { create(:issue, project: project, labels: [label], iteration: iteration) }
let_it_be(:issue_without_iteration) { create(:issue, project: project, labels: [label]) } expect(result).to contain_exactly(issue2, issue3)
let_it_be(:issue_with_current_iteration) { create(:issue, project: project, labels: [label], iteration: current_iteration) } end
it 'accepts weight wildcard id any' do
result = resolve_board_list_issues({ filters: { weight_wildcard_id: 'ANY' } })
expect(result).to contain_exactly(issue1, issue4)
end
it 'filters by weight' do
result = resolve_board_list_issues({ filters: { weight: '3' } })
expect(result).to contain_exactly(issue1)
end
context 'when providing mutually exclusive filters' do
let(:filters) { { weight: 5, weight_wildcard_id: 'ANY' } }
it_behaves_like 'raises error on mutually exclusive arguments'
end
context 'filtering by negated weight' do
it 'filters by negated weight' do
result = resolve_board_list_issues({ filters: { not: { weight: '3' } } })
expect(result).to contain_exactly(issue2, issue3, issue4)
end
end
end
context 'filtering by iteration' do
it 'accepts iteration title' do it 'accepts iteration title' do
result = resolve_board_list_issues({ filters: { iteration_title: iteration.title } }) result = resolve_board_list_issues({ filters: { iteration_title: iteration.title } })
expect(result).to contain_exactly(issue_with_iteration) expect(result).to contain_exactly(issue2)
end end
it 'accepts iteration wildcard id' do it 'accepts iteration wildcard id' do
result = resolve_board_list_issues({ filters: { iteration_wildcard_id: 'NONE' } }) result = resolve_board_list_issues({ filters: { iteration_wildcard_id: 'NONE' } })
expect(result).to contain_exactly(issue_without_iteration) expect(result).to contain_exactly(issue1, issue3)
end end
context 'filterning by negated iteration' do context 'filterning by negated iteration' do
it 'accepts iteration wildcard id' do it 'accepts iteration wildcard id' do
result = resolve_board_list_issues({ filters: { not: { iteration_wildcard_id: 'CURRENT' } } }) result = resolve_board_list_issues({ filters: { not: { iteration_wildcard_id: 'CURRENT' } } })
expect(result).to contain_exactly(issue_without_iteration, issue_with_iteration) expect(result).to contain_exactly(issue1, issue3, issue2)
end
end
end
context 'filtering by iids' do
it 'filters by iids' do
result = resolve_board_list_issues({ filters: { iids: [issue1.iid, issue3.iid] } })
expect(result).to contain_exactly(issue1, issue3)
end
context 'filtering by negated iids' do
it 'filters by negated iid' do
result = resolve_board_list_issues({ filters: { not: { iids: [issue1.iid, issue3.iid] } } })
expect(result).to contain_exactly(issue2, issue4)
end 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