cucumber 4.1.0 → 5.1.3

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
  SHA256:
3
- metadata.gz: a1f051aade812ee4bb28ab3670734b189ade8bc0cd0150a686e21874594ae62f
4
- data.tar.gz: 80c272791953dc442492c0571acffc628cb7b1f37a28a00adeef413bc7f76e1b
3
+ metadata.gz: 3e1477c70b949106c7f0a7f30f5b387cfa8a86ed41180d791d3bed792dde0c38
4
+ data.tar.gz: d0aa04c7c51cd100d2419684f4b7e8c4d245a68567588fe6cf5e1e4c2a301ac6
5
5
  SHA512:
6
- metadata.gz: 5026e105060af702f3b0adf50f3925ce04fdee7de79c2482093831cab838e2a605d69c056733d7820b6592c7229ee93e1ce64b80ae373ac7acd29f11d113d3a8
7
- data.tar.gz: c66fe1effa60270eb430bc2c381252e5c3da5dec524e49c58a7e508febaeb0b1398791f75eba5542395672b2431dafcfb820da2870410a52474ebc157bfbe333
6
+ metadata.gz: 4d32e30dca15261c3f1aca9e0393c7a75ef2d044cae7bd209861a0d32580dc3ba59fc334269a6fe66fd29c792041552806c2fb3670670586c3cf27bf969795aa
7
+ data.tar.gz: a17f70e4b4731c13b700be8e2ff3a9c8e97e8075531938a351d9a9df711fbbd1a1911f88903953e9c387079767b3efb9cfe647a0e3c658aca7be3ac9a70b444d
@@ -10,6 +10,88 @@ Please visit [cucumber/CONTRIBUTING.md](https://github.com/cucumber/cucumber/blo
10
10
 
11
11
  ----
12
12
 
13
+ ## [In GIT](https://github.com/cucumber/cucumber-ruby/compare/v5.1.3...master)
14
+
15
+ ### Added
16
+
17
+ ### Changed
18
+
19
+ ### Removed
20
+
21
+ ### Deprecated
22
+
23
+ ### Fixed
24
+
25
+ ### Security fixes
26
+
27
+ ## [In GIT](https://github.com/cucumber/cucumber-ruby/compare/v5.1.2...v5.1.3)
28
+
29
+ ### Fixed
30
+
31
+ * The `CUCUMBER_PUBLISH_TOKEN` now sets the correct HTTP header, following a fix in the curl option parser.
32
+
33
+ ## [5.1.2](https://github.com/cucumber/cucumber-ruby/compare/v5.1.1...v5.1.2)
34
+
35
+ ### Fixed
36
+
37
+ * Do not send headers after following redirection [#1475](https://github.com/cucumber/cucumber-ruby/pull/1475)
38
+
39
+ ## [5.1.1](https://github.com/cucumber/cucumber-ruby/compare/v5.1.0...v5.1.1)
40
+
41
+ ### Security fixes
42
+
43
+ * Update `cucumber-create-meta` to 2.0.2
44
+
45
+ ## [5.1.0](https://github.com/cucumber/cucumber-ruby/compare/v5.0.0...5.1.0)
46
+
47
+ ### Added
48
+
49
+ * `-X GET` in an `--out` URL will now issue a `GET` request *without* a body. If the response is `202 Accepted` *and*
50
+ the `Location` header is present, a new `PUT` request will be sent *with* the body.
51
+
52
+ The main reason for this added behaviour is to allow request bodies larger than 6Mb to be sent while using `--publish`.
53
+ This also improves performance since the request body is only sent once (previously it would be sent twice).
54
+
55
+ ### Changed
56
+
57
+ * Set banner border color to green when publishing reports
58
+ * Postpone removal of `--format=json`, `embed` and `puts` to version 6.0.0 in deprecation messages
59
+
60
+ ### Fixed
61
+
62
+ * Display banner on stderr when publishing reports [#1462](https://github.com/cucumber/cucumber-ruby/issues/1462)
63
+
64
+ ## [5.0.0](https://github.com/cucumber/cucumber-ruby/compare/v4.1.0...5.0.0)
65
+
66
+ ### Added
67
+
68
+ * `--publish` automatically publishes reports to [reports.cucumber.io](https://reports.cucumber.io)
69
+ * `--publish-quiet` does not print information banner about [reports.cucumber.io](https://reports.cucumber.io)
70
+
71
+ ### Changed
72
+
73
+ * `-q, --quiet` will also imply `--publish-quiet` in addition to `--no-snippets --no-source --no-duration`
74
+
75
+ ### Removed
76
+
77
+ * Dropped support for Ruby [2.3](https://www.ruby-lang.org/en/news/2019/03/31/support-of-ruby-2-3-has-ended/)
78
+ and [2.4](https://www.ruby-lang.org/en/news/2020/04/05/support-of-ruby-2-4-has-ended/)
79
+
80
+ ### Fixed
81
+
82
+ * Update code to be compatible with `diff-lcs` versions 1.3 and 1.4
83
+ * Defer registration of `at_exit` hook that flushes and closes formatter streams
84
+ ([#1458](https://github.com/cucumber/cucumber-ruby/pull/1458))
85
+ * Updated gems (see git diff for details)
86
+ * `cucumber-expressions`
87
+ * `cucumber-gherkin`
88
+ * `cucumber-create-meta`
89
+ * `cucumber-messages`
90
+ * Fix issue with timestamp nanos [#1438](https://github.com/cucumber/cucumber-ruby/issues/1438)
91
+ * `cucumber-html-formatter`
92
+ * Add filtering capabilities [#1444](https://github.com/cucumber/cucumber-ruby/issues/1444)
93
+ * Fix Interceptor that was raising exception when calling `puts` on the wrapped stream ([#1445](https://github.com/cucumber/cucumber-ruby/issues/1445))
94
+
13
95
  ## [4.1.0](https://github.com/cucumber/cucumber-ruby/compare/v4.0.1...v4.1.0)
14
96
 
15
97
  ### Changed
@@ -59,13 +59,15 @@ help us to correct style violations reported here:
59
59
 
60
60
  ## Release Process
61
61
 
62
- * Bump the version number in `lib/cucumber/version`.
63
- * Make sure `CHANGELOG.md` is updated with the upcoming version number, and has entries for all fixes.
64
-
65
- Now release it
66
-
67
- bundle update
68
- bundle exec rake
69
- git commit -m "Release X.Y.Z"
70
- # Make sure you run gem signin as the cukebot@cucumber.io user before running the following step. Credentials can be found in 1Password
71
- rake release
62
+ * Upgrade gems with `scripts/update-gemspec`
63
+ * Bump the version number in `lib/cucumber/version`
64
+ * Update `CHANGELOG.md` with the upcoming version number and create a new `In Git` section
65
+ * Remove empty sections from `CHANGELOG.md`
66
+ * Now release it:
67
+
68
+ ```
69
+ git commit -am "Release X.Y.Z"
70
+ make release
71
+ ```
72
+
73
+ * Finally, update the cucumber-ruby version in the [documentation project](https://cucumber.io/docs/installation/) in [versions.yaml](https://github.com/cucumber/docs.cucumber.io/blob/master/data/versions.yaml) file.
@@ -24,23 +24,21 @@ module Autotest::CucumberMixin
24
24
  add_sigint_handler
25
25
 
26
26
  loop do # ^c handler
27
- begin
28
- get_to_green
29
- if tainted
30
- rerun_all_tests
31
- rerun_all_features if all_good
32
- else
33
- hook :all_good
34
- end
35
- wait_for_changes
36
- # Once tests and features are green, reset features every
37
- # time a file is changed to see if anything breaks.
38
- reset_features
39
- rescue Interrupt
40
- break if wants_to_quit
41
- reset
42
- reset_features
27
+ get_to_green
28
+ if tainted
29
+ rerun_all_tests
30
+ rerun_all_features if all_good
31
+ else
32
+ hook :all_good
43
33
  end
34
+ wait_for_changes
35
+ # Once tests and features are green, reset features every
36
+ # time a file is changed to see if anything breaks.
37
+ reset_features
38
+ rescue Interrupt
39
+ break if wants_to_quit
40
+ reset
41
+ reset_features
44
42
  end
45
43
  hook :quit
46
44
  end
@@ -9,6 +9,7 @@ require 'cucumber/core/test/result'
9
9
  module Cucumber
10
10
  module Cli
11
11
  class Options
12
+ CUCUMBER_PUBLISH_URL = ENV['CUCUMBER_PUBLISH_URL'] || 'https://messages.cucumber.io/api/reports -X GET'
12
13
  INDENT = ' ' * 53
13
14
  BUILTIN_FORMATS = {
14
15
  'pretty' => ['Cucumber::Formatter::Pretty', 'Prints the feature as is - in colours.'],
@@ -93,6 +94,10 @@ module Cucumber
93
94
 
94
95
  @args.options do |opts| # rubocop:disable Metrics/BlockLength
95
96
  opts.banner = banner
97
+ opts.on('--publish', 'Publish a report to https://reports.cucumber.io') do
98
+ set_option :publish_enabled, true
99
+ end
100
+ opts.on('--publish-quiet', 'Don\'t print information banner about publishing reports') { set_option :publish_quiet }
96
101
  opts.on('-r LIBRARY|DIR', '--require LIBRARY|DIR', *require_files_msg) { |lib| require_files(lib) }
97
102
 
98
103
  opts.on('-j DIR', '--jars DIR', 'Load all the jars under DIR') { |jars| load_jars(jars) } if Cucumber::JRUBY
@@ -117,7 +122,7 @@ module Cucumber
117
122
  opts.on('-s', '--no-source', "Don't print the file and line of the step definition with the steps.") { set_option :source, false }
118
123
  opts.on('-i', '--no-snippets', "Don't print snippets for pending steps.") { set_option :snippets, false }
119
124
  opts.on('-I', '--snippet-type TYPE', *snippet_type_msg) { |v| set_option :snippet_type, v.to_sym }
120
- opts.on('-q', '--quiet', 'Alias for --no-snippets --no-source.') { shut_up }
125
+ opts.on('-q', '--quiet', 'Alias for --no-snippets --no-source --no-duration --publish-quiet.') { shut_up }
121
126
  opts.on('--no-duration', "Don't print the duration at the end of the summary") { set_option :duration, false }
122
127
  opts.on('-b', '--backtrace', 'Show full backtrace for all errors.') { Cucumber.use_full_backtrace = true }
123
128
  opts.on('-S', '--[no-]strict', *strict_msg) { |setting| set_strict(setting) }
@@ -145,6 +150,8 @@ Specify SEED to reproduce the shuffling from a previous run.
145
150
  opts.on_tail('-h', '--help', "You're looking at it.") { exit_ok(opts.help) }
146
151
  end.parse!
147
152
 
153
+ process_publish_options
154
+
148
155
  @args.map! { |a| "#{a}:#{@options[:lines]}" } if @options[:lines]
149
156
 
150
157
  extract_environment_variables
@@ -182,6 +189,18 @@ Specify SEED to reproduce the shuffling from a previous run.
182
189
 
183
190
  private
184
191
 
192
+ def process_publish_options
193
+ @options[:publish_enabled] = true if truthy_string?(ENV['CUCUMBER_PUBLISH_ENABLED']) || ENV['CUCUMBER_PUBLISH_TOKEN']
194
+ @options[:formats] << publisher if @options[:publish_enabled]
195
+
196
+ @options[:publish_quiet] = true if truthy_string?(ENV['CUCUMBER_PUBLISH_QUIET'])
197
+ end
198
+
199
+ def truthy_string?(str)
200
+ return false if str.nil?
201
+ str !~ /^(false|no|0)$/i
202
+ end
203
+
185
204
  def color_msg
186
205
  [
187
206
  'Whether or not to use ANSI color in the output. Cucumber decides',
@@ -348,7 +367,13 @@ Specify SEED to reproduce the shuffling from a previous run.
348
367
  end
349
368
 
350
369
  def require_jars(jars)
351
- Dir["#{jars}/**/*.jar"].each { |jar| require jar }
370
+ Dir["#{jars}/**/*.jar"].sort.each { |jar| require jar }
371
+ end
372
+
373
+ def publisher
374
+ url = CUCUMBER_PUBLISH_URL
375
+ url += %( -H "Authorization: Bearer #{ENV['CUCUMBER_PUBLISH_TOKEN']}") if ENV['CUCUMBER_PUBLISH_TOKEN']
376
+ ['message', {}, url]
352
377
  end
353
378
 
354
379
  def language(lang)
@@ -415,6 +440,7 @@ Specify SEED to reproduce the shuffling from a previous run.
415
440
  end
416
441
 
417
442
  def shut_up
443
+ @options[:publish_quiet] = true
418
444
  @options[:snippets] = false
419
445
  @options[:source] = false
420
446
  @options[:duration] = false
@@ -62,6 +62,14 @@ module Cucumber
62
62
  @options[:dry_run]
63
63
  end
64
64
 
65
+ def publish_enabled?
66
+ @options[:publish_enabled]
67
+ end
68
+
69
+ def publish_quiet?
70
+ @options[:publish_quiet]
71
+ end
72
+
65
73
  def fail_fast?
66
74
  @options[:fail_fast]
67
75
  end
@@ -197,14 +205,12 @@ module Cucumber
197
205
 
198
206
  def formatter_factories
199
207
  formats.map do |format, formatter_options, path_or_io|
200
- begin
201
- factory = formatter_class(format)
202
- yield factory,
203
- formatter_options,
204
- path_or_io
205
- rescue Exception => e # rubocop:disable Lint/RescueException
206
- raise e, "#{e.message}\nError creating formatter: #{format}", e.backtrace
207
- end
208
+ factory = formatter_class(format)
209
+ yield factory,
210
+ formatter_options,
211
+ path_or_io
212
+ rescue Exception => e # rubocop:disable Lint/RescueException
213
+ raise e, "#{e.message}\nError creating formatter: #{format}", e.backtrace
208
214
  end
209
215
  end
210
216
 
@@ -256,6 +262,7 @@ module Cucumber
256
262
  strict: Cucumber::Core::Test::Result::StrictConfiguration.new,
257
263
  require: [],
258
264
  dry_run: false,
265
+ publish_quiet: false,
259
266
  fail_fast: false,
260
267
  formats: [],
261
268
  excludes: [],
@@ -41,7 +41,7 @@ module Cucumber
41
41
 
42
42
  module ForDevelopers
43
43
  def self.call(_message, _method, remove_after_version)
44
- raise "This method is due for removal after version #{remove_after_version}" if Cucumber::VERSION > remove_after_version
44
+ raise "This method is due for removal after version #{remove_after_version}" if Cucumber::VERSION >= remove_after_version
45
45
  end
46
46
  end
47
47
 
@@ -11,7 +11,7 @@ module Cucumber
11
11
  begin
12
12
  raise new(with_prefix(step_name)) # rubocop:disable Style/RaiseArgs
13
13
  rescue StandardError => e
14
- return e
14
+ e
15
15
  end
16
16
  end
17
17
 
@@ -136,7 +136,6 @@ module Cucumber
136
136
 
137
137
  private
138
138
 
139
- # rubocop:disable Metrics/PerceivedComplexity
140
139
  def process_scenario_container(container, original_previous_node)
141
140
  container.children.each do |child|
142
141
  previous_node = original_previous_node
@@ -158,7 +157,6 @@ module Cucumber
158
157
  end
159
158
  end
160
159
  end
161
- # rubocop:enable Metrics/PerceivedComplexity
162
160
  end
163
161
  end
164
162
  end
@@ -1,79 +1,80 @@
1
1
  require 'net/http'
2
2
  require 'tempfile'
3
+ require 'shellwords'
3
4
 
4
5
  module Cucumber
5
6
  module Formatter
6
7
  class HTTPIO
7
8
  class << self
8
9
  # Returns an IO that will write to a HTTP request's body
9
- def open(url, https_verify_mode = nil)
10
+ # https_verify_mode can be set to OpenSSL::SSL::VERIFY_NONE
11
+ # to ignore unsigned certificate - setting to nil will verify the certificate
12
+ def open(url, https_verify_mode = nil, reporter = nil)
10
13
  @https_verify_mode = https_verify_mode
11
14
  uri, method, headers = CurlOptionParser.parse(url)
12
- IOHTTPBuffer.new(uri, method, headers, https_verify_mode)
15
+ IOHTTPBuffer.new(uri, method, headers, https_verify_mode, reporter)
13
16
  end
14
17
  end
15
18
  end
16
19
 
17
20
  class CurlOptionParser
18
21
  def self.parse(options)
19
- chunks = options.split(/\s/).compact
20
- http_method = 'PUT'
21
- url = chunks[0]
22
- headers = ''
23
-
24
- last_flag = nil
25
- chunks.each do |chunk|
26
- if ['-X', '--request'].include?(chunk)
27
- last_flag = '-X'
28
- next
29
- end
30
-
31
- if chunk == '-H'
32
- last_flag = '-H'
33
- next
34
- end
22
+ args = Shellwords.split(options)
35
23
 
36
- if last_flag == '-X'
37
- http_method = chunk
38
- last_flag = nil
24
+ url = nil
25
+ http_method = 'PUT'
26
+ headers = {}
27
+
28
+ until args.empty?
29
+ arg = args.shift
30
+ case arg
31
+ when '-X', '--request'
32
+ http_method = remove_arg_for(args, arg)
33
+ when '-H'
34
+ header_arg = remove_arg_for(args, arg)
35
+ headers = headers.merge(parse_header(header_arg))
36
+ else
37
+ raise StandardError, "#{options} was not a valid curl command. Can't set url to #{arg} it is already set to #{url}" if url
38
+ url = arg
39
39
  end
40
-
41
- headers += chunk if last_flag == '-H'
42
40
  end
41
+ raise StandardError, "#{options} was not a valid curl command" unless url
43
42
 
44
43
  [
45
44
  url,
46
45
  http_method,
47
- make_headers(headers)
46
+ headers
48
47
  ]
49
48
  end
50
49
 
51
- def self.make_headers(headers)
52
- hash_headers = {}
53
- str_scanner = /("(?<key>[^":]+)\s*:\s*(?<value>[^":]+)")|('(?<key1>[^':]+)\s*:\s*(?<value1>[^':]+)')/
54
-
55
- headers.scan(str_scanner) do |header|
56
- header = header.compact!
57
- hash_headers[header[0]] = header[1]&.strip
58
- end
50
+ def self.remove_arg_for(args, arg)
51
+ return args.shift unless args.empty?
52
+ raise StandardError, "Missing argument for #{arg}"
53
+ end
59
54
 
60
- hash_headers
55
+ def self.parse_header(header_arg)
56
+ parts = header_arg.split(':', 2)
57
+ raise StandardError, "#{header_arg} was not a valid header" unless parts.length == 2
58
+ { parts[0].strip => parts[1].strip }
61
59
  end
62
60
  end
63
61
 
64
62
  class IOHTTPBuffer
65
63
  attr_reader :uri, :method, :headers
66
64
 
67
- def initialize(uri, method, headers = {}, https_verify_mode = nil)
65
+ def initialize(uri, method, headers = {}, https_verify_mode = nil, reporter = nil)
68
66
  @uri = URI(uri)
69
67
  @method = method
70
68
  @headers = headers
71
69
  @write_io = Tempfile.new('cucumber', encoding: 'UTF-8')
72
70
  @https_verify_mode = https_verify_mode
71
+ @reporter = reporter || NoReporter.new
73
72
  end
74
73
 
75
74
  def close
76
- post_content(@uri, @method, @headers)
75
+ resource_uri = send_content(@uri, @method, @headers)
76
+
77
+ @reporter.report(resource_uri)
77
78
  @write_io.close
78
79
  end
79
80
 
@@ -91,8 +92,8 @@ module Cucumber
91
92
 
92
93
  private
93
94
 
94
- def post_content(uri, method, headers, attempt = 10)
95
- content = @write_io
95
+ def send_content(uri, method, headers, attempt = 10)
96
+ content = (method == 'GET' ? StringIO.new : @write_io)
96
97
  http = build_client(uri, @https_verify_mode)
97
98
 
98
99
  raise StandardError, "request to #{uri} failed (too many redirections)" if attempt <= 0
@@ -115,10 +116,14 @@ module Cucumber
115
116
  end
116
117
 
117
118
  case response
119
+ when Net::HTTPAccepted
120
+ return uri unless response['Location']
121
+
122
+ send_content(URI(response['Location']), 'PUT', {}, attempt - 1)
118
123
  when Net::HTTPSuccess
119
- response
124
+ uri
120
125
  when Net::HTTPRedirection
121
- post_content(URI(response['Location']), method, headers, attempt - 1)
126
+ send_content(URI(response['Location']), method, headers, attempt - 1)
122
127
  else
123
128
  raise StandardError, "request to #{uri} failed with status #{response.code}"
124
129
  end