one_sky 1.0.0 → 2.0.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.
@@ -0,0 +1,129 @@
1
+ module OneSky
2
+
3
+ # Implements the Translation I/O API for a given :platform_id
4
+ class Translation
5
+
6
+ attr_reader :platform_id, :client
7
+
8
+ # Provide the id of the platform, together with an instance of OneSky::Client.
9
+ def initialize(platform_id, client)
10
+ @platform_id = platform_id
11
+ @client = client
12
+ end
13
+
14
+ # Add new strings to be translated.
15
+ # expects an array of strings, or an array of hashes [{:string_key => k, :string => v}, ...]
16
+ def input_strings(strings)
17
+ post("string/input", :input => format_input_strings(strings))
18
+ end
19
+
20
+ # Add new strings to be translated.
21
+ # expects a string, or a hash of {:string_key => k, :string => v}
22
+ def input_string(string)
23
+ input_strings([string])
24
+ end
25
+
26
+ # Add new strings to be translated.
27
+ # expects a hash of {"string_key1" => "String 1", "string_key2" => "String 2"}
28
+ def input_phrases(phrases)
29
+ strings = phrases.map do |string_key, string|
30
+ {:string_key => string_key, :string => string}
31
+ end
32
+ input_strings(strings)
33
+ end
34
+
35
+ # Add translation to a string.
36
+ def translate(string_key, locale, translation)
37
+ post("string/translate", :"string-key" => string_key, :locale => locale, :translation => translation)
38
+ end
39
+
40
+ # Get the strings with translations.
41
+ def output
42
+ get_output
43
+ end
44
+
45
+ # Get the strings for a particular locale.
46
+ def output_for_locale(locale)
47
+ get_output(locale)
48
+ end
49
+
50
+ YAML_FORMAT = "RUBY_YAML".freeze
51
+ PO_FORMAT = "GNU_PO".freeze
52
+
53
+ # I don't believe these work right now.
54
+
55
+ # Upload a string file to add new strings. In RUBY_YAML format.
56
+ def upload_yaml(file)
57
+ upload_file(file, YAML_FORMAT)
58
+ end
59
+
60
+ # Upload a string file to add new strings. In GNU_PO format.
61
+ def upload_po(file)
62
+ upload_file(file, PO_FORMAT)
63
+ end
64
+
65
+ # Download strings and translations as string file. In RUBY_YAML format.
66
+ def download_yaml(locale)
67
+ download_file(locale, YAML_FORMAT)
68
+ end
69
+
70
+ # Download strings and translations as string file. In GNU_PO format.
71
+ def download_po(locale)
72
+ download_file(locale, PO_FORMAT)
73
+ end
74
+
75
+ protected
76
+
77
+ # Get the strings with translations.
78
+ def get_output(locale=nil)
79
+ options = {}
80
+ options[:locale] = locale if locale
81
+
82
+ get("string/output", options)["translation"]
83
+ end
84
+
85
+ # Upload a string file to add new strings.
86
+ def upload_file(file, format)
87
+ post("string/upload", :file => file, :format => format)
88
+ end
89
+
90
+ # Download strings and translations as string file.
91
+ def download_file(locale, format)
92
+ get("string/download", :locale => locale, :format => format)
93
+ end
94
+
95
+ def get(path, params={})
96
+ client.get(path, params.merge(:"platform-id" => platform_id))
97
+ end
98
+
99
+ def post(path, params={})
100
+ client.post(path, params.merge(:"platform-id" => platform_id))
101
+ end
102
+
103
+ def format_input_strings(strings)
104
+ JSON.dump(strings.map{|string| format_input_string(string)})
105
+ end
106
+
107
+ def format_input_string(string)
108
+ case string
109
+ when String
110
+ {:string => string}
111
+ when Hash
112
+ dashify_string_hash(string)
113
+ else
114
+ raise "input string must either be a string, or a hash"
115
+ end
116
+ end
117
+
118
+ # convert to "string-key" not "string_key"
119
+ def dashify_string_hash(string_hash)
120
+ output = Hash.new
121
+ string_hash.each do |key, value|
122
+ dashed = key.to_s.gsub("_", "-").to_sym
123
+ output[dashed] = value
124
+ end
125
+ output
126
+ end
127
+
128
+ end
129
+ end
@@ -0,0 +1,38 @@
1
+ module OneSky
2
+
3
+ # Implements the Utility API
4
+ class Utility
5
+
6
+ attr_reader :client
7
+
8
+ def initialize(client)
9
+ @client = client
10
+ end
11
+
12
+ # Get available locale list.
13
+ def locales
14
+ get("locales")["locales"]
15
+ end
16
+
17
+ # Get available platform type list.
18
+ def platform_types
19
+ get("platform-types")["types"]
20
+ end
21
+
22
+ # Get the Single-Sign-On link for logging in.
23
+ def get_sso_link(unique_id, name)
24
+ post("sso/get-link", {:"unique-id" => unique_id, :name => name})["url"]
25
+ end
26
+
27
+ protected
28
+
29
+ def get(path)
30
+ client.get(path)
31
+ end
32
+
33
+ def post(path, params)
34
+ client.post(path, params)
35
+ end
36
+
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module OneSky
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/one_sky.gemspec CHANGED
@@ -14,11 +14,12 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.rubyforge_project = "one_sky"
16
16
 
17
- s.add_dependency "json", ">= 1.4.6"
18
- s.add_dependency "rest-client", "~> 1.6.1"
17
+ s.add_dependency "json", ">= 1.4.0"
18
+ s.add_dependency "rest-client", ">= 1.4.0"
19
19
 
20
20
  s.add_development_dependency "rspec", "~> 2.2.0"
21
- s.add_development_dependency "bundler", "~> 1.0.0"
21
+ s.add_development_dependency "bundler", ">= 1.0.0"
22
+ s.add_development_dependency "time_freeze"
22
23
 
23
24
  s.files = `git ls-files`.split("\n")
24
25
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -0,0 +1,172 @@
1
+ require 'spec_helper'
2
+
3
+ describe OneSky::Client do
4
+
5
+ let(:api_key) { "apikey" }
6
+ let(:secret) { "secret" }
7
+
8
+ let(:client) { OneSky::Client.new(api_key, secret) }
9
+
10
+ let(:fake_response) { mock("some response", :headers => {:content_type => "text/plain"}, :body => "response") }
11
+ let(:fake_json) { mock("json response", :headers => {:content_type => "json"}, :body => %|{"some": "json"}|) }
12
+
13
+ describe "proxies" do
14
+ describe "utility" do
15
+ it "returns a OneSky::Utility instance" do
16
+ client.utility.should be_an_instance_of OneSky::Utility
17
+ end
18
+
19
+ it "sets the client to itself" do
20
+ client.utility.client.should == client
21
+ end
22
+ end
23
+
24
+ describe "project" do
25
+ it "returns a OneSky::Project instance" do
26
+ client.project("some-project").should be_an_instance_of OneSky::Project
27
+ end
28
+
29
+ it "sets the client to itself" do
30
+ client.project("some-project").client.should == client
31
+ end
32
+
33
+ it "sets the provided project name" do
34
+ client.project("some-project").project_name.should == "some-project"
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ describe "get" do
41
+
42
+ it "GETs the given path" do
43
+ RestClient.should respond_to(:post)
44
+ RestClient.should_receive(:get).with("https://api.oneskyapp.com/2/some_path/to/something", kind_of(Hash)).and_return(fake_response)
45
+ client.get("some_path/to/something")
46
+ end
47
+
48
+ it "GETs the given path - when given a leading /" do
49
+ RestClient.should_receive(:get).with("https://api.oneskyapp.com/2/some_path/to/something", kind_of(Hash)).and_return(fake_response)
50
+ client.get("/some_path/to/something")
51
+ end
52
+
53
+ it "passes in the api key, timestamp, and a hash of the secret" do
54
+ Time.freeze! do
55
+ timestamp = Time.now.to_i.to_s
56
+ RestClient.should_receive(:get).with(
57
+ kind_of(String),
58
+ {:params => {
59
+ :"api-key" => api_key,
60
+ :timestamp => timestamp,
61
+ :"dev-hash" => Digest::MD5.hexdigest(timestamp + secret)
62
+ },
63
+ :content_type => "text/plain; charset=UTF-8"}
64
+ ).and_return(fake_response)
65
+ client.get("some_path/to/something")
66
+ end
67
+ end
68
+
69
+ it "adds any provided params" do
70
+ Time.freeze! do
71
+ timestamp = Time.now.to_i.to_s
72
+ RestClient.should_receive(:get).with(
73
+ kind_of(String),
74
+ {:params => {
75
+ :"api-key" => api_key,
76
+ :timestamp => timestamp,
77
+ :"dev-hash" => Digest::MD5.hexdigest(timestamp + secret),
78
+ :some => "other param"
79
+ },
80
+ :content_type => "text/plain; charset=UTF-8"}
81
+ ).and_return(fake_response)
82
+ client.get("some_path/to/something", :some => "other param")
83
+ end
84
+ end
85
+
86
+ context "with a json content_type" do
87
+ it "parses the json" do
88
+ RestClient.should_receive(:get).and_return(fake_json)
89
+ client.get("some_path").should == {"some" => "json"}
90
+ end
91
+
92
+ it "raises an error if the response: is not OK" do
93
+ fake_json.should_receive(:body).and_return(%|{"response": "bad"}|)
94
+ RestClient.should_receive(:get).and_return(fake_json)
95
+ expect {
96
+ client.get("some_path")
97
+ }.to raise_error(OneSky::ApiError)
98
+ end
99
+ end
100
+
101
+ context "without a non-json content_type" do
102
+ it "returns the body" do
103
+ RestClient.should_receive(:get).and_return(fake_response)
104
+ client.get("some_path").should == fake_response.body
105
+ end
106
+ end
107
+ end
108
+
109
+ describe "post" do
110
+
111
+ it "POSTSs the given path" do
112
+ RestClient.should respond_to(:post)
113
+ RestClient.should_receive(:post).with("https://api.oneskyapp.com/2/some_path/to/something", kind_of(Hash)).and_return(fake_response)
114
+ client.post("some_path/to/something")
115
+ end
116
+
117
+ it "passes in the api key, timestamp, and a hash of the secret" do
118
+ Time.freeze! do
119
+ timestamp = Time.now.to_i.to_s
120
+ RestClient.should_receive(:post).with(
121
+ kind_of(String),
122
+ {
123
+ :"api-key" => api_key,
124
+ :timestamp => timestamp,
125
+ :"dev-hash" => Digest::MD5.hexdigest(timestamp + secret),
126
+ :content_type => "text/plain; charset=UTF-8"
127
+ }
128
+ ).and_return(fake_response)
129
+ client.post("some_path/to/something")
130
+ end
131
+ end
132
+
133
+ it "adds any provided params" do
134
+ Time.freeze! do
135
+ timestamp = Time.now.to_i.to_s
136
+ RestClient.should_receive(:post).with(
137
+ kind_of(String),
138
+ {
139
+ :"api-key" => api_key,
140
+ :timestamp => timestamp,
141
+ :"dev-hash" => Digest::MD5.hexdigest(timestamp + secret),
142
+ :some => "other param",
143
+ :content_type => "text/plain; charset=UTF-8"
144
+ }
145
+ ).and_return(fake_response)
146
+ client.post("some_path/to/something", :some => "other param")
147
+ end
148
+ end
149
+
150
+ context "with a json content_type" do
151
+ it "parses the json" do
152
+ RestClient.should_receive(:post).and_return(fake_json)
153
+ client.post("some_path").should == {"some" => "json"}
154
+ end
155
+
156
+ it "raises an error if the response: is not OK" do
157
+ fake_json.should_receive(:body).and_return(%|{"response": "bad"}|)
158
+ RestClient.should_receive(:post).and_return(fake_json)
159
+ expect {
160
+ client.post("some_path")
161
+ }.to raise_error(OneSky::ApiError)
162
+ end
163
+ end
164
+
165
+ context "without a non-json content_type" do
166
+ it "returns the body" do
167
+ RestClient.should_receive(:post).and_return(fake_response)
168
+ client.post("some_path").should == fake_response.body
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,2 @@
1
+ msgid "test1"
2
+ msgstr "Test 1"
@@ -0,0 +1,5 @@
1
+ en_US:
2
+ test1: "Test 1"
3
+
4
+ zh_CN:
5
+ test1: "测试一"
data/spec/live_spec.rb ADDED
@@ -0,0 +1,187 @@
1
+ # encoding: utf-8
2
+
3
+ # this spec runs through live api calls
4
+ # and requires a real api key for the account
5
+ #
6
+ # http://ruby-gem-tests.oneskyapp.com/
7
+ #
8
+ # before running this test we need to do
9
+ #
10
+ # export ONESKY_API_KEY="the key"
11
+ # export ONESKY_API_SECRET="the secret"
12
+ #
13
+ # the rake spec task skips these test
14
+ # you need to run
15
+ #
16
+ # rake spec:live
17
+ #
18
+ require 'spec_helper'
19
+ require 'yaml'
20
+
21
+ describe OneSky, :live => true do
22
+
23
+ let(:onesky_api_key) { ENV["ONESKY_API_KEY"] }
24
+ let(:onesky_api_secret) { ENV["ONESKY_API_SECRET"] }
25
+ let(:project_name) { "api-test" }
26
+ let(:platform_id) { 840 }
27
+ let(:platform_code) { "website" }
28
+
29
+ let(:english_locale) { "en_US" }
30
+ let(:chinese_locale) { "zh_CN" }
31
+
32
+ let(:client) do
33
+ client = OneSky::Client.new(onesky_api_key, onesky_api_secret)
34
+ end
35
+
36
+ context "utility apis" do
37
+ let(:utility) do
38
+ client.utility
39
+ end
40
+
41
+ it "locales" do
42
+ locales = utility.locales
43
+ locales.should be_an_instance_of Array
44
+ locales.should_not be_empty
45
+ en_us = locales.detect{|l| l["locale"] == english_locale }
46
+ en_us["name"]["eng"].should == "English (US)"
47
+ end
48
+
49
+ it "platform_types" do
50
+ types = utility.platform_types
51
+ types.should be_an_instance_of Array
52
+ types.should_not be_empty
53
+ website = types.detect{|t| t["code"] == platform_code }
54
+ website.should == {"name" => "Website", "code" => platform_code}
55
+ end
56
+
57
+ it "get_sso_link" do
58
+ link = utility.get_sso_link(123, "fred")
59
+ link.should be_an_instance_of String
60
+ link.should match(".oneskyapp.com/")
61
+ end
62
+ end
63
+
64
+ context "project" do
65
+ let(:project) do
66
+ client.project(project_name)
67
+ end
68
+
69
+ it "details" do
70
+ details = project.details
71
+ details.should be_an_instance_of Hash
72
+ details["name"].should == project_name
73
+ end
74
+
75
+ it "platforms" do
76
+ platforms = project.platforms
77
+ platforms.should be_an_instance_of Array
78
+ platforms.should_not be_empty
79
+
80
+ expected = platforms.detect{|p| p["id"]== platform_id}
81
+ expected.should be_an_instance_of Hash
82
+ expected["code"].should == platform_code
83
+ end
84
+ end
85
+
86
+ context "platform" do
87
+ let(:platform) do
88
+ client.project(project_name).platform(platform_id)
89
+ end
90
+
91
+ it "details" do
92
+ details = platform.details
93
+ details.should be_an_instance_of Hash
94
+ details["project"].should == project_name
95
+ details["type"]["code"].should == platform_code
96
+ end
97
+
98
+ it "locales" do
99
+ locales = platform.locales
100
+ locales.should be_an_instance_of Array
101
+ locales.should_not be_empty
102
+ en_us = locales.detect{|l| l["locale"] == english_locale }
103
+ en_us["name"]["eng"].should == "English (US)"
104
+ end
105
+ end
106
+
107
+ context "translation" do
108
+ let(:translation) do
109
+ client.project(project_name).platform(platform_id).translation
110
+ end
111
+
112
+ it "input_phrases" do
113
+ translation.input_phrases("test1" => "Test 1", "test2" => "Test 2")
114
+ end
115
+
116
+ it "input_strings - as strings" do
117
+ translation.input_strings(["test1", "test2"])
118
+ end
119
+
120
+ it "input_strings - as hashes" do
121
+ translation.input_strings([{:string => "Test 3", :string_key => "test3"}, {:string => "Test 4", :string_key => "test4"}])
122
+ end
123
+
124
+ it "input_string - as string" do
125
+ translation.input_string("test5")
126
+ end
127
+
128
+ it "input_string - as hash" do
129
+ translation.input_string({:string => "Test 6", :string_key => "test6"})
130
+ end
131
+
132
+ it "translate" do
133
+ translation.translate("test1", chinese_locale, "测试一")
134
+ end
135
+
136
+ it "output" do
137
+ output = translation.output
138
+ output.should be_an_instance_of Hash
139
+
140
+ output["Default"].should have_key(english_locale)
141
+ output["Default"].should have_key(chinese_locale)
142
+
143
+ output["Default"][english_locale].should have_key("test1")
144
+ end
145
+
146
+ it "output_for_locale" do
147
+ output = translation.output_for_locale(chinese_locale)
148
+ output.should be_an_instance_of Hash
149
+
150
+ output["Default"].keys.should == [chinese_locale]
151
+ output["Default"][chinese_locale].should have_key("test1")
152
+ end
153
+
154
+ def file(filename)
155
+ path = File.join(File.dirname(__FILE__), "files", filename)
156
+ File.open(File.expand_path(path))
157
+ end
158
+
159
+ it "upload_yaml" do
160
+ translation.upload_yaml(file("example.yml"))
161
+ end
162
+
163
+ it "upload_po" do
164
+ translation.upload_po(file("example.po"))
165
+ end
166
+
167
+ it "download_yaml" do
168
+ yaml = translation.download_yaml(chinese_locale)
169
+ yaml.should be_an_instance_of String
170
+
171
+ hash = YAML.load(yaml)
172
+ hash.should be_an_instance_of Hash
173
+
174
+ hash[chinese_locale].should have_key("test1")
175
+ end
176
+
177
+ it "download_po" do
178
+ po = translation.download_po(chinese_locale)
179
+ po.should be_an_instance_of String
180
+
181
+ # some way of verifying it looks like a po
182
+ po.should match(%(msgid "test1"\nmsgstr "))
183
+ end
184
+ end
185
+
186
+
187
+ end