debian-mirror-gitlab/spec/graphql/resolvers/merge_requests_resolver_spec.rb

379 lines
13 KiB
Ruby
Raw Normal View History

2019-12-21 20:55:43 +05:30
# frozen_string_literal: true
2018-11-08 19:23:39 +05:30
require 'spec_helper'
2020-07-28 23:09:34 +05:30
RSpec.describe Resolvers::MergeRequestsResolver do
2018-11-08 19:23:39 +05:30
include GraphqlHelpers
2021-03-11 19:13:27 +05:30
include SortingHelper
2018-11-08 19:23:39 +05:30
2020-04-08 14:13:33 +05:30
let_it_be(:project) { create(:project, :repository) }
2021-04-29 21:17:54 +05:30
let_it_be(:other_project) { create(:project, :repository) }
2020-11-24 15:15:51 +05:30
let_it_be(:milestone) { create(:milestone, project: project) }
2020-06-23 00:09:42 +05:30
let_it_be(:current_user) { create(:user) }
2020-11-24 15:15:51 +05:30
let_it_be(:other_user) { create(:user) }
2020-06-23 00:09:42 +05:30
let_it_be(:common_attrs) { { author: current_user, source_project: project, target_project: project } }
let_it_be(:merge_request_1) { create(:merge_request, :simple, **common_attrs) }
let_it_be(:merge_request_2) { create(:merge_request, :rebased, **common_attrs) }
let_it_be(:merge_request_3) { create(:merge_request, :unique_branches, **common_attrs) }
let_it_be(:merge_request_4) { create(:merge_request, :unique_branches, :locked, **common_attrs) }
let_it_be(:merge_request_5) { create(:merge_request, :simple, :locked, **common_attrs) }
2021-04-29 21:17:54 +05:30
let_it_be(:merge_request_6) do
create(:labeled_merge_request, :unique_branches, **common_attrs, labels: create_list(:label, 2, project: project))
end
let_it_be(:merge_request_with_milestone) do
create(:merge_request, :unique_branches, **common_attrs, milestone: milestone)
end
let_it_be(:other_merge_request) do
create(:merge_request, source_project: other_project, target_project: other_project)
end
2020-11-24 15:15:51 +05:30
2018-11-08 19:23:39 +05:30
let(:iid_1) { merge_request_1.iid }
let(:iid_2) { merge_request_2.iid }
let(:other_iid) { other_merge_request.iid }
2020-06-23 00:09:42 +05:30
before do
project.add_developer(current_user)
2020-07-28 23:09:34 +05:30
other_project.add_developer(current_user)
2020-06-23 00:09:42 +05:30
end
2018-11-08 19:23:39 +05:30
describe '#resolve' do
2021-03-11 19:13:27 +05:30
# One for the initial auth, then MRs, and the load of project and project_feature (for further auth):
# SELECT MAX("project_authorizations"."access_level") AS maximum_access_level,
# "project_authorizations"."user_id" AS project_authorizations_user_id
# FROM "project_authorizations"
# WHERE "project_authorizations"."project_id" = 2 AND "project_authorizations"."user_id" = 2
# GROUP BY "project_authorizations"."user_id"
# SELECT "merge_requests".* FROM "merge_requests" WHERE "merge_requests"."target_project_id" = 2
# AND "merge_requests"."iid" = 1 ORDER BY "merge_requests"."id" DESC
# SELECT "projects".* FROM "projects" WHERE "projects"."id" = 2
# SELECT "project_features".* FROM "project_features" WHERE "project_features"."project_id" = 2
2021-04-29 21:17:54 +05:30
let(:queries_per_project) { 4 }
2020-07-28 23:09:34 +05:30
2021-04-29 21:17:54 +05:30
context 'without arguments' do
2020-06-23 00:09:42 +05:30
it 'returns all merge requests' do
2021-01-29 00:20:46 +05:30
result = resolve_mr(project)
2020-06-23 00:09:42 +05:30
2021-04-29 21:17:54 +05:30
expect(result).to contain_exactly(
merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5,
merge_request_6, merge_request_with_milestone
)
2019-07-07 11:18:12 +05:30
end
2020-06-23 00:09:42 +05:30
it 'returns only merge requests that the current user can see' do
2021-01-29 00:20:46 +05:30
result = resolve_mr(project, user: build(:user))
2020-06-23 00:09:42 +05:30
expect(result).to be_empty
end
2019-07-07 11:18:12 +05:30
end
2021-04-29 21:17:54 +05:30
context 'with iid alone' do
2020-07-28 23:09:34 +05:30
it 'batch-resolves by target project full path and individual IID', :request_store do
# 1 query for project_authorizations, and 1 for merge_requests
result = batch_sync(max_queries: queries_per_project) do
2020-06-23 00:09:42 +05:30
[iid_1, iid_2].map { |iid| resolve_mr_single(project, iid) }
end
expect(result).to contain_exactly(merge_request_1, merge_request_2)
end
2020-07-28 23:09:34 +05:30
it 'batch-resolves by target project full path and IIDS', :request_store do
result = batch_sync(max_queries: queries_per_project) do
2021-04-17 20:07:23 +05:30
resolve_mr(project, iids: [iid_1, iid_2]).to_a
2020-06-23 00:09:42 +05:30
end
expect(result).to contain_exactly(merge_request_1, merge_request_2)
end
2020-07-28 23:09:34 +05:30
it 'batch-resolves by target project full path and IIDS, single or plural', :request_store do
result = batch_sync(max_queries: queries_per_project) do
[resolve_mr_single(project, merge_request_3.iid), *resolve_mr(project, iids: [iid_1, iid_2])]
end
expect(result).to contain_exactly(merge_request_1, merge_request_2, merge_request_3)
end
2021-04-29 21:17:54 +05:30
it 'can batch-resolve merge requests from different projects', :request_store do
2020-07-28 23:09:34 +05:30
# 2 queries for project_authorizations, and 2 for merge_requests
2021-03-11 19:13:27 +05:30
results = batch_sync(max_queries: queries_per_project * 2) do
a = resolve_mr(project, iids: [iid_1])
b = resolve_mr(project, iids: [iid_2])
c = resolve_mr(other_project, iids: [other_iid])
[a, b, c].flat_map(&:to_a)
2020-06-23 00:09:42 +05:30
end
2021-03-11 19:13:27 +05:30
expect(results).to contain_exactly(merge_request_1, merge_request_2, other_merge_request)
2020-06-23 00:09:42 +05:30
end
it 'resolves an unknown iid to be empty' do
result = batch_sync { resolve_mr_single(project, -1) }
expect(result).to be_nil
2018-11-08 19:23:39 +05:30
end
2020-06-23 00:09:42 +05:30
it 'resolves empty iids to be empty' do
result = batch_sync { resolve_mr(project, iids: []) }
expect(result).to be_empty
end
it 'resolves an unknown project to be nil when single' do
result = batch_sync { resolve_mr_single(nil, iid_1) }
expect(result).to be_nil
end
it 'resolves an unknown project to be empty' do
result = batch_sync { resolve_mr(nil, iids: [iid_1]) }
expect(result).to be_empty
end
2018-11-08 19:23:39 +05:30
end
2021-04-29 21:17:54 +05:30
context 'with source branches argument' do
2020-06-23 00:09:42 +05:30
it 'takes one argument' do
2021-02-22 17:27:13 +05:30
result = resolve_mr(project, source_branches: [merge_request_3.source_branch])
2020-06-23 00:09:42 +05:30
expect(result).to contain_exactly(merge_request_3)
2018-11-08 19:23:39 +05:30
end
2020-06-23 00:09:42 +05:30
it 'takes more than one argument' do
mrs = [merge_request_3, merge_request_4]
branches = mrs.map(&:source_branch)
2021-04-29 21:17:54 +05:30
result = resolve_mr(project, source_branches: branches)
2020-06-23 00:09:42 +05:30
expect(result).to match_array(mrs)
end
2018-11-08 19:23:39 +05:30
end
2021-04-29 21:17:54 +05:30
context 'with target branches argument' do
2020-06-23 00:09:42 +05:30
it 'takes one argument' do
2021-02-22 17:27:13 +05:30
result = resolve_mr(project, target_branches: [merge_request_3.target_branch])
2020-06-23 00:09:42 +05:30
expect(result).to contain_exactly(merge_request_3)
end
2019-07-07 11:18:12 +05:30
2020-06-23 00:09:42 +05:30
it 'takes more than one argument' do
mrs = [merge_request_3, merge_request_4]
branches = mrs.map(&:target_branch)
2021-03-11 19:13:27 +05:30
result = resolve_mr(project, target_branches: branches)
2020-06-23 00:09:42 +05:30
2021-03-11 19:13:27 +05:30
expect(result).to match_array(mrs)
2020-06-23 00:09:42 +05:30
end
2019-07-07 11:18:12 +05:30
end
2021-04-29 21:17:54 +05:30
context 'with state argument' do
2020-06-23 00:09:42 +05:30
it 'takes one argument' do
result = resolve_mr(project, state: 'locked')
2018-11-08 19:23:39 +05:30
2020-06-23 00:09:42 +05:30
expect(result).to contain_exactly(merge_request_4, merge_request_5)
end
2018-11-08 19:23:39 +05:30
end
2020-04-22 19:07:51 +05:30
2021-04-29 21:17:54 +05:30
context 'with label argument' do
2020-06-23 00:09:42 +05:30
let_it_be(:label) { merge_request_6.labels.first }
let_it_be(:with_label) { create(:labeled_merge_request, :closed, labels: [label], **common_attrs) }
2020-04-22 19:07:51 +05:30
2020-06-23 00:09:42 +05:30
it 'takes one argument' do
2021-02-22 17:27:13 +05:30
result = resolve_mr(project, labels: [label.title])
2020-06-23 00:09:42 +05:30
expect(result).to contain_exactly(merge_request_6, with_label)
end
it 'takes multiple arguments, with semantics of ALL MUST MATCH' do
2021-02-22 17:27:13 +05:30
result = resolve_mr(project, labels: merge_request_6.labels.map(&:title))
2020-06-23 00:09:42 +05:30
expect(result).to contain_exactly(merge_request_6)
end
end
2021-04-29 21:17:54 +05:30
context 'with negated label argument' do
let_it_be(:label) { merge_request_6.labels.first }
let_it_be(:with_label) { create(:labeled_merge_request, :closed, labels: [label], **common_attrs) }
it 'excludes merge requests with given label from selection' do
result = resolve_mr(project, not: { labels: [label.title] })
expect(result).not_to include(merge_request_6, with_label)
end
end
context 'with merged_after and merged_before arguments' do
2020-10-24 23:57:45 +05:30
before do
merge_request_1.metrics.update!(merged_at: 10.days.ago)
end
it 'returns merge requests merged between the given period' do
result = resolve_mr(project, merged_after: 20.days.ago, merged_before: 5.days.ago)
2021-03-11 19:13:27 +05:30
expect(result).to contain_exactly(merge_request_1)
2020-10-24 23:57:45 +05:30
end
it 'does not return anything' do
result = resolve_mr(project, merged_after: 2.days.ago)
expect(result).to be_empty
end
end
2021-12-11 22:18:48 +05:30
context 'with created_after and created_before arguments' do
before do
merge_request_1.update!(created_at: 4.days.ago)
end
let(:all_mrs) do
[merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5, merge_request_6, merge_request_with_milestone]
end
it 'returns merge requests created within a given period' do
result = resolve_mr(project, created_after: 5.days.ago, created_before: 2.days.ago)
expect(result).to contain_exactly(
merge_request_1
)
end
it 'returns some values filtered with created_before' do
result = resolve_mr(project, created_before: 1.day.ago)
expect(result).to contain_exactly(merge_request_1)
end
it 'returns some values filtered with created_after' do
result = resolve_mr(project, created_after: 3.days.ago)
expect(result).to match_array(all_mrs - [merge_request_1])
end
it 'does not return anything for dates (even in the future) not matching any MRs' do
result = resolve_mr(project, created_after: 5.days.from_now)
expect(result).to be_empty
end
it 'does not return anything for dates not matching any MRs' do
result = resolve_mr(project, created_before: 15.days.ago)
expect(result).to be_empty
end
it 'does not return any values for an impossible set' do
result = resolve_mr(project, created_after: 5.days.ago, created_before: 6.days.ago)
expect(result).to be_empty
end
end
2021-04-29 21:17:54 +05:30
context 'with milestone argument' do
2020-11-24 15:15:51 +05:30
it 'filters merge requests by milestone title' do
result = resolve_mr(project, milestone_title: milestone.title)
2021-03-11 19:13:27 +05:30
expect(result).to contain_exactly(merge_request_with_milestone)
2020-11-24 15:15:51 +05:30
end
it 'does not find anything' do
result = resolve_mr(project, milestone_title: 'unknown-milestone')
expect(result).to be_empty
end
end
2021-04-29 21:17:54 +05:30
context 'with negated milestone argument' do
it 'filters out merge requests with given milestone title' do
result = resolve_mr(project, not: { milestone_title: milestone.title })
expect(result).not_to include(merge_request_with_milestone)
end
end
2020-06-23 00:09:42 +05:30
describe 'combinations' do
it 'requires all filters' do
2021-04-29 21:17:54 +05:30
create(:merge_request, :closed, **common_attrs, source_branch: merge_request_4.source_branch)
2020-06-23 00:09:42 +05:30
2021-02-22 17:27:13 +05:30
result = resolve_mr(project, source_branches: [merge_request_4.source_branch], state: 'locked')
2020-06-23 00:09:42 +05:30
2021-03-11 19:13:27 +05:30
expect(result).to contain_exactly(merge_request_4)
2020-06-23 00:09:42 +05:30
end
2020-04-22 19:07:51 +05:30
end
2020-11-24 15:15:51 +05:30
describe 'sorting' do
2021-03-11 19:13:27 +05:30
let(:mrs) do
[
merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4,
merge_request_3, merge_request_2, merge_request_1
]
end
2020-11-24 15:15:51 +05:30
context 'when sorting by created' do
it 'sorts merge requests ascending' do
2021-03-11 19:13:27 +05:30
expect(resolve_mr(project, sort: 'created_asc'))
.to match_array(mrs)
.and be_sorted(:created_at, :asc)
2020-11-24 15:15:51 +05:30
end
it 'sorts merge requests descending' do
2021-03-11 19:13:27 +05:30
expect(resolve_mr(project, sort: 'created_desc'))
.to match_array(mrs)
.and be_sorted(:created_at, :desc)
2020-11-24 15:15:51 +05:30
end
end
context 'when sorting by merged at' do
before do
merge_request_1.metrics.update!(merged_at: 10.days.ago)
merge_request_3.metrics.update!(merged_at: 5.days.ago)
end
it 'sorts merge requests ascending' do
2021-03-11 19:13:27 +05:30
expect(resolve_mr(project, sort: :merged_at_asc))
.to match_array(mrs)
.and be_sorted(->(mr) { [merged_at(mr), -mr.id] })
2020-11-24 15:15:51 +05:30
end
it 'sorts merge requests descending' do
2021-03-11 19:13:27 +05:30
expect(resolve_mr(project, sort: :merged_at_desc))
.to match_array(mrs)
.and be_sorted(->(mr) { [-merged_at(mr), -mr.id] })
end
def merged_at(mr)
nils_last(mr.metrics.merged_at)
2020-11-24 15:15:51 +05:30
end
2021-03-08 18:12:59 +05:30
2021-10-27 15:23:28 +05:30
context 'when sorting by closed at' do
before do
merge_request_1.metrics.update!(latest_closed_at: 10.days.ago)
merge_request_3.metrics.update!(latest_closed_at: 5.days.ago)
end
it 'sorts merge requests ascending' do
expect(resolve_mr(project, sort: :closed_at_asc))
.to match_array(mrs)
.and be_sorted(->(mr) { [closed_at(mr), -mr.id] })
end
it 'sorts merge requests descending' do
expect(resolve_mr(project, sort: :closed_at_desc))
.to match_array(mrs)
.and be_sorted(->(mr) { [-closed_at(mr), -mr.id] })
end
def closed_at(mr)
nils_last(mr.metrics.latest_closed_at)
end
end
2020-11-24 15:15:51 +05:30
end
end
2018-11-08 19:23:39 +05:30
end
2020-06-23 00:09:42 +05:30
def resolve_mr_single(project, iid)
2021-02-22 17:27:13 +05:30
resolve_mr(project, resolver: described_class.single, iid: iid.to_s)
2020-06-23 00:09:42 +05:30
end
2021-01-29 00:20:46 +05:30
def resolve_mr(project, resolver: described_class, user: current_user, **args)
2020-06-23 00:09:42 +05:30
resolve(resolver, obj: project, args: args, ctx: { current_user: user })
2018-11-08 19:23:39 +05:30
end
end