localeapp 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.autotest +4 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/.rvmrc +1 -0
  5. data/.travis.yml +7 -0
  6. data/Gemfile +2 -0
  7. data/README.textile +147 -0
  8. data/Rakefile +11 -0
  9. data/bin/localeapp +61 -0
  10. data/cucumber.yml +8 -0
  11. data/features/localeapp_binary.feature +116 -0
  12. data/features/step_definitions/cli_steps.rb +27 -0
  13. data/features/support/env.rb +21 -0
  14. data/features/support/hooks.rb +3 -0
  15. data/init.rb +1 -0
  16. data/lib/locale_app/api_call.rb +9 -0
  17. data/lib/locale_app/api_caller.rb +77 -0
  18. data/lib/locale_app/cli/install.rb +41 -0
  19. data/lib/locale_app/cli/pull.rb +34 -0
  20. data/lib/locale_app/cli/push.rb +49 -0
  21. data/lib/locale_app/cli/update.rb +19 -0
  22. data/lib/locale_app/configuration.rb +93 -0
  23. data/lib/locale_app/exception_handler.rb +21 -0
  24. data/lib/locale_app/key_checker.rb +43 -0
  25. data/lib/locale_app/missing_translations.rb +36 -0
  26. data/lib/locale_app/poller.rb +61 -0
  27. data/lib/locale_app/rails/2_3_translation_helper_monkeypatch.rb +36 -0
  28. data/lib/locale_app/rails/controller.rb +34 -0
  29. data/lib/locale_app/rails/flatten.rb +113 -0
  30. data/lib/locale_app/rails.rb +53 -0
  31. data/lib/locale_app/routes.rb +80 -0
  32. data/lib/locale_app/sender.rb +49 -0
  33. data/lib/locale_app/tasks/locale_app.rake +20 -0
  34. data/lib/locale_app/updater.rb +63 -0
  35. data/lib/locale_app/version.rb +3 -0
  36. data/lib/locale_app.rb +98 -0
  37. data/lib/localeapp.rb +1 -0
  38. data/localeapp.gemspec +35 -0
  39. data/run_ci +5 -0
  40. data/spec/fixtures/en.yml +6 -0
  41. data/spec/fixtures/es.yml +6 -0
  42. data/spec/locale_app/api_call_spec.rb +15 -0
  43. data/spec/locale_app/api_caller_spec.rb +157 -0
  44. data/spec/locale_app/cli/install_spec.rb +42 -0
  45. data/spec/locale_app/cli/pull_spec.rb +45 -0
  46. data/spec/locale_app/cli/push_spec.rb +30 -0
  47. data/spec/locale_app/cli/update_spec.rb +18 -0
  48. data/spec/locale_app/configuration_spec.rb +119 -0
  49. data/spec/locale_app/exception_handler_spec.rb +21 -0
  50. data/spec/locale_app/key_checker_spec.rb +19 -0
  51. data/spec/locale_app/missing_translations_spec.rb +28 -0
  52. data/spec/locale_app/poller_spec.rb +61 -0
  53. data/spec/locale_app/rails/controller_spec.rb +117 -0
  54. data/spec/locale_app/routes_spec.rb +134 -0
  55. data/spec/locale_app/sender_spec.rb +49 -0
  56. data/spec/locale_app/updater_spec.rb +89 -0
  57. data/spec/spec_helper.rb +24 -0
  58. data/spec/support/locale_app_integration_data.rb +33 -0
  59. data/spec/support/locale_app_synchronization_data.rb +21 -0
  60. metadata +300 -0
@@ -0,0 +1,63 @@
1
+ module LocaleApp
2
+ class Updater
3
+
4
+ def update(data)
5
+ data['locales'].each do |short_code|
6
+ filename = File.join(LocaleApp.configuration.translation_data_directory, "#{short_code}.yml")
7
+
8
+ if File.exist?(filename)
9
+ translations = YAML.load(File.read(filename))
10
+ if data['translations'] && data['translations'][short_code]
11
+ new_data = { short_code => data['translations'][short_code] }
12
+ translations.deep_merge!(new_data)
13
+ end
14
+ else
15
+ translations = { short_code => data['translations'][short_code] }
16
+ end
17
+
18
+ if data['deleted']
19
+ data['deleted'].each do |key|
20
+ remove_flattened_key!(translations, short_code, key)
21
+ end
22
+ end
23
+
24
+ if translations[short_code]
25
+ atomic_write(filename) do |file|
26
+ file.write translations.ya2yaml[5..-1]
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+ def remove_flattened_key!(hash, locale, key)
34
+ keys = I18n.normalize_keys(locale, key, '').map(&:to_s)
35
+ current_key = keys.shift
36
+ remove_child_keys!(hash[current_key], keys)
37
+ hash
38
+ end
39
+
40
+ def remove_child_keys!(sub_hash, keys)
41
+ current_key = keys.shift
42
+ if keys.empty?
43
+ sub_hash.delete(current_key)
44
+ else
45
+ child_hash = sub_hash[current_key]
46
+ unless child_hash.nil?
47
+ remove_child_keys!(child_hash, keys)
48
+ if child_hash.empty?
49
+ sub_hash.delete(current_key)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ # from ActiveSupport
56
+ def atomic_write(file_name, temp_dir = Dir.tmpdir)
57
+ temp_file = Tempfile.new(File.basename(file_name), temp_dir)
58
+ yield temp_file
59
+ temp_file.close
60
+ File.rename(temp_file.path, file_name)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ module LocaleApp
2
+ VERSION = "0.0.7"
3
+ end
data/lib/locale_app.rb ADDED
@@ -0,0 +1,98 @@
1
+ # AUDIT: Find a better way of doing this
2
+ begin
3
+ require 'i18n'
4
+ rescue LoadError
5
+ # we're in 2.3 and we need to load rails to get the vendored i18n
6
+ require 'thread' # for rubygems > 1.6.0 support
7
+ require 'active_support'
8
+ end
9
+
10
+ begin
11
+ require 'i18n/core_ext/hash'
12
+ rescue LoadError
13
+ # Assume that we're in rails 2.3 and AS supplies deep_merge
14
+ end
15
+
16
+
17
+ require 'locale_app/version'
18
+ require 'locale_app/configuration'
19
+ require 'locale_app/routes'
20
+ require 'locale_app/api_call'
21
+ require 'locale_app/api_caller'
22
+ require 'locale_app/sender'
23
+ require 'locale_app/poller'
24
+ require 'locale_app/updater'
25
+ require 'locale_app/key_checker'
26
+ require 'locale_app/missing_translations'
27
+
28
+ require 'locale_app/cli/install'
29
+ require 'locale_app/cli/pull'
30
+ require 'locale_app/cli/push'
31
+ require 'locale_app/cli/update'
32
+
33
+ # AUDIT: Will this work on ruby 1.9.x
34
+ $KCODE="UTF8" if RUBY_VERSION < '1.9'
35
+
36
+ require 'ya2yaml'
37
+
38
+ module LocaleApp
39
+ API_VERSION = "1"
40
+ LOG_PREFIX = "** [LocaleApp] "
41
+
42
+ class << self
43
+ # An LocaleApp configuration object.
44
+ attr_accessor :configuration
45
+
46
+ # The sender object is responsible for delivering formatted data to the LocaleApp server.
47
+ attr_accessor :sender
48
+
49
+ # The poller object is responsible for retrieving data for the LocaleApp server
50
+ attr_accessor :poller
51
+
52
+ # The updater object is responsible for merging translations into the i18n backend
53
+ attr_accessor :updater
54
+
55
+ # The missing_translations object is responsible for keeping track of missing translations
56
+ # that will be sent to the backend
57
+ attr_reader :missing_translations
58
+
59
+
60
+ # Writes out the given message to the #logger
61
+ def log(message)
62
+ logger.info LOG_PREFIX + message if logger
63
+ end
64
+
65
+ def debug(message)
66
+ logger.debug(LOG_PREFIX + message) if logger
67
+ end
68
+
69
+ # Look for the Rails logger currently defined
70
+ def logger
71
+ self.configuration && self.configuration.logger
72
+ end
73
+
74
+ # @example Configuration
75
+ # LocaleApp.configure do |config|
76
+ # config.api_key = '1234567890abcdef'
77
+ # end
78
+ def configure
79
+ self.configuration ||= Configuration.new
80
+ yield(configuration)
81
+ self.sender = Sender.new
82
+ self.poller = Poller.new
83
+ self.updater = Updater.new
84
+ @missing_translations = MissingTranslations.new
85
+ end
86
+
87
+ # requires the LocaleApp configuration
88
+ def include_config_file(file_path=nil)
89
+ file_path ||= File.join(Dir.pwd, 'config', 'initializers', 'locale_app')
90
+ begin
91
+ require file_path
92
+ true
93
+ rescue
94
+ false
95
+ end
96
+ end
97
+ end
98
+ end
data/lib/localeapp.rb ADDED
@@ -0,0 +1 @@
1
+ require File.expand_path("locale_app.rb",File.dirname(__FILE__))
data/localeapp.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "locale_app/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "localeapp"
7
+ s.version = LocaleApp::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Christopher Dell", "Chris McGrath"]
10
+ s.email = ["chris@tigrish.com", "chris@octopod.info"]
11
+ s.homepage = "http://rubygems.org/gems/localeapp"
12
+ s.summary = %q{Add missing translation keys to localeapp.com}
13
+ s.description = %q{Post any unfound translation keys to the Locale SaaS}
14
+
15
+ s.rubyforge_project = "localeapp"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency('json')
23
+ s.add_dependency('rest-client')
24
+ s.add_dependency('ya2yaml')
25
+
26
+ # i18n is a dev dependency as we'll use whichever version is in rails
27
+ # when the gem runs
28
+ s.add_development_dependency('i18n', '0.5.0')
29
+ s.add_development_dependency('rake')
30
+ s.add_development_dependency('rspec', '2.5.0')
31
+ s.add_development_dependency('yard', '0.6.7')
32
+ s.add_development_dependency('RedCloth', '4.2.7')
33
+ s.add_development_dependency('aruba', '0.3.6')
34
+ s.add_development_dependency('fakeweb', '1.3.0')
35
+ end
data/run_ci ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+ source "$HOME/.rvm/scripts/rvm"
3
+ rvm gemset use $BUILD_RUBY_VERSION@locale_app
4
+ bundle install
5
+ rake
@@ -0,0 +1,6 @@
1
+ en:
2
+ bar:
3
+ delete_me_too: Delete
4
+ foo:
5
+ delete_me: Delete
6
+ monkey: Monkey
@@ -0,0 +1,6 @@
1
+ es:
2
+ bar:
3
+ delete_me_too: ES_Delete
4
+ foo:
5
+ delete_me: ES_Delete
6
+ monkey: Mono
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ class ApiCallTest
4
+ include LocaleApp::ApiCall
5
+ end
6
+
7
+ describe LocaleApp::ApiCall, "#api_call(endpoint, options = {})" do
8
+ it "creates an ApiCaller object and tells it to make the call" do
9
+ api_call_test = ApiCallTest.new
10
+ api_call = double('api_call')
11
+ api_call.should_receive(:call).with(api_call_test)
12
+ LocaleApp::ApiCaller.should_receive(:new).with(:endpoint, { :foo => :bar }).and_return(api_call)
13
+ api_call_test.api_call(:endpoint, { :foo => :bar })
14
+ end
15
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+
3
+ describe LocaleApp::ApiCaller, ".new(endpoint, options = {})" do
4
+ it "stores the endpoint and options" do
5
+ api_caller = LocaleApp::ApiCaller.new(:endpoint, :foo => :bar)
6
+ api_caller.endpoint.should == :endpoint
7
+ api_caller.options.should == { :foo => :bar }
8
+ end
9
+ end
10
+
11
+ describe LocaleApp::ApiCaller, "#call(object)" do
12
+ before do
13
+ @api_caller = LocaleApp::ApiCaller.new(:test)
14
+ @url = 'http://example.com/test'
15
+ @api_caller.stub!(:test_endpoint).and_return([:get, @url])
16
+ @api_caller.stub!(:sleep_if_retrying)
17
+ end
18
+
19
+ it "gets the method and url for the endpoint" do
20
+ @api_caller.should_receive(:test_endpoint).with({}).and_return([:get, @url])
21
+ RestClient.stub!(:get).and_return(double('response', :code => 200))
22
+ @api_caller.call(self)
23
+ end
24
+
25
+ it "passes through any url options" do
26
+ @api_caller.should_receive(:test_endpoint).with({:foo => :bar}).and_return([:get, @url])
27
+ @api_caller.options[:url_options] = { :foo => :bar }
28
+ RestClient.stub!(:get).and_return(double('response', :code => 200))
29
+ @api_caller.call(self)
30
+ end
31
+
32
+ context "a GET request" do
33
+ it "makes the call to the api" do
34
+ RestClient.should_receive(:get).with(@url, {}).and_return(double('response', :code => 200))
35
+ @api_caller.call(self)
36
+ end
37
+
38
+ it "adds any :request_options to the api call" do
39
+ RestClient.should_receive(:get).with(@url, :foo => :bar).and_return(double('response', :code => 200))
40
+ @api_caller.options[:request_options] = { :foo => :bar }
41
+ @api_caller.call(self)
42
+ end
43
+ end
44
+
45
+
46
+ context " a POST request" do
47
+ before do
48
+ @api_caller.stub!(:test_endpoint).and_return([:post, @url])
49
+ @api_caller.options[:payload] = "test data"
50
+ end
51
+
52
+ it "makes the call to the api using :payload as the payload" do
53
+ RestClient.should_receive(:post).with(@url, "test data", {}).and_return(double('response', :code => 200))
54
+ @api_caller.call(self)
55
+ end
56
+
57
+ it "adds any :request_options to the api call" do
58
+ RestClient.should_receive(:post).with(@url, "test data", :foo => :bar).and_return(double('response', :code => 200))
59
+ @api_caller.options[:request_options] = { :foo => :bar }
60
+ @api_caller.call(self)
61
+ end
62
+ end
63
+
64
+ context " call succeeded" do
65
+ before do
66
+ FakeWeb.register_uri(:get, @url, :body => '', :status => [200, 'OK'])
67
+ @object = double('calling object')
68
+ end
69
+
70
+ it "calls the :success option callback if present" do
71
+ @api_caller.options[:success] = :success
72
+ @object.should_receive(:success).with(kind_of(RestClient::Response))
73
+ @api_caller.call(@object)
74
+ end
75
+
76
+ it "does nothing if :success option callback not present" do
77
+ @object.should_not_receive(:success)
78
+ @api_caller.call(@object)
79
+ end
80
+
81
+ it "should not try the call again" do
82
+ @api_caller.max_connection_attempts = 2
83
+ @api_caller.call(@object)
84
+ @api_caller.connection_attempts.should == 1
85
+ end
86
+
87
+ it "doesn't call the failure handler" do
88
+ @api_caller.options[:failure] = :failure
89
+ @object.should_not_receive(:failure)
90
+ @api_caller.call(@object)
91
+ end
92
+ end
93
+
94
+ context " call failed" do
95
+ before do
96
+ FakeWeb.register_uri(:get, @url, :body => '', :status => [500, 'Internal Server Error'])
97
+ @object = double('calling object')
98
+ end
99
+
100
+ it "retries call, up to value of :max_connection_attempts option" do
101
+ @api_caller.max_connection_attempts = 2
102
+ @api_caller.call(@object)
103
+ @api_caller.connection_attempts.should == 2
104
+ end
105
+
106
+ it "backs off each retry attempt" do
107
+ @api_caller.should_receive(:sleep_if_retrying)
108
+ @api_caller.call(@object)
109
+ end
110
+
111
+ it "calls the :failure option callback if present" do
112
+ @api_caller.options[:failure] = :fail
113
+ @object.should_receive(:fail).with(kind_of(RestClient::Response))
114
+ @api_caller.call(@object)
115
+ end
116
+
117
+ it "does nothing if :failure option callback not present" do
118
+ @object.should_not_receive(:fail)
119
+ @api_caller.call(@object)
120
+ end
121
+
122
+ {
123
+ 304 => 'Not Modified',
124
+ 404 => 'Resource Not Found',
125
+ 500 => 'Internal Server Error',
126
+ # Work out when this could happen
127
+ # 501 => 'Not Implemented',
128
+ 502 => 'Bad Gateway',
129
+ 503 => 'Service Unavailable',
130
+ 504 => 'Gateway Timeout',
131
+ # Work out when this could happen
132
+ # 505 => 'HTTP Version Not Supported',
133
+ # Work out when this could happen
134
+ # 506 => 'Variant Also Negotiates',
135
+ # Work out when this could happen
136
+ # 507 => 'Insufficient Storage', #WebDAV
137
+ # Work out when this could happen
138
+ # 509 => 'Bandwidth Limit Exceeded', #Apache
139
+ # Work out when this could happen
140
+ # 510 => 'Not Extended'
141
+ }.each do |code, reason|
142
+ it "fails when response is #{code} #{reason}" do
143
+ FakeWeb.register_uri(:get, @url, :body => '', :status => [code.to_s, reason])
144
+ @api_caller.options[:failure] = :fail
145
+ @object.should_receive(:fail)
146
+ @api_caller.call(@object)
147
+ end
148
+ end
149
+
150
+ it "handles ECONNREFUSED" do
151
+ RestClient.stub(:send).and_raise(Errno::ECONNREFUSED)
152
+ @api_caller.options[:failure] = :fail
153
+ @object.should_receive(:fail)
154
+ @api_caller.call(@object)
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'locale_app/cli/install'
3
+
4
+ describe LocaleApp::CLI::Install, '.execute(key, output = $stdout)' do
5
+ before(:each) do
6
+ @output = StringIO.new
7
+ @command = LocaleApp::CLI::Install.new
8
+ end
9
+
10
+ it "displays error if key is nil" do
11
+ @command.execute(nil, @output)
12
+ @output.string.should match(/You must supply an API key/)
13
+ end
14
+
15
+ it "displays error if the key is there but isn't valid on localeapp.com" do
16
+ @command.stub!(:check_key).and_return([false, {}])
17
+ @command.execute('API_KEY', @output)
18
+ @output.string.should match(/Project not found/)
19
+ end
20
+
21
+ it "displays project name and base locale if the key is there and valid on localeapp.com" do
22
+ @command.stub!(:check_key).and_return([true, valid_project_data])
23
+ @command.stub!(:write_configuration_file)
24
+ @command.execute('API_KEY', @output)
25
+ @output.string.should match(/Test Project/)
26
+ @output.string.should match(/en \(English\)/)
27
+ end
28
+
29
+ it "displays warning if I18n.default_locale doesn't match what's configured on localeapp.com" do
30
+ I18n.stub(:default_locale).and_return(:es)
31
+ @command.stub!(:check_key).and_return([true, valid_project_data])
32
+ @command.stub!(:write_configuration_file)
33
+ @command.execute('API_KEY', @output)
34
+ @output.string.should match(%r{WARNING: I18n.default_locale is es, change in config/environment.rb \(Rails 2\) or config/application.rb \(Rails 3\)})
35
+ end
36
+
37
+ it "asks the default configuration to write itself" do
38
+ @command.stub!(:check_key).and_return([true, valid_project_data])
39
+ @command.should_receive(:write_configuration_file).with('config/initializers/localeapp.rb')
40
+ @command.execute('API_KEY', @output)
41
+ end
42
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'locale_app/cli/pull'
3
+
4
+ describe LocaleApp::CLI::Pull, "#execute" do
5
+ before do
6
+ @output = StringIO.new
7
+ @puller = LocaleApp::CLI::Pull.new(@output)
8
+ end
9
+
10
+ it "makes the api call to the translations endpoint" do
11
+ with_configuration do
12
+ @puller.should_receive(:api_call).with(
13
+ :translations,
14
+ :success => :update_backend,
15
+ :failure => :report_failure,
16
+ :max_connection_attempts => 3
17
+ )
18
+ @puller.execute
19
+ end
20
+ end
21
+ end
22
+
23
+ describe LocaleApp::CLI::Pull, "#update_backend(response)" do
24
+ before do
25
+ @test_data = ['test data'].to_json
26
+ @output = StringIO.new
27
+ @puller = LocaleApp::CLI::Pull.new(@output)
28
+ end
29
+
30
+ it "calls the updater" do
31
+ with_configuration do
32
+ LocaleApp.poller.stub!(:write_synchronization_data!)
33
+ LocaleApp.updater.should_receive(:update).with(['test data'])
34
+ @puller.update_backend(@test_data)
35
+ end
36
+ end
37
+
38
+ it "writes the synchronization data" do
39
+ with_configuration do
40
+ LocaleApp.updater.stub!(:update)
41
+ LocaleApp.poller.should_receive(:write_synchronization_data!)
42
+ @puller.update_backend(@test_data)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe LocaleApp::CLI::Push, "#execute(file)" do
4
+ before do
5
+ @output = StringIO.new
6
+ @pusher = LocaleApp::CLI::Push.new(@output)
7
+ end
8
+
9
+ it "creates a new file object and makes the api call to the translations endpoint" do
10
+ with_configuration do
11
+ file = double('file')
12
+ file_path = 'test_path'
13
+ @pusher.stub!(:sanitize_file).and_return(file)
14
+ @pusher.should_receive(:api_call).with(
15
+ :import,
16
+ :payload => { :file => file },
17
+ :success => :report_success,
18
+ :failure => :report_failure,
19
+ :max_connection_attempts => 3
20
+ )
21
+ @pusher.execute(file_path)
22
+ end
23
+ end
24
+
25
+ it "doesn't make the api call when the file doesn't exist" do
26
+ @pusher.stub!(:sanitize_file).and_return(nil)
27
+ @pusher.should_not_receive(:api_call)
28
+ @pusher.execute('foo')
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'locale_app/cli/update'
3
+
4
+ describe LocaleApp::CLI::Update, "#execute" do
5
+ before do
6
+ @output = StringIO.new
7
+ @updater = LocaleApp::CLI::Update.new(@output)
8
+ end
9
+
10
+ it "creates a Poller and calls poll! on it" do
11
+ with_configuration do
12
+ poller = LocaleApp::Poller.new
13
+ poller.should_receive(:poll!)
14
+ LocaleApp::Poller.should_receive(:new).and_return(poller)
15
+ @updater.execute
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ describe LocaleApp::Configuration do
4
+ before(:each) do
5
+ @configuration = LocaleApp::Configuration.new
6
+ end
7
+
8
+ it "sets the host by default" do
9
+ @configuration.host.should == 'api.localeapp.com'
10
+ end
11
+
12
+ it "allows the host to be overwritten" do
13
+ expect { @configuration.host = 'test.host' }.to change(@configuration, :host).to('test.host')
14
+ end
15
+
16
+ it "includes http_auth_username defaulting to nil" do
17
+ @configuration.http_auth_username.should == nil
18
+ @configuration.http_auth_username = "test"
19
+ @configuration.http_auth_username.should == "test"
20
+ end
21
+
22
+ it "includes http_auth_password defaulting to nil" do
23
+ @configuration.http_auth_password.should == nil
24
+ @configuration.http_auth_password = "test"
25
+ @configuration.http_auth_password.should == "test"
26
+ end
27
+
28
+ it "includes translation_data_directory defaulting to config/locales" do
29
+ @configuration.translation_data_directory.should == File.join("config", "locales")
30
+ @configuration.translation_data_directory = "test"
31
+ @configuration.translation_data_directory.should == "test"
32
+ end
33
+
34
+ context "disabled_sending_environments" do
35
+ it "does not include development by default" do
36
+ @configuration.environment_name = 'development'
37
+ @configuration.sending_disabled?.should be_false
38
+ end
39
+
40
+ it "include cucumber by default" do
41
+ @configuration.environment_name = 'cucumber'
42
+ @configuration.sending_disabled?.should be_true
43
+ end
44
+
45
+ it "include test by default" do
46
+ @configuration.environment_name = 'test'
47
+ @configuration.sending_disabled?.should be_true
48
+ end
49
+
50
+ it "include production by default" do
51
+ @configuration.environment_name = 'production'
52
+ @configuration.sending_disabled?.should be_true
53
+ end
54
+ end
55
+
56
+ context "disabled_reloading_environments" do
57
+ it "does not include development by default" do
58
+ @configuration.environment_name = 'development'
59
+ @configuration.reloading_disabled?.should be_false
60
+ end
61
+
62
+ it "include cucumber by default" do
63
+ @configuration.environment_name = 'cucumber'
64
+ @configuration.reloading_disabled?.should be_true
65
+ end
66
+
67
+ it "include test by default" do
68
+ @configuration.environment_name = 'test'
69
+ @configuration.reloading_disabled?.should be_true
70
+ end
71
+
72
+ it "include production by default" do
73
+ @configuration.environment_name = 'production'
74
+ @configuration.reloading_disabled?.should be_true
75
+ end
76
+ end
77
+
78
+ context "disabled_polling_environments" do
79
+ it "does not include development by default" do
80
+ @configuration.environment_name = 'development'
81
+ @configuration.polling_disabled?.should be_false
82
+ end
83
+
84
+ it "include cucumber by default" do
85
+ @configuration.environment_name = 'cucumber'
86
+ @configuration.polling_disabled?.should be_true
87
+ end
88
+
89
+ it "include test by default" do
90
+ @configuration.environment_name = 'test'
91
+ @configuration.polling_disabled?.should be_true
92
+ end
93
+
94
+ it "include production by default" do
95
+ @configuration.environment_name = 'production'
96
+ @configuration.polling_disabled?.should be_true
97
+ end
98
+ end
99
+ end
100
+
101
+ describe LocaleApp::Configuration, "#write_initial(path)" do
102
+ it "creates a configuration file containing just the api key at the given path" do
103
+ configuration = LocaleApp::Configuration.new
104
+ configuration.api_key = "APIKEY"
105
+ path = 'test_path'
106
+ file = stub('file')
107
+ file.should_receive(:write).with <<-CONTENT
108
+ require 'locale_app/rails'
109
+
110
+ LocaleApp.configure do |config|
111
+ config.api_key = 'APIKEY'
112
+ config.host = 'api.localeapp.com'
113
+ config.port = 80
114
+ end
115
+ CONTENT
116
+ File.should_receive(:open).with(path, 'w+').and_yield(file)
117
+ configuration.write_initial(path)
118
+ end
119
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+ require 'locale_app/exception_handler'
3
+
4
+ describe LocaleApp::ExceptionHandler, '#call(exception, locale, key, options)' do
5
+ before(:each) do
6
+ LocaleApp.configure do |config|
7
+ config.api_key = 'abcdef'
8
+ end
9
+ end
10
+
11
+ it "adds the missing translation to the missing translation list" do
12
+ LocaleApp.missing_translations.should_receive(:add).with(:en, 'foo', { :baz => 'bam' })
13
+ I18n.t('foo', :baz => 'bam')
14
+ end
15
+
16
+ it "handles when the key is an array of keys" do
17
+ LocaleApp.missing_translations.should_receive(:add).with(:en, 'foo', {})
18
+ LocaleApp.missing_translations.should_receive(:add).with(:en, 'bar', {})
19
+ I18n.t(['foo', 'bar'])
20
+ end
21
+ end