Commit a3e72ac4 authored by Sean Arnold's avatar Sean Arnold

Move shared fields to concerns

- Update some wording
- Add resolver specs
parent 5e107b66
# frozen_string_literal: true
module IssueResolverFields
extend ActiveSupport::Concern
prepended do
argument :iid, GraphQL::STRING_TYPE,
required: false,
description: 'IID of the issue. For example, "1"'
argument :iids, [GraphQL::STRING_TYPE],
required: false,
description: 'List of IIDs of issues. For example, [1, 2]'
argument :label_name, GraphQL::STRING_TYPE.to_list_type,
required: false,
description: 'Labels applied to this issue'
argument :milestone_title, GraphQL::STRING_TYPE.to_list_type,
required: false,
description: 'Milestones applied to this issue'
argument :assignee_username, GraphQL::STRING_TYPE,
required: false,
description: 'Username of a user assigned to the issues'
argument :assignee_id, GraphQL::STRING_TYPE,
required: false,
description: 'ID of a user assigned to the issues, "none" and "any" values supported'
argument :created_before, Types::TimeType,
required: false,
description: 'Issues created before this date'
argument :created_after, Types::TimeType,
required: false,
description: 'Issues created after this date'
argument :updated_before, Types::TimeType,
required: false,
description: 'Issues updated before this date'
argument :updated_after, Types::TimeType,
required: false,
description: 'Issues updated after this date'
argument :closed_before, Types::TimeType,
required: false,
description: 'Issues closed before this date'
argument :closed_after, Types::TimeType,
required: false,
description: 'Issues closed after this date'
argument :search, GraphQL::STRING_TYPE,
required: false,
description: 'Search query for issue title or description'
argument :types, [Types::IssueTypeEnum],
as: :issue_types,
description: 'Filter issues by the given issue types',
required: false
end
end
# frozen_string_literal: true
module Resolvers
module IssueResolverFields
extend ActiveSupport::Concern
prepended do
argument :iid, GraphQL::STRING_TYPE,
required: false,
description: 'IID of the issue. For example, "1"'
argument :iids, [GraphQL::STRING_TYPE],
required: false,
description: 'List of IIDs of issues. For example, [1, 2]'
argument :state, Types::IssuableStateEnum,
required: false,
description: 'Current state of this issue'
argument :label_name, GraphQL::STRING_TYPE.to_list_type,
required: false,
description: 'Labels applied to this issue'
argument :milestone_title, GraphQL::STRING_TYPE.to_list_type,
required: false,
description: 'Milestones applied to this issue'
argument :assignee_username, GraphQL::STRING_TYPE,
required: false,
description: 'Username of a user assigned to the issues'
argument :assignee_id, GraphQL::STRING_TYPE,
required: false,
description: 'ID of a user assigned to the issues, "none" and "any" values supported'
argument :created_before, Types::TimeType,
required: false,
description: 'Issues created before this date'
argument :created_after, Types::TimeType,
required: false,
description: 'Issues created after this date'
argument :updated_before, Types::TimeType,
required: false,
description: 'Issues updated before this date'
argument :updated_after, Types::TimeType,
required: false,
description: 'Issues updated after this date'
argument :closed_before, Types::TimeType,
required: false,
description: 'Issues closed before this date'
argument :closed_after, Types::TimeType,
required: false,
description: 'Issues closed after this date'
argument :search, GraphQL::STRING_TYPE,
required: false,
description: 'Search query for issue title or description'
argument :types, [Types::IssueTypeEnum],
as: :issue_types,
description: 'Filter issues by the given issue types',
required: false
end
end
end
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
module Resolvers module Resolvers
class IssueStatusCountsResolver < BaseResolver class IssueStatusCountsResolver < BaseResolver
prepend Resolvers::IssueResolverFields prepend IssueResolverFields
type Types::IssueStatusCountsType, null: true type Types::IssueStatusCountsType, null: true
......
...@@ -4,6 +4,9 @@ module Resolvers ...@@ -4,6 +4,9 @@ module Resolvers
class IssuesResolver < BaseResolver class IssuesResolver < BaseResolver
prepend Resolvers::IssueResolverFields prepend Resolvers::IssueResolverFields
argument :state, Types::IssuableStateEnum,
required: false,
description: 'Current state of this issue'
argument :sort, Types::IssueSortEnum, argument :sort, Types::IssueSortEnum,
description: 'Sort issues by this criteria', description: 'Sort issues by this criteria',
required: false, required: false,
......
...@@ -7,11 +7,13 @@ module Types ...@@ -7,11 +7,13 @@ module Types
authorize :read_issue authorize :read_issue
::Gitlab::IssuablesCountForState::STATES.each do |status| ::Gitlab::IssuablesCountForState::STATES.each do |state|
field status, next unless Issue.available_states.keys.push('all').include?(state)
field state,
GraphQL::INT_TYPE, GraphQL::INT_TYPE,
null: true, null: true,
description: "Number of issues with status #{status.upcase} for the project" description: "Number of issues with status #{state.upcase} for the project"
end end
end end
end end
--- ---
title: Add status counts to Issues in GraphQL title: Add issue status counts to Projects in GraphQL
merge_request: 38263 merge_request: 38263
author: author:
type: added type: added
...@@ -7266,11 +7266,6 @@ type IssueStatusCountsType { ...@@ -7266,11 +7266,6 @@ type IssueStatusCountsType {
""" """
closed: Int closed: Int
"""
Number of issues with status MERGED for the project
"""
merged: Int
""" """
Number of issues with status OPENED for the project Number of issues with status OPENED for the project
""" """
...@@ -10357,11 +10352,6 @@ type Project { ...@@ -10357,11 +10352,6 @@ type Project {
""" """
search: String search: String
"""
Current state of this issue
"""
state: IssuableState
""" """
Filter issues by the given issue types Filter issues by the given issue types
""" """
......
...@@ -15599,16 +15599,6 @@ ...@@ -15599,16 +15599,6 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "state",
"description": "Current state of this issue",
"type": {
"kind": "ENUM",
"name": "IssuableState",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "labelName", "name": "labelName",
"description": "Labels applied to this issue", "description": "Labels applied to this issue",
...@@ -15745,6 +15735,16 @@ ...@@ -15745,6 +15735,16 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "state",
"description": "Current state of this issue",
"type": {
"kind": "ENUM",
"name": "IssuableState",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "sort", "name": "sort",
"description": "Sort issues by this criteria", "description": "Sort issues by this criteria",
...@@ -20034,20 +20034,6 @@ ...@@ -20034,20 +20034,6 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "merged",
"description": "Number of issues with status MERGED for the project",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "opened", "name": "opened",
"description": "Number of issues with status OPENED for the project", "description": "Number of issues with status OPENED for the project",
...@@ -30529,16 +30515,6 @@ ...@@ -30529,16 +30515,6 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "state",
"description": "Current state of this issue",
"type": {
"kind": "ENUM",
"name": "IssuableState",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "labelName", "name": "labelName",
"description": "Labels applied to this issue", "description": "Labels applied to this issue",
...@@ -30675,6 +30651,16 @@ ...@@ -30675,6 +30651,16 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "state",
"description": "Current state of this issue",
"type": {
"kind": "ENUM",
"name": "IssuableState",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "sort", "name": "sort",
"description": "Sort issues by this criteria", "description": "Sort issues by this criteria",
...@@ -30740,16 +30726,6 @@ ...@@ -30740,16 +30726,6 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "state",
"description": "Current state of this issue",
"type": {
"kind": "ENUM",
"name": "IssuableState",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "labelName", "name": "labelName",
"description": "Labels applied to this issue", "description": "Labels applied to this issue",
...@@ -30927,16 +30903,6 @@ ...@@ -30927,16 +30903,6 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "state",
"description": "Current state of this issue",
"type": {
"kind": "ENUM",
"name": "IssuableState",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "labelName", "name": "labelName",
"description": "Labels applied to this issue", "description": "Labels applied to this issue",
...@@ -31073,6 +31039,16 @@ ...@@ -31073,6 +31039,16 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "state",
"description": "Current state of this issue",
"type": {
"kind": "ENUM",
"name": "IssuableState",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "sort", "name": "sort",
"description": "Sort issues by this criteria", "description": "Sort issues by this criteria",
...@@ -1112,7 +1112,6 @@ Represents total number of issues for the represented statuses ...@@ -1112,7 +1112,6 @@ Represents total number of issues for the represented statuses
| --- | ---- | ---------- | | --- | ---- | ---------- |
| `all` | Int | Number of issues with status ALL for the project | | `all` | Int | Number of issues with status ALL for the project |
| `closed` | Int | Number of issues with status CLOSED for the project | | `closed` | Int | Number of issues with status CLOSED for the project |
| `merged` | Int | Number of issues with status MERGED for the project |
| `opened` | Int | Number of issues with status OPENED for the project | | `opened` | Int | Number of issues with status OPENED for the project |
## Iteration ## Iteration
......
...@@ -26,9 +26,9 @@ module Gitlab ...@@ -26,9 +26,9 @@ module Gitlab
self[state || :opened] self[state || :opened]
end end
# Define method for each status # Define method for each state
STATES.each do |status| STATES.each do |state|
define_method(status) { self[status] } define_method(state) { self[state] }
end end
# Returns the count for the given state. # Returns the count for the given state.
......
...@@ -8,13 +8,53 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do ...@@ -8,13 +8,53 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do
describe '#resolve' do describe '#resolve' do
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago) }
let_it_be(:incident) { create(:incident, project: project, state: :closed, created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago) }
let(:args) { {} } let(:args) { {} }
before do
project.add_developer(current_user)
end
subject { resolve_issue_status_counts(args) } subject { resolve_issue_status_counts(args) }
it { is_expected.to be_a(Gitlab::IssuablesCountForState) } it { is_expected.to be_a(Gitlab::IssuablesCountForState) }
specify { expect(subject.project).to eq(project) } specify { expect(subject.project).to eq(project) }
it 'returns expected results' do
result = resolve_issue_status_counts
expect(result.all).to eq 2
expect(result.opened).to eq 1
expect(result.closed).to eq 1
end
it 'filters by search', :aggregate_failures do
result = resolve_issue_status_counts(search: issue.title)
expect(result.all).to eq 1
expect(result.opened).to eq 1
expect(result.closed).to eq 0
end
it 'filters by issue type', :aggregate_failures do
result = resolve_issue_status_counts(issue_types: ['incident'])
expect(result.all).to eq 1
expect(result.opened).to eq 0
expect(result.closed).to eq 1
end
# The state param is ignored in IssuableFinder#count_by_state
it 'ignores state filter', :aggregate_failures do
result = resolve_issue_status_counts(state: 'closed')
expect(result.all).to eq 2
expect(result.opened).to eq 1
expect(result.closed).to eq 1
end
private private
def resolve_issue_status_counts(args = {}, context = { current_user: current_user }) def resolve_issue_status_counts(args = {}, context = { current_user: current_user })
......
...@@ -10,7 +10,6 @@ RSpec.describe GitlabSchema.types['IssueStatusCountsType'] do ...@@ -10,7 +10,6 @@ RSpec.describe GitlabSchema.types['IssueStatusCountsType'] do
all all
opened opened
closed closed
merged
] ]
expect(described_class).to have_graphql_fields(*expected_fields) expect(described_class).to have_graphql_fields(*expected_fields)
......
...@@ -50,9 +50,8 @@ RSpec.describe 'getting Issue counts by status' do ...@@ -50,9 +50,8 @@ RSpec.describe 'getting Issue counts by status' do
expect(issue_counts).to eq( expect(issue_counts).to eq(
'all' => 2, 'all' => 2,
'opened' => 1, 'opened' => 1,
'closed' => 1, 'closed' => 1
'merged' => 0 # merged is not relevant for issues )
) # but is included in the return type (Gitlab::IssuablesCountForState)
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