cucumber 3.1.2 → 7.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.
Files changed (118) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1780 -1146
  3. data/CONTRIBUTING.md +224 -61
  4. data/README.md +144 -22
  5. data/bin/cucumber +1 -1
  6. data/lib/autotest/cucumber_mixin.rb +46 -53
  7. data/lib/cucumber/cli/configuration.rb +28 -6
  8. data/lib/cucumber/cli/main.rb +12 -12
  9. data/lib/cucumber/cli/options.rb +103 -77
  10. data/lib/cucumber/cli/profile_loader.rb +49 -26
  11. data/lib/cucumber/configuration.rb +44 -29
  12. data/lib/cucumber/constantize.rb +2 -5
  13. data/lib/cucumber/deprecate.rb +31 -7
  14. data/lib/cucumber/errors.rb +5 -7
  15. data/lib/cucumber/events/envelope.rb +9 -0
  16. data/lib/cucumber/events/gherkin_source_parsed.rb +11 -0
  17. data/lib/cucumber/events/hook_test_step_created.rb +13 -0
  18. data/lib/cucumber/events/step_activated.rb +2 -1
  19. data/lib/cucumber/events/test_case_created.rb +13 -0
  20. data/lib/cucumber/events/test_case_ready.rb +12 -0
  21. data/lib/cucumber/events/test_step_created.rb +13 -0
  22. data/lib/cucumber/events/undefined_parameter_type.rb +10 -0
  23. data/lib/cucumber/events.rb +14 -7
  24. data/lib/cucumber/file_specs.rb +6 -6
  25. data/lib/cucumber/filters/activate_steps.rb +5 -3
  26. data/lib/cucumber/filters/broadcast_test_case_ready_event.rb +12 -0
  27. data/lib/cucumber/filters/prepare_world.rb +5 -9
  28. data/lib/cucumber/filters/quit.rb +1 -3
  29. data/lib/cucumber/filters/tag_limits/verifier.rb +2 -4
  30. data/lib/cucumber/filters.rb +1 -0
  31. data/lib/cucumber/formatter/ansicolor.rb +40 -52
  32. data/lib/cucumber/formatter/ast_lookup.rb +163 -0
  33. data/lib/cucumber/formatter/backtrace_filter.rb +10 -8
  34. data/lib/cucumber/formatter/console.rb +69 -69
  35. data/lib/cucumber/formatter/console_counts.rb +4 -9
  36. data/lib/cucumber/formatter/console_issues.rb +6 -3
  37. data/lib/cucumber/formatter/duration.rb +1 -1
  38. data/lib/cucumber/formatter/duration_extractor.rb +3 -1
  39. data/lib/cucumber/formatter/errors.rb +6 -0
  40. data/lib/cucumber/formatter/fanout.rb +2 -0
  41. data/lib/cucumber/formatter/html.rb +11 -598
  42. data/lib/cucumber/formatter/http_io.rb +147 -0
  43. data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -1
  44. data/lib/cucumber/formatter/interceptor.rb +11 -30
  45. data/lib/cucumber/formatter/io.rb +55 -13
  46. data/lib/cucumber/formatter/json.rb +115 -122
  47. data/lib/cucumber/formatter/junit.rb +72 -55
  48. data/lib/cucumber/formatter/message.rb +23 -0
  49. data/lib/cucumber/formatter/message_builder.rb +255 -0
  50. data/lib/cucumber/formatter/pretty.rb +360 -153
  51. data/lib/cucumber/formatter/progress.rb +30 -32
  52. data/lib/cucumber/formatter/publish_banner_printer.rb +77 -0
  53. data/lib/cucumber/formatter/query/hook_by_test_step.rb +31 -0
  54. data/lib/cucumber/formatter/query/pickle_by_test.rb +26 -0
  55. data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +26 -0
  56. data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +40 -0
  57. data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +40 -0
  58. data/lib/cucumber/formatter/rerun.rb +22 -4
  59. data/lib/cucumber/formatter/stepdefs.rb +1 -2
  60. data/lib/cucumber/formatter/steps.rb +8 -6
  61. data/lib/cucumber/formatter/summary.rb +16 -8
  62. data/lib/cucumber/formatter/unicode.rb +15 -17
  63. data/lib/cucumber/formatter/url_reporter.rb +17 -0
  64. data/lib/cucumber/formatter/usage.rb +17 -14
  65. data/lib/cucumber/gherkin/data_table_parser.rb +17 -6
  66. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +13 -17
  67. data/lib/cucumber/gherkin/formatter/escaping.rb +2 -2
  68. data/lib/cucumber/gherkin/steps_parser.rb +17 -8
  69. data/lib/cucumber/glue/dsl.rb +19 -0
  70. data/lib/cucumber/glue/hook.rb +34 -11
  71. data/lib/cucumber/glue/invoke_in_world.rb +13 -18
  72. data/lib/cucumber/glue/proto_world.rb +37 -44
  73. data/lib/cucumber/glue/registry_and_more.rb +71 -12
  74. data/lib/cucumber/glue/registry_wrapper.rb +31 -0
  75. data/lib/cucumber/glue/snippet.rb +23 -22
  76. data/lib/cucumber/glue/step_definition.rb +42 -20
  77. data/lib/cucumber/glue/world_factory.rb +1 -1
  78. data/lib/cucumber/hooks.rb +11 -11
  79. data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +2 -2
  80. data/lib/cucumber/multiline_argument/data_table.rb +97 -64
  81. data/lib/cucumber/multiline_argument/doc_string.rb +1 -1
  82. data/lib/cucumber/multiline_argument.rb +4 -6
  83. data/lib/cucumber/platform.rb +3 -3
  84. data/lib/cucumber/rake/task.rb +16 -18
  85. data/lib/cucumber/rspec/disable_option_parser.rb +9 -8
  86. data/lib/cucumber/rspec/doubles.rb +3 -5
  87. data/lib/cucumber/running_test_case.rb +2 -53
  88. data/lib/cucumber/runtime/after_hooks.rb +8 -4
  89. data/lib/cucumber/runtime/before_hooks.rb +8 -4
  90. data/lib/cucumber/runtime/for_programming_languages.rb +4 -2
  91. data/lib/cucumber/runtime/step_hooks.rb +6 -2
  92. data/lib/cucumber/runtime/support_code.rb +13 -15
  93. data/lib/cucumber/runtime/user_interface.rb +6 -16
  94. data/lib/cucumber/runtime.rb +77 -59
  95. data/lib/cucumber/step_definition_light.rb +4 -3
  96. data/lib/cucumber/step_definitions.rb +2 -2
  97. data/lib/cucumber/step_match.rb +12 -17
  98. data/lib/cucumber/step_match_search.rb +2 -1
  99. data/lib/cucumber/term/ansicolor.rb +9 -9
  100. data/lib/cucumber/term/banner.rb +56 -0
  101. data/lib/cucumber/version +1 -1
  102. data/lib/cucumber.rb +1 -1
  103. metadata +272 -81
  104. data/lib/cucumber/core_ext/string.rb +0 -11
  105. data/lib/cucumber/events/gherkin_source_parsed.rb~ +0 -14
  106. data/lib/cucumber/formatter/ast_lookup.rb~ +0 -9
  107. data/lib/cucumber/formatter/cucumber.css +0 -286
  108. data/lib/cucumber/formatter/cucumber.sass +0 -247
  109. data/lib/cucumber/formatter/hook_query_visitor.rb +0 -42
  110. data/lib/cucumber/formatter/html_builder.rb +0 -121
  111. data/lib/cucumber/formatter/inline-js.js +0 -30
  112. data/lib/cucumber/formatter/jquery-min.js +0 -154
  113. data/lib/cucumber/formatter/json_pretty.rb +0 -11
  114. data/lib/cucumber/formatter/legacy_api/adapter.rb +0 -1028
  115. data/lib/cucumber/formatter/legacy_api/ast.rb +0 -394
  116. data/lib/cucumber/formatter/legacy_api/results.rb +0 -50
  117. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +0 -32
  118. data/lib/cucumber/step_argument.rb +0 -25
@@ -3,7 +3,6 @@
3
3
  require 'forwardable'
4
4
  require 'cucumber/gherkin/data_table_parser'
5
5
  require 'cucumber/gherkin/formatter/escaping'
6
- require 'cucumber/core/ast/describes_itself'
7
6
  require 'cucumber/multiline_argument/data_table/diff_matrices'
8
7
 
9
8
  module Cucumber
@@ -28,19 +27,21 @@ module Cucumber
28
27
  # This will store <tt>[['a', 'b'], ['c', 'd']]</tt> in the <tt>data</tt> variable.
29
28
  #
30
29
  class DataTable
31
- include Core::Ast::DescribesItself
32
-
33
30
  def self.default_arg_name #:nodoc:
34
31
  'table'
35
32
  end
36
33
 
34
+ def describe_to(visitor, *args)
35
+ visitor.legacy_table(self, *args)
36
+ end
37
+
37
38
  class << self
38
- def from(data, location = Core::Ast::Location.of_caller)
39
+ def from(data)
39
40
  case data
40
41
  when Array
41
- from_array(data, location)
42
+ from_array(data)
42
43
  when String
43
- parse(data, location)
44
+ parse(data)
44
45
  else
45
46
  raise ArgumentError, 'expected data to be a String or an Array.'
46
47
  end
@@ -48,15 +49,15 @@ module Cucumber
48
49
 
49
50
  private
50
51
 
51
- def parse(text, location = Core::Ast::Location.of_caller)
52
+ def parse(text)
52
53
  builder = Builder.new
53
54
  parser = Cucumber::Gherkin::DataTableParser.new(builder)
54
55
  parser.parse(text)
55
- from_array(builder.rows, location)
56
+ from_array(builder.rows)
56
57
  end
57
58
 
58
- def from_array(data, location = Core::Ast::Location.of_caller)
59
- new Core::Ast::DataTable.new(data, location)
59
+ def from_array(data)
60
+ new Core::Test::DataTable.new(data)
60
61
  end
61
62
  end
62
63
 
@@ -71,18 +72,17 @@ module Cucumber
71
72
  @rows << row
72
73
  end
73
74
 
74
- def eof
75
- end
75
+ def eof; end
76
76
  end
77
77
 
78
- NULL_CONVERSIONS = Hash.new({ :strict => false, :proc => lambda { |cell_value| cell_value } }).freeze
78
+ NULL_CONVERSIONS = Hash.new(strict: false, proc: ->(cell_value) { cell_value }).freeze
79
79
 
80
- # @param data [Core::Ast::DataTable] the data for the table
80
+ # @param data [Core::Test::DataTable] the data for the table
81
81
  # @param conversion_procs [Hash] see map_columns!
82
82
  # @param header_mappings [Hash] see map_headers!
83
83
  # @param header_conversion_proc [Proc] see map_headers!
84
84
  def initialize(data, conversion_procs = NULL_CONVERSIONS.dup, header_mappings = {}, header_conversion_proc = nil)
85
- raise ArgumentError, 'data must be a Core::Ast::DataTable' unless data.is_a? Core::Ast::DataTable
85
+ raise ArgumentError, 'data must be a Core::Test::DataTable' unless data.is_a? Core::Test::DataTable
86
86
  ast_table = data
87
87
  # Verify that it's square
88
88
  ast_table.transpose
@@ -111,7 +111,7 @@ module Cucumber
111
111
  # registered with #map_column! and #map_headers!.
112
112
  #
113
113
  def dup
114
- self.class.new(Core::Ast::DataTable.new(raw, location), @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
114
+ self.class.new(Core::Test::DataTable.new(raw), @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
115
115
  end
116
116
 
117
117
  # Returns a new, transposed table. Example:
@@ -126,7 +126,7 @@ module Cucumber
126
126
  # | 4 | 2 |
127
127
  #
128
128
  def transpose
129
- self.class.new(Core::Ast::DataTable.new(raw.transpose, location), @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
129
+ self.class.new(Core::Test::DataTable.new(raw.transpose), @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
130
130
  end
131
131
 
132
132
  # Converts this table into an Array of Hash where the keys of each
@@ -160,7 +160,7 @@ module Cucumber
160
160
  #
161
161
  def symbolic_hashes
162
162
  @symbolic_hashes ||=
163
- self.hashes.map do |string_hash|
163
+ hashes.map do |string_hash|
164
164
  Hash[string_hash.map { |a, b| [symbolize_key(a), b] }]
165
165
  end
166
166
  end
@@ -180,7 +180,7 @@ module Cucumber
180
180
  def rows_hash
181
181
  return @rows_hash if @rows_hash
182
182
  verify_table_width(2)
183
- @rows_hash = self.transpose.hashes[0]
183
+ @rows_hash = transpose.hashes[0]
184
184
  end
185
185
 
186
186
  # Gets the raw data of this table. For example, a Table built from
@@ -200,7 +200,7 @@ module Cucumber
200
200
  end
201
201
 
202
202
  def column_names #:nodoc:
203
- @col_names ||= cell_matrix[0].map(&:value)
203
+ @column_names ||= cell_matrix[0].map(&:value)
204
204
  end
205
205
 
206
206
  def rows
@@ -269,7 +269,7 @@ module Cucumber
269
269
 
270
270
  # Returns a new Table where the headers are redefined. See #map_headers!
271
271
  def map_headers(mappings = {}, &block)
272
- self.class.new(Core::Ast::DataTable.new(raw, location), @conversion_procs.dup, mappings, block)
272
+ self.class.new(Core::Test::DataTable.new(raw), @conversion_procs.dup, mappings, block)
273
273
  end
274
274
 
275
275
  # Change how #hashes converts column values. The +column_name+ argument identifies the column
@@ -286,15 +286,15 @@ module Cucumber
286
286
  #
287
287
  def map_column!(column_name, strict = true, &conversion_proc)
288
288
  # TODO: Remove this method for 2.0
289
- @conversion_procs[column_name.to_s] = { :strict => strict, :proc => conversion_proc }
289
+ @conversion_procs[column_name.to_s] = { strict: strict, proc: conversion_proc }
290
290
  self
291
291
  end
292
292
 
293
293
  # Returns a new Table with an additional column mapping. See #map_column!
294
294
  def map_column(column_name, strict = true, &conversion_proc)
295
295
  conversion_procs = @conversion_procs.dup
296
- conversion_procs[column_name.to_s] = { :strict => strict, :proc => conversion_proc }
297
- self.class.new(Core::Ast::DataTable.new(raw, location), conversion_procs, @header_mappings.dup, @header_conversion_proc)
296
+ conversion_procs[column_name.to_s] = { strict: strict, proc: conversion_proc }
297
+ self.class.new(Core::Test::DataTable.new(raw), conversion_procs, @header_mappings.dup, @header_conversion_proc)
298
298
  end
299
299
 
300
300
  # Compares +other_table+ to self. If +other_table+ contains columns
@@ -352,9 +352,13 @@ module Cucumber
352
352
  end
353
353
  end
354
354
 
355
- def to_hash(cells) #:nodoc:
356
- hash = Hash.new do |hash, key|
357
- hash[key.to_s] if key.is_a?(Symbol)
355
+ def to_hash
356
+ cells_rows.map { |cells| cells.map(&:value) }
357
+ end
358
+
359
+ def cells_to_hash(cells) #:nodoc:
360
+ hash = Hash.new do |hash_inner, key|
361
+ hash_inner[key.to_s] if key.is_a?(Symbol)
358
362
  end
359
363
  column_names.each_with_index do |column_name, column_index|
360
364
  hash[column_name] = cells.value(column_index)
@@ -367,19 +371,21 @@ module Cucumber
367
371
  end
368
372
 
369
373
  def verify_column(column_name) #:nodoc:
370
- raise %{The column named "#{column_name}" does not exist} unless raw[0].include?(column_name)
374
+ raise %(The column named "#{column_name}" does not exist) unless raw[0].include?(column_name)
371
375
  end
372
376
 
373
377
  def verify_table_width(width) #:nodoc:
374
- raise %{The table must have exactly #{width} columns} unless raw[0].size == width
378
+ raise %(The table must have exactly #{width} columns) unless raw[0].size == width
375
379
  end
376
380
 
377
- def has_text?(text) #:nodoc:
381
+ # TODO: remove the below function if it's not actually being used.
382
+ # Nothing else in this repo calls it.
383
+ def text?(text) #:nodoc:
378
384
  raw.flatten.compact.detect { |cell_value| cell_value.index(text) }
379
385
  end
380
386
 
381
387
  def cells_rows #:nodoc:
382
- @rows ||= cell_matrix.map do |cell_row|
388
+ @rows ||= cell_matrix.map do |cell_row| # rubocop:disable Naming/MemoizedInstanceVariableName
383
389
  Cells.new(self, cell_row)
384
390
  end
385
391
  end
@@ -399,26 +405,48 @@ module Cucumber
399
405
  end
400
406
 
401
407
  def to_s(options = {}) #:nodoc:
402
- # TODO: factor out this code so we don't depend on such a big lump of old cruft
403
- require 'cucumber/formatter/pretty'
404
- require 'cucumber/formatter/legacy_api/adapter'
405
- options = {:color => true, :indent => 2, :prefixes => TO_S_PREFIXES}.merge(options)
406
- io = StringIO.new
407
-
408
- c = Cucumber::Term::ANSIColor.coloring?
409
- Cucumber::Term::ANSIColor.coloring = options[:color]
410
- runtime = Struct.new(:configuration).new(Configuration.new)
411
- formatter = Formatter::Pretty.new(runtime, io, options)
412
- formatter.instance_variable_set('@indent', options[:indent])
413
- Formatter::LegacyApi::Ast::MultilineArg.for(self).accept(Formatter::Fanout.new([formatter]))
414
- Cucumber::Term::ANSIColor.coloring = c
415
- io.rewind
416
- s = "\n" + io.read + (' ' * (options[:indent] - 2))
417
- s
408
+ indentation = options.key?(:indent) ? options[:indent] : 2
409
+ prefixes = options.key?(:prefixes) ? options[:prefixes] : TO_S_PREFIXES
410
+ DataTablePrinter.new(self, indentation, prefixes).to_s
418
411
  end
419
412
 
420
- def description_for_visitors
421
- :legacy_table
413
+ class DataTablePrinter #:nodoc:
414
+ include Cucumber::Gherkin::Formatter::Escaping
415
+ attr_reader :data_table, :indentation, :prefixes
416
+ private :data_table, :indentation, :prefixes
417
+
418
+ def initialize(data_table, indentation, prefixes)
419
+ @data_table = data_table
420
+ @indentation = indentation
421
+ @prefixes = prefixes
422
+ end
423
+
424
+ def to_s
425
+ leading_row = "\n"
426
+ end_indentation = indentation - 2
427
+ trailing_row = "\n" + (' ' * end_indentation)
428
+ table_rows = data_table.cell_matrix.map { |row| format_row(row) }
429
+ leading_row + table_rows.join("\n") + trailing_row
430
+ end
431
+
432
+ private
433
+
434
+ def format_row(row)
435
+ row_start = (' ' * indentation) + '| '
436
+ row_end = '|'
437
+ cells = row.map.with_index do |cell, i|
438
+ format_cell(cell, data_table.col_width(i))
439
+ end
440
+ row_start + cells.join('| ') + row_end
441
+ end
442
+
443
+ def format_cell(cell, col_width)
444
+ cell_text = escape_cell(cell.value.to_s)
445
+ cell_text_width = cell_text.unpack('U*').length
446
+ padded_text = cell_text + (' ' * (col_width - cell_text_width))
447
+ prefix = prefixes[cell.status]
448
+ "#{prefix}#{padded_text} "
449
+ end
422
450
  end
423
451
 
424
452
  def columns #:nodoc:
@@ -446,7 +474,11 @@ module Cucumber
446
474
 
447
475
  def create_cell_matrix(ast_table) #:nodoc:
448
476
  ast_table.raw.map do |raw_row|
449
- line = raw_row.line rescue -1
477
+ line = begin
478
+ raw_row.line
479
+ rescue StandardError
480
+ -1
481
+ end
450
482
  raw_row.map do |raw_cell|
451
483
  Cell.new(raw_cell, self, line)
452
484
  end
@@ -476,22 +508,20 @@ module Cucumber
476
508
  end
477
509
 
478
510
  @header_mappings.each_pair do |pre, post|
479
- mapped_cells = header_cells.select { |cell| pre === cell.value }
511
+ mapped_cells = header_cells.reject { |cell| cell.value.match(pre).nil? }
480
512
  raise "No headers matched #{pre.inspect}" if mapped_cells.empty?
481
513
  raise "#{mapped_cells.length} headers matched #{pre.inspect}: #{mapped_cells.map(&:value).inspect}" if mapped_cells.length > 1
482
514
  mapped_cells[0].value = post
483
- if @conversion_procs.key?(pre)
484
- @conversion_procs[post] = @conversion_procs.delete(pre)
485
- end
515
+ @conversion_procs[post] = @conversion_procs.delete(pre) if @conversion_procs.key?(pre)
486
516
  end
487
517
  end
488
518
 
489
519
  def clear_cache! #:nodoc:
490
- @hashes = @rows_hash = @col_names = @rows = @columns = nil
520
+ @hashes = @rows_hash = @column_names = @rows = @columns = nil
491
521
  end
492
522
 
493
523
  def ensure_table(table_or_array) #:nodoc:
494
- return table_or_array if DataTable === table_or_array
524
+ return table_or_array if DataTable == table_or_array.class
495
525
  DataTable.from(table_or_array)
496
526
  end
497
527
 
@@ -507,7 +537,8 @@ module Cucumber
507
537
  attr_reader :exception
508
538
 
509
539
  def initialize(table, cells)
510
- @table, @cells = table, cells
540
+ @table = table
541
+ @cells = cells
511
542
  end
512
543
 
513
544
  def accept(visitor)
@@ -524,7 +555,7 @@ module Cucumber
524
555
  end
525
556
 
526
557
  def to_hash #:nodoc:
527
- @to_hash ||= @table.to_hash(self)
558
+ @to_hash ||= @table.cells_to_hash(self)
528
559
  end
529
560
 
530
561
  def value(n) #:nodoc:
@@ -563,19 +594,21 @@ module Cucumber
563
594
  attr_accessor :status, :value
564
595
 
565
596
  def initialize(value, table, line)
566
- @value, @table, @line = value, table, line
597
+ @value = value
598
+ @table = table
599
+ @line = line
567
600
  end
568
601
 
569
602
  def inspect!
570
603
  @value = "(i) #{value.inspect}"
571
604
  end
572
605
 
573
- def ==(o)
574
- SurplusCell === o || value == o.value
606
+ def ==(other)
607
+ SurplusCell == other.class || value == other.value
575
608
  end
576
609
 
577
- def eql?(o)
578
- self == o
610
+ def eql?(other)
611
+ self == other
579
612
  end
580
613
 
581
614
  def hash
@@ -593,7 +626,7 @@ module Cucumber
593
626
  :comment
594
627
  end
595
628
 
596
- def ==(_o)
629
+ def ==(_other)
597
630
  true
598
631
  end
599
632
 
@@ -4,7 +4,7 @@ module Cucumber
4
4
  module MultilineArgument
5
5
  class DocString < SimpleDelegator
6
6
  def append_to(array)
7
- array << self.to_s
7
+ array << to_s
8
8
  end
9
9
  end
10
10
  end
@@ -12,10 +12,10 @@ module Cucumber
12
12
  end
13
13
 
14
14
  def from(argument, location = nil, content_type = nil)
15
- location ||= Core::Ast::Location.of_caller
15
+ location ||= Core::Test::Location.of_caller
16
16
  case argument
17
17
  when String
18
- builder.doc_string(Core::Ast::DocString.new(argument, content_type, location))
18
+ builder.doc_string(Core::Test::DocString.new(argument, content_type))
19
19
  when Array
20
20
  location = location.on_line(argument.first.line..argument.last.line)
21
21
  builder.data_table(argument.map(&:cells), location)
@@ -52,11 +52,9 @@ module Cucumber
52
52
  end
53
53
 
54
54
  class None
55
- def append_to(array)
56
- end
55
+ def append_to(array); end
57
56
 
58
- def describe_to(visitor)
59
- end
57
+ def describe_to(visitor); end
60
58
  end
61
59
  end
62
60
  end
@@ -7,7 +7,7 @@ require 'cucumber/core/platform'
7
7
 
8
8
  module Cucumber
9
9
  unless defined?(Cucumber::VERSION)
10
- VERSION = File.read(File.expand_path('../version', __FILE__))
10
+ VERSION = File.read(File.expand_path('version', __dir__)).strip
11
11
  BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
12
12
  LIBDIR = File.expand_path(File.dirname(__FILE__) + '/../../lib')
13
13
  RAILS = defined?(Rails)
@@ -18,8 +18,8 @@ module Cucumber
18
18
  attr_accessor :use_full_backtrace
19
19
 
20
20
  # @private
21
- def file_mode(m, encoding = 'UTF-8')
22
- "#{m}:#{encoding}"
21
+ def file_mode(mode, encoding = 'UTF-8')
22
+ "#{mode}:#{encoding}"
23
23
  end
24
24
  end
25
25
  self.use_full_backtrace = false
@@ -5,9 +5,7 @@ require 'cucumber/gherkin/formatter/ansi_escapes'
5
5
  begin
6
6
  # Support Rake > 0.8.7
7
7
  require 'rake/dsl_definition'
8
- # rubocop:disable Lint/HandleExceptions
9
8
  rescue LoadError
10
- # rubocop:enable Lint/HandleExceptions
11
9
  end
12
10
 
13
11
  module Cucumber
@@ -38,8 +36,8 @@ module Cucumber
38
36
  attr_reader :args
39
37
 
40
38
  def initialize(libs, cucumber_opts, feature_files)
41
- raise 'libs must be an Array when running in-process' unless Array === libs
42
- libs.reverse.each { |lib| $LOAD_PATH.unshift(lib) }
39
+ raise 'libs must be an Array when running in-process' unless Array == libs.class
40
+ libs.reverse_each { |lib| $LOAD_PATH.unshift(lib) }
43
41
  @args = (
44
42
  cucumber_opts +
45
43
  feature_files
@@ -65,11 +63,11 @@ module Cucumber
65
63
  end
66
64
 
67
65
  def load_path
68
- [format('"%s"', @libs.join(File::PATH_SEPARATOR))]
66
+ [format('"%<path>s"', path: @libs.join(File::PATH_SEPARATOR))]
69
67
  end
70
68
 
71
69
  def quoted_binary(cucumber_bin)
72
- [format('"%s"', cucumber_bin)]
70
+ [format('"%<path>s"', path: cucumber_bin)]
73
71
  end
74
72
 
75
73
  def use_bundler
@@ -98,9 +96,7 @@ module Cucumber
98
96
 
99
97
  def run
100
98
  sh cmd.join(' ') do |ok, res|
101
- if !ok
102
- exit res.exitstatus
103
- end
99
+ exit res.exitstatus unless ok
104
100
  end
105
101
  end
106
102
  end
@@ -113,9 +109,9 @@ module Cucumber
113
109
 
114
110
  # Extra options to pass to the cucumber binary. Can be overridden by the CUCUMBER_OPTS environment variable.
115
111
  # It's recommended to pass an Array, but if it's a String it will be #split by ' '.
116
- attr_accessor :cucumber_opts
112
+ attr_reader :cucumber_opts
117
113
  def cucumber_opts=(opts) #:nodoc:
118
- @cucumber_opts = String === opts ? opts.split(' ') : opts
114
+ @cucumber_opts = String == opts.class ? opts.split(' ') : opts
119
115
  end
120
116
 
121
117
  # Whether or not to fork a new ruby interpreter. Defaults to true. You may gain
@@ -134,12 +130,16 @@ module Cucumber
134
130
  # Note that this attribute has no effect if you don't run in forked mode.
135
131
  attr_accessor :bundler
136
132
 
133
+ # Name of the running task
134
+ attr_reader :task_name
135
+
137
136
  # Define Cucumber Rake task
138
137
  def initialize(task_name = 'cucumber', desc = 'Run Cucumber features')
139
- @task_name, @desc = task_name, desc
138
+ @task_name = task_name
139
+ @desc = desc
140
140
  @fork = true
141
141
  @libs = ['lib']
142
- @rcov_opts = %w{--rails --exclude osx\/objc,gems\/}
142
+ @rcov_opts = %w[--rails --exclude osx\/objc,gems\/]
143
143
  yield self if block_given?
144
144
  @binary = binary.nil? ? Cucumber::BINARY : File.expand_path(binary)
145
145
  define_task
@@ -154,18 +154,16 @@ module Cucumber
154
154
 
155
155
  def runner(_task_args = nil) #:nodoc:
156
156
  cucumber_opts = [(ENV['CUCUMBER_OPTS'] ? ENV['CUCUMBER_OPTS'].split(/\s+/) : nil) || cucumber_opts_with_profile]
157
- if @fork
158
- return ForkedCucumberRunner.new(libs, binary, cucumber_opts, bundler, feature_files)
159
- end
157
+ return ForkedCucumberRunner.new(libs, binary, cucumber_opts, bundler, feature_files) if fork
160
158
  InProcessCucumberRunner.new(libs, cucumber_opts, feature_files)
161
159
  end
162
160
 
163
161
  def cucumber_opts_with_profile #:nodoc:
164
- Array(cucumber_opts).concat Array(@profile).flat_map { |p| ['--profile', p] }
162
+ Array(cucumber_opts).concat(Array(@profile).flat_map { |p| ['--profile', p] })
165
163
  end
166
164
 
167
165
  def feature_files #:nodoc:
168
- make_command_line_safe(FileList[ ENV['FEATURE'] || [] ])
166
+ make_command_line_safe(FileList[ENV['FEATURE'] || []])
169
167
  end
170
168
 
171
169
  def make_command_line_safe(list)
@@ -9,16 +9,17 @@ module Spec #:nodoc:
9
9
  # will fail when running cucumber)
10
10
  class OptionParser < ::OptionParser #:nodoc:
11
11
  NEUTERED_RSPEC = Object.new
12
- def NEUTERED_RSPEC.method_missing(_m, *_args); self; end
12
+ def NEUTERED_RSPEC.method_missing(_method, *_args) # rubocop:disable Style/MissingRespondToMissing
13
+ self || super
14
+ end
13
15
 
14
- def self.method_added(m)
15
- unless @__neutering_rspec
16
- @__neutering_rspec = true
17
- define_method(m) do |*a|
18
- NEUTERED_RSPEC
19
- end
20
- @__neutering_rspec = false
16
+ def self.method_added(method)
17
+ return if @__neutering_rspec
18
+ @__neutering_rspec = true
19
+ define_method(method) do |*_a|
20
+ NEUTERED_RSPEC
21
21
  end
22
+ @__neutering_rspec = false
22
23
  end
23
24
  end
24
25
  end
@@ -13,9 +13,7 @@ Before do
13
13
  end
14
14
 
15
15
  After do
16
- begin
17
- RSpec::Mocks.verify
18
- ensure
19
- RSpec::Mocks.teardown
20
- end
16
+ RSpec::Mocks.verify
17
+ ensure
18
+ RSpec::Mocks.teardown
21
19
  end
@@ -15,45 +15,12 @@ module Cucumber
15
15
  # the passed / failed / undefined / skipped status of
16
16
  # the test case.
17
17
  #
18
- # The test case might come from a regular Scenario or
19
- # a Scenario outline. You can call the `#outline?`
20
- # predicate to find out. If it's from an outline,
21
- # you get a couple of extra methods.
22
18
  module RunningTestCase
23
19
  def self.new(test_case)
24
- Builder.new(test_case).running_test_case
20
+ TestCase.new(test_case)
25
21
  end
26
22
 
27
- class Builder
28
- def initialize(test_case)
29
- @test_case = test_case
30
- test_case.describe_source_to(self)
31
- end
32
-
33
- def feature(feature)
34
- end
35
-
36
- def scenario(_scenario)
37
- @factory = Scenario
38
- end
39
-
40
- def scenario_outline(_scenario)
41
- @factory = ScenarioOutlineExample
42
- end
43
-
44
- def examples_table(examples_table)
45
- end
46
-
47
- def examples_table_row(row)
48
- end
49
-
50
- def running_test_case
51
- @factory.new(@test_case)
52
- end
53
- end
54
- private_constant :Builder
55
-
56
- class Scenario < SimpleDelegator
23
+ class TestCase < SimpleDelegator
57
24
  def initialize(test_case, result = Core::Test::Result::Unknown.new)
58
25
  @test_case = test_case
59
26
  @result = result
@@ -85,27 +52,9 @@ module Cucumber
85
52
  tags.map &:name
86
53
  end
87
54
 
88
- def outline?
89
- false
90
- end
91
-
92
55
  def with_result(result)
93
56
  self.class.new(@test_case, result)
94
57
  end
95
58
  end
96
-
97
- class ScenarioOutlineExample < Scenario
98
- def outline?
99
- true
100
- end
101
-
102
- def scenario_outline
103
- self
104
- end
105
-
106
- def cell_values
107
- source.last.values
108
- end
109
- end
110
59
  end
111
60
  end
@@ -3,23 +3,27 @@
3
3
  module Cucumber
4
4
  class Runtime
5
5
  class AfterHooks
6
- def initialize(hooks, scenario)
6
+ def initialize(id_generator, hooks, scenario, event_bus)
7
7
  @hooks = hooks
8
8
  @scenario = scenario
9
+ @id_generator = id_generator
10
+ @event_bus = event_bus
9
11
  end
10
12
 
11
13
  def apply_to(test_case)
12
14
  test_case.with_steps(
13
- test_case.test_steps + after_hooks(test_case.source).reverse
15
+ test_case.test_steps + after_hooks.reverse
14
16
  )
15
17
  end
16
18
 
17
19
  private
18
20
 
19
- def after_hooks(source)
21
+ def after_hooks
20
22
  @hooks.map do |hook|
21
23
  action = ->(result) { hook.invoke('After', @scenario.with_result(result)) }
22
- Hooks.after_hook(source, hook.location, &action)
24
+ hook_step = Hooks.after_hook(@id_generator.new_id, hook.location, &action)
25
+ @event_bus.hook_test_step_created(hook_step, hook)
26
+ hook_step
23
27
  end
24
28
  end
25
29
  end
@@ -5,23 +5,27 @@ require 'cucumber/hooks'
5
5
  module Cucumber
6
6
  class Runtime
7
7
  class BeforeHooks
8
- def initialize(hooks, scenario)
8
+ def initialize(id_generator, hooks, scenario, event_bus)
9
9
  @hooks = hooks
10
10
  @scenario = scenario
11
+ @id_generator = id_generator
12
+ @event_bus = event_bus
11
13
  end
12
14
 
13
15
  def apply_to(test_case)
14
16
  test_case.with_steps(
15
- before_hooks(test_case.source) + test_case.test_steps
17
+ before_hooks + test_case.test_steps
16
18
  )
17
19
  end
18
20
 
19
21
  private
20
22
 
21
- def before_hooks(source)
23
+ def before_hooks
22
24
  @hooks.map do |hook|
23
25
  action_block = ->(result) { hook.invoke('Before', @scenario.with_result(result)) }
24
- Hooks.before_hook(source, hook.location, &action_block)
26
+ hook_step = Hooks.before_hook(@id_generator.new_id, hook.location, &action_block)
27
+ @event_bus.hook_test_step_created(hook_step, hook)
28
+ hook_step
25
29
  end
26
30
  end
27
31
  end