rainforest-cli 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +8 -0
- data/lib/rainforest/cli.rb +2 -1
- data/lib/rainforest/cli/exporter.rb +2 -2
- data/lib/rainforest/cli/http_client.rb +9 -7
- data/lib/rainforest/cli/resources.rb +17 -11
- data/lib/rainforest/cli/runner.rb +54 -2
- data/lib/rainforest/cli/test_parser.rb +1 -1
- data/lib/rainforest/cli/version.rb +1 -1
- data/spec/cli_spec.rb +10 -6
- data/spec/exporter_spec.rb +47 -25
- data/spec/resources_spec.rb +46 -61
- data/spec/runner_spec.rb +68 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 854465637763f313d813365ea7996c8aa2d43808
|
4
|
+
data.tar.gz: 44115420d528b8ee03e501eba5fca683439aecca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c8ed4a11a1bca3e2b58672f1ebaae2c3e12265d458107bd19082a193f44cc47bb22113c4d9714190e19bff7fa383ebab4d8cc4d5b260ffc28a3462c72dff957
|
7
|
+
data.tar.gz: 3a335dbc44d8a00c7910d5b1eabb66d6f25e0d7f4d4e9f982b2b246d8450ec78706c189afbbf817559d091eb613a81dc19f80a319b857289ae02848add661f32
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Rainforest CLI Changelog
|
2
2
|
|
3
|
+
## 1.5.0
|
4
|
+
- Retry on API exceptions when creating a run. (85830adcef426e64bd72c9d6208881e955a5bb0c, @bbeck)
|
5
|
+
- Add `browsers` command. (2a810ec27edfc66ef7bf27d8cb7da1129b05e32b, @epaulet)
|
6
|
+
- Add support for files using `app-source-url`. (562e4772e71e8028209d128091ff644f4ae0a9f6, @marianafranco)
|
7
|
+
- Remove newlines from test actions and questions when exporting. (e28583b553b5f30b33b232b2e377c109123b11ff, @epaulet)
|
8
|
+
|
3
9
|
## 1.4.0
|
4
10
|
- Support for new `--version` command. (4362c85fe599a02eaa1b772d184be31e692e934e, @epaulet)
|
5
11
|
- Validate duplicate RFML IDs before uploading. (67f71d053c755eaf92c1bd205931e89e903b88c9, @curtis-rainforestqa)
|
data/README.md
CHANGED
@@ -72,6 +72,11 @@ See a list of all of your smart folders and their IDs
|
|
72
72
|
rainforest folders
|
73
73
|
```
|
74
74
|
|
75
|
+
See a list of all of your browsers and their IDs
|
76
|
+
```bash
|
77
|
+
rainforest browsers
|
78
|
+
```
|
79
|
+
|
75
80
|
## Options
|
76
81
|
|
77
82
|
### General
|
@@ -87,6 +92,7 @@ Rainforest Tests written using RFML have the following format
|
|
87
92
|
# start_uri: [START_URI]
|
88
93
|
# tags: [TAGS]
|
89
94
|
# site_id: [SITE ID]
|
95
|
+
# browsers: [BROWSER IDS]
|
90
96
|
# [OTHER COMMENTS]
|
91
97
|
|
92
98
|
[ACTION 1]
|
@@ -116,6 +122,8 @@ Optional Fields:
|
|
116
122
|
- `SITE ID` - Site ID for the site this test is for. You can find your available
|
117
123
|
site IDs with the `sites` command. Sites can be configured at
|
118
124
|
https://app.rainforestqa.com/settings/sites.
|
125
|
+
- `BROWSER IDS` - Comma separated list of browsers for this test. You can reference
|
126
|
+
your available browsers with the `browsers` command.
|
119
127
|
- `TAGS` - Comma separated list of your desired tags for this test.
|
120
128
|
- `OTHER COMMENTS` - Any comments you'd like to save to this test. All lines beginning with
|
121
129
|
`#` will be ignored by Rainforest unless they begin with a supported data field,
|
data/lib/rainforest/cli.rb
CHANGED
@@ -35,7 +35,8 @@ module RainforestCli
|
|
35
35
|
when 'validate' then Validator.new(options).validate
|
36
36
|
when 'upload' then Uploader.new(options).upload
|
37
37
|
when 'export' then Exporter.new(options).export
|
38
|
-
when 'sites', 'folders'
|
38
|
+
when 'sites', 'folders', 'browsers'
|
39
|
+
Resources.new(options).public_send(options.command)
|
39
40
|
else
|
40
41
|
logger.fatal 'Unknown command'
|
41
42
|
exit 2
|
@@ -64,8 +64,8 @@ class RainforestCli::Exporter
|
|
64
64
|
when 'step'
|
65
65
|
file.puts '' unless index == 0
|
66
66
|
file.puts "# step #{index + 1}" if @options.debug
|
67
|
-
file.puts element[:element][:action]
|
68
|
-
file.puts element[:element][:response]
|
67
|
+
file.puts element[:element][:action].gsub("\n", ' ')
|
68
|
+
file.puts element[:element][:response].gsub("\n", ' ')
|
69
69
|
else
|
70
70
|
raise "Unknown element type: #{element[:type]}"
|
71
71
|
end
|
@@ -23,14 +23,16 @@ module RainforestCli
|
|
23
23
|
JSON.parse(response.body)
|
24
24
|
end
|
25
25
|
|
26
|
-
def post(url, body = {})
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
def post(url, body = {}, options = {})
|
27
|
+
wrap_exceptions(options[:retries_on_failures]) do
|
28
|
+
response = HTTParty.post make_url(url), {
|
29
|
+
body: body,
|
30
|
+
headers: headers,
|
31
|
+
verify: false
|
32
|
+
}
|
32
33
|
|
33
|
-
|
34
|
+
return JSON.parse(response.body)
|
35
|
+
end
|
34
36
|
end
|
35
37
|
|
36
38
|
def get(url, body = {}, options = {})
|
@@ -1,43 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
class RainforestCli::Resources
|
3
|
+
Resource = Struct.new(:identifier, :name)
|
4
|
+
|
3
5
|
def initialize(options)
|
4
6
|
@client = RainforestCli::HttpClient.new(token: options.token)
|
5
7
|
end
|
6
8
|
|
7
9
|
def sites
|
8
|
-
sites = @client.get('/sites')
|
10
|
+
sites = @client.get('/sites').map { |s| Resource.new(s['id'], s['name']) }
|
9
11
|
|
10
12
|
if sites.empty?
|
11
13
|
logger.info('No sites found on your account.')
|
12
14
|
logger.info('Please visit https://app.rainforestqa.com/settings/sites to create and edit your sites.')
|
13
15
|
else
|
14
|
-
print_table('Site', sites)
|
15
|
-
{ id: site['id'], name: site['name'] }
|
16
|
-
end
|
16
|
+
print_table('Site', sites)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
def folders
|
21
|
-
folders = @client.get('/folders')
|
21
|
+
folders = @client.get('/folders').map { |f| Resource.new(f['id'], f['title']) }
|
22
22
|
|
23
23
|
if folders.empty?
|
24
24
|
logger.info('No folders found on your account.')
|
25
25
|
logger.info('Please visit https://app.rainforestqa.com/folders to create and edit your sites.')
|
26
26
|
else
|
27
|
-
print_table('Folder', folders)
|
28
|
-
{ id: folder['id'], name: folder['title'] }
|
29
|
-
end
|
27
|
+
print_table('Folder', folders)
|
30
28
|
end
|
31
29
|
end
|
32
30
|
|
31
|
+
def browsers
|
32
|
+
account = @client.get('/clients')
|
33
|
+
browsers = account['available_browsers'].map { |b| Resource.new(b['name'], b['description']) }
|
34
|
+
print_table('Browser', browsers)
|
35
|
+
end
|
36
|
+
|
33
37
|
def print_table(resource_name, resources)
|
34
38
|
id_col = "#{resource_name} ID"
|
35
|
-
|
39
|
+
longest_id = resources.map { |r| r.identifier.to_s }.max_by(&:length)
|
40
|
+
col_length = [id_col.length, longest_id.length].max
|
41
|
+
|
42
|
+
table_heading = "#{id_col.rjust(col_length)} | #{resource_name} Name"
|
36
43
|
puts table_heading
|
37
44
|
puts '-' * table_heading.length
|
38
45
|
resources.each do |resource|
|
39
|
-
|
40
|
-
puts "#{resource_data[:id].to_s.rjust(id_col.length)} | #{resource_data[:name]}"
|
46
|
+
puts "#{resource.identifier.to_s.rjust(col_length)} | #{resource.name}"
|
41
47
|
end
|
42
48
|
end
|
43
49
|
|
@@ -19,7 +19,7 @@ module RainforestCli
|
|
19
19
|
logger.debug "POST options: #{post_opts.inspect}"
|
20
20
|
logger.info 'Issuing run'
|
21
21
|
|
22
|
-
response = client.post('/runs', post_opts)
|
22
|
+
response = client.post('/runs', post_opts, retries_on_failures: true)
|
23
23
|
|
24
24
|
if response['error']
|
25
25
|
logger.fatal "Error starting your run: #{response['error']}"
|
@@ -99,7 +99,9 @@ module RainforestCli
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
|
102
|
+
app_source_url = options.app_source_url ? upload_app(options.app_source_url) : options.app_source_url
|
103
|
+
|
104
|
+
post_opts[:app_source_url] = app_source_url if app_source_url
|
103
105
|
post_opts[:crowd] = options.crowd if options.crowd
|
104
106
|
post_opts[:conflict] = options.conflict if options.conflict
|
105
107
|
post_opts[:browsers] = options.browsers if options.browsers
|
@@ -153,5 +155,55 @@ module RainforestCli
|
|
153
155
|
|
154
156
|
return environment['id']
|
155
157
|
end
|
158
|
+
|
159
|
+
def upload_app(app_source_url)
|
160
|
+
return app_source_url if url_valid?(app_source_url)
|
161
|
+
|
162
|
+
unless File.exist?(app_source_url)
|
163
|
+
logger.fatal "App source file: #{app_source_url} not found"
|
164
|
+
exit 1
|
165
|
+
end
|
166
|
+
|
167
|
+
unless File.extname(app_source_url) == '.ipa'
|
168
|
+
logger.fatal "Invalid app source file: #{app_source_url}"
|
169
|
+
exit 1
|
170
|
+
end
|
171
|
+
|
172
|
+
url = client.get('/uploads', {}, retries_on_failures: true)
|
173
|
+
unless url
|
174
|
+
logger.fatal "Failed to upload file #{app_source_url}. Please, check your API token."
|
175
|
+
exit 1
|
176
|
+
end
|
177
|
+
data = File.read(app_source_url)
|
178
|
+
logger.info 'Uploading app source file, this operation may take few minutes...'
|
179
|
+
response_code = upload_file(url, data)
|
180
|
+
|
181
|
+
if response_code != '200'
|
182
|
+
logger.fatal "Failed to upload file #{app_source_url}"
|
183
|
+
exit 1
|
184
|
+
else
|
185
|
+
logger.info 'Upload completed.'
|
186
|
+
return url['path']
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def upload_file(url, body)
|
191
|
+
begin
|
192
|
+
# using Net::HTTP because HTTParty do not support large files
|
193
|
+
http = Net::HTTP.new(url['host'], url['port'])
|
194
|
+
http.use_ssl = true
|
195
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
196
|
+
|
197
|
+
request = Net::HTTP::Put.new(url['uri'])
|
198
|
+
request['Content-Type'] = 'application/zip'
|
199
|
+
request.body = body
|
200
|
+
|
201
|
+
response = http.request(request)
|
202
|
+
return response.code
|
203
|
+
rescue Http::Exceptions::HttpException => e
|
204
|
+
logger.fatal "Error uploading the app source file: #{e.message}"
|
205
|
+
exit 1
|
206
|
+
end
|
207
|
+
end
|
156
208
|
end
|
157
209
|
end
|
@@ -87,7 +87,7 @@ module RainforestCli::TestParser
|
|
87
87
|
@test.browsers = []
|
88
88
|
end
|
89
89
|
|
90
|
-
TEST_DATA_FIELDS = [:start_uri, :title, :
|
90
|
+
TEST_DATA_FIELDS = [:start_uri, :title, :site_id, :browsers].freeze
|
91
91
|
STEP_DATA_FIELDS = [:redirect].freeze
|
92
92
|
CSV_FIELDS = [:tags, :browsers].freeze
|
93
93
|
|
data/spec/cli_spec.rb
CHANGED
@@ -102,7 +102,7 @@ describe RainforestCli do
|
|
102
102
|
|
103
103
|
it 'starts the run with the specified tags' do
|
104
104
|
expect_any_instance_of(http_client).to receive(:post)
|
105
|
-
.with('/runs', tags: ['run-me']).and_return({})
|
105
|
+
.with('/runs', { tags: ['run-me'] }, { retries_on_failures: true }).and_return({})
|
106
106
|
|
107
107
|
start_with_params(params, 0)
|
108
108
|
end
|
@@ -116,7 +116,7 @@ describe RainforestCli do
|
|
116
116
|
.with('/environments', name: 'temporary-env-for-custom-url-via-CLI', url: 'http://ad-hoc.example.com')
|
117
117
|
.and_return({ 'id' => 333 })
|
118
118
|
|
119
|
-
expect_any_instance_of(http_client).to receive(:post).with('/runs', anything)
|
119
|
+
expect_any_instance_of(http_client).to receive(:post).with('/runs', anything, { retries_on_failures: true })
|
120
120
|
.and_return({ 'id' => 1 })
|
121
121
|
|
122
122
|
# This is a hack because when expecting a function to be called with
|
@@ -140,7 +140,8 @@ describe RainforestCli do
|
|
140
140
|
|
141
141
|
expect_any_instance_of(http_client).to receive(:post).with(
|
142
142
|
'/runs',
|
143
|
-
{ tests: [], site_id: 3, environment_id: 333 }
|
143
|
+
{ tests: [], site_id: 3, environment_id: 333 },
|
144
|
+
{ retries_on_failures: true }
|
144
145
|
).and_return({})
|
145
146
|
described_class.start(params)
|
146
147
|
end
|
@@ -155,7 +156,8 @@ describe RainforestCli do
|
|
155
156
|
|
156
157
|
expect_any_instance_of(http_client).to receive(:post).with(
|
157
158
|
'/runs',
|
158
|
-
{ tests: [], environment_id: 123 }
|
159
|
+
{ tests: [], environment_id: 123 },
|
160
|
+
{ retries_on_failures: true }
|
159
161
|
).and_return({})
|
160
162
|
described_class.start(params)
|
161
163
|
end
|
@@ -167,7 +169,8 @@ describe RainforestCli do
|
|
167
169
|
it 'starts the run with smart folder' do
|
168
170
|
expect_any_instance_of(http_client).to receive(:post).with(
|
169
171
|
'/runs',
|
170
|
-
{ smart_folder_id: 123 }
|
172
|
+
{ smart_folder_id: 123 },
|
173
|
+
{ retries_on_failures: true }
|
171
174
|
).and_return({})
|
172
175
|
described_class.start(params)
|
173
176
|
end
|
@@ -179,7 +182,8 @@ describe RainforestCli do
|
|
179
182
|
it 'starts the run without error' do
|
180
183
|
expect_any_instance_of(http_client).to receive(:post).with(
|
181
184
|
'/runs',
|
182
|
-
{ tests: [] }
|
185
|
+
{ tests: [] },
|
186
|
+
{ retries_on_failures: true }
|
183
187
|
).and_return({})
|
184
188
|
allow(ENV).to receive(:[]).with('RAINFOREST_API_TOKEN').and_return('x')
|
185
189
|
described_class.start(params)
|
data/spec/exporter_spec.rb
CHANGED
@@ -9,6 +9,11 @@ describe RainforestCli::Exporter do
|
|
9
9
|
# Collect everything printed to file in an array-like file double object
|
10
10
|
class FileDouble < Array
|
11
11
|
alias_method :puts, :push
|
12
|
+
|
13
|
+
# join into a string like a file
|
14
|
+
def include?(str)
|
15
|
+
join("\n").include?(str)
|
16
|
+
end
|
12
17
|
end
|
13
18
|
|
14
19
|
let(:file) { FileDouble.new }
|
@@ -28,6 +33,21 @@ describe RainforestCli::Exporter do
|
|
28
33
|
]
|
29
34
|
}
|
30
35
|
end
|
36
|
+
let(:test_elements) do
|
37
|
+
[
|
38
|
+
{
|
39
|
+
type: 'step',
|
40
|
+
element: {
|
41
|
+
action: 'Step Action',
|
42
|
+
response: 'Step Response'
|
43
|
+
}
|
44
|
+
},
|
45
|
+
{
|
46
|
+
type: 'test',
|
47
|
+
element: embedded_test
|
48
|
+
}
|
49
|
+
]
|
50
|
+
end
|
31
51
|
let(:single_test) do
|
32
52
|
Rainforest::Test.new(
|
33
53
|
{
|
@@ -36,32 +56,11 @@ describe RainforestCli::Exporter do
|
|
36
56
|
start_uri: '/uri',
|
37
57
|
tags: ['foo', 'bar'],
|
38
58
|
browsers: [
|
39
|
-
{
|
40
|
-
|
41
|
-
|
42
|
-
},
|
43
|
-
{
|
44
|
-
name: 'safari',
|
45
|
-
state: 'enabled'
|
46
|
-
},
|
47
|
-
{
|
48
|
-
name: 'firefox',
|
49
|
-
state: 'disabled'
|
50
|
-
}
|
59
|
+
{ name: 'chrome', state: 'enabled' },
|
60
|
+
{ name: 'safari', state: 'enabled' },
|
61
|
+
{ name: 'firefox', state: 'disabled' }
|
51
62
|
],
|
52
|
-
elements:
|
53
|
-
{
|
54
|
-
type: 'step',
|
55
|
-
element: {
|
56
|
-
action: 'Step Action',
|
57
|
-
response: 'Step Response'
|
58
|
-
}
|
59
|
-
},
|
60
|
-
{
|
61
|
-
type: 'test',
|
62
|
-
element: embedded_test
|
63
|
-
}
|
64
|
-
]
|
63
|
+
elements: test_elements
|
65
64
|
}
|
66
65
|
)
|
67
66
|
end
|
@@ -98,6 +97,29 @@ describe RainforestCli::Exporter do
|
|
98
97
|
expect(comments).to_not include('firefox')
|
99
98
|
end
|
100
99
|
|
100
|
+
context 'action and/or question contain newlines' do
|
101
|
+
let(:action) { "Step Action\nwith newlines\n" }
|
102
|
+
let(:expected_action) { 'Step Action with newlines' }
|
103
|
+
let(:response) { "Step Response\nwith\nnewlines\n" }
|
104
|
+
let(:expected_response) { 'Step Response with newlines' }
|
105
|
+
let(:test_elements) do
|
106
|
+
[
|
107
|
+
{
|
108
|
+
type: 'step',
|
109
|
+
element: {
|
110
|
+
action: action,
|
111
|
+
response: response
|
112
|
+
}
|
113
|
+
}
|
114
|
+
]
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'removes the newlines' do
|
118
|
+
expect(file).to include(expected_action)
|
119
|
+
expect(file).to include(expected_response)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
101
123
|
context 'with embed-tests flag' do
|
102
124
|
let(:options) do
|
103
125
|
instance_double(
|
data/spec/resources_spec.rb
CHANGED
@@ -3,6 +3,22 @@ describe RainforestCli::Resources do
|
|
3
3
|
let(:options) { instance_double('RainforestCli::Options', token: 'fake_token') }
|
4
4
|
subject { described_class.new(options) }
|
5
5
|
|
6
|
+
shared_examples 'a properly formatted resource' do |tested_method|
|
7
|
+
before do
|
8
|
+
allow_any_instance_of(RainforestCli::HttpClient).to receive(:get).and_return(api_response)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'calls the print method with the correct information' do
|
12
|
+
expect(subject).to receive(:print_table) do |_name, resources|
|
13
|
+
resource = resources.first
|
14
|
+
expect(resource.identifier).to eq(expected_id)
|
15
|
+
expect(resource.name).to eq(expected_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
subject.send(tested_method)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
6
22
|
describe '#sites' do
|
7
23
|
context 'no sites configured' do
|
8
24
|
before do
|
@@ -22,39 +38,17 @@ describe RainforestCli::Resources do
|
|
22
38
|
end
|
23
39
|
|
24
40
|
context 'with sites in account' do
|
25
|
-
let(:
|
41
|
+
let(:api_response) do
|
26
42
|
[
|
27
|
-
{
|
28
|
-
|
29
|
-
|
30
|
-
},
|
31
|
-
{
|
32
|
-
'id' => 456,
|
33
|
-
'name'=> 'The Bar Site'
|
34
|
-
},
|
35
|
-
{
|
36
|
-
'id' => 789,
|
37
|
-
'name' => 'The Baz Site'
|
38
|
-
}
|
43
|
+
{ 'id' => 123, 'name' => 'The Foo Site' },
|
44
|
+
{ 'id' => 456, 'name'=> 'The Bar Site' },
|
45
|
+
{ 'id' => 789, 'name' => 'The Baz Site' }
|
39
46
|
]
|
40
47
|
end
|
48
|
+
let(:expected_id) { api_response.first['id'] }
|
49
|
+
let(:expected_name) { api_response.first['name'] }
|
41
50
|
|
42
|
-
|
43
|
-
allow_any_instance_of(RainforestCli::HttpClient).to receive(:get).and_return(sites)
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'calls the print method' do
|
47
|
-
expect(subject).to receive(:print_table).with('Site', sites).and_yield(sites.first)
|
48
|
-
subject.sites
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'correctly formats the site information in the given block' do
|
52
|
-
expect(subject).to receive(:print_table) do |_resource_name, _resource, &blk|
|
53
|
-
site = sites.first
|
54
|
-
expect(blk.call(site)).to include(id: site['id'], name: site['name'])
|
55
|
-
end
|
56
|
-
subject.sites
|
57
|
-
end
|
51
|
+
it_should_behave_like 'a properly formatted resource', :sites
|
58
52
|
end
|
59
53
|
end
|
60
54
|
|
@@ -77,46 +71,39 @@ describe RainforestCli::Resources do
|
|
77
71
|
end
|
78
72
|
|
79
73
|
context 'with folders in account' do
|
80
|
-
let(:
|
74
|
+
let(:api_response) do
|
81
75
|
[
|
82
|
-
{
|
83
|
-
|
84
|
-
|
85
|
-
},
|
86
|
-
{
|
87
|
-
'id' => 456,
|
88
|
-
'title'=> 'The Bar Folder'
|
89
|
-
},
|
90
|
-
{
|
91
|
-
'id' => 789,
|
92
|
-
'title' => 'The Baz Folder'
|
93
|
-
}
|
76
|
+
{ 'id' => 123, 'title' => 'The Foo Folder' },
|
77
|
+
{ 'id' => 456, 'title'=> 'The Bar Folder' },
|
78
|
+
{ 'id' => 789, 'title' => 'The Baz Folder' }
|
94
79
|
]
|
95
80
|
end
|
81
|
+
let(:expected_id) { api_response.first['id'] }
|
82
|
+
let(:expected_name) { api_response.first['title'] }
|
96
83
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
it 'calls the print method' do
|
102
|
-
expect(subject).to receive(:print_table).with('Folder', folders).and_yield(folders.first)
|
103
|
-
subject.folders
|
104
|
-
end
|
84
|
+
it_should_behave_like 'a properly formatted resource', :folders
|
85
|
+
end
|
86
|
+
end
|
105
87
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
88
|
+
describe '#browsers' do
|
89
|
+
let(:api_resources) do
|
90
|
+
[
|
91
|
+
{ 'name' => 'chrome', 'description' => 'Chrome' },
|
92
|
+
{ 'name' => 'safari', 'description' => 'Safari' },
|
93
|
+
{ 'name' => 'firefox', 'description' => 'Firefox' }
|
94
|
+
]
|
113
95
|
end
|
96
|
+
let(:api_response) { { 'available_browsers' => api_resources } }
|
97
|
+
let(:expected_id) { api_resources.first['name'] }
|
98
|
+
let(:expected_name) { api_resources.first['description'] }
|
99
|
+
|
100
|
+
it_should_behave_like 'a properly formatted resource', :browsers
|
114
101
|
end
|
115
102
|
|
116
103
|
describe '#print_table' do
|
117
104
|
let(:resource_id) { 123456 }
|
118
105
|
let(:resource_name) { 'resource name' }
|
119
|
-
let(:resources) { [
|
106
|
+
let(:resources) { [ RainforestCli::Resources::Resource.new(resource_id, resource_name) ] }
|
120
107
|
|
121
108
|
it 'prints out the resources' do
|
122
109
|
expect(subject).to receive(:puts) do |message|
|
@@ -132,9 +119,7 @@ describe RainforestCli::Resources do
|
|
132
119
|
expect(message).to include(resource_name)
|
133
120
|
end
|
134
121
|
|
135
|
-
subject.print_table('Resource', resources)
|
136
|
-
{ id: resource_id, name: resource_name }
|
137
|
-
end
|
122
|
+
subject.print_table('Resource', resources)
|
138
123
|
end
|
139
124
|
end
|
140
125
|
end
|
data/spec/runner_spec.rb
CHANGED
@@ -57,4 +57,72 @@ describe RainforestCli::Runner do
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
+
describe '#upload_app' do
|
61
|
+
|
62
|
+
context 'with valid URL' do
|
63
|
+
it 'returns the given app_source_url' do
|
64
|
+
expect(subject.upload_app('http://my.app.url')).to eq 'http://my.app.url'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'with invalid URL' do
|
69
|
+
|
70
|
+
it 'errors out and exits if the file does not exists' do
|
71
|
+
expect_any_instance_of(Logger).to receive(:fatal).with('App source file: fobar not found')
|
72
|
+
expect do
|
73
|
+
subject.upload_app('fobar')
|
74
|
+
end.to raise_error(SystemExit) { |error|
|
75
|
+
expect(error.status).to eq 1
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'errors out and exits if not an .ipa file' do
|
80
|
+
File.should_receive(:exist?).with('fobar.txt') { true }
|
81
|
+
expect_any_instance_of(Logger).to receive(:fatal).with('Invalid app source file: fobar.txt')
|
82
|
+
expect do
|
83
|
+
subject.upload_app('fobar.txt')
|
84
|
+
end.to raise_error(SystemExit) { |error|
|
85
|
+
expect(error.status).to eq 1
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'errors out and exits if valid file but invalid token' do
|
90
|
+
File.should_receive(:exist?).with('fobar.ipa') { true }
|
91
|
+
subject.client.should_receive(:get).with('/uploads', {}, retries_on_failures: true) { nil }
|
92
|
+
expect_any_instance_of(Logger).to receive(:fatal).with(
|
93
|
+
'Failed to upload file fobar.ipa. Please, check your API token.')
|
94
|
+
expect do
|
95
|
+
subject.upload_app('fobar.ipa')
|
96
|
+
end.to raise_error(SystemExit) { |error|
|
97
|
+
expect(error.status).to eq 1
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'errors out and exits if was not possible to upload the file' do
|
102
|
+
File.should_receive(:exist?).with('fobar.ipa') { true }
|
103
|
+
File.should_receive(:read).with('fobar.ipa') { 'File data' }
|
104
|
+
url = {'host' => 'host', 'port' => 'port', 'uri' => 'uri', 'path' => 'path'}
|
105
|
+
subject.client.should_receive(:get).with('/uploads', {}, retries_on_failures: true) { url }
|
106
|
+
subject.should_receive(:upload_file).with(url, 'File data') { '500' }
|
107
|
+
expect_any_instance_of(Logger).to receive(:fatal).with('Failed to upload file fobar.ipa')
|
108
|
+
expect do
|
109
|
+
subject.upload_app('fobar.ipa')
|
110
|
+
end.to raise_error(SystemExit) { |error|
|
111
|
+
expect(error.status).to eq 1
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'returns the new app_source_url in case of success' do
|
116
|
+
File.should_receive(:exist?).with('fobar.ipa') { true }
|
117
|
+
File.should_receive(:read).with('fobar.ipa') { 'File data' }
|
118
|
+
url = {'host' => 'host', 'port' => 'port', 'uri' => 'uri', 'path' => 'path'}
|
119
|
+
subject.client.should_receive(:get).with('/uploads', {}, retries_on_failures: true) { url }
|
120
|
+
subject.should_receive(:upload_file).with(url, 'File data') { '200' }
|
121
|
+
|
122
|
+
expect(subject.upload_app('fobar.ipa')).to eq 'path'
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
60
128
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rainforest-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Russell Smith
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-05-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|