localeapp 0.0.7
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.
- data/.autotest +4 -0
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +2 -0
- data/README.textile +147 -0
- data/Rakefile +11 -0
- data/bin/localeapp +61 -0
- data/cucumber.yml +8 -0
- data/features/localeapp_binary.feature +116 -0
- data/features/step_definitions/cli_steps.rb +27 -0
- data/features/support/env.rb +21 -0
- data/features/support/hooks.rb +3 -0
- data/init.rb +1 -0
- data/lib/locale_app/api_call.rb +9 -0
- data/lib/locale_app/api_caller.rb +77 -0
- data/lib/locale_app/cli/install.rb +41 -0
- data/lib/locale_app/cli/pull.rb +34 -0
- data/lib/locale_app/cli/push.rb +49 -0
- data/lib/locale_app/cli/update.rb +19 -0
- data/lib/locale_app/configuration.rb +93 -0
- data/lib/locale_app/exception_handler.rb +21 -0
- data/lib/locale_app/key_checker.rb +43 -0
- data/lib/locale_app/missing_translations.rb +36 -0
- data/lib/locale_app/poller.rb +61 -0
- data/lib/locale_app/rails/2_3_translation_helper_monkeypatch.rb +36 -0
- data/lib/locale_app/rails/controller.rb +34 -0
- data/lib/locale_app/rails/flatten.rb +113 -0
- data/lib/locale_app/rails.rb +53 -0
- data/lib/locale_app/routes.rb +80 -0
- data/lib/locale_app/sender.rb +49 -0
- data/lib/locale_app/tasks/locale_app.rake +20 -0
- data/lib/locale_app/updater.rb +63 -0
- data/lib/locale_app/version.rb +3 -0
- data/lib/locale_app.rb +98 -0
- data/lib/localeapp.rb +1 -0
- data/localeapp.gemspec +35 -0
- data/run_ci +5 -0
- data/spec/fixtures/en.yml +6 -0
- data/spec/fixtures/es.yml +6 -0
- data/spec/locale_app/api_call_spec.rb +15 -0
- data/spec/locale_app/api_caller_spec.rb +157 -0
- data/spec/locale_app/cli/install_spec.rb +42 -0
- data/spec/locale_app/cli/pull_spec.rb +45 -0
- data/spec/locale_app/cli/push_spec.rb +30 -0
- data/spec/locale_app/cli/update_spec.rb +18 -0
- data/spec/locale_app/configuration_spec.rb +119 -0
- data/spec/locale_app/exception_handler_spec.rb +21 -0
- data/spec/locale_app/key_checker_spec.rb +19 -0
- data/spec/locale_app/missing_translations_spec.rb +28 -0
- data/spec/locale_app/poller_spec.rb +61 -0
- data/spec/locale_app/rails/controller_spec.rb +117 -0
- data/spec/locale_app/routes_spec.rb +134 -0
- data/spec/locale_app/sender_spec.rb +49 -0
- data/spec/locale_app/updater_spec.rb +89 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/locale_app_integration_data.rb +33 -0
- data/spec/support/locale_app_synchronization_data.rb +21 -0
- 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
|
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,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
|