lokalise_rails 2.0.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -0
  3. data/Gemfile +12 -1
  4. data/README.md +74 -57
  5. data/lib/generators/lokalise_rails/install_generator.rb +2 -0
  6. data/lib/generators/templates/lokalise_rails_config.rb +2 -4
  7. data/lib/lokalise_rails/global_config.rb +12 -0
  8. data/lib/lokalise_rails/railtie.rb +1 -0
  9. data/lib/lokalise_rails/utils.rb +23 -0
  10. data/lib/lokalise_rails/version.rb +3 -1
  11. data/lib/lokalise_rails.rb +8 -88
  12. data/lib/tasks/lokalise_rails_tasks.rake +6 -3
  13. data/lokalise_rails.gemspec +7 -18
  14. data/spec/dummy/config/lokalise_rails.rb +3 -3
  15. data/spec/lib/generators/lokalise_rails/install_generator_spec.rb +2 -2
  16. data/spec/lib/{lokalise_rails_spec.rb → lokalise_rails/global_config_spec.rb} +17 -5
  17. data/spec/lib/lokalise_rails/version_spec.rb +7 -0
  18. data/spec/lib/tasks/export_task_spec.rb +25 -18
  19. data/spec/lib/tasks/import_task_spec.rb +36 -99
  20. data/spec/lib/utils_spec.rb +16 -0
  21. data/spec/spec_helper.rb +0 -2
  22. data/spec/support/file_manager.rb +8 -11
  23. data/spec/support/spec_addons.rb +8 -3
  24. metadata +21 -178
  25. data/lib/lokalise_rails/error.rb +0 -10
  26. data/lib/lokalise_rails/task_definition/base.rb +0 -80
  27. data/lib/lokalise_rails/task_definition/exporter.rb +0 -79
  28. data/lib/lokalise_rails/task_definition/importer.rb +0 -109
  29. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
  30. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
  31. data/spec/dummy/config/initializers/content_security_policy.rb +0 -29
  32. data/spec/dummy/config/initializers/inflections.rb +0 -17
  33. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  34. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  35. data/spec/lib/lokalise_rails/task_definition/base_spec.rb +0 -81
  36. data/spec/lib/lokalise_rails/task_definition/exporter_spec.rb +0 -200
  37. data/spec/lib/lokalise_rails/task_definition/importer_spec.rb +0 -72
  38. data/spec/support/rake_utils.rb +0 -15
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ruby-lokalise-api'
4
- require 'pathname'
5
-
6
- module LokaliseRails
7
- module TaskDefinition
8
- class Base
9
- class << self
10
- attr_writer :api_client
11
-
12
- # Creates a Lokalise API client
13
- #
14
- # @return [Lokalise::Client]
15
- def api_client
16
- @api_client ||= ::Lokalise.client LokaliseRails.api_token, {enable_compression: true}.merge(LokaliseRails.timeouts)
17
- end
18
-
19
- # Resets API client
20
- def reset_api_client!
21
- Lokalise.reset_client!
22
- @api_client = nil
23
- end
24
-
25
- # Checks task options
26
- #
27
- # @return Array
28
- def check_options_errors!
29
- errors = []
30
- errors << 'Project ID is not set!' if LokaliseRails.project_id.nil? || LokaliseRails.project_id.empty?
31
- errors << 'Lokalise API token is not set!' if LokaliseRails.api_token.nil? || LokaliseRails.api_token.empty?
32
-
33
- raise(LokaliseRails::Error, errors.join(' ')) if errors.any?
34
- end
35
-
36
- private
37
-
38
- # Checks whether the provided file has a proper extension as dictated by the `file_ext_regexp` option
39
- #
40
- # @return Boolean
41
- # @param raw_path [String, Pathname]
42
- def proper_ext?(raw_path)
43
- path = raw_path.is_a?(Pathname) ? raw_path : Pathname.new(raw_path)
44
- LokaliseRails.file_ext_regexp.match? path.extname
45
- end
46
-
47
- # Returns directory and filename for the given entry
48
- #
49
- # @return Array
50
- # @param entry [String]
51
- def subdir_and_filename_for(entry)
52
- Pathname.new(entry).split
53
- end
54
-
55
- # Returns Lokalise project ID and branch, semicolumn separated
56
- #
57
- # @return [String]
58
- def project_id_with_branch
59
- "#{LokaliseRails.project_id}:#{LokaliseRails.branch}"
60
- end
61
-
62
- # Sends request with exponential backoff mechanism
63
- def with_exp_backoff(max_retries)
64
- return unless block_given?
65
-
66
- retries = 0
67
- begin
68
- yield
69
- rescue Lokalise::Error::TooManyRequests => e
70
- raise(e.class, "Gave up after #{retries} retries") if retries >= max_retries
71
-
72
- sleep 2**retries
73
- retries += 1
74
- retry
75
- end
76
- end
77
- end
78
- end
79
- end
80
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'base64'
4
-
5
- module LokaliseRails
6
- module TaskDefinition
7
- class Exporter < Base
8
- class << self
9
- # Performs translation file export from Rails to Lokalise and returns an array of queued processes
10
- #
11
- # @return [Array]
12
- def export!
13
- check_options_errors!
14
-
15
- queued_processes = []
16
- each_file do |full_path, relative_path|
17
- queued_processes << do_upload(full_path, relative_path)
18
- rescue StandardError => e
19
- raise e.class, "Error while trying to upload #{full_path}: #{e.message}"
20
- end
21
-
22
- $stdout.print 'Task complete!'
23
-
24
- queued_processes
25
- end
26
-
27
- # Performs the actual file uploading to Lokalise. If the API rate limit is exceeed,
28
- # applies exponential backoff
29
- def do_upload(f_path, r_path)
30
- with_exp_backoff(LokaliseRails.max_retries_export) do
31
- api_client.upload_file project_id_with_branch, opts(f_path, r_path)
32
- end
33
- end
34
-
35
- # Processes each translation file in the specified directory
36
- def each_file
37
- return unless block_given?
38
-
39
- loc_path = LokaliseRails.locales_path
40
- Dir["#{loc_path}/**/*"].sort.each do |f|
41
- full_path = Pathname.new f
42
-
43
- next unless file_matches_criteria? full_path
44
-
45
- relative_path = full_path.relative_path_from Pathname.new(loc_path)
46
-
47
- yield full_path, relative_path
48
- end
49
- end
50
-
51
- # Generates export options
52
- #
53
- # @return [Hash]
54
- # @param full_p [Pathname]
55
- # @param relative_p [Pathname]
56
- def opts(full_p, relative_p)
57
- content = File.read full_p
58
-
59
- initial_opts = {
60
- data: Base64.strict_encode64(content.strip),
61
- filename: relative_p,
62
- lang_iso: LokaliseRails.lang_iso_inferer.call(content)
63
- }
64
-
65
- initial_opts.merge LokaliseRails.export_opts
66
- end
67
-
68
- # Checks whether the specified file has to be processed or not
69
- #
70
- # @return [Boolean]
71
- # @param full_path [Pathname]
72
- def file_matches_criteria?(full_path)
73
- full_path.file? && proper_ext?(full_path) &&
74
- !LokaliseRails.skip_file_export.call(full_path)
75
- end
76
- end
77
- end
78
- end
79
- end
@@ -1,109 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'zip'
4
- require 'yaml'
5
- require 'open-uri'
6
- require 'fileutils'
7
-
8
- module LokaliseRails
9
- module TaskDefinition
10
- class Importer < Base
11
- class << self
12
- # Performs translation files import from Lokalise to Rails app
13
- #
14
- # @return [Boolean]
15
- def import!
16
- check_options_errors!
17
-
18
- unless proceed_when_safe_mode?
19
- $stdout.print 'Task cancelled!'
20
- return false
21
- end
22
-
23
- open_and_process_zip download_files['bundle_url']
24
-
25
- $stdout.print 'Task complete!'
26
- true
27
- end
28
-
29
- # Downloads files from Lokalise using the specified options.
30
- # Utilizes exponential backoff if "too many requests" error is received
31
- #
32
- # @return [Hash]
33
- def download_files
34
- with_exp_backoff(LokaliseRails.max_retries_import) do
35
- api_client.download_files project_id_with_branch, LokaliseRails.import_opts
36
- end
37
- rescue StandardError => e
38
- raise e.class, "There was an error when trying to download files: #{e.message}"
39
- end
40
-
41
- # Opens ZIP archive (local or remote) with translations and processes its entries
42
- #
43
- # @param path [String]
44
- def open_and_process_zip(path)
45
- Zip::File.open_buffer(open_file_or_remote(path)) do |zip|
46
- fetch_zip_entries(zip) { |entry| process!(entry) }
47
- end
48
- rescue StandardError => e
49
- raise e.class, "There was an error when trying to process the downloaded files: #{e.message}"
50
- end
51
-
52
- # Iterates over ZIP entries. Each entry may be a file or folder.
53
- def fetch_zip_entries(zip)
54
- return unless block_given?
55
-
56
- zip.each do |entry|
57
- next unless proper_ext? entry.name
58
-
59
- yield entry
60
- end
61
- end
62
-
63
- # Processes ZIP entry by reading its contents and creating the corresponding translation file
64
- def process!(zip_entry)
65
- data = data_from zip_entry
66
- subdir, filename = subdir_and_filename_for zip_entry.name
67
- full_path = "#{LokaliseRails.locales_path}/#{subdir}"
68
- FileUtils.mkdir_p full_path
69
-
70
- File.open(File.join(full_path, filename), 'w+:UTF-8') do |f|
71
- f.write LokaliseRails.translations_converter.call(data)
72
- end
73
- rescue StandardError => e
74
- raise e.class, "Error when trying to process #{zip_entry&.name}: #{e.message}"
75
- end
76
-
77
- # Checks whether the user wishes to proceed when safe mode is enabled and the target directory is not empty
78
- #
79
- # @return [Boolean]
80
- def proceed_when_safe_mode?
81
- return true unless LokaliseRails.import_safe_mode && !Dir.empty?(LokaliseRails.locales_path.to_s)
82
-
83
- $stdout.puts "The target directory #{LokaliseRails.locales_path} is not empty!"
84
- $stdout.print 'Enter Y to continue: '
85
- answer = $stdin.gets
86
- answer.to_s.strip == 'Y'
87
- end
88
-
89
- # Opens a local file or a remote URL using the provided patf
90
- #
91
- # @return [String]
92
- def open_file_or_remote(path)
93
- parsed_path = URI.parse(path)
94
- if parsed_path&.scheme&.include?('http')
95
- parsed_path.open
96
- else
97
- File.open path
98
- end
99
- end
100
-
101
- private
102
-
103
- def data_from(zip_entry)
104
- LokaliseRails.translations_loader.call zip_entry.get_input_stream.read
105
- end
106
- end
107
- end
108
- end
109
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
- # Be sure to restart your server when you modify this file.
3
-
4
- # ActiveSupport::Reloader.to_prepare do
5
- # ApplicationController.renderer.defaults.merge!(
6
- # http_host: 'example.org',
7
- # https: false
8
- # )
9
- # end
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
- # Be sure to restart your server when you modify this file.
3
-
4
- # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
5
- # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
6
-
7
- # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
8
- # Rails.backtrace_cleaner.remove_silencers!
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
- # Be sure to restart your server when you modify this file.
3
-
4
- # Define an application-wide content security policy
5
- # For further information see the following documentation
6
- # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
7
-
8
- # Rails.application.config.content_security_policy do |policy|
9
- # policy.default_src :self, :https
10
- # policy.font_src :self, :https, :data
11
- # policy.img_src :self, :https, :data
12
- # policy.object_src :none
13
- # policy.script_src :self, :https
14
- # policy.style_src :self, :https
15
-
16
- # # Specify URI for violation reports
17
- # # policy.report_uri "/csp-violation-report-endpoint"
18
- # end
19
-
20
- # If you are using UJS then enable automatic nonce generation
21
- # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
22
-
23
- # Set the nonce only to specific directives
24
- # Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
25
-
26
- # Report CSP violations to a specified URI
27
- # For further information see the following documentation:
28
- # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
29
- # Rails.application.config.content_security_policy_report_only = true
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
- # Be sure to restart your server when you modify this file.
3
-
4
- # Add new inflection rules using the following format. Inflections
5
- # are locale specific, and you may define rules for as many different
6
- # locales as you wish. All of these examples are active by default:
7
- # ActiveSupport::Inflector.inflections(:en) do |inflect|
8
- # inflect.plural /^(ox)$/i, '\1en'
9
- # inflect.singular /^(ox)en/i, '\1'
10
- # inflect.irregular 'person', 'people'
11
- # inflect.uncountable %w( fish sheep )
12
- # end
13
-
14
- # These inflection rules are supported but not enabled by default:
15
- # ActiveSupport::Inflector.inflections(:en) do |inflect|
16
- # inflect.acronym 'RESTful'
17
- # end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
- # Be sure to restart your server when you modify this file.
3
-
4
- # Add new mime types for use in respond_to blocks:
5
- # Mime::Type.register "text/richtext", :rtf
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Be sure to restart your server when you modify this file.
4
-
5
- # This file contains settings for ActionController::ParamsWrapper which
6
- # is enabled by default.
7
-
8
- # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
9
- ActiveSupport.on_load(:action_controller) do
10
- wrap_parameters format: [:json]
11
- end
12
-
13
- # To enable root element in JSON for ActiveRecord objects.
14
- # ActiveSupport.on_load(:active_record) do
15
- # self.include_root_in_json = true
16
- # end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe LokaliseRails::TaskDefinition::Base do
4
- specify '.reset_client!' do
5
- expect(described_class.api_client).to be_an_instance_of(Lokalise::Client)
6
- described_class.reset_api_client!
7
- current_client = described_class.instance_variable_get '@api_client'
8
- expect(current_client).to be_nil
9
- end
10
-
11
- specify '.project_id_with_branch!' do
12
- result = described_class.send :project_id_with_branch
13
- expect(result).to be_an_instance_of(String)
14
- expect(result).to include(':master')
15
- end
16
-
17
- describe '.subdir_and_filename_for' do
18
- it 'works properly for longer paths' do
19
- path = 'my_path/is/here/file.yml'
20
- result = described_class.send(:subdir_and_filename_for, path)
21
- expect(result.length).to eq(2)
22
- expect(result[0]).to be_an_instance_of(Pathname)
23
- expect(result[0].to_s).to eq('my_path/is/here')
24
- expect(result[1].to_s).to eq('file.yml')
25
- end
26
-
27
- it 'works properly for shorter paths' do
28
- path = 'file.yml'
29
- result = described_class.send(:subdir_and_filename_for, path)
30
- expect(result.length).to eq(2)
31
- expect(result[1]).to be_an_instance_of(Pathname)
32
- expect(result[0].to_s).to eq('.')
33
- expect(result[1].to_s).to eq('file.yml')
34
- end
35
- end
36
-
37
- describe '.check_options_errors!' do
38
- it 'raises an error when the API key is not set' do
39
- allow(LokaliseRails).to receive(:api_token).and_return(nil)
40
-
41
- expect(-> { described_class.check_options_errors! }).to raise_error(LokaliseRails::Error, /API token is not set/i)
42
-
43
- expect(LokaliseRails).to have_received(:api_token)
44
- end
45
-
46
- it 'returns an error when the project_id is not set' do
47
- allow_project_id nil do
48
- expect(-> { described_class.check_options_errors! }).to raise_error(LokaliseRails::Error, /ID is not set/i)
49
- end
50
- end
51
- end
52
-
53
- describe '.proper_ext?' do
54
- it 'works properly with path represented as a string' do
55
- path = 'my_path/here/file.yml'
56
- expect(described_class.send(:proper_ext?, path)).to be true
57
- end
58
-
59
- it 'works properly with path represented as a pathname' do
60
- path = Pathname.new 'my_path/here/file.json'
61
- expect(described_class.send(:proper_ext?, path)).to be false
62
- end
63
- end
64
-
65
- describe '.api_client' do
66
- before(:all) { described_class.reset_api_client! }
67
-
68
- after(:all) { described_class.reset_api_client! }
69
-
70
- it 'is possible to set timeouts' do
71
- allow(LokaliseRails).to receive(:timeouts).and_return({
72
- open_timeout: 100,
73
- timeout: 500
74
- })
75
-
76
- expect(described_class.api_client).to be_an_instance_of(Lokalise::Client)
77
- expect(described_class.api_client.open_timeout).to eq(100)
78
- expect(described_class.api_client.timeout).to eq(500)
79
- end
80
- end
81
- end
@@ -1,200 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'base64'
4
-
5
- describe LokaliseRails::TaskDefinition::Exporter do
6
- let(:filename) { 'en.yml' }
7
- let(:path) { "#{Rails.root}/config/locales/nested/#{filename}" }
8
- let(:relative_name) { "nested/#{filename}" }
9
-
10
- context 'with many translation files' do
11
- let(:fake_class) { described_class }
12
-
13
- before :all do
14
- add_translation_files! with_ru: true, additional: 5
15
- end
16
-
17
- after :all do
18
- rm_translation_files
19
- end
20
-
21
- describe '.export!' do
22
- it 'sends a proper API request and handles rate limiting' do
23
- allow_project_id '672198945b7d72fc048021.15940510'
24
-
25
- process = VCR.use_cassette('upload_files_multiple') do
26
- described_class.export!
27
- end.first
28
-
29
- expect(process.project_id).to eq(LokaliseRails.project_id)
30
- expect(process.status).to eq('queued')
31
- end
32
-
33
- it 'handles too many requests' do
34
- allow_project_id '672198945b7d72fc048021.15940510'
35
- allow(LokaliseRails).to receive(:max_retries_export).and_return(2)
36
-
37
- fake_client = double
38
- allow(fake_client).to receive(:upload_file).and_raise(Lokalise::Error::TooManyRequests)
39
- allow(fake_class).to receive(:api_client).and_return(fake_client)
40
-
41
- expect(-> { fake_class.export! }).to raise_error(Lokalise::Error::TooManyRequests, /Gave up after 2 retries/i)
42
- expect(LokaliseRails).to have_received(:max_retries_export).exactly(1).times
43
- expect(fake_class).to have_received(:api_client).exactly(3).times
44
- expect(fake_client).to have_received(:upload_file).exactly(3).times
45
- end
46
- end
47
- end
48
-
49
- context 'with one translation file' do
50
- before :all do
51
- add_translation_files!
52
- end
53
-
54
- after :all do
55
- rm_translation_files
56
- end
57
-
58
- describe '.export!' do
59
- it 'sends a proper API request' do
60
- allow_project_id
61
-
62
- process = VCR.use_cassette('upload_files') do
63
- described_class.export!
64
- end.first
65
-
66
- expect(process.project_id).to eq(LokaliseRails.project_id)
67
- expect(process.status).to eq('queued')
68
- expect(LokaliseRails.max_retries_export).to eq(5)
69
- end
70
-
71
- it 'sends a proper API request when a different branch is provided' do
72
- allow_project_id
73
- allow(LokaliseRails).to receive(:branch).and_return('develop')
74
-
75
- process = VCR.use_cassette('upload_files_branch') do
76
- described_class.export!
77
- end.first
78
-
79
- expect(LokaliseRails).to have_received(:branch)
80
- expect(process.project_id).to eq(LokaliseRails.project_id)
81
- expect(process.status).to eq('queued')
82
- end
83
-
84
- it 'halts when the API key is not set' do
85
- allow(LokaliseRails).to receive(:api_token).and_return(nil)
86
-
87
- expect(-> { described_class.export! }).to raise_error(LokaliseRails::Error, /API token is not set/i)
88
- expect(LokaliseRails).to have_received(:api_token)
89
- end
90
-
91
- it 'halts when the project_id is not set' do
92
- allow_project_id nil do
93
- expect(-> { described_class.export! }).to raise_error(LokaliseRails::Error, /ID is not set/i)
94
- end
95
- end
96
- end
97
-
98
- describe '.each_file' do
99
- it 'yield proper arguments' do
100
- expect { |b| described_class.each_file(&b) }.to yield_with_args(
101
- Pathname.new(path),
102
- Pathname.new(relative_name)
103
- )
104
- end
105
- end
106
-
107
- describe '.opts' do
108
- let(:base64content) { Base64.strict_encode64(File.read(path).strip) }
109
-
110
- it 'generates proper options' do
111
- resulting_opts = described_class.opts(path, relative_name)
112
-
113
- expect(resulting_opts[:data]).to eq(base64content)
114
- expect(resulting_opts[:filename]).to eq(relative_name)
115
- expect(resulting_opts[:lang_iso]).to eq('en')
116
- end
117
-
118
- it 'allows to redefine options' do
119
- allow(LokaliseRails).to receive(:export_opts).and_return({
120
- detect_icu_plurals: true,
121
- convert_placeholders: true
122
- })
123
-
124
- resulting_opts = described_class.opts(path, relative_name)
125
-
126
- expect(LokaliseRails).to have_received(:export_opts)
127
- expect(resulting_opts[:data]).to eq(base64content)
128
- expect(resulting_opts[:filename]).to eq(relative_name)
129
- expect(resulting_opts[:lang_iso]).to eq('en')
130
- expect(resulting_opts[:detect_icu_plurals]).to be true
131
- expect(resulting_opts[:convert_placeholders]).to be true
132
- end
133
- end
134
- end
135
-
136
- context 'with two translation files' do
137
- let(:filename_ru) { 'ru.yml' }
138
- let(:path_ru) { "#{Rails.root}/config/locales/#{filename_ru}" }
139
- let(:relative_name_ru) { filename_ru }
140
-
141
- before :all do
142
- add_translation_files! with_ru: true
143
- end
144
-
145
- after :all do
146
- rm_translation_files
147
- end
148
-
149
- describe '.export!' do
150
- it 're-raises export errors' do
151
- allow_project_id
152
-
153
- VCR.use_cassette('upload_files_error') do
154
- expect { described_class.export! }.to raise_error(Lokalise::Error::BadRequest, /Unknown `lang_iso`/)
155
- end
156
- end
157
- end
158
-
159
- describe '.opts' do
160
- let(:base64content_ru) { Base64.strict_encode64(File.read(path_ru).strip) }
161
-
162
- it 'generates proper options' do
163
- resulting_opts = described_class.opts(path_ru, relative_name_ru)
164
-
165
- expect(resulting_opts[:data]).to eq(base64content_ru)
166
- expect(resulting_opts[:filename]).to eq(relative_name_ru)
167
- expect(resulting_opts[:lang_iso]).to eq('ru_RU')
168
- end
169
- end
170
-
171
- describe '.each_file' do
172
- it 'yields every translation file' do
173
- expect { |b| described_class.each_file(&b) }.to yield_successive_args(
174
- [
175
- Pathname.new(path),
176
- Pathname.new(relative_name)
177
- ],
178
- [
179
- Pathname.new(path_ru),
180
- Pathname.new(relative_name_ru)
181
- ]
182
- )
183
- end
184
-
185
- it 'does not yield files that have to be skipped' do
186
- allow(LokaliseRails).to receive(:skip_file_export).twice.and_return(
187
- ->(f) { f.split[1].to_s.include?('ru') }
188
- )
189
- expect { |b| described_class.each_file(&b) }.to yield_successive_args(
190
- [
191
- Pathname.new(path),
192
- Pathname.new(relative_name)
193
- ]
194
- )
195
-
196
- expect(LokaliseRails).to have_received(:skip_file_export).twice
197
- end
198
- end
199
- end
200
- end