cucumber 3.1.2 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fef34be35b9337e5d78fe68a0b9e642e96a5bc8e
4
- data.tar.gz: 5331fac4008b678c3bdc18ec18f4df77e3e67bfb
2
+ SHA256:
3
+ metadata.gz: 6a9339e408c80955872fc7386ee99fc26b6519458369e06f0a65be76b27b6129
4
+ data.tar.gz: 10667fb8062a67fbf034a80a35a0d6ad53ca087bbe9cef9a9019d3343fddae94
5
5
  SHA512:
6
- metadata.gz: 560857486693d265017f21421942be4bc737f852d2972cd5a76c93f678ffe4ac06a0fd58e91f52b7ccb2d5c63156c2af13cb2e11e2bdaf9e194e516ddd663387
7
- data.tar.gz: e3ecdbb8d5a93e5e20d0e72a46be9ccb10021b12caa7d023cd3f16e845882331231764fb772cf7d1935c4db724166dbbe3eb40bbda33a4a84760ff7bd296e54a
6
+ metadata.gz: 4e9417b90d33b309f6a90845de1e66aeea91767146ca534b80f09989600ff50c1cc868f1c46696dccd48767d0cc78794df29cbe97cc227178db27c05bf510687
7
+ data.tar.gz: 2b2cdf34b49f79ec6bbb4d8b484d211c4afb82f0572baa75463b0bc8f9c614e02d1acb303fc623730b42a61e37343c1d882ffb817a1fd9eebdf7c59da7bf8813
@@ -10,6 +10,18 @@ Please visit [cucumber/CONTRIBUTING.md](https://github.com/cucumber/cucumber/blo
10
10
 
11
11
  ----
12
12
 
13
+ ## [3.2.0](https://github.com/cucumber/cucumber-ruby/compare/v3.1.2...v3.2.0) (2020-07-02)
14
+
15
+ ### Added
16
+
17
+ * `--out` option now supports URL:
18
+ * default method is `PUT`
19
+ * you can ussed cURL like options, for example: `--out "http://example.com -X POST -H Content-Type:text/json"` (Backport of [#1395](https://github.com/cucumber/cucumber-ruby/pull/1395) and [#1406](https://github.com/cucumber/cucumber-ruby/pull/1406))
20
+
21
+ ### Fixed
22
+
23
+ * JSON report: Do not fail when trying to embed bytes [#1388](https://github.com/cucumber/cucumber-ruby/issues/1388)
24
+
13
25
  ## [3.1.2](https://github.com/cucumber/cucumber-ruby/compare/v3.1.1...v3.1.2) (2018-07-13)
14
26
 
15
27
  ### Changed
@@ -109,7 +109,7 @@ module Cucumber
109
109
  add_option :formats, [*parse_formats(v), @out_stream]
110
110
  end
111
111
  opts.on('--init', *init_msg) { |v| initialize_project }
112
- opts.on('-o', '--out [FILE|DIR]', *out_msg) { |v| out_stream v }
112
+ opts.on('-o', '--out [FILE|DIR|URL]', *out_msg) { |v| out_stream v }
113
113
  opts.on('-t TAG_EXPRESSION', '--tags TAG_EXPRESSION', *tags_msg) { |v| add_tag v }
114
114
  opts.on('-n NAME', '--name NAME', *name_msg) { |v| add_option :name_regexps, /#{v}/ }
115
115
  opts.on('-e', '--exclude PATTERN', *exclude_msg) { |v| add_option :excludes, Regexp.new(v) }
@@ -305,10 +305,14 @@ TEXT
305
305
 
306
306
  def out_msg
307
307
  [
308
- 'Write output to a file/directory instead of STDOUT. This option',
308
+ 'Write output to a file/directory/URL instead of STDOUT. This option',
309
309
  'applies to the previously specified --format, or the',
310
310
  'default format if no format is specified. Check the specific',
311
- "formatter's docs to see whether to pass a file or a dir."
311
+ "formatter's docs to see whether to pass a file, dir or URL.",
312
+ "\n",
313
+ 'When using a URL, the output of the formatter will be sent as the HTTP request body.',
314
+ 'HTTP headers and request method can be set with cURL like options.',
315
+ 'Example: --out "http://example.com -X POST -H Content-Type:text/json"'
312
316
  ]
313
317
  end
314
318
 
@@ -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] ? header[1].strip : header[1]
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
@@ -1,32 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'cucumber/formatter/http_io'
4
+
3
5
  module Cucumber
4
6
  module Formatter
5
7
  module Io
6
8
  module_function
7
9
 
8
- def ensure_io(path_or_io)
9
- return nil if path_or_io.nil?
10
- return path_or_io if path_or_io.respond_to?(:write)
11
- file = File.open(path_or_io, Cucumber.file_mode('w'))
10
+ def ensure_io(path_or_url_or_io)
11
+ return nil if path_or_url_or_io.nil?
12
+ return path_or_url_or_io if path_or_url_or_io.respond_to?(:write)
13
+ io = if path_or_url_or_io =~ %r{^https?://}
14
+ HTTPIO.open(path_or_url_or_io)
15
+ else
16
+ File.open(path_or_url_or_io, Cucumber.file_mode('w'))
17
+ end
12
18
  at_exit do
13
- unless file.closed?
14
- file.flush
15
- file.close
19
+ unless io.closed?
20
+ io.flush
21
+ io.close
16
22
  end
17
23
  end
18
- file
24
+ io
19
25
  end
20
26
 
21
27
  def ensure_file(path, name)
22
- raise "You *must* specify --out FILE for the #{name} formatter" unless String === path
28
+ raise "You *must* specify --out FILE for the #{name} formatter" unless String == path.class
23
29
  raise "I can't write #{name} to a directory - it has to be a file" if File.directory?(path)
24
- raise "I can't write #{name} to a file in the non-existing directory #{File.dirname(path)}" if !File.directory?(File.dirname(path))
30
+ raise "I can't write #{name} to a file in the non-existing directory #{File.dirname(path)}" unless File.directory?(File.dirname(path))
25
31
  ensure_io(path)
26
32
  end
27
33
 
28
34
  def ensure_dir(path, name)
29
- raise "You *must* specify --out DIR for the #{name} formatter" unless String === path
35
+ raise "You *must* specify --out DIR for the #{name} formatter" unless String == path.class
30
36
  raise "I can't write #{name} reports to a file - it has to be a directory" if File.file?(path)
31
37
  FileUtils.mkdir_p(path) unless File.directory?(path)
32
38
  File.absolute_path path
@@ -82,7 +82,13 @@ module Cucumber
82
82
  end
83
83
 
84
84
  def embed(src, mime_type, _label)
85
- if File.file?(src)
85
+ begin
86
+ is_file = File.file?(src)
87
+ rescue ArgumentError
88
+ is_file = false
89
+ end
90
+
91
+ if is_file
86
92
  content = File.open(src, 'rb', &:read)
87
93
  data = encode64(content)
88
94
  else
@@ -1 +1 @@
1
- 3.1.2
1
+ 3.2.0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.2
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aslak Hellesøy
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-07-13 00:00:00.000000000 Z
13
+ date: 2020-06-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: builder
@@ -345,7 +345,6 @@ files:
345
345
  - lib/cucumber/encoding.rb
346
346
  - lib/cucumber/errors.rb
347
347
  - lib/cucumber/events.rb
348
- - lib/cucumber/events/gherkin_source_parsed.rb~
349
348
  - lib/cucumber/events/gherkin_source_read.rb
350
349
  - lib/cucumber/events/step_activated.rb
351
350
  - lib/cucumber/events/step_definition_registered.rb
@@ -372,7 +371,6 @@ files:
372
371
  - lib/cucumber/filters/tag_limits/test_case_index.rb
373
372
  - lib/cucumber/filters/tag_limits/verifier.rb
374
373
  - lib/cucumber/formatter/ansicolor.rb
375
- - lib/cucumber/formatter/ast_lookup.rb~
376
374
  - lib/cucumber/formatter/backtrace_filter.rb
377
375
  - lib/cucumber/formatter/console.rb
378
376
  - lib/cucumber/formatter/console_counts.rb
@@ -386,6 +384,7 @@ files:
386
384
  - lib/cucumber/formatter/hook_query_visitor.rb
387
385
  - lib/cucumber/formatter/html.rb
388
386
  - lib/cucumber/formatter/html_builder.rb
387
+ - lib/cucumber/formatter/http_io.rb
389
388
  - lib/cucumber/formatter/ignore_missing_messages.rb
390
389
  - lib/cucumber/formatter/inline-js.js
391
390
  - lib/cucumber/formatter/interceptor.rb
@@ -467,9 +466,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
467
466
  - !ruby/object:Gem::Version
468
467
  version: '0'
469
468
  requirements: []
470
- rubyforge_project:
471
- rubygems_version: 2.5.2
469
+ rubygems_version: 3.0.6
472
470
  signing_key:
473
471
  specification_version: 4
474
- summary: cucumber-3.1.2
472
+ summary: cucumber-3.2.0
475
473
  test_files: []
@@ -1,14 +0,0 @@
1
- require 'cucumber/core/events'
2
-
3
- module Cucumber
4
- module Events
5
- # Fired after we've read in the contents of a feature file
6
- class GherkinSourceRead < Core::Event.new(:path, :body)
7
- # The path to the file
8
- attr_reader :path
9
-
10
- # The raw Gherkin source
11
- attr_reader :body
12
- end
13
- end
14
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Cucumber
4
- module Formatter
5
- module AstLookup
6
-
7
- end
8
- end
9
- end