quke 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a97a09f733f534285c847c3d370ece578c2bbb4
4
- data.tar.gz: 20e5a6f2fa15f487fe6e091ee43270b68a29090c
3
+ metadata.gz: 0051a72fdd98008ae4f027109205c8d3bce58f3f
4
+ data.tar.gz: f15a28e5d9952605671bce3a877d4f8f87d2c668
5
5
  SHA512:
6
- metadata.gz: 78ee9101a34857bc43f390e9c1355cc8c7f06af00bbbb8b59c71c023eb33699057fa30344c08bc96789d3a0de6ea3cfc8882858b111c529d5f6b37360978bd0a
7
- data.tar.gz: 8b6ab52037eeeed7f7346a3712633d3eb31db261332d928979295513097630a5e6822ce45c3df47b33d18a1488eea5a6e961eef0f362d311d70633fc3a2509b7
6
+ metadata.gz: a3330b63b302bf6023d014498f577a5fe373550705d6ab3f1c098692bb6a55c22fc9710e24739ff0e351c2b0c89e2c1f489f8f14e821ebf1413ba1ff1772a1f8
7
+ data.tar.gz: 9918ae1f6936bdc891bf4c67634fa6e96f0b8b7a9f01284b183286a741cc38e5941f03a664b1fcc84fefbb333ffa9141e09c35dad1df37a79974fb0731afeb42
data/README.md CHANGED
@@ -124,9 +124,11 @@ You should be aware of some default behaviours included in Quke.
124
124
 
125
125
  Capybara includes the ability to save the source of the current page at any point. Quke has been configured so that if you are not using a headless browser and a step fails it will save the source to file and then use a tool called [Launchy](https://github.com/copiousfreetime/launchy) to open it in your default browser.
126
126
 
127
+ You can disable this behaviour using `display_failures: false` in your `.config.yml`
128
+
127
129
  ### Quit on 5 failures
128
130
 
129
- If you are running using Chrome or Firefox after the 5th failure Quke will automatically stop. This is to prevent scores of tabs being opened in the browser when an error is found, which may just be the result of an error in the test code.
131
+ If you are running using Chrome or Firefox after the 5th failure Quke will automatically stop. This is to prevent scores of tabs being opened in the browser when an error is found and Quke is set to show failures, which may just be the result of an error in the test code.
130
132
 
131
133
  ### Automatically setting Browserstack session status
132
134
 
@@ -14,22 +14,20 @@ After("not @nonweb") do |scenario|
14
14
  if scenario.failed?
15
15
  $fail_count = $fail_count + 1
16
16
 
17
- # Tell Cucumber to quit after first failing scenario when stop_on_error is
18
- # true.
19
- # Also experience has shown that should a major element of your service go
17
+ # Experience has shown that should a major element of your service go
20
18
  # down all your tests will start failing which means you can be swamped
21
19
  # with output from `save_and_open_page`. Using a global count of the
22
20
  # number of fails, if it hits 5 it will cause cucumber to close.
23
- if Quke::Quke.config.stop_on_error || $fail_count >= 5
21
+ if $fail_count >= 5 && !%w["chrome firefox"].include?(Quke::Quke.config.driver)
24
22
  Cucumber.wants_to_quit = true
25
23
  else
26
- # If we're not using poltergiest or running in headless mode and the
27
- # scenario has failed, we want to save a copy of the page and open it
28
- # automatically using Launchy. We wrap this in a begin/rescue in case of
29
- # any issues in which case it defaults to outputting the source to STDOUT.
24
+ # Depending on our config, driver and whether we are running headless we
25
+ # may want to save a copy of the page and open it automatically using
26
+ # Launchy. We wrap this in a begin/rescue in case of any issues in which
27
+ # case it defaults to outputting the source to STDOUT.
30
28
  begin
31
29
  # rubocop:disable Lint/Debugger
32
- save_and_open_page unless Quke::Quke.config.headless
30
+ save_and_open_page if Quke::Quke.config.display_failures?
33
31
  # rubocop:enable Lint/Debugger
34
32
  rescue StandardError
35
33
  # handle e
@@ -10,6 +10,8 @@ require "quke/configuration"
10
10
  require "quke/cuke_runner"
11
11
  require "quke/driver_registration"
12
12
  require "quke/driver_configuration"
13
+ require "quke/parallel_configuration"
14
+ require "quke/proxy_configuration"
13
15
 
14
16
  module Quke #:nodoc:
15
17
 
@@ -136,10 +136,10 @@ module Quke #:nodoc:
136
136
  # Rather than
137
137
  "logfile" => File.join(Dir.pwd, "/tmp/bowerstack_local_log.txt")
138
138
  }
139
- return unless configuration.use_proxy?
139
+ return unless configuration.proxy.use_proxy?
140
140
 
141
- @local_testing_args["proxyHost"] = configuration.proxy["host"]
142
- @local_testing_args["proxyPort"] = configuration.proxy["port"].to_s
141
+ @local_testing_args["proxyHost"] = configuration.proxy.host
142
+ @local_testing_args["proxyPort"] = configuration.proxy.port.to_s
143
143
  end
144
144
 
145
145
  end
@@ -18,6 +18,20 @@ module Quke #:nodoc:
18
18
  # returning the config for setting up Quke to use browserstack.
19
19
  attr_reader :browserstack
20
20
 
21
+ # Instance of +Quke::ParallelConfiguration+ which manages reading and
22
+ # returning the config for setting up Quke to use parallel tests.
23
+ #
24
+ # The instance will be populated based on what was set in the config.yml
25
+ # merged with default values.
26
+ #
27
+ # These values will then tell Quke whether to run tests in parallel, and if
28
+ # so how to setup the runs.
29
+ attr_reader :parallel
30
+
31
+ # Instance of +Quke::ProxyConfiguration+ which manages reading and
32
+ # returning the config for setting up Quke to use proxy server.
33
+ attr_reader :proxy
34
+
21
35
  class << self
22
36
  # Class level setter for the location of the config file.
23
37
  #
@@ -41,10 +55,13 @@ module Quke #:nodoc:
41
55
  end
42
56
 
43
57
  # When an instance is initialized it will automatically populate itself by
44
- # calling a private method +load_data()+.
58
+ # calling a private method +default_data()+.
45
59
  def initialize
46
- @data = load_data
60
+ @data = default_data!(load_yml_data)
61
+ # Order is important. @browserstack relies on @proxy being set
62
+ @proxy = ::Quke::ProxyConfiguration.new(@data["proxy"] || {})
47
63
  @browserstack = ::Quke::BrowserstackConfiguration.new(self)
64
+ @parallel = ::Quke::ParallelConfiguration.new(self)
48
65
  end
49
66
 
50
67
  # Returns the value set for +features_folder+.
@@ -87,21 +104,6 @@ module Quke #:nodoc:
87
104
  @data["headless"]
88
105
  end
89
106
 
90
- # Returns the value set for +parallel+.
91
- #
92
- # Tells Quke whether run the features in parallel. Depending on the number
93
- # of cores on the host machine, it will split the features across a given
94
- # number of processes and run them in parallel.
95
- #
96
- # This is great if you have a large test suite (the performance improvement
97
- # is negligible if you only have a few). However your scenarios must be
98
- # independent, and the console output will be 'number of processes' *
99
- # cucumber output. This is best used if you are just after a simple
100
- # pass/fail result.
101
- def parallel
102
- @data["parallel"]
103
- end
104
-
105
107
  # Return the value set for +pause+.
106
108
  #
107
109
  # Add a pause (in seconds) between steps so you can visually track how the
@@ -124,6 +126,26 @@ module Quke #:nodoc:
124
126
  # rubocop:enable Security/YAMLLoad
125
127
  end
126
128
 
129
+ # Returns the value set for +display_failures+.
130
+ #
131
+ # Tells Quke not to display the html for the last page when a failure
132
+ # happens. Quke uses Capybara to save a copy of the page as html and uses
133
+ # launchy to display it in the default browser.
134
+ def display_failures
135
+ @data["display_failures"]
136
+ end
137
+
138
+ # Returns whether failures should be displayed.
139
+ #
140
+ # If the browser is headless then we never display failures, even if the
141
+ # setting has been set to true. Else whether we display a failure is based
142
+ # on the value set for display_failures.
143
+ def display_failures?
144
+ return false if headless
145
+
146
+ display_failures
147
+ end
148
+
127
149
  # Return the value for +max_wait_time+
128
150
  #
129
151
  # +max_wait_time+ is the time Capybara will spend waiting for an element
@@ -161,22 +183,13 @@ module Quke #:nodoc:
161
183
  @data["javascript_errors"]
162
184
  end
163
185
 
164
- # Return the hash of +proxy+ server settings
165
- #
166
- # If your environment requires you to go via a proxy server you can
167
- # configure Quke to use it by setting the +host+ and +port+ in your config
168
- # file.
169
- def proxy
170
- @data["proxy"]
171
- end
172
-
173
- # Return true if the +proxy: host+ value has been set in the +.config.yml+
174
- # file, else false.
186
+ # Returns the value set for +print_progress+.
175
187
  #
176
- # It is mainly used when determining whether to apply proxy server settings
177
- # to the different drivers when registering them with Capybara.
178
- def use_proxy?
179
- proxy["host"] != ""
188
+ # If set Quke will tell Cucumber to output to the console using its
189
+ # 'progress' formatter, rather than the default 'pretty' which displays each
190
+ # scenario in detail.
191
+ def print_progress
192
+ @data["print_progress"]
180
193
  end
181
194
 
182
195
  # Return the hash of +custom+ server settings
@@ -195,14 +208,36 @@ module Quke #:nodoc:
195
208
  @data["custom"]
196
209
  end
197
210
 
198
- private
199
-
200
- def load_data
201
- data = default_data!(load_yml_data)
202
- data["proxy"] = proxy_data(data["proxy"])
203
- data
211
+ # Returns a string representing the agruments that are passed to Cucumber
212
+ # by ParallelTests when it creates a new process and executes.
213
+ #
214
+ # Specifically its the value for ParallelTests' `--test-options` argument
215
+ # which will be used when generating the array of args to be passed to
216
+ # ParallelTests. It returns just a string rather than an array because
217
+ # ParallelTests needs to see this as a single argument.
218
+ #
219
+ # The additional args are whatever a user enters after the
220
+ # `bundle exec quke` command.
221
+ def cucumber_arg(additional_args)
222
+ # Because cucumber is called in the context of the executing project and
223
+ # not Quke it will take its arguments in the context of that location, and
224
+ # not from where the Quke currently sits. This means to Cucumber
225
+ # 'lib/features' doesn't exist, which means our env.rb never gets loaded.
226
+ # Instead we first have to determine where this file is running from when
227
+ # called, then we simply replace the last part of that result (which we
228
+ # know will be lib/quke) with lib/features. For example __dir__ returns
229
+ # '/Users/acruikshanks/projects/defra/quke/lib/quke' but we need Cucumber
230
+ # to load '/Users/acruikshanks/projects/defra/quke/lib/features'
231
+ # We then pass this full path to Cucumber so it can correctly find the
232
+ # folder holding our predefined env.rb file.
233
+ env_folder = __dir__.sub!("lib/quke", "lib/features")
234
+ fail_fast = "--fail-fast" if stop_on_error
235
+ print_format = print_progress ? "progress" : "pretty"
236
+ "#{fail_fast} --format #{print_format} -r #{env_folder} -r #{features_folder} #{additional_args.join(' ')}".strip
204
237
  end
205
238
 
239
+ private
240
+
206
241
  # rubocop:disable Metrics/AbcSize
207
242
  # rubocop:disable Metrics/CyclomaticComplexity
208
243
  # rubocop:disable Metrics/PerceivedComplexity
@@ -212,7 +247,7 @@ module Quke #:nodoc:
212
247
  "app_host" => (data["app_host"] || "").downcase.strip,
213
248
  "driver" => (data["driver"] || "phantomjs").downcase.strip,
214
249
  "headless" => (data["headless"].to_s.downcase.strip == "true"),
215
- "parallel" => (data["parallel"].to_s.downcase.strip == "true"),
250
+ "print_progress" => (data["print_progress"].to_s.downcase.strip == "true"),
216
251
  "pause" => (data["pause"] || "0").to_s.downcase.strip.to_i,
217
252
  "stop_on_error" => (data["stop_on_error"] || "false").to_s.downcase.strip,
218
253
  "max_wait_time" => (data["max_wait_time"] || Capybara.default_max_wait_time).to_s.downcase.strip.to_i,
@@ -224,6 +259,7 @@ module Quke #:nodoc:
224
259
  # Else the condition fails and we get 'false', which when flipped gives
225
260
  # us 'true', which is what we want the default value to be
226
261
  # rubocop:disable Style/InverseMethods
262
+ "display_failures" => !(data["display_failures"].to_s.downcase.strip == "false"),
227
263
  "javascript_errors" => !(data["javascript_errors"].to_s.downcase.strip == "false"),
228
264
  # rubocop:enable Style/InverseMethods
229
265
  "custom" => (data["custom"] || nil)
@@ -233,15 +269,6 @@ module Quke #:nodoc:
233
269
  # rubocop:enable Metrics/CyclomaticComplexity
234
270
  # rubocop:enable Metrics/PerceivedComplexity
235
271
 
236
- def proxy_data(data)
237
- data = {} if data.nil?
238
- data.merge(
239
- "host" => (data["host"] || "").downcase.strip,
240
- "port" => (data["port"] || "0").to_s.downcase.strip.to_i,
241
- "no_proxy" => (data["no_proxy"] || "").downcase.strip
242
- )
243
- end
244
-
245
272
  def load_yml_data
246
273
  if File.exist? self.class.file_location
247
274
  # YAML.load_file returns false if the file exists but is empty. So
@@ -8,9 +8,6 @@ module Quke #:nodoc:
8
8
  # Handles executing Cucumber, including sorting the arguments we pass to it
9
9
  class CukeRunner
10
10
 
11
- # Access the arguments used by Quke when it was executed
12
- attr_reader :args
13
-
14
11
  # When an instance of CukeRunner is initialized it will take the arguments
15
12
  # passed in and combine them with its own default args. Those args are a mix
16
13
  # of ones specific to ParallelTests, and ones for Cucumber.
@@ -36,7 +33,7 @@ module Quke #:nodoc:
36
33
  # parallel.
37
34
  def initialize(passed_in_args = [])
38
35
  Quke.config = Configuration.new
39
- @args = parallel_args + test_options_args(passed_in_args)
36
+ @args = Quke.config.parallel.command_args(passed_in_args)
40
37
  end
41
38
 
42
39
  # Executes ParallelTests, which in turn executes Cucumber passing in the
@@ -48,38 +45,6 @@ module Quke #:nodoc:
48
45
  raise StandardError, "Cucumber exited in a failed state" unless e.success?
49
46
  end
50
47
 
51
- private
52
-
53
- def parallel_args
54
- args = [
55
- Quke.config.features_folder,
56
- "--type", "cucumber",
57
- "--serialize-stdout",
58
- "--combine-stderr"
59
- ]
60
- args += ["--single", "--quiet"] unless Quke.config.parallel
61
- args
62
- end
63
-
64
- def test_options_args(passed_in_args)
65
- # Because cucumber is called in the context of the executing project and
66
- # not Quke it will take its arguments in the context of that location, and
67
- # not from where the Quke currently sits. This means to Cucumber
68
- # 'lib/features' doesn't exist, which means our env.rb never gets loaded.
69
- # Instead we first have to determine where this file is running from when
70
- # called, then we simply replace the last part of that result (which we
71
- # know will be lib/quke) with lib/features. For example __dir__ returns
72
- # '/Users/acruikshanks/projects/defra/quke/lib/quke' but we need Cucumber
73
- # to load '/Users/acruikshanks/projects/defra/quke/lib/features'
74
- # We then pass this full path to Cucumber so it can correctly find the
75
- # folder holding our predefined env.rb file.
76
- env_folder = __dir__.sub!("lib/quke", "lib/features")
77
- [
78
- "--test-options",
79
- "--format pretty -r #{env_folder} -r #{Quke.config.features_folder} #{passed_in_args.join(' ')}"
80
- ]
81
- end
82
-
83
48
  end
84
49
 
85
50
  end
@@ -112,7 +112,7 @@ module Quke #:nodoc:
112
112
  "--ignore-ssl-errors=yes"
113
113
  ]
114
114
 
115
- options.push("--proxy=#{config.proxy['host']}:#{config.proxy['port']}") if config.use_proxy?
115
+ options.push("--proxy=#{config.proxy.host}:#{config.proxy.port}") if config.proxy.use_proxy?
116
116
 
117
117
  options
118
118
  end
@@ -147,15 +147,13 @@ module Quke #:nodoc:
147
147
  # )
148
148
  #
149
149
  def chrome
150
- host = config.proxy["host"]
151
- port = config.proxy["port"]
152
- no_proxy = config.proxy["no_proxy"].tr(",", ";")
150
+ no_proxy = config.proxy.no_proxy.tr(",", ";")
153
151
 
154
152
  options = Selenium::WebDriver::Chrome::Options.new
155
153
  options.headless! if config.headless
156
154
 
157
- options.add_argument("--proxy-server=#{host}:#{port}") if config.use_proxy?
158
- options.add_argument("--proxy-bypass-list=#{no_proxy}") unless config.proxy["no_proxy"].empty?
155
+ options.add_argument("--proxy-server=#{config.proxy.host}:#{config.proxy.port}") if config.proxy.use_proxy?
156
+ options.add_argument("--proxy-bypass-list=#{no_proxy}") unless config.proxy.no_proxy.empty?
159
157
 
160
158
  options.add_argument("--user-agent=#{config.user_agent}") unless config.user_agent.empty?
161
159
 
@@ -249,12 +247,7 @@ module Quke #:nodoc:
249
247
  profile = Selenium::WebDriver::Firefox::Profile.new
250
248
  profile["general.useragent.override"] = config.user_agent unless config.user_agent.empty?
251
249
 
252
- settings = {}
253
- settings[:http] = "#{config.proxy['host']}:#{config.proxy['port']}" if config.use_proxy?
254
- settings[:ssl] = settings[:http] if config.use_proxy?
255
- settings[:no_proxy] = config.proxy["no_proxy"] unless config.proxy["no_proxy"].empty?
256
-
257
- profile.proxy = Selenium::WebDriver::Proxy.new(settings) if config.use_proxy?
250
+ profile.proxy = Selenium::WebDriver::Proxy.new(config.proxy.firefox_settings) if config.proxy.use_proxy?
258
251
 
259
252
  profile
260
253
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "quke/configuration"
4
+
5
+ module Quke #:nodoc:
6
+
7
+ # Manages all parallel configuration for Quke.
8
+ class ParallelConfiguration
9
+
10
+ # Whether use of parallel tests has been enabled
11
+ attr_reader :enabled
12
+ # How to group the tests. Default is features
13
+ attr_reader :group_by
14
+ # How many processes to start. Default is 0 which means we will leave
15
+ # ParallelTests to determine the number.
16
+ attr_reader :processes
17
+
18
+ def initialize(config)
19
+ @config = config
20
+ data = @config.data["parallel"] || {}
21
+ @enabled = (data["enable"].to_s.downcase.strip == "true")
22
+ @group_by = (data["group_by"] || "default").downcase.strip
23
+ @processes = (data["processes"] || "0").to_s.downcase.strip.to_i
24
+ end
25
+
26
+ # Returns an array of arguments, correctly ordered for passing to
27
+ # +ParallelTests::CLI.new.run()+.
28
+ #
29
+ # The arguments are based on the values set for the parallel configuration
30
+ # plus those passed in. It then orders them in an order that makes sense to
31
+ # parallel tests.
32
+ def command_args(additional_args = [])
33
+ args = standard_args(@config.features_folder)
34
+ args += ["--single", "--quiet"] unless @enabled
35
+ args += ["--group-by", @group_by] unless @group_by == "default"
36
+ args += ["-n", @processes.to_s] if @enabled && @processes.positive?
37
+ args + ["--test-options", @config.cucumber_arg(additional_args)]
38
+ end
39
+
40
+ private
41
+
42
+ def standard_args(features_folder)
43
+ [
44
+ features_folder,
45
+ "--type", "cucumber",
46
+ "--serialize-stdout",
47
+ "--combine-stderr"
48
+ ]
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Quke #:nodoc:
4
+
5
+ # Manages all parallel configuration for Quke.
6
+ class ProxyConfiguration
7
+
8
+ # The host address for the proxy server
9
+ attr_reader :host
10
+
11
+ # The port number for the proxy server
12
+ attr_reader :port
13
+
14
+ # In some cases you may also need to tell the driver not to use the proxy for local
15
+ # or specific connections. This returns a comma separated list of addresses of
16
+ # those addresses if set.
17
+ attr_reader :no_proxy
18
+
19
+ def initialize(data = {})
20
+ @host = (data["host"] || "").downcase.strip
21
+ @port = (data["port"] || "0").to_s.downcase.strip.to_i
22
+ @no_proxy = (data["no_proxy"] || "").downcase.strip
23
+ end
24
+
25
+ # Return true if the +host+ value has been set in the +.config.yml+
26
+ # file, else false.
27
+ #
28
+ # It is mainly used when determining whether to apply proxy server settings
29
+ # to the different drivers when registering them with Capybara.
30
+ def use_proxy?
31
+ @host != ""
32
+ end
33
+
34
+ # Returns a hash of settings specific to initialising a
35
+ # +Selenium::WebDriver::Proxy+ instance, which will be created as part of
36
+ # registering the Selenium firefox driver
37
+ def firefox_settings
38
+ settings = {}
39
+ return settings unless use_proxy?
40
+
41
+ settings[:http] = "#{host}:#{port}"
42
+ settings[:ssl] = settings[:http]
43
+ settings[:no_proxy] = no_proxy unless no_proxy.empty?
44
+
45
+ settings
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quke #:nodoc:
4
- VERSION = "0.9.1"
4
+ VERSION = "0.10.0"
5
5
  end
@@ -74,71 +74,101 @@ RSpec.describe Quke::Configuration do
74
74
  end
75
75
  end
76
76
 
77
- describe "#parallel" do
77
+ describe "#pause" do
78
78
  context "when NOT specified in the config file" do
79
- it "defaults to false" do
79
+ it "defaults to 0" do
80
80
  Quke::Configuration.file_location = data_path(".no_file.yml")
81
- expect(subject.parallel).to eq(false)
81
+ expect(subject.pause).to eq(0)
82
82
  end
83
83
  end
84
84
 
85
- context "when specified in the config file" do
85
+ context "when specified in config file" do
86
86
  it "matches the config file" do
87
- Quke::Configuration.file_location = data_path(".parallel.yml")
88
- expect(subject.parallel).to eq(true)
87
+ Quke::Configuration.file_location = data_path(".simple.yml")
88
+ expect(subject.pause).to eq(1)
89
89
  end
90
90
  end
91
91
 
92
92
  context "when in the config file as a string" do
93
93
  it "matches the config file" do
94
94
  Quke::Configuration.file_location = data_path(".as_string.yml")
95
- expect(subject.parallel).to eq(true)
95
+ expect(subject.pause).to eq(1)
96
96
  end
97
97
  end
98
98
  end
99
99
 
100
- describe "#pause" do
100
+ describe "#stop_on_error" do
101
101
  context "when NOT specified in the config file" do
102
- it "defaults to 0" do
102
+ it "defaults to false" do
103
103
  Quke::Configuration.file_location = data_path(".no_file.yml")
104
- expect(subject.pause).to eq(0)
104
+ expect(subject.stop_on_error).to eq(false)
105
105
  end
106
106
  end
107
107
 
108
108
  context "when specified in config file" do
109
109
  it "matches the config file" do
110
110
  Quke::Configuration.file_location = data_path(".simple.yml")
111
- expect(subject.pause).to eq(1)
111
+ expect(subject.stop_on_error).to eq(true)
112
112
  end
113
113
  end
114
114
 
115
115
  context "when in the config file as a string" do
116
116
  it "matches the config file" do
117
117
  Quke::Configuration.file_location = data_path(".as_string.yml")
118
- expect(subject.pause).to eq(1)
118
+ expect(subject.stop_on_error).to eq(true)
119
119
  end
120
120
  end
121
121
  end
122
122
 
123
- describe "#stop_on_error" do
123
+ describe "#display_failures" do
124
124
  context "when NOT specified in the config file" do
125
- it "defaults to false" do
125
+ it "defaults to true" do
126
126
  Quke::Configuration.file_location = data_path(".no_file.yml")
127
- expect(subject.stop_on_error).to eq(false)
127
+ expect(subject.display_failures).to eq(true)
128
128
  end
129
129
  end
130
130
 
131
- context "when specified in config file" do
131
+ context "when specified in the config file" do
132
132
  it "matches the config file" do
133
- Quke::Configuration.file_location = data_path(".simple.yml")
134
- expect(subject.stop_on_error).to eq(true)
133
+ Quke::Configuration.file_location = data_path(".display_failures.yml")
134
+ expect(subject.display_failures).to eq(false)
135
135
  end
136
136
  end
137
137
 
138
138
  context "when in the config file as a string" do
139
139
  it "matches the config file" do
140
140
  Quke::Configuration.file_location = data_path(".as_string.yml")
141
- expect(subject.stop_on_error).to eq(true)
141
+ expect(subject.display_failures).to eq(false)
142
+ end
143
+ end
144
+ end
145
+
146
+ describe "#display_failures?" do
147
+ context "when `headless` is false and `display_failures` is false" do
148
+ it "returns false" do
149
+ Quke::Configuration.file_location = data_path(".display_failures.yml")
150
+ expect(subject.display_failures?).to eq(false)
151
+ end
152
+ end
153
+
154
+ context "when `headless` is true and `display_failures` is false" do
155
+ it "returns false" do
156
+ Quke::Configuration.file_location = data_path(".as_string.yml")
157
+ expect(subject.display_failures?).to eq(false)
158
+ end
159
+ end
160
+
161
+ context "when `headless` is false and `display_failures` is true" do
162
+ it "returns false" do
163
+ Quke::Configuration.file_location = data_path(".no_file.yml")
164
+ expect(subject.display_failures?).to eq(true)
165
+ end
166
+ end
167
+
168
+ context "when `headless` is true and `display_failures` is true" do
169
+ it "returns false" do
170
+ Quke::Configuration.file_location = data_path(".should_display_failures.yml")
171
+ expect(subject.display_failures?).to eq(false)
142
172
  end
143
173
  end
144
174
  end
@@ -205,49 +235,25 @@ RSpec.describe Quke::Configuration do
205
235
  end
206
236
  end
207
237
 
208
- describe "#proxy" do
238
+ describe "#print_progress" do
209
239
  context "when NOT specified in the config file" do
210
- it "defaults to blank values" do
240
+ it "defaults to false" do
211
241
  Quke::Configuration.file_location = data_path(".no_file.yml")
212
- expect(subject.proxy).to eq("host" => "", "port" => 0, "no_proxy" => "")
242
+ expect(subject.print_progress).to eq(false)
213
243
  end
214
244
  end
215
245
 
216
246
  context "when specified in the config file" do
217
247
  it "matches the config file" do
218
- Quke::Configuration.file_location = data_path(".proxy.yml")
219
- expect(subject.proxy).to eq(
220
- "host" => "10.10.2.70",
221
- "port" => 8080,
222
- "no_proxy" => "127.0.0.1,192.168.0.1"
223
- )
248
+ Quke::Configuration.file_location = data_path(".print_progress.yml")
249
+ expect(subject.print_progress).to eq(true)
224
250
  end
225
251
  end
226
252
 
227
- context "when port is specified in the config file as a string" do
253
+ context "when in the config file as a string" do
228
254
  it "matches the config file" do
229
255
  Quke::Configuration.file_location = data_path(".as_string.yml")
230
- expect(subject.proxy).to eq(
231
- "host" => "",
232
- "port" => 8080,
233
- "no_proxy" => ""
234
- )
235
- end
236
- end
237
- end
238
-
239
- describe "#use_proxy?" do
240
- context "when proxy host details are NOT specified in the config file" do
241
- it "returns false" do
242
- Quke::Configuration.file_location = data_path(".no_file.yml")
243
- expect(subject.use_proxy?).to eq(false)
244
- end
245
- end
246
-
247
- context "when proxy host details are specified in the config file" do
248
- it "returns true" do
249
- Quke::Configuration.file_location = data_path(".proxy_basic.yml")
250
- expect(subject.use_proxy?).to eq(true)
256
+ expect(subject.print_progress).to eq(true)
251
257
  end
252
258
  end
253
259
  end
@@ -306,6 +312,39 @@ RSpec.describe Quke::Configuration do
306
312
  end
307
313
  end
308
314
 
315
+ describe "#cucumber_arg" do
316
+ let(:default_arg) { "--format pretty -r #{File.join(Dir.pwd, 'lib', 'features')} -r features" }
317
+ let(:additional_args) { ["--tags", "@wip"] }
318
+
319
+ context "when there are no additional arguments" do
320
+ it "returns the default cucumber arg value" do
321
+ Quke::Configuration.file_location = data_path(".no-file.yml")
322
+ expect(subject.cucumber_arg([])).to eq(default_arg)
323
+ end
324
+ end
325
+
326
+ context "when `stop_on_error` is true" do
327
+ it "returns the default cucumber arg value including the '--fail-fast' option" do
328
+ Quke::Configuration.file_location = data_path(".stop_on_error.yml")
329
+ expect(subject.cucumber_arg([])).to eq("--fail-fast #{default_arg}")
330
+ end
331
+ end
332
+
333
+ context "when `print_progress` is true" do
334
+ it "returns the default cucumber arg value including the '--format progress' option" do
335
+ Quke::Configuration.file_location = data_path(".print_progress.yml")
336
+ expect(subject.cucumber_arg([])).to include("--format progress")
337
+ end
338
+ end
339
+
340
+ context "when there are additional arguments" do
341
+ it "returns the default cucumber arg value plus the arguments" do
342
+ Quke::Configuration.file_location = data_path(".no-file.yml")
343
+ expect(subject.cucumber_arg(additional_args)).to eq("#{default_arg} #{additional_args.join(' ')}")
344
+ end
345
+ end
346
+ end
347
+
309
348
  describe ".file_name" do
310
349
  context "environment variable not set" do
311
350
  it "returns the default value '.config.yml'" do
@@ -36,7 +36,7 @@ RSpec.describe Quke::DriverConfiguration do
36
36
  "--load-images=no",
37
37
  "--disk-cache=false",
38
38
  "--ignore-ssl-errors=yes",
39
- "--proxy=#{config.proxy['host']}:#{config.proxy['port']}"
39
+ "--proxy=#{config.proxy.host}:#{config.proxy.port}"
40
40
  ],
41
41
  inspector: true
42
42
  )
@@ -88,7 +88,7 @@ RSpec.describe Quke::DriverConfiguration do
88
88
  "--load-images=no",
89
89
  "--disk-cache=false",
90
90
  "--ignore-ssl-errors=yes",
91
- "--proxy=#{config.proxy['host']}:#{config.proxy['port']}"
91
+ "--proxy=#{config.proxy.host}:#{config.proxy.port}"
92
92
  ]
93
93
  )
94
94
  end
@@ -126,7 +126,7 @@ RSpec.describe Quke::DriverConfiguration do
126
126
  config = Quke::Configuration.new
127
127
  expect(Quke::DriverConfiguration.new(config).chrome.args).to eq(
128
128
  Set[
129
- "--proxy-server=#{config.proxy['host']}:#{config.proxy['port']}"
129
+ "--proxy-server=#{config.proxy.host}:#{config.proxy.port}"
130
130
  ]
131
131
  )
132
132
  end
@@ -138,7 +138,7 @@ RSpec.describe Quke::DriverConfiguration do
138
138
  config = Quke::Configuration.new
139
139
  expect(Quke::DriverConfiguration.new(config).chrome.args).to eq(
140
140
  Set[
141
- "--proxy-server=#{config.proxy['host']}:#{config.proxy['port']}",
141
+ "--proxy-server=#{config.proxy.host}:#{config.proxy.port}",
142
142
  "--proxy-bypass-list=127.0.0.1;192.168.0.1"
143
143
  ]
144
144
  )
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Quke::ParallelConfiguration do
6
+ describe "instantiating" do
7
+ context "when `.config.yml` is blank or contains no parallel section" do
8
+ subject do
9
+ Quke::Configuration.file_location = data_path(".no_file.yml")
10
+ Quke::Configuration.new.parallel
11
+ end
12
+
13
+ it "returns an instance defaulted to blank values" do
14
+ expect(subject.enabled).to eq(false)
15
+ expect(subject.group_by).to eq("default")
16
+ expect(subject.processes).to eq(0)
17
+ end
18
+
19
+ end
20
+
21
+ context "when `.config.yml` contains a parallel section" do
22
+ subject do
23
+ Quke::Configuration.file_location = data_path(".simple.yml")
24
+ Quke::Configuration.new.parallel
25
+ end
26
+
27
+ it "returns an instance with properties that match the input" do
28
+ expect(subject.enabled).to eq(true)
29
+ expect(subject.group_by).to eq("scenarios")
30
+ expect(subject.processes).to eq(4)
31
+ end
32
+
33
+ end
34
+
35
+ context "when `.config.yml` contains a parallel section where processes is entered as a string" do
36
+ subject do
37
+ Quke::Configuration.file_location = data_path(".as_string.yml")
38
+ Quke::Configuration.new.parallel
39
+ end
40
+
41
+ it "returns an instance processes set as a number" do
42
+ expect(subject.processes).to eq(4)
43
+ end
44
+
45
+ end
46
+ end
47
+
48
+ describe "#command_args" do
49
+ context "when the instance has been instantiated with no data" do
50
+ subject do
51
+ Quke::Configuration.file_location = data_path(".no-file.yml")
52
+ Quke::Configuration.new.parallel
53
+ end
54
+
55
+ it "returns an array of default args for ParallelTests" do
56
+ expect(subject.command_args).to match_array(
57
+ [
58
+ "features",
59
+ "--type",
60
+ "cucumber",
61
+ "--serialize-stdout",
62
+ "--combine-stderr",
63
+ "--single",
64
+ "--quiet",
65
+ "--test-options",
66
+ "--format pretty -r #{File.join(Dir.pwd, 'lib', 'features')} -r features"
67
+ ]
68
+ )
69
+ end
70
+
71
+ end
72
+
73
+ context "when the instance has been instantiated with parallel enabled" do
74
+ subject do
75
+ Quke::Configuration.file_location = data_path(".parallel.yml")
76
+ Quke::Configuration.new.parallel
77
+ end
78
+
79
+ it "returns an array without the args '--single' and '--quiet'" do
80
+ args = subject.command_args
81
+ expect(args).not_to include(["--single", "--quiet"])
82
+ end
83
+
84
+ end
85
+
86
+ context "when the instance has been instantiated with group_by set" do
87
+ subject do
88
+ Quke::Configuration.file_location = data_path(".parallel.yml")
89
+ Quke::Configuration.new.parallel
90
+ end
91
+
92
+ it "returns an array with the args '--group-by' and 'scenarios'" do
93
+ args = subject.command_args
94
+ expect(args).to include("--group-by", "scenarios")
95
+ end
96
+
97
+ end
98
+
99
+ context "when the instance has been instantiated with processes set" do
100
+ subject do
101
+ Quke::Configuration.file_location = data_path(".parallel.yml")
102
+ Quke::Configuration.new.parallel
103
+ end
104
+
105
+ it "returns an array with the args '-n' and '4'" do
106
+ args = subject.command_args
107
+ expect(args).to include("-n", "4")
108
+ end
109
+
110
+ end
111
+
112
+ context "when the instance has been instantiated with processes set but parallel disabled" do
113
+ subject do
114
+ Quke::Configuration.file_location = data_path(".parallel_disabled.yml")
115
+ Quke::Configuration.new.parallel
116
+ end
117
+
118
+ it "returns an array without the args '-n' and '4'" do
119
+ args = subject.command_args
120
+ expect(args).not_to include("-n", "4")
121
+ end
122
+
123
+ end
124
+
125
+ context "when additional arguments are passed in" do
126
+ let(:additional_args) { ["--tags", "@wip"] }
127
+ subject do
128
+ Quke::Configuration.file_location = data_path(".no-file.yml")
129
+ Quke::Configuration.new.parallel
130
+ end
131
+
132
+ it "the last argument contains those values" do
133
+ args = subject.command_args(additional_args)
134
+ expect(args.last).to include(additional_args.join(" "))
135
+ end
136
+
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Quke::ProxyConfiguration do
6
+ describe "instantiating" do
7
+ context "when `.config.yml` is blank or contains no parallel section" do
8
+ subject do
9
+ Quke::Configuration.file_location = data_path(".no_file.yml")
10
+ Quke::Configuration.new.proxy
11
+ end
12
+
13
+ it "returns an instance defaulted to blank values" do
14
+ expect(subject.host).to eq("")
15
+ expect(subject.port).to eq(0)
16
+ expect(subject.no_proxy).to eq("")
17
+ end
18
+
19
+ end
20
+
21
+ context "when `.config.yml` contains a proxy section" do
22
+ subject do
23
+ Quke::Configuration.file_location = data_path(".proxy.yml")
24
+ Quke::Configuration.new.proxy
25
+ end
26
+
27
+ it "returns an instance with properties that match the input" do
28
+ expect(subject.host).to eq("10.10.2.70")
29
+ expect(subject.port).to eq(8080)
30
+ expect(subject.no_proxy).to eq("127.0.0.1,192.168.0.1")
31
+ end
32
+
33
+ end
34
+
35
+ context "when `.config.yml` contains a proxy section where port is entered as a string" do
36
+ subject do
37
+ Quke::Configuration.file_location = data_path(".as_string.yml")
38
+ Quke::Configuration.new.proxy
39
+ end
40
+
41
+ it "returns an instance with port set as a number" do
42
+ expect(subject.port).to eq(8080)
43
+ end
44
+
45
+ end
46
+ end
47
+
48
+ describe "#use_proxy?" do
49
+ context "when the instance has been instantiated with no data" do
50
+ subject { Quke::ProxyConfiguration.new }
51
+
52
+ it "returns false" do
53
+ expect(subject.use_proxy?).to eq(false)
54
+ end
55
+ end
56
+
57
+ context "when the instance has been instantiated with 'host' set" do
58
+ subject { Quke::ProxyConfiguration.new("host" => "10.10.2.70") }
59
+
60
+ it "returns true" do
61
+ expect(subject.use_proxy?).to eq(true)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "#firefox_settings" do
67
+ context "when the instance has been instantiated with no data" do
68
+ subject { Quke::ProxyConfiguration.new }
69
+
70
+ it "returns an empty hash" do
71
+ expect(subject.firefox_settings).to eq({})
72
+ end
73
+ end
74
+
75
+ context "when the instance has been instantiated with everything but 'host'" do
76
+ subject { Quke::ProxyConfiguration.new("port" => "8080", "no_proxy" => "127.0.0.1") }
77
+
78
+ it "returns an empty hash" do
79
+ expect(subject.firefox_settings).to eq({})
80
+ end
81
+ end
82
+
83
+ context "when the instance has been instantiated with data" do
84
+ subject do
85
+ Quke::ProxyConfiguration.new(
86
+ "host" => "10.10.2.70",
87
+ "port" => "8080",
88
+ "no_proxy" => "127.0.0.1"
89
+ )
90
+ end
91
+
92
+ it "returns a correctly populated hash" do
93
+ expect(subject.firefox_settings).to eq(
94
+ http: "10.10.2.70:8080",
95
+ ssl: "10.10.2.70:8080",
96
+ no_proxy: "127.0.0.1"
97
+ )
98
+ end
99
+ end
100
+ end
101
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quke
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Defra
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-28 00:00:00.000000000 Z
11
+ date: 2019-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber
@@ -305,13 +305,16 @@ files:
305
305
  - lib/quke/cuke_runner.rb
306
306
  - lib/quke/driver_configuration.rb
307
307
  - lib/quke/driver_registration.rb
308
+ - lib/quke/parallel_configuration.rb
309
+ - lib/quke/proxy_configuration.rb
308
310
  - lib/quke/version.rb
309
311
  - spec/quke/browserstack_configuration_spec.rb
310
312
  - spec/quke/browserstack_status_reporter_spec.rb
311
313
  - spec/quke/configuration_spec.rb
312
- - spec/quke/cuke_runner_spec.rb
313
314
  - spec/quke/driver_configuration_spec.rb
314
315
  - spec/quke/driver_registration_spec.rb
316
+ - spec/quke/parallel_configuration_spec.rb
317
+ - spec/quke/proxy_configuration_spec.rb
315
318
  - spec/quke/quke_spec.rb
316
319
  - spec/spec_helper.rb
317
320
  - spec/support/helpers.rb
@@ -344,11 +347,12 @@ specification_version: 4
344
347
  summary: A gem to simplify creating acceptance tests using Cucumber
345
348
  test_files:
346
349
  - spec/quke/browserstack_configuration_spec.rb
350
+ - spec/quke/proxy_configuration_spec.rb
347
351
  - spec/quke/quke_spec.rb
352
+ - spec/quke/parallel_configuration_spec.rb
348
353
  - spec/quke/browserstack_status_reporter_spec.rb
349
354
  - spec/quke/driver_registration_spec.rb
350
355
  - spec/quke/driver_configuration_spec.rb
351
- - spec/quke/cuke_runner_spec.rb
352
356
  - spec/quke/configuration_spec.rb
353
357
  - spec/spec_helper.rb
354
358
  - spec/support/simplecov.rb
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Quke::CukeRunner do
6
- let(:default_args) do
7
- features_folder = __dir__.sub!("spec/quke", "lib/features")
8
- ["features", "--type", "cucumber", "--serialize-stdout", "--combine-stderr", "--single", "--quiet", "--test-options", "--format pretty -r #{features_folder} -r features "]
9
- end
10
- describe "#initialize" do
11
- context "no additional Cucumber arguments passed" do
12
- let(:subject) { Quke::CukeRunner.new }
13
- it "returns just the default args used by Quke" do
14
- expect(subject.args).to eq(default_args)
15
- end
16
- end
17
- context "additional Cucumber arguments passed" do
18
- let(:args) { ["--tags", "test"] }
19
- let!(:subject) { Quke::CukeRunner.new(args) }
20
- it "returns the default args plus those passed in" do
21
- expected_args = default_args
22
- expected_args[-1] = expected_args.last + args.join(" ")
23
- expect(subject.args).to eq(expected_args)
24
- end
25
- end
26
- end
27
- end