rainforest-cli 1.3.1 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 855968ae7a28f0b1023fd41714fefc0fca6b5ad2
4
- data.tar.gz: b4eb76a7382c5645811cbb4cbd97a12eb9385d2a
3
+ metadata.gz: 70b8d8fad3a7886f4cdff271fc383dca7614061a
4
+ data.tar.gz: b9bc2a5e63a3b95ad661a6d74212f9b01a8cefee
5
5
  SHA512:
6
- metadata.gz: 83cf3f5e28a712add5c8077beecfdd869627f911bf9ad66aae75abb7090204ada77c19f450133437f028ca152cc8786198651b5ec4e5b4e168e00025988730d3
7
- data.tar.gz: 5615003a01351ffd1d9acd7ba924580f767c2a2d72f1e14ead0be38097e83c3402a2343d71b58b0fa7fc99b77d80f562ea1bec11b34ea272186cc084beb53bd9
6
+ metadata.gz: c0888185bfefe12bf782dbf73c380b5c75dc3d36bdc8971031b467ff716b152989ebfcafe24ded4c67fe2a190f20a5e87a2ef0fcc8c7ddf880af2cf98ec4be9a
7
+ data.tar.gz: f0080514d2ae49f2bec4662e746343ab8336e721f97e32f3f00250d340b24444cd4290aaa88bb90b59d7d3bab65676b026c26051ba3247294d62b409e8d574f1
data/CHANGELOG.md CHANGED
@@ -1,7 +1,12 @@
1
1
  # Rainforest CLI Changelog
2
2
 
3
+ ## 1.4.0
4
+ - Support for new `--version` command. (4362c85fe599a02eaa1b772d184be31e692e934e, @epaulet)
5
+ - Validate duplicate RFML IDs before uploading. (67f71d053c755eaf92c1bd205931e89e903b88c9, @curtis-rainforestqa)
6
+ - Add `folders` commands for a folder ID reference. (4ab19fec0924b4764e140fb3c5aa85f1dbfe4006, @epaulet)
7
+
3
8
  ## 1.3.1 - 11th April 2016
4
- - Support crowd selection
9
+ - Support crowd selection. (03fedacfb7a6e69a174fb3e0e1fd75218fdbbfa9, @ukd1)
5
10
 
6
11
  ## 1.3.0 - 7th April 2016
7
12
  - Export tests with embedded tests unflattened. (0ed4c62cac8a0d5fbd98f03190d3c18c48ac7119,
data/README.md CHANGED
@@ -62,6 +62,16 @@ Export all tests from Rainforest
62
62
  rainforest export
63
63
  ```
64
64
 
65
+ See a list of all of your sites and their IDs
66
+ ```bash
67
+ rainforest sites
68
+ ```
69
+
70
+ See a list of all of your smart folders and their IDs
71
+ ```bash
72
+ rainforest folders
73
+ ```
74
+
65
75
  ## Options
66
76
 
67
77
  ### General
@@ -134,6 +144,7 @@ Popular command line options are:
134
144
  - `--description "CI automatic run"` - add an arbitrary description for the run.
135
145
  - `--embed-tests` - Use with `rainforest export` to export your tests without extracting the
136
146
  steps of an embedded test.
147
+ - `--test-folder /path/to/directory` - Use with `rainforest [new, upload, export]`. If this option is not provided, rainforest-cli will, in the case of 'new' create a directory, or in the case of 'upload' and 'export' use the directory, at the default path `./spec/rainforest/`.
137
148
 
138
149
 
139
150
  #### Specifying Test IDs
@@ -15,7 +15,7 @@ require 'rainforest/cli/remote_tests'
15
15
  require 'rainforest/cli/validator'
16
16
  require 'rainforest/cli/exporter'
17
17
  require 'rainforest/cli/uploader'
18
- require 'rainforest/cli/sites'
18
+ require 'rainforest/cli/resources'
19
19
 
20
20
  module RainforestCli
21
21
  def self.start(args)
@@ -30,24 +30,12 @@ module RainforestCli
30
30
  end
31
31
 
32
32
  case options.command
33
- when 'run'
34
- runner = Runner.new(options)
35
- runner.run
36
- when 'new'
37
- t = TestFiles.new(options)
38
- t.create_file
39
- when 'validate'
40
- t = Validator.new(options)
41
- t.validate
42
- when 'upload'
43
- t = Uploader.new(options)
44
- t.upload
45
- when 'export'
46
- t = Exporter.new(options)
47
- t.export
48
- when 'sites'
49
- t = Sites.new(options)
50
- t.list_sites
33
+ when 'run' then Runner.new(options).run
34
+ when 'new' then TestFiles.new(options).create_file
35
+ when 'validate' then Validator.new(options).validate
36
+ when 'upload' then Uploader.new(options).upload
37
+ when 'export' then Exporter.new(options).export
38
+ when 'sites', 'folders' then Resources.new(options).public_send(options.command)
51
39
  else
52
40
  logger.fatal 'Unknown command'
53
41
  exit 2
@@ -53,6 +53,9 @@ module RainforestCli
53
53
  # NOTE: Disabling line length cop to allow for consistency of syntax
54
54
  # rubocop:disable Metrics/LineLength
55
55
  @parsed = ::OptionParser.new do |opts|
56
+ opts.set_program_name 'Rainforest CLI'
57
+ opts.version = RainforestCli::VERSION
58
+
56
59
  opts.on('--debug') do
57
60
  @debug = true
58
61
  end
@@ -138,6 +141,11 @@ module RainforestCli
138
141
  exit 0
139
142
  end
140
143
 
144
+ opts.on_tail('--version', 'Display gem version') do
145
+ puts opts.ver
146
+ exit 0
147
+ end
148
+
141
149
  end.parse!(@args)
142
150
  # rubocop:enable Metrics/LineLength
143
151
  # NOTE: end Rubocop exception
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ class RainforestCli::Resources
3
+ def initialize(options)
4
+ @client = RainforestCli::HttpClient.new(token: options.token)
5
+ end
6
+
7
+ def sites
8
+ sites = @client.get('/sites')
9
+
10
+ if sites.empty?
11
+ logger.info('No sites found on your account.')
12
+ logger.info('Please visit https://app.rainforestqa.com/settings/sites to create and edit your sites.')
13
+ else
14
+ print_table('Site', sites) do |site|
15
+ { id: site['id'], name: site['name'] }
16
+ end
17
+ end
18
+ end
19
+
20
+ def folders
21
+ folders = @client.get('/folders')
22
+
23
+ if folders.empty?
24
+ logger.info('No folders found on your account.')
25
+ logger.info('Please visit https://app.rainforestqa.com/folders to create and edit your sites.')
26
+ else
27
+ print_table('Folder', folders) do |folder|
28
+ { id: folder['id'], name: folder['title'] }
29
+ end
30
+ end
31
+ end
32
+
33
+ def print_table(resource_name, resources)
34
+ id_col = "#{resource_name} ID"
35
+ table_heading = "#{id_col} | #{resource_name} Name"
36
+ puts table_heading
37
+ puts '-' * table_heading.length
38
+ resources.each do |resource|
39
+ resource_data = yield(resource)
40
+ puts "#{resource_data[:id].to_s.rjust(id_col.length)} | #{resource_data[:name]}"
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def logger
47
+ RainforestCli.logger
48
+ end
49
+ end
@@ -32,7 +32,9 @@ class RainforestCli::Validator
32
32
  # (no short-circuiting with ||)
33
33
  parsing_errors = has_parsing_errors?
34
34
  dependency_errors = has_test_dependency_errors?
35
- is_invalid = parsing_errors || dependency_errors
35
+ duplicate_rfml_id_errors = has_duplicate_rfml_id_errors?
36
+
37
+ is_invalid = parsing_errors || dependency_errors || duplicate_rfml_id_errors
36
38
 
37
39
  logger.info ''
38
40
  logger.info(is_invalid ? VALIDATIONS_FAILED : VALIDATIONS_PASSED)
@@ -48,6 +50,21 @@ class RainforestCli::Validator
48
50
  end
49
51
  end
50
52
 
53
+ def has_duplicate_rfml_id_errors?
54
+ duped_rfml_ids_and_counts = collect_duplicate_rfml_ids
55
+ return false unless duped_rfml_ids_and_counts.size > 0
56
+ duplicate_rfml_ids_notification(duped_rfml_ids_and_counts)
57
+ true
58
+ end
59
+
60
+ def collect_duplicate_rfml_ids
61
+ rfml_ids_and_counts = Hash.new(0)
62
+ local_tests.test_data.each do |test|
63
+ rfml_ids_and_counts[test.rfml_id] += 1
64
+ end
65
+ rfml_ids_and_counts.select {|_, count| count > 1}
66
+ end
67
+
51
68
  def has_parsing_errors?
52
69
  logger.info 'Validating parsing errors...'
53
70
  has_parsing_errors = rfml_tests.select { |t| t.errors.any? }
@@ -152,6 +169,16 @@ class RainforestCli::Validator
152
169
  logger.error ''
153
170
  end
154
171
 
172
+ def duplicate_rfml_ids_notification(duplicate_rfml_ids_and_counts)
173
+ logger.error "The test ids are not unique!"
174
+ logger.error ''
175
+ duplicate_rfml_ids_and_counts.each do |rfml_id, count|
176
+ count_str = count == 1 ? 'is 1 file' : "are #{count} files"
177
+ logger.error "\tThere #{count_str} with an id of #{rfml_id}"
178
+ end
179
+ logger.error ''
180
+ end
181
+
155
182
  def logger
156
183
  RainforestCli.logger
157
184
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module RainforestCli
3
- VERSION = '1.3.1'
3
+ VERSION = '1.4.0'
4
4
  end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+ describe RainforestCli::Resources do
3
+ let(:options) { instance_double('RainforestCli::Options', token: 'fake_token') }
4
+ subject { described_class.new(options) }
5
+
6
+ describe '#sites' do
7
+ context 'no sites configured' do
8
+ before do
9
+ allow_any_instance_of(RainforestCli::HttpClient).to receive(:get).and_return([])
10
+ end
11
+
12
+ it 'directs you to the site settings' do
13
+ # first line of text
14
+ expect(RainforestCli.logger).to receive(:info).with(an_instance_of(String))
15
+ # second line of text
16
+ expect(RainforestCli.logger).to receive(:info) do |message|
17
+ expect(message).to include('/settings/sites')
18
+ end
19
+
20
+ subject.sites
21
+ end
22
+ end
23
+
24
+ context 'with sites in account' do
25
+ let(:sites) do
26
+ [
27
+ {
28
+ 'id' => 123,
29
+ 'name' => 'The Foo Site'
30
+ },
31
+ {
32
+ 'id' => 456,
33
+ 'name'=> 'The Bar Site'
34
+ },
35
+ {
36
+ 'id' => 789,
37
+ 'name' => 'The Baz Site'
38
+ }
39
+ ]
40
+ end
41
+
42
+ before do
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
58
+ end
59
+ end
60
+
61
+ describe '#folders' do
62
+ context 'no folders in account' do
63
+ before do
64
+ allow_any_instance_of(RainforestCli::HttpClient).to receive(:get).and_return([])
65
+ end
66
+
67
+ it 'directs you to the folders page' do
68
+ # first line of text
69
+ expect(RainforestCli.logger).to receive(:info).with(an_instance_of(String))
70
+ # second line of text
71
+ expect(RainforestCli.logger).to receive(:info) do |message|
72
+ expect(message).to include('/folders')
73
+ end
74
+
75
+ subject.folders
76
+ end
77
+ end
78
+
79
+ context 'with folders in account' do
80
+ let(:folders) do
81
+ [
82
+ {
83
+ 'id' => 123,
84
+ 'title' => 'The Foo Folder'
85
+ },
86
+ {
87
+ 'id' => 456,
88
+ 'title'=> 'The Bar Folder'
89
+ },
90
+ {
91
+ 'id' => 789,
92
+ 'title' => 'The Baz Folder'
93
+ }
94
+ ]
95
+ end
96
+
97
+ before do
98
+ allow_any_instance_of(RainforestCli::HttpClient).to receive(:get).and_return(folders)
99
+ end
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
105
+
106
+ it 'correctly formats the site information in the given block' do
107
+ expect(subject).to receive(:print_table) do |_resource_name, _resource, &blk|
108
+ folder = folders.first
109
+ expect(blk.call(folder)).to include(id: folder['id'], name: folder['title'])
110
+ end
111
+ subject.folders
112
+ end
113
+ end
114
+ end
115
+
116
+ describe '#print_table' do
117
+ let(:resource_id) { 123456 }
118
+ let(:resource_name) { 'resource name' }
119
+ let(:resources) { [ { id: resource_id, name: resource_name } ] }
120
+
121
+ it 'prints out the resources' do
122
+ expect(subject).to receive(:puts) do |message|
123
+ expect(message).to include('Resource ID')
124
+ expect(message).to include('Resource Name')
125
+ end
126
+
127
+ # Stub dashed the line dividing table header and body
128
+ expect(subject).to receive(:puts)
129
+
130
+ expect(subject).to receive(:puts) do |message|
131
+ expect(message).to include(resource_id.to_s)
132
+ expect(message).to include(resource_name)
133
+ end
134
+
135
+ subject.print_table('Resource', resources) do
136
+ { id: resource_id, name: resource_name }
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,7 @@
1
+ #! a-test
2
+ # title: New test
3
+ # start_uri: /
4
+ #
5
+
6
+ This is a step action.
7
+ This is a step question?
@@ -0,0 +1,7 @@
1
+ #! a-test
2
+ # title: Some other test
3
+ # start_uri: /
4
+ #
5
+
6
+ This is another action.
7
+ This is another question?
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe RainforestCli::Validator do
4
- let(:rfml_id_regex) { /^#! (.+?)($| .+?$)/ }
5
4
  let(:file_path) { File.join(test_directory, correct_file_name) }
6
5
 
7
6
  def notifies_with_correct_file_name
@@ -29,6 +28,8 @@ describe RainforestCli::Validator do
29
28
  end
30
29
 
31
30
  shared_examples 'it detects all the correct errors' do
31
+ let(:tested_method) { :validate }
32
+ let(:raises_error) { false }
32
33
  let(:options) { instance_double('RainforestCli::Options', test_folder: test_directory, token: 'api_token') }
33
34
  subject { described_class.new(options) }
34
35
 
@@ -92,10 +93,24 @@ describe RainforestCli::Validator do
92
93
  end
93
94
 
94
95
  describe '#validate' do
95
- let(:tested_method) { :validate }
96
- let(:raises_error) { false }
97
-
98
96
  it_behaves_like 'it detects all the correct errors'
97
+
98
+ context 'when multiple tests have the same rfml_ids' do
99
+ let(:test_directory) { File.expand_path(File.join(__FILE__, '../validation-examples/duplicate_rfml_ids')) }
100
+ let(:options) { instance_double('RainforestCli::Options', test_folder: test_directory, token: 'api_token') }
101
+
102
+ subject { described_class.new(options) }
103
+
104
+ before do
105
+ allow(subject).to receive(:remote_rfml_ids) { [] }
106
+ end
107
+
108
+ it 'logs the errors' do
109
+ expect(subject).to receive(:duplicate_rfml_ids_notification).with({'a-test' => 2}).and_call_original
110
+
111
+ subject.validate
112
+ end
113
+ end
99
114
  end
100
115
 
101
116
  describe '#validate_with_exception!' do
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.3.1
4
+ version: 1.4.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-04-11 00:00:00.000000000 Z
12
+ date: 2016-04-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty
@@ -169,8 +169,8 @@ files:
169
169
  - lib/rainforest/cli/http_client.rb
170
170
  - lib/rainforest/cli/options.rb
171
171
  - lib/rainforest/cli/remote_tests.rb
172
+ - lib/rainforest/cli/resources.rb
172
173
  - lib/rainforest/cli/runner.rb
173
- - lib/rainforest/cli/sites.rb
174
174
  - lib/rainforest/cli/test_files.rb
175
175
  - lib/rainforest/cli/test_parser.rb
176
176
  - lib/rainforest/cli/uploader.rb
@@ -193,8 +193,8 @@ files:
193
193
  - spec/redirection-examples/wrong_redirect_embedded.rfml
194
194
  - spec/redirection-examples/wrong_redirect_spacing.rfml
195
195
  - spec/remote_tests_spec.rb
196
+ - spec/resources_spec.rb
196
197
  - spec/runner_spec.rb
197
- - spec/sites_spec.rb
198
198
  - spec/spec_helper.rb
199
199
  - spec/test_files_spec.rb
200
200
  - spec/test_parser_spec.rb
@@ -203,6 +203,8 @@ files:
203
203
  - spec/validation-examples/circular_embeds/test2.rfml
204
204
  - spec/validation-examples/correct_embeds/embedded_test.rfml
205
205
  - spec/validation-examples/correct_embeds/test_with_embedded.rfml
206
+ - spec/validation-examples/duplicate_rfml_ids/file1.rfml
207
+ - spec/validation-examples/duplicate_rfml_ids/file2.rfml
206
208
  - spec/validation-examples/missing_embeds/correct_test.rfml
207
209
  - spec/validation-examples/missing_embeds/incorrect_test.rfml
208
210
  - spec/validation-examples/parse_errors/no_parse_errors.rfml
@@ -251,8 +253,8 @@ test_files:
251
253
  - spec/redirection-examples/wrong_redirect_embedded.rfml
252
254
  - spec/redirection-examples/wrong_redirect_spacing.rfml
253
255
  - spec/remote_tests_spec.rb
256
+ - spec/resources_spec.rb
254
257
  - spec/runner_spec.rb
255
- - spec/sites_spec.rb
256
258
  - spec/spec_helper.rb
257
259
  - spec/test_files_spec.rb
258
260
  - spec/test_parser_spec.rb
@@ -261,6 +263,8 @@ test_files:
261
263
  - spec/validation-examples/circular_embeds/test2.rfml
262
264
  - spec/validation-examples/correct_embeds/embedded_test.rfml
263
265
  - spec/validation-examples/correct_embeds/test_with_embedded.rfml
266
+ - spec/validation-examples/duplicate_rfml_ids/file1.rfml
267
+ - spec/validation-examples/duplicate_rfml_ids/file2.rfml
264
268
  - spec/validation-examples/missing_embeds/correct_test.rfml
265
269
  - spec/validation-examples/missing_embeds/incorrect_test.rfml
266
270
  - spec/validation-examples/parse_errors/no_parse_errors.rfml
@@ -268,3 +272,4 @@ test_files:
268
272
  - spec/validation-examples/parse_errors/no_question_mark.rfml
269
273
  - spec/validation-examples/parse_errors/no_rfml_id.rfml
270
274
  - spec/validator_spec.rb
275
+ has_rdoc:
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
- class RainforestCli::Sites
3
- def initialize(options)
4
- @client = RainforestCli::HttpClient.new(token: options.token)
5
- end
6
-
7
- def list_sites
8
- sites = fetch_sites
9
-
10
- if sites.empty?
11
- logger.info('No configured sites found on your account.')
12
- logger.info('Please visit https://app.rainforestqa.com/settings/sites to create and edit your sites.')
13
- else
14
- print_site_table(sites)
15
- end
16
- end
17
-
18
- def print_site_table(sites)
19
- puts 'Site ID | Site Name'
20
- puts '-------------------'
21
- sites.each do |site|
22
- puts "#{site['id'].to_s.rjust(7)} | #{site['name']}"
23
- end
24
- end
25
-
26
- private
27
-
28
- def fetch_sites
29
- @sites ||= @client.get('/sites')
30
- end
31
-
32
- def logger
33
- RainforestCli.logger
34
- end
35
- end
data/spec/sites_spec.rb DELETED
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
- describe RainforestCli::Sites do
3
- let(:options) { instance_double('RainforestCli::Options', token: 'fake_token') }
4
- subject { described_class.new(options) }
5
-
6
- let(:sites) do
7
- [
8
- {
9
- 'id' => 123,
10
- 'name' => 'The Foo Site'
11
- },
12
- {
13
- 'id' => 456,
14
- 'name'=> 'The Bar Site'
15
- },
16
- {
17
- 'id' => 789,
18
- 'name' => 'The Baz Site'
19
- }
20
- ]
21
- end
22
-
23
- describe '#list_sites' do
24
- context 'no sites configured' do
25
- before do
26
- allow_any_instance_of(RainforestCli::HttpClient).to receive(:get).and_return([])
27
- end
28
-
29
- it 'directs you to the site settings' do
30
- # first line of text
31
- expect(RainforestCli.logger).to receive(:info).with(an_instance_of(String))
32
- # second line of text
33
- expect(RainforestCli.logger).to receive(:info) do |message|
34
- expect(message).to include('/settings/sites')
35
- end
36
-
37
- subject.list_sites
38
- end
39
- end
40
-
41
- context 'with sites configured' do
42
- before do
43
- allow_any_instance_of(RainforestCli::HttpClient).to receive(:get).and_return(sites)
44
- end
45
-
46
- it 'prints the site table' do
47
- expect(subject).to receive(:print_site_table).with(sites)
48
- subject.list_sites
49
- end
50
-
51
- end
52
- end
53
-
54
- describe '#print_site_table' do
55
- it 'prints out the sites' do
56
- expect(subject).to receive(:puts) do |message|
57
- expect(message).to include('Site ID')
58
- expect(message).to include('Site Name')
59
- end
60
-
61
- # The line dividing table header and body
62
- expect(subject).to receive(:puts)
63
-
64
- sites.each do |site|
65
- expect(subject).to receive(:puts) do |message|
66
- expect(message).to include(site['id'].to_s)
67
- expect(message).to include(site['name'])
68
- end
69
- end
70
-
71
- subject.print_site_table(sites)
72
- end
73
- end
74
- end