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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1379 -1096
- data/CONTRIBUTING.md +40 -28
- data/README.md +17 -14
- data/lib/cucumber/cli/configuration.rb +23 -1
- data/lib/cucumber/cli/options.rb +8 -3
- data/lib/cucumber/formatter/backtrace_filter.rb +1 -0
- data/lib/cucumber/formatter/html.rb +1 -1
- data/lib/cucumber/formatter/http_io.rb +33 -41
- data/lib/cucumber/formatter/io.rb +3 -3
- data/lib/cucumber/formatter/json.rb +26 -25
- data/lib/cucumber/formatter/junit.rb +18 -1
- data/lib/cucumber/formatter/message.rb +1 -1
- data/lib/cucumber/formatter/pretty.rb +1 -1
- data/lib/cucumber/formatter/progress.rb +1 -1
- data/lib/cucumber/formatter/rerun.rb +1 -1
- data/lib/cucumber/formatter/steps.rb +1 -1
- data/lib/cucumber/formatter/summary.rb +1 -1
- data/lib/cucumber/formatter/url_reporter.rb +3 -16
- data/lib/cucumber/glue/dsl.rb +1 -1
- data/lib/cucumber/glue/proto_world.rb +15 -31
- data/lib/cucumber/glue/registry_and_more.rb +1 -1
- data/lib/cucumber/runtime.rb +6 -1
- data/lib/cucumber/step_match.rb +1 -7
- data/lib/cucumber/version +1 -1
- metadata +88 -68
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
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?
|
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/
|
70
|
+
[.rubocop_todo.yml](https://github.com/cucumber/cucumber-ruby/blob/main/.rubocop_todo.yml).
|
59
71
|
|
60
72
|
## Release Process
|
61
73
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
-
|
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
|
[](https://opencollective.com/cucumber)
|
2
2
|
[](https://opencollective.com/cucumber)
|
3
|
-
|
3
|
+
[](https://oselvar.com/github/cucumber/oselvar-github-metrics/main/cucumber/cucumber-ruby)
|
4
|
+
[](https://oselvar.com/github/cucumber/oselvar-github-metrics/main/cucumber/cucumber-ruby)
|
4
5
|
[](https://circleci.com/gh/cucumber/cucumber-ruby)
|
5
|
-
|
6
6
|
[](https://codeclimate.com/github/cucumber/cucumber-ruby)
|
7
|
-
[](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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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://
|
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
|
-
|
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
|
data/lib/cucumber/cli/options.rb
CHANGED
@@ -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',
|
26
|
-
|
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"
|
343
|
+
'required or if the "support" directories themselves are',
|
339
344
|
'explicitly required.',
|
340
345
|
'This option can be specified multiple times.'
|
341
346
|
]
|
@@ -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
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
46
|
+
headers
|
50
47
|
]
|
51
48
|
end
|
52
49
|
|
53
|
-
def self.
|
54
|
-
|
55
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
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
|