aslakhellesoy-cucumber 0.3.11.6 → 0.3.11.200907091518
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/History.txt +49 -1
- data/Manifest.txt +3 -0
- data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +1 -1
- data/examples/self_test/features/support/env.rb +2 -1
- data/examples/steps_library/features/step_definitions/steps_lib1.rb +8 -0
- data/examples/steps_library/features/step_definitions/steps_lib2.rb +8 -0
- data/examples/tickets/features/step_definitons/tickets_steps.rb +15 -0
- data/features/html_formatter/a.html +4 -4
- data/features/rake_task.feature +28 -0
- data/features/steps_formatter.feature +25 -0
- data/features/support/env.rb +5 -0
- data/lib/cucumber/ast/outline_table.rb +2 -1
- data/lib/cucumber/ast/py_string.rb +0 -1
- data/lib/cucumber/ast/step.rb +4 -1
- data/lib/cucumber/ast/table.rb +286 -48
- data/lib/cucumber/ast/visitor.rb +2 -1
- data/lib/cucumber/cli/configuration.rb +8 -2
- data/lib/cucumber/cli/language_help_formatter.rb +9 -7
- data/lib/cucumber/feature_file.rb +7 -1
- data/lib/cucumber/filter.rb +2 -2
- data/lib/cucumber/formatter/html.rb +1 -1
- data/lib/cucumber/formatter/pretty.rb +20 -5
- data/lib/cucumber/formatter/progress.rb +1 -1
- data/lib/cucumber/formatter/steps.rb +49 -0
- data/lib/cucumber/parser/feature.rb +27 -0
- data/lib/cucumber/parser/i18n/language.rb +8 -5
- data/lib/cucumber/rake/task.rb +6 -0
- data/lib/cucumber/step_match.rb +1 -1
- data/lib/cucumber/version.rb +1 -1
- data/rails_generators/cucumber/templates/env.rb +1 -0
- data/rails_generators/feature/templates/feature.erb +1 -1
- data/rails_generators/feature/templates/steps.erb +2 -8
- data/spec/cucumber/ast/table_spec.rb +144 -0
- data/spec/cucumber/cli/configuration_spec.rb +13 -0
- data/spec/cucumber/cli/main_spec.rb +0 -1
- data/spec/cucumber/formatter/progress_spec.rb +2 -2
- metadata +8 -4
data/History.txt
CHANGED
@@ -1,12 +1,18 @@
|
|
1
1
|
== 0.3.12 (In Git)
|
2
2
|
|
3
|
-
The
|
3
|
+
The Hot summer release
|
4
|
+
|
5
|
+
This is a hot summer in Norway, and Cucumbers are growing in abundance. To celebrate this we give you
|
6
|
+
a new release with some hot new features:
|
7
|
+
|
8
|
+
=== Egality
|
4
9
|
|
5
10
|
English is not the world's most spoken language, so why should Cucumber force non-English speakers to use the
|
6
11
|
--language flag? As of this release you're no longer forced to do that. Instead, you can add a comment header
|
7
12
|
to your .feature files:
|
8
13
|
|
9
14
|
# language: fr
|
15
|
+
# Cucumber understands that this is French
|
10
16
|
Fonctionnalité: Trou de boulette
|
11
17
|
|
12
18
|
If you don't have that header, Cucumber will work as before - using whatever you specified with --language,
|
@@ -14,6 +20,40 @@ or default to English if no --language option was specified. A nice side effect
|
|
14
20
|
have features in several languages side by side and run them in the same cucumber. (Not recommended unless
|
15
21
|
you want to take polyglot programming to an extreme level).
|
16
22
|
|
23
|
+
=== Table diffing
|
24
|
+
|
25
|
+
When you pass a table as an argument to your Then steps you often want to compare that table
|
26
|
+
to some actual values. In previous releases you had to iterate over the table's values and manually
|
27
|
+
compare each row using cell.should equal('foo') or assert_equal('foo', cell). If a discrepancy was found
|
28
|
+
you'd get an error and then you were done.
|
29
|
+
|
30
|
+
With this release you have a much more powerful way to compare expected tables with actual data. An
|
31
|
+
Ast::Table object now has a new #diff!(table) method that you can invoke in your step definitions
|
32
|
+
that take table arguments. If the table you pass in is different from the expected table (from your
|
33
|
+
plain text step), Cucumber will print the difference for each of the row or column and fail your step.
|
34
|
+
|
35
|
+
The Table#diff! method expects an Array of Array, Array of Hash (similar to what you'd get from table#hashes)
|
36
|
+
or simply another Ast::Table object.
|
37
|
+
|
38
|
+
As an extra bonus we provide you with a new Webrat method that you can use to transform the data from
|
39
|
+
an HTML table into an Array of Array, so that you can easily compare the contents of your HTML table to
|
40
|
+
expected data passed to a step:
|
41
|
+
|
42
|
+
Then /^I should see the following cukes:$/ do |expected_cukes_table|
|
43
|
+
expected_cukes_table.diff!(table_at('#cuke_table').to_a)
|
44
|
+
end
|
45
|
+
|
46
|
+
You can do the same trick to compare data from a Rails ActiveRecord table (although this is not a
|
47
|
+
recommended practice - your Then steps should compare against what users *see*, not what's in the
|
48
|
+
database):
|
49
|
+
|
50
|
+
# This requires that you use the column names in the header of the plain text expected table
|
51
|
+
Then /^I should have the following cukes in the database:$/ do |expected_cukes_table|
|
52
|
+
expected_cukes_table.diff!(Cuke.find(:all).map(&attributes), :coldiff => false) # Don't care about extra columns
|
53
|
+
end
|
54
|
+
|
55
|
+
=== Environment variables
|
56
|
+
|
17
57
|
Another useful new feature is the ability to define environment variables on Cucumber's command line (just
|
18
58
|
like you can with Rake). Example:
|
19
59
|
|
@@ -25,6 +65,8 @@ for example enabling your super hack that validates all HTTP responses for XHTML
|
|
25
65
|
This release also has several bugfixes related to --format and Before/Adter hooks.
|
26
66
|
|
27
67
|
=== Bugfixes
|
68
|
+
* Make it possible to write non-localized step definitions (#377 Aslak Hellesøy)
|
69
|
+
* Table cells containing unicode are rendered incorrectly (#386 Stefan Kanev)
|
28
70
|
* Before and After hooks run after everything is finished whn there are 2+ --format options (#371 Aslak Hellesøy)
|
29
71
|
* When using --out and two --format the first is not delivered inline with execution of features (#361 Aslak Hellesøy)
|
30
72
|
* Profile Formatter broken (#370 Aslak Hellesøy)
|
@@ -33,15 +75,21 @@ This release also has several bugfixes related to --format and Before/Adter hook
|
|
33
75
|
* rake gems no longer lists cucumber as a [F]ramework gem (David Chelimsky)
|
34
76
|
* CLI issues correct exit code when using --drb. Requires Spork version >= 0.5.1. (#355 Ben Mabey)
|
35
77
|
* Make sure script/generate cucumber --spork uses the cucumber Rails environment (Philippe Lafoucrière)
|
78
|
+
* Fixed bug with rake task raising errors with feature files with spaces (#380 Joseph Wilk)
|
36
79
|
|
37
80
|
=== New Features
|
81
|
+
* Access to scenario outline name from After hook scenario parameter (#342 Aslak Hellesøy)
|
82
|
+
* Allow multiple --tags switches to be passed
|
83
|
+
* Load step definitions from vendored gems and plugins (#388 Mike Burns)
|
38
84
|
* New --format steps formatter. Variant of the usage formatter that lists available step definitions (Demetrius Nunes)
|
39
85
|
* Possibility to specify scenario language as part of the .feature file (#345 Aslak Hellesøy)
|
40
86
|
* Support specifying environment variables using foo=bar syntax on command line or in profiles (#362 Bryan Helmkamp)
|
41
87
|
* Display failing scenarios at the end of pretty format to make it easier for people to play them back (#360 Ryan Bigg)
|
42
88
|
|
43
89
|
=== Changed Features
|
90
|
+
* With --tags, positive tags are &&'ed while negative tags are ||'ed (John Wilger)
|
44
91
|
* The data returned from Table#hashes and similar methods are frozen. Dup if you need to modify. (Aslak Hellesøy)
|
92
|
+
* Visitor.visit_table_cell_value(value, col_width, status) is now visitor.visit_table_cell_value(value, status)
|
45
93
|
|
46
94
|
== 0.3.11 2009-06-05
|
47
95
|
|
data/Manifest.txt
CHANGED
@@ -239,6 +239,7 @@ examples/tickets/features/step_definitons/246_steps.rb
|
|
239
239
|
examples/tickets/features/step_definitons/248_steps.rb
|
240
240
|
examples/tickets/features/step_definitons/scenario_outline_steps.rb
|
241
241
|
examples/tickets/features/step_definitons/tickets_steps.rb
|
242
|
+
examples/tickets/features/table_diffing.feature
|
242
243
|
examples/tickets/features/tickets.feature
|
243
244
|
examples/watir/README.textile
|
244
245
|
examples/watir/Rakefile
|
@@ -268,6 +269,7 @@ features/step_definitions/cucumber_steps.rb
|
|
268
269
|
features/step_definitions/extra_steps.rb
|
269
270
|
features/steps_formatter.feature
|
270
271
|
features/support/env.rb
|
272
|
+
features/table_diffing.feature
|
271
273
|
features/usage.feature
|
272
274
|
features/work_in_progress.feature
|
273
275
|
gem_tasks/deployment.rake
|
@@ -349,6 +351,7 @@ lib/cucumber/step_definition.rb
|
|
349
351
|
lib/cucumber/step_match.rb
|
350
352
|
lib/cucumber/step_mother.rb
|
351
353
|
lib/cucumber/version.rb
|
354
|
+
lib/cucumber/webrat/table_locator.rb
|
352
355
|
lib/cucumber/world.rb
|
353
356
|
rails_generators/cucumber/USAGE
|
354
357
|
rails_generators/cucumber/cucumber_generator.rb
|
@@ -64,3 +64,18 @@ end
|
|
64
64
|
Then /^I should get a no method error for 'backtrace_line'$/ do
|
65
65
|
pending
|
66
66
|
end
|
67
|
+
|
68
|
+
Then /the table should be different with table:/ do |expected|
|
69
|
+
expected.diff!(table(%{
|
70
|
+
| b | c | a | d |
|
71
|
+
| KASHA | AIIT | BOOYA | X |
|
72
|
+
| four | five | three | Y |
|
73
|
+
}), :coldiff => true)
|
74
|
+
end
|
75
|
+
|
76
|
+
Then /the table should be different with array:/ do |expected|
|
77
|
+
expected.diff!([
|
78
|
+
{'a' => 'BOOYA', 'b' => 'KASHA'},
|
79
|
+
{'a' => 'three', 'b' => 'four'},
|
80
|
+
])
|
81
|
+
end
|
@@ -142,7 +142,7 @@ features/background/failing_background_after_success.feature:5:in `And '10' glob
|
|
142
142
|
I sleep all night and I test all day</pre></li></ol></div></div><div class="feature"><h2><span class="val">Feature: Passing background sample</span></h2><p class="narrative"></p><div class="background"><h3><span class="keyword">Background:</span> <span class="val"></span></h3><ol><li class="step passed" id="features_background_passing_background_feature_4"><div><span class="keyword">Given</span> <span class="step val">'<span class="param">10</span>' cukes</span></div></li></ol></div><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">passing background</span></h3><ol><li class="step passed" id="features_background_passing_background_feature_7"><div><span class="keyword">Then</span> <span class="step val">I should have '<span class="param">10</span>' cukes</span></div></li></ol></div><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">another passing background</span></h3><ol><li class="step passed" id="features_background_passing_background_feature_10"><div><span class="keyword">Then</span> <span class="step val">I should have '<span class="param">10</span>' cukes</span></div></li></ol></div></div><div class="feature"><h2><span class="val">Feature: Pending background sample</span></h2><p class="narrative"></p><div class="background"><h3><span class="keyword">Background:</span> <span class="val"></span></h3><ol><li class="step undefined" id="features_background_pending_background_feature_4"><div><span class="keyword">Given</span> <span class="step val">pending</span></div></li></ol></div><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">pending background</span></h3><ol><li class="step skipped" id="features_background_pending_background_feature_7"><div><span class="keyword">Then</span> <span class="step val">I should have '<span class="param">10</span>' cukes</span></div></li></ol></div><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">another pending background</span></h3><ol><li class="step skipped" id="features_background_pending_background_feature_10"><div><span class="keyword">Then</span> <span class="step val">I should have '<span class="param">10</span>' cukes</span></div></li></ol></div></div><div class="feature"><h2><span class="val">Feature: Failing background with scenario outlines sample</span></h2><p class="narrative"></p><div class="background"><h3><span class="keyword">Background:</span> <span class="val"></span></h3><ol><li class="step failed" id="features_background_scenario_outline_failing_background_feature_4"><div><span class="keyword">Given</span> <span class="step val">failing without a table</span></div><pre class="failed">FAIL (RuntimeError)
|
143
143
|
./features/step_definitions/sample_steps.rb:2:in `flunker'
|
144
144
|
./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
|
145
|
-
features/background/scenario_outline_failing_background.feature:4:in `Given failing without a table'</pre></li></ol></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">failing background</span></h3><ol><li class="step skipped" id="features_background_scenario_outline_failing_background_feature_7"><div><span class="keyword">Then</span> <span class="step val">I should have '<count>' cukes</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_9"><th class="val skipped_param" id="row_9_0">count</th></tr><tr id="row_10"><td class="val skipped" id="row_10_0">10</td></tr><tr><td
|
145
|
+
features/background/scenario_outline_failing_background.feature:4:in `Given failing without a table'</pre></li></ol></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">failing background</span></h3><ol><li class="step skipped" id="features_background_scenario_outline_failing_background_feature_7"><div><span class="keyword">Then</span> <span class="step val">I should have '<count>' cukes</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_9"><th class="val skipped_param" id="row_9_0">count</th></tr><tr id="row_10"><td class="val skipped" id="row_10_0">10</td></tr><tr><td colspan="1" class="failed"><pre>FAIL (RuntimeError)
|
146
146
|
./features/step_definitions/sample_steps.rb:2:in `flunker'
|
147
147
|
./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
|
148
148
|
features/background/scenario_outline_failing_background.feature:4:in `Given failing without a table'</pre></td></tr></table></div></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">another failing background</span></h3><ol><li class="step skipped" id="features_background_scenario_outline_failing_background_feature_13"><div><span class="keyword">Then</span> <span class="step val">I should have '<count>' cukes</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_15"><th class="val skipped_param" id="row_15_0">count</th></tr><tr id="row_16"><td class="val skipped" id="row_16_0">10</td></tr></table></div></div></div><div class="feature"><h2><span class="val">Feature: Passing background with scenario outlines sample</span></h2><p class="narrative"></p><div class="background"><h3><span class="keyword">Background:</span> <span class="val"></span></h3><ol><li class="step passed" id="features_background_scenario_outline_passing_background_feature_4"><div><span class="keyword">Given</span> <span class="step val">'<span class="param">10</span>' cukes</span></div></li></ol></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">passing background</span></h3><ol><li class="step skipped" id="features_background_scenario_outline_passing_background_feature_7"><div><span class="keyword">Then</span> <span class="step val">I should have '<count>' cukes</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_9"><th class="val skipped_param" id="row_9_0">count</th></tr><tr id="row_10"><td class="val passed" id="row_10_0">10</td></tr></table></div></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">another passing background</span></h3><ol><li class="step skipped" id="features_background_scenario_outline_passing_background_feature_13"><div><span class="keyword">Then</span> <span class="step val">I should have '<count>' cukes</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_15"><th class="val skipped_param" id="row_15_0">count</th></tr><tr id="row_16"><td class="val passed" id="row_16_0">10</td></tr></table></div></div></div><div class="feature"><h2><span class="val">Feature: Calling undefined step</span></h2><p class="narrative"></p><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">Call directly</span></h3><ol><li class="step undefined" id="features_call_undefined_step_from_step_def_feature_4"><div><span class="keyword">Given</span> <span class="step val">a step definition that calls an undefined step</span></div><pre class="undefined">Undefined step: "this does not exist" (Cucumber::Undefined)
|
@@ -165,7 +165,7 @@ yawn</span></h3><ol><li class="step passed" id="features_multiline_name_feature_
|
|
165
165
|
which goes on and on and on for three lines
|
166
166
|
yawn</span></h3><ol><li class="step skipped" id="features_multiline_name_feature_16"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_18"><th class="val skipped_param" id="row_18_0">state</th></tr><tr id="row_19"><td class="val passed" id="row_19_0">passing</td></tr></table></div></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">name</span></h3><ol><li class="step skipped" id="features_multiline_name_feature_22"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val">I'm a multiline name
|
167
167
|
which goes on and on and on for three lines
|
168
|
-
yawn</span></h4><table><tr id="row_26"><th class="val skipped_param" id="row_26_0">state</th></tr><tr id="row_27"><td class="val passed" id="row_27_0">passing</td></tr></table></div></div></div><div class="feature"><h2><span class="val">Feature: Outline Sample</span></h2><p class="narrative"></p><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">I have no steps</span></h3><ol></ol></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">Test state</span></h3><ol><li class="step skipped" id="features_outline_sample_feature_6"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li><li class="step skipped" id="features_outline_sample_feature_7"><div><span class="keyword">Given</span> <span class="step val"><other_state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val">Rainbow colours</span></h4><table><tr id="row_9"><th class="val skipped_param" id="row_9_0">state</th><th class="val skipped_param" id="row_9_1">other_state</th></tr><tr id="row_10"><td class="val undefined" id="row_10_0">missing</td><td class="val skipped" id="row_10_1">passing</td></tr><tr id="row_11"><td class="val passed" id="row_11_0">passing</td><td class="val passed" id="row_11_1">passing</td></tr><tr id="row_12"><td class="val failed" id="row_12_0">failing</td><td class="val skipped" id="row_12_1">passing</td></tr><tr><td
|
168
|
+
yawn</span></h4><table><tr id="row_26"><th class="val skipped_param" id="row_26_0">state</th></tr><tr id="row_27"><td class="val passed" id="row_27_0">passing</td></tr></table></div></div></div><div class="feature"><h2><span class="val">Feature: Outline Sample</span></h2><p class="narrative"></p><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">I have no steps</span></h3><ol></ol></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">Test state</span></h3><ol><li class="step skipped" id="features_outline_sample_feature_6"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li><li class="step skipped" id="features_outline_sample_feature_7"><div><span class="keyword">Given</span> <span class="step val"><other_state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val">Rainbow colours</span></h4><table><tr id="row_9"><th class="val skipped_param" id="row_9_0">state</th><th class="val skipped_param" id="row_9_1">other_state</th></tr><tr id="row_10"><td class="val undefined" id="row_10_0">missing</td><td class="val skipped" id="row_10_1">passing</td></tr><tr id="row_11"><td class="val passed" id="row_11_0">passing</td><td class="val passed" id="row_11_1">passing</td></tr><tr id="row_12"><td class="val failed" id="row_12_0">failing</td><td class="val skipped" id="row_12_1">passing</td></tr><tr><td colspan="2" class="failed"><pre>FAIL (RuntimeError)
|
169
169
|
./features/step_definitions/sample_steps.rb:2:in `flunker'
|
170
170
|
./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
|
171
171
|
features/outline_sample.feature:6:in `Given <state> without a table'</pre></td></tr></table></div><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val">Only passing</span></h4><table><tr id="row_14"><th class="val skipped_param" id="row_14_0">state</th><th class="val skipped_param" id="row_14_1">other_state</th></tr><tr id="row_15"><td class="val passed" id="row_15_0">passing</td><td class="val passed" id="row_15_1">passing</td></tr></table></div></div></div><div class="feature"><pre class="comment"># Feature comment<br/></pre><span class="tag">@one</span><h2><span class="val">Feature: Sample</span></h2><p class="narrative"></p><div class="scenario"><span class="tag">@two</span><span class="tag">@three</span><h3><span class="keyword">Scenario:</span> <span class="val">Missing</span></h3><ol><li class="step undefined" id="features_sample_feature_7"><div><span class="keyword">Given</span> <span class="step val">missing</span></div></li></ol></div><div class="scenario"><pre class="comment"># Scenario comment<br/></pre><span class="tag">@three</span><h3><span class="keyword">Scenario:</span> <span class="val">Passing</span></h3><ol><li class="step passed" id="features_sample_feature_12"><div><span class="keyword">Given</span> <span class="step val">passing</span></div><table><tr id="row_13"><td class="val" id="row_13_0">a</td><td class="val" id="row_13_1">b</td></tr><tr id="row_14"><td class="val" id="row_14_0">c</td><td class="val" id="row_14_1">d</td></tr></table></li></ol></div><div class="scenario"><span class="tag">@four</span><h3><span class="keyword">Scenario:</span> <span class="val">Failing</span></h3><ol><li class="step failed" id="features_sample_feature_18"><div><span class="keyword">Given</span> <span class="step val">failing</span></div><pre class="val"> hello</pre><pre class="failed">FAIL (RuntimeError)
|
@@ -174,10 +174,10 @@ features/outline_sample.feature:6:in `Given <state> without a table'</pre></td><
|
|
174
174
|
features/sample.feature:18:in `Given failing'</pre></li></ol></div></div><div class="feature"><h2><span class="val">Feature: search examples</span></h2><p class="narrative"></p><div class="background"><h3><span class="keyword">Background:</span> <span class="val">Hantu Pisang background match</span></h3><ol><li class="step passed" id="features_search_sample_feature_4"><div><span class="keyword">Given</span> <span class="step val">passing without a table</span></div></li></ol></div><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">should match Hantu Pisang</span></h3><ol><li class="step passed" id="features_search_sample_feature_7"><div><span class="keyword">Given</span> <span class="step val">passing without a table</span></div></li></ol></div><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">Ignore me</span></h3><ol><li class="step failed" id="features_search_sample_feature_10"><div><span class="keyword">Given</span> <span class="step val">failing without a table</span></div><pre class="failed">FAIL (RuntimeError)
|
175
175
|
./features/step_definitions/sample_steps.rb:2:in `flunker'
|
176
176
|
./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
|
177
|
-
features/search_sample.feature:10:in `Given failing without a table'</pre></li></ol></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">Ignore me</span></h3><ol><li class="step skipped" id="features_search_sample_feature_13"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_15"><th class="val skipped_param" id="row_15_0">state</th></tr><tr id="row_16"><td class="val failed" id="row_16_0">failing</td></tr><tr><td
|
177
|
+
features/search_sample.feature:10:in `Given failing without a table'</pre></li></ol></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">Ignore me</span></h3><ol><li class="step skipped" id="features_search_sample_feature_13"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_15"><th class="val skipped_param" id="row_15_0">state</th></tr><tr id="row_16"><td class="val failed" id="row_16_0">failing</td></tr><tr><td colspan="1" class="failed"><pre>FAIL (RuntimeError)
|
178
178
|
./features/step_definitions/sample_steps.rb:2:in `flunker'
|
179
179
|
./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
|
180
|
-
features/search_sample.feature:13:in `Given <state> without a table'</pre></td></tr></table></div></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">Hantu Pisang match</span></h3><ol><li class="step skipped" id="features_search_sample_feature_19"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_21"><th class="val skipped_param" id="row_21_0">state</th></tr><tr id="row_22"><td class="val passed" id="row_22_0">passing</td></tr></table></div></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">no match in name but in examples</span></h3><ol><li class="step skipped" id="features_search_sample_feature_25"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val">Hantu Pisang</span></h4><table><tr id="row_27"><th class="val skipped_param" id="row_27_0">state</th></tr><tr id="row_28"><td class="val passed" id="row_28_0">passing</td></tr></table></div><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val">Ignore me</span></h4><table><tr id="row_31"><th class="val skipped_param" id="row_31_0">state</th></tr><tr id="row_32"><td class="val failed" id="row_32_0">failing</td></tr><tr><td
|
180
|
+
features/search_sample.feature:13:in `Given <state> without a table'</pre></td></tr></table></div></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">Hantu Pisang match</span></h3><ol><li class="step skipped" id="features_search_sample_feature_19"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val"></span></h4><table><tr id="row_21"><th class="val skipped_param" id="row_21_0">state</th></tr><tr id="row_22"><td class="val passed" id="row_22_0">passing</td></tr></table></div></div><div class="scenario outline"><h3><span class="keyword">Scenario Outline:</span> <span class="val">no match in name but in examples</span></h3><ol><li class="step skipped" id="features_search_sample_feature_25"><div><span class="keyword">Given</span> <span class="step val"><state> without a table</span></div></li></ol><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val">Hantu Pisang</span></h4><table><tr id="row_27"><th class="val skipped_param" id="row_27_0">state</th></tr><tr id="row_28"><td class="val passed" id="row_28_0">passing</td></tr></table></div><div class="examples"><h4><span class="keyword">Examples:</span> <span class="val">Ignore me</span></h4><table><tr id="row_31"><th class="val skipped_param" id="row_31_0">state</th></tr><tr id="row_32"><td class="val failed" id="row_32_0">failing</td></tr><tr><td colspan="1" class="failed"><pre>FAIL (RuntimeError)
|
181
181
|
./features/step_definitions/sample_steps.rb:2:in `flunker'
|
182
182
|
./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
|
183
183
|
features/search_sample.feature:25:in `Given <state> without a table'</pre></td></tr></table></div></div></div><div class="feature"><span class="tag">@lots</span><h2><span class="val">Feature: Tons of cukes</span></h2><p class="narrative"></p><div class="scenario"><h3><span class="keyword">Scenario:</span> <span class="val">Lots and lots</span></h3><ol><li class="step passed" id="features_tons_of_cukes_feature_4"><div><span class="keyword">Given</span> <span class="step val">'<span class="param">2</span>' cukes</span></div></li><li class="step failed" id="features_tons_of_cukes_feature_5"><div><span class="keyword">Given</span> <span class="step val">'<span class="param">2</span>' cukes</span></div><pre class="failed">We already have 2 cukes! (RuntimeError)
|
data/features/rake_task.feature
CHANGED
@@ -148,3 +148,31 @@ Feature: Rake task
|
|
148
148
|
"""
|
149
149
|
* features/support/dont_require_me.rb
|
150
150
|
"""
|
151
|
+
|
152
|
+
Scenario: feature files with spaces
|
153
|
+
Given a file named "features/spaces are nasty.feature" with:
|
154
|
+
"""
|
155
|
+
Feature: The futures green
|
156
|
+
|
157
|
+
Scenario: Orange
|
158
|
+
Given this is missing
|
159
|
+
"""
|
160
|
+
And a file named "Rakefile" with:
|
161
|
+
"""
|
162
|
+
$LOAD_PATH.unshift(CUCUMBER_LIB)
|
163
|
+
require 'cucumber/rake/task'
|
164
|
+
|
165
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
166
|
+
t.cucumber_opts = %w{--quiet --no-color}
|
167
|
+
end
|
168
|
+
"""
|
169
|
+
When I run rake features
|
170
|
+
Then it should pass
|
171
|
+
And the output should contain
|
172
|
+
"""
|
173
|
+
Feature: The futures green
|
174
|
+
|
175
|
+
Scenario: Orange
|
176
|
+
Given this is missing
|
177
|
+
|
178
|
+
"""
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Feature: --formatter steps option - Steps Formatter
|
2
|
+
In order to easily see which steps are already defined,
|
3
|
+
specially when using 3rd party steps libraries,
|
4
|
+
Cucumber should show the available steps in a user-friendly format
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given I am in steps_library
|
8
|
+
|
9
|
+
Scenario: Printing steps
|
10
|
+
When I run cucumber -f steps features
|
11
|
+
Then it should pass with
|
12
|
+
"""
|
13
|
+
features/step_definitions/steps_lib1.rb
|
14
|
+
/^I defined a first step$/ # features/step_definitions/steps_lib1.rb:1
|
15
|
+
/^I define a second step$/ # features/step_definitions/steps_lib1.rb:4
|
16
|
+
/^I should also have a third step$/ # features/step_definitions/steps_lib1.rb:7
|
17
|
+
|
18
|
+
features/step_definitions/steps_lib2.rb
|
19
|
+
/^I defined a step 4$/ # features/step_definitions/steps_lib2.rb:1
|
20
|
+
/^I create a step 5$/ # features/step_definitions/steps_lib2.rb:4
|
21
|
+
/^I should be too tired for step 6$/ # features/step_definitions/steps_lib2.rb:7
|
22
|
+
|
23
|
+
6 step definition(s) in 2 source file(s).
|
24
|
+
|
25
|
+
"""
|
data/features/support/env.rb
CHANGED
@@ -70,6 +70,11 @@ class CucumberWorld
|
|
70
70
|
stderr_file.close
|
71
71
|
in_current_dir do
|
72
72
|
@last_stdout = `#{command} 2> #{stderr_file.path}`
|
73
|
+
mode = Cucumber::RUBY_1_9 ? {:external_encoding=>"UTF-8"} : 'r'
|
74
|
+
IO.popen("#{command} 2> #{stderr_file.path}", mode) do |io|
|
75
|
+
@last_stdout = io.read
|
76
|
+
end
|
77
|
+
|
73
78
|
@last_exit_status = $?.exitstatus
|
74
79
|
end
|
75
80
|
@last_stderr = IO.read(stderr_file.path)
|
@@ -44,7 +44,8 @@ module Cucumber
|
|
44
44
|
end
|
45
45
|
|
46
46
|
class ExampleRow < Cells
|
47
|
-
|
47
|
+
attr_reader :scenario_outline # https://rspec.lighthouseapp.com/projects/16211/tickets/342
|
48
|
+
|
48
49
|
def create_step_invocations!(scenario_outline)
|
49
50
|
@scenario_outline = scenario_outline
|
50
51
|
@step_invocations = scenario_outline.step_invocations(self)
|
data/lib/cucumber/ast/step.rb
CHANGED
@@ -85,8 +85,11 @@ module Cucumber
|
|
85
85
|
private
|
86
86
|
|
87
87
|
def matched_cells(cells)
|
88
|
+
col_index = 0
|
88
89
|
cells.select do |cell|
|
89
|
-
|
90
|
+
header_cell = cell.table.header_cell(col_index)
|
91
|
+
col_index += 1
|
92
|
+
delimited = delimited(header_cell.value)
|
90
93
|
@name.index(delimited) || (@multiline_arg && @multiline_arg.has_text?(delimited))
|
91
94
|
end
|
92
95
|
end
|
data/lib/cucumber/ast/table.rb
CHANGED
@@ -7,7 +7,9 @@ module Cucumber
|
|
7
7
|
#
|
8
8
|
# This gets parsed into a Table holding the values <tt>[['a', 'b'], ['c', 'd']]</tt>
|
9
9
|
#
|
10
|
-
class Table
|
10
|
+
class Table
|
11
|
+
include Enumerable
|
12
|
+
|
11
13
|
NULL_CONVERSIONS = Hash.new(lambda{ |cell_value| cell_value }).freeze
|
12
14
|
|
13
15
|
attr_accessor :file
|
@@ -16,18 +18,19 @@ module Cucumber
|
|
16
18
|
"table"
|
17
19
|
end
|
18
20
|
|
19
|
-
def initialize(raw,
|
20
|
-
# Verify that it's square
|
21
|
-
raw.transpose
|
22
|
-
@raw = raw
|
21
|
+
def initialize(raw, conversion_procs = NULL_CONVERSIONS.dup)
|
23
22
|
@cells_class = Cells
|
24
23
|
@cell_class = Cell
|
25
|
-
|
24
|
+
|
25
|
+
# Verify that it's square
|
26
|
+
transposed = raw.transpose
|
27
|
+
create_cell_matrix(raw)
|
28
|
+
@conversion_procs = conversion_procs
|
26
29
|
end
|
27
30
|
|
28
31
|
# Creates a copy of this table, inheriting the column mappings.
|
29
32
|
def dup
|
30
|
-
self.class.new(
|
33
|
+
self.class.new(raw.dup, @conversion_procs.dup)
|
31
34
|
end
|
32
35
|
|
33
36
|
# Returns a new, transposed table. Example:
|
@@ -42,7 +45,7 @@ module Cucumber
|
|
42
45
|
# | 4 | 2 |
|
43
46
|
#
|
44
47
|
def transpose
|
45
|
-
self.class.new(
|
48
|
+
self.class.new(raw.transpose, @conversion_procs.dup)
|
46
49
|
end
|
47
50
|
|
48
51
|
# Converts this table into an Array of Hash where the keys of each
|
@@ -78,8 +81,9 @@ module Cucumber
|
|
78
81
|
# The table must be exactly two columns wide
|
79
82
|
#
|
80
83
|
def rows_hash
|
84
|
+
return @rows_hash if @rows_hash
|
81
85
|
verify_table_width(2)
|
82
|
-
@rows_hash = self.transpose.hashes[0]
|
86
|
+
@rows_hash = self.transpose.hashes[0].freeze
|
83
87
|
end
|
84
88
|
|
85
89
|
# Gets the raw data of this table. For example, a Table built from
|
@@ -88,17 +92,21 @@ module Cucumber
|
|
88
92
|
# | a | b |
|
89
93
|
# | c | d |
|
90
94
|
#
|
91
|
-
#
|
95
|
+
# gets converted into the following:
|
92
96
|
#
|
93
97
|
# [['a', 'b], ['c', 'd']]
|
94
98
|
#
|
95
99
|
def raw
|
96
|
-
|
100
|
+
cell_matrix.map do |row|
|
101
|
+
row.map do |cell|
|
102
|
+
cell.value
|
103
|
+
end
|
104
|
+
end
|
97
105
|
end
|
98
106
|
|
99
107
|
# Same as #raw, but skips the first (header) row
|
100
108
|
def rows
|
101
|
-
|
109
|
+
raw[1..-1]
|
102
110
|
end
|
103
111
|
|
104
112
|
def each_cells_row(&proc)
|
@@ -117,7 +125,7 @@ module Cucumber
|
|
117
125
|
[:table, *cells_rows.map{|row| row.to_sexp}]
|
118
126
|
end
|
119
127
|
|
120
|
-
#
|
128
|
+
# Redefines the table headers. This makes it
|
121
129
|
# possible to use prettier header names in the features. Example:
|
122
130
|
#
|
123
131
|
# | Phone Number | Address |
|
@@ -130,6 +138,18 @@ module Cucumber
|
|
130
138
|
# hashes = mapped_table.hashes
|
131
139
|
# # => [{:phone => '123456', :address => 'xyz'}, {:phone => '345678', :address => 'abc'}]
|
132
140
|
#
|
141
|
+
def map_headers!(mappings)
|
142
|
+
header_cells = cell_matrix[0]
|
143
|
+
mappings.each_pair do |pre, post|
|
144
|
+
header_cell = header_cells.detect{|cell| cell.value == pre}
|
145
|
+
header_cell.value = post
|
146
|
+
if @conversion_procs.has_key?(pre)
|
147
|
+
@conversion_procs[post] = @conversion_procs.delete(pre)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns a new Table where the headers are redefined. See #map_headers!
|
133
153
|
def map_headers(mappings)
|
134
154
|
table = self.dup
|
135
155
|
table.map_headers!(mappings)
|
@@ -153,11 +173,110 @@ module Cucumber
|
|
153
173
|
@conversion_procs[column_name] = conversion_proc
|
154
174
|
end
|
155
175
|
|
176
|
+
# Compares +other_table+ to self. If +other_table+ contains columns
|
177
|
+
# and/or rows that are not in self, new columns/rows are added at the
|
178
|
+
# relevant positions, marking the cells in those rows/columns as
|
179
|
+
# <tt>surplus</tt>. Likewise, if +other_table+ lacks columns and/or
|
180
|
+
# rows that are present in self, these are marked as <tt>missing</tt>.
|
181
|
+
#
|
182
|
+
# <tt>surplus</tt> and <tt>missing</tt> cells are recognised by formatters
|
183
|
+
# and displayed so that it's easy to read the differences.
|
184
|
+
#
|
185
|
+
# Cells that are different, but <em>look</em> identical (for example the
|
186
|
+
# boolean true and the string "true") are converted to their Object#inspect
|
187
|
+
# representation and preceded with (i) - to make it easier to identify
|
188
|
+
# where the difference actually is.
|
189
|
+
#
|
190
|
+
# Since all tables that are passed to StepDefinitions always have String
|
191
|
+
# objects in their cells, you may want to use #map_column! before calling
|
192
|
+
# #diff!
|
193
|
+
#
|
194
|
+
# An exception is raised if there are missing rows or columns, or
|
195
|
+
# surplus rows. An error is <em>not</em> raised for surplus columns.
|
196
|
+
# Whether to raise or not raise can be changed by setting values in
|
197
|
+
# +options+ to true or false:
|
198
|
+
#
|
199
|
+
# * <tt>missing_row</tt>: Raise on missing rows (defaults to true)
|
200
|
+
# * <tt>surplus_row</tt>: Raise on surplus rows (defaults to true)
|
201
|
+
# * <tt>missing_col</tt>: Raise on missing columns (defaults to true)
|
202
|
+
# * <tt>surplus_col</tt>: Raise on surplus columns (defaults to false)
|
203
|
+
#
|
204
|
+
# The +other_table+ argument can be another Table, an Array of Array or
|
205
|
+
# an Array of Hash (similar to the structure returned by #hashes).
|
206
|
+
#
|
207
|
+
# Calling this method is particularly useful in <tt>Then</tt> steps that take
|
208
|
+
# a Table argument, if you want to compare that table to some actual values.
|
209
|
+
#
|
210
|
+
def diff!(other_table, options={})
|
211
|
+
options = {:missing_row => true, :surplus_row => true, :missing_col => true, :surplus_col => false}.merge(options)
|
212
|
+
|
213
|
+
other_table = ensure_table(other_table)
|
214
|
+
ensure_green!
|
215
|
+
|
216
|
+
original_width = cell_matrix[0].length
|
217
|
+
other_table_cell_matrix = pad!(other_table.cell_matrix)
|
218
|
+
padded_width = cell_matrix[0].length
|
219
|
+
|
220
|
+
missing_col = cell_matrix[0].detect{|cell| cell.status == :undefined}
|
221
|
+
surplus_col = padded_width > original_width
|
222
|
+
|
223
|
+
require_diff_lcs
|
224
|
+
cell_matrix.extend(Diff::LCS)
|
225
|
+
convert_columns!
|
226
|
+
changes = cell_matrix.diff(other_table_cell_matrix).flatten
|
227
|
+
|
228
|
+
inserted = 0
|
229
|
+
missing = 0
|
230
|
+
|
231
|
+
row_indices = Array.new(other_table_cell_matrix.length) {|n| n}
|
232
|
+
|
233
|
+
last_change = nil
|
234
|
+
missing_row_pos = nil
|
235
|
+
insert_row_pos = nil
|
236
|
+
|
237
|
+
changes.each do |change|
|
238
|
+
if(change.action == '-')
|
239
|
+
missing_row_pos = change.position + inserted
|
240
|
+
cell_matrix[missing_row_pos].each{|cell| cell.status = :undefined}
|
241
|
+
row_indices.insert(missing_row_pos, nil)
|
242
|
+
missing += 1
|
243
|
+
else # '+'
|
244
|
+
insert_row_pos = change.position + missing
|
245
|
+
inserted_row = change.element
|
246
|
+
inserted_row.each{|cell| cell.status = :comment}
|
247
|
+
cell_matrix.insert(insert_row_pos, inserted_row)
|
248
|
+
row_indices[insert_row_pos] = nil
|
249
|
+
inspect_rows(cell_matrix[missing_row_pos], inserted_row) if last_change && last_change.action == '-'
|
250
|
+
inserted += 1
|
251
|
+
end
|
252
|
+
last_change = change
|
253
|
+
end
|
254
|
+
|
255
|
+
other_table_cell_matrix.each_with_index do |other_row, i|
|
256
|
+
row_index = row_indices.index(i)
|
257
|
+
row = cell_matrix[row_index] if row_index
|
258
|
+
if row
|
259
|
+
(original_width..padded_width).each do |col_index|
|
260
|
+
surplus_cell = other_row[col_index]
|
261
|
+
row[col_index].value = surplus_cell.value if row[col_index]
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
clear_cache!
|
267
|
+
should_raise =
|
268
|
+
missing_row_pos && options[:missing_row] ||
|
269
|
+
insert_row_pos && options[:surplus_row] ||
|
270
|
+
missing_col && options[:missing_col] ||
|
271
|
+
surplus_col && options[:surplus_col]
|
272
|
+
raise 'Tables were not identical' if should_raise
|
273
|
+
end
|
274
|
+
|
156
275
|
def to_hash(cells) #:nodoc:
|
157
276
|
hash = Hash.new do |hash, key|
|
158
277
|
hash[key.to_s] if key.is_a?(Symbol)
|
159
278
|
end
|
160
|
-
|
279
|
+
raw[0].each_with_index do |column_name, column_index|
|
161
280
|
value = @conversion_procs[column_name].call(cells.value(column_index))
|
162
281
|
hash[column_name] = value
|
163
282
|
end
|
@@ -169,11 +288,11 @@ module Cucumber
|
|
169
288
|
end
|
170
289
|
|
171
290
|
def verify_column(column_name)
|
172
|
-
raise %{The column named "#{column_name}" does not exist} unless
|
291
|
+
raise %{The column named "#{column_name}" does not exist} unless raw[0].include?(column_name)
|
173
292
|
end
|
174
293
|
|
175
294
|
def verify_table_width(width)
|
176
|
-
raise %{The table must have exactly #{width} columns} unless
|
295
|
+
raise %{The table must have exactly #{width} columns} unless raw[0].size == width
|
177
296
|
end
|
178
297
|
|
179
298
|
def arguments_replaced(arguments) #:nodoc:
|
@@ -198,33 +317,88 @@ module Cucumber
|
|
198
317
|
def cells_rows
|
199
318
|
@rows ||= cell_matrix.map do |cell_row|
|
200
319
|
@cells_class.new(self, cell_row)
|
201
|
-
end
|
320
|
+
end
|
202
321
|
end
|
203
322
|
|
204
323
|
def headers
|
205
|
-
|
324
|
+
raw.first
|
206
325
|
end
|
207
326
|
|
208
327
|
def header_cell(col)
|
209
328
|
cells_rows[0][col]
|
210
329
|
end
|
211
330
|
|
331
|
+
def cell_matrix
|
332
|
+
@cell_matrix
|
333
|
+
end
|
334
|
+
|
335
|
+
def col_width(col)
|
336
|
+
columns[col].__send__(:width)
|
337
|
+
end
|
338
|
+
|
339
|
+
def to_s(options = {})
|
340
|
+
options = {:color => true, :indent => 2, :prefixes => TO_S_PREFIXES}.merge(options)
|
341
|
+
io = StringIO.new
|
342
|
+
|
343
|
+
c = Term::ANSIColor.coloring?
|
344
|
+
Term::ANSIColor.coloring = options[:color]
|
345
|
+
f = Formatter::Pretty.new(nil, io, options)
|
346
|
+
f.instance_variable_set('@indent', options[:indent])
|
347
|
+
f.visit_multiline_arg(self)
|
348
|
+
Term::ANSIColor.coloring = c
|
349
|
+
|
350
|
+
io.rewind
|
351
|
+
s = "\n" + io.read + (" " * (options[:indent] - 2))
|
352
|
+
s
|
353
|
+
end
|
354
|
+
|
355
|
+
private
|
356
|
+
|
357
|
+
TO_S_PREFIXES = Hash.new(' ')
|
358
|
+
TO_S_PREFIXES[:comment] = ['(+) ']
|
359
|
+
TO_S_PREFIXES[:undefined] = ['(-) ']
|
360
|
+
|
212
361
|
protected
|
213
362
|
|
214
|
-
def
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
363
|
+
def inspect_rows(missing_row, inserted_row)
|
364
|
+
missing_row.each_with_index do |missing_cell, col|
|
365
|
+
inserted_cell = inserted_row[col]
|
366
|
+
if(missing_cell.value != inserted_cell.value && (missing_cell.value.to_s == inserted_cell.value.to_s))
|
367
|
+
missing_cell.inspect!
|
368
|
+
inserted_cell.inspect!
|
220
369
|
end
|
221
370
|
end
|
222
371
|
end
|
223
372
|
|
224
|
-
|
373
|
+
def create_cell_matrix(raw)
|
374
|
+
@cell_matrix = raw.map do |raw_row|
|
375
|
+
line = raw_row.line rescue -1
|
376
|
+
raw_row.map do |raw_cell|
|
377
|
+
new_cell(raw_cell, line)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
225
381
|
|
226
|
-
def
|
227
|
-
|
382
|
+
def convert_columns!
|
383
|
+
cell_matrix.transpose.each do |col|
|
384
|
+
conversion_proc = @conversion_procs[col[0].value]
|
385
|
+
col[1..-1].each do |cell|
|
386
|
+
cell.value = conversion_proc.call(cell.value)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
def require_diff_lcs
|
392
|
+
begin
|
393
|
+
require 'diff/lcs'
|
394
|
+
rescue LoadError => e
|
395
|
+
e.message << "\n Please gem install diff-lcs\n"
|
396
|
+
raise e
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
def clear_cache!
|
401
|
+
@hashes = @rows_hash = @rows = @columns = nil
|
228
402
|
end
|
229
403
|
|
230
404
|
def columns
|
@@ -233,17 +407,73 @@ module Cucumber
|
|
233
407
|
end.freeze
|
234
408
|
end
|
235
409
|
|
236
|
-
def
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
410
|
+
def new_cell(raw_cell, line)
|
411
|
+
@cell_class.new(raw_cell, self, line)
|
412
|
+
end
|
413
|
+
|
414
|
+
# Pads our own cell_matrix and returns a cell matrix of same
|
415
|
+
# column width that can be used for diffing
|
416
|
+
def pad!(other_cell_matrix)
|
417
|
+
clear_cache!
|
418
|
+
cols = cell_matrix.transpose
|
419
|
+
unmapped_cols = other_cell_matrix.transpose
|
420
|
+
|
421
|
+
mapped_cols = []
|
422
|
+
|
423
|
+
cols.each_with_index do |col, col_index|
|
424
|
+
header = col[0]
|
425
|
+
candidate_cols, unmapped_cols = unmapped_cols.partition do |other_col|
|
426
|
+
other_col[0] == header
|
245
427
|
end
|
246
|
-
|
428
|
+
raise "More than one column has the header #{header}" if candidate_cols.size > 2
|
429
|
+
|
430
|
+
other_padded_col = if candidate_cols.size == 1
|
431
|
+
# Found a matching column
|
432
|
+
candidate_cols[0]
|
433
|
+
else
|
434
|
+
mark_as_missing(cols[col_index])
|
435
|
+
(0...other_cell_matrix.length).map do |row|
|
436
|
+
val = row == 0 ? header.value : nil
|
437
|
+
SurplusCell.new(val, self, -1)
|
438
|
+
end
|
439
|
+
end
|
440
|
+
mapped_cols.insert(col_index, other_padded_col)
|
441
|
+
end
|
442
|
+
|
443
|
+
unmapped_cols.each_with_index do |col, col_index|
|
444
|
+
empty_col = (0...cell_matrix.length).map do |row|
|
445
|
+
SurplusCell.new(nil, self, -1)
|
446
|
+
end
|
447
|
+
cols << empty_col
|
448
|
+
end
|
449
|
+
|
450
|
+
@cell_matrix = cols.transpose
|
451
|
+
(mapped_cols + unmapped_cols).transpose
|
452
|
+
end
|
453
|
+
|
454
|
+
def ensure_table(table_or_array)
|
455
|
+
return table_or_array if Table === table_or_array
|
456
|
+
table_or_array = hashes_to_array(table_or_array) if Hash === table_or_array[0]
|
457
|
+
Table.new(table_or_array)
|
458
|
+
end
|
459
|
+
|
460
|
+
def hashes_to_array(hashes)
|
461
|
+
header = hashes[0].keys
|
462
|
+
[header] + hashes.map{|hash| header.map{|key| hash[key]}}
|
463
|
+
end
|
464
|
+
|
465
|
+
def ensure_green!
|
466
|
+
each_cell{|cell| cell.status = :passed}
|
467
|
+
end
|
468
|
+
|
469
|
+
def each_cell(&proc)
|
470
|
+
cell_matrix.each{|row| row.each(&proc)}
|
471
|
+
end
|
472
|
+
|
473
|
+
def mark_as_missing(col)
|
474
|
+
col.each do |cell|
|
475
|
+
cell.status = :undefined
|
476
|
+
end
|
247
477
|
end
|
248
478
|
|
249
479
|
# Represents a row of cells or columns of cells
|
@@ -303,30 +533,38 @@ module Cucumber
|
|
303
533
|
end
|
304
534
|
|
305
535
|
class Cell
|
306
|
-
attr_reader :
|
307
|
-
|
536
|
+
attr_reader :line, :table
|
537
|
+
attr_accessor :status, :value
|
308
538
|
|
309
|
-
def initialize(value, table,
|
310
|
-
@value, @table, @
|
539
|
+
def initialize(value, table, line)
|
540
|
+
@value, @table, @line = value, table, line
|
311
541
|
end
|
312
542
|
|
313
543
|
def accept(visitor)
|
314
|
-
visitor.visit_table_cell_value(
|
544
|
+
visitor.visit_table_cell_value(value, status)
|
545
|
+
end
|
546
|
+
|
547
|
+
def inspect!
|
548
|
+
@value = "(i) #{value.inspect}"
|
315
549
|
end
|
316
550
|
|
317
|
-
def
|
318
|
-
|
551
|
+
def ==(o)
|
552
|
+
SurplusCell === o || value == o.value
|
319
553
|
end
|
320
554
|
|
321
555
|
# For testing only
|
322
556
|
def to_sexp #:nodoc:
|
323
557
|
[:cell, @value]
|
324
558
|
end
|
559
|
+
end
|
560
|
+
|
561
|
+
class SurplusCell < Cell
|
562
|
+
def status
|
563
|
+
:comment
|
564
|
+
end
|
325
565
|
|
326
|
-
|
327
|
-
|
328
|
-
def col_width
|
329
|
-
@col_width ||= @table.__send__(:col_width, @col).freeze
|
566
|
+
def ==(o)
|
567
|
+
true
|
330
568
|
end
|
331
569
|
end
|
332
570
|
end
|