summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/graphql/loaders/issuable_loader_spec.rb
blob: 180966de8958eb7cc8e094e24c9275262a3c12b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Gitlab::Graphql::Loaders::IssuableLoader do
  subject { described_class.new(parent, finder) }

  let(:params) { HashWithIndifferentAccess.new }

  describe '#find_all' do
    let(:finder) { double(:finder, params: params, execute: %i[x y z]) }

    where(:factory, :param_name) do
      %i[project group].map { |thing| [thing, :"#{thing}_id"] }
    end

    with_them do
      let(:parent) { build_stubbed(factory) }

      it 'assignes the parent parameter, and batching_find_alls the finder' do
        expect(subject.find_all).to contain_exactly(:x, :y, :z)
        expect(params).to include(param_name => parent)
      end
    end

    context 'the parent is of an unexpected type' do
      let(:parent) { build(:merge_request) }

      it 'raises an error if we pass an unexpected parent' do
        expect { subject.find_all }.to raise_error(/Unexpected parent/)
      end
    end
  end

  describe '#batching_find_all' do
    context 'the finder params are anything other than [iids]' do
      let(:finder) { double(:finder, params: params, execute: [:foo]) }
      let(:parent) { build_stubbed(:project) }

      it 'batching_find_alls the finder, setting the correct parent parameter' do
        expect(subject.batching_find_all).to eq([:foo])
        expect(params[:project_id]).to eq(parent)
      end

      it 'allows a post-process block' do
        expect(subject.batching_find_all(&:first)).to eq(:foo)
      end
    end

    context 'the finder params are exactly [iids]' do
      # Dumb finder class, that only implements what we need, and has
      # predictable query counts.
      let(:finder_class) do
        Class.new do
          attr_reader :current_user, :params

          def initialize(user, args)
            @current_user = user
            @params = HashWithIndifferentAccess.new(args.to_h)
          end

          def execute
            params[:project_id].issues.where(iid: params[:iids])
          end
        end
      end

      it 'batches requests' do
        issue_a = create(:issue)
        issue_b = create(:issue)
        issue_c = create(:issue, project: issue_a.project)
        proj_1 = issue_a.project
        proj_2 = issue_b.project
        user = create(:user, developer_projects: [proj_1, proj_2])

        finder_a = finder_class.new(user, iids: [issue_a.iid])
        finder_b = finder_class.new(user, iids: [issue_b.iid])
        finder_c = finder_class.new(user, iids: [issue_c.iid])

        results = []

        expect do
          results.concat(described_class.new(proj_1, finder_a).batching_find_all)
          results.concat(described_class.new(proj_2, finder_b).batching_find_all)
          results.concat(described_class.new(proj_1, finder_c).batching_find_all)
        end.not_to exceed_query_limit(0)

        expect do
          results = results.map(&:sync)
        end.not_to exceed_query_limit(2)

        expect(results).to contain_exactly(issue_a, issue_b, issue_c)
      end
    end
  end
end