cucumber 4.0.0.rc.4 → 4.1.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
  SHA256:
3
- metadata.gz: 3cf95e63d73ffec417fa0dfc1f13e208355e78783a9f092d8e143dc5ca26d636
4
- data.tar.gz: 869fe72a5dd449be55d00e2e72d8f78c236961141bf1cc85a7919bca426ec299
3
+ metadata.gz: a1f051aade812ee4bb28ab3670734b189ade8bc0cd0150a686e21874594ae62f
4
+ data.tar.gz: 80c272791953dc442492c0571acffc628cb7b1f37a28a00adeef413bc7f76e1b
5
5
  SHA512:
6
- metadata.gz: 37c240a47d8127723e75c33051ff4e546a7e5a084a22400bb55e6d00d6d578ab7d5d7daf905259cba6625a512986fcacd4076810202e6f63dbffea16b366e9f5
7
- data.tar.gz: 4556b216164535c0c2b39a1f2116b511f0cb1cccfee41cddb513073d0d887014edb38a632978347d1c127e228f1bd683317fbc62588bd4b497cdd51e10a3c550
6
+ metadata.gz: 5026e105060af702f3b0adf50f3925ce04fdee7de79c2482093831cab838e2a605d69c056733d7820b6592c7229ee93e1ce64b80ae373ac7acd29f11d113d3a8
7
+ data.tar.gz: c66fe1effa60270eb430bc2c381252e5c3da5dec524e49c58a7e508febaeb0b1398791f75eba5542395672b2431dafcfb820da2870410a52474ebc157bfbe333
@@ -10,8 +10,83 @@ Please visit [cucumber/CONTRIBUTING.md](https://github.com/cucumber/cucumber/blo
10
10
 
11
11
  ----
12
12
 
13
- ## [4.0.0.rc.4](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.3...4.0.0.rc.4)
13
+ ## [4.1.0](https://github.com/cucumber/cucumber-ruby/compare/v4.0.1...v4.1.0)
14
+
15
+ ### Changed
16
+
17
+ * Use [`cucumber-create-meta`](https://rubygems.org/gems/cucumber-create-meta) to produce the `Meta` message before the run.
18
+
19
+ * Updated gems:
20
+ * `cucumber-wire` ~> 3.1.0
21
+ * `cucumber-core` ~> 7.1.0
22
+ * `cucumber-gherkin` ~> 14.0.1
23
+ * Fix issue with empty feature files [#1427](https://github.com/cucumber/cucumber-ruby/issues/1427)
24
+ * `cucumber-messages` ~> 12.2.0
25
+ * `cucumber-html-formatter` ~> 7.0.0
26
+ * Fix issue with Hook attachments [#1420](https://github.com/cucumber/cucumber-ruby/issues/1420)
27
+
28
+ ### Fixed
29
+
30
+ * `AfterStep` hook do not cause issue when running `message` formatter. [#1433](https://github.com/cucumber/cucumber-ruby/issues/1433) - [#1434](https://github.com/cucumber/cucumber-ruby/pull/1434)
31
+
32
+
33
+ ## [4.0.1](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0...v4.0.1)
34
+
35
+ ### Fixed
36
+
37
+ * force reference to `diff-lcs` to 1.3 as 1.4 introduced breaking changes.
38
+
39
+ ## [4.0.0](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.5...v4.0.0)
40
+
41
+ ### Changed
42
+
43
+ * `log` method can now be called with non-string objects and will run `.to_s` on them. [#1410](https://github.com/cucumber/cucumber-ruby/issues/1410)
44
+
45
+ ### Improved
14
46
 
47
+ * Display snippet when using undefined parameter type [#1411](https://github.com/cucumber/cucumber-ruby/issues/1411)
48
+
49
+ ## [4.0.0.rc.6](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.5...4.0.0.rc.6)
50
+
51
+ ### Changed
52
+
53
+ * Code snippet for an undefined step with a Doc String will ouput `doc_string` instead of `string` in block params
54
+ ([#1401](https://github.com/cucumber/cucumber-ruby/issues/1401)
55
+ [#1402](https://github.com/cucumber/cucumber-ruby/pull/1402)
56
+ [karamosky](https://github.com/karamosky))
57
+
58
+ * Updated monorepo libraries:
59
+ - cucumber-gherkin ~> 13
60
+ - cucumber-html-formatter ~> 6
61
+ - cucumber-cucumber-expressions ~> 10
62
+
63
+ * Use `cucumber-ruby-core` 7.0.0
64
+
65
+ * Use `cucumber-ruby-wire` 3.0.0
66
+
67
+ * Use `body` field of attachments
68
+
69
+ ### Improved
70
+
71
+ * `--out url` updates:
72
+ * supports redirects
73
+ * use `PUT` method by default
74
+ * use a cURL like options (for example: `cucumber --out 'http://example.com -X POST -H Content-Type: json`)
75
+
76
+ ## [4.0.0.rc.5](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.4...4.0.0.rc.5)
77
+
78
+ ### Added
79
+
80
+ * New html formatter enabled by option `--format html --out report.html`.
81
+
82
+ * Accept `--out URL` to POST results to a web server
83
+ If a URL is used as output, the output will be sent with a POST request.
84
+ This can be overridden by specifying e.g. `http-method=PUT` as a query parameter.
85
+ Other `http-` prefixed query parameters will be converted to request headers
86
+ (with the `http-` prefix stripped off).
87
+
88
+
89
+ ## [4.0.0.rc.4](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.3...4.0.0.rc.4)
15
90
 
16
91
  ### Added
17
92
 
@@ -42,7 +117,7 @@ Please visit [cucumber/CONTRIBUTING.md](https://github.com/cucumber/cucumber/blo
42
117
  * If you wish to alter this, then you can set a top level config option: `Cucumber.use_legacy_autoloader`
43
118
  * Like most config options, setting this inside a `spec_helper.rb` or `env.rb` file is advised
44
119
  * For more information on this change, including why it was made. Please read this
45
- [Blog Post](www.google.com)
120
+ [Blog Post](https://cucumber.io/blog/open-source/tweaking-cucumber-rubys-auto-loader/)
46
121
  ([#1349](https://github.com/cucumber/cucumber-ruby/pull/1349),
47
122
  [#1043](https://github.com/cucumber/cucumber-ruby/issues/1043)
48
123
  [luke-hill](https://github.com/luke-hill))
data/README.md CHANGED
@@ -15,7 +15,7 @@ your team.
15
15
 
16
16
  Where to get more info:
17
17
 
18
- * The main website: https://cucumber.io/
18
+ * The main website: https://cucumber.io/
19
19
  * Documentation: https://cucumber.io/docs
20
20
  * Ruby API Documentation: http://www.rubydoc.info/github/cucumber/cucumber-ruby/
21
21
  * Support forum: https://groups.google.com/group/cukes
@@ -28,7 +28,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for info on contributing to Cucumber.
28
28
  * Ruby 2.5
29
29
  * Ruby 2.4
30
30
  * Ruby 2.3
31
- * JRuby 9.1
31
+ * JRuby 9.2 (with [some limitations](https://github.com/cucumber/cucumber-ruby/blob/master/docs/jruby-limitations.md))
32
32
 
33
33
  ## Code of Conduct
34
34
 
@@ -24,6 +24,7 @@ module Cucumber
24
24
  'junit' => ['Cucumber::Formatter::Junit', 'Generates a report similar to Ant+JUnit.'],
25
25
  'json' => ['Cucumber::Formatter::Json', '[DEPRECATED] Prints the feature as JSON'],
26
26
  'message' => ['Cucumber::Formatter::Message', 'Outputs protobuf messages'],
27
+ 'html' => ['Cucumber::Formatter::HTML', 'Outputs HTML report'],
27
28
  'summary' => ['Cucumber::Formatter::Summary', 'Summary output of feature and scenarios']
28
29
  }.freeze
29
30
  max = BUILTIN_FORMATS.keys.map(&:length).max
@@ -104,7 +105,7 @@ module Cucumber
104
105
  add_option :formats, [*parse_formats(v), @out_stream]
105
106
  end
106
107
  opts.on('--init', *init_msg) { |_v| initialize_project }
107
- opts.on('-o', '--out [FILE|DIR]', *out_msg) { |v| out_stream v }
108
+ opts.on('-o', '--out [FILE|DIR|URL]', *out_msg) { |v| out_stream v }
108
109
  opts.on('-t TAG_EXPRESSION', '--tags TAG_EXPRESSION', *tags_msg) { |v| add_tag v }
109
110
  opts.on('-n NAME', '--name NAME', *name_msg) { |v| add_option :name_regexps, /#{v}/ }
110
111
  opts.on('-e', '--exclude PATTERN', *exclude_msg) { |v| add_option :excludes, Regexp.new(v) }
@@ -295,10 +296,14 @@ Specify SEED to reproduce the shuffling from a previous run.
295
296
 
296
297
  def out_msg
297
298
  [
298
- 'Write output to a file/directory instead of STDOUT. This option',
299
+ 'Write output to a file/directory/URL instead of STDOUT. This option',
299
300
  'applies to the previously specified --format, or the',
300
301
  'default format if no format is specified. Check the specific',
301
- "formatter's docs to see whether to pass a file or a dir."
302
+ "formatter's docs to see whether to pass a file, dir or URL.",
303
+ "\n",
304
+ 'When using a URL, the output of the formatter will be sent as the HTTP request body.',
305
+ 'HTTP headers and request method can be set with cURL like options.',
306
+ 'Example: --out "http://example.com -X POST -H Content-Type:text/json"'
302
307
  ]
303
308
  end
304
309
 
@@ -49,7 +49,4 @@ module Cucumber
49
49
  super(messages.join("\n"))
50
50
  end
51
51
  end
52
-
53
- class LogTypeInvalid < StandardError
54
- end
55
52
  end
@@ -38,7 +38,8 @@ module Cucumber
38
38
  TestStepCreated,
39
39
  TestStepFinished,
40
40
  TestStepStarted,
41
- Envelope
41
+ Envelope,
42
+ UndefinedParameterType
42
43
  )
43
44
  end
44
45
  end
@@ -0,0 +1,10 @@
1
+ require 'cucumber/core/events'
2
+
3
+ module Cucumber
4
+ module Events
5
+ class UndefinedParameterType < Core::Event.new(:type_name, :expression)
6
+ attr_reader :type_name
7
+ attr_reader :expression
8
+ end
9
+ end
10
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Metrics/ModuleLength
4
+
3
5
  require 'cucumber/formatter/ansicolor'
4
6
  require 'cucumber/formatter/duration'
5
7
  require 'cucumber/gherkin/i18n'
@@ -116,14 +118,21 @@ module Cucumber
116
118
  @snippets_input << Console::SnippetData.new(keyword, test_step)
117
119
  end
118
120
 
121
+ def collect_undefined_parameter_type_names(undefined_parameter_type)
122
+ @undefined_parameter_types << undefined_parameter_type.type_name
123
+ end
124
+
119
125
  def print_snippets(options)
120
126
  return unless options[:snippets]
121
- return if @snippets_input.empty?
122
127
 
123
128
  snippet_text_proc = lambda do |step_keyword, step_name, multiline_arg|
124
129
  snippet_text(step_keyword, step_name, multiline_arg)
125
130
  end
126
- do_print_snippets(snippet_text_proc)
131
+ do_print_snippets(snippet_text_proc) unless @snippets_input.empty?
132
+
133
+ @undefined_parameter_types.map do |type_name|
134
+ do_print_undefined_parameter_type_snippet(type_name)
135
+ end
127
136
  end
128
137
 
129
138
  def do_print_snippets(snippet_text_proc)
@@ -181,6 +190,24 @@ module Cucumber
181
190
  @io.puts "Using the #{profiles_sentence} profile#{'s' if profiles.size > 1}..."
182
191
  end
183
192
 
193
+ def do_print_undefined_parameter_type_snippet(type_name)
194
+ camelized = type_name.split(/_|-/).collect(&:capitalize).join
195
+
196
+ @io.puts [
197
+ "The parameter #{type_name} is not defined. You can define a new one with:",
198
+ '',
199
+ 'ParameterType(',
200
+ " name: '#{type_name}',",
201
+ ' regexp: /some regexp here/,',
202
+ " type: #{camelized},",
203
+ ' # The transformer takes as many arguments as there are capture groups in the regexp,',
204
+ ' # or just one if there are none.',
205
+ " transformer: ->(s) { #{camelized}.new(s) }",
206
+ ')',
207
+ ''
208
+ ].join("\n")
209
+ end
210
+
184
211
  private
185
212
 
186
213
  FORMATS = Hash.new { |hash, format| hash[format] = method(format).to_proc }
@@ -219,3 +246,4 @@ module Cucumber
219
246
  end
220
247
  end
221
248
  end
249
+ # rubocop:enable Metrics/ModuleLength
@@ -0,0 +1,24 @@
1
+ require 'cucumber/formatter/io'
2
+ require 'cucumber/html_formatter'
3
+ require 'cucumber/formatter/message_builder'
4
+
5
+ module Cucumber
6
+ module Formatter
7
+ class HTML < MessageBuilder
8
+ include Io
9
+
10
+ def initialize(config)
11
+ @io = ensure_io(config.out_stream)
12
+ @html_formatter = Cucumber::HTMLFormatter::Formatter.new(@io)
13
+ @html_formatter.write_pre_message
14
+
15
+ super(config)
16
+ end
17
+
18
+ def output_envelope(envelope)
19
+ @html_formatter.write_message(envelope)
20
+ @html_formatter.write_post_message if envelope.test_run_finished
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,146 @@
1
+ require 'net/http'
2
+ require 'tempfile'
3
+
4
+ module Cucumber
5
+ module Formatter
6
+ class HTTPIO
7
+ class << self
8
+ # Returns an IO that will write to a HTTP request's body
9
+ def open(url, https_verify_mode = nil)
10
+ @https_verify_mode = https_verify_mode
11
+ uri, method, headers = CurlOptionParser.parse(url)
12
+ IOHTTPBuffer.new(uri, method, headers, https_verify_mode)
13
+ end
14
+ end
15
+ end
16
+
17
+ class CurlOptionParser
18
+ 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
35
+
36
+ if last_flag == '-X'
37
+ http_method = chunk
38
+ last_flag = nil
39
+ end
40
+
41
+ headers += chunk if last_flag == '-H'
42
+ end
43
+
44
+ [
45
+ url,
46
+ http_method,
47
+ make_headers(headers)
48
+ ]
49
+ end
50
+
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
59
+
60
+ hash_headers
61
+ end
62
+ end
63
+
64
+ class IOHTTPBuffer
65
+ attr_reader :uri, :method, :headers
66
+
67
+ def initialize(uri, method, headers = {}, https_verify_mode = nil)
68
+ @uri = URI(uri)
69
+ @method = method
70
+ @headers = headers
71
+ @write_io = Tempfile.new('cucumber', encoding: 'UTF-8')
72
+ @https_verify_mode = https_verify_mode
73
+ end
74
+
75
+ def close
76
+ post_content(@uri, @method, @headers)
77
+ @write_io.close
78
+ end
79
+
80
+ def write(data)
81
+ @write_io.write(data)
82
+ end
83
+
84
+ def flush
85
+ @write_io.flush
86
+ end
87
+
88
+ def closed?
89
+ @write_io.closed?
90
+ end
91
+
92
+ private
93
+
94
+ def post_content(uri, method, headers, attempt = 10)
95
+ content = @write_io
96
+ http = build_client(uri, @https_verify_mode)
97
+
98
+ raise StandardError, "request to #{uri} failed (too many redirections)" if attempt <= 0
99
+ req = build_request(
100
+ uri,
101
+ method,
102
+ headers.merge(
103
+ 'Content-Length' => content.size.to_s
104
+ )
105
+ )
106
+
107
+ content.rewind
108
+ req.body_stream = content
109
+
110
+ begin
111
+ response = http.request(req)
112
+ rescue SystemCallError
113
+ # We may get the redirect response before pushing the file.
114
+ response = http.request(build_request(uri, method, headers))
115
+ end
116
+
117
+ case response
118
+ when Net::HTTPSuccess
119
+ response
120
+ when Net::HTTPRedirection
121
+ post_content(URI(response['Location']), method, headers, attempt - 1)
122
+ else
123
+ raise StandardError, "request to #{uri} failed with status #{response.code}"
124
+ end
125
+ end
126
+
127
+ def build_request(uri, method, headers)
128
+ method_class_name = "#{method[0].upcase}#{method[1..-1].downcase}"
129
+ req = Net::HTTP.const_get(method_class_name).new(uri)
130
+ headers.each do |header, value|
131
+ req[header] = value
132
+ end
133
+ req
134
+ end
135
+
136
+ def build_client(uri, https_verify_mode)
137
+ http = Net::HTTP.new(uri.hostname, uri.port)
138
+ if uri.scheme == 'https'
139
+ http.use_ssl = true
140
+ http.verify_mode = https_verify_mode if https_verify_mode
141
+ end
142
+ http
143
+ end
144
+ end
145
+ end
146
+ end
@@ -9,17 +9,18 @@ module Cucumber
9
9
  @pipe = pipe
10
10
  @buffer = StringIO.new
11
11
  @wrapped = true
12
+ @lock = Mutex.new
12
13
  end
13
14
 
14
15
  def write(str)
15
- lock.synchronize do
16
+ @lock.synchronize do
16
17
  @buffer << str if @wrapped
17
18
  return @pipe.write(str)
18
19
  end
19
20
  end
20
21
 
21
22
  def buffer_string
22
- lock.synchronize do
23
+ @lock.synchronize do
23
24
  return @buffer.string.dup
24
25
  end
25
26
  end
@@ -67,12 +68,6 @@ module Cucumber
67
68
  return $stdout
68
69
  end
69
70
  end
70
-
71
- private
72
-
73
- def lock
74
- @lock ||= Mutex.new
75
- end
76
71
  end
77
72
  end
78
73
  end