Welcome to mirror list, hosted at ThFree Co, Russian Federation.

predictive_tests_spec.rb « tooling « lib « tooling « spec - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b82364fe6f60bbb049711ed9374d4ee04372630f (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# frozen_string_literal: true

require 'tempfile'
require 'fileutils'
require_relative '../../../../tooling/lib/tooling/predictive_tests'
require_relative '../../../support/helpers/stub_env'

RSpec.describe Tooling::PredictiveTests, feature_category: :tooling do
  include StubENV

  let(:instance)                       { described_class.new }
  let(:matching_tests_initial_content) { 'initial_matching_spec' }
  let(:fixtures_mapping_content)       { '{}' }

  attr_accessor :changed_files, :changed_files_path, :fixtures_mapping,
    :matching_js_files, :matching_tests, :views_with_partials

  around do |example|
    self.changed_files       = Tempfile.new('test-folder/changed_files.txt')
    self.changed_files_path  = changed_files.path
    self.fixtures_mapping    = Tempfile.new('test-folder/fixtures_mapping.txt')
    self.matching_js_files   = Tempfile.new('test-folder/matching_js_files.txt')
    self.matching_tests      = Tempfile.new('test-folder/matching_tests.txt')
    self.views_with_partials = Tempfile.new('test-folder/views_with_partials.txt')

    # See https://ruby-doc.org/stdlib-1.9.3/libdoc/tempfile/rdoc/
    #     Tempfile.html#class-Tempfile-label-Explicit+close
    begin
      # In practice, we let PredictiveTests create the file, and we just
      # use its file name.
      changed_files.close
      changed_files.unlink

      example.run
    ensure
      # Since example.run can create the file again, let's remove it again
      FileUtils.rm_f(changed_files_path)
      fixtures_mapping.close
      fixtures_mapping.unlink
      matching_js_files.close
      matching_js_files.unlink
      matching_tests.close
      matching_tests.unlink
      views_with_partials.close
      views_with_partials.unlink
    end
  end

  before do
    stub_env(
      'RSPEC_CHANGED_FILES_PATH' => changed_files_path,
      'RSPEC_MATCHING_TESTS_PATH' => matching_tests.path,
      'RSPEC_VIEWS_INCLUDING_PARTIALS_PATH' => views_with_partials.path,
      'FRONTEND_FIXTURES_MAPPING_PATH' => fixtures_mapping.path,
      'RSPEC_MATCHING_JS_FILES_PATH' => matching_js_files.path,
      'RSPEC_TESTS_MAPPING_ENABLED' => "false",
      'RSPEC_TESTS_MAPPING_PATH' => '/tmp/does-not-exist.out'
    )

    # We write some data to later on verify that we only append to this file.
    File.write(matching_tests.path, matching_tests_initial_content)
    File.write(fixtures_mapping.path, fixtures_mapping_content)

    allow(Gitlab).to receive(:configure)
  end

  describe '#execute' do
    subject { instance.execute }

    context 'when ENV variables are missing' do
      before do
        stub_env(
          'RSPEC_CHANGED_FILES_PATH' => '',
          'FRONTEND_FIXTURES_MAPPING_PATH' => ''
        )
      end

      it 'raises an error' do
        expect { subject }.to raise_error(
          '[predictive tests] Missing ENV variable(s): RSPEC_CHANGED_FILES_PATH,FRONTEND_FIXTURES_MAPPING_PATH.'
        )
      end
    end

    context 'when all ENV variables are provided' do
      before do
        change = double('GitLab::Change') # rubocop:disable RSpec/VerifiedDoubles
        allow(change).to receive_message_chain(:to_h, :values_at)
          .and_return([changed_files_content, changed_files_content])

        allow(Gitlab).to receive_message_chain(:merge_request_changes, :changes)
          .and_return([change])
      end

      context 'when no files were changed' do
        let(:changed_files_content) { '' }

        it 'does not change files other than RSPEC_CHANGED_FILES_PATH' do
          expect { subject }.not_to change { File.read(matching_tests.path) }
          expect { subject }.not_to change { File.read(views_with_partials.path) }
          expect { subject }.not_to change { File.read(fixtures_mapping.path) }
          expect { subject }.not_to change { File.read(matching_js_files.path) }
        end
      end

      context 'when some files used for frontend fixtures were changed' do
        let(:changed_files_content) { 'app/models/todo.rb' }
        let(:changed_files_matching_test) { 'spec/models/todo_spec.rb' }
        let(:matching_frontend_fixture) { 'tmp/tests/frontend/fixtures-ee/todos/todos.html' }
        let(:fixtures_mapping_content) do
          JSON.dump(changed_files_matching_test => [matching_frontend_fixture]) # rubocop:disable Gitlab/Json
        end

        it 'writes to RSPEC_CHANGED_FILES_PATH with API contents and appends with matching fixtures' do
          subject

          expect(File.read(changed_files_path)).to eq("#{changed_files_content} #{matching_frontend_fixture}")
        end

        it 'appends the spec file to RSPEC_MATCHING_TESTS_PATH' do
          expect { subject }.to change { File.read(matching_tests.path) }
            .from(matching_tests_initial_content)
            .to("#{matching_tests_initial_content} #{changed_files_matching_test}")
        end

        it 'does not change files other than RSPEC_CHANGED_FILES_PATH nor RSPEC_MATCHING_TESTS_PATH' do
          expect { subject }.not_to change { File.read(views_with_partials.path) }
          expect { subject }.not_to change { File.read(fixtures_mapping.path) }
          expect { subject }.not_to change { File.read(matching_js_files.path) }
        end
      end
    end
  end
end