summaryrefslogtreecommitdiff
path: root/spec/services/packages/create_dependency_service_spec.rb
blob: 55414ea68fe3cc0270da42f82316bdd25d40dac3 (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# frozen_string_literal: true
require 'spec_helper'

RSpec.describe Packages::CreateDependencyService do
  describe '#execute' do
    let_it_be(:namespace) {create(:namespace)}
    let_it_be(:version) { '1.0.1' }
    let_it_be(:package_name) { "@#{namespace.path}/my-app" }

    context 'when packages are published' do
      let(:json_file) { 'packages/npm/payload.json' }
      let(:params) do
        Gitlab::Json.parse(fixture_file(json_file)
                .gsub('@root/npm-test', package_name)
                .gsub('1.0.1', version))
                .with_indifferent_access
      end

      let(:package_version) { params[:versions].each_key.first }
      let(:dependencies) { params[:versions][package_version] }
      let(:package) { create(:npm_package) }
      let(:dependency_names) { package.dependency_links.flat_map(&:dependency).map(&:name).sort }
      let(:dependency_link_types) { package.dependency_links.map(&:dependency_type).sort }

      subject { described_class.new(package, dependencies).execute }

      it 'creates dependencies and links' do
        expect(Packages::Dependency)
            .to receive(:ids_for_package_names_and_version_patterns)
            .once
            .and_call_original

        expect { subject }
          .to change { Packages::Dependency.count }.by(1)
          .and change { Packages::DependencyLink.count }.by(1)
        expect(dependency_names).to match_array(%w(express))
        expect(dependency_link_types).to match_array(%w(dependencies))
      end

      context 'with repeated packages' do
        let(:json_file) { 'packages/npm/payload_with_duplicated_packages.json' }

        it 'creates dependencies and links' do
          expect(Packages::Dependency)
            .to receive(:ids_for_package_names_and_version_patterns)
            .exactly(4).times
            .and_call_original

          expect { subject }
            .to change { Packages::Dependency.count }.by(4)
            .and change { Packages::DependencyLink.count }.by(6)
          expect(dependency_names).to match_array(%w(d3 d3 d3 dagre-d3 dagre-d3 express))
          expect(dependency_link_types).to match_array(%w(bundleDependencies dependencies dependencies devDependencies devDependencies peerDependencies))
        end
      end

      context 'with dependencies bulk insert conflicts' do
        let_it_be(:rows) { [{ name: 'express', version_pattern: '^4.16.4' }] }

        it 'creates dependences and links' do
          original_bulk_insert = ::ApplicationRecord.method(:legacy_bulk_insert)
          expect(::ApplicationRecord)
            .to receive(:legacy_bulk_insert) do |table, rows, return_ids: false, disable_quote: [], on_conflict: nil|
              call_count = table == Packages::Dependency.table_name ? 2 : 1
              call_count.times { original_bulk_insert.call(table, rows, return_ids: return_ids, disable_quote: disable_quote, on_conflict: on_conflict) }
            end.twice
          expect(Packages::Dependency)
            .to receive(:ids_for_package_names_and_version_patterns)
            .twice
            .and_call_original

          expect { subject }
            .to change { Packages::Dependency.count }.by(1)
            .and change { Packages::DependencyLink.count }.by(1)
          expect(dependency_names).to match_array(%w(express))
          expect(dependency_link_types).to match_array(%w(dependencies))
        end
      end

      context 'with existing dependencies' do
        let(:other_package) { create(:npm_package) }

        before do
          described_class.new(other_package, dependencies).execute
        end

        it 'reuses them' do
          expect { subject }
            .to not_change { Packages::Dependency.count }
            .and change { Packages::DependencyLink.count }.by(1)
        end
      end

      context 'with a dependency not described with a hash' do
        let(:invalid_dependencies) { dependencies.tap { |d| d['bundleDependencies'] = false } }

        subject { described_class.new(package, invalid_dependencies).execute }

        it 'creates dependencies and links' do
          expect(Packages::Dependency)
              .to receive(:ids_for_package_names_and_version_patterns)
              .once
              .and_call_original

          expect { subject }
            .to change { Packages::Dependency.count }.by(1)
            .and change { Packages::DependencyLink.count }.by(1)
          expect(dependency_names).to match_array(%w(express))
          expect(dependency_link_types).to match_array(%w(dependencies))
        end
      end
    end
  end
end