cucumber 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|