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
         
     |