txgh 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +202 -0
- data/README.md +64 -0
- data/lib/ext/zipline/output_stream.rb +62 -0
- data/lib/txgh.rb +53 -0
- data/lib/txgh/app.rb +135 -0
- data/lib/txgh/category_support.rb +31 -0
- data/lib/txgh/config.rb +11 -0
- data/lib/txgh/config/config_pair.rb +36 -0
- data/lib/txgh/config/key_manager.rb +54 -0
- data/lib/txgh/config/provider_instance.rb +20 -0
- data/lib/txgh/config/provider_support.rb +26 -0
- data/lib/txgh/config/providers.rb +9 -0
- data/lib/txgh/config/providers/file_provider.rb +19 -0
- data/lib/txgh/config/providers/git_provider.rb +58 -0
- data/lib/txgh/config/providers/raw_provider.rb +19 -0
- data/lib/txgh/config/tx_config.rb +77 -0
- data/lib/txgh/config/tx_manager.rb +15 -0
- data/lib/txgh/diff_calculator.rb +90 -0
- data/lib/txgh/empty_resource_contents.rb +43 -0
- data/lib/txgh/errors.rb +9 -0
- data/lib/txgh/github_api.rb +83 -0
- data/lib/txgh/github_repo.rb +88 -0
- data/lib/txgh/github_request_auth.rb +28 -0
- data/lib/txgh/handlers.rb +12 -0
- data/lib/txgh/handlers/download_handler.rb +84 -0
- data/lib/txgh/handlers/github.rb +10 -0
- data/lib/txgh/handlers/github/delete_handler.rb +65 -0
- data/lib/txgh/handlers/github/handler.rb +20 -0
- data/lib/txgh/handlers/github/push_handler.rb +108 -0
- data/lib/txgh/handlers/github/request_handler.rb +106 -0
- data/lib/txgh/handlers/response.rb +17 -0
- data/lib/txgh/handlers/stream_response.rb +39 -0
- data/lib/txgh/handlers/tgz_stream_response.rb +41 -0
- data/lib/txgh/handlers/transifex.rb +8 -0
- data/lib/txgh/handlers/transifex/hook_handler.rb +77 -0
- data/lib/txgh/handlers/transifex/request_handler.rb +78 -0
- data/lib/txgh/handlers/triggers.rb +9 -0
- data/lib/txgh/handlers/triggers/handler.rb +66 -0
- data/lib/txgh/handlers/triggers/pull_handler.rb +29 -0
- data/lib/txgh/handlers/triggers/push_handler.rb +21 -0
- data/lib/txgh/handlers/zip_stream_response.rb +21 -0
- data/lib/txgh/merge_calculator.rb +74 -0
- data/lib/txgh/parse_config.rb +24 -0
- data/lib/txgh/resource_committer.rb +39 -0
- data/lib/txgh/resource_contents.rb +118 -0
- data/lib/txgh/resource_downloader.rb +141 -0
- data/lib/txgh/resource_updater.rb +104 -0
- data/lib/txgh/response_helpers.rb +30 -0
- data/lib/txgh/transifex_api.rb +165 -0
- data/lib/txgh/transifex_project.rb +37 -0
- data/lib/txgh/transifex_request_auth.rb +53 -0
- data/lib/txgh/tx_branch_resource.rb +59 -0
- data/lib/txgh/tx_logger.rb +12 -0
- data/lib/txgh/tx_resource.rb +66 -0
- data/lib/txgh/utils.rb +44 -0
- data/lib/txgh/version.rb +3 -0
- data/spec/app_spec.rb +346 -0
- data/spec/category_support_spec.rb +43 -0
- data/spec/config/config_pair_spec.rb +47 -0
- data/spec/config/key_manager_spec.rb +48 -0
- data/spec/config/provider_instance_spec.rb +30 -0
- data/spec/config/provider_support_spec.rb +55 -0
- data/spec/config/tx_config_spec.rb +49 -0
- data/spec/config/tx_manager_spec.rb +57 -0
- data/spec/diff_calculator_spec.rb +90 -0
- data/spec/github_api_spec.rb +148 -0
- data/spec/github_repo_spec.rb +178 -0
- data/spec/github_request_auth_spec.rb +39 -0
- data/spec/handlers/download_handler_spec.rb +81 -0
- data/spec/handlers/github/delete_handler_spec.rb +71 -0
- data/spec/handlers/github/push_handler_spec.rb +76 -0
- data/spec/handlers/tgz_stream_response_spec.rb +59 -0
- data/spec/handlers/transifex/hook_handler_spec.rb +115 -0
- data/spec/handlers/zip_stream_response_spec.rb +58 -0
- data/spec/helpers/github_payload_builder.rb +141 -0
- data/spec/helpers/integration_setup.rb +47 -0
- data/spec/helpers/nil_logger.rb +10 -0
- data/spec/helpers/standard_txgh_setup.rb +92 -0
- data/spec/helpers/test_provider.rb +12 -0
- data/spec/integration/cassettes/github_l10n_hook_endpoint.yml +536 -0
- data/spec/integration/cassettes/pull.yml +47 -0
- data/spec/integration/cassettes/push.yml +544 -0
- data/spec/integration/cassettes/transifex_hook_endpoint.yml +560 -0
- data/spec/integration/config/tx.config +10 -0
- data/spec/integration/hooks_spec.rb +158 -0
- data/spec/integration/payloads/github_postbody.json +161 -0
- data/spec/integration/payloads/github_postbody_l10n.json +136 -0
- data/spec/integration/payloads/github_postbody_release.json +136 -0
- data/spec/integration/triggers_spec.rb +45 -0
- data/spec/merge_calculator_spec.rb +112 -0
- data/spec/parse_config_spec.rb +52 -0
- data/spec/resource_committer_spec.rb +42 -0
- data/spec/resource_contents_spec.rb +212 -0
- data/spec/resource_downloader_spec.rb +205 -0
- data/spec/resource_updater_spec.rb +147 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/transifex_api_spec.rb +345 -0
- data/spec/transifex_project_spec.rb +45 -0
- data/spec/transifex_request_auth_spec.rb +39 -0
- data/spec/tx_branch_resource_spec.rb +99 -0
- data/spec/tx_resource_spec.rb +47 -0
- data/spec/utils_spec.rb +58 -0
- data/txgh.gemspec +29 -0
- metadata +296 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'helpers/standard_txgh_setup'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
include Txgh
|
6
|
+
|
7
|
+
describe ResourceDownloader do
|
8
|
+
include StandardTxghSetup
|
9
|
+
|
10
|
+
let(:api_languages) { %w(es de ja) }
|
11
|
+
let(:format) { '.zip' }
|
12
|
+
|
13
|
+
let(:downloader) do
|
14
|
+
ResourceDownloader.new(transifex_project, github_repo, ref)
|
15
|
+
end
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
allow(transifex_api).to(
|
19
|
+
receive(:get_languages).with(project_name).and_return(
|
20
|
+
api_languages.map do |language_code|
|
21
|
+
{ 'language_code' => language_code }
|
22
|
+
end
|
23
|
+
)
|
24
|
+
)
|
25
|
+
|
26
|
+
allow(transifex_api).to(
|
27
|
+
receive(:download) do |resource, language|
|
28
|
+
translations_for(resource, language)
|
29
|
+
end
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def translations_for(resource, language)
|
34
|
+
outdent(%Q{
|
35
|
+
#{language}:
|
36
|
+
string: ! "translation"
|
37
|
+
})
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with a basic resource' do
|
41
|
+
let(:resource) do
|
42
|
+
tx_config.resource(resource_slug)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'downloads the resource in all languages' do
|
46
|
+
expect(downloader.each.to_a).to eq(
|
47
|
+
api_languages.map do |language|
|
48
|
+
[
|
49
|
+
"translations/#{language}/sample.yml",
|
50
|
+
translations_for(resource, language)
|
51
|
+
]
|
52
|
+
end
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'with more than one resource' do
|
58
|
+
before(:each) do
|
59
|
+
tx_config.resources << Txgh::TxResource.new(
|
60
|
+
project_name, "#{resource_slug}_second", 'YML',
|
61
|
+
'en', 'en.yml', '', 'translations/<lang>/sample2.yml'
|
62
|
+
)
|
63
|
+
|
64
|
+
allow(Txgh::Config::TxManager).to(
|
65
|
+
receive(:tx_config).and_return(tx_config)
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when told to process all branches' do
|
70
|
+
let(:branch) { 'all' }
|
71
|
+
|
72
|
+
it 'includes all resources' do
|
73
|
+
resource = tx_config.resource(resource_slug)
|
74
|
+
actual_results = downloader.each.to_a
|
75
|
+
|
76
|
+
expected_results = api_languages.map do |language|
|
77
|
+
[
|
78
|
+
"translations/#{language}/sample.yml",
|
79
|
+
translations_for(resource, language)
|
80
|
+
]
|
81
|
+
end
|
82
|
+
|
83
|
+
expected_results += api_languages.map do |language|
|
84
|
+
[
|
85
|
+
"translations/#{language}/sample2.yml",
|
86
|
+
translations_for(resource, language)
|
87
|
+
]
|
88
|
+
end
|
89
|
+
|
90
|
+
expect(actual_results).to eq(expected_results)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when told to upload diffs' do
|
96
|
+
let(:diff_point) { 'heads/master' }
|
97
|
+
let(:ref) { 'heads/mybranch' }
|
98
|
+
|
99
|
+
before(:each) do
|
100
|
+
allow(github_api).to receive(:download) do |repo_name, file, branch|
|
101
|
+
source_for(branch)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def source_for(branch)
|
106
|
+
if branch == diff_point
|
107
|
+
diff_point_source_for(branch)
|
108
|
+
else
|
109
|
+
head_source_for(branch)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def head_source_for(branch)
|
114
|
+
# picard unmodified, janeway modified, sisko added, sulu removed
|
115
|
+
outdent(%Q{
|
116
|
+
en:
|
117
|
+
picard: ! "enterprise"
|
118
|
+
janeway: ! "uss voyager"
|
119
|
+
sisko: ! "deep space nine"
|
120
|
+
})
|
121
|
+
end
|
122
|
+
|
123
|
+
def diff_point_source_for(branch)
|
124
|
+
outdent(%Q{
|
125
|
+
en:
|
126
|
+
picard: ! "enterprise"
|
127
|
+
janeway: ! "voyager"
|
128
|
+
sulu: ! "excelsior"
|
129
|
+
})
|
130
|
+
end
|
131
|
+
|
132
|
+
def translations_for(resource, language)
|
133
|
+
branch = resource.respond_to?(:branch) ? resource.branch : nil
|
134
|
+
|
135
|
+
if branch == diff_point
|
136
|
+
diff_point_translations_for(language)
|
137
|
+
else
|
138
|
+
head_translations_for(language)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# picard unmodified, janeway modified, sisko added, sulu removed
|
143
|
+
def head_translations_for(language)
|
144
|
+
outdent(%Q{
|
145
|
+
#{language}:
|
146
|
+
picard: ! "enterprise (head trans)"
|
147
|
+
janeway: ! "uss voyager (head trans)"
|
148
|
+
sisko: ! "deep space nine (head trans)"
|
149
|
+
})
|
150
|
+
end
|
151
|
+
|
152
|
+
def diff_point_translations_for(language)
|
153
|
+
# diff point strings (i.e. strings in master)
|
154
|
+
outdent(%Q{
|
155
|
+
#{language}:
|
156
|
+
picard: ! "enterprise (dp trans)"
|
157
|
+
janeway: ! "voyager (dp trans)"
|
158
|
+
sulu: ! "excelsior (dp trans)"
|
159
|
+
})
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'merges the head and diff point strings together' do
|
163
|
+
# picard unmodified, janeway modified, sisko added, sulu removed
|
164
|
+
expect(downloader.each.to_a).to eq(
|
165
|
+
api_languages.map do |language|
|
166
|
+
[
|
167
|
+
"translations/#{language}/sample.yml",
|
168
|
+
outdent(%Q{
|
169
|
+
#{language}:
|
170
|
+
picard: ! "enterprise (dp trans)"
|
171
|
+
janeway: ! "uss voyager (head trans)"
|
172
|
+
sisko: ! "deep space nine (head trans)"
|
173
|
+
})
|
174
|
+
]
|
175
|
+
end
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "works even if the resource doesn't exist in transifex" do
|
180
|
+
allow(transifex_api).to(
|
181
|
+
receive(:download) do |resource, language|
|
182
|
+
if resource.respond_to?(:branch)
|
183
|
+
translations_for(resource, language)
|
184
|
+
else
|
185
|
+
raise TransifexNotFoundError
|
186
|
+
end
|
187
|
+
end
|
188
|
+
)
|
189
|
+
|
190
|
+
results = downloader.each.to_a
|
191
|
+
expect(results).to eq(
|
192
|
+
api_languages.map do |language|
|
193
|
+
[
|
194
|
+
"translations/#{language}/sample.yml",
|
195
|
+
outdent(%Q{
|
196
|
+
#{language}:
|
197
|
+
picard: ! "enterprise (dp trans)"
|
198
|
+
janeway: ! "voyager (dp trans)"
|
199
|
+
})
|
200
|
+
]
|
201
|
+
end
|
202
|
+
)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'helpers/standard_txgh_setup'
|
3
|
+
|
4
|
+
include Txgh
|
5
|
+
|
6
|
+
describe ResourceUpdater do
|
7
|
+
include StandardTxghSetup
|
8
|
+
|
9
|
+
let(:updater) do
|
10
|
+
ResourceUpdater.new(transifex_project, github_repo, logger)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:branch) { nil }
|
14
|
+
let(:ref) { nil }
|
15
|
+
let(:resource) { tx_config.resource(resource_slug, ref) }
|
16
|
+
let(:commit_sha) { '8765309' }
|
17
|
+
|
18
|
+
let(:modified_files) do
|
19
|
+
[{ 'path' => resource.source_file, 'sha' => 'def456' }]
|
20
|
+
end
|
21
|
+
|
22
|
+
def phrases_for(path)
|
23
|
+
YAML.load("|
|
24
|
+
en:
|
25
|
+
welcome: Hello
|
26
|
+
goodbye: Goodbye
|
27
|
+
new_phrase: I'm new
|
28
|
+
")
|
29
|
+
end
|
30
|
+
|
31
|
+
before(:each) do
|
32
|
+
tree_sha = 'abc123'
|
33
|
+
|
34
|
+
allow(github_api).to(
|
35
|
+
receive(:get_commit).with(repo_name, commit_sha) do
|
36
|
+
{ 'commit' => { 'tree' => { 'sha' => tree_sha } } }
|
37
|
+
end
|
38
|
+
)
|
39
|
+
|
40
|
+
allow(github_api).to(
|
41
|
+
receive(:tree).with(repo_name, tree_sha) do
|
42
|
+
{ 'tree' => modified_files }
|
43
|
+
end
|
44
|
+
)
|
45
|
+
|
46
|
+
modified_files.each do |file|
|
47
|
+
translations = phrases_for(file['path'])
|
48
|
+
|
49
|
+
allow(github_api).to(
|
50
|
+
receive(:blob).with(repo_name, file['sha']) do
|
51
|
+
{ 'content' => translations, 'encoding' => 'utf-8' }
|
52
|
+
end
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'correctly uploads modified files to transifex' do
|
58
|
+
modified_files.each do |file|
|
59
|
+
translations = phrases_for(file['path'])
|
60
|
+
|
61
|
+
expect(transifex_api).to(
|
62
|
+
receive(:create_or_update) do |resource, content|
|
63
|
+
expect(resource.source_file).to eq(file['path'])
|
64
|
+
expect(content).to eq(translations)
|
65
|
+
end
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
updater.update_resource(resource, commit_sha)
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when asked to process all branches' do
|
73
|
+
let(:branch) { 'all' }
|
74
|
+
let(:ref) { 'heads/master' }
|
75
|
+
|
76
|
+
it 'uploads by branch name if asked' do
|
77
|
+
allow(transifex_api).to receive(:resource_exists?).and_return(false)
|
78
|
+
|
79
|
+
modified_files.each do |file|
|
80
|
+
translations = phrases_for(file['path'])
|
81
|
+
|
82
|
+
expect(transifex_api).to(
|
83
|
+
receive(:create) do |resource, content, categories|
|
84
|
+
expect(resource.source_file).to eq(file['path'])
|
85
|
+
expect(content).to eq(translations)
|
86
|
+
expect(categories).to include("branch:#{ref}")
|
87
|
+
end
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
updater.update_resource(resource, commit_sha)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'adds categories when passed in' do
|
95
|
+
expect(transifex_api).to receive(:resource_exists?).and_return(false)
|
96
|
+
|
97
|
+
modified_files.each do |file|
|
98
|
+
translations = phrases_for(file['path'])
|
99
|
+
|
100
|
+
expect(transifex_api).to(
|
101
|
+
receive(:create) do |resource, content, categories|
|
102
|
+
expect(categories).to include('foo:bar')
|
103
|
+
end
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
updater.update_resource(resource, commit_sha, { 'foo' => 'bar' })
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when asked to upload diffs' do
|
112
|
+
let(:diff_point) { 'heads/diff_point' }
|
113
|
+
let(:resource) do
|
114
|
+
TxResource.new(
|
115
|
+
project_name, resource_slug, 'YAML',
|
116
|
+
'en', 'en.yml', '', 'translation_file'
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'uploads a diff instead of the whole resource' do
|
121
|
+
expect(github_api).to(
|
122
|
+
receive(:download)
|
123
|
+
.with(repo_name, 'en.yml', diff_point)
|
124
|
+
.and_return(YAML.load("|
|
125
|
+
en:
|
126
|
+
welcome: Hello
|
127
|
+
goodbye: Goodbye
|
128
|
+
"))
|
129
|
+
)
|
130
|
+
|
131
|
+
diff = YAML.load(%Q(|
|
132
|
+
en:
|
133
|
+
new_phrase: ! "I'm new"
|
134
|
+
))
|
135
|
+
|
136
|
+
expect(updater).to(
|
137
|
+
receive(:upload_by_branch).with(resource, diff, anything)
|
138
|
+
)
|
139
|
+
|
140
|
+
allow(updater).to(
|
141
|
+
receive(:categories_for).and_return({})
|
142
|
+
)
|
143
|
+
|
144
|
+
updater.update_resource(resource, commit_sha)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'pry-byebug'
|
4
|
+
require 'rake'
|
5
|
+
require 'rspec'
|
6
|
+
require 'txgh'
|
7
|
+
require 'vcr'
|
8
|
+
require 'webmock'
|
9
|
+
require 'yaml'
|
10
|
+
|
11
|
+
module SpecHelpers
|
12
|
+
def outdent(str)
|
13
|
+
# The special YAML pipe operator treats the text that follows as literal,
|
14
|
+
# and includes newlines, tabs, and spaces. It also strips leading tabs and
|
15
|
+
# spaces. This means you can include a fully indented bit of, say, source
|
16
|
+
# code in your source code, and it will give you back a string with all the
|
17
|
+
# indentation preserved (but without any leading indentation).
|
18
|
+
YAML.load("|#{str}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
RSpec.configure do |config|
|
23
|
+
config.filter_run(focus: true)
|
24
|
+
config.run_all_when_everything_filtered = true
|
25
|
+
config.filter_run_excluding(integration: true) unless ENV['FULL_SPEC']
|
26
|
+
config.include(SpecHelpers)
|
27
|
+
end
|
28
|
+
|
29
|
+
VCR.configure do |config|
|
30
|
+
config.cassette_library_dir = 'spec/integration/cassettes'
|
31
|
+
config.hook_into :webmock
|
32
|
+
end
|
@@ -0,0 +1,345 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'helpers/standard_txgh_setup'
|
3
|
+
|
4
|
+
include Txgh
|
5
|
+
|
6
|
+
describe TransifexApi do
|
7
|
+
include StandardTxghSetup
|
8
|
+
|
9
|
+
let(:connection) { double(:connection) }
|
10
|
+
let(:api) { TransifexApi.create_from_connection(connection) }
|
11
|
+
let(:resource) { tx_config.resources.first }
|
12
|
+
let(:response) { double(:response) }
|
13
|
+
|
14
|
+
describe '#create_or_update' do
|
15
|
+
context 'with a preexisting resource' do
|
16
|
+
before(:each) do
|
17
|
+
expect(api).to receive(:resource_exists?).and_return(true)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'updates the resource with new content' do
|
21
|
+
expect(api).to receive(:update_details).with(resource, categories: [])
|
22
|
+
expect(api).to receive(:update_content).with(resource, 'new_content')
|
23
|
+
expect(api).to receive(:get_resource).and_return({})
|
24
|
+
|
25
|
+
api.create_or_update(resource, 'new_content')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "additively updates the resource's categories" do
|
29
|
+
expect(api).to receive(:update_details) do |rsrc, details|
|
30
|
+
expect(details[:categories].sort).to eq(['branch:foobar', 'name:Jesse James'])
|
31
|
+
end
|
32
|
+
|
33
|
+
expect(api).to receive(:update_content).with(resource, 'new_content')
|
34
|
+
expect(api).to receive(:get_resource).and_return({ 'categories' => ['name:Jesse James'] })
|
35
|
+
|
36
|
+
api.create_or_update(resource, 'new_content', ['branch:foobar'])
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'only submits a unique set of categories' do
|
40
|
+
expect(api).to receive(:update_details).with(resource, categories: ['branch:foobar'])
|
41
|
+
expect(api).to receive(:update_content).with(resource, 'new_content')
|
42
|
+
expect(api).to receive(:get_resource).and_return({ 'categories' => ['branch:foobar'] })
|
43
|
+
|
44
|
+
api.create_or_update(resource, 'new_content', ['branch:foobar'])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with a non-existent resource' do
|
49
|
+
before(:each) do
|
50
|
+
expect(api).to receive(:resource_exists?).and_return(false)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'makes a request with the correct parameters' do
|
54
|
+
expect(connection).to receive(:post) do |url, payload|
|
55
|
+
expect(url).to(
|
56
|
+
end_with("project/#{project_name}/resources/")
|
57
|
+
)
|
58
|
+
|
59
|
+
expect(payload[:slug]).to eq(resource_slug)
|
60
|
+
expect(payload[:name]).to eq(resource.source_file)
|
61
|
+
expect(payload[:i18n_type]).to eq('YML')
|
62
|
+
|
63
|
+
response
|
64
|
+
end
|
65
|
+
|
66
|
+
allow(response).to receive(:status).and_return(200)
|
67
|
+
allow(response).to receive(:body).and_return("{}")
|
68
|
+
api.create_or_update(resource, 'new_content')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '#create' do
|
74
|
+
it 'makes a request with the correct parameters' do
|
75
|
+
expect(connection).to receive(:post) do |url, payload|
|
76
|
+
expect(url).to(
|
77
|
+
end_with("project/#{project_name}/resources/")
|
78
|
+
)
|
79
|
+
|
80
|
+
expect(payload[:content].io.string).to eq('new_content')
|
81
|
+
expect(payload[:categories]).to eq('abc def')
|
82
|
+
response
|
83
|
+
end
|
84
|
+
|
85
|
+
allow(response).to receive(:status).and_return(200)
|
86
|
+
api.create(resource, 'new_content', ['abc', 'def'])
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'submits de-duped categories' do
|
90
|
+
expect(connection).to receive(:post) do |url, payload|
|
91
|
+
expect(payload[:categories]).to eq('abc')
|
92
|
+
response
|
93
|
+
end
|
94
|
+
|
95
|
+
allow(response).to receive(:status).and_return(200)
|
96
|
+
api.create(resource, 'new_content', ['abc', 'abc'])
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'raises an exception if the api responds with an error code' do
|
100
|
+
allow(connection).to receive(:post).and_return(response)
|
101
|
+
allow(response).to receive(:status).and_return(404)
|
102
|
+
allow(response).to receive(:body).and_return('{}')
|
103
|
+
expect { api.create(resource, 'new_content') }.to raise_error(TransifexApiError)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe '#delete' do
|
108
|
+
it 'deletes the given resource' do
|
109
|
+
expect(connection).to receive(:delete) do |url|
|
110
|
+
expect(url).to(
|
111
|
+
end_with("project/#{project_name}/resource/#{resource_slug}/")
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
api.delete(resource)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#update_content' do
|
120
|
+
it 'makes a request with the correct parameters' do
|
121
|
+
expect(connection).to receive(:put) do |url, payload|
|
122
|
+
expect(url).to(
|
123
|
+
end_with("project/#{project_name}/resource/#{resource_slug}/content/")
|
124
|
+
)
|
125
|
+
|
126
|
+
expect(payload[:content].io.string).to eq('new_content')
|
127
|
+
response
|
128
|
+
end
|
129
|
+
|
130
|
+
allow(response).to receive(:status).and_return(200)
|
131
|
+
api.update_content(resource, 'new_content')
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'raises an exception if the api responds with an error code' do
|
135
|
+
allow(connection).to receive(:put).and_return(response)
|
136
|
+
allow(response).to receive(:status).and_return(404)
|
137
|
+
allow(response).to receive(:body).and_return('{}')
|
138
|
+
expect { api.update_content(resource, 'new_content') }.to raise_error(TransifexApiError)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#update_details' do
|
143
|
+
it 'makes a request with the correct parameters' do
|
144
|
+
expect(connection).to receive(:put) do |url, payload|
|
145
|
+
expect(url).to(
|
146
|
+
end_with("project/#{project_name}/resource/#{resource_slug}/")
|
147
|
+
)
|
148
|
+
|
149
|
+
expect(payload[:i18n_type]).to eq('FOO')
|
150
|
+
expect(payload[:categories]).to eq(['abc'])
|
151
|
+
response
|
152
|
+
end
|
153
|
+
|
154
|
+
allow(response).to receive(:status).and_return(200)
|
155
|
+
api.update_details(resource, i18n_type: 'FOO', categories: ['abc'])
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'raises an exception if the api responds with an error code' do
|
159
|
+
allow(connection).to receive(:put).and_return(response)
|
160
|
+
allow(response).to receive(:status).and_return(404)
|
161
|
+
allow(response).to receive(:body).and_return('{}')
|
162
|
+
expect { api.update_details(resource, {}) }.to raise_error(TransifexApiError)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#resource_exists?' do
|
167
|
+
it 'makes a request with the correct parameters' do
|
168
|
+
expect(connection).to receive(:get) do |url|
|
169
|
+
expect(url).to(
|
170
|
+
end_with("project/#{project_name}/resource/#{resource_slug}/")
|
171
|
+
)
|
172
|
+
|
173
|
+
response
|
174
|
+
end
|
175
|
+
|
176
|
+
allow(response).to receive(:status).and_return(200)
|
177
|
+
api.resource_exists?(resource)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'returns true if the api responds with a 200 status code' do
|
181
|
+
allow(connection).to receive(:get).and_return(response)
|
182
|
+
allow(response).to receive(:status).and_return(200)
|
183
|
+
expect(api.resource_exists?(resource)).to eq(true)
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'returns false if the api does not respond with a 200 status code' do
|
187
|
+
allow(connection).to receive(:get).and_return(response)
|
188
|
+
allow(response).to receive(:status).and_return(404)
|
189
|
+
expect(api.resource_exists?(resource)).to eq(false)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '#download' do
|
194
|
+
let(:language) { 'pt-BR' }
|
195
|
+
|
196
|
+
it 'makes a request with the correct parameters' do
|
197
|
+
expect(connection).to receive(:get) do |url|
|
198
|
+
expect(url).to(
|
199
|
+
end_with("project/#{project_name}/resource/#{resource_slug}/translation/#{language}/")
|
200
|
+
)
|
201
|
+
|
202
|
+
response
|
203
|
+
end
|
204
|
+
|
205
|
+
allow(response).to receive(:status).and_return(200)
|
206
|
+
allow(response).to receive(:body).and_return('{}')
|
207
|
+
api.download(resource, language)
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'parses and returns the response content' do
|
211
|
+
allow(connection).to receive(:get).and_return(response)
|
212
|
+
allow(response).to receive(:status).and_return(200)
|
213
|
+
allow(response).to receive(:body).and_return('{"content": "foobar"}')
|
214
|
+
expect(api.download(resource, language)).to eq('foobar')
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'raises an exception if the api responds with an error code' do
|
218
|
+
allow(connection).to receive(:get).and_return(response)
|
219
|
+
allow(response).to receive(:status).and_return(401)
|
220
|
+
allow(response).to receive(:body).and_return('{}')
|
221
|
+
expect { api.download(resource, language) }.to raise_error(TransifexApiError)
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'raises a specific exception if the api responds with a 404 not found' do
|
225
|
+
allow(connection).to receive(:get).and_return(response)
|
226
|
+
allow(response).to receive(:status).and_return(404)
|
227
|
+
allow(response).to receive(:body).and_return('{}')
|
228
|
+
expect { api.download(resource, language) }.to raise_error(
|
229
|
+
TransifexNotFoundError
|
230
|
+
)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe '#get_resource' do
|
235
|
+
it 'makes a request with the correct parameters' do
|
236
|
+
expect(connection).to receive(:get) do |url, payload|
|
237
|
+
expect(url).to(
|
238
|
+
end_with("project/#{project_name}/resource/#{resource_slug}/")
|
239
|
+
)
|
240
|
+
|
241
|
+
response
|
242
|
+
end
|
243
|
+
|
244
|
+
allow(response).to receive(:status).and_return(200)
|
245
|
+
allow(response).to receive(:body).and_return('{"foo":"bar"}')
|
246
|
+
expect(api.get_resource(*resource.slugs)).to eq({ 'foo' => 'bar' })
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'raises an exception if the api responds with an error code' do
|
250
|
+
allow(connection).to receive(:get).and_return(response)
|
251
|
+
allow(response).to receive(:status).and_return(404)
|
252
|
+
allow(response).to receive(:body).and_return('{}')
|
253
|
+
expect { api.get_resource(*resource.slugs) }.to raise_error(TransifexApiError)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe '#get_resources' do
|
258
|
+
it 'makes a request with the correct parameters' do
|
259
|
+
expect(connection).to receive(:get) do |url, payload|
|
260
|
+
expect(url).to(
|
261
|
+
end_with("project/#{project_name}/resources/")
|
262
|
+
)
|
263
|
+
|
264
|
+
response
|
265
|
+
end
|
266
|
+
|
267
|
+
allow(response).to receive(:status).and_return(200)
|
268
|
+
allow(response).to receive(:body).and_return('{"foo":"bar"}')
|
269
|
+
expect(api.get_resources(project_name)).to eq({ 'foo' => 'bar' })
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'raises an exception if the api responds with an error code' do
|
273
|
+
allow(connection).to receive(:get).and_return(response)
|
274
|
+
allow(response).to receive(:status).and_return(404)
|
275
|
+
allow(response).to receive(:body).and_return('{}')
|
276
|
+
expect { api.get_resources(project_name) }.to raise_error(TransifexApiError)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
describe '#get_languages' do
|
281
|
+
it 'makes a request with the correct parameters' do
|
282
|
+
expect(connection).to receive(:get) do |url, payload|
|
283
|
+
expect(url).to(
|
284
|
+
end_with("project/#{project_name}/languages/")
|
285
|
+
)
|
286
|
+
|
287
|
+
response
|
288
|
+
end
|
289
|
+
|
290
|
+
allow(response).to receive(:status).and_return(200)
|
291
|
+
allow(response).to receive(:body).and_return('[{"language_code":"de"}]')
|
292
|
+
expect(api.get_languages(project_name)).to eq([{ 'language_code' => 'de' }])
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'raises an exception if the api responds with an error code' do
|
296
|
+
allow(connection).to receive(:get).and_return(response)
|
297
|
+
allow(response).to receive(:status).and_return(404)
|
298
|
+
allow(response).to receive(:body).and_return('{}')
|
299
|
+
expect { api.get_languages(project_name) }.to raise_error(TransifexApiError)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
describe '#get_project' do
|
304
|
+
it 'makes a request with the correct parameters' do
|
305
|
+
expect(connection).to receive(:get) do |url, payload|
|
306
|
+
expect(url).to(
|
307
|
+
end_with("project/#{project_name}/")
|
308
|
+
)
|
309
|
+
|
310
|
+
response
|
311
|
+
end
|
312
|
+
|
313
|
+
allow(response).to receive(:status).and_return(200)
|
314
|
+
allow(response).to receive(:body).and_return('{"slug":"projectslug"}')
|
315
|
+
expect(api.get_project(project_name)).to eq({ 'slug' => 'projectslug' })
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'raises an exception if the api responds with an error code' do
|
319
|
+
allow(connection).to receive(:get).and_return(response)
|
320
|
+
allow(response).to receive(:status).and_return(404)
|
321
|
+
allow(response).to receive(:body).and_return('{}')
|
322
|
+
expect { api.get_project(project_name) }.to raise_error(TransifexApiError)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
describe '#get_formats' do
|
327
|
+
it 'makes a request with the correct parameters' do
|
328
|
+
expect(connection).to receive(:get) do |url, payload|
|
329
|
+
expect(url).to end_with("formats/")
|
330
|
+
response
|
331
|
+
end
|
332
|
+
|
333
|
+
allow(response).to receive(:status).and_return(200)
|
334
|
+
allow(response).to receive(:body).and_return('{}')
|
335
|
+
expect(api.get_formats).to eq({})
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'raises an exception if the api responds with an error code' do
|
339
|
+
allow(connection).to receive(:get).and_return(response)
|
340
|
+
allow(response).to receive(:status).and_return(404)
|
341
|
+
allow(response).to receive(:body).and_return('{}')
|
342
|
+
expect { api.get_formats }.to raise_error(TransifexApiError)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|