cucumber 2.0.0.beta.3 → 2.0.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/.travis.yml +3 -3
- data/History.md +131 -32
- data/Rakefile +0 -2
- data/cucumber.gemspec +4 -3
- data/examples/i18n/ht/Rakefile +6 -0
- data/examples/i18n/ht/features/adisyon.feature +17 -0
- data/examples/i18n/ht/features/divizyon.feature +10 -0
- data/examples/i18n/ht/features/step_definitions/kalkilatris_steps.rb +25 -0
- data/examples/i18n/ht/lib/kalkilatris.rb +14 -0
- data/examples/tcl/features/step_definitions/fib_steps.rb +1 -1
- data/features/docs/cli/dry_run.feature +48 -0
- data/features/docs/cli/exclude_files.feature +1 -2
- data/features/docs/cli/run_specific_scenarios.feature +28 -66
- data/features/docs/cli/strict_mode.feature +24 -1
- data/features/docs/defining_steps/nested_steps.feature +49 -0
- data/features/docs/defining_steps/skip_scenario.feature +31 -2
- data/features/docs/defining_steps/snippets.feature +15 -0
- data/features/docs/exception_in_after_step_hook.feature +1 -1
- data/features/docs/exception_in_around_hook.feature +80 -0
- data/features/docs/extending_cucumber/custom_filter.feature +29 -0
- data/features/docs/extending_cucumber/custom_formatter.feature +65 -7
- data/features/docs/formatters/debug_formatter.feature +24 -17
- data/features/docs/formatters/json_formatter.feature +65 -1
- data/features/docs/formatters/junit_formatter.feature +40 -0
- data/features/docs/formatters/pretty_formatter.feature +42 -0
- data/features/docs/formatters/rerun_formatter.feature +3 -2
- data/features/docs/getting_started.feature +1 -1
- data/features/docs/{wire_protocol_erb.feature → wire_protocol/erb_configuration.feature} +2 -2
- data/features/docs/wire_protocol/handle_unexpected_response.feature +30 -0
- data/features/docs/wire_protocol/invoke_message.feature +216 -0
- data/features/docs/wire_protocol/readme.md +26 -0
- data/features/docs/wire_protocol/snippets_message.feature +51 -0
- data/features/docs/wire_protocol/step_matches_message.feature +81 -0
- data/features/docs/{wire_protocol_table_diffing.feature → wire_protocol/table_diffing.feature} +1 -0
- data/features/docs/{wire_protocol_tags.feature → wire_protocol/tags.feature} +1 -0
- data/features/docs/{wire_protocol_timeouts.feature → wire_protocol/timeouts.feature} +1 -0
- data/features/docs/work_in_progress.feature +1 -1
- data/features/docs/writing_support_code/after_hooks.feature +24 -0
- data/features/docs/writing_support_code/around_hooks.feature +31 -0
- data/features/docs/writing_support_code/before_hook.feature +7 -3
- data/features/docs/writing_support_code/tagged_hooks.feature +44 -6
- data/features/lib/step_definitions/wire_steps.rb +18 -1
- data/features/lib/support/fake_wire_server.rb +10 -7
- data/lib/cucumber/cli/configuration.rb +6 -11
- data/lib/cucumber/cli/main.rb +2 -2
- data/lib/cucumber/cli/options.rb +8 -1
- data/lib/cucumber/cli/profile_loader.rb +1 -1
- data/lib/cucumber/core_ext/instance_exec.rb +1 -1
- data/lib/cucumber/encoding.rb +5 -0
- data/lib/cucumber/errors.rb +8 -0
- data/lib/cucumber/file_specs.rb +3 -1
- data/lib/cucumber/filters/activate_steps.rb +33 -0
- data/lib/cucumber/filters/apply_after_hooks.rb +9 -0
- data/lib/cucumber/filters/apply_after_step_hooks.rb +12 -0
- data/lib/cucumber/filters/apply_around_hooks.rb +12 -0
- data/lib/cucumber/filters/apply_before_hooks.rb +9 -0
- data/lib/cucumber/{runtime → filters}/gated_receiver.rb +5 -1
- data/lib/cucumber/filters/prepare_world.rb +45 -0
- data/lib/cucumber/filters/quit.rb +28 -0
- data/lib/cucumber/filters/randomizer.rb +40 -0
- data/lib/cucumber/{runtime → filters}/tag_limits/test_case_index.rb +4 -2
- data/lib/cucumber/{runtime → filters}/tag_limits/verifier.rb +4 -2
- data/lib/cucumber/filters/tag_limits.rb +45 -0
- data/lib/cucumber/filters.rb +9 -0
- data/lib/cucumber/formatter/ansicolor.rb +0 -8
- data/lib/cucumber/formatter/console.rb +37 -20
- data/lib/cucumber/formatter/debug.rb +1 -8
- data/lib/cucumber/formatter/fanout.rb +27 -0
- data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +10 -9
- data/lib/cucumber/formatter/html.rb +31 -6
- data/lib/cucumber/formatter/ignore_missing_messages.rb +20 -0
- data/lib/cucumber/formatter/junit.rb +97 -2
- data/lib/cucumber/formatter/legacy_api/adapter.rb +1060 -0
- data/lib/cucumber/formatter/legacy_api/ast.rb +376 -0
- data/lib/cucumber/formatter/legacy_api/results.rb +51 -0
- data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +30 -0
- data/lib/cucumber/formatter/pretty.rb +14 -0
- data/lib/cucumber/formatter/progress.rb +10 -0
- data/lib/cucumber/formatter/rerun.rb +14 -88
- data/lib/cucumber/hooks.rb +97 -0
- data/lib/cucumber/language_support/language_methods.rb +0 -54
- data/lib/cucumber/multiline_argument/data_table.rb +41 -29
- data/lib/cucumber/platform.rb +3 -3
- data/lib/cucumber/project_initializer.rb +43 -0
- data/lib/cucumber/rb_support/rb_hook.rb +2 -2
- data/lib/cucumber/rb_support/rb_step_definition.rb +11 -2
- data/lib/cucumber/rb_support/rb_transform.rb +3 -1
- data/lib/cucumber/rb_support/rb_world.rb +2 -2
- data/lib/cucumber/rb_support/snippet.rb +1 -1
- data/lib/cucumber/rspec/doubles.rb +1 -1
- data/lib/cucumber/running_test_case.rb +115 -0
- data/lib/cucumber/runtime/after_hooks.rb +24 -0
- data/lib/cucumber/runtime/before_hooks.rb +23 -0
- data/lib/cucumber/runtime/for_programming_languages.rb +4 -8
- data/lib/cucumber/runtime/step_hooks.rb +22 -0
- data/lib/cucumber/runtime/support_code.rb +70 -5
- data/lib/cucumber/runtime.rb +56 -112
- data/lib/cucumber/step_match.rb +26 -2
- data/lib/cucumber.rb +7 -3
- data/spec/cucumber/cli/configuration_spec.rb +16 -1
- data/spec/cucumber/cli/profile_loader_spec.rb +10 -0
- data/spec/cucumber/core_ext/instance_exec_spec.rb +4 -0
- data/spec/cucumber/file_specs_spec.rb +21 -2
- data/spec/cucumber/filters/activate_steps_spec.rb +57 -0
- data/spec/cucumber/{runtime → filters}/gated_receiver_spec.rb +3 -3
- data/spec/cucumber/{runtime → filters}/tag_limits/test_case_index_spec.rb +3 -3
- data/spec/cucumber/{runtime → filters}/tag_limits/verifier_spec.rb +4 -4
- data/spec/cucumber/{runtime/tag_limits/filter_spec.rb → filters/tag_limits_spec.rb} +6 -6
- data/spec/cucumber/formatter/debug_spec.rb +25 -530
- data/spec/cucumber/formatter/html_spec.rb +140 -0
- data/spec/cucumber/formatter/junit_spec.rb +212 -156
- data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +2090 -0
- data/spec/cucumber/formatter/pretty_spec.rb +248 -2
- data/spec/cucumber/formatter/rerun_spec.rb +107 -0
- data/spec/cucumber/formatter/spec_helper.rb +17 -8
- data/spec/cucumber/hooks_spec.rb +30 -0
- data/spec/cucumber/multiline_argument/data_table_spec.rb +53 -47
- data/spec/cucumber/project_initializer_spec.rb +87 -0
- data/spec/cucumber/rb_support/rb_language_spec.rb +2 -2
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +32 -7
- data/spec/cucumber/rb_support/rb_transform_spec.rb +20 -0
- data/spec/cucumber/rb_support/snippet_spec.rb +6 -6
- data/spec/cucumber/running_test_case_spec.rb +83 -0
- data/spec/cucumber/runtime_spec.rb +1 -5
- data/spec/spec_helper.rb +3 -4
- metadata +149 -107
- data/bin/cuke +0 -60
- data/features/docs/extending_cucumber/formatter_callbacks.feature +0 -370
- data/features/docs/output_from_hooks.feature +0 -128
- data/features/docs/report_called_undefined_steps.feature +0 -57
- data/features/docs/wire_protocol.feature +0 -337
- data/gem_tasks/yard/default/layout/html/bubble_32x32.png +0 -0
- data/gem_tasks/yard/default/layout/html/footer.erb +0 -5
- data/gem_tasks/yard/default/layout/html/index.erb +0 -1
- data/gem_tasks/yard/default/layout/html/layout.erb +0 -25
- data/gem_tasks/yard/default/layout/html/logo.erb +0 -1
- data/gem_tasks/yard/default/layout/html/setup.rb +0 -4
- data/gem_tasks/yard.rake +0 -43
- data/lib/cucumber/mappings.rb +0 -238
- data/lib/cucumber/reports/legacy_formatter.rb +0 -1349
- data/lib/cucumber/runtime/results.rb +0 -64
- data/lib/cucumber/runtime/tag_limits/filter.rb +0 -31
- data/lib/cucumber/runtime/tag_limits.rb +0 -15
- data/spec/cucumber/mappings_spec.rb +0 -180
- data/spec/cucumber/reports/legacy_formatter_spec.rb +0 -1860
- data/spec/cucumber/runtime/results_spec.rb +0 -88
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
require 'cucumber/core/test/around_hook'
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
|
|
5
|
+
# Hooks quack enough like `Cucumber::Core::Ast` source nodes that we can use them as
|
|
6
|
+
# source for test steps
|
|
7
|
+
module Hooks
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def before_hook(source, &block)
|
|
11
|
+
build_hook_step(source, block, BeforeHook, Core::Test::UnskippableAction)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def after_hook(source, &block)
|
|
15
|
+
build_hook_step(source, block, AfterHook, Core::Test::UnskippableAction)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def after_step_hook(source, &block)
|
|
19
|
+
raise ArgumentError unless source.last.kind_of?(Core::Ast::Step)
|
|
20
|
+
build_hook_step(source, block, AfterStepHook, Core::Test::Action)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def around_hook(source, &block)
|
|
24
|
+
Core::Test::AroundHook.new(&block)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def build_hook_step(source, block, hook_type, action_type)
|
|
30
|
+
action = action_type.new(&block)
|
|
31
|
+
hook = hook_type.new(action.location)
|
|
32
|
+
Core::Test::Step.new(source + [hook], action)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class AfterHook
|
|
37
|
+
attr_reader :location
|
|
38
|
+
|
|
39
|
+
def initialize(location)
|
|
40
|
+
@location = location
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def name
|
|
44
|
+
"After hook"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def match_locations?(queried_locations)
|
|
48
|
+
queried_locations.any? { |other_location| other_location.match?(location) }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def describe_to(visitor, *args)
|
|
52
|
+
visitor.after_hook(self, *args)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class BeforeHook
|
|
57
|
+
attr_reader :location
|
|
58
|
+
|
|
59
|
+
def initialize(location)
|
|
60
|
+
@location = location
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def name
|
|
64
|
+
"Before hook"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def match_locations?(queried_locations)
|
|
68
|
+
queried_locations.any? { |other_location| other_location.match?(location) }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def describe_to(visitor, *args)
|
|
72
|
+
visitor.before_hook(self, *args)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class AfterStepHook
|
|
77
|
+
attr_reader :location
|
|
78
|
+
|
|
79
|
+
def initialize(location)
|
|
80
|
+
@location = location
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def name
|
|
84
|
+
"AfterStep hook"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def match_locations?(queried_locations)
|
|
88
|
+
queried_locations.any? { |other_location| other_location.match?(location) }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def describe_to(visitor, *args)
|
|
92
|
+
visitor.after_step_hook(self, *args)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -4,21 +4,6 @@ require 'cucumber/step_definition_light'
|
|
|
4
4
|
module Cucumber
|
|
5
5
|
module LanguageSupport
|
|
6
6
|
module LanguageMethods
|
|
7
|
-
def around(scenario)
|
|
8
|
-
execute_around(scenario) do
|
|
9
|
-
yield
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def before(scenario)
|
|
14
|
-
begin_scenario(scenario)
|
|
15
|
-
execute_before(scenario)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def after(scenario)
|
|
19
|
-
execute_after(scenario)
|
|
20
|
-
end_scenario
|
|
21
|
-
end
|
|
22
7
|
|
|
23
8
|
def after_configuration(configuration)
|
|
24
9
|
hooks[:after_configuration].each do |hook|
|
|
@@ -26,12 +11,6 @@ module Cucumber
|
|
|
26
11
|
end
|
|
27
12
|
end
|
|
28
13
|
|
|
29
|
-
def execute_after_step(scenario)
|
|
30
|
-
hooks_for(:after_step, scenario).each do |hook|
|
|
31
|
-
invoke(hook, 'AfterStep', scenario)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
14
|
def execute_transforms(args)
|
|
36
15
|
args.map do |arg|
|
|
37
16
|
matching_transform = transforms.detect {|transform| transform.match(arg) }
|
|
@@ -87,39 +66,6 @@ module Cucumber
|
|
|
87
66
|
@transforms ||= []
|
|
88
67
|
end
|
|
89
68
|
|
|
90
|
-
def execute_around(scenario, &block)
|
|
91
|
-
hooks_for(:around, scenario).reverse.inject(block) do |blk, hook|
|
|
92
|
-
proc do
|
|
93
|
-
invoke(hook, 'Around', scenario, true) do
|
|
94
|
-
blk.call(scenario)
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end.call
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def execute_before(scenario)
|
|
101
|
-
hooks_for(:before, scenario).each do |hook|
|
|
102
|
-
invoke(hook, 'Before', scenario, true)
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def execute_after(scenario)
|
|
107
|
-
hooks_for(:after, scenario).reverse_each do |hook|
|
|
108
|
-
invoke(hook, 'After', scenario, true)
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def invoke(hook, location, scenario, exception_fails_scenario, &block)
|
|
113
|
-
begin
|
|
114
|
-
hook.invoke(location, scenario, &block)
|
|
115
|
-
rescue Exception => exception
|
|
116
|
-
if exception_fails_scenario
|
|
117
|
-
scenario.fail!(exception)
|
|
118
|
-
else
|
|
119
|
-
raise
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
69
|
end
|
|
124
70
|
end
|
|
125
71
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'forwardable'
|
|
1
2
|
require 'gherkin/formatter/escaping'
|
|
2
3
|
require 'cucumber/core/ast/describes_itself'
|
|
3
4
|
|
|
@@ -46,34 +47,50 @@ module Cucumber
|
|
|
46
47
|
|
|
47
48
|
include Enumerable
|
|
48
49
|
include Core::Ast::DescribesItself
|
|
50
|
+
extend Forwardable
|
|
49
51
|
|
|
50
52
|
NULL_CONVERSIONS = Hash.new({ :strict => false, :proc => lambda{ |cell_value| cell_value } }).freeze
|
|
51
53
|
|
|
52
54
|
attr_accessor :file
|
|
55
|
+
def_delegator :@ast_table, :location
|
|
53
56
|
|
|
54
57
|
def self.default_arg_name #:nodoc:
|
|
55
58
|
"table"
|
|
56
59
|
end
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
class << self
|
|
62
|
+
def from(data, location = Core::Ast::Location.of_caller)
|
|
63
|
+
case data
|
|
64
|
+
when Array
|
|
65
|
+
from_array(data, location)
|
|
66
|
+
when String
|
|
67
|
+
parse(data, location)
|
|
68
|
+
else
|
|
69
|
+
raise ArgumentError, "expected data to be a String or an Array."
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
def parse(text, location = Core::Ast::Location.of_caller)
|
|
75
|
+
builder = Builder.new
|
|
76
|
+
lexer = Gherkin::Lexer::I18nLexer.new(builder)
|
|
77
|
+
lexer.scan(text)
|
|
78
|
+
from_array(builder.rows, location)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def from_array(data, location = Core::Ast::Location.of_caller)
|
|
82
|
+
new Core::Ast::DataTable.new(data, location)
|
|
83
|
+
end
|
|
63
84
|
end
|
|
64
85
|
|
|
65
|
-
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
86
|
+
|
|
87
|
+
# @param data [Core::Ast::DataTable] the data for the table
|
|
88
|
+
# @param conversion_procs [Hash] see map_columns!
|
|
89
|
+
# @param header_mappings [Hash] see map_headers!
|
|
90
|
+
# @param header_conversion_proc [Proc] see map_headers!
|
|
70
91
|
def initialize(data, conversion_procs = NULL_CONVERSIONS.dup, header_mappings = {}, header_conversion_proc = nil)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
data
|
|
74
|
-
when Array
|
|
75
|
-
Core::Ast::DataTable.new(data, Core::Ast::Location.of_caller)
|
|
76
|
-
end
|
|
92
|
+
raise ArgumentError, "data must be a Core::Ast::DataTable" unless data.kind_of? Core::Ast::DataTable
|
|
93
|
+
ast_table = data
|
|
77
94
|
# Verify that it's square
|
|
78
95
|
ast_table.transpose
|
|
79
96
|
@cell_matrix = create_cell_matrix(ast_table)
|
|
@@ -95,7 +112,7 @@ module Cucumber
|
|
|
95
112
|
# registered with #map_column! and #map_headers!.
|
|
96
113
|
#
|
|
97
114
|
def dup
|
|
98
|
-
self.class.new(raw
|
|
115
|
+
self.class.new(Core::Ast::DataTable.new(raw, location), @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
|
|
99
116
|
end
|
|
100
117
|
|
|
101
118
|
# Returns a new, transposed table. Example:
|
|
@@ -110,7 +127,7 @@ module Cucumber
|
|
|
110
127
|
# | 4 | 2 |
|
|
111
128
|
#
|
|
112
129
|
def transpose
|
|
113
|
-
self.class.new(raw.transpose, @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
|
|
130
|
+
self.class.new(Core::Ast::DataTable.new(raw.transpose, location), @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
|
|
114
131
|
end
|
|
115
132
|
|
|
116
133
|
# Converts this table into an Array of Hash where the keys of each
|
|
@@ -237,7 +254,7 @@ module Cucumber
|
|
|
237
254
|
|
|
238
255
|
# Returns a new Table where the headers are redefined. See #map_headers!
|
|
239
256
|
def map_headers(mappings={}, &block)
|
|
240
|
-
self.class.new
|
|
257
|
+
self.class.new(Core::Ast::DataTable.new(raw, location), @conversion_procs.dup, mappings, block)
|
|
241
258
|
end
|
|
242
259
|
|
|
243
260
|
# Change how #hashes converts column values. The +column_name+ argument identifies the column
|
|
@@ -262,7 +279,7 @@ module Cucumber
|
|
|
262
279
|
def map_column(column_name, strict=true, &conversion_proc)
|
|
263
280
|
conversion_procs = @conversion_procs.dup
|
|
264
281
|
conversion_procs[column_name.to_s] = { :strict => strict, :proc => conversion_proc }
|
|
265
|
-
self.class.new(raw
|
|
282
|
+
self.class.new(Core::Ast::DataTable.new(raw, location), conversion_procs, @header_mappings.dup, @header_conversion_proc)
|
|
266
283
|
end
|
|
267
284
|
|
|
268
285
|
# Compares +other_table+ to self. If +other_table+ contains columns
|
|
@@ -427,8 +444,9 @@ module Cucumber
|
|
|
427
444
|
end
|
|
428
445
|
|
|
429
446
|
def to_s(options = {}) #:nodoc:
|
|
447
|
+
# TODO: factor out this code so we don't depend on such a big lump of old cruft
|
|
430
448
|
require 'cucumber/formatter/pretty'
|
|
431
|
-
require 'cucumber/
|
|
449
|
+
require 'cucumber/formatter/legacy_api/adapter'
|
|
432
450
|
options = {:color => true, :indent => 2, :prefixes => TO_S_PREFIXES}.merge(options)
|
|
433
451
|
io = StringIO.new
|
|
434
452
|
|
|
@@ -436,19 +454,13 @@ module Cucumber
|
|
|
436
454
|
Cucumber::Term::ANSIColor.coloring = options[:color]
|
|
437
455
|
formatter = Formatter::Pretty.new(nil, io, options)
|
|
438
456
|
formatter.instance_variable_set('@indent', options[:indent])
|
|
439
|
-
|
|
440
|
-
Reports::Legacy::Ast::MultilineArg.for(self).accept(Reports::FormatterWrapper.new([formatter]))
|
|
441
|
-
|
|
457
|
+
Formatter::LegacyApi::Ast::MultilineArg.for(self).accept(Formatter::Fanout.new([formatter]))
|
|
442
458
|
Cucumber::Term::ANSIColor.coloring = c
|
|
443
459
|
io.rewind
|
|
444
460
|
s = "\n" + io.read + (" " * (options[:indent] - 2))
|
|
445
461
|
s
|
|
446
462
|
end
|
|
447
463
|
|
|
448
|
-
def location
|
|
449
|
-
@ast_table.location
|
|
450
|
-
end
|
|
451
|
-
|
|
452
464
|
def description_for_visitors
|
|
453
465
|
:legacy_table
|
|
454
466
|
end
|
|
@@ -586,7 +598,7 @@ module Cucumber
|
|
|
586
598
|
|
|
587
599
|
def ensure_table(table_or_array) #:nodoc:
|
|
588
600
|
return table_or_array if DataTable === table_or_array
|
|
589
|
-
DataTable.
|
|
601
|
+
DataTable.from(table_or_array)
|
|
590
602
|
end
|
|
591
603
|
|
|
592
604
|
def ensure_array_of_array(array)
|
data/lib/cucumber/platform.rb
CHANGED
|
@@ -4,16 +4,16 @@ require 'rbconfig'
|
|
|
4
4
|
|
|
5
5
|
module Cucumber
|
|
6
6
|
unless defined?(Cucumber::VERSION)
|
|
7
|
-
VERSION = '2.0.0
|
|
7
|
+
VERSION = '2.0.0'
|
|
8
8
|
BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
|
|
9
9
|
LIBDIR = File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
|
10
10
|
JRUBY = defined?(JRUBY_VERSION)
|
|
11
|
-
IRONRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == "ironruby"
|
|
12
11
|
WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
|
13
12
|
OS_X = RbConfig::CONFIG['host_os'] =~ /darwin/
|
|
14
|
-
WINDOWS_MRI = WINDOWS && !JRUBY
|
|
13
|
+
WINDOWS_MRI = WINDOWS && !JRUBY
|
|
15
14
|
RAILS = defined?(Rails)
|
|
16
15
|
RUBY_BINARY = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
|
|
16
|
+
RUBY_2_2 = RUBY_VERSION =~ /^2\.2/
|
|
17
17
|
RUBY_2_1 = RUBY_VERSION =~ /^2\.1/
|
|
18
18
|
RUBY_2_0 = RUBY_VERSION =~ /^2\.0/
|
|
19
19
|
RUBY_1_9 = RUBY_VERSION =~ /^1\.9/
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
|
|
3
|
+
# Generates generic file structure for a cucumber project
|
|
4
|
+
class ProjectInitializer
|
|
5
|
+
def run
|
|
6
|
+
create_directory('features')
|
|
7
|
+
create_directory('features/step_definitions')
|
|
8
|
+
create_directory('features/support')
|
|
9
|
+
create_file('features/support/env.rb')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def create_directory(dir_name)
|
|
15
|
+
create_directory_or_file dir_name, true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_file(file_name)
|
|
19
|
+
create_directory_or_file file_name, false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_directory_or_file(file_name, directory)
|
|
23
|
+
file_type = if directory
|
|
24
|
+
:mkdir_p
|
|
25
|
+
else
|
|
26
|
+
:touch
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
report_exists(file_name) || return if File.exists?(file_name)
|
|
30
|
+
|
|
31
|
+
report_creating(file_name)
|
|
32
|
+
FileUtils.send file_type, file_name
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def report_exists(file)
|
|
36
|
+
puts " exist #{file}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def report_creating(file)
|
|
40
|
+
puts " create #{file}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -10,8 +10,8 @@ module Cucumber
|
|
|
10
10
|
@proc = proc
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def invoke(
|
|
14
|
-
@rb_language.current_world.cucumber_instance_exec(false,
|
|
13
|
+
def invoke(pseudo_method, arguments, &block)
|
|
14
|
+
@rb_language.current_world.cucumber_instance_exec(false, pseudo_method, *[arguments, block].compact, &@proc)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -44,10 +44,19 @@ module Cucumber
|
|
|
44
44
|
raise ArgumentError unless proc_or_sym.is_a?(Symbol)
|
|
45
45
|
message = proc_or_sym
|
|
46
46
|
target_proc = parse_target_proc_from(options)
|
|
47
|
-
lambda
|
|
47
|
+
patch_location_onto lambda { |*args|
|
|
48
48
|
target = instance_exec(&target_proc)
|
|
49
49
|
target.send(message, *args)
|
|
50
|
-
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def patch_location_onto(block)
|
|
54
|
+
file, line = caller[5].split(':')[0..1]
|
|
55
|
+
location = Core::Ast::Location.new(
|
|
56
|
+
Pathname.new(file).relative_path_from(Pathname.new(Dir.pwd)),
|
|
57
|
+
line)
|
|
58
|
+
block.define_singleton_method(:file_colon_line) { location.to_s }
|
|
59
|
+
block
|
|
51
60
|
end
|
|
52
61
|
|
|
53
62
|
def parse_target_proc_from(options)
|
|
@@ -37,7 +37,7 @@ module Cucumber
|
|
|
37
37
|
# @param [String,Cucumber::Ast::DocString,Cucumber::Ast::Table] multiline_argument
|
|
38
38
|
def step(name, raw_multiline_arg=nil)
|
|
39
39
|
location = Core::Ast::Location.of_caller
|
|
40
|
-
@__cucumber_runtime.
|
|
40
|
+
@__cucumber_runtime.invoke_dynamic_step(name, MultilineArgument.from(raw_multiline_arg, location))
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
# Run a snippet of Gherkin
|
|
@@ -48,7 +48,7 @@ module Cucumber
|
|
|
48
48
|
# }
|
|
49
49
|
# @param [String] steps_text The Gherkin snippet to run
|
|
50
50
|
def steps(steps_text)
|
|
51
|
-
@__cucumber_runtime.
|
|
51
|
+
@__cucumber_runtime.invoke_dynamic_steps(steps_text, @__natural_language, caller[0])
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# Parse Gherkin into a {Cucumber::Ast::Table} object.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'delegate'
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
# Represents the current status of a running test case.
|
|
5
|
+
#
|
|
6
|
+
# This wraps a `Cucumber::Core::Test::Case` and delegates
|
|
7
|
+
# many methods to that object.
|
|
8
|
+
#
|
|
9
|
+
# We decorete the core object with the current result.
|
|
10
|
+
# In the first Before hook of a scenario, this will be an
|
|
11
|
+
# instance of `Cucumber::Core::Test::Result::Unknown`
|
|
12
|
+
# but as the scenario runs, it will be updated to reflect
|
|
13
|
+
# the passed / failed / undefined / skipped status of
|
|
14
|
+
# the test case.
|
|
15
|
+
#
|
|
16
|
+
# The test case might come from a regular Scenario or
|
|
17
|
+
# a Scenario outline. You can call the `#outline?`
|
|
18
|
+
# predicate to find out. If it's from an outline,
|
|
19
|
+
# you get a couple of extra methods.
|
|
20
|
+
module RunningTestCase
|
|
21
|
+
def self.new(test_case)
|
|
22
|
+
Builder.new(test_case).result
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class Builder
|
|
26
|
+
def initialize(test_case)
|
|
27
|
+
@test_case = test_case
|
|
28
|
+
test_case.describe_source_to(self)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def feature(feature)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def scenario(scenario)
|
|
35
|
+
@factory = Scenario
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def scenario_outline(scenario)
|
|
39
|
+
@factory = ScenarioOutlineExample
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def examples_table(examples_table)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def examples_table_row(row)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def result
|
|
49
|
+
@factory.new(@test_case)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
private_constant :Builder
|
|
53
|
+
|
|
54
|
+
class Scenario < SimpleDelegator
|
|
55
|
+
def initialize(test_case, result = Core::Test::Result::Unknown.new)
|
|
56
|
+
@test_case = test_case
|
|
57
|
+
@result = result
|
|
58
|
+
super test_case
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def accept_hook?(hook)
|
|
62
|
+
hook.tag_expressions.all? { |expression| @test_case.match_tags?(expression) }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def failed?
|
|
66
|
+
@result.failed?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def passed?
|
|
70
|
+
!failed?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def title
|
|
74
|
+
warn("deprecated: call #name instead")
|
|
75
|
+
name
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def source_tags
|
|
79
|
+
#warn('deprecated: call #tags instead')
|
|
80
|
+
tags
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def source_tag_names
|
|
84
|
+
tags.map &:name
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def skip_invoke!
|
|
88
|
+
Cucumber.deprecate(self.class.name, __method__, "Call #skip_this_scenario on the World directly")
|
|
89
|
+
raise Cucumber::Core::Test::Result::Skipped
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def outline?
|
|
93
|
+
false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def with_result(result)
|
|
97
|
+
self.class.new(@test_case, result)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class ScenarioOutlineExample < Scenario
|
|
102
|
+
def outline?
|
|
103
|
+
true
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def scenario_outline
|
|
107
|
+
self
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def cell_values
|
|
111
|
+
source.last.values
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
class Runtime
|
|
3
|
+
class AfterHooks
|
|
4
|
+
def initialize(action_blocks)
|
|
5
|
+
@action_blocks = action_blocks
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def apply_to(test_case)
|
|
9
|
+
test_case.with_steps(
|
|
10
|
+
test_case.test_steps + after_hooks(test_case.source).reverse
|
|
11
|
+
)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def after_hooks(source)
|
|
17
|
+
@action_blocks.map do |action_block|
|
|
18
|
+
Hooks.after_hook(source, &action_block)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
class Runtime
|
|
3
|
+
class BeforeHooks
|
|
4
|
+
def initialize(action_blocks)
|
|
5
|
+
@action_blocks = action_blocks
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def apply_to(test_case)
|
|
9
|
+
test_case.with_steps(
|
|
10
|
+
before_hooks(test_case.source) + test_case.test_steps
|
|
11
|
+
)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def before_hooks(source)
|
|
17
|
+
@action_blocks.map do |action_block|
|
|
18
|
+
Hooks.before_hook(source, &action_block)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -23,8 +23,8 @@ module Cucumber
|
|
|
23
23
|
:step_match
|
|
24
24
|
|
|
25
25
|
def_delegators :@support_code,
|
|
26
|
-
:
|
|
27
|
-
:
|
|
26
|
+
:invoke_dynamic_steps,
|
|
27
|
+
:invoke_dynamic_step,
|
|
28
28
|
:load_programming_language
|
|
29
29
|
|
|
30
30
|
# Returns a Cucumber::MultilineArgument::DataTable for +text_or_table+, which can either
|
|
@@ -44,17 +44,13 @@ module Cucumber
|
|
|
44
44
|
# %w{ CUC-101 Peeler 22 }
|
|
45
45
|
# ])
|
|
46
46
|
#
|
|
47
|
-
def table(text_or_table, file=nil,
|
|
47
|
+
def table(text_or_table, file=nil, line=0)
|
|
48
48
|
if !file
|
|
49
49
|
location = Core::Ast::Location.of_caller
|
|
50
50
|
else
|
|
51
51
|
location = Core::Ast::Location.new(file, line)
|
|
52
52
|
end
|
|
53
|
-
|
|
54
|
-
MultilineArgument::DataTable.new(text_or_table, location)
|
|
55
|
-
else
|
|
56
|
-
MultilineArgument::DataTable.parse(text_or_table, file, location)
|
|
57
|
-
end
|
|
53
|
+
MultilineArgument::DataTable.from(text_or_table, location)
|
|
58
54
|
end
|
|
59
55
|
|
|
60
56
|
# Returns a Cucumber::MultilineArgument::DocString for +body+.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
class Runtime
|
|
3
|
+
class StepHooks
|
|
4
|
+
def initialize(after)
|
|
5
|
+
@after = after
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def apply(test_steps)
|
|
9
|
+
test_steps.flat_map do |test_step|
|
|
10
|
+
[test_step] + after_step_hooks(test_step)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
def after_step_hooks(test_step)
|
|
16
|
+
@after.map do |action_block|
|
|
17
|
+
Hooks.after_step_hook(test_step.source, &action_block)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|