cucumber 5.1.2 → 6.1.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.
data/CONTRIBUTING.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  We appreciate that. But before you do, please learn our basic rules:
4
4
 
5
- * This is not a support forum. If you have a question, please go to [The Cukes Google Group](http://groups.google.com/group/cukes).
6
- * Do you have an idea for a new feature? Then don't expect it to be implemented unless you or someone else sends a [pull request](https://help.github.com/articles/using-pull-requests). You might be better to start a discussion on [the google group](http://groups.google.com/group/cukes).
7
- * Reporting a bug? Please tell us:
8
- * which version of Cucumber you're using
9
- * which version of Ruby you're using.
10
- * How to reproduce it. Bugs with a failing test in a [pull request](https://help.github.com/articles/using-pull-requests) get fixed much quicker. Some bugs may never be fixed.
11
- * Want to paste some code or output? Put \`\`\` on a line above and below your code/output. See [GFM](https://help.github.com/articles/github-flavored-markdown)'s *Fenced Code Blocks* for details.
12
- * We love [pull requests](https://help.github.com/articles/using-pull-requests). But if you don't have a test to go with it we probably won't merge it.
5
+ - This is not a support forum. If you have a question, please go to [The Cukes Google Group](http://groups.google.com/group/cukes).
6
+ - Do you have an idea for a new feature? Then don't expect it to be implemented unless you or someone else sends a [pull request](https://help.github.com/articles/using-pull-requests). You might be better to start a discussion on [the google group](http://groups.google.com/group/cukes).
7
+ - Reporting a bug? Please tell us:
8
+ - which version of Cucumber you're using
9
+ - which version of Ruby you're using.
10
+ - How to reproduce it. Bugs with a failing test in a [pull request](https://help.github.com/articles/using-pull-requests) get fixed much quicker. Some bugs may never be fixed.
11
+ - Want to paste some code or output? Put \`\`\` on a line above and below your code/output. See [GFM](https://help.github.com/articles/github-flavored-markdown)'s _Fenced Code Blocks_ for details.
12
+ - We love [pull requests](https://help.github.com/articles/using-pull-requests). But if you don't have a test to go with it we probably won't merge it.
13
13
 
14
14
  # Contributing to Cucumber
15
15
 
@@ -21,26 +21,38 @@ You can chat with the core team on https://gitter.im/cucumber/contributors. We t
21
21
 
22
22
  ## Installing your own gems
23
23
 
24
- A `Gemfile.local`-file can be used to have your own gems installed to support
25
- your normal development workflow.
24
+ A `Gemfile.local`-file can be used to have your own gems installed to support your normal development workflow.
25
+ Execute `bundle config set --local gemfile Gemfile.local` to use it per default.
26
26
 
27
27
  Example:
28
28
 
29
- ~~~ruby
30
- gem 'pry'
31
- gem 'pry-byebug'
32
- gem 'byebug'
33
- ~~~
29
+ ```ruby
30
+ # Include the regular Gemfile
31
+ eval File.read('Gemfile')
32
+
33
+ group :development do
34
+ gem 'byebug'
35
+ gem 'debase', require: false
36
+ gem 'ruby-debug-ide', require: false
37
+ gem 'pry'
38
+ gem 'pry-byebug'
39
+ end
40
+ ```
41
+
42
+ ## Using Visual Studio Code?
43
+
44
+ Sample for launch.json configuration is available in
45
+ [docs/vscode-example-launch-configuration.md](https://github.com/cucumber/cucumber-ruby/blob/main/docs/vscode-example-launch-configuration.md)
34
46
 
35
47
  ## Note on Patches/Pull Requests
36
48
 
37
- * Fork the project. Make a branch for your change.
38
- * Make your feature addition or bug fix.
39
- * Make sure your patch is well covered by tests. We don't accept changes to Cucumber that aren't tested.
40
- * Please do not change the Rakefile, version, or history.
49
+ - Fork the project. Make a branch for your change.
50
+ - Make your feature addition or bug fix.
51
+ - Make sure your patch is well covered by tests. We don't accept changes to Cucumber that aren't tested.
52
+ - Please do not change the Rakefile, version, or history.
41
53
  (if you want to have your own version, that is fine but
42
54
  bump version in a commit by itself so we can ignore when we merge your change)
43
- * Send us a pull request.
55
+ - Send us a pull request.
44
56
 
45
57
  ## Running tests
46
58
 
@@ -50,24 +62,24 @@ gem 'byebug'
50
62
 
51
63
  To get code coverage results, run `bundle exec rake cov`
52
64
 
53
- ## First timer? No problem!
65
+ ## First timer? Welcome!
54
66
 
55
67
  If you are new to the project or to OSS, check the label
56
68
  [Easy](https://github.com/cucumber/cucumber-ruby/labels/Easy). Also, you can
57
69
  help us to correct style violations reported here:
58
- [.rubocop_todo.yml](https://github.com/cucumber/cucumber-ruby/blob/master/.rubocop_todo.yml).
70
+ [.rubocop_todo.yml](https://github.com/cucumber/cucumber-ruby/blob/main/.rubocop_todo.yml).
59
71
 
60
72
  ## Release Process
61
73
 
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:
74
+ - Upgrade gems with `scripts/update-gemspec`
75
+ - Bump the version number in `lib/cucumber/version`
76
+ - Update `CHANGELOG.md` with the upcoming version number and create a new `In Git` section
77
+ - Remove empty sections from `CHANGELOG.md`
78
+ - Now release it:
67
79
 
68
80
  ```
69
81
  git commit -am "Release X.Y.Z"
70
82
  make release
71
83
  ```
72
84
 
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.
85
+ - Finally, update the cucumber-ruby version in the [documentation project](https://cucumber.io/docs/installation/) in [versions.yaml](https://github.com/cucumber/docs/blob/master/data/versions.yaml) file.
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  [![OpenCollective](https://opencollective.com/cucumber/backers/badge.svg)](https://opencollective.com/cucumber)
2
2
  [![OpenCollective](https://opencollective.com/cucumber/sponsors/badge.svg)](https://opencollective.com/cucumber)
3
-
3
+ [![pull requests](https://oselvar.com/api/badge?label=pull%20requests&csvUrl=https%3A%2F%2Fraw.githubusercontent.com%2Fcucumber%2Foselvar-github-metrics%2Fmain%2Fdata%2Fcucumber%2Fcucumber-ruby%2FpullRequests.csv)](https://oselvar.com/github/cucumber/oselvar-github-metrics/main/cucumber/cucumber-ruby)
4
+ [![issues](https://oselvar.com/api/badge?label=issues&csvUrl=https%3A%2F%2Fraw.githubusercontent.com%2Fcucumber%2Foselvar-github-metrics%2Fmain%2Fdata%2Fcucumber%2Fcucumber-ruby%2Fissues.csv)](https://oselvar.com/github/cucumber/oselvar-github-metrics/main/cucumber/cucumber-ruby)
4
5
  [![CircleCI](https://circleci.com/gh/cucumber/cucumber-ruby.svg?style=svg)](https://circleci.com/gh/cucumber/cucumber-ruby)
5
-
6
6
  [![Code Climate](https://codeclimate.com/github/cucumber/cucumber-ruby.svg)](https://codeclimate.com/github/cucumber/cucumber-ruby)
7
- [![Coverage Status](https://coveralls.io/repos/cucumber/cucumber-ruby/badge.svg?branch=master)](https://coveralls.io/r/cucumber/cucumber-ruby?branch=master)
7
+ [![Coverage Status](https://coveralls.io/repos/cucumber/cucumber-ruby/badge.svg?branch=main)](https://coveralls.io/r/cucumber/cucumber-ruby?branch=main)
8
8
 
9
9
  # Cucumber
10
10
 
@@ -15,24 +15,27 @@ your team.
15
15
 
16
16
  Where to get more info:
17
17
 
18
- * The main website: https://cucumber.io/
19
- * Documentation: https://cucumber.io/docs
20
- * Ruby API Documentation: http://www.rubydoc.info/github/cucumber/cucumber-ruby/
21
- * Support forum: https://groups.google.com/group/cukes
22
- * Chat: ([Slack](https://cucumber.io/support#slack) and [Gitter](https://cucumber.io/support#gitter))
18
+ - The main website: https://cucumber.io/
19
+ - Documentation: https://cucumber.io/docs
20
+ - Ruby API Documentation: http://www.rubydoc.info/github/cucumber/cucumber-ruby/
21
+ - Support forum: https://groups.google.com/group/cukes
22
+ - Chat: ([Slack](https://cucumber.io/support#slack) and [Gitter](https://cucumber.io/support#gitter))
23
23
 
24
24
  See [CONTRIBUTING.md](CONTRIBUTING.md) for info on contributing to Cucumber.
25
25
 
26
26
  ## Supported platforms
27
- * Ruby 2.6
28
- * Ruby 2.5
29
- * Ruby 2.4
30
- * Ruby 2.3
31
- * JRuby 9.2 (with [some limitations](https://github.com/cucumber/cucumber-ruby/blob/master/docs/jruby-limitations.md))
27
+
28
+ - Ruby 3.0
29
+ - Ruby 2.7
30
+ - Ruby 2.6
31
+ - Ruby 2.5
32
+ - Ruby 2.4
33
+ - Ruby 2.3
34
+ - JRuby 9.2 (with [some limitations](https://github.com/cucumber/cucumber-ruby/blob/main/docs/jruby-limitations.md))
32
35
 
33
36
  ## Code of Conduct
34
37
 
35
- Everyone interacting in this codebase and issue tracker is expected to follow the Cucumber [code of conduct](https://github.com/cucumber/cucumber/blob/master/CODE_OF_CONDUCT.md).
38
+ Everyone interacting in this codebase and issue tracker is expected to follow the Cucumber [code of conduct](https://cucumber.io/conduct).
36
39
 
37
40
  ## Copyright
38
41
 
@@ -126,13 +126,35 @@ module Cucumber
126
126
  end
127
127
 
128
128
  def arrange_formats
129
- @options[:formats] << ['pretty', {}, @out_stream] if @options[:formats].empty?
129
+ add_default_formatter if needs_default_formatter?
130
+
130
131
  @options[:formats] = @options[:formats].sort_by do |f|
131
132
  f[2] == @out_stream ? -1 : 1
132
133
  end
133
134
  @options[:formats].uniq!
134
135
  @options.check_formatter_stream_conflicts
135
136
  end
137
+
138
+ def add_default_formatter
139
+ @options[:formats] << ['pretty', {}, @out_stream]
140
+ end
141
+
142
+ def needs_default_formatter?
143
+ formatter_missing? || publish_only?
144
+ end
145
+
146
+ def formatter_missing?
147
+ @options[:formats].empty?
148
+ end
149
+
150
+ def publish_only?
151
+ @options[:formats]
152
+ .uniq
153
+ .map { |formatter, _, stream| [formatter, stream] }
154
+ .uniq
155
+ .reject { |formatter, stream| formatter == 'message' && stream != @out_stream }
156
+ .empty?
157
+ end
136
158
  end
137
159
  end
138
160
  end
@@ -22,8 +22,13 @@ module Cucumber
22
22
  "#{INDENT}filename instead."],
23
23
  'stepdefs' => ['Cucumber::Formatter::Stepdefs', "Prints All step definitions with their locations. Same as\n" \
24
24
  "#{INDENT}the usage formatter, except that steps are not printed."],
25
- 'junit' => ['Cucumber::Formatter::Junit', 'Generates a report similar to Ant+JUnit.'],
26
- 'json' => ['Cucumber::Formatter::Json', '[DEPRECATED] Prints the feature as JSON'],
25
+ 'junit' => ['Cucumber::Formatter::Junit', "Generates a report similar to Ant+JUnit. Use\n" \
26
+ "#{INDENT}junit,fileattribute=true to include a file attribute."],
27
+ 'json' => ['Cucumber::Formatter::Json', "Prints the feature as JSON.\n" \
28
+ "#{INDENT}The JSON format is in maintenance mode.\n" \
29
+ "#{INDENT}Please consider using the message formatter\n"\
30
+ "#{INDENT}with the standalone json-formatter\n" \
31
+ "#{INDENT}(https://github.com/cucumber/cucumber/tree/master/json-formatter)."],
27
32
  'message' => ['Cucumber::Formatter::Message', 'Outputs protobuf messages'],
28
33
  'html' => ['Cucumber::Formatter::HTML', 'Outputs HTML report'],
29
34
  'summary' => ['Cucumber::Formatter::Summary', 'Summary output of feature and scenarios']
@@ -335,7 +340,7 @@ Specify SEED to reproduce the shuffling from a previous run.
335
340
  'option is specified; all loading becomes explicit.',
336
341
  'Files in directories named "support" are still always',
337
342
  'loaded first when their parent directories are',
338
- 'required or if the "support" directoires themselves are',
343
+ 'required or if the "support" directories themselves are',
339
344
  'explicitly required.',
340
345
  'This option can be specified multiple times.'
341
346
  ]
@@ -15,6 +15,7 @@ module Cucumber
15
15
  test/unit
16
16
  .gem/ruby
17
17
  bin/bundle
18
+ rdebug-ide
18
19
  ]
19
20
 
20
21
  @backtrace_filters << RbConfig::CONFIG['rubyarchdir'] if RbConfig::CONFIG['rubyarchdir']
@@ -8,7 +8,7 @@ module Cucumber
8
8
  include Io
9
9
 
10
10
  def initialize(config)
11
- @io = ensure_io(config.out_stream)
11
+ @io = ensure_io(config.out_stream, config.error_stream)
12
12
  @html_formatter = Cucumber::HTMLFormatter::Formatter.new(@io)
13
13
  @html_formatter.write_pre_message
14
14
 
@@ -1,5 +1,6 @@
1
1
  require 'net/http'
2
2
  require 'tempfile'
3
+ require 'shellwords'
3
4
 
4
5
  module Cucumber
5
6
  module Formatter
@@ -18,48 +19,43 @@ module Cucumber
18
19
 
19
20
  class CurlOptionParser
20
21
  def self.parse(options)
21
- chunks = options.split(/\s/).compact
22
- http_method = 'PUT'
23
- url = chunks[0]
24
- headers = ''
25
-
26
- last_flag = nil
27
- chunks.each do |chunk|
28
- if ['-X', '--request'].include?(chunk)
29
- last_flag = '-X'
30
- next
31
- end
32
-
33
- if chunk == '-H'
34
- last_flag = '-H'
35
- next
36
- end
22
+ args = Shellwords.split(options)
37
23
 
38
- if last_flag == '-X'
39
- http_method = chunk
40
- 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
41
39
  end
42
-
43
- headers += chunk if last_flag == '-H'
44
40
  end
41
+ raise StandardError, "#{options} was not a valid curl command" unless url
45
42
 
46
43
  [
47
44
  url,
48
45
  http_method,
49
- make_headers(headers)
46
+ headers
50
47
  ]
51
48
  end
52
49
 
53
- def self.make_headers(headers)
54
- hash_headers = {}
55
- str_scanner = /("(?<key>[^":]+)\s*:\s*(?<value>[^":]+)")|('(?<key1>[^':]+)\s*:\s*(?<value1>[^':]+)')/
56
-
57
- headers.scan(str_scanner) do |header|
58
- header = header.compact!
59
- hash_headers[header[0]] = header[1]&.strip
60
- 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
61
54
 
62
- 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 }
63
59
  end
64
60
  end
65
61
 
@@ -76,10 +72,11 @@ module Cucumber
76
72
  end
77
73
 
78
74
  def close
79
- resource_uri = send_content(@uri, @method, @headers)
80
-
81
- @reporter.report(resource_uri)
75
+ response = send_content(@uri, @method, @headers)
76
+ @reporter.report(response.body)
82
77
  @write_io.close
78
+ return if response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPRedirection)
79
+ raise StandardError, "request to #{uri} failed with status #{response.code}"
83
80
  end
84
81
 
85
82
  def write(data)
@@ -121,16 +118,11 @@ module Cucumber
121
118
 
122
119
  case response
123
120
  when Net::HTTPAccepted
124
- return uri unless response['Location']
125
-
126
- send_content(URI(response['Location']), 'PUT', {}, attempt - 1)
127
- when Net::HTTPSuccess
128
- uri
121
+ send_content(URI(response['Location']), 'PUT', {}, attempt - 1) if response['Location']
129
122
  when Net::HTTPRedirection
130
123
  send_content(URI(response['Location']), method, headers, attempt - 1)
131
- else
132
- raise StandardError, "request to #{uri} failed with status #{response.code}"
133
124
  end
125
+ response
134
126
  end
135
127
 
136
128
  def build_request(uri, method, headers)
@@ -9,13 +9,13 @@ module Cucumber
9
9
  module Io
10
10
  module_function
11
11
 
12
- def ensure_io(path_or_url_or_io)
12
+ def ensure_io(path_or_url_or_io, error_stream)
13
13
  return nil if path_or_url_or_io.nil?
14
14
  return path_or_url_or_io if io?(path_or_url_or_io)
15
15
 
16
16
  io = if url?(path_or_url_or_io)
17
17
  url = path_or_url_or_io
18
- reporter = url.start_with?(Cucumber::Cli::Options::CUCUMBER_PUBLISH_URL) ? URLReporter.new($stderr) : NoReporter.new
18
+ reporter = url.start_with?(Cucumber::Cli::Options::CUCUMBER_PUBLISH_URL) ? URLReporter.new(error_stream) : NoReporter.new
19
19
  HTTPIO.open(url, nil, reporter)
20
20
  else
21
21
  File.open(path_or_url_or_io, Cucumber.file_mode('w'))
@@ -64,7 +64,7 @@ module Cucumber
64
64
  raise "You *must* specify --out FILE for the #{name} formatter" unless String == path.class
65
65
  raise "I can't write #{name} to a directory - it has to be a file" if File.directory?(path)
66
66
  raise "I can't write #{name} to a file in the non-existing directory #{File.dirname(path)}" unless File.directory?(File.dirname(path))
67
- ensure_io(path)
67
+ ensure_io(path, nil)
68
68
  end
69
69
 
70
70
  def ensure_dir(path, name)
@@ -5,7 +5,6 @@ require 'base64'
5
5
  require 'cucumber/formatter/backtrace_filter'
6
6
  require 'cucumber/formatter/io'
7
7
  require 'cucumber/formatter/ast_lookup'
8
- require 'cucumber/deprecate'
9
8
 
10
9
  module Cucumber
11
10
  module Formatter
@@ -14,15 +13,7 @@ module Cucumber
14
13
  include Io
15
14
 
16
15
  def initialize(config)
17
- Cucumber::Deprecate::CliOption.deprecate(
18
- config.error_stream,
19
- '--format=json',
20
- "Please use --format=message and stand-alone json-formatter.\n" \
21
- 'json-formatter homepage: https://github.com/cucumber/cucumber/tree/master/json-formatter#cucumber-json-formatter',
22
- '6.0.0'
23
- )
24
-
25
- @io = ensure_io(config.out_stream)
16
+ @io = ensure_io(config.out_stream, config.error_stream)
26
17
  @ast_lookup = AstLookup.new(config)
27
18
  @feature_hashes = []
28
19
  @step_or_hook_hash = {}
@@ -41,21 +32,23 @@ module Cucumber
41
32
  @feature_hashes << @feature_hash
42
33
  end
43
34
  @test_case_hash = builder.test_case_hash
44
- if builder.background?
45
- @in_background = true
46
- feature_elements << builder.background_hash
47
- @element_hash = builder.background_hash
48
- else
49
- @in_background = false
50
- feature_elements << @test_case_hash
51
- @element_hash = @test_case_hash
52
- end
35
+
36
+ @element_hash = nil
37
+ @element_background_hash = builder.background_hash
38
+ @in_background = builder.background?
39
+
53
40
  @any_step_failed = false
54
41
  end
55
42
 
56
43
  def on_test_step_started(event)
57
44
  test_step = event.test_step
58
45
  return if internal_hook?(test_step)
46
+
47
+ if @element_hash.nil?
48
+ @element_hash = create_element_hash(test_step)
49
+ feature_elements << @element_hash
50
+ end
51
+
59
52
  if test_step.hook?
60
53
  @step_or_hook_hash = {}
61
54
  hooks_of_type(test_step) << @step_or_hook_hash
@@ -80,6 +73,8 @@ module Cucumber
80
73
  end
81
74
 
82
75
  def on_test_case_finished(event)
76
+ feature_elements << @test_case_hash if @in_background
77
+
83
78
  _test_case, result = *event.attributes
84
79
  result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
85
80
  add_failed_around_hook(result) if result.failed? && !@any_step_failed
@@ -94,10 +89,7 @@ module Cucumber
94
89
  test_step_output << src
95
90
  return
96
91
  end
97
- if File.file?(src)
98
- content = File.open(src, 'rb', &:read)
99
- data = encode64(content)
100
- elsif mime_type =~ /;base64$/
92
+ if mime_type =~ /;base64$/
101
93
  mime_type = mime_type[0..-8]
102
94
  data = src
103
95
  else
@@ -169,6 +161,13 @@ module Cucumber
169
161
  @step_or_hook_hash[:embeddings] ||= []
170
162
  end
171
163
 
164
+ def create_element_hash(test_step)
165
+ return @element_background_hash if @in_background && !first_step_after_background?(test_step)
166
+
167
+ @in_background = false
168
+ @test_case_hash
169
+ end
170
+
172
171
  def create_step_hash(test_step)
173
172
  step_source = @ast_lookup.step_source(test_step).step
174
173
  step_hash = {
@@ -269,7 +268,8 @@ module Cucumber
269
268
  name: background.name,
270
269
  description: value_or_empty_string(background.description),
271
270
  line: background.location.line,
272
- type: 'background'
271
+ type: 'background',
272
+ steps: []
273
273
  }
274
274
  end
275
275
 
@@ -281,7 +281,8 @@ module Cucumber
281
281
  name: test_case.name,
282
282
  description: value_or_empty_string(scenario.description),
283
283
  line: test_case.location.lines.max,
284
- type: 'scenario'
284
+ type: 'scenario',
285
+ steps: []
285
286
  }
286
287
  @test_case_hash[:tags] = create_tags_array_from_tags_array(test_case.tags) unless test_case.tags.empty?
287
288
  end