diff --git a/spec/tooling/lib/tooling/find_changes_spec.rb b/spec/tooling/lib/tooling/find_changes_spec.rb index 5932eb5e9190238d7393d40fbf0182eb2c235c1d..0e34659e42aac961604ca64c22bd79ad2043accb 100644 --- a/spec/tooling/lib/tooling/find_changes_spec.rb +++ b/spec/tooling/lib/tooling/find_changes_spec.rb @@ -11,12 +11,17 @@ attr_accessor :changed_files_file, :predictive_tests_file, :frontend_fixtures_mapping_file let(:instance) do - described_class.new(changed_files_pathname, predictive_tests_pathname, frontend_fixtures_mapping_pathname) + described_class.new( + changed_files_pathname: changed_files_pathname, + predictive_tests_pathname: predictive_tests_pathname, + frontend_fixtures_mapping_pathname: frontend_fixtures_mapping_pathname, + append: append) end let(:changed_files_pathname) { changed_files_file.path } let(:predictive_tests_pathname) { predictive_tests_file.path } let(:frontend_fixtures_mapping_pathname) { frontend_fixtures_mapping_file.path } + let(:append) { false } let(:gitlab_client) { double('GitLab') } # rubocop:disable RSpec/VerifiedDoubles around do |example| @@ -57,12 +62,24 @@ it 'raises an ArgumentError' do expect { subject }.to raise_error( - ArgumentError, "A path to the changed files file must be given as first argument." + ArgumentError, "A path to the changed files file must be given as :changed_files_pathname" ) end end - context 'when an changed files file is provided' do + context 'when not in append mode' do + let(:append) { false } + + it 'calls GitLab API to retrieve the MR diff' do + expect(gitlab_client).to receive_message_chain(:merge_request_changes, :changes).and_return([]) + + subject + end + end + + context 'when in append mode' do + let(:append) { true } + it 'does not call GitLab API to retrieve the MR diff' do expect(gitlab_client).not_to receive(:merge_request_changes) diff --git a/spec/tooling/lib/tooling/predictive_tests_spec.rb b/spec/tooling/lib/tooling/predictive_tests_spec.rb index 79554037c4862eaf19fd0423b29b02a86d3e22f9..f5ff6d05f0a2e59c62eb740ea15f9bad4fc9c10e 100644 --- a/spec/tooling/lib/tooling/predictive_tests_spec.rb +++ b/spec/tooling/lib/tooling/predictive_tests_spec.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'tempfile' +require 'fileutils' require_relative '../../../../tooling/lib/tooling/predictive_tests' require_relative '../../../support/helpers/stub_env' @@ -10,10 +11,12 @@ let(:instance) { described_class.new } let(:matching_tests_initial_content) { 'initial_matching_spec' } - attr_accessor :changed_files, :fixtures_mapping, :matching_js_files, :matching_tests, :views_with_partials + 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') @@ -22,10 +25,15 @@ # See https://ruby-doc.org/stdlib-1.9.3/libdoc/tempfile/rdoc/ # Tempfile.html#class-Tempfile-label-Explicit+close begin - example.run - ensure + # 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 @@ -39,7 +47,7 @@ before do stub_env( - 'RSPEC_CHANGED_FILES_PATH' => changed_files.path, + '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, @@ -51,6 +59,8 @@ # 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, '{}') # We write valid JSON, so that the file can be processed + + allow(Gitlab).to receive(:configure) end describe '#execute' do @@ -73,14 +83,18 @@ context 'when all ENV variables are provided' do before do - File.write(changed_files, changed_files_content) + 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 any files' do - expect { subject }.not_to change { File.read(changed_files.path) } + 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) } @@ -91,14 +105,19 @@ context 'when some files were changed' do let(:changed_files_content) { 'tooling/lib/tooling/predictive_tests.rb' } + it 'writes to RSPEC_CHANGED_FILES_PATH with API contents' do + subject + + expect(File.read(changed_files_path)).to eq(changed_files_content) + 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} spec/tooling/lib/tooling/predictive_tests_spec.rb") end - it 'does not change files other than RSPEC_MATCHING_TESTS_PATH' do - expect { subject }.not_to change { File.read(changed_files.path) } + 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) } diff --git a/tooling/lib/tooling/find_changes.rb b/tooling/lib/tooling/find_changes.rb index b4439bd4abe05e8f179aa98bfb83e1a529c8d92d..2544bcbbed4758cec3edfda16369c20d8ec21b35 100755 --- a/tooling/lib/tooling/find_changes.rb +++ b/tooling/lib/tooling/find_changes.rb @@ -9,7 +9,10 @@ class FindChanges include Helpers::FileHandler def initialize( - changed_files_pathname = nil, predictive_tests_pathname = nil, frontend_fixtures_mapping_pathname = nil + changed_files_pathname: nil, + predictive_tests_pathname: nil, + frontend_fixtures_mapping_pathname: nil, + append: false ) @gitlab_token = ENV['PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE'] || '' @gitlab_endpoint = ENV['CI_API_V4_URL'] @@ -18,11 +21,12 @@ def initialize( @changed_files_pathname = changed_files_pathname @predictive_tests_pathname = predictive_tests_pathname @frontend_fixtures_mapping_pathname = frontend_fixtures_mapping_pathname + @append = append end def execute if changed_files_pathname.nil? - raise ArgumentError, "A path to the changed files file must be given as first argument." + raise ArgumentError, "A path to the changed files file must be given as :changed_files_pathname" end add_frontend_fixture_files! @@ -30,8 +34,6 @@ def execute end def only_js_files_changed - @changed_files_pathname = nil # We ensure that we'll get the diff from the MR directly, not from a file. - file_changes.any? && file_changes.all? { |file| file.end_with?('.js') } end @@ -68,7 +70,7 @@ def add_frontend_fixture_files! def file_changes @file_changes ||= - if changed_files_pathname && File.exist?(changed_files_pathname) + if @append && File.exist?(changed_files_pathname) read_array_from_file(changed_files_pathname) else mr_changes.changes.flat_map do |change| diff --git a/tooling/lib/tooling/predictive_tests.rb b/tooling/lib/tooling/predictive_tests.rb index 2691e1ba56d6054b5e73f16e0ad027b57c4ece81..56b108a2ddf900b0d11d3b9f9895247a261ab34d 100644 --- a/tooling/lib/tooling/predictive_tests.rb +++ b/tooling/lib/tooling/predictive_tests.rb @@ -32,7 +32,7 @@ def initialize end def execute - Tooling::FindChanges.new(rspec_changed_files_path).execute + Tooling::FindChanges.new(changed_files_pathname: rspec_changed_files_path).execute Tooling::FindTests.new(rspec_changed_files_path, rspec_matching_tests_path).execute Tooling::Mappings::PartialToViewsMappings.new( rspec_changed_files_path, rspec_views_including_partials_path).execute @@ -41,7 +41,11 @@ def execute Tooling::Mappings::GraphqlBaseTypeMappings.new(rspec_changed_files_path, rspec_matching_tests_path).execute Tooling::Mappings::ViewToSystemSpecsMappings.new(rspec_changed_files_path, rspec_matching_tests_path).execute Tooling::FindChanges.new( - rspec_changed_files_path, rspec_matching_tests_path, frontend_fixtures_mapping_path).execute + append: true, + changed_files_pathname: rspec_changed_files_path, + predictive_tests_pathname: rspec_matching_tests_path, + frontend_fixtures_mapping_pathname: frontend_fixtures_mapping_path + ).execute Tooling::Mappings::ViewToJsMappings.new(rspec_changed_files_path, rspec_matching_js_files_path).execute end