Commit 36d62cd4 authored by Jan Provaznik's avatar Jan Provaznik

Merge branch '335496-expose-mergerequestscount-field-in-graphql-issue-type' into 'master'

Expose `mergeRequestsCount` field in GraphQL Issue type

See merge request gitlab-org/gitlab!65931
parents 5e292260 3645688b
# frozen_string_literal: true
module Resolvers
class MergeRequestsCountResolver < BaseResolver
type GraphQL::Types::Int, null: true
def resolve
BatchLoader::GraphQL.for(object.id).batch do |ids, loader, args|
counts = MergeRequestsClosingIssues.count_for_collection(ids, context[:current_user]).to_h
ids.each do |id|
loader.call(id, counts[id] || 0)
end
end
end
end
end
...@@ -60,6 +60,9 @@ module Types ...@@ -60,6 +60,9 @@ module Types
description: 'Number of upvotes the issue has received.' description: 'Number of upvotes the issue has received.'
field :downvotes, GraphQL::Types::Int, null: false, field :downvotes, GraphQL::Types::Int, null: false,
description: 'Number of downvotes the issue has received.' description: 'Number of downvotes the issue has received.'
field :merge_requests_count, GraphQL::Types::Int, null: false,
description: 'Number of merge requests that close the issue on merge.',
resolver: Resolvers::MergeRequestsCountResolver
field :user_notes_count, GraphQL::Types::Int, null: false, field :user_notes_count, GraphQL::Types::Int, null: false,
description: 'Number of user notes of the issue.', description: 'Number of user notes of the issue.',
resolver: Resolvers::UserNotesCountResolver resolver: Resolvers::UserNotesCountResolver
......
...@@ -9080,6 +9080,7 @@ Relationship between an epic and an issue. ...@@ -9080,6 +9080,7 @@ Relationship between an epic and an issue.
| <a id="epicissueiid"></a>`iid` | [`ID!`](#id) | Internal ID of the issue. | | <a id="epicissueiid"></a>`iid` | [`ID!`](#id) | Internal ID of the issue. |
| <a id="epicissueiteration"></a>`iteration` | [`Iteration`](#iteration) | Iteration of the issue. | | <a id="epicissueiteration"></a>`iteration` | [`Iteration`](#iteration) | Iteration of the issue. |
| <a id="epicissuelabels"></a>`labels` | [`LabelConnection`](#labelconnection) | Labels of the issue. (see [Connections](#connections)) | | <a id="epicissuelabels"></a>`labels` | [`LabelConnection`](#labelconnection) | Labels of the issue. (see [Connections](#connections)) |
| <a id="epicissuemergerequestscount"></a>`mergeRequestsCount` | [`Int!`](#int) | Number of merge requests that close the issue on merge. |
| <a id="epicissuemetricimages"></a>`metricImages` | [`[MetricImage!]`](#metricimage) | Metric images associated to the issue. | | <a id="epicissuemetricimages"></a>`metricImages` | [`[MetricImage!]`](#metricimage) | Metric images associated to the issue. |
| <a id="epicissuemilestone"></a>`milestone` | [`Milestone`](#milestone) | Milestone of the issue. | | <a id="epicissuemilestone"></a>`milestone` | [`Milestone`](#milestone) | Milestone of the issue. |
| <a id="epicissuemoved"></a>`moved` | [`Boolean`](#boolean) | Indicates if issue got moved from other project. | | <a id="epicissuemoved"></a>`moved` | [`Boolean`](#boolean) | Indicates if issue got moved from other project. |
...@@ -10153,6 +10154,7 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount). ...@@ -10153,6 +10154,7 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
| <a id="issueiid"></a>`iid` | [`ID!`](#id) | Internal ID of the issue. | | <a id="issueiid"></a>`iid` | [`ID!`](#id) | Internal ID of the issue. |
| <a id="issueiteration"></a>`iteration` | [`Iteration`](#iteration) | Iteration of the issue. | | <a id="issueiteration"></a>`iteration` | [`Iteration`](#iteration) | Iteration of the issue. |
| <a id="issuelabels"></a>`labels` | [`LabelConnection`](#labelconnection) | Labels of the issue. (see [Connections](#connections)) | | <a id="issuelabels"></a>`labels` | [`LabelConnection`](#labelconnection) | Labels of the issue. (see [Connections](#connections)) |
| <a id="issuemergerequestscount"></a>`mergeRequestsCount` | [`Int!`](#int) | Number of merge requests that close the issue on merge. |
| <a id="issuemetricimages"></a>`metricImages` | [`[MetricImage!]`](#metricimage) | Metric images associated to the issue. | | <a id="issuemetricimages"></a>`metricImages` | [`[MetricImage!]`](#metricimage) | Metric images associated to the issue. |
| <a id="issuemilestone"></a>`milestone` | [`Milestone`](#milestone) | Milestone of the issue. | | <a id="issuemilestone"></a>`milestone` | [`Milestone`](#milestone) | Milestone of the issue. |
| <a id="issuemoved"></a>`moved` | [`Boolean`](#boolean) | Indicates if issue got moved from other project. | | <a id="issuemoved"></a>`moved` | [`Boolean`](#boolean) | Indicates if issue got moved from other project. |
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::MergeRequestsCountResolver do
include GraphqlHelpers
describe '#resolve' do
let_it_be(:user) { create(:user) }
let_it_be(:project1) { create(:project, :repository, :public) }
let_it_be(:project2) { create(:project, :repository, repository_access_level: ProjectFeature::PRIVATE) }
let_it_be(:issue) { create(:issue, project: project1) }
let_it_be(:merge_request_closing_issue1) { create(:merge_requests_closing_issues, issue: issue) }
let_it_be(:merge_request_closing_issue2) do
merge_request = create(:merge_request, source_project: project2)
create(:merge_requests_closing_issues, issue: issue, merge_request: merge_request)
end
specify do
expect(described_class).to have_nullable_graphql_type(GraphQL::Types::Int)
end
subject { batch_sync { resolve_merge_requests_count(issue) } }
context "when user can only view an issue's closing merge requests that are public" do
it 'returns the count of the merge requests closing the issue' do
expect(subject).to eq(1)
end
end
context "when user can view an issue's closing merge requests that are both public and private" do
before do
project2.add_reporter(user)
end
it 'returns the count of the merge requests closing the issue' do
expect(subject).to eq(2)
end
end
end
def resolve_merge_requests_count(obj)
resolve(described_class, obj: obj, ctx: { current_user: user })
end
end
...@@ -15,7 +15,7 @@ RSpec.describe GitlabSchema.types['Issue'] do ...@@ -15,7 +15,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
it 'has specific fields' do it 'has specific fields' do
fields = %i[id iid title description state reference author assignees updated_by participants labels milestone due_date fields = %i[id iid title description state reference author assignees updated_by participants labels milestone due_date
confidential discussion_locked upvotes downvotes user_notes_count user_discussions_count web_path web_url relative_position confidential discussion_locked upvotes downvotes merge_requests_count user_notes_count user_discussions_count web_path web_url relative_position
emails_disabled subscribed time_estimate total_time_spent human_time_estimate human_total_time_spent closed_at created_at updated_at task_completion_status emails_disabled subscribed time_estimate total_time_spent human_time_estimate human_total_time_spent closed_at created_at updated_at task_completion_status
design_collection alert_management_alert severity current_user_todos moved moved_to design_collection alert_management_alert severity current_user_todos moved moved_to
create_note_email timelogs project_id] create_note_email timelogs project_id]
......
...@@ -476,6 +476,17 @@ RSpec.describe 'getting an issue list for a project' do ...@@ -476,6 +476,17 @@ RSpec.describe 'getting an issue list for a project' do
include_examples 'N+1 query check' include_examples 'N+1 query check'
end end
context 'when requesting `merge_requests_count`' do
let(:requested_fields) { [:merge_requests_count] }
before do
create_list(:merge_requests_closing_issues, 2, issue: issue_a)
create_list(:merge_requests_closing_issues, 3, issue: issue_b)
end
include_examples 'N+1 query check'
end
context 'when requesting `timelogs`' do context 'when requesting `timelogs`' do
let(:requested_fields) { 'timelogs { nodes { timeSpent } }' } let(:requested_fields) { 'timelogs { nodes { timeSpent } }' }
......
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