cucumber 1.2.1 → 1.2.2
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.
- data/.rvmrc +1 -1
- data/.travis.yml +3 -2
- data/DEVELOPERS.md +48 -0
- data/History.md +22 -3
- data/README.md +13 -31
- data/Rakefile +1 -0
- data/cucumber.gemspec +18 -17
- data/cucumber.yml +3 -2
- data/examples/i18n/cs/Rakefile +6 -0
- data/examples/i18n/cs/features/addition.feature +17 -0
- data/examples/i18n/cs/features/division.feature +11 -0
- data/examples/i18n/cs/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/cs/lib/calculator.rb +14 -0
- data/examples/i18n/hi/Rakefile +6 -0
- data/examples/i18n/hi/features/addition.feature +16 -0
- data/examples/i18n/hi/features/division.feature +10 -0
- data/examples/i18n/hi/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/hi/lib/calculator.rb +15 -0
- data/examples/python/README.textile +2 -1
- data/examples/ruby2python/README.textile +2 -1
- data/features/.cucumber/stepdefs.json +1688 -445
- data/features/assertions.feature +69 -0
- data/features/formatter_callbacks.feature +189 -0
- data/features/html_formatter.feature +19 -0
- data/features/json_formatter.feature +8 -4
- data/features/nested_steps_with_second_arg.feature +73 -0
- data/features/step_definitions.feature +65 -0
- data/features/step_definitions/cucumber_steps.rb +18 -3
- data/fixtures/self_test/features/support/env.rb +1 -1
- data/gem_tasks/cucumber.rake +5 -3
- data/gem_tasks/downloads.rb +3 -3
- data/gem_tasks/stats +4 -2
- data/gem_tasks/yard.rake +31 -13
- data/legacy_features/default_snippets.feature +3 -3
- data/legacy_features/language_help.feature +4 -0
- data/legacy_features/report_called_undefined_steps.feature +1 -1
- data/legacy_features/snippet.feature +3 -3
- data/legacy_features/snippets_when_using_star_keyword.feature +1 -1
- data/legacy_features/step_definitions/cucumber_steps.rb +4 -3
- data/legacy_features/support/env.rb +1 -1
- data/legacy_features/support/fake_wire_server.rb +9 -9
- data/lib/autotest/cucumber_mixin.rb +14 -14
- data/lib/autotest/discover.rb +2 -0
- data/lib/cucumber.rb +2 -2
- data/lib/cucumber/ast.rb +1 -1
- data/lib/cucumber/ast/background.rb +11 -7
- data/lib/cucumber/ast/comment.rb +2 -2
- data/lib/cucumber/ast/doc_string.rb +1 -1
- data/lib/cucumber/ast/examples.rb +1 -1
- data/lib/cucumber/ast/feature.rb +2 -2
- data/lib/cucumber/ast/feature_element.rb +1 -1
- data/lib/cucumber/ast/multiline_argument.rb +2 -2
- data/lib/cucumber/ast/names.rb +2 -2
- data/lib/cucumber/ast/outline_table.rb +4 -5
- data/lib/cucumber/ast/scenario.rb +14 -14
- data/lib/cucumber/ast/scenario_outline.rb +4 -4
- data/lib/cucumber/ast/step.rb +3 -3
- data/lib/cucumber/ast/step_collection.rb +5 -5
- data/lib/cucumber/ast/step_invocation.rb +8 -8
- data/lib/cucumber/ast/table.rb +40 -27
- data/lib/cucumber/ast/tree_walker.rb +9 -8
- data/lib/cucumber/ast/visitor.rb +1 -1
- data/lib/cucumber/cli/configuration.rb +10 -10
- data/lib/cucumber/cli/drb_client.rb +1 -1
- data/lib/cucumber/cli/main.rb +3 -3
- data/lib/cucumber/cli/options.rb +3 -2
- data/lib/cucumber/cli/profile_loader.rb +1 -1
- data/lib/cucumber/configuration.rb +12 -12
- data/lib/cucumber/constantize.rb +11 -2
- data/lib/cucumber/core_ext/disable_mini_and_test_unit_autorun.rb +1 -1
- data/lib/cucumber/core_ext/instance_exec.rb +4 -4
- data/lib/cucumber/core_ext/proc.rb +3 -3
- data/lib/cucumber/errors.rb +1 -1
- data/lib/cucumber/feature_file.rb +1 -1
- data/lib/cucumber/formatter/ansicolor.rb +36 -23
- data/lib/cucumber/formatter/console.rb +45 -25
- data/lib/cucumber/formatter/debug.rb +7 -7
- data/lib/cucumber/formatter/duration.rb +1 -1
- data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +7 -0
- data/lib/cucumber/formatter/gpretty.rb +1 -1
- data/lib/cucumber/formatter/html.rb +52 -53
- data/lib/cucumber/formatter/interceptor.rb +2 -2
- data/lib/cucumber/formatter/json.rb +1 -1
- data/lib/cucumber/formatter/json_pretty.rb +2 -1
- data/lib/cucumber/formatter/junit.rb +1 -1
- data/lib/cucumber/formatter/ordered_xml_markup.rb +1 -1
- data/lib/cucumber/formatter/pretty.rb +12 -12
- data/lib/cucumber/formatter/progress.rb +5 -5
- data/lib/cucumber/formatter/rerun.rb +5 -5
- data/lib/cucumber/formatter/stepdefs.rb +1 -1
- data/lib/cucumber/formatter/steps.rb +6 -6
- data/lib/cucumber/formatter/summary.rb +6 -6
- data/lib/cucumber/formatter/unicode.rb +18 -18
- data/lib/cucumber/formatter/usage.rb +7 -7
- data/lib/cucumber/js_support/js_dsl.js +1 -1
- data/lib/cucumber/language_support.rb +1 -1
- data/lib/cucumber/parser/gherkin_builder.rb +33 -33
- data/lib/cucumber/platform.rb +3 -2
- data/lib/cucumber/py_support/py_dsl.py +2 -2
- data/lib/cucumber/py_support/py_language.py +2 -2
- data/lib/cucumber/py_support/py_language.rb +2 -2
- data/lib/cucumber/rake/task.rb +4 -3
- data/lib/cucumber/rb_support/rb_dsl.rb +10 -10
- data/lib/cucumber/rb_support/rb_language.rb +27 -19
- data/lib/cucumber/rb_support/rb_step_definition.rb +39 -11
- data/lib/cucumber/rb_support/rb_transform.rb +3 -3
- data/lib/cucumber/rb_support/rb_world.rb +15 -15
- data/lib/cucumber/rb_support/regexp_argument_matcher.rb +1 -1
- data/lib/cucumber/rspec/disable_option_parser.rb +1 -1
- data/lib/cucumber/rspec/doubles.rb +1 -1
- data/lib/cucumber/runtime.rb +11 -10
- data/lib/cucumber/runtime/features_loader.rb +6 -6
- data/lib/cucumber/runtime/for_programming_languages.rb +8 -15
- data/lib/cucumber/runtime/results.rb +6 -6
- data/lib/cucumber/runtime/support_code.rb +37 -28
- data/lib/cucumber/runtime/user_interface.rb +4 -4
- data/lib/cucumber/step_definition_light.rb +4 -4
- data/lib/cucumber/step_definitions.rb +2 -3
- data/lib/cucumber/step_match.rb +6 -6
- data/lib/cucumber/step_mother.rb +1 -1
- data/lib/cucumber/term/ansicolor.rb +22 -22
- data/lib/cucumber/wire_support/configuration.rb +11 -14
- data/lib/cucumber/wire_support/connection.rb +10 -9
- data/lib/cucumber/wire_support/request_handler.rb +3 -3
- data/lib/cucumber/wire_support/wire_exception.rb +3 -3
- data/lib/cucumber/wire_support/wire_language.rb +11 -11
- data/lib/cucumber/wire_support/wire_packet.rb +7 -5
- data/lib/cucumber/wire_support/wire_protocol.rb +6 -6
- data/lib/cucumber/wire_support/wire_protocol/requests.rb +20 -20
- data/lib/cucumber/wire_support/wire_step_definition.rb +4 -4
- data/spec/cucumber/ast/background_spec.rb +4 -4
- data/spec/cucumber/ast/doc_string_spec.rb +8 -8
- data/spec/cucumber/ast/feature_factory.rb +4 -4
- data/spec/cucumber/ast/feature_spec.rb +18 -18
- data/spec/cucumber/ast/outline_table_spec.rb +3 -3
- data/spec/cucumber/ast/step_spec.rb +4 -4
- data/spec/cucumber/ast/table_spec.rb +50 -29
- data/spec/cucumber/ast/tree_walker_spec.rb +12 -4
- data/spec/cucumber/broadcaster_spec.rb +1 -1
- data/spec/cucumber/cli/configuration_spec.rb +10 -4
- data/spec/cucumber/cli/drb_client_spec.rb +1 -1
- data/spec/cucumber/cli/main_spec.rb +28 -7
- data/spec/cucumber/cli/options_spec.rb +3 -3
- data/spec/cucumber/configuration_spec.rb +4 -4
- data/spec/cucumber/constantize_spec.rb +2 -0
- data/spec/cucumber/core_ext/proc_spec.rb +7 -7
- data/spec/cucumber/formatter/ansicolor_spec.rb +2 -2
- data/spec/cucumber/formatter/duration_spec.rb +2 -2
- data/spec/cucumber/formatter/html_spec.rb +31 -31
- data/spec/cucumber/formatter/interceptor_spec.rb +10 -0
- data/spec/cucumber/formatter/progress_spec.rb +1 -1
- data/spec/cucumber/formatter/spec_helper.rb +7 -7
- data/spec/cucumber/rake/forked_spec.rb +15 -2
- data/spec/cucumber/rake/rcov_spec.rb +2 -2
- data/spec/cucumber/rb_support/rb_language_spec.rb +34 -17
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +45 -35
- data/spec/cucumber/rb_support/rb_transform_spec.rb +3 -3
- data/spec/cucumber/runtime/for_programming_languages_spec.rb +31 -0
- data/spec/cucumber/runtime/results_spec.rb +5 -5
- data/spec/cucumber/runtime/support_code_spec.rb +13 -2
- data/spec/cucumber/runtime_spec.rb +7 -7
- data/spec/cucumber/step_match_spec.rb +2 -2
- data/spec/cucumber/wire_support/configuration_spec.rb +16 -6
- data/spec/cucumber/wire_support/connection_spec.rb +25 -11
- data/spec/cucumber/wire_support/wire_exception_spec.rb +3 -3
- data/spec/cucumber/wire_support/wire_language_spec.rb +3 -3
- data/spec/cucumber/wire_support/wire_packet_spec.rb +4 -4
- data/spec/cucumber/wire_support/wire_step_definition_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- metadata +98 -128
- data/legacy_features/html_formatter.feature +0 -8
- data/legacy_features/html_formatter/a.html +0 -561
data/lib/cucumber/ast/comment.rb
CHANGED
@@ -5,7 +5,7 @@ module Cucumber
|
|
5
5
|
class Examples #:nodoc:
|
6
6
|
include Names
|
7
7
|
attr_writer :outline_table
|
8
|
-
|
8
|
+
|
9
9
|
def initialize(comment, line, keyword, title, description, outline_table)
|
10
10
|
@comment, @keyword, @title, @description, @outline_table = comment, keyword, title, description, outline_table
|
11
11
|
end
|
data/lib/cucumber/ast/feature.rb
CHANGED
@@ -5,7 +5,7 @@ module Cucumber
|
|
5
5
|
# Represents the root node of a parsed feature.
|
6
6
|
class Feature #:nodoc:
|
7
7
|
include Names
|
8
|
-
|
8
|
+
|
9
9
|
attr_accessor :language
|
10
10
|
attr_writer :features, :background
|
11
11
|
attr_reader :file, :feature_elements
|
@@ -80,7 +80,7 @@ module Cucumber
|
|
80
80
|
file = file.gsub(/\//, '\\') if Cucumber::WINDOWS && file && !ENV['CUCUMBER_FORWARD_SLASH_PATHS']
|
81
81
|
@file = file
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
def file_colon_line(line)
|
85
85
|
"#{@file}:#{line}"
|
86
86
|
end
|
@@ -10,7 +10,7 @@ module Cucumber
|
|
10
10
|
def from(argument)
|
11
11
|
return unless argument
|
12
12
|
return argument if argument.respond_to?(:to_step_definition_arg)
|
13
|
-
|
13
|
+
|
14
14
|
case(rubify(argument))
|
15
15
|
when String
|
16
16
|
# TODO: this duplicates work that gherkin does. We should really pass the string to gherkin and let it parse it.
|
@@ -27,4 +27,4 @@ module Cucumber
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
30
|
-
end
|
30
|
+
end
|
data/lib/cucumber/ast/names.rb
CHANGED
@@ -114,9 +114,9 @@ module Cucumber
|
|
114
114
|
visitor.visit_table_cell(cell)
|
115
115
|
end
|
116
116
|
else
|
117
|
-
visitor.
|
117
|
+
visitor.runtime.with_hooks(self) do
|
118
118
|
@step_invocations.each do |step_invocation|
|
119
|
-
step_invocation.invoke(visitor.
|
119
|
+
step_invocation.invoke(visitor.runtime, visitor.configuration)
|
120
120
|
@exception ||= step_invocation.reported_exception
|
121
121
|
end
|
122
122
|
|
@@ -132,12 +132,11 @@ module Cucumber
|
|
132
132
|
def accept_expand(visitor)
|
133
133
|
if header?
|
134
134
|
else
|
135
|
-
visitor.
|
135
|
+
visitor.runtime.with_hooks(self) do
|
136
136
|
@table.visit_scenario_name(visitor, self)
|
137
137
|
@step_invocations.each do |step_invocation|
|
138
|
-
|
138
|
+
visitor.visit_step(step_invocation)
|
139
139
|
@exception ||= step_invocation.reported_exception
|
140
|
-
step_invocation.visit_step_result(visitor)
|
141
140
|
end
|
142
141
|
end
|
143
142
|
end
|
@@ -6,26 +6,26 @@ module Cucumber
|
|
6
6
|
class Scenario #:nodoc:
|
7
7
|
include FeatureElement
|
8
8
|
include Names
|
9
|
-
|
9
|
+
|
10
10
|
attr_reader :line
|
11
|
-
|
12
|
-
class EmptyBackground
|
11
|
+
|
12
|
+
class EmptyBackground
|
13
13
|
def failed?
|
14
14
|
false
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def feature_elements
|
18
18
|
[]
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def step_collection(step_invocations)
|
22
22
|
StepCollection.new(step_invocations)
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def init
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def initialize(background, comment, tags, line, keyword, title, description, raw_steps)
|
30
30
|
@background = background || EmptyBackground.new
|
31
31
|
@comment, @tags, @line, @keyword, @title, @description, @raw_steps = comment, tags, line, keyword, title, description, raw_steps
|
@@ -43,14 +43,14 @@ module Cucumber
|
|
43
43
|
|
44
44
|
def accept(visitor)
|
45
45
|
return if Cucumber.wants_to_quit
|
46
|
-
|
46
|
+
|
47
47
|
with_visitor(visitor) do
|
48
48
|
visitor.visit_comment(@comment) unless @comment.empty?
|
49
49
|
visitor.visit_tags(@tags)
|
50
50
|
visitor.visit_scenario_name(@keyword, name, file_colon_line(@line), source_indent(first_line_length))
|
51
51
|
|
52
52
|
skip_invoke! if @background.failed?
|
53
|
-
visitor.
|
53
|
+
visitor.runtime.with_hooks(self, skip_hooks?) do
|
54
54
|
skip_invoke! if failed?
|
55
55
|
visitor.visit_steps(@steps)
|
56
56
|
end
|
@@ -62,7 +62,7 @@ module Cucumber
|
|
62
62
|
def failed?
|
63
63
|
@steps.failed? || !!@exception
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
def fail!(exception)
|
67
67
|
@exception = exception
|
68
68
|
@current_visitor.visit_exception(@exception, :failed)
|
@@ -101,16 +101,16 @@ module Cucumber
|
|
101
101
|
sexp += steps if steps.any?
|
102
102
|
sexp
|
103
103
|
end
|
104
|
-
|
105
|
-
|
104
|
+
|
105
|
+
|
106
106
|
def with_visitor(visitor)
|
107
107
|
@current_visitor = visitor
|
108
108
|
yield
|
109
109
|
@current_visitor = nil
|
110
110
|
end
|
111
|
-
|
111
|
+
|
112
112
|
private
|
113
|
-
|
113
|
+
|
114
114
|
def skip_hooks?
|
115
115
|
@background.failed? || @executed
|
116
116
|
end
|
@@ -6,7 +6,7 @@ module Cucumber
|
|
6
6
|
class ScenarioOutline #:nodoc:
|
7
7
|
include FeatureElement
|
8
8
|
include Names
|
9
|
-
|
9
|
+
|
10
10
|
module ExamplesArray #:nodoc:
|
11
11
|
def accept(visitor)
|
12
12
|
return if Cucumber.wants_to_quit
|
@@ -38,7 +38,7 @@ module Cucumber
|
|
38
38
|
@examples_array = @example_sections.map do |example_section_and_gherkin_examples|
|
39
39
|
example_section = example_section_and_gherkin_examples[0]
|
40
40
|
gherkin_examples = example_section_and_gherkin_examples[1]
|
41
|
-
|
41
|
+
|
42
42
|
examples_comment = example_section[0]
|
43
43
|
examples_line = example_section[1]
|
44
44
|
examples_keyword = example_section[2]
|
@@ -98,8 +98,8 @@ module Cucumber
|
|
98
98
|
def visit_scenario_name(visitor, row)
|
99
99
|
visitor.visit_scenario_name(
|
100
100
|
@feature.language.keywords('scenario')[0],
|
101
|
-
row.name,
|
102
|
-
file_colon_line(row.line),
|
101
|
+
row.name,
|
102
|
+
file_colon_line(row.line),
|
103
103
|
source_indent(first_line_length)
|
104
104
|
)
|
105
105
|
end
|
data/lib/cucumber/ast/step.rb
CHANGED
@@ -9,7 +9,7 @@ module Cucumber
|
|
9
9
|
attr_accessor :feature_element, :exception, :multiline_arg
|
10
10
|
|
11
11
|
INDENT = 2
|
12
|
-
|
12
|
+
|
13
13
|
def initialize(line, keyword, name, multiline_arg=nil)
|
14
14
|
@line, @keyword, @name, @multiline_arg = line, keyword, name, multiline_arg
|
15
15
|
end
|
@@ -48,7 +48,7 @@ module Cucumber
|
|
48
48
|
# Otherwise it's always StepInvocation that gets visited instead.
|
49
49
|
visit_step_result(visitor, first_match(visitor), @multiline_arg, :skipped, nil, nil)
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
def visit_step_result(visitor, step_match, multiline_arg, status, exception, background)
|
53
53
|
visitor.visit_step_result(@keyword, step_match, @multiline_arg, status, exception, source_indent, background, file_colon_line)
|
54
54
|
end
|
@@ -59,7 +59,7 @@ module Cucumber
|
|
59
59
|
argument_hash = cells.to_hash
|
60
60
|
delimited_arguments = delimit_argument_names(argument_hash)
|
61
61
|
name = replace_name_arguments(delimited_arguments)
|
62
|
-
step_match = visitor.
|
62
|
+
step_match = visitor.runtime.step_match(name, @name) rescue nil
|
63
63
|
return step_match if step_match
|
64
64
|
end
|
65
65
|
NoStepMatch.new(self, @name)
|
@@ -3,21 +3,21 @@ module Cucumber
|
|
3
3
|
# Holds an Array of Step or StepDefinition
|
4
4
|
class StepCollection #:nodoc:
|
5
5
|
include Enumerable
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(steps)
|
8
8
|
@steps = steps
|
9
9
|
@steps.each{|step| step.step_collection = self}
|
10
10
|
end
|
11
11
|
|
12
|
-
def accept(visitor
|
12
|
+
def accept(visitor)
|
13
13
|
return if Cucumber.wants_to_quit
|
14
14
|
@steps.each do |step|
|
15
|
-
visitor.visit_step(step)
|
15
|
+
visitor.visit_step(step)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
def step_invocations(background = false)
|
20
|
-
StepCollection.new(@steps.map{ |step|
|
20
|
+
StepCollection.new(@steps.map{ |step|
|
21
21
|
i = step.step_invocation
|
22
22
|
i.background = background
|
23
23
|
i
|
@@ -62,7 +62,7 @@ module Cucumber
|
|
62
62
|
def passed?
|
63
63
|
status == :passed
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
def status
|
67
67
|
@steps.each{|step_invocation| return step_invocation.status if step_invocation.status != :passed}
|
68
68
|
:passed
|
@@ -35,7 +35,7 @@ module Cucumber
|
|
35
35
|
|
36
36
|
def accept(visitor)
|
37
37
|
return if Cucumber.wants_to_quit
|
38
|
-
invoke(visitor.
|
38
|
+
invoke(visitor.runtime, visitor.configuration)
|
39
39
|
visit_step_result(visitor)
|
40
40
|
end
|
41
41
|
|
@@ -52,13 +52,13 @@ module Cucumber
|
|
52
52
|
)
|
53
53
|
end
|
54
54
|
|
55
|
-
def invoke(
|
56
|
-
find_step_match!(
|
55
|
+
def invoke(runtime, configuration)
|
56
|
+
find_step_match!(runtime, configuration)
|
57
57
|
unless @skip_invoke || configuration.dry_run? || @exception || @step_collection.exception
|
58
58
|
@skip_invoke = true
|
59
59
|
begin
|
60
60
|
@step_match.invoke(@multiline_arg)
|
61
|
-
|
61
|
+
runtime.after_step
|
62
62
|
status!(:passed)
|
63
63
|
rescue Pending => e
|
64
64
|
failed(configuration, e, false)
|
@@ -77,10 +77,10 @@ module Cucumber
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
def find_step_match!(
|
80
|
+
def find_step_match!(runtime, configuration)
|
81
81
|
return if @step_match
|
82
82
|
begin
|
83
|
-
@step_match =
|
83
|
+
@step_match = runtime.step_match(@name)
|
84
84
|
rescue Undefined => e
|
85
85
|
failed(configuration, e, true)
|
86
86
|
status!(:undefined)
|
@@ -90,7 +90,7 @@ module Cucumber
|
|
90
90
|
status!(:failed)
|
91
91
|
@step_match = NoStepMatch.new(@step, @name)
|
92
92
|
end
|
93
|
-
|
93
|
+
runtime.step_visited(self)
|
94
94
|
end
|
95
95
|
|
96
96
|
def failed(configuration, e, clear_backtrace)
|
@@ -113,7 +113,7 @@ module Cucumber
|
|
113
113
|
def filter_backtrace(e)
|
114
114
|
return e if Cucumber.use_full_backtrace
|
115
115
|
e.backtrace.each{|line| line.gsub!(PWD_PATTERN, "./")}
|
116
|
-
|
116
|
+
|
117
117
|
filtered = (e.backtrace || []).reject do |line|
|
118
118
|
BACKTRACE_FILTER_PATTERNS.detect { |p| line =~ p }
|
119
119
|
end
|
data/lib/cucumber/ast/table.rb
CHANGED
@@ -5,7 +5,7 @@ require 'gherkin/formatter/escaping'
|
|
5
5
|
module Cucumber
|
6
6
|
module Ast
|
7
7
|
# Step Definitions that match a plain text Step with a multiline argument table
|
8
|
-
# will receive it as an instance of Table. A Table object holds the data of a
|
8
|
+
# will receive it as an instance of Table. A Table object holds the data of a
|
9
9
|
# table parsed from a feature file and lets you access and manipulate the data
|
10
10
|
# in different ways.
|
11
11
|
#
|
@@ -26,13 +26,13 @@ module Cucumber
|
|
26
26
|
class Table
|
27
27
|
class Different < StandardError
|
28
28
|
attr_reader :table
|
29
|
-
|
29
|
+
|
30
30
|
def initialize(table)
|
31
31
|
super('Tables were not identical')
|
32
32
|
@table = table
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
class Builder
|
37
37
|
attr_reader :rows
|
38
38
|
|
@@ -50,7 +50,7 @@ module Cucumber
|
|
50
50
|
|
51
51
|
include Enumerable
|
52
52
|
include Gherkin::Rubify
|
53
|
-
|
53
|
+
|
54
54
|
NULL_CONVERSIONS = Hash.new({ :strict => false, :proc => lambda{ |cell_value| cell_value } }).freeze
|
55
55
|
|
56
56
|
attr_accessor :file
|
@@ -76,7 +76,7 @@ module Cucumber
|
|
76
76
|
@cell_class = Cell
|
77
77
|
raw = ensure_array_of_array(rubify(raw))
|
78
78
|
# Verify that it's square
|
79
|
-
|
79
|
+
raw.transpose
|
80
80
|
create_cell_matrix(raw)
|
81
81
|
@conversion_procs = conversion_procs
|
82
82
|
@header_mappings = header_mappings
|
@@ -108,7 +108,7 @@ module Cucumber
|
|
108
108
|
def transpose
|
109
109
|
self.class.new(raw.transpose, @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
|
110
110
|
end
|
111
|
-
|
111
|
+
|
112
112
|
# Converts this table into an Array of Hash where the keys of each
|
113
113
|
# Hash are the headers in the table. For example, a Table built from
|
114
114
|
# the following plain text:
|
@@ -126,7 +126,7 @@ module Cucumber
|
|
126
126
|
def hashes
|
127
127
|
@hashes ||= build_hashes
|
128
128
|
end
|
129
|
-
|
129
|
+
|
130
130
|
# Converts this table into a Hash where the first column is
|
131
131
|
# used as keys and the second column is used as values
|
132
132
|
#
|
@@ -137,7 +137,7 @@ module Cucumber
|
|
137
137
|
#
|
138
138
|
# {'a' => '2', 'b' => '3'}
|
139
139
|
#
|
140
|
-
# The table must be exactly two columns wide
|
140
|
+
# The table must be exactly two columns wide
|
141
141
|
#
|
142
142
|
def rows_hash
|
143
143
|
return @rows_hash if @rows_hash
|
@@ -163,7 +163,7 @@ module Cucumber
|
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
-
def column_names
|
166
|
+
def column_names #:nodoc:
|
167
167
|
@col_names ||= cell_matrix[0].map { |cell| cell.value }
|
168
168
|
end
|
169
169
|
|
@@ -193,7 +193,7 @@ module Cucumber
|
|
193
193
|
# | x | y |
|
194
194
|
#
|
195
195
|
# table.match(/table:column_1_name,column_2_name/) #=> non-nil
|
196
|
-
#
|
196
|
+
#
|
197
197
|
# Note: must use 'table:' prefix on match
|
198
198
|
def match(pattern)
|
199
199
|
header_to_match = "table:#{headers.join(',')}"
|
@@ -218,7 +218,7 @@ module Cucumber
|
|
218
218
|
# | 123456 | xyz |
|
219
219
|
# | 345678 | abc |
|
220
220
|
#
|
221
|
-
# A StepDefinition receiving this table can then map the columns
|
221
|
+
# A StepDefinition receiving this table can then map the columns
|
222
222
|
# with both Regexp and String:
|
223
223
|
#
|
224
224
|
# table.map_headers!(/phone( number)?/i => :phone, 'Address' => :address)
|
@@ -238,6 +238,7 @@ module Cucumber
|
|
238
238
|
# # => ['phone number', 'ADDRESS']
|
239
239
|
#
|
240
240
|
def map_headers!(mappings={}, &block)
|
241
|
+
clear_cache!
|
241
242
|
@header_mappings = mappings
|
242
243
|
@header_conversion_proc = block
|
243
244
|
end
|
@@ -250,8 +251,8 @@ module Cucumber
|
|
250
251
|
end
|
251
252
|
|
252
253
|
# Change how #hashes converts column values. The +column_name+ argument identifies the column
|
253
|
-
# and +conversion_proc+ performs the conversion for each cell in that column. If +strict+ is
|
254
|
-
# true, an error will be raised if the column named +column_name+ is not found. If +strict+
|
254
|
+
# and +conversion_proc+ performs the conversion for each cell in that column. If +strict+ is
|
255
|
+
# true, an error will be raised if the column named +column_name+ is not found. If +strict+
|
255
256
|
# is false, no error will be raised. Example:
|
256
257
|
#
|
257
258
|
# Given /^an expense report for (.*) with the following posts:$/ do |table|
|
@@ -269,7 +270,7 @@ module Cucumber
|
|
269
270
|
# Compares +other_table+ to self. If +other_table+ contains columns
|
270
271
|
# and/or rows that are not in self, new columns/rows are added at the
|
271
272
|
# relevant positions, marking the cells in those rows/columns as
|
272
|
-
# <tt>surplus</tt>. Likewise, if +other_table+ lacks columns and/or
|
273
|
+
# <tt>surplus</tt>. Likewise, if +other_table+ lacks columns and/or
|
273
274
|
# rows that are present in self, these are marked as <tt>missing</tt>.
|
274
275
|
#
|
275
276
|
# <tt>surplus</tt> and <tt>missing</tt> cells are recognised by formatters
|
@@ -300,7 +301,7 @@ module Cucumber
|
|
300
301
|
# an Array of Hash (similar to the structure returned by #hashes).
|
301
302
|
#
|
302
303
|
# Calling this method is particularly useful in <tt>Then</tt> steps that take
|
303
|
-
# a Table argument, if you want to compare that table to some actual values.
|
304
|
+
# a Table argument, if you want to compare that table to some actual values.
|
304
305
|
#
|
305
306
|
def diff!(other_table, options={})
|
306
307
|
options = {
|
@@ -315,7 +316,7 @@ module Cucumber
|
|
315
316
|
other_table.convert_headers!
|
316
317
|
other_table.convert_columns!
|
317
318
|
ensure_green!
|
318
|
-
|
319
|
+
|
319
320
|
convert_headers!
|
320
321
|
convert_columns!
|
321
322
|
|
@@ -339,7 +340,7 @@ module Cucumber
|
|
339
340
|
last_change = nil
|
340
341
|
missing_row_pos = nil
|
341
342
|
insert_row_pos = nil
|
342
|
-
|
343
|
+
|
343
344
|
changes.each do |change|
|
344
345
|
if(change.action == '-')
|
345
346
|
missing_row_pos = change.position + inserted
|
@@ -368,9 +369,9 @@ module Cucumber
|
|
368
369
|
end
|
369
370
|
end
|
370
371
|
end
|
371
|
-
|
372
|
+
|
372
373
|
clear_cache!
|
373
|
-
should_raise =
|
374
|
+
should_raise =
|
374
375
|
missing_row_pos && options[:missing_row] ||
|
375
376
|
insert_row_pos && options[:surplus_row] ||
|
376
377
|
missing_col && options[:missing_col] ||
|
@@ -396,7 +397,7 @@ module Cucumber
|
|
396
397
|
def verify_column(column_name) #:nodoc:
|
397
398
|
raise %{The column named "#{column_name}" does not exist} unless raw[0].include?(column_name)
|
398
399
|
end
|
399
|
-
|
400
|
+
|
400
401
|
def verify_table_width(width) #:nodoc:
|
401
402
|
raise %{The table must have exactly #{width} columns} unless raw[0].size == width
|
402
403
|
end
|
@@ -429,7 +430,7 @@ module Cucumber
|
|
429
430
|
def headers #:nodoc:
|
430
431
|
raw.first
|
431
432
|
end
|
432
|
-
|
433
|
+
|
433
434
|
def header_cell(col) #:nodoc:
|
434
435
|
cells_rows[0][col]
|
435
436
|
end
|
@@ -452,7 +453,7 @@ module Cucumber
|
|
452
453
|
formatter = Formatter::Pretty.new(nil, io, options)
|
453
454
|
formatter.instance_variable_set('@indent', options[:indent])
|
454
455
|
TreeWalker.new(nil, [formatter]).visit_multiline_arg(self)
|
455
|
-
|
456
|
+
|
456
457
|
Cucumber::Term::ANSIColor.coloring = c
|
457
458
|
io.rewind
|
458
459
|
s = "\n" + io.read + (" " * (options[:indent] - 2))
|
@@ -498,7 +499,7 @@ module Cucumber
|
|
498
499
|
@conversion_procs.each do |column_name, conversion_proc|
|
499
500
|
verify_column(column_name) if conversion_proc[:strict]
|
500
501
|
end
|
501
|
-
|
502
|
+
|
502
503
|
cell_matrix.transpose.each do |col|
|
503
504
|
column_name = col[0].value
|
504
505
|
conversion_proc = @conversion_procs[column_name][:proc]
|
@@ -537,7 +538,7 @@ module Cucumber
|
|
537
538
|
end
|
538
539
|
|
539
540
|
def clear_cache! #:nodoc:
|
540
|
-
@hashes = @rows_hash = @rows = @columns = nil
|
541
|
+
@hashes = @rows_hash = @col_names = @rows = @columns = nil
|
541
542
|
end
|
542
543
|
|
543
544
|
def columns #:nodoc:
|
@@ -580,7 +581,7 @@ module Cucumber
|
|
580
581
|
end
|
581
582
|
|
582
583
|
unmapped_cols.each_with_index do |col, col_index|
|
583
|
-
empty_col = (0...cell_matrix.length).map do |row|
|
584
|
+
empty_col = (0...cell_matrix.length).map do |row|
|
584
585
|
SurplusCell.new(nil, self, -1)
|
585
586
|
end
|
586
587
|
cols << empty_col
|
@@ -600,7 +601,7 @@ module Cucumber
|
|
600
601
|
end
|
601
602
|
|
602
603
|
def hashes_to_array(hashes) #:nodoc:
|
603
|
-
header = hashes[0].keys
|
604
|
+
header = hashes[0].keys.sort
|
604
605
|
[header] + hashes.map{|hash| header.map{|key| hash[key]}}
|
605
606
|
end
|
606
607
|
|
@@ -698,12 +699,20 @@ module Cucumber
|
|
698
699
|
SurplusCell === o || value == o.value
|
699
700
|
end
|
700
701
|
|
702
|
+
def eql?(o)
|
703
|
+
self == o
|
704
|
+
end
|
705
|
+
|
706
|
+
def hash
|
707
|
+
0
|
708
|
+
end
|
709
|
+
|
701
710
|
# For testing only
|
702
711
|
def to_sexp #:nodoc:
|
703
712
|
[:cell, @value]
|
704
713
|
end
|
705
714
|
end
|
706
|
-
|
715
|
+
|
707
716
|
class SurplusCell < Cell #:nodoc:
|
708
717
|
def status
|
709
718
|
:comment
|
@@ -712,6 +721,10 @@ module Cucumber
|
|
712
721
|
def ==(o)
|
713
722
|
true
|
714
723
|
end
|
724
|
+
|
725
|
+
def hash
|
726
|
+
0
|
727
|
+
end
|
715
728
|
end
|
716
729
|
end
|
717
730
|
end
|