Commit 28d98d1a authored by Eugenia Grieff's avatar Eugenia Grieff

Add confidential filter to board list in GraphQL

- Add confidential filter for board and epic lists
- Add spec

Changelog: added
parent 2b556843
......@@ -17,6 +17,10 @@ module Types
argument :assignee_wildcard_id, ::Types::Boards::AssigneeWildcardIdEnum,
required: false,
description: 'Filter by assignee wildcard. Incompatible with assigneeUsername.'
argument :confidential, GraphQL::Types::Boolean,
required: false,
description: 'Filter by confidentiality.'
end
end
end
......
......@@ -18322,6 +18322,7 @@ Field that are available while modifying the custom mapping attributes for an HT
| <a id="boardissueinputassigneeusername"></a>`assigneeUsername` | [`[String]`](#string) | Filter by assignee username. |
| <a id="boardissueinputassigneewildcardid"></a>`assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee wildcard. Incompatible with assigneeUsername. |
| <a id="boardissueinputauthorusername"></a>`authorUsername` | [`String`](#string) | Filter by author username. |
| <a id="boardissueinputconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter by confidentiality. |
| <a id="boardissueinputepicid"></a>`epicId` | [`EpicID`](#epicid) | Filter by epic ID. Incompatible with epicWildcardId. |
| <a id="boardissueinputepicwildcardid"></a>`epicWildcardId` | [`EpicWildcardId`](#epicwildcardid) | Filter by epic ID wildcard. Incompatible with epicId. |
| <a id="boardissueinputiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of issues. For example `["1", "2"]`. |
......@@ -18448,6 +18449,7 @@ Input type for DastSiteProfile authentication.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="epicfiltersauthorusername"></a>`authorUsername` | [`String`](#string) | Filter by author username. |
| <a id="epicfiltersconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter by confidentiality. |
| <a id="epicfilterslabelname"></a>`labelName` | [`[String]`](#string) | Filter by label name. |
| <a id="epicfiltersmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. Wildcard values "NONE" and "ANY" are supported. |
| <a id="epicfiltersnot"></a>`not` | [`NegatedEpicBoardIssueInput`](#negatedepicboardissueinput) | Negated epic arguments. |
......@@ -15,6 +15,10 @@ module Types
argument :search, GraphQL::Types::String,
required: false,
description: 'Search query for epic title or description.'
argument :confidential, GraphQL::Types::Boolean,
required: false,
description: 'Filter by confidentiality.'
end
end
end
......@@ -86,8 +86,9 @@ RSpec.describe 'get list of epic boards' do
# filtering.
create(:labeled_epic, group: group)
create(:labeled_epic, group: group, labels: [label])
create(:labeled_epic, group: group, labels: [label], confidential: true)
params = { epicFilters: { labelName: label.title } }
params = { epicFilters: { labelName: label.title, confidential: false } }
post_graphql(pagination_query(params), current_user: current_user)
assert_field_value('epicsCount', [1, 0, 0])
......
......@@ -25,7 +25,7 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
let(:wildcard_started) { 'STARTED' }
let(:filters) { { milestone_title: ["started"], milestone_wildcard_id: wildcard_started } }
it 'raises a mutually exclusive filter error when milstone wildcard and title are provided' do
it 'raises a mutually exclusive filter error when milestone wildcard and title are provided' do
expect do
resolve_board_list_issues(args: { filters: filters })
end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
......@@ -80,6 +80,16 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
expect(result).to match_array([])
end
context 'when filtering by confidential' do
let(:confidential_issue) { create(:issue, project: project, labels: [label], relative_position: nil, confidential: true) }
it 'returns matching issue' do
result = resolve_board_list_issues(args: { filters: { confidential: true } })
expect(result).to contain_exactly(confidential_issue)
end
end
end
end
......
......@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['BoardIssueInput'] do
it 'has specific fields' do
allowed_args = %w(labelName milestoneTitle assigneeUsername authorUsername
releaseTag myReactionEmoji not search assigneeWildcardId)
releaseTag myReactionEmoji not search assigneeWildcardId confidential)
expect(described_class.arguments.keys).to include(*allowed_args)
expect(described_class.arguments['not'].type).to eq(Types::Boards::NegatedBoardIssueInputType)
......
......@@ -16,6 +16,7 @@ RSpec.describe 'get board lists' do
let(:params) { '' }
let(:board) { }
let(:confidential) { false }
let(:board_parent_type) { board_parent.class.to_s.downcase }
let(:board_data) { graphql_data[board_parent_type]['boards']['nodes'][0] }
let(:lists_data) { board_data['lists']['nodes'][0] }
......@@ -30,7 +31,7 @@ RSpec.describe 'get board lists' do
nodes {
lists {
nodes {
issues(filters: {labelName: "#{label2.title}"}, first: 3) {
issues(filters: {labelName: "#{label2.title}", confidential: #{confidential}}, first: 3) {
count
nodes {
#{all_graphql_fields_for('issues'.classify)}
......@@ -57,14 +58,15 @@ RSpec.describe 'get board lists' do
end
shared_examples 'group and project board list issues query' do
let!(:board) { create(:board, resource_parent: board_parent) }
let!(:label_list) { create(:list, board: board, label: label, position: 10) }
let!(:issue1) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 9) }
let!(:issue2) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 2) }
let!(:issue3) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) }
let!(:issue4) { create(:issue, project: issue_project, labels: [label], relative_position: 9) }
let!(:issue5) { create(:issue, project: issue_project, labels: [label2], relative_position: 432) }
let!(:issue6) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) }
let_it_be(:board) { create(:board, resource_parent: board_parent) }
let_it_be(:label_list) { create(:list, board: board, label: label, position: 10) }
let_it_be(:issue1) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 9) }
let_it_be(:issue2) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 2) }
let_it_be(:issue3) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) }
let_it_be(:issue4) { create(:issue, project: issue_project, labels: [label], relative_position: 9) }
let_it_be(:issue5) { create(:issue, project: issue_project, labels: [label2], relative_position: 432) }
let_it_be(:issue6) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) }
let_it_be(:issue7) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 5, confidential: true) }
context 'when the user does not have access to the board' do
it 'returns nil' do
......@@ -90,23 +92,33 @@ RSpec.describe 'get board lists' do
expect(issue_id).not_to include(issue6.id)
expect(issue3.relative_position).to be_nil
end
context 'when filtering by confidential' do
let(:confidential) { true }
it 'returns matching issue' do
expect(issue_titles).to match_array([issue7.title])
expect(issue_relative_positions).not_to include(nil)
end
end
end
end
describe 'for a project' do
let(:board_parent) { project }
let(:label) { project_label }
let(:label2) { project_label2 }
let(:issue_project) { project }
let_it_be(:board_parent) { project }
let_it_be(:label) { project_label }
let_it_be(:label2) { project_label2 }
let_it_be(:issue_project) { project }
it_behaves_like 'group and project board list issues query'
end
describe 'for a group' do
let(:board_parent) { group }
let(:label) { group_label }
let(:label2) { group_label2 }
let(:issue_project) { create(:project, :private, group: group) }
let_it_be(:board_parent) { group }
let_it_be(:label) { group_label }
let_it_be(:label2) { group_label2 }
let_it_be(:issue_project) { create(:project, :private, group: group) }
before do
allow(board_parent).to receive(:multiple_issue_boards_available?).and_return(false)
......
......@@ -12,6 +12,7 @@ RSpec.describe 'Querying a Board list' do
let_it_be(:list) { create(:list, board: board, label: label) }
let_it_be(:issue1) { create(:issue, project: project, labels: [label]) }
let_it_be(:issue2) { create(:issue, project: project, labels: [label], assignees: [current_user]) }
let_it_be(:issue3) { create(:issue, project: project, labels: [label], confidential: true) }
let(:filters) { {} }
let(:query) do
......@@ -37,19 +38,33 @@ RSpec.describe 'Querying a Board list' do
it { is_expected.to include({ 'issuesCount' => 2, 'title' => list.title }) }
context 'with matching issue filters' do
let(:filters) { { assigneeUsername: current_user.username } }
describe 'issue filters' do
context 'with matching assignee username issue filters' do
let(:filters) { { assigneeUsername: current_user.username } }
it 'filters issues metadata' do
is_expected.to include({ 'issuesCount' => 1, 'title' => list.title })
it 'filters issues metadata' do
is_expected.to include({ 'issuesCount' => 1, 'title' => list.title })
end
end
end
context 'with unmatching issue filters' do
let(:filters) { { assigneeUsername: 'foo' } }
context 'with unmatching assignee username issue filters' do
let(:filters) { { assigneeUsername: 'foo' } }
it 'filters issues metadata' do
is_expected.to include({ 'issuesCount' => 0, 'title' => list.title })
end
end
context 'when filtering by confidential' do
let(:filters) { { confidential: true } }
before_all do
project.add_developer(current_user)
end
it 'filters issues metadata' do
is_expected.to include({ 'issuesCount' => 0, 'title' => list.title })
it 'filters issues metadata' do
is_expected.to include({ 'issuesCount' => 1, 'title' => list.title })
end
end
end
end
......
......@@ -109,9 +109,15 @@ RSpec.describe 'get board lists' do
it 'returns the correct list with issue count for matching issue filters' do
label_list = create(:list, board: board, label: label, position: 10)
create(:issue, project: project, labels: [label, label2])
create(:issue, project: project, labels: [label, label2], confidential: true)
create(:issue, project: project, labels: [label])
post_graphql(query(id: global_id_of(label_list), issueFilters: { labelName: label2.title }), current_user: user)
post_graphql(
query(
id: global_id_of(label_list),
issueFilters: { labelName: label2.title, confidential: false }
), current_user: user
)
aggregate_failures do
list_node = lists_data[0]['node']
......
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