diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 2dea29051..0c088ef80 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -131,6 +131,7 @@ RSpec/FilePath: - 'spec/android_localize_helper_spec.rb' - 'spec/android_merge_translators_strings_spec.rb' - 'spec/android_version_helper_spec.rb' + - 'spec/an_localize_libs_action_spec.rb' - 'spec/an_metadata_update_helper_spec.rb' - 'spec/an_update_metadata_source_spec.rb' - 'spec/configuration_spec.rb' diff --git a/CHANGELOG.md b/CHANGELOG.md index 86f7618b9..9d8e9685c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ _None_ * Ensure that the `gem push` step only runs on CI if lint, test and danger steps passed before it. [#325] * Rename internal `Ios::L10nHelper` to `Ios::L10nLinterHelper`. [#328] +* Provide new `run_described_fastlane_action` to run Fastlane actions more thoroughly in unit tests [#330] ## 2.3.0 diff --git a/spec/an_localize_libs_action_spec.rb b/spec/an_localize_libs_action_spec.rb new file mode 100644 index 000000000..86455e3a7 --- /dev/null +++ b/spec/an_localize_libs_action_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +describe Fastlane::Actions::AnLocalizeLibsAction do + # This test is more of a way of ensuring `run_described_fastlane_action` handles array + # of hashes properly than a comprehensive test for the + # `an_localize_libs_action` action. + # + # Please consider expanding this test if you'll find yourself working on its + # action. + it 'merges the strings from the given array into the given main strings file' do + in_tmp_dir do |tmp_dir| + app_strings_path = File.join(tmp_dir, 'app.xml') + File.write(app_strings_path, android_xml_with_content('test from app')) + + lib1_strings_path = File.join(tmp_dir, 'lib1.xml') + File.write(lib1_strings_path, android_xml_with_content('test from lib 1')) + + lib2_strings_path = File.join(tmp_dir, 'lib2.xml') + File.write(lib2_strings_path, android_xml_with_content('test from lib 2')) + + run_described_fastlane_action( + app_strings_path: app_strings_path, + libs_strings_path: [ + { library: 'lib_1', strings_path: lib1_strings_path, exclusions: [] }, + { library: 'lib_2', strings_path: lib2_strings_path, exclusions: [] }, + ] + ) + + # Notice the extra indentation in the library strings. The action doesn't + # modify the app's strings content indentation, but it applies its own + # standard to the values read from the given library strings + expected = <<~XML + test from app + test from lib 1 + test from lib 2 + XML + expect(File.read(app_strings_path)).to eq(android_xml_with_content(expected)) + end + end +end + +def android_xml_with_content(content) + # I couldn't find a way to interpolate a multiline string preserving its + # indentation in the heredoc below, so I hacked the following transformation + # of the input that adds the desired indentation to all lines. + indented_content = content.chomp.lines.map { |l| " #{l}" }.join + + return <<~XML + + + #{indented_content} + + XML +end diff --git a/spec/android_merge_translators_strings_spec.rb b/spec/android_merge_translators_strings_spec.rb index f11c7e8b4..e7695b7ae 100644 --- a/spec/android_merge_translators_strings_spec.rb +++ b/spec/android_merge_translators_strings_spec.rb @@ -35,7 +35,7 @@ def amts_run_test(script) test_script = @amtsTestUtils.get_test_from_file(script) @amtsTestUtils.create_test_data(test_script) - Fastlane::Actions::AndroidMergeTranslatorsStringsAction.run(strings_folder: @amtsTestUtils.test_folder_path) + run_described_fastlane_action(strings_folder: @amtsTestUtils.test_folder_path) expect(@amtsTestUtils.read_result_data(test_script)).to eq(test_script['result']['content']) end diff --git a/spec/ios_lint_localizations_spec.rb b/spec/ios_lint_localizations_spec.rb index 4e6ac3888..036acff29 100644 --- a/spec/ios_lint_localizations_spec.rb +++ b/spec/ios_lint_localizations_spec.rb @@ -23,7 +23,7 @@ expect(FileUtils).to receive(:cp_r) expect_shell_command("#{install_dir}/bin/swiftgen", 'config', 'run', '--config', anything) - Fastlane::Actions::IosLintLocalizationsAction.run( + run_described_fastlane_action( install_path: install_dir, input_dir: empty_dataset, base_lang: 'en' @@ -43,7 +43,7 @@ # Second run: ensure we only run SwiftGen directly, without a call to curl nor unzip beforehand expect_shell_command("#{install_dir}/bin/swiftgen", 'config', 'run', '--config', anything) - Fastlane::Actions::IosLintLocalizationsAction.run( + run_described_fastlane_action( install_path: install_dir, input_dir: empty_dataset, base_lang: 'en' @@ -103,7 +103,7 @@ def run_l10n_linter_test(data_file) # remove this after the test ends, so that further executions of the test run faster. # Only the first execution of the tests might take longer if it needs to install SwiftGen first to be able to run the tests. install_dir = "vendor/swiftgen/#{Fastlane::Helper::Ios::L10nLinterHelper::SWIFTGEN_VERSION}" - result = Fastlane::Actions::IosLintLocalizationsAction.run( + result = run_described_fastlane_action( install_path: install_dir, input_dir: @test_data_dir, base_lang: 'en' diff --git a/spec/ios_merge_strings_files_spec.rb b/spec/ios_merge_strings_files_spec.rb index cba549a18..22bd4cc2d 100644 --- a/spec/ios_merge_strings_files_spec.rb +++ b/spec/ios_merge_strings_files_spec.rb @@ -1,41 +1,39 @@ -describe Fastlane do - describe Fastlane::FastFile do - let(:test_data_dir) { File.join(File.dirname(__FILE__), 'test-data', 'translations', 'ios_l10n_helper') } +describe Fastlane::Actions::IosMergeStringsFilesAction do + let(:test_data_dir) { File.join(File.dirname(__FILE__), 'test-data', 'translations', 'ios_l10n_helper') } - def fixture(name) - File.join(test_data_dir, name) - end - - describe '#ios_merge_strings_files' do - it 'calls the action with the proper parameters and warn and return duplicate keys' do - # Arrange - messages = [] - allow(FastlaneCore::UI).to receive(:important) do |message| - messages.append(message) - end - inputs = ['Localizable-utf16.strings', 'non-latin-utf16.strings'] + def fixture(name) + File.join(test_data_dir, name) + end - Dir.mktmpdir('a8c-release-toolkit-tests-') do |tmpdir| - inputs.each { |f| FileUtils.cp(fixture(f), tmpdir) } + describe '#ios_merge_strings_files' do + it 'calls the action with the proper parameters and warn and return duplicate keys' do + # Arrange + messages = [] + allow(FastlaneCore::UI).to receive(:important) do |message| + messages.append(message) + end + inputs = ['Localizable-utf16.strings', 'non-latin-utf16.strings'] - # Act - result = Dir.chdir(tmpdir) do - described_class.new.parse("lane :test do - ios_merge_strings_files( - paths: ['#{inputs[0]}', '#{inputs[1]}'], - destination: 'output.strings' - ) - end").runner.execute(:test) - end + Dir.mktmpdir('a8c-release-toolkit-tests-') do |tmpdir| + inputs.each { |f| FileUtils.cp(fixture(f), tmpdir) } - # Assert - expect(File).to exist(File.join(tmpdir, 'output.strings')) - expect(result).to eq(%w[key1 key2]) - expect(messages).to eq([ - 'Duplicate key found while merging the `.strings` files: `key1`', - 'Duplicate key found while merging the `.strings` files: `key2`', - ]) + # Act + result = Dir.chdir(tmpdir) do + run_described_fastlane_action( + paths: [inputs[0], inputs[1]], + destination: 'output.strings' + ) end + + # Assert + expect(File).to exist(File.join(tmpdir, 'output.strings')) + expect(result).to eq(%w[key1 key2]) + expect(messages).to eq( + [ + 'Duplicate key found while merging the `.strings` files: `key1`', + 'Duplicate key found while merging the `.strings` files: `key2`', + ] + ) end end end diff --git a/spec/ios_merge_translators_strings_spec.rb b/spec/ios_merge_translators_strings_spec.rb index f20eebfef..4ae829f8f 100644 --- a/spec/ios_merge_translators_strings_spec.rb +++ b/spec/ios_merge_translators_strings_spec.rb @@ -35,7 +35,7 @@ def imts_run_test(script) test_script = @imtsTestUtils.get_test_from_file(script) @imtsTestUtils.create_test_data(test_script) - Fastlane::Actions::IosMergeTranslatorsStringsAction.run(strings_folder: @imtsTestUtils.test_folder_path) + run_described_fastlane_action(strings_folder: @imtsTestUtils.test_folder_path) expect(@imtsTestUtils.read_result_data(test_script)).to eq(test_script['result']['content']) end diff --git a/spec/shared_examples_for_update_metadata_source_action.rb b/spec/shared_examples_for_update_metadata_source_action.rb index 2c82949df..d096096e2 100644 --- a/spec/shared_examples_for_update_metadata_source_action.rb +++ b/spec/shared_examples_for_update_metadata_source_action.rb @@ -19,8 +19,9 @@ file_2_path = File.join(dir, '2.txt') File.write(file_2_path, 'value 2') - described_class.run( + run_described_fastlane_action( po_file_path: output_path, + release_version: '1.0', source_files: { key1: file_1_path, key2: file_2_path @@ -56,7 +57,7 @@ whats_new_path = File.join(dir, 'whats_new.txt') File.write(whats_new_path, "- something new\n- something else new") - described_class.run( + run_described_fastlane_action( po_file_path: output_path, release_version: '1.23', source_files: { @@ -94,8 +95,9 @@ file_2_path = File.join(dir, '2.txt') File.write(file_2_path, 'value 2') - described_class.run( + run_described_fastlane_action( po_file_path: output_path, + release_version: '1.0', source_files: { key1: file_1_path, key2: file_2_path @@ -135,7 +137,7 @@ release_notes_path = File.join(dir, 'release_notes.txt') File.write(release_notes_path, "- release notes\n- more release notes") - described_class.run( + run_described_fastlane_action( po_file_path: output_path, release_version: '1.23', source_files: { diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9fc311a64..8bc4ad62d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -67,6 +67,24 @@ def expect_shell_command(*command, exitstatus: 0, output: '') expect(Open3).to receive(:popen2e).with(*command).and_yield(mock_input, mock_output, mock_thread) end +# If the `described_class` of a spec is a `Fastlane::Action` subclass, it runs +# it with the given parameters. +# +def run_described_fastlane_action(parameters) + raise "Only call `#{__callee__}` from a spec describing a `Fastlane::Action` subclass." unless Fastlane::Actions.is_class_action?(described_class) + + # Avoid logging messages about deprecated actions while running tests on them + allow(Fastlane::Actions).to receive(:is_deprecated?).and_return(false) + lane = <<~LANE + lane :test do + #{described_class.action_name}( + #{parameters.inspect} + ) + end + LANE + Fastlane::FastFile.new.parse(lane).runner.execute(:test) +end + # Executes the given block within an ad hoc temporary directory. def in_tmp_dir Dir.mktmpdir('a8c-release-toolkit-tests-') do |tmpdir|