rainforest-cli 1.4.0 → 1.5.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.
- 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
|