Commit b8993fd5 authored by Alex Kalderimis's avatar Alex Kalderimis

Merge branch 'issue_322686-negated_filters' into 'master'

Support epic board lists negated filters on GraphQL

See merge request gitlab-org/gitlab!57001
parents 47d8b264 0896cb7d
...@@ -129,6 +129,8 @@ class EpicsFinder < IssuableFinder ...@@ -129,6 +129,8 @@ class EpicsFinder < IssuableFinder
# API endpoints send in `nil` values so we test if there are any non-nil # API endpoints send in `nil` values so we test if there are any non-nil
return items unless not_params&.values&.any? return items unless not_params&.values&.any?
items = by_negated_my_reaction_emoji(items)
by_negated_label(items) by_negated_label(items)
end end
......
...@@ -5,6 +5,13 @@ module Types ...@@ -5,6 +5,13 @@ module Types
class BoardEpicInputType < BoardIssuableInputBaseType class BoardEpicInputType < BoardIssuableInputBaseType
graphql_name 'EpicFilters' graphql_name 'EpicFilters'
class NegatedEpicBoardIssueInputType < BoardIssuableInputBaseType
end
argument :not, NegatedEpicBoardIssueInputType,
required: false,
description: 'List of epic negated params. Warning: this argument is experimental and a subject to change in the future.'
argument :search, GraphQL::STRING_TYPE, argument :search, GraphQL::STRING_TYPE,
required: false, required: false,
description: 'Search query for epic title or description.' description: 'Search query for epic title or description.'
......
---
title: Support epic board list negated filter params
merge_request: 57001
author:
type: added
...@@ -673,6 +673,25 @@ RSpec.describe EpicsFinder do ...@@ -673,6 +673,25 @@ RSpec.describe EpicsFinder do
end end
end end
end end
context 'with negated reaction emoji' do
let_it_be(:awarded_emoji) { create(:award_emoji, name: 'thumbsup', awardable: epic3, user: search_user) }
let_it_be(:params) { { not: { my_reaction_emoji: awarded_emoji.name } } }
it 'returns all epics without given emoji name' do
expect(epics(params)).to contain_exactly(epic1, epic2)
end
context 'when not_issuable_queries is disabled' do
before do
stub_feature_flags(not_issuable_queries: false)
end
it 'returns epics that include negated params' do
expect(epics(params)).to contain_exactly(epic1, epic2, epic3)
end
end
end
end end
end end
end end
......
...@@ -41,43 +41,56 @@ RSpec.describe Resolvers::Boards::BoardListEpicsResolver do ...@@ -41,43 +41,56 @@ RSpec.describe Resolvers::Boards::BoardListEpicsResolver do
expect(result.to_a).to eq([list1_epic2, list1_epic1]) expect(result.to_a).to eq([list1_epic2, list1_epic1])
end end
context 'with filters' do context 'when filtering' do
let_it_be(:production_label) { create(:group_label, group: group, name: 'production') } let_it_be(:production_label) { create(:group_label, group: group, name: 'production') }
let_it_be(:list1_epic3) { create(:labeled_epic, group: group, labels: [development, production_label], title: 'filter_this 1') } let_it_be(:list1_epic3) { create(:labeled_epic, group: group, labels: [development, production_label], title: 'filter_this 1') }
let_it_be(:list1_epic4) { create(:labeled_epic, group: group, labels: [development], description: 'filter_this 2') } let_it_be(:list1_epic4) { create(:labeled_epic, group: group, labels: [development], description: 'filter_this 2') }
let_it_be(:awarded_emoji) { create(:award_emoji, name: 'thumbsup', awardable: list1_epic1, user: user) }
it 'filters epics by label' do subject(:results) { resolve(described_class, ctx: { current_user: user }, obj: list1, args: args) }
args = { filters: { label_name: [production_label.title] } }
result = resolve_board_list_epics(args: args) context 'by label' do
let(:args) { { filters: { label_name: [production_label.title] } } }
expect(result).to contain_exactly(list1_epic3) it { is_expected.to contain_exactly(list1_epic3) }
end end
it 'filters epics by author' do context 'by author' do
args = { filters: { author_username: list1_epic4.author.username } } let(:args) { { filters: { author_username: list1_epic4.author.username } } }
result = resolve_board_list_epics(args: args) it { is_expected.to contain_exactly(list1_epic4) }
end
context 'by reaction emoji' do
let(:args) { { filters: { my_reaction_emoji: awarded_emoji.name } } }
expect(result).to contain_exactly(list1_epic4) it { is_expected.to contain_exactly(list1_epic1) }
end end
it 'filters epics by reaction emoji' do context 'by title and description' do
emoji_name = 'thumbsup' let(:args) { { filters: { search: 'filter_this' } } }
create(:award_emoji, name: emoji_name, awardable: list1_epic1, user: user)
args = { filters: { my_reaction_emoji: emoji_name } } it { is_expected.to contain_exactly(list1_epic3, list1_epic4) }
end
result = resolve_board_list_epics(args: args) context 'with negated filters' do
context 'by label' do
let(:args) { { filters: { not: { label_name: [production_label.title] } } } }
expect(result).to contain_exactly(list1_epic1) it { is_expected.to contain_exactly(list1_epic1, list1_epic2, list1_epic4) }
end end
it 'filters epics by title and description' do context 'by author' do
args = { filters: { search: 'filter_this' } } let(:args) { { filters: { not: { author_username: list1_epic2.author.username } } } }
result = resolve_board_list_epics(args: args) it { is_expected.to contain_exactly(list1_epic1, list1_epic3, list1_epic4) }
end
context 'by emoji' do
let(:args) { { filters: { not: { my_reaction_emoji: awarded_emoji.name } } } }
expect(result).to contain_exactly(list1_epic3, list1_epic4) it { is_expected.to contain_exactly(list1_epic2, list1_epic3, list1_epic4) }
end
end end
end end
end end
......
...@@ -56,7 +56,7 @@ RSpec.describe 'get list of epics for an epic board list' do ...@@ -56,7 +56,7 @@ RSpec.describe 'get list of epics for an epic board list' do
end end
end end
context 'filters' do context 'with filters' do
let(:epic_fields) { 'id' } let(:epic_fields) { 'id' }
it 'finds only epics matching the filter' do it 'finds only epics matching the filter' do
...@@ -68,5 +68,17 @@ RSpec.describe 'get list of epics for an epic board list' do ...@@ -68,5 +68,17 @@ RSpec.describe 'get list of epics for an epic board list' do
boards = graphql_data_at(*data_path, :nodes, :id) boards = graphql_data_at(*data_path, :nodes, :id)
expect(boards).to contain_exactly(global_id_of(epic3)) expect(boards).to contain_exactly(global_id_of(epic3))
end end
context 'when negated' do
it 'finds only epics matching the negated filter' do
filter_params = { filters: { not: { label_name: [staging.title] } } }
query = pagination_query(filter_params)
post_graphql(query, current_user: current_user)
boards = graphql_data_at(*data_path, :nodes, :id)
expect(boards).to contain_exactly(global_id_of(epic1), global_id_of(epic2))
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