localeapp 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -3
  3. data/CHANGELOG.md +12 -0
  4. data/README.md +9 -0
  5. data/bin/localeapp +141 -119
  6. data/features/add.feature +15 -49
  7. data/features/bad_command.feature +4 -3
  8. data/features/env_file.feature +7 -0
  9. data/features/environment.feature +7 -0
  10. data/features/help.feature +3 -4
  11. data/features/install.feature +19 -33
  12. data/features/install/write_env_file.feature +26 -0
  13. data/features/mv.feature +9 -5
  14. data/features/options/api_key.feature +6 -0
  15. data/features/pull.feature +15 -27
  16. data/features/push.feature +15 -28
  17. data/features/rm.feature +10 -5
  18. data/features/step_definitions/cli_steps.rb +13 -10
  19. data/features/step_definitions/execution_steps.rb +3 -0
  20. data/features/step_definitions/filesystem_steps.rb +12 -0
  21. data/features/step_definitions/output_steps.rb +10 -0
  22. data/features/support/env.rb +2 -2
  23. data/features/update.feature +20 -29
  24. data/lib/localeapp.rb +7 -0
  25. data/lib/localeapp/cli/install.rb +28 -15
  26. data/lib/localeapp/cli/pull.rb +2 -1
  27. data/lib/localeapp/cli/push.rb +2 -1
  28. data/lib/localeapp/cli/remove.rb +2 -1
  29. data/lib/localeapp/cli/rename.rb +2 -1
  30. data/lib/localeapp/configuration.rb +1 -1
  31. data/lib/localeapp/poller.rb +4 -1
  32. data/lib/localeapp/sender.rb +1 -0
  33. data/lib/localeapp/version.rb +1 -1
  34. data/spec/localeapp/cli/install_spec.rb +103 -63
  35. data/spec/localeapp/cli/pull_spec.rb +1 -1
  36. data/spec/localeapp/cli/push_spec.rb +1 -1
  37. data/spec/localeapp/cli/rename_spec.rb +1 -1
  38. metadata +10 -6
  39. data/.autotest +0 -4
  40. data/.rvmrc +0 -1
  41. data/init.rb +0 -1
data/lib/localeapp.rb CHANGED
@@ -29,10 +29,13 @@ require 'localeapp/cli/daemon'
29
29
  module Localeapp
30
30
  API_VERSION = "1"
31
31
  LOG_PREFIX = "** [Localeapp] "
32
+ ENV_FILE_PATH = ".env".freeze
32
33
 
33
34
  class LocaleappError < StandardError; end
34
35
  class PotentiallyInsecureYaml < LocaleappError; end
35
36
  class MissingApiKey < LocaleappError; end
37
+ class RuntimeError < LocaleappError; end
38
+ class APIResponseError < RuntimeError; end
36
39
 
37
40
  class << self
38
41
  # An Localeapp configuration object.
@@ -106,6 +109,10 @@ module Localeapp
106
109
  load_yaml(File.read(filename))
107
110
  end
108
111
 
112
+ def env_file_path
113
+ ENV_FILE_PATH
114
+ end
115
+
109
116
  private
110
117
 
111
118
  def private_null_type(results)
@@ -8,8 +8,9 @@ module Localeapp
8
8
  @config_type = :default
9
9
  end
10
10
 
11
- def execute(key = nil)
12
- installer("#{config_type.to_s.capitalize}Installer").execute(key)
11
+ def execute(key = nil, **options)
12
+ installer("#{config_type.to_s.capitalize}Installer")
13
+ .execute key, options
13
14
  end
14
15
 
15
16
  def installer(installer_class)
@@ -19,18 +20,22 @@ module Localeapp
19
20
  class DefaultInstaller
20
21
  attr_accessor :key, :project_data, :config_file_path, :data_directory
21
22
 
22
- def initialize(output)
23
- @output = output
23
+ def initialize(output, key_checker: Localeapp::KeyChecker.new)
24
+ @output = output
25
+ @key_checker = key_checker
24
26
  end
25
27
 
26
- def execute(key = nil)
28
+ def execute(key = nil, **options)
27
29
  self.key = key
28
30
  print_header
29
31
  if validate_key
30
- check_default_locale
32
+ print_default_locale
31
33
  set_config_paths
32
34
  @output.puts "Writing configuration file to #{config_file_path}"
33
35
  write_config_file
36
+ if options[:write_env_file]
37
+ write_env_file_apikey options[:write_env_file], key
38
+ end
34
39
  check_data_directory_exists
35
40
  true
36
41
  else
@@ -61,12 +66,13 @@ module Localeapp
61
66
  end
62
67
  end
63
68
 
64
- def check_default_locale
69
+ def print_default_locale
65
70
  localeapp_default_code = project_data['default_locale']['code']
66
- @output.puts "Default Locale: #{localeapp_default_code} (#{project_data['default_locale']['name']})"
67
- if I18n.default_locale.to_s != localeapp_default_code
68
- @output.puts "WARNING: I18n.default_locale is #{I18n.default_locale}, change in config/application.rb (Rails 3+)"
69
- end
71
+ @output.puts <<-eoh
72
+ Default Locale: #{localeapp_default_code} (#{project_data['default_locale']['name']})
73
+ Please ensure I18n.default_locale is #{localeapp_default_code} or change it in
74
+ config/application.rb
75
+ eoh
70
76
  end
71
77
 
72
78
  def set_config_paths
@@ -85,7 +91,7 @@ module Localeapp
85
91
  require 'localeapp/rails'
86
92
 
87
93
  Localeapp.configure do |config|
88
- config.api_key = '#{key}'
94
+ config.api_key = ENV['LOCALEAPP_API_KEY']
89
95
  end
90
96
  CONTENT
91
97
  end
@@ -98,10 +104,13 @@ CONTENT
98
104
  end
99
105
 
100
106
  def check_key(key)
101
- Localeapp::KeyChecker.new.check(key)
107
+ key_checker.check key
102
108
  end
103
109
 
104
110
  private
111
+
112
+ attr_reader :key_checker
113
+
105
114
  def config_dir
106
115
  File.dirname(config_file_path)
107
116
  end
@@ -109,6 +118,10 @@ CONTENT
109
118
  def create_config_dir
110
119
  FileUtils.mkdir_p(config_dir)
111
120
  end
121
+
122
+ def write_env_file_apikey(path, key)
123
+ File.open(path, "a") { |f| f.puts "LOCALEAPP_API_KEY=#{key}" }
124
+ end
112
125
  end
113
126
 
114
127
  class HerokuInstaller < DefaultInstaller
@@ -161,7 +174,7 @@ CONTENT
161
174
  end
162
175
 
163
176
  class StandaloneInstaller < DefaultInstaller
164
- def check_default_locale
177
+ def print_default_locale
165
178
  # do nothing standalone
166
179
  end
167
180
 
@@ -181,7 +194,7 @@ CONTENT
181
194
  File.open(config_file_path, 'w+') do |file|
182
195
  file.write <<-CONTENT
183
196
  Localeapp.configure do |config|
184
- config.api_key = '#{key}'
197
+ config.api_key = ENV['LOCALEAPP_API_KEY']
185
198
  config.translation_data_directory = '#{data_directory}'
186
199
  config.synchronization_data_file = '#{config_dir}/log.yml'
187
200
  config.daemon_pid_file = '#{config_dir}/localeapp.pid'
@@ -11,7 +11,7 @@ module Localeapp
11
11
  api_call :export,
12
12
  :success => :update_backend,
13
13
  :failure => :report_failure,
14
- :max_connection_attempts => 3
14
+ :max_connection_attempts => 1
15
15
  end
16
16
 
17
17
  def update_backend(response)
@@ -24,6 +24,7 @@ module Localeapp
24
24
 
25
25
  def report_failure(response)
26
26
  @output.puts "Failed!"
27
+ fail APIResponseError, "API returned #{response.code} status code"
27
28
  end
28
29
  end
29
30
  end
@@ -24,7 +24,7 @@ module Localeapp
24
24
  :payload => { :file => file },
25
25
  :success => :report_success,
26
26
  :failure => :report_failure,
27
- :max_connection_attempts => 3
27
+ :max_connection_attempts => 1
28
28
  else
29
29
  @output.puts "Could not load file"
30
30
  end
@@ -38,6 +38,7 @@ module Localeapp
38
38
 
39
39
  def report_failure(response)
40
40
  @output.puts "Failed!"
41
+ fail APIResponseError, "API returned #{response.code} status code"
41
42
  end
42
43
 
43
44
  private
@@ -11,7 +11,7 @@ module Localeapp
11
11
  :url_options => { :key => key },
12
12
  :success => :report_success,
13
13
  :failure => :report_failure,
14
- :max_connection_attempts => 3
14
+ :max_connection_attempts => 1
15
15
  end
16
16
 
17
17
  def report_success(response)
@@ -20,6 +20,7 @@ module Localeapp
20
20
 
21
21
  def report_failure(response)
22
22
  @output.puts "Failed!"
23
+ fail APIResponseError, "API returned #{response.code} status code"
23
24
  end
24
25
  end
25
26
  end
@@ -12,7 +12,7 @@ module Localeapp
12
12
  :payload => { :new_name => new_name },
13
13
  :success => :report_success,
14
14
  :failure => :report_failure,
15
- :max_connection_attempts => 3
15
+ :max_connection_attempts => 1
16
16
  end
17
17
 
18
18
  def report_success(response)
@@ -21,6 +21,7 @@ module Localeapp
21
21
 
22
22
  def report_failure(response)
23
23
  @output.puts "Failed!"
24
+ fail APIResponseError, "API returned #{response.code} status code"
24
25
  end
25
26
  end
26
27
  end
@@ -38,7 +38,7 @@ module Localeapp
38
38
  # RAILS_ROOT
39
39
  attr_accessor :project_root
40
40
 
41
- # The names of environments where notifications are sent
41
+ # The names of environments where missing translations are sent from
42
42
  # (defaults to 'development')
43
43
  attr_accessor :sending_environments
44
44
 
@@ -52,10 +52,13 @@ module Localeapp
52
52
  end
53
53
 
54
54
  def handle_failure(response)
55
- if response.code == 304
55
+ case response.code
56
+ when 304
56
57
  Localeapp.log_with_time "No new data"
57
58
  # Nothing new, update synchronization files
58
59
  write_synchronization_data!(current_time, updated_at)
60
+ when 404
61
+ fail APIResponseError, "API returned #{response.code} status code"
59
62
  end
60
63
  @success = false
61
64
  end
@@ -48,6 +48,7 @@ module Localeapp
48
48
 
49
49
  def handle_missing_translation_failure(response)
50
50
  Localeapp.log([translations_url, response.code, @data.inspect].join(' - '))
51
+ fail APIResponseError, "API returned #{response.code} status code"
51
52
  end
52
53
  end
53
54
  end
@@ -1,3 +1,3 @@
1
1
  module Localeapp
2
- VERSION = "2.1.1"
2
+ VERSION = "2.2.0"
3
3
  end
@@ -1,63 +1,78 @@
1
1
  require 'spec_helper'
2
2
  require 'localeapp/cli/install'
3
3
 
4
- describe Localeapp::CLI::Install, '.execute(key = nil)' do
5
- let(:output) { StringIO.new }
6
- let(:key) { 'MYAPIKEY' }
7
- let(:command) { Localeapp::CLI::Install.new(:output => output) }
4
+ describe Localeapp::CLI::Install, "#execute" do
5
+ let(:key) { "MYAPIKEY" }
6
+ let(:installer) { double "installer" }
7
+ subject(:command) { described_class.new output: output }
8
8
 
9
- it "creates the installer based on the config type" do
9
+ it "executes the appropriate installer based on the config type" do
10
10
  command.config_type = :heroku
11
- expect(command).to receive(:installer).with("HerokuInstaller").and_return(double.as_null_object)
12
- command.execute(key)
11
+ allow(Localeapp::CLI::Install::HerokuInstaller).to receive :new do
12
+ installer
13
+ end
14
+ expect(installer).to receive :execute
15
+ command.execute key
13
16
  end
14
17
 
15
18
  it "executes the installer with the given key" do
16
- installer = double(:installer)
17
- expect(installer).to receive(:execute).with(key)
18
- allow(command).to receive(:installer).and_return(installer)
19
- command.execute(key)
19
+ allow(Localeapp::CLI::Install::DefaultInstaller).to receive :new do
20
+ installer
21
+ end
22
+ expect(installer)
23
+ .to receive(:execute)
24
+ .with key, anything
25
+ command.execute key
26
+ end
27
+
28
+ it "executes the installer with the given options" do
29
+ allow(Localeapp::CLI::Install::DefaultInstaller).to receive :new do
30
+ installer
31
+ end
32
+ expect(installer)
33
+ .to receive(:execute)
34
+ .with anything, foo: :bar
35
+ command.execute key, foo: :bar
20
36
  end
21
37
  end
22
38
 
23
- describe Localeapp::CLI::Install::DefaultInstaller, '#execute(key = nil)' do
24
- let(:output) { StringIO.new }
25
- let(:key) { 'MYAPIKEY' }
26
- let(:installer) { Localeapp::CLI::Install::DefaultInstaller.new(output) }
39
+ describe Localeapp::CLI::Install::DefaultInstaller, "#execute" do
40
+ let(:key) { "MYAPIKEY" }
41
+ subject(:installer) { described_class.new StringIO.new }
27
42
 
28
- before do
29
- allow(installer).to receive(:print_header)
30
- allow(installer).to receive(:validate_key).and_return(false)
31
- end
43
+ context "when key validation fails" do
44
+ before do
45
+ allow(installer).to receive(:print_header)
46
+ allow(installer).to receive(:validate_key).and_return(false)
47
+ end
32
48
 
33
- it "prints the header" do
34
- expect(installer).to receive(:print_header)
35
- installer.execute
36
- end
49
+ it "prints the header" do
50
+ expect(installer).to receive(:print_header)
51
+ installer.execute
52
+ end
37
53
 
38
- it "validates the key" do
39
- expect(installer).to receive(:key=).with(key)
40
- expect(installer).to receive(:validate_key)
41
- installer.execute(key)
42
- end
54
+ it "validates the key" do
55
+ expect(installer).to receive(:key=).with(key)
56
+ expect(installer).to receive(:validate_key)
57
+ installer.execute(key)
58
+ end
43
59
 
44
- context "When key validation fails" do
45
60
  it "returns false" do
46
61
  expect(installer.execute(key)).to eq(false)
47
62
  end
48
63
  end
49
64
 
50
- context "When key validation is successful" do
65
+ context "when key validation is successful" do
51
66
  before do
52
67
  allow(installer).to receive(:validate_key).and_return(true)
53
- allow(installer).to receive(:check_default_locale)
68
+ allow(installer).to receive(:print_default_locale)
54
69
  allow(installer).to receive(:set_config_paths)
55
70
  allow(installer).to receive(:write_config_file)
56
71
  allow(installer).to receive(:check_data_directory_exists)
57
72
  end
58
73
 
59
74
  it "checks the default locale" do
60
- expect(installer).to receive(:check_default_locale)
75
+ expect(installer).to receive(:print_default_locale)
61
76
  installer.execute(key)
62
77
  end
63
78
 
@@ -80,6 +95,32 @@ describe Localeapp::CLI::Install::DefaultInstaller, '#execute(key = nil)' do
80
95
  expect(installer.execute(key)).to eq(true)
81
96
  end
82
97
  end
98
+
99
+ context "when given `write_env_file' option with a path" do
100
+ let :key_checker do
101
+ double "key checker", check: [true, Hash.new({})]
102
+ end
103
+ subject :installer do
104
+ described_class.new StringIO.new, key_checker: key_checker
105
+ end
106
+
107
+ around do |example|
108
+ Dir.mktmpdir("localeapp-spec") { |dir| Dir.chdir(dir) { example.run } }
109
+ end
110
+
111
+ it "writes the API key and a new line to the file at given path" do
112
+ installer.execute key, write_env_file: "some_env_file"
113
+ expect(File.read("some_env_file"))
114
+ .to eq "LOCALEAPP_API_KEY=#{key}\n"
115
+ end
116
+
117
+ it "appends the API key at the end of the file" do
118
+ File.open("some_env_file", "w") { |f| f.puts "FOO=BAR" }
119
+ installer.execute key, write_env_file: "some_env_file"
120
+ expect(File.read("some_env_file"))
121
+ .to match /\AFOO=BAR\nLOCALEAPP_API_KEY/
122
+ end
123
+ end
83
124
  end
84
125
 
85
126
  describe Localeapp::CLI::Install::DefaultInstaller, '#validate_key(key)' do
@@ -110,7 +151,7 @@ describe Localeapp::CLI::Install::DefaultInstaller, '#validate_key(key)' do
110
151
  end
111
152
  end
112
153
 
113
- describe Localeapp::CLI::Install::DefaultInstaller, '#check_default_locale' do
154
+ describe Localeapp::CLI::Install::DefaultInstaller, '#print_default_locale' do
114
155
  let(:output) { StringIO.new }
115
156
  let(:installer) { Localeapp::CLI::Install::DefaultInstaller.new(output) }
116
157
 
@@ -119,15 +160,13 @@ describe Localeapp::CLI::Install::DefaultInstaller, '#check_default_locale' do
119
160
  end
120
161
 
121
162
  it "displays project base locale" do
122
- installer.check_default_locale
163
+ installer.print_default_locale
123
164
  expect(output.string).to match(/en \(English\)/)
124
165
  end
125
166
 
126
- it "displays warning if I18n.default_locale doesn't match what's configured on localeapp.com" do
127
- allow(I18n).to receive(:default_locale).and_return(:es)
128
- installer.check_default_locale
129
- expect(output.string)
130
- .to match(%r{WARNING: I18n\.default_locale is es, change in config/application\.rb \(Rails 3\+\)})
167
+ it "warns that I18n.default_locale must match project locale" do
168
+ installer.print_default_locale
169
+ expect(output.string).to include "Please ensure I18n.default_locale is en"
131
170
  end
132
171
  end
133
172
 
@@ -148,24 +187,25 @@ describe Localeapp::CLI::Install::DefaultInstaller, '#set_config_paths' do
148
187
  end
149
188
  end
150
189
 
151
- describe Localeapp::CLI::Install::DefaultInstaller, '#write_config_file' do
152
- let(:output) { StringIO.new }
153
- let(:config_file_path) { 'config/initializers/localeapp.rb' }
154
- let(:key) { 'APIKEY' }
155
- let(:installer) { Localeapp::CLI::Install::DefaultInstaller.new(output) }
190
+ describe Localeapp::CLI::Install::DefaultInstaller, "#write_config_file" do
191
+ let(:config_file_path) { "config/initializers/localeapp.rb" }
192
+ let(:key) { "APIKEY" }
193
+ let(:file) { double "file" }
194
+ subject(:installer) { described_class.new StringIO.new }
156
195
 
157
- it "creates a configuration file containing just the api key" do
158
- installer.key = key
196
+ before do
197
+ allow(File).to receive(:open).and_yield file
159
198
  installer.config_file_path = config_file_path
160
- file = double('file')
199
+ end
200
+
201
+ it "creates a configuration file reading the API key from the environment" do
161
202
  expect(file).to receive(:write).with <<-CONTENT
162
203
  require 'localeapp/rails'
163
204
 
164
205
  Localeapp.configure do |config|
165
- config.api_key = 'APIKEY'
206
+ config.api_key = ENV['LOCALEAPP_API_KEY']
166
207
  end
167
208
  CONTENT
168
- expect(File).to receive(:open).with(config_file_path, 'w+').and_yield(file)
169
209
  installer.write_config_file
170
210
  end
171
211
  end
@@ -222,12 +262,12 @@ CONTENT
222
262
  installer.write_config_file
223
263
  end
224
264
  end
225
- describe Localeapp::CLI::Install::StandaloneInstaller, '#check_default_locale' do
265
+ describe Localeapp::CLI::Install::StandaloneInstaller, '#print_default_locale' do
226
266
  let(:output) { StringIO.new }
227
267
  let(:installer) { Localeapp::CLI::Install::StandaloneInstaller.new(output) }
228
268
 
229
269
  it "does nothing" do
230
- installer.check_default_locale
270
+ installer.print_default_locale
231
271
  expect(output.string).to eq('')
232
272
  end
233
273
  end
@@ -249,28 +289,28 @@ describe Localeapp::CLI::Install::StandaloneInstaller, '#set_config_paths' do
249
289
  end
250
290
  end
251
291
 
252
- describe Localeapp::CLI::Install::StandaloneInstaller, '#write_config_file' do
253
- let(:output) { StringIO.new }
254
- let(:key) { 'APIKEY' }
255
- let(:config_file_path) { '.localeapp/config.rb' }
256
- let(:data_directory) { 'locales' }
257
- let(:installer) { Localeapp::CLI::Install::StandaloneInstaller.new(output) }
292
+ describe Localeapp::CLI::Install::StandaloneInstaller, "#write_config_file" do
293
+ let(:key) { "APIKEY" }
294
+ let(:config_file_path) { ".localeapp/config.rb" }
295
+ let(:data_directory) { "locales" }
296
+ let(:file) { double "file" }
297
+ subject(:installer) { described_class.new StringIO.new }
258
298
 
259
- it "creates a configuration file containing the dot file configuration at the given config_file_path" do
260
- allow(installer).to receive(:create_config_dir).and_return(File.dirname(config_file_path))
261
- installer.key = key
299
+ before do
300
+ allow(File).to receive(:open).and_yield file
262
301
  installer.config_file_path = config_file_path
263
302
  installer.data_directory = data_directory
264
- file = double('file')
303
+ end
304
+
305
+ it "creates a configuration file using given config_file_path" do
265
306
  expect(file).to receive(:write).with <<-CONTENT
266
307
  Localeapp.configure do |config|
267
- config.api_key = 'APIKEY'
308
+ config.api_key = ENV['LOCALEAPP_API_KEY']
268
309
  config.translation_data_directory = 'locales'
269
310
  config.synchronization_data_file = '.localeapp/log.yml'
270
311
  config.daemon_pid_file = '.localeapp/localeapp.pid'
271
312
  end
272
313
  CONTENT
273
- expect(File).to receive(:open).with(config_file_path, 'w+').and_yield(file)
274
314
  installer.write_config_file
275
315
  end
276
316
  end