lokalise_manager 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe LokaliseManager::TaskDefinitions::Importer do
4
+ let(:described_object) do
5
+ described_class.new project_id: project_id,
6
+ api_token: ENV['LOKALISE_API_TOKEN'],
7
+ max_retries_import: 2
8
+ end
9
+ let(:loc_path) { described_object.config.locales_path }
10
+ let(:project_id) { ENV['LOKALISE_PROJECT_ID'] }
11
+ let(:local_trans) { "#{Dir.getwd}/spec/fixtures/trans.zip" }
12
+ let(:faulty_trans) { "#{Dir.getwd}/spec/fixtures/faulty_trans.zip" }
13
+
14
+ describe '.open_and_process_zip' do
15
+ it 're-raises errors during file processing' do
16
+ expect(-> { described_object.send(:open_and_process_zip, faulty_trans) }).
17
+ to raise_error(Psych::DisallowedClass, /Error when trying to process fail\.yml/)
18
+ end
19
+
20
+ it 're-raises errors during file opening' do
21
+ expect(-> { described_object.send(:open_and_process_zip, 'http://fake.url/wrong/path.zip') }).
22
+ to raise_error(SocketError, /Failed to open TCP connection/)
23
+ end
24
+ end
25
+
26
+ describe '.download_files' do
27
+ it 'returns a proper download URL' do
28
+ response = VCR.use_cassette('download_files') do
29
+ described_object.send :download_files
30
+ end
31
+
32
+ expect(response['project_id']).to eq('672198945b7d72fc048021.15940510')
33
+ expect(response['bundle_url']).to include('s3-eu-west-1.amazonaws.com')
34
+ expect(described_object.api_client.enable_compression).to eq(true)
35
+ end
36
+
37
+ it 're-raises errors during file download' do
38
+ allow_project_id described_object, 'invalid'
39
+
40
+ VCR.use_cassette('download_files_error') do
41
+ expect(-> { described_object.send :download_files }).
42
+ to raise_error(Lokalise::Error::BadRequest, /Invalid `project_id` parameter/)
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '.import!' do
48
+ context 'with errors' do
49
+ it 'handles too many requests' do
50
+ allow(described_object).to receive(:sleep).and_return(0)
51
+
52
+ fake_client = instance_double('Lokalise::Client')
53
+ allow(fake_client).to receive(:download_files).and_raise(Lokalise::Error::TooManyRequests)
54
+ allow(described_object).to receive(:api_client).and_return(fake_client)
55
+
56
+ expect(-> { described_object.import! }).to raise_error(Lokalise::Error::TooManyRequests, /Gave up after 2 retries/i)
57
+
58
+ expect(described_object).to have_received(:sleep).exactly(2).times
59
+ expect(described_object).to have_received(:api_client).exactly(3).times
60
+ expect(fake_client).to have_received(:download_files).exactly(3).times
61
+ end
62
+
63
+ it 'halts when the API key is not set' do
64
+ allow(described_object.config).to receive(:api_token).and_return(nil)
65
+ expect(-> { described_object.import! }).to raise_error(LokaliseManager::Error, /API token is not set/i)
66
+ expect(described_object.config).to have_received(:api_token)
67
+ expect(count_translations).to eq(0)
68
+ end
69
+
70
+ it 'halts when the project_id is not set' do
71
+ allow_project_id described_object, nil do
72
+ expect(-> { described_object.import! }).to raise_error(LokaliseManager::Error, /ID is not set/i)
73
+ expect(count_translations).to eq(0)
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'when directory is empty' do
79
+ before do
80
+ mkdir_locales
81
+ rm_translation_files
82
+ end
83
+
84
+ after :all do
85
+ rm_translation_files
86
+ end
87
+
88
+ it 'runs import successfully for local files' do
89
+ allow(described_object).to receive(:download_files).and_return(
90
+ {
91
+ 'project_id' => '123.abc',
92
+ 'bundle_url' => local_trans
93
+ }
94
+ )
95
+
96
+ expect(described_object.import!).to be true
97
+
98
+ expect(count_translations).to eq(4)
99
+ expect(described_object).to have_received(:download_files)
100
+ expect_file_exist loc_path, 'en/nested/main_en.yml'
101
+ expect_file_exist loc_path, 'en/nested/deep/secondary_en.yml'
102
+ expect_file_exist loc_path, 'ru/main_ru.yml'
103
+ end
104
+
105
+ it 'runs import successfully' do
106
+ result = VCR.use_cassette('import') do
107
+ described_object.import!
108
+ end
109
+
110
+ expect(result).to be true
111
+
112
+ expect(count_translations).to eq(8)
113
+ expect_file_exist loc_path, 'en.yml'
114
+ expect_file_exist loc_path, 'ru.yml'
115
+ end
116
+ end
117
+
118
+ context 'when directory is not empty and safe mode enabled' do
119
+ let(:safe_mode_obj) do
120
+ described_class.new project_id: project_id,
121
+ api_token: ENV['LOKALISE_API_TOKEN'],
122
+ import_safe_mode: true
123
+ end
124
+
125
+ before :all do
126
+ mkdir_locales
127
+ end
128
+
129
+ before do
130
+ rm_translation_files
131
+ add_translation_files!
132
+ end
133
+
134
+ after :all do
135
+ rm_translation_files
136
+ end
137
+
138
+ it 'import proceeds when the user agrees' do
139
+ allow(safe_mode_obj).to receive(:download_files).and_return(
140
+ {
141
+ 'project_id' => '123.abc',
142
+ 'bundle_url' => local_trans
143
+ }
144
+ )
145
+
146
+ allow($stdin).to receive(:gets).and_return('Y')
147
+ expect(-> { safe_mode_obj.import! }).to output(/is not empty/).to_stdout
148
+
149
+ expect(count_translations).to eq(5)
150
+ expect($stdin).to have_received(:gets)
151
+ expect(safe_mode_obj).to have_received(:download_files)
152
+ expect_file_exist loc_path, 'en/nested/main_en.yml'
153
+ expect_file_exist loc_path, 'en/nested/deep/secondary_en.yml'
154
+ expect_file_exist loc_path, 'ru/main_ru.yml'
155
+ end
156
+
157
+ it 'import halts when a user chooses not to proceed' do
158
+ allow(safe_mode_obj).to receive(:download_files).at_most(0).times
159
+ allow($stdin).to receive(:gets).and_return('N')
160
+ expect(-> { safe_mode_obj.import! }).to output(/is not empty/).to_stdout
161
+
162
+ expect(safe_mode_obj).not_to have_received(:download_files)
163
+ expect($stdin).to have_received(:gets)
164
+ expect(count_translations).to eq(1)
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe LokaliseManager do
4
+ it 'returns a proper version' do
5
+ expect(described_class::VERSION).to be_a(String)
6
+ end
7
+
8
+ specify '.importer' do
9
+ expect(described_class.importer).to be_a(LokaliseManager::TaskDefinitions::Importer)
10
+ end
11
+
12
+ specify '.exporter' do
13
+ expect(described_class.exporter).to be_a(LokaliseManager::TaskDefinitions::Exporter)
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dotenv/load'
4
+ require 'simplecov'
5
+
6
+ SimpleCov.start do
7
+ add_filter 'spec/'
8
+ add_filter '.github/'
9
+ end
10
+
11
+ if ENV['CI'] == 'true'
12
+ require 'codecov'
13
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
14
+ end
15
+
16
+ require 'lokalise_manager'
17
+
18
+ # Support files
19
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |f| require f }
20
+
21
+ RSpec.configure do |config|
22
+ config.include FileManager
23
+ config.include SpecAddons
24
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module FileManager
6
+ def mkdir_locales
7
+ FileUtils.mkdir_p(LokaliseManager::GlobalConfig.locales_path) unless File.directory?(LokaliseManager::GlobalConfig.locales_path)
8
+ end
9
+
10
+ def rm_translation_files
11
+ FileUtils.rm_rf locales_dir
12
+ end
13
+
14
+ def locales_dir
15
+ Dir["#{LokaliseManager::GlobalConfig.locales_path}/**/*"]
16
+ end
17
+
18
+ def count_translations
19
+ locales_dir.count { |file| File.file?(file) }
20
+ end
21
+
22
+ def add_translation_files!(with_ru: false, additional: nil)
23
+ FileUtils.mkdir_p "#{Dir.getwd}/locales/nested"
24
+ open_and_write('locales/nested/en.yml') { |f| f.write en_data }
25
+
26
+ return unless with_ru
27
+
28
+ open_and_write('locales/ru.yml') { |f| f.write ru_data }
29
+
30
+ return unless additional
31
+
32
+ additional.times do |i|
33
+ data = {'en' => {"key_#{i}" => "value #{i}"}}
34
+
35
+ open_and_write("locales/en_#{i}.yml") { |f| f.write data.to_yaml }
36
+ end
37
+ end
38
+
39
+ def open_and_write(rel_path, &block)
40
+ return unless block
41
+
42
+ File.open("#{Dir.getwd}/#{rel_path}", 'w+:UTF-8', &block)
43
+ end
44
+
45
+ private
46
+
47
+ def en_data
48
+ <<~DATA
49
+ en:
50
+ my_key: "My value"
51
+ nested:
52
+ key: "Value 2"
53
+ DATA
54
+ end
55
+
56
+ def ru_data
57
+ <<~DATA
58
+ ru_RU:
59
+ my_key: "Моё значение"
60
+ nested:
61
+ key: "Значение 2"
62
+ DATA
63
+ end
64
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SpecAddons
4
+ def allow_project_id(obj, value)
5
+ allow(obj.config).to receive(:project_id).and_return(value)
6
+ return unless block_given?
7
+
8
+ yield
9
+ expect(obj.config).to have_received(:project_id)
10
+ end
11
+
12
+ def expect_file_exist(path, file)
13
+ file_path = File.join path, file
14
+ expect(File.file?(file_path)).to be true
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vcr'
4
+
5
+ VCR.configure do |c|
6
+ c.ignore_hosts 'codeclimate.com'
7
+ c.hook_into :faraday
8
+ c.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes')
9
+ c.filter_sensitive_data('<LOKALISE_TOKEN>') { ENV.fetch('LOKALISE_API_TOKEN') }
10
+ c.configure_rspec_metadata!
11
+ end
metadata ADDED
@@ -0,0 +1,233 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lokalise_manager
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ilya Bodrov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-10-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby-lokalise-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubyzip
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: codecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: dotenv
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '13.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '13.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.6'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-performance
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.5'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 2.5.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 2.5.0
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.16'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.16'
153
+ - !ruby/object:Gem::Dependency
154
+ name: vcr
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '6.0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '6.0'
167
+ description: This gem contains a collection of some common tasks for Lokalise. Specifically,
168
+ it allows to import/export translation files from/to Lokalise TMS.
169
+ email:
170
+ - golosizpru@gmail.com
171
+ executables: []
172
+ extensions: []
173
+ extra_rdoc_files:
174
+ - README.md
175
+ files:
176
+ - ".github/CODE_OF_CONDUCT.md"
177
+ - ".github/CONTRIBUTING.md"
178
+ - ".github/PULL_REQUEST_TEMPLATE.md"
179
+ - CHANGELOG.md
180
+ - Gemfile
181
+ - LICENSE
182
+ - README.md
183
+ - Rakefile
184
+ - lib/lokalise_manager.rb
185
+ - lib/lokalise_manager/error.rb
186
+ - lib/lokalise_manager/global_config.rb
187
+ - lib/lokalise_manager/task_definitions/base.rb
188
+ - lib/lokalise_manager/task_definitions/exporter.rb
189
+ - lib/lokalise_manager/task_definitions/importer.rb
190
+ - lib/lokalise_manager/version.rb
191
+ - lokalise_manager.gemspec
192
+ - spec/lib/lokalise_manager/global_config_spec.rb
193
+ - spec/lib/lokalise_manager/task_definitions/base_spec.rb
194
+ - spec/lib/lokalise_manager/task_definitions/exporter_spec.rb
195
+ - spec/lib/lokalise_manager/task_definitions/importer_spec.rb
196
+ - spec/lib/lokalise_manager_spec.rb
197
+ - spec/spec_helper.rb
198
+ - spec/support/file_manager.rb
199
+ - spec/support/spec_addons.rb
200
+ - spec/support/vcr.rb
201
+ homepage: https://github.com/bodrovis/lokalise_manager
202
+ licenses:
203
+ - MIT
204
+ metadata: {}
205
+ post_install_message:
206
+ rdoc_options: []
207
+ require_paths:
208
+ - lib
209
+ required_ruby_version: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: 2.5.0
214
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - ">="
217
+ - !ruby/object:Gem::Version
218
+ version: '0'
219
+ requirements: []
220
+ rubygems_version: 3.2.26
221
+ signing_key:
222
+ specification_version: 4
223
+ summary: Lokalise integration for Ruby
224
+ test_files:
225
+ - spec/lib/lokalise_manager/global_config_spec.rb
226
+ - spec/lib/lokalise_manager/task_definitions/base_spec.rb
227
+ - spec/lib/lokalise_manager/task_definitions/exporter_spec.rb
228
+ - spec/lib/lokalise_manager/task_definitions/importer_spec.rb
229
+ - spec/lib/lokalise_manager_spec.rb
230
+ - spec/spec_helper.rb
231
+ - spec/support/file_manager.rb
232
+ - spec/support/spec_addons.rb
233
+ - spec/support/vcr.rb