Commit 0896cb7d authored by Felipe Artur's avatar Felipe Artur

Support epic board list negated filter params

Allow to filter epics by negated params
on epic boards lists using  GraphQL.
parent c840c099
......@@ -129,6 +129,8 @@ class EpicsFinder < IssuableFinder
# API endpoints send in `nil` values so we test if there are any non-nil
return items unless not_params&.values&.any?
items = by_negated_my_reaction_emoji(items)
by_negated_label(items)
end
......
......@@ -5,6 +5,13 @@ module Types
class BoardEpicInputType < BoardIssuableInputBaseType
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,
required: false,
description: 'Search query for epic title or description.'
......
---
title: Support epic board list negated filter params
merge_request: 57001
author:
type: added
......@@ -649,6 +649,25 @@ RSpec.describe EpicsFinder do
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
......
......@@ -41,43 +41,56 @@ RSpec.describe Resolvers::Boards::BoardListEpicsResolver do
expect(result.to_a).to eq([list1_epic2, list1_epic1])
end
context 'with filters' do
context 'when filtering' do
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_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
args = { filters: { label_name: [production_label.title] } }
subject(:results) { resolve(described_class, ctx: { current_user: user }, obj: list1, args: args) }
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
it 'filters epics by author' do
args = { filters: { author_username: list1_epic4.author.username } }
context 'by author' do
let(:args) { { filters: { author_username: list1_epic4.author.username } } }
result = resolve_board_list_epics(args: args)
expect(result).to contain_exactly(list1_epic4)
it { is_expected.to contain_exactly(list1_epic4) }
end
it 'filters epics by reaction emoji' do
emoji_name = 'thumbsup'
create(:award_emoji, name: emoji_name, awardable: list1_epic1, user: user)
args = { filters: { my_reaction_emoji: emoji_name } }
context 'by reaction emoji' do
let(:args) { { filters: { my_reaction_emoji: awarded_emoji.name } } }
it { is_expected.to contain_exactly(list1_epic1) }
end
result = resolve_board_list_epics(args: args)
context 'by title and description' do
let(:args) { { filters: { search: 'filter_this' } } }
expect(result).to contain_exactly(list1_epic1)
it { is_expected.to contain_exactly(list1_epic3, list1_epic4) }
end
it 'filters epics by title and description' do
args = { filters: { search: 'filter_this' } }
context 'with negated filters' do
context 'by label' do
let(:args) { { filters: { not: { label_name: [production_label.title] } } } }
it { is_expected.to contain_exactly(list1_epic1, list1_epic2, list1_epic4) }
end
context 'by author' do
let(:args) { { filters: { not: { author_username: list1_epic2.author.username } } } }
it { is_expected.to contain_exactly(list1_epic1, list1_epic3, list1_epic4) }
end
result = resolve_board_list_epics(args: args)
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
......
......@@ -56,7 +56,7 @@ RSpec.describe 'get list of epics for an epic board list' do
end
end
context 'filters' do
context 'with filters' do
let(:epic_fields) { 'id' }
it 'finds only epics matching the filter' 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)
expect(boards).to contain_exactly(global_id_of(epic3))
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
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