File: create_dependency_service_spec.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (140 lines) | stat: -rw-r--r-- 5,465 bytes parent folder | download
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Packages::CreateDependencyService, feature_category: :package_registry 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_project_id_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_project_id_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_project_id_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(:name_and_version_pattern) { dependencies['dependencies'].to_a.flatten }

        let!(:dependency) do
          create(
            :packages_dependency,
            name: name_and_version_pattern[0],
            version_pattern: name_and_version_pattern[1],
            project: project
          )
        end

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

        context 'with project' do
          context 'in the same project' do
            let(:project) { package.project }

            it_behaves_like 'reuses dependencies'
          end

          context 'in the different project' do
            let_it_be(:project) { create(:project) }

            it 'does not reuse them' do
              expect { subject }
                .to change { Packages::Dependency.count }.by(1)
                .and change { Packages::DependencyLink.count }.by(1)
            end
          end
        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_project_id_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