Commit 71400cff authored by charlie ablett's avatar charlie ablett

Merge branch '38296-graphql-add-milestone_due_asc-sort-for-issuables' into 'master'

GraphQL: Add 'milestone_due_asc' sort for Issuables

See merge request gitlab-org/gitlab!29992
parents fb9d90f2 d504b0c9
......@@ -52,7 +52,9 @@ module Resolvers
type Types::IssueType, null: true
NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc label_priority_asc label_priority_desc].freeze
NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc
label_priority_asc label_priority_desc
milestone_due_asc milestone_due_desc].freeze
def resolve(**args)
# The project could have been loaded in batch by `BatchLoader`.
......
......@@ -9,5 +9,7 @@ module Types
value 'PRIORITY_DESC', 'Priority by descending order', value: :priority_desc
value 'LABEL_PRIORITY_ASC', 'Label priority by ascending order', value: :label_priority_asc
value 'LABEL_PRIORITY_DESC', 'Label priority by descending order', value: :label_priority_desc
value 'MILESTONE_DUE_ASC', 'Milestone due date by ascending order', value: :milestone_due_asc
value 'MILESTONE_DUE_DESC', 'Milestone due date by descending order', value: :milestone_due_desc
end
end
---
title: GraphQL issue queries can now be sorted by milestone due date
merge_request: 29992
author:
type: added
......@@ -4677,6 +4677,16 @@ enum IssueSort {
"""
LABEL_PRIORITY_DESC
"""
Milestone due date by ascending order
"""
MILESTONE_DUE_ASC
"""
Milestone due date by descending order
"""
MILESTONE_DUE_DESC
"""
Priority by ascending order
"""
......
......@@ -13272,6 +13272,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "MILESTONE_DUE_ASC",
"description": "Milestone due date by ascending order",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "MILESTONE_DUE_DESC",
"description": "Milestone due date by descending order",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DUE_DATE_ASC",
"description": "Due date by ascending order",
......
......@@ -190,6 +190,23 @@ describe Resolvers::IssuesResolver do
expect(resolve_issues(sort: :label_priority_desc).items).to eq([label_issue2, label_issue3, label_issue1, label_issue4])
end
end
context 'when sorting by milestone due date' do
let_it_be(:project) { create(:project) }
let_it_be(:early_milestone) { create(:milestone, project: project, due_date: 10.days.from_now) }
let_it_be(:late_milestone) { create(:milestone, project: project, due_date: 30.days.from_now) }
let_it_be(:milestone_issue1) { create(:issue, project: project) }
let_it_be(:milestone_issue2) { create(:issue, project: project, milestone: early_milestone) }
let_it_be(:milestone_issue3) { create(:issue, project: project, milestone: late_milestone) }
it 'sorts issues ascending' do
expect(resolve_issues(sort: :milestone_due_asc).items).to eq([milestone_issue2, milestone_issue3, milestone_issue1])
end
it 'sorts issues descending' do
expect(resolve_issues(sort: :milestone_due_desc).items).to eq([milestone_issue3, milestone_issue2, milestone_issue1])
end
end
end
it 'returns issues user can see' do
......
......@@ -6,6 +6,10 @@ describe Types::IssuableSortEnum do
it { expect(described_class.graphql_name).to eq('IssuableSort') }
it 'exposes all the existing issuable sort values' do
expect(described_class.values.keys).to include(*%w[PRIORITY_ASC PRIORITY_DESC])
expect(described_class.values.keys).to include(
*%w[PRIORITY_ASC PRIORITY_DESC
LABEL_PRIORITY_ASC LABEL_PRIORITY_DESC
MILESTONE_DUE_ASC MILESTONE_DUE_DESC]
)
end
end
......@@ -9,7 +9,7 @@ describe GitlabSchema.types['IssueSort'] do
it 'exposes all the existing issue sort values' do
expect(described_class.values.keys).to include(
*%w[DUE_DATE_ASC DUE_DATE_DESC RELATIVE_POSITION_ASC LABEL_PRIORITY_ASC LABEL_PRIORITY_DESC]
*%w[DUE_DATE_ASC DUE_DATE_DESC RELATIVE_POSITION_ASC]
)
end
end
......@@ -118,138 +118,64 @@ describe 'getting an issue list for a project' do
end
describe 'sorting and pagination' do
let(:start_cursor) { graphql_data['project']['issues']['pageInfo']['startCursor'] }
let(:end_cursor) { graphql_data['project']['issues']['pageInfo']['endCursor'] }
let_it_be(:data_path) { [:project, :issues] }
context 'when sorting by due date' do
let_it_be(:sort_project) { create(:project, :public) }
let_it_be(:due_issue1) { create(:issue, project: sort_project, due_date: 3.days.from_now) }
let_it_be(:due_issue2) { create(:issue, project: sort_project, due_date: nil) }
let_it_be(:due_issue3) { create(:issue, project: sort_project, due_date: 2.days.ago) }
let_it_be(:due_issue4) { create(:issue, project: sort_project, due_date: nil) }
let_it_be(:due_issue5) { create(:issue, project: sort_project, due_date: 1.day.ago) }
let_it_be(:params) { 'sort: DUE_DATE_ASC' }
def query(issue_params = params)
def pagination_query(params, page_info)
graphql_query_for(
'project',
{ 'fullPath' => sort_project.full_path },
<<~ISSUES
issues(#{issue_params}) {
pageInfo {
endCursor
}
edges {
node {
iid
dueDate
}
}
}
ISSUES
"issues(#{params}) { #{page_info} edges { node { iid dueDate } } }"
)
end
before do
post_graphql(query, current_user: current_user)
def pagination_results_data(data)
data.map { |issue| issue.dig('node', 'iid').to_i }
end
it_behaves_like 'a working graphql query'
context 'when sorting by due date' do
let_it_be(:sort_project) { create(:project, :public) }
let_it_be(:due_issue1) { create(:issue, project: sort_project, due_date: 3.days.from_now) }
let_it_be(:due_issue2) { create(:issue, project: sort_project, due_date: nil) }
let_it_be(:due_issue3) { create(:issue, project: sort_project, due_date: 2.days.ago) }
let_it_be(:due_issue4) { create(:issue, project: sort_project, due_date: nil) }
let_it_be(:due_issue5) { create(:issue, project: sort_project, due_date: 1.day.ago) }
context 'when ascending' do
it 'sorts issues' do
expect(grab_iids).to eq([due_issue3.iid, due_issue5.iid, due_issue1.iid, due_issue4.iid, due_issue2.iid])
end
context 'when paginating' do
let(:params) { 'sort: DUE_DATE_ASC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq([due_issue3.iid, due_issue5.iid])
cursored_query = query("sort: DUE_DATE_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([due_issue1.iid, due_issue4.iid, due_issue2.iid])
end
it_behaves_like 'sorted paginated query' do
let(:sort_param) { 'DUE_DATE_ASC' }
let(:first_param) { 2 }
let(:expected_results) { [due_issue3.iid, due_issue5.iid, due_issue1.iid, due_issue4.iid, due_issue2.iid] }
end
end
context 'when descending' do
let(:params) { 'sort: DUE_DATE_DESC' }
it 'sorts issues' do
expect(grab_iids).to eq([due_issue1.iid, due_issue5.iid, due_issue3.iid, due_issue4.iid, due_issue2.iid])
end
context 'when paginating' do
let(:params) { 'sort: DUE_DATE_DESC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq([due_issue1.iid, due_issue5.iid])
cursored_query = query("sort: DUE_DATE_DESC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([due_issue3.iid, due_issue4.iid, due_issue2.iid])
end
it_behaves_like 'sorted paginated query' do
let(:sort_param) { 'DUE_DATE_DESC' }
let(:first_param) { 2 }
let(:expected_results) { [due_issue1.iid, due_issue5.iid, due_issue3.iid, due_issue4.iid, due_issue2.iid] }
end
end
end
context 'when sorting by relative position' do
let_it_be(:sort_project) { create(:project, :public) }
let_it_be(:relative_issue1) { create(:issue, project: sort_project, relative_position: 2000) }
let_it_be(:relative_issue2) { create(:issue, project: sort_project, relative_position: nil) }
let_it_be(:relative_issue3) { create(:issue, project: sort_project, relative_position: 1000) }
let_it_be(:relative_issue4) { create(:issue, project: sort_project, relative_position: nil) }
let_it_be(:relative_issue5) { create(:issue, project: sort_project, relative_position: 500) }
let_it_be(:params) { 'sort: RELATIVE_POSITION_ASC' }
def query(issue_params = params)
graphql_query_for(
'project',
{ 'fullPath' => sort_project.full_path },
"issues(#{issue_params}) { pageInfo { endCursor} edges { node { iid dueDate } } }"
)
end
before do
post_graphql(query, current_user: current_user)
end
it_behaves_like 'a working graphql query'
context 'when ascending' do
it 'sorts issues' do
expect(grab_iids).to eq([relative_issue5.iid, relative_issue3.iid, relative_issue1.iid, relative_issue4.iid, relative_issue2.iid])
end
context 'when paginating' do
let(:params) { 'sort: RELATIVE_POSITION_ASC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq([relative_issue5.iid, relative_issue3.iid])
cursored_query = query("sort: RELATIVE_POSITION_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([relative_issue1.iid, relative_issue4.iid, relative_issue2.iid])
end
it_behaves_like 'sorted paginated query' do
let(:sort_param) { 'RELATIVE_POSITION_ASC' }
let(:first_param) { 2 }
let(:expected_results) { [relative_issue5.iid, relative_issue3.iid, relative_issue1.iid, relative_issue4.iid, relative_issue2.iid] }
end
end
end
context 'when sorting by priority' do
let_it_be(:sort_project) { create(:project, :public) }
let_it_be(:early_milestone) { create(:milestone, project: sort_project, due_date: 10.days.from_now) }
let_it_be(:late_milestone) { create(:milestone, project: sort_project, due_date: 30.days.from_now) }
let_it_be(:priority_label1) { create(:label, project: sort_project, priority: 1) }
......@@ -259,68 +185,25 @@ describe 'getting an issue list for a project' do
let_it_be(:priority_issue3) { create(:issue, project: sort_project, milestone: early_milestone) }
let_it_be(:priority_issue4) { create(:issue, project: sort_project) }
let_it_be(:params) { 'sort: PRIORITY_ASC' }
def query(issue_params = params)
graphql_query_for(
'project',
{ 'fullPath' => sort_project.full_path },
"issues(#{issue_params}) { pageInfo { endCursor} edges { node { iid dueDate } } }"
)
end
before do
post_graphql(query, current_user: current_user)
end
it_behaves_like 'a working graphql query'
context 'when ascending' do
it 'sorts issues' do
expect(grab_iids).to eq([priority_issue3.iid, priority_issue1.iid, priority_issue2.iid, priority_issue4.iid])
end
context 'when paginating' do
let(:params) { 'sort: PRIORITY_ASC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq([priority_issue3.iid, priority_issue1.iid])
cursored_query = query("sort: PRIORITY_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([priority_issue2.iid, priority_issue4.iid])
end
it_behaves_like 'sorted paginated query' do
let(:sort_param) { 'PRIORITY_ASC' }
let(:first_param) { 2 }
let(:expected_results) { [priority_issue3.iid, priority_issue1.iid, priority_issue2.iid, priority_issue4.iid] }
end
end
context 'when descending' do
let(:params) { 'sort: PRIORITY_DESC' }
it 'sorts issues' do
expect(grab_iids).to eq([priority_issue1.iid, priority_issue3.iid, priority_issue2.iid, priority_issue4.iid])
end
context 'when paginating' do
let(:params) { 'sort: PRIORITY_DESC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq([priority_issue1.iid, priority_issue3.iid])
cursored_query = query("sort: PRIORITY_DESC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([priority_issue2.iid, priority_issue4.iid])
end
it_behaves_like 'sorted paginated query' do
let(:sort_param) { 'PRIORITY_DESC' }
let(:first_param) { 2 }
let(:expected_results) { [priority_issue1.iid, priority_issue3.iid, priority_issue2.iid, priority_issue4.iid] }
end
end
end
context 'when sorting by label priority' do
let_it_be(:sort_project) { create(:project, :public) }
let_it_be(:label1) { create(:label, project: sort_project, priority: 1) }
let_it_be(:label2) { create(:label, project: sort_project, priority: 5) }
let_it_be(:label3) { create(:label, project: sort_project, priority: 10) }
......@@ -329,61 +212,44 @@ describe 'getting an issue list for a project' do
let_it_be(:label_issue3) { create(:issue, project: sort_project, labels: [label1, label3]) }
let_it_be(:label_issue4) { create(:issue, project: sort_project) }
let_it_be(:params) { 'sort: LABEL_PRIORITY_ASC' }
def query(issue_params = params)
graphql_query_for(
'project',
{ 'fullPath' => sort_project.full_path },
"issues(#{issue_params}) { pageInfo { endCursor} edges { node { iid dueDate } } }"
)
end
before do
post_graphql(query, current_user: current_user)
end
it_behaves_like 'a working graphql query'
context 'when ascending' do
it 'sorts issues' do
expect(grab_iids).to eq [label_issue3.iid, label_issue1.iid, label_issue2.iid, label_issue4.iid]
it_behaves_like 'sorted paginated query' do
let(:sort_param) { 'LABEL_PRIORITY_ASC' }
let(:first_param) { 2 }
let(:expected_results) { [label_issue3.iid, label_issue1.iid, label_issue2.iid, label_issue4.iid] }
end
end
context 'when paginating' do
let(:params) { 'sort: LABEL_PRIORITY_ASC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq [label_issue3.iid, label_issue1.iid]
cursored_query = query("sort: LABEL_PRIORITY_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq [label_issue2.iid, label_issue4.iid]
context 'when descending' do
it_behaves_like 'sorted paginated query' do
let(:sort_param) { 'LABEL_PRIORITY_DESC' }
let(:first_param) { 2 }
let(:expected_results) { [label_issue2.iid, label_issue3.iid, label_issue1.iid, label_issue4.iid] }
end
end
end
context 'when descending' do
let(:params) { 'sort: LABEL_PRIORITY_DESC' }
context 'when sorting by milestone due date' do
let_it_be(:sort_project) { create(:project, :public) }
let_it_be(:early_milestone) { create(:milestone, project: sort_project, due_date: 10.days.from_now) }
let_it_be(:late_milestone) { create(:milestone, project: sort_project, due_date: 30.days.from_now) }
let_it_be(:milestone_issue1) { create(:issue, project: sort_project) }
let_it_be(:milestone_issue2) { create(:issue, project: sort_project, milestone: early_milestone) }
let_it_be(:milestone_issue3) { create(:issue, project: sort_project, milestone: late_milestone) }
it 'sorts issues' do
expect(grab_iids).to eq [label_issue2.iid, label_issue3.iid, label_issue1.iid, label_issue4.iid]
context 'when ascending' do
it_behaves_like 'sorted paginated query' do
let(:sort_param) { 'MILESTONE_DUE_ASC' }
let(:first_param) { 2 }
let(:expected_results) { [milestone_issue2.iid, milestone_issue3.iid, milestone_issue1.iid] }
end
context 'when paginating' do
let(:params) { 'sort: LABEL_PRIORITY_DESC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq [label_issue2.iid, label_issue3.iid]
cursored_query = query("sort: LABEL_PRIORITY_DESC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq [label_issue1.iid, label_issue4.iid]
end
context 'when descending' do
it_behaves_like 'sorted paginated query' do
let(:sort_param) { 'MILESTONE_DUE_DESC' }
let(:first_param) { 2 }
let(:expected_results) { [milestone_issue3.iid, milestone_issue2.iid, milestone_issue1.iid] }
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