casecumber 1.0.2.1
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/.gitattributes +1 -0
- data/.gitignore +26 -0
- data/.gitmodules +3 -0
- data/.rspec +1 -0
- data/.travis.yml +7 -0
- data/.yardopts +0 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +115 -0
- data/History.md +1702 -0
- data/LICENSE +22 -0
- data/README.md +25 -0
- data/Rakefile +12 -0
- data/bin/cucumber +22 -0
- data/cucumber.gemspec +60 -0
- data/cucumber.yml +20 -0
- data/examples/i18n/README.textile +18 -0
- data/examples/i18n/Rakefile +33 -0
- data/examples/i18n/ar/Rakefile +6 -0
- data/examples/i18n/ar/features/addition.feature +17 -0
- data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/ar/lib/calculator.rb +11 -0
- data/examples/i18n/bg/Rakefile +6 -0
- data/examples/i18n/bg/features/addition.feature +12 -0
- data/examples/i18n/bg/features/consecutive_calculations.feature +19 -0
- data/examples/i18n/bg/features/division.feature +17 -0
- data/examples/i18n/bg/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/bg/features/support/env.rb +5 -0
- data/examples/i18n/bg/features/support/world.rb +8 -0
- data/examples/i18n/bg/lib/calculator.rb +24 -0
- data/examples/i18n/ca/Rakefile +6 -0
- data/examples/i18n/ca/features/step_definitons/calculator_steps.rb +21 -0
- data/examples/i18n/ca/features/suma.feature +17 -0
- data/examples/i18n/ca/lib/calculadora.rb +16 -0
- data/examples/i18n/da/Rakefile +6 -0
- data/examples/i18n/da/features/sammenlaegning.feature +18 -0
- data/examples/i18n/da/features/step_definitons/lommeregner_steps.rb +24 -0
- data/examples/i18n/da/lib/lommeregner.rb +11 -0
- data/examples/i18n/de/.gitignore +1 -0
- data/examples/i18n/de/Rakefile +6 -0
- data/examples/i18n/de/features/addition.feature +17 -0
- data/examples/i18n/de/features/division.feature +10 -0
- data/examples/i18n/de/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/de/lib/calculator.rb +14 -0
- data/examples/i18n/en-lol/Rakefile +4 -0
- data/examples/i18n/en-lol/features/step_definitions/cucumbrz_steps.rb +16 -0
- data/examples/i18n/en-lol/features/stuffing.feature +8 -0
- data/examples/i18n/en-lol/features/support/env.rb +7 -0
- data/examples/i18n/en-lol/lib/basket.rb +12 -0
- data/examples/i18n/en-lol/lib/belly.rb +11 -0
- data/examples/i18n/en/.gitignore +1 -0
- data/examples/i18n/en/Rakefile +6 -0
- data/examples/i18n/en/features/addition.feature +17 -0
- data/examples/i18n/en/features/division.feature +10 -0
- data/examples/i18n/en/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/en/lib/calculator.rb +14 -0
- data/examples/i18n/eo/.gitignore +1 -0
- data/examples/i18n/eo/Rakefile +6 -0
- data/examples/i18n/eo/features/adicio.feature +17 -0
- data/examples/i18n/eo/features/divido.feature +10 -0
- data/examples/i18n/eo/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/eo/lib/calculator.rb +14 -0
- data/examples/i18n/es/Rakefile +6 -0
- data/examples/i18n/es/features/adicion.feature +17 -0
- data/examples/i18n/es/features/step_definitons/calculador_steps.rb +21 -0
- data/examples/i18n/es/lib/calculador.rb +14 -0
- data/examples/i18n/et/Rakefile +6 -0
- data/examples/i18n/et/features/jagamine.feature +10 -0
- data/examples/i18n/et/features/liitmine.feature +17 -0
- data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +24 -0
- data/examples/i18n/et/lib/kalkulaator.rb +14 -0
- data/examples/i18n/fi/.gitignore +1 -0
- data/examples/i18n/fi/Rakefile +6 -0
- data/examples/i18n/fi/features/jakolasku.feature +10 -0
- data/examples/i18n/fi/features/step_definitons/laskin_steps.rb +24 -0
- data/examples/i18n/fi/features/yhteenlasku.feature +17 -0
- data/examples/i18n/fi/lib/laskin.rb +14 -0
- data/examples/i18n/fr/Rakefile +6 -0
- data/examples/i18n/fr/features/addition.feature +18 -0
- data/examples/i18n/fr/features/addition2.feature +17 -0
- data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +32 -0
- data/examples/i18n/fr/features/support/env.rb +5 -0
- data/examples/i18n/fr/lib/calculatrice.rb +10 -0
- data/examples/i18n/he/Rakefile +6 -0
- data/examples/i18n/he/features/addition.feature +17 -0
- data/examples/i18n/he/features/division.feature +10 -0
- data/examples/i18n/he/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/he/lib/calculator.rb +15 -0
- data/examples/i18n/hu/.gitignore +1 -0
- data/examples/i18n/hu/Rakefile +6 -0
- data/examples/i18n/hu/features/osszeadas.feature +17 -0
- data/examples/i18n/hu/features/osztas.feature +10 -0
- data/examples/i18n/hu/features/step_definitons/calculator_steps.rb +25 -0
- data/examples/i18n/hu/lib/calculator.rb +14 -0
- data/examples/i18n/id/.gitignore +1 -0
- data/examples/i18n/id/Rakefile +6 -0
- data/examples/i18n/id/features/addition.feature +17 -0
- data/examples/i18n/id/features/division.feature +10 -0
- data/examples/i18n/id/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/id/lib/calculator.rb +14 -0
- data/examples/i18n/it/Rakefile +6 -0
- data/examples/i18n/it/features/somma.feature +11 -0
- data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +24 -0
- data/examples/i18n/it/lib/calcolatrice.rb +11 -0
- data/examples/i18n/ja/.gitignore +1 -0
- data/examples/i18n/ja/Rakefile +6 -0
- data/examples/i18n/ja/features/addition.feature +17 -0
- data/examples/i18n/ja/features/division.feature +10 -0
- data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +19 -0
- data/examples/i18n/ja/features/support/env.rb +5 -0
- data/examples/i18n/ja/lib/calculator.rb +14 -0
- data/examples/i18n/ko/.gitignore +1 -0
- data/examples/i18n/ko/Rakefile +6 -0
- data/examples/i18n/ko/features/addition.feature +17 -0
- data/examples/i18n/ko/features/division.feature +11 -0
- data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/ko/lib/calculator.rb +14 -0
- data/examples/i18n/lt/.gitignore +1 -0
- data/examples/i18n/lt/Rakefile +6 -0
- data/examples/i18n/lt/features/addition.feature +17 -0
- data/examples/i18n/lt/features/division.feature +10 -0
- data/examples/i18n/lt/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/lt/lib/calculator.rb +14 -0
- data/examples/i18n/lv/Rakefile +6 -0
- data/examples/i18n/lv/features/addition.feature +17 -0
- data/examples/i18n/lv/features/division.feature +10 -0
- data/examples/i18n/lv/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/lv/lib/calculator.rb +14 -0
- data/examples/i18n/no/Rakefile +6 -0
- data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +17 -0
- data/examples/i18n/no/features/summering.feature +19 -0
- data/examples/i18n/no/features/support/env.rb +6 -0
- data/examples/i18n/no/lib/kalkulator.rb +11 -0
- data/examples/i18n/pl/.gitignore +1 -0
- data/examples/i18n/pl/Rakefile +6 -0
- data/examples/i18n/pl/features/addition.feature +17 -0
- data/examples/i18n/pl/features/division.feature +10 -0
- data/examples/i18n/pl/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/pl/features/support/env.rb +5 -0
- data/examples/i18n/pl/lib/calculator.rb +14 -0
- data/examples/i18n/pt/Rakefile +6 -0
- data/examples/i18n/pt/features/adicao.feature +11 -0
- data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +20 -0
- data/examples/i18n/pt/features/support/env.rb +5 -0
- data/examples/i18n/pt/lib/calculadora.rb +10 -0
- data/examples/i18n/ro/Rakefile +6 -0
- data/examples/i18n/ro/features/adunare.feature +12 -0
- data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +21 -0
- data/examples/i18n/ro/lib/calculator.rb +11 -0
- data/examples/i18n/ru/Rakefile +6 -0
- data/examples/i18n/ru/features/addition.feature +11 -0
- data/examples/i18n/ru/features/consecutive_calculations.feature +17 -0
- data/examples/i18n/ru/features/division.feature +16 -0
- data/examples/i18n/ru/features/step_definitons/calculator_steps.rb +19 -0
- data/examples/i18n/ru/features/support/env.rb +5 -0
- data/examples/i18n/ru/features/support/world.rb +8 -0
- data/examples/i18n/ru/lib/calculator.rb +24 -0
- data/examples/i18n/sk/.gitignore +1 -0
- data/examples/i18n/sk/Rakefile +6 -0
- data/examples/i18n/sk/features/addition.feature +17 -0
- data/examples/i18n/sk/features/division.feature +10 -0
- data/examples/i18n/sk/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/sk/lib/calculator.rb +14 -0
- data/examples/i18n/sr-Cyrl/Rakefile +6 -0
- data/examples/i18n/sr-Cyrl/features/sabiranje.feature +18 -0
- data/examples/i18n/sr-Cyrl/features/step_definitons/calculator_steps.rb +20 -0
- data/examples/i18n/sr-Cyrl/features/support/env.rb +5 -0
- data/examples/i18n/sr-Cyrl/lib/calculator.rb +12 -0
- data/examples/i18n/sr-Latn/Rakefile +6 -0
- data/examples/i18n/sr-Latn/features/sabiranje.feature +18 -0
- data/examples/i18n/sr-Latn/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/sr-Latn/lib/calculator.rb +12 -0
- data/examples/i18n/sv/Rakefile +6 -0
- data/examples/i18n/sv/features/step_definitons/kalkulator_steps.rb +24 -0
- data/examples/i18n/sv/features/summering.feature +18 -0
- data/examples/i18n/sv/lib/kalkulator.rb +11 -0
- data/examples/i18n/tr/.gitignore +1 -0
- data/examples/i18n/tr/Rakefile +6 -0
- data/examples/i18n/tr/features/bolme.feature +10 -0
- data/examples/i18n/tr/features/step_definitons/hesap_makinesi_adimlari.rb +24 -0
- data/examples/i18n/tr/features/toplama.feature +18 -0
- data/examples/i18n/tr/lib/hesap_makinesi.rb +15 -0
- data/examples/i18n/uk/Rakefile +6 -0
- data/examples/i18n/uk/features/addition.feature +11 -0
- data/examples/i18n/uk/features/consecutive_calculations.feature +17 -0
- data/examples/i18n/uk/features/division.feature +16 -0
- data/examples/i18n/uk/features/step_definitons/calculator_steps.rb +19 -0
- data/examples/i18n/uk/features/support/env.rb +5 -0
- data/examples/i18n/uk/features/support/world.rb +8 -0
- data/examples/i18n/uk/lib/calculator.rb +24 -0
- data/examples/i18n/uz/Rakefile +6 -0
- data/examples/i18n/uz/features/addition.feature +10 -0
- data/examples/i18n/uz/features/consecutive_calculations.feature +17 -0
- data/examples/i18n/uz/features/division.feature +17 -0
- data/examples/i18n/uz/features/step_definitons/calculator_steps.rb +19 -0
- data/examples/i18n/uz/features/support/env.rb +5 -0
- data/examples/i18n/uz/features/support/world.rb +8 -0
- data/examples/i18n/uz/lib/calculator.rb +24 -0
- data/examples/i18n/zh-CN/Rakefile +4 -0
- data/examples/i18n/zh-CN/features/addition.feature +18 -0
- data/examples/i18n/zh-CN/features/step_definitons/calculator_steps.rb +26 -0
- data/examples/i18n/zh-CN/lib/calculator.rb +10 -0
- data/examples/i18n/zh-TW/.gitignore +1 -0
- data/examples/i18n/zh-TW/Rakefile +4 -0
- data/examples/i18n/zh-TW/features/addition.feature +17 -0
- data/examples/i18n/zh-TW/features/division.feature +11 -0
- data/examples/i18n/zh-TW/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/zh-TW/lib/calculator.rb +14 -0
- data/examples/python/README.textile +7 -0
- data/examples/python/Rakefile +4 -0
- data/examples/python/features/fibonacci.feature +19 -0
- data/examples/python/features/step_definitions/fib_steps.py +11 -0
- data/examples/python/lib/.gitignore +1 -0
- data/examples/python/lib/fib.py +7 -0
- data/examples/ramaze/README.textile +7 -0
- data/examples/ramaze/Rakefile +6 -0
- data/examples/ramaze/app.rb +21 -0
- data/examples/ramaze/features/add.feature +11 -0
- data/examples/ramaze/features/step_definitions/add_steps.rb +15 -0
- data/examples/ramaze/features/support/env.rb +32 -0
- data/examples/ramaze/layout/default.html.erb +8 -0
- data/examples/ramaze/view/index.html.erb +5 -0
- data/examples/rspec_doubles/Rakefile +4 -0
- data/examples/rspec_doubles/features/mocking.feature +9 -0
- data/examples/rspec_doubles/features/step_definitions/calvin_steps.rb +19 -0
- data/examples/rspec_doubles/features/support/env.rb +12 -0
- data/examples/ruby2python/README.textile +7 -0
- data/examples/ruby2python/Rakefile +4 -0
- data/examples/ruby2python/features/fibonacci.feature +19 -0
- data/examples/ruby2python/features/step_definitions/fib_steps.rb +7 -0
- data/examples/ruby2python/features/support/env.rb +21 -0
- data/examples/ruby2python/lib/.gitignore +1 -0
- data/examples/ruby2python/lib/fib.py +7 -0
- data/examples/sinatra/README.textile +13 -0
- data/examples/sinatra/Rakefile +6 -0
- data/examples/sinatra/app.rb +14 -0
- data/examples/sinatra/features/add.feature +11 -0
- data/examples/sinatra/features/step_definitions/add_steps.rb +15 -0
- data/examples/sinatra/features/support/env.rb +10 -0
- data/examples/sinatra/views/add.erb +7 -0
- data/examples/sinatra/views/layout.erb +8 -0
- data/examples/tcl/README.textile +11 -0
- data/examples/tcl/Rakefile +6 -0
- data/examples/tcl/features/fibonnacci.feature +17 -0
- data/examples/tcl/features/step_definitions/fib_steps.rb +7 -0
- data/examples/tcl/features/support/env.rb +6 -0
- data/examples/tcl/src/fib.tcl +3 -0
- data/examples/test_unit/Rakefile +6 -0
- data/examples/test_unit/features/step_definitions/test_unit_steps.rb +23 -0
- data/examples/test_unit/features/test_unit.feature +9 -0
- data/examples/v8/Rakefile +6 -0
- data/examples/v8/features/fibonacci.feature +43 -0
- data/examples/v8/features/step_definitions/fib_steps.js +49 -0
- data/examples/v8/features/support/env.js +14 -0
- data/examples/v8/lib/fibonacci.js +19 -0
- data/examples/watir/.gitignore +2 -0
- data/examples/watir/README.textile +16 -0
- data/examples/watir/Rakefile +12 -0
- data/examples/watir/cucumber.yml +1 -0
- data/examples/watir/features/search.feature +12 -0
- data/examples/watir/features/step_definitions/search_steps.rb +26 -0
- data/examples/watir/features/support/env.rb +32 -0
- data/examples/watir/features/support/screenshots.rb +47 -0
- data/features/background.feature +498 -0
- data/features/bootstrap.feature +13 -0
- data/features/custom_formatter.feature +41 -0
- data/features/execute_with_tag_filter.feature +63 -0
- data/features/hooks.feature +59 -0
- data/features/iso-8859-1.feature +6 -0
- data/features/json_formatter.feature +248 -0
- data/features/stats_formatters.feature +70 -0
- data/features/step_definitions/cucumber-features/cucumber_ruby_mappings.rb +168 -0
- data/features/step_definitions/cucumber_steps.rb +23 -0
- data/features/step_definitions/iso-8859-1_steps.rb +24 -0
- data/features/support/env.rb +26 -0
- data/features/tagged_hooks.feature +217 -0
- data/features/transforms.feature +63 -0
- data/fixtures/json/features/background.feature +7 -0
- data/fixtures/json/features/embed.feature +4 -0
- data/fixtures/json/features/one_passing_one_failing.feature +11 -0
- data/fixtures/json/features/step_definitions/steps.rb +32 -0
- data/fixtures/json/features/tables.feature +13 -0
- data/fixtures/junit/features/one_passing_one_failing.feature +8 -0
- data/fixtures/junit/features/pending.feature +7 -0
- data/fixtures/junit/features/scenario_outline.feature +9 -0
- data/fixtures/junit/features/some_subdirectory/one_passing_one_failing.feature +8 -0
- data/fixtures/junit/features/step_definitions/steps.rb +11 -0
- data/fixtures/self_test/.gitignore +1 -0
- data/fixtures/self_test/README.textile +6 -0
- data/fixtures/self_test/Rakefile +6 -0
- data/fixtures/self_test/features/call_undefined_step_from_step_def.feature +7 -0
- data/fixtures/self_test/features/failing_expectation.feature +4 -0
- data/fixtures/self_test/features/lots_of_undefined.feature +8 -0
- data/fixtures/self_test/features/multiline_name.feature +27 -0
- data/fixtures/self_test/features/outline_sample.feature +15 -0
- data/fixtures/self_test/features/sample.feature +21 -0
- data/fixtures/self_test/features/search_sample.feature +32 -0
- data/fixtures/self_test/features/step_definitions/sample_steps.rb +84 -0
- data/fixtures/self_test/features/support/bubble_256x256.png +0 -0
- data/fixtures/self_test/features/support/env.rb +26 -0
- data/fixtures/self_test/features/tags_sample.feature +17 -0
- data/fixtures/self_test/features/tons_of_cukes.feature +52 -0
- data/fixtures/self_test/features/undefined_multiline_args.feature +12 -0
- data/fixtures/self_test/list-of-features.txt +1 -0
- data/fixtures/steps_library/features/step_definitions/steps_lib1.rb +8 -0
- data/fixtures/steps_library/features/step_definitions/steps_lib2.rb +8 -0
- data/fixtures/tickets/Rakefile +20 -0
- data/fixtures/tickets/features.html +138 -0
- data/fixtures/tickets/features/172.feature +28 -0
- data/fixtures/tickets/features/177/1.feature +28 -0
- data/fixtures/tickets/features/177/2.feature +20 -0
- data/fixtures/tickets/features/177/3.feature +18 -0
- data/fixtures/tickets/features/180.feature +7 -0
- data/fixtures/tickets/features/229/tagged_hooks.feature +8 -0
- data/fixtures/tickets/features/229/tagged_hooks.rb +14 -0
- data/fixtures/tickets/features/236.feature +13 -0
- data/fixtures/tickets/features/241.feature +12 -0
- data/fixtures/tickets/features/246.feature +4 -0
- data/fixtures/tickets/features/248.feature +11 -0
- data/fixtures/tickets/features/270/back.feature +14 -0
- data/fixtures/tickets/features/270/back.steps.rb +14 -0
- data/fixtures/tickets/features/272/hooks.feature +26 -0
- data/fixtures/tickets/features/272/hooks_steps.rb +53 -0
- data/fixtures/tickets/features/279/py_string_indent.feature +25 -0
- data/fixtures/tickets/features/279/py_string_indent.steps.rb +12 -0
- data/fixtures/tickets/features/279/wrong.feature_ +11 -0
- data/fixtures/tickets/features/301/filter_background_tagged_hooks.feature +6 -0
- data/fixtures/tickets/features/301/filter_background_tagged_hooks_steps.rb +12 -0
- data/fixtures/tickets/features/306/only_background.feature +4 -0
- data/fixtures/tickets/features/around_timeout.feature +6 -0
- data/fixtures/tickets/features/gherkin_67.feature +12 -0
- data/fixtures/tickets/features/gherkin_68.feature +4 -0
- data/fixtures/tickets/features/half_manual.feature +11 -0
- data/fixtures/tickets/features/lib/eatting_machine.rb +18 -0
- data/fixtures/tickets/features/lib/pantry.rb +20 -0
- data/fixtures/tickets/features/scenario_outline.feature +95 -0
- data/fixtures/tickets/features/step_definitons/246_steps.rb +3 -0
- data/fixtures/tickets/features/step_definitons/248_steps.rb +15 -0
- data/fixtures/tickets/features/step_definitons/around_timeout_steps.rb +9 -0
- data/fixtures/tickets/features/step_definitons/half_manual_steps.rb +11 -0
- data/fixtures/tickets/features/step_definitons/scenario_outline_steps.rb +42 -0
- data/fixtures/tickets/features/step_definitons/tickets_steps.rb +88 -0
- data/fixtures/tickets/features/table_diffing.feature +13 -0
- data/fixtures/tickets/features/tickets.feature +28 -0
- data/gem_tasks/contributors.rake +15 -0
- data/gem_tasks/cucumber.rake +21 -0
- data/gem_tasks/downloads.rb +7 -0
- data/gem_tasks/environment.rake +7 -0
- data/gem_tasks/examples.rake +11 -0
- data/gem_tasks/fix_cr_lf.rake +10 -0
- data/gem_tasks/flog.rake +4 -0
- data/gem_tasks/rspec.rake +8 -0
- data/gem_tasks/sass.rake +4 -0
- data/gem_tasks/stats +14 -0
- data/gem_tasks/versions.txt +74 -0
- data/gem_tasks/yard.rake +0 -0
- data/gem_tasks/yard/default/layout/html/bubble_32x32.png +0 -0
- data/gem_tasks/yard/default/layout/html/footer.erb +5 -0
- data/gem_tasks/yard/default/layout/html/index.erb +1 -0
- data/gem_tasks/yard/default/layout/html/layout.erb +25 -0
- data/gem_tasks/yard/default/layout/html/logo.erb +1 -0
- data/gem_tasks/yard/default/layout/html/setup.rb +4 -0
- data/legacy_features/announce.feature +152 -0
- data/legacy_features/api/list_step_defs_as_json.feature +50 -0
- data/legacy_features/api/run_cli_main_with_existing_runtime.feature +34 -0
- data/legacy_features/around_hooks.feature +232 -0
- data/legacy_features/bug_371.feature +32 -0
- data/legacy_features/bug_464.feature +16 -0
- data/legacy_features/bug_475.feature +42 -0
- data/legacy_features/bug_585_tab_indentation.feature +22 -0
- data/legacy_features/bug_600.feature +73 -0
- data/legacy_features/call_steps_from_stepdefs.feature +154 -0
- data/legacy_features/cucumber_cli.feature +591 -0
- data/legacy_features/cucumber_cli_outlines.feature +117 -0
- data/legacy_features/default_snippets.feature +42 -0
- data/legacy_features/diffing.feature +25 -0
- data/legacy_features/drb_server_integration.feature +174 -0
- data/legacy_features/exception_in_after_block.feature +127 -0
- data/legacy_features/exception_in_after_step_block.feature +104 -0
- data/legacy_features/exception_in_before_block.feature +98 -0
- data/legacy_features/exclude_files.feature +20 -0
- data/legacy_features/expand.feature +60 -0
- data/legacy_features/html_formatter.feature +8 -0
- data/legacy_features/html_formatter/a.html +561 -0
- data/legacy_features/junit_formatter.feature +164 -0
- data/legacy_features/language_from_header.feature +30 -0
- data/legacy_features/language_help.feature +77 -0
- data/legacy_features/listener_debugger_formatter.feature +42 -0
- data/legacy_features/multiline_names.feature +44 -0
- data/legacy_features/post_configuration_hook.feature +50 -0
- data/legacy_features/profiles.feature +126 -0
- data/legacy_features/rake_task.feature +152 -0
- data/legacy_features/report_called_undefined_steps.feature +34 -0
- data/legacy_features/rerun_formatter.feature +52 -0
- data/legacy_features/simplest.feature +11 -0
- data/legacy_features/snippet.feature +23 -0
- data/legacy_features/snippets_when_using_star_keyword.feature +36 -0
- data/legacy_features/step_definitions/cucumber_steps.rb +172 -0
- data/legacy_features/step_definitions/extra_steps.rb +2 -0
- data/legacy_features/step_definitions/simplest_steps.rb +3 -0
- data/legacy_features/step_definitions/wire_steps.rb +34 -0
- data/legacy_features/support/env.rb +157 -0
- data/legacy_features/support/env.rb.simplest +7 -0
- data/legacy_features/support/fake_wire_server.rb +77 -0
- data/legacy_features/table_diffing.feature +45 -0
- data/legacy_features/table_mapping.feature +34 -0
- data/legacy_features/transform.feature +245 -0
- data/legacy_features/unicode_table.feature +35 -0
- data/legacy_features/wire_protocol.feature +332 -0
- data/legacy_features/wire_protocol_erb.feature +57 -0
- data/legacy_features/wire_protocol_table_diffing.feature +119 -0
- data/legacy_features/wire_protocol_tags.feature +87 -0
- data/legacy_features/wire_protocol_timeouts.feature +63 -0
- data/legacy_features/work_in_progress.feature +156 -0
- data/lib/README.rdoc +12 -0
- data/lib/autotest/cucumber.rb +6 -0
- data/lib/autotest/cucumber_mixin.rb +135 -0
- data/lib/autotest/cucumber_rails.rb +6 -0
- data/lib/autotest/cucumber_rails_rspec.rb +6 -0
- data/lib/autotest/cucumber_rails_rspec2.rb +6 -0
- data/lib/autotest/cucumber_rspec.rb +6 -0
- data/lib/autotest/cucumber_rspec2.rb +6 -0
- data/lib/autotest/discover.rb +9 -0
- data/lib/cucumber.rb +27 -0
- data/lib/cucumber/ast.rb +30 -0
- data/lib/cucumber/ast/background.rb +101 -0
- data/lib/cucumber/ast/comment.rb +31 -0
- data/lib/cucumber/ast/doc_string.rb +80 -0
- data/lib/cucumber/ast/examples.rb +46 -0
- data/lib/cucumber/ast/feature.rb +106 -0
- data/lib/cucumber/ast/feature_element.rb +78 -0
- data/lib/cucumber/ast/features.rb +35 -0
- data/lib/cucumber/ast/names.rb +13 -0
- data/lib/cucumber/ast/outline_table.rb +187 -0
- data/lib/cucumber/ast/scenario.rb +119 -0
- data/lib/cucumber/ast/scenario_outline.rb +125 -0
- data/lib/cucumber/ast/step.rb +126 -0
- data/lib/cucumber/ast/step_collection.rb +76 -0
- data/lib/cucumber/ast/step_invocation.rb +206 -0
- data/lib/cucumber/ast/table.rb +689 -0
- data/lib/cucumber/ast/tags.rb +28 -0
- data/lib/cucumber/ast/tree_walker.rb +183 -0
- data/lib/cucumber/ast/visitor.rb +11 -0
- data/lib/cucumber/broadcaster.rb +13 -0
- data/lib/cucumber/cli/configuration.rb +209 -0
- data/lib/cucumber/cli/drb_client.rb +43 -0
- data/lib/cucumber/cli/main.rb +78 -0
- data/lib/cucumber/cli/options.rb +410 -0
- data/lib/cucumber/cli/profile_loader.rb +91 -0
- data/lib/cucumber/configuration.rb +49 -0
- data/lib/cucumber/constantize.rb +34 -0
- data/lib/cucumber/core_ext/disable_mini_and_test_unit_autorun.rb +25 -0
- data/lib/cucumber/core_ext/instance_exec.rb +98 -0
- data/lib/cucumber/core_ext/proc.rb +34 -0
- data/lib/cucumber/core_ext/string.rb +9 -0
- data/lib/cucumber/errors.rb +40 -0
- data/lib/cucumber/feature_file.rb +101 -0
- data/lib/cucumber/formatter/ansicolor.rb +160 -0
- data/lib/cucumber/formatter/console.rb +187 -0
- data/lib/cucumber/formatter/cucumber.css +279 -0
- data/lib/cucumber/formatter/cucumber.sass +247 -0
- data/lib/cucumber/formatter/debug.rb +33 -0
- data/lib/cucumber/formatter/duration.rb +13 -0
- data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +83 -0
- data/lib/cucumber/formatter/gpretty.rb +24 -0
- data/lib/cucumber/formatter/html.rb +649 -0
- data/lib/cucumber/formatter/io.rb +31 -0
- data/lib/cucumber/formatter/jquery-min.js +154 -0
- data/lib/cucumber/formatter/json.rb +31 -0
- data/lib/cucumber/formatter/json_pretty.rb +13 -0
- data/lib/cucumber/formatter/junit.rb +155 -0
- data/lib/cucumber/formatter/ordered_xml_markup.rb +24 -0
- data/lib/cucumber/formatter/pdf.rb +244 -0
- data/lib/cucumber/formatter/pretty.rb +237 -0
- data/lib/cucumber/formatter/progress.rb +92 -0
- data/lib/cucumber/formatter/rerun.rb +68 -0
- data/lib/cucumber/formatter/stepdefs.rb +14 -0
- data/lib/cucumber/formatter/steps.rb +49 -0
- data/lib/cucumber/formatter/summary.rb +35 -0
- data/lib/cucumber/formatter/unicode.rb +79 -0
- data/lib/cucumber/formatter/usage.rb +127 -0
- data/lib/cucumber/js_support/js_dsl.js +57 -0
- data/lib/cucumber/js_support/js_language.rb +185 -0
- data/lib/cucumber/js_support/js_snippets.rb +27 -0
- data/lib/cucumber/language_support.rb +30 -0
- data/lib/cucumber/language_support/language_methods.rb +129 -0
- data/lib/cucumber/parser.rb +2 -0
- data/lib/cucumber/parser/gherkin_builder.rb +129 -0
- data/lib/cucumber/platform.rb +29 -0
- data/lib/cucumber/py_support/py_dsl.py +10 -0
- data/lib/cucumber/py_support/py_language.py +10 -0
- data/lib/cucumber/py_support/py_language.rb +84 -0
- data/lib/cucumber/rake/task.rb +225 -0
- data/lib/cucumber/rb_support/rb_dsl.rb +112 -0
- data/lib/cucumber/rb_support/rb_hook.rb +18 -0
- data/lib/cucumber/rb_support/rb_language.rb +195 -0
- data/lib/cucumber/rb_support/rb_step_definition.rb +82 -0
- data/lib/cucumber/rb_support/rb_transform.rb +54 -0
- data/lib/cucumber/rb_support/rb_world.rb +103 -0
- data/lib/cucumber/rb_support/regexp_argument_matcher.rb +21 -0
- data/lib/cucumber/rspec/disable_option_parser.rb +23 -0
- data/lib/cucumber/rspec/doubles.rb +16 -0
- data/lib/cucumber/runtime.rb +145 -0
- data/lib/cucumber/runtime/features_loader.rb +62 -0
- data/lib/cucumber/runtime/for_programming_languages.rb +67 -0
- data/lib/cucumber/runtime/results.rb +64 -0
- data/lib/cucumber/runtime/support_code.rb +203 -0
- data/lib/cucumber/runtime/user_interface.rb +81 -0
- data/lib/cucumber/step_argument.rb +9 -0
- data/lib/cucumber/step_definition_light.rb +20 -0
- data/lib/cucumber/step_definitions.rb +14 -0
- data/lib/cucumber/step_match.rb +115 -0
- data/lib/cucumber/step_mother.rb +10 -0
- data/lib/cucumber/wire_support/configuration.rb +31 -0
- data/lib/cucumber/wire_support/connection.rb +55 -0
- data/lib/cucumber/wire_support/request_handler.rb +32 -0
- data/lib/cucumber/wire_support/wire_exception.rb +32 -0
- data/lib/cucumber/wire_support/wire_language.rb +54 -0
- data/lib/cucumber/wire_support/wire_packet.rb +32 -0
- data/lib/cucumber/wire_support/wire_protocol.rb +44 -0
- data/lib/cucumber/wire_support/wire_protocol/requests.rb +123 -0
- data/lib/cucumber/wire_support/wire_step_definition.rb +26 -0
- data/spec/cucumber/ast/background_spec.rb +115 -0
- data/spec/cucumber/ast/doc_string_spec.rb +40 -0
- data/spec/cucumber/ast/feature_factory.rb +61 -0
- data/spec/cucumber/ast/feature_spec.rb +63 -0
- data/spec/cucumber/ast/outline_table_spec.rb +21 -0
- data/spec/cucumber/ast/scenario_outline_spec.rb +69 -0
- data/spec/cucumber/ast/step_spec.rb +66 -0
- data/spec/cucumber/ast/table_spec.rb +484 -0
- data/spec/cucumber/ast/tree_walker_spec.rb +11 -0
- data/spec/cucumber/broadcaster_spec.rb +15 -0
- data/spec/cucumber/cli/configuration_spec.rb +431 -0
- data/spec/cucumber/cli/drb_client_spec.rb +76 -0
- data/spec/cucumber/cli/main_spec.rb +137 -0
- data/spec/cucumber/cli/options_spec.rb +358 -0
- data/spec/cucumber/cli/profile_loader_spec.rb +35 -0
- data/spec/cucumber/configuration_spec.rb +23 -0
- data/spec/cucumber/core_ext/proc_spec.rb +68 -0
- data/spec/cucumber/formatter/ansicolor_spec.rb +31 -0
- data/spec/cucumber/formatter/duration_spec.rb +22 -0
- data/spec/cucumber/formatter/html_spec.rb +256 -0
- data/spec/cucumber/formatter/junit_spec.rb +125 -0
- data/spec/cucumber/formatter/progress_spec.rb +38 -0
- data/spec/cucumber/formatter/spec_helper.rb +52 -0
- data/spec/cucumber/rake/forked_spec.rb +62 -0
- data/spec/cucumber/rake/rcov_spec.rb +71 -0
- data/spec/cucumber/rb_support/rb_language_spec.rb +282 -0
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +98 -0
- data/spec/cucumber/rb_support/rb_transform_spec.rb +21 -0
- data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +18 -0
- data/spec/cucumber/runtime/support_code_spec.rb +112 -0
- data/spec/cucumber/runtime_spec.rb +41 -0
- data/spec/cucumber/sell_cucumbers.feature +19 -0
- data/spec/cucumber/step_match_spec.rb +69 -0
- data/spec/cucumber/wire_support/configuration_spec.rb +51 -0
- data/spec/cucumber/wire_support/connection_spec.rb +46 -0
- data/spec/cucumber/wire_support/wire_exception_spec.rb +44 -0
- data/spec/cucumber/wire_support/wire_language_spec.rb +47 -0
- data/spec/cucumber/wire_support/wire_packet_spec.rb +40 -0
- data/spec/cucumber/wire_support/wire_step_definition_spec.rb +20 -0
- data/spec/cucumber/world/pending_spec.rb +46 -0
- data/spec/spec_helper.rb +22 -0
- metadata +1044 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require 'cucumber/core_ext/string'
|
|
2
|
+
require 'cucumber/step_match'
|
|
3
|
+
|
|
4
|
+
module Cucumber
|
|
5
|
+
module Ast
|
|
6
|
+
class Step #:nodoc:
|
|
7
|
+
attr_reader :line, :keyword, :name
|
|
8
|
+
attr_writer :step_collection, :options
|
|
9
|
+
attr_accessor :feature_element, :exception, :multiline_arg
|
|
10
|
+
|
|
11
|
+
INDENT = 2
|
|
12
|
+
|
|
13
|
+
def initialize(line, keyword, name, multiline_arg=nil)
|
|
14
|
+
@line, @keyword, @name, @multiline_arg = line, keyword, name, multiline_arg
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_reader :gherkin_statement
|
|
18
|
+
def gherkin_statement(statement=nil)
|
|
19
|
+
@gherkin_statement ||= statement
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def background?
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def status
|
|
27
|
+
# Step always has status skipped, because Step is always in a ScenarioOutline
|
|
28
|
+
:skipped
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def step_invocation
|
|
32
|
+
StepInvocation.new(self, @name, @multiline_arg, [])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def step_invocation_from_cells(cells)
|
|
36
|
+
matched_cells = matched_cells(cells)
|
|
37
|
+
|
|
38
|
+
delimited_arguments = delimit_argument_names(cells.to_hash)
|
|
39
|
+
name = replace_name_arguments(delimited_arguments)
|
|
40
|
+
multiline_arg = @multiline_arg.nil? ? nil : @multiline_arg.arguments_replaced(delimited_arguments)
|
|
41
|
+
|
|
42
|
+
StepInvocation.new(self, name, multiline_arg, matched_cells)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def accept(visitor)
|
|
46
|
+
return if Cucumber.wants_to_quit
|
|
47
|
+
# The only time a Step is visited is when it is in a ScenarioOutline.
|
|
48
|
+
# Otherwise it's always StepInvocation that gets visited instead.
|
|
49
|
+
visit_step_result(visitor, first_match(visitor), @multiline_arg, :skipped, nil, nil)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def visit_step_result(visitor, step_match, multiline_arg, status, exception, background)
|
|
53
|
+
visitor.visit_step_result(@keyword, step_match, @multiline_arg, status, exception, source_indent, background)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def first_match(visitor)
|
|
57
|
+
# @feature_element is always a ScenarioOutline in this case
|
|
58
|
+
@feature_element.each_example_row do |cells|
|
|
59
|
+
argument_hash = cells.to_hash
|
|
60
|
+
delimited_arguments = delimit_argument_names(argument_hash)
|
|
61
|
+
name = replace_name_arguments(delimited_arguments)
|
|
62
|
+
step_match = visitor.step_mother.step_match(name, @name) rescue nil
|
|
63
|
+
return step_match if step_match
|
|
64
|
+
end
|
|
65
|
+
NoStepMatch.new(self, @name)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def to_sexp
|
|
69
|
+
[:step, @line, @keyword, @name, (@multiline_arg.nil? ? nil : @multiline_arg.to_sexp)].compact
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def source_indent
|
|
73
|
+
@feature_element.source_indent(text_length)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def text_length(name=@name)
|
|
77
|
+
INDENT + INDENT + @keyword.unpack('U*').length + name.unpack('U*').length
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def backtrace_line
|
|
81
|
+
@backtrace_line ||= @feature_element.backtrace_line("#{@keyword}#{@name}", @line) unless @feature_element.nil?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def file_colon_line
|
|
85
|
+
@file_colon_line ||= @feature_element.file_colon_line(@line) unless @feature_element.nil?
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def language
|
|
89
|
+
@feature_element.language
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def dom_id
|
|
93
|
+
@dom_id ||= file_colon_line.gsub(/\//, '_').gsub(/\./, '_').gsub(/:/, '_')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
def matched_cells(cells)
|
|
99
|
+
col_index = 0
|
|
100
|
+
cells.select do |cell|
|
|
101
|
+
header_cell = cell.table.header_cell(col_index)
|
|
102
|
+
col_index += 1
|
|
103
|
+
delimited = delimited(header_cell.value)
|
|
104
|
+
@name.index(delimited) || (@multiline_arg && @multiline_arg.has_text?(delimited))
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def delimit_argument_names(argument_hash)
|
|
109
|
+
argument_hash.inject({}) { |h,(name,value)| h[delimited(name)] = value; h }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def delimited(s)
|
|
113
|
+
"<#{s}>"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def replace_name_arguments(argument_hash)
|
|
117
|
+
name_with_arguments_replaced = @name
|
|
118
|
+
argument_hash.each do |name, value|
|
|
119
|
+
value ||= ''
|
|
120
|
+
name_with_arguments_replaced = name_with_arguments_replaced.gsub(name, value)
|
|
121
|
+
end
|
|
122
|
+
name_with_arguments_replaced
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
module Ast
|
|
3
|
+
# Holds an Array of Step or StepDefinition
|
|
4
|
+
class StepCollection #:nodoc:
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
def initialize(steps)
|
|
8
|
+
@steps = steps
|
|
9
|
+
@steps.each{|step| step.step_collection = self}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def accept(visitor, &proc)
|
|
13
|
+
return if Cucumber.wants_to_quit
|
|
14
|
+
@steps.each do |step|
|
|
15
|
+
visitor.visit_step(step) if proc.nil? || proc.call(step)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def step_invocations(background = false)
|
|
20
|
+
StepCollection.new(@steps.map{ |step|
|
|
21
|
+
i = step.step_invocation
|
|
22
|
+
i.background = background
|
|
23
|
+
i
|
|
24
|
+
})
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def step_invocations_from_cells(cells)
|
|
28
|
+
@steps.map{|step| step.step_invocation_from_cells(cells)}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Duplicates this instance and adds +step_invocations+ to the end
|
|
32
|
+
def dup(step_invocations = [])
|
|
33
|
+
StepCollection.new(@steps + step_invocations)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def each(&proc)
|
|
37
|
+
@steps.each(&proc)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def previous_step(step)
|
|
41
|
+
i = @steps.index(step) || -1
|
|
42
|
+
@steps[i-1]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def empty?
|
|
46
|
+
@steps.empty?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def max_line_length(feature_element)
|
|
50
|
+
lengths = (@steps + [feature_element]).map{|e| e.text_length}
|
|
51
|
+
lengths.max
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def exception
|
|
55
|
+
@exception ||= ((failed = @steps.detect {|step| step.exception}) && failed.exception)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def failed?
|
|
59
|
+
status == :failed
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def passed?
|
|
63
|
+
status == :passed
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def status
|
|
67
|
+
@steps.each{|step_invocation| return step_invocation.status if step_invocation.status != :passed}
|
|
68
|
+
:passed
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def to_sexp
|
|
72
|
+
@steps.map{|step| step.to_sexp}
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
require 'cucumber/errors'
|
|
2
|
+
require 'cucumber/step_match'
|
|
3
|
+
require 'cucumber/ast/table'
|
|
4
|
+
require 'gherkin/rubify'
|
|
5
|
+
|
|
6
|
+
module Cucumber
|
|
7
|
+
module Ast
|
|
8
|
+
class StepInvocation #:nodoc:
|
|
9
|
+
include Gherkin::Rubify
|
|
10
|
+
|
|
11
|
+
attr_writer :step_collection, :background
|
|
12
|
+
attr_reader :name, :matched_cells, :status, :reported_exception
|
|
13
|
+
attr_accessor :exception
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
SEVERITY = [:passed, :undefined, :pending, :skipped, :failed]
|
|
17
|
+
def worst_status(statuses)
|
|
18
|
+
SEVERITY[statuses.map{|status| SEVERITY.index(status)}.max]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize(step, name, multiline_arg, matched_cells)
|
|
23
|
+
@step, @name, @multiline_arg, @matched_cells = step, name, multiline_arg, matched_cells
|
|
24
|
+
status!(:skipped)
|
|
25
|
+
@skip_invoke = @exception = @step_match = @different_table = @reported_exception = @background = nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def background?
|
|
29
|
+
@background
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def skip_invoke!
|
|
33
|
+
@skip_invoke = true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def accept(visitor)
|
|
37
|
+
return if Cucumber.wants_to_quit
|
|
38
|
+
invoke(visitor.step_mother, visitor.configuration)
|
|
39
|
+
visit_step_result(visitor)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def visit_step_result(visitor)
|
|
43
|
+
visitor.visit_step_result(
|
|
44
|
+
keyword,
|
|
45
|
+
@step_match,
|
|
46
|
+
(@different_table || @multiline_arg),
|
|
47
|
+
@status,
|
|
48
|
+
@reported_exception,
|
|
49
|
+
source_indent,
|
|
50
|
+
@background
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def invoke(step_mother, configuration)
|
|
55
|
+
find_step_match!(step_mother, configuration)
|
|
56
|
+
unless @skip_invoke || configuration.dry_run? || @exception || @step_collection.exception
|
|
57
|
+
@skip_invoke = true
|
|
58
|
+
begin
|
|
59
|
+
@step_match.invoke(@multiline_arg)
|
|
60
|
+
step_mother.after_step
|
|
61
|
+
status!(:passed)
|
|
62
|
+
rescue Pending => e
|
|
63
|
+
failed(configuration, e, false)
|
|
64
|
+
status!(:pending)
|
|
65
|
+
rescue Undefined => e
|
|
66
|
+
failed(configuration, e, false)
|
|
67
|
+
status!(:undefined)
|
|
68
|
+
rescue Cucumber::Ast::Table::Different => e
|
|
69
|
+
@different_table = e.table
|
|
70
|
+
failed(configuration, e, false)
|
|
71
|
+
status!(:failed)
|
|
72
|
+
rescue Exception => e
|
|
73
|
+
failed(configuration, e, false)
|
|
74
|
+
status!(:failed)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def find_step_match!(step_mother, configuration)
|
|
80
|
+
return if @step_match
|
|
81
|
+
begin
|
|
82
|
+
@step_match = step_mother.step_match(@name)
|
|
83
|
+
rescue Undefined => e
|
|
84
|
+
failed(configuration, e, true)
|
|
85
|
+
status!(:undefined)
|
|
86
|
+
@step_match = NoStepMatch.new(@step, @name)
|
|
87
|
+
rescue Ambiguous => e
|
|
88
|
+
failed(configuration, e, false)
|
|
89
|
+
status!(:failed)
|
|
90
|
+
@step_match = NoStepMatch.new(@step, @name)
|
|
91
|
+
end
|
|
92
|
+
step_mother.step_visited(self)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def failed(configuration, e, clear_backtrace)
|
|
96
|
+
if Cucumber::JRUBY && e.class.name == 'NativeException'
|
|
97
|
+
# JRuby's NativeException ignores #set_backtrace.
|
|
98
|
+
# We're fixing it.
|
|
99
|
+
e.instance_eval do
|
|
100
|
+
def set_backtrace(backtrace)
|
|
101
|
+
@backtrace = backtrace
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def backtrace
|
|
105
|
+
@backtrace
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
e.set_backtrace([]) if e.backtrace.nil? || clear_backtrace
|
|
111
|
+
e.backtrace << @step.backtrace_line unless @step.backtrace_line.nil?
|
|
112
|
+
e = filter_backtrace(e)
|
|
113
|
+
@exception = e
|
|
114
|
+
if(configuration.strict? || !(Undefined === e) || e.nested?)
|
|
115
|
+
@reported_exception = e
|
|
116
|
+
else
|
|
117
|
+
@reported_exception = nil
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# This constant is appended to by Cuke4Duke. Do not change its name
|
|
122
|
+
BACKTRACE_FILTER_PATTERNS = [/vendor\/rails|lib\/cucumber|bin\/cucumber:|lib\/rspec|gems\/|minitest|test\/unit/]
|
|
123
|
+
PWD_PATTERN = /#{Regexp.escape(Dir.pwd)}\//m
|
|
124
|
+
|
|
125
|
+
# This is to work around double ":in " segments in JRuby backtraces. JRuby bug?
|
|
126
|
+
def filter_backtrace(e)
|
|
127
|
+
return e if Cucumber.use_full_backtrace
|
|
128
|
+
e.backtrace.each{|line| line.gsub!(PWD_PATTERN, "./")}
|
|
129
|
+
|
|
130
|
+
filtered = (e.backtrace || []).reject do |line|
|
|
131
|
+
BACKTRACE_FILTER_PATTERNS.detect { |p| line =~ p }
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if ENV['CUCUMBER_TRUNCATE_OUTPUT']
|
|
135
|
+
# Strip off file locations
|
|
136
|
+
filtered = filtered.map do |line|
|
|
137
|
+
line =~ /(.*):in `/ ? $1 : line
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
e.set_backtrace(filtered)
|
|
142
|
+
e
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def status!(status)
|
|
146
|
+
@status = status
|
|
147
|
+
@matched_cells.each do |cell|
|
|
148
|
+
cell.status = status
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def previous
|
|
153
|
+
@step_collection.previous_step(self)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def actual_keyword
|
|
157
|
+
repeat_keywords = rubify([language.keywords('but'), language.keywords('and')]).flatten.uniq.reject{|kw| kw == '* '}
|
|
158
|
+
if repeat_keywords.index(@step.keyword) && previous
|
|
159
|
+
previous.actual_keyword
|
|
160
|
+
else
|
|
161
|
+
keyword == '* ' ? language.code_keywords.first : keyword
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def source_indent
|
|
166
|
+
@step.feature_element.source_indent(text_length)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def text_length
|
|
170
|
+
@step.text_length(@name)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def keyword
|
|
174
|
+
@step.keyword
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def multiline_arg
|
|
178
|
+
@step.multiline_arg
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def file_colon_line
|
|
182
|
+
@step.file_colon_line
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def dom_id
|
|
186
|
+
@step.dom_id
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def backtrace_line
|
|
190
|
+
@step.backtrace_line
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def language
|
|
194
|
+
@step.language
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def gherkin_statement
|
|
198
|
+
@step.gherkin_statement
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def to_sexp
|
|
202
|
+
[:step_invocation, @step.line, @step.keyword, @name, (@multiline_arg.nil? ? nil : @multiline_arg.to_sexp)].compact
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,689 @@
|
|
|
1
|
+
require 'gherkin/rubify'
|
|
2
|
+
require 'gherkin/lexer/i18n_lexer'
|
|
3
|
+
require 'gherkin/formatter/escaping'
|
|
4
|
+
|
|
5
|
+
module Cucumber
|
|
6
|
+
module Ast
|
|
7
|
+
# Step Definitions that match a plain text Step with a multiline argument table
|
|
8
|
+
# will receive it as an instance of Table. A Table object holds the data of a
|
|
9
|
+
# table parsed from a feature file and lets you access and manipulate the data
|
|
10
|
+
# in different ways.
|
|
11
|
+
#
|
|
12
|
+
# For example:
|
|
13
|
+
#
|
|
14
|
+
# Given I have:
|
|
15
|
+
# | a | b |
|
|
16
|
+
# | c | d |
|
|
17
|
+
#
|
|
18
|
+
# And a matching StepDefinition:
|
|
19
|
+
#
|
|
20
|
+
# Given /I have:/ do |table|
|
|
21
|
+
# data = table.raw
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# This will store <tt>[['a', 'b'], ['c', 'd']]</tt> in the <tt>data</tt> variable.
|
|
25
|
+
#
|
|
26
|
+
class Table
|
|
27
|
+
class Different < StandardError
|
|
28
|
+
attr_reader :table
|
|
29
|
+
|
|
30
|
+
def initialize(table)
|
|
31
|
+
super('Tables were not identical')
|
|
32
|
+
@table = table
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class Builder
|
|
37
|
+
attr_reader :rows
|
|
38
|
+
|
|
39
|
+
def initialize
|
|
40
|
+
@rows = []
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def row(row, line_number)
|
|
44
|
+
@rows << row
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def eof
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
include Enumerable
|
|
52
|
+
include Gherkin::Rubify
|
|
53
|
+
|
|
54
|
+
NULL_CONVERSIONS = Hash.new(lambda{ |cell_value| cell_value }).freeze
|
|
55
|
+
|
|
56
|
+
attr_accessor :file
|
|
57
|
+
|
|
58
|
+
def self.default_arg_name #:nodoc:
|
|
59
|
+
"table"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.parse(text, uri, offset)
|
|
63
|
+
builder = Builder.new
|
|
64
|
+
lexer = Gherkin::Lexer::I18nLexer.new(builder)
|
|
65
|
+
lexer.scan(text)
|
|
66
|
+
new(builder.rows)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Creates a new instance. +raw+ should be an Array of Array of String
|
|
70
|
+
# or an Array of Hash (similar to what #hashes returns).
|
|
71
|
+
# You don't typically create your own Table objects - Cucumber will do
|
|
72
|
+
# it internally and pass them to your Step Definitions.
|
|
73
|
+
#
|
|
74
|
+
def initialize(raw, conversion_procs = NULL_CONVERSIONS.dup)
|
|
75
|
+
@cells_class = Cells
|
|
76
|
+
@cell_class = Cell
|
|
77
|
+
raw = ensure_array_of_array(rubify(raw))
|
|
78
|
+
# Verify that it's square
|
|
79
|
+
transposed = raw.transpose
|
|
80
|
+
create_cell_matrix(raw)
|
|
81
|
+
@conversion_procs = conversion_procs
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def to_step_definition_arg
|
|
85
|
+
dup
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Creates a copy of this table, inheriting any column mappings.
|
|
89
|
+
# registered with #map_headers!
|
|
90
|
+
#
|
|
91
|
+
def dup
|
|
92
|
+
self.class.new(raw.dup, @conversion_procs.dup)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Returns a new, transposed table. Example:
|
|
96
|
+
#
|
|
97
|
+
# | a | 7 | 4 |
|
|
98
|
+
# | b | 9 | 2 |
|
|
99
|
+
#
|
|
100
|
+
# Gets converted into the following:
|
|
101
|
+
#
|
|
102
|
+
# | a | b |
|
|
103
|
+
# | 7 | 9 |
|
|
104
|
+
# | 4 | 2 |
|
|
105
|
+
#
|
|
106
|
+
def transpose
|
|
107
|
+
self.class.new(raw.transpose, @conversion_procs.dup)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Converts this table into an Array of Hash where the keys of each
|
|
111
|
+
# Hash are the headers in the table. For example, a Table built from
|
|
112
|
+
# the following plain text:
|
|
113
|
+
#
|
|
114
|
+
# | a | b | sum |
|
|
115
|
+
# | 2 | 3 | 5 |
|
|
116
|
+
# | 7 | 9 | 16 |
|
|
117
|
+
#
|
|
118
|
+
# Gets converted into the following:
|
|
119
|
+
#
|
|
120
|
+
# [{'a' => '2', 'b' => '3', 'sum' => '5'}, {'a' => '7', 'b' => '9', 'sum' => '16'}]
|
|
121
|
+
#
|
|
122
|
+
# Use #map_column! to specify how values in a column are converted.
|
|
123
|
+
#
|
|
124
|
+
def hashes
|
|
125
|
+
@hashes ||= cells_rows[1..-1].map do |row|
|
|
126
|
+
row.to_hash
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Converts this table into a Hash where the first column is
|
|
131
|
+
# used as keys and the second column is used as values
|
|
132
|
+
#
|
|
133
|
+
# | a | 2 |
|
|
134
|
+
# | b | 3 |
|
|
135
|
+
#
|
|
136
|
+
# Gets converted into the following:
|
|
137
|
+
#
|
|
138
|
+
# {'a' => '2', 'b' => '3'}
|
|
139
|
+
#
|
|
140
|
+
# The table must be exactly two columns wide
|
|
141
|
+
#
|
|
142
|
+
def rows_hash
|
|
143
|
+
return @rows_hash if @rows_hash
|
|
144
|
+
verify_table_width(2)
|
|
145
|
+
@rows_hash = self.transpose.hashes[0]
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Gets the raw data of this table. For example, a Table built from
|
|
149
|
+
# the following plain text:
|
|
150
|
+
#
|
|
151
|
+
# | a | b |
|
|
152
|
+
# | c | d |
|
|
153
|
+
#
|
|
154
|
+
# gets converted into the following:
|
|
155
|
+
#
|
|
156
|
+
# [['a', 'b'], ['c', 'd']]
|
|
157
|
+
#
|
|
158
|
+
def raw
|
|
159
|
+
cell_matrix.map do |row|
|
|
160
|
+
row.map do |cell|
|
|
161
|
+
cell.value
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def column_names #:nodoc:
|
|
167
|
+
@col_names ||= cell_matrix[0].map { |cell| cell.value }
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def rows
|
|
171
|
+
hashes.map do |hash|
|
|
172
|
+
hash.values_at *headers
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def each_cells_row(&proc) #:nodoc:
|
|
177
|
+
cells_rows.each(&proc)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def accept(visitor) #:nodoc:
|
|
181
|
+
return if Cucumber.wants_to_quit
|
|
182
|
+
cells_rows.each do |row|
|
|
183
|
+
visitor.visit_table_row(row)
|
|
184
|
+
end
|
|
185
|
+
nil
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Matches +pattern+ against the header row of the table.
|
|
189
|
+
# This is used especially for argument transforms.
|
|
190
|
+
#
|
|
191
|
+
# Example:
|
|
192
|
+
# | column_1_name | column_2_name |
|
|
193
|
+
# | x | y |
|
|
194
|
+
#
|
|
195
|
+
# table.match(/table:column_1_name,column_2_name/) #=> non-nil
|
|
196
|
+
#
|
|
197
|
+
# Note: must use 'table:' prefix on match
|
|
198
|
+
def match(pattern)
|
|
199
|
+
header_to_match = "table:#{headers.join(',')}"
|
|
200
|
+
pattern.match(header_to_match)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# For testing only
|
|
204
|
+
def to_sexp #:nodoc:
|
|
205
|
+
[:table, *cells_rows.map{|row| row.to_sexp}]
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Redefines the table headers. This makes it possible to use
|
|
209
|
+
# prettier and more flexible header names in the features. The
|
|
210
|
+
# keys of +mappings+ are Strings or regular expressions
|
|
211
|
+
# (anything that responds to #=== will work) that may match
|
|
212
|
+
# column headings in the table. The values of +mappings+ are
|
|
213
|
+
# desired names for the columns.
|
|
214
|
+
#
|
|
215
|
+
# Example:
|
|
216
|
+
#
|
|
217
|
+
# | Phone Number | Address |
|
|
218
|
+
# | 123456 | xyz |
|
|
219
|
+
# | 345678 | abc |
|
|
220
|
+
#
|
|
221
|
+
# A StepDefinition receiving this table can then map the columns
|
|
222
|
+
# with both Regexp and String:
|
|
223
|
+
#
|
|
224
|
+
# table.map_headers!(/phone( number)?/i => :phone, 'Address' => :address)
|
|
225
|
+
# table.hashes
|
|
226
|
+
# # => [{:phone => '123456', :address => 'xyz'}, {:phone => '345678', :address => 'abc'}]
|
|
227
|
+
#
|
|
228
|
+
# You may also pass in a block if you wish to convert all of the headers:
|
|
229
|
+
#
|
|
230
|
+
# table.map_headers! { |header| header.downcase }
|
|
231
|
+
# table.hashes.keys
|
|
232
|
+
# # => ['phone number', 'address']
|
|
233
|
+
#
|
|
234
|
+
# When a block is passed in along with a hash then the mappings in the hash take precendence:
|
|
235
|
+
#
|
|
236
|
+
# table.map_headers!('Address' => 'ADDRESS') { |header| header.downcase }
|
|
237
|
+
# table.hashes.keys
|
|
238
|
+
# # => ['phone number', 'ADDRESS']
|
|
239
|
+
#
|
|
240
|
+
def map_headers!(mappings={}, &block)
|
|
241
|
+
header_cells = cell_matrix[0]
|
|
242
|
+
|
|
243
|
+
if block_given?
|
|
244
|
+
header_values = header_cells.map { |cell| cell.value } - mappings.keys
|
|
245
|
+
mappings = mappings.merge(Hash[*header_values.zip(header_values.map(&block)).flatten])
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
mappings.each_pair do |pre, post|
|
|
249
|
+
mapped_cells = header_cells.select{|cell| pre === cell.value}
|
|
250
|
+
raise "No headers matched #{pre.inspect}" if mapped_cells.empty?
|
|
251
|
+
raise "#{mapped_cells.length} headers matched #{pre.inspect}: #{mapped_cells.map{|c| c.value}.inspect}" if mapped_cells.length > 1
|
|
252
|
+
mapped_cells[0].value = post
|
|
253
|
+
if @conversion_procs.has_key?(pre)
|
|
254
|
+
@conversion_procs[post] = @conversion_procs.delete(pre)
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Returns a new Table where the headers are redefined. See #map_headers!
|
|
260
|
+
def map_headers(mappings={})
|
|
261
|
+
table = self.dup
|
|
262
|
+
table.map_headers!(mappings)
|
|
263
|
+
table
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# Change how #hashes converts column values. The +column_name+ argument identifies the column
|
|
267
|
+
# and +conversion_proc+ performs the conversion for each cell in that column. If +strict+ is
|
|
268
|
+
# true, an error will be raised if the column named +column_name+ is not found. If +strict+
|
|
269
|
+
# is false, no error will be raised. Example:
|
|
270
|
+
#
|
|
271
|
+
# Given /^an expense report for (.*) with the following posts:$/ do |table|
|
|
272
|
+
# posts_table.map_column!('amount') { |a| a.to_i }
|
|
273
|
+
# posts_table.hashes.each do |post|
|
|
274
|
+
# # post['amount'] is a Fixnum, rather than a String
|
|
275
|
+
# end
|
|
276
|
+
# end
|
|
277
|
+
#
|
|
278
|
+
def map_column!(column_name, strict=true, &conversion_proc)
|
|
279
|
+
verify_column(column_name.to_s) if strict
|
|
280
|
+
@conversion_procs[column_name.to_s] = conversion_proc
|
|
281
|
+
self
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Compares +other_table+ to self. If +other_table+ contains columns
|
|
285
|
+
# and/or rows that are not in self, new columns/rows are added at the
|
|
286
|
+
# relevant positions, marking the cells in those rows/columns as
|
|
287
|
+
# <tt>surplus</tt>. Likewise, if +other_table+ lacks columns and/or
|
|
288
|
+
# rows that are present in self, these are marked as <tt>missing</tt>.
|
|
289
|
+
#
|
|
290
|
+
# <tt>surplus</tt> and <tt>missing</tt> cells are recognised by formatters
|
|
291
|
+
# and displayed so that it's easy to read the differences.
|
|
292
|
+
#
|
|
293
|
+
# Cells that are different, but <em>look</em> identical (for example the
|
|
294
|
+
# boolean true and the string "true") are converted to their Object#inspect
|
|
295
|
+
# representation and preceded with (i) - to make it easier to identify
|
|
296
|
+
# where the difference actually is.
|
|
297
|
+
#
|
|
298
|
+
# Since all tables that are passed to StepDefinitions always have String
|
|
299
|
+
# objects in their cells, you may want to use #map_column! before calling
|
|
300
|
+
# #diff!. You can use #map_column! on either of the tables.
|
|
301
|
+
#
|
|
302
|
+
# A Different error is raised if there are missing rows or columns, or
|
|
303
|
+
# surplus rows. An error is <em>not</em> raised for surplus columns.
|
|
304
|
+
# Whether to raise or not raise can be changed by setting values in
|
|
305
|
+
# +options+ to true or false:
|
|
306
|
+
#
|
|
307
|
+
# * <tt>missing_row</tt> : Raise on missing rows (defaults to true)
|
|
308
|
+
# * <tt>surplus_row</tt> : Raise on surplus rows (defaults to true)
|
|
309
|
+
# * <tt>missing_col</tt> : Raise on missing columns (defaults to true)
|
|
310
|
+
# * <tt>surplus_col</tt> : Raise on surplus columns (defaults to false)
|
|
311
|
+
#
|
|
312
|
+
# The +other_table+ argument can be another Table, an Array of Array or
|
|
313
|
+
# an Array of Hash (similar to the structure returned by #hashes).
|
|
314
|
+
#
|
|
315
|
+
# Calling this method is particularly useful in <tt>Then</tt> steps that take
|
|
316
|
+
# a Table argument, if you want to compare that table to some actual values.
|
|
317
|
+
#
|
|
318
|
+
def diff!(other_table, options={})
|
|
319
|
+
options = {:missing_row => true, :surplus_row => true, :missing_col => true, :surplus_col => false}.merge(options)
|
|
320
|
+
|
|
321
|
+
other_table = ensure_table(other_table)
|
|
322
|
+
other_table.convert_columns!
|
|
323
|
+
ensure_green!
|
|
324
|
+
|
|
325
|
+
original_width = cell_matrix[0].length
|
|
326
|
+
other_table_cell_matrix = pad!(other_table.cell_matrix)
|
|
327
|
+
padded_width = cell_matrix[0].length
|
|
328
|
+
|
|
329
|
+
missing_col = cell_matrix[0].detect{|cell| cell.status == :undefined}
|
|
330
|
+
surplus_col = padded_width > original_width
|
|
331
|
+
|
|
332
|
+
require_diff_lcs
|
|
333
|
+
cell_matrix.extend(Diff::LCS)
|
|
334
|
+
convert_columns!
|
|
335
|
+
changes = cell_matrix.diff(other_table_cell_matrix).flatten
|
|
336
|
+
|
|
337
|
+
inserted = 0
|
|
338
|
+
missing = 0
|
|
339
|
+
|
|
340
|
+
row_indices = Array.new(other_table_cell_matrix.length) {|n| n}
|
|
341
|
+
|
|
342
|
+
last_change = nil
|
|
343
|
+
missing_row_pos = nil
|
|
344
|
+
insert_row_pos = nil
|
|
345
|
+
|
|
346
|
+
changes.each do |change|
|
|
347
|
+
if(change.action == '-')
|
|
348
|
+
missing_row_pos = change.position + inserted
|
|
349
|
+
cell_matrix[missing_row_pos].each{|cell| cell.status = :undefined}
|
|
350
|
+
row_indices.insert(missing_row_pos, nil)
|
|
351
|
+
missing += 1
|
|
352
|
+
else # '+'
|
|
353
|
+
insert_row_pos = change.position + missing
|
|
354
|
+
inserted_row = change.element
|
|
355
|
+
inserted_row.each{|cell| cell.status = :comment}
|
|
356
|
+
cell_matrix.insert(insert_row_pos, inserted_row)
|
|
357
|
+
row_indices[insert_row_pos] = nil
|
|
358
|
+
inspect_rows(cell_matrix[missing_row_pos], inserted_row) if last_change && last_change.action == '-'
|
|
359
|
+
inserted += 1
|
|
360
|
+
end
|
|
361
|
+
last_change = change
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
other_table_cell_matrix.each_with_index do |other_row, i|
|
|
365
|
+
row_index = row_indices.index(i)
|
|
366
|
+
row = cell_matrix[row_index] if row_index
|
|
367
|
+
if row
|
|
368
|
+
(original_width..padded_width).each do |col_index|
|
|
369
|
+
surplus_cell = other_row[col_index]
|
|
370
|
+
row[col_index].value = surplus_cell.value if row[col_index]
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
clear_cache!
|
|
376
|
+
should_raise =
|
|
377
|
+
missing_row_pos && options[:missing_row] ||
|
|
378
|
+
insert_row_pos && options[:surplus_row] ||
|
|
379
|
+
missing_col && options[:missing_col] ||
|
|
380
|
+
surplus_col && options[:surplus_col]
|
|
381
|
+
raise Different.new(self) if should_raise
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def to_hash(cells) #:nodoc:
|
|
385
|
+
hash = Hash.new do |hash, key|
|
|
386
|
+
hash[key.to_s] if key.is_a?(Symbol)
|
|
387
|
+
end
|
|
388
|
+
column_names.each_with_index do |column_name, column_index|
|
|
389
|
+
value = @conversion_procs[column_name].call(cells.value(column_index))
|
|
390
|
+
hash[column_name] = value
|
|
391
|
+
end
|
|
392
|
+
hash
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def index(cells) #:nodoc:
|
|
396
|
+
cells_rows.index(cells)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
def verify_column(column_name) #:nodoc:
|
|
400
|
+
raise %{The column named "#{column_name}" does not exist} unless raw[0].include?(column_name)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def verify_table_width(width) #:nodoc:
|
|
404
|
+
raise %{The table must have exactly #{width} columns} unless raw[0].size == width
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
def arguments_replaced(arguments) #:nodoc:
|
|
408
|
+
raw_with_replaced_args = raw.map do |row|
|
|
409
|
+
row.map do |cell|
|
|
410
|
+
cell_with_replaced_args = cell
|
|
411
|
+
arguments.each do |name, value|
|
|
412
|
+
if cell_with_replaced_args && cell_with_replaced_args.include?(name)
|
|
413
|
+
cell_with_replaced_args = value ? cell_with_replaced_args.gsub(name, value) : nil
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
cell_with_replaced_args
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
Table.new(raw_with_replaced_args)
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def has_text?(text) #:nodoc:
|
|
423
|
+
raw.flatten.compact.detect{|cell_value| cell_value.index(text)}
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def cells_rows #:nodoc:
|
|
427
|
+
@rows ||= cell_matrix.map do |cell_row|
|
|
428
|
+
@cells_class.new(self, cell_row)
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def headers #:nodoc:
|
|
433
|
+
raw.first
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def header_cell(col) #:nodoc:
|
|
437
|
+
cells_rows[0][col]
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def cell_matrix #:nodoc:
|
|
441
|
+
@cell_matrix
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def col_width(col) #:nodoc:
|
|
445
|
+
columns[col].__send__(:width)
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def to_s(options = {}) #:nodoc:
|
|
449
|
+
require 'cucumber/formatter/pretty'
|
|
450
|
+
options = {:color => true, :indent => 2, :prefixes => TO_S_PREFIXES}.merge(options)
|
|
451
|
+
io = StringIO.new
|
|
452
|
+
|
|
453
|
+
c = Term::ANSIColor.coloring?
|
|
454
|
+
Term::ANSIColor.coloring = options[:color]
|
|
455
|
+
formatter = Formatter::Pretty.new(nil, io, options)
|
|
456
|
+
formatter.instance_variable_set('@indent', options[:indent])
|
|
457
|
+
TreeWalker.new(nil, [formatter]).visit_multiline_arg(self)
|
|
458
|
+
|
|
459
|
+
Term::ANSIColor.coloring = c
|
|
460
|
+
io.rewind
|
|
461
|
+
s = "\n" + io.read + (" " * (options[:indent] - 2))
|
|
462
|
+
s
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
private
|
|
466
|
+
|
|
467
|
+
TO_S_PREFIXES = Hash.new(' ')
|
|
468
|
+
TO_S_PREFIXES[:comment] = '(+) '
|
|
469
|
+
TO_S_PREFIXES[:undefined] = '(-) '
|
|
470
|
+
|
|
471
|
+
protected
|
|
472
|
+
|
|
473
|
+
def inspect_rows(missing_row, inserted_row) #:nodoc:
|
|
474
|
+
missing_row.each_with_index do |missing_cell, col|
|
|
475
|
+
inserted_cell = inserted_row[col]
|
|
476
|
+
if(missing_cell.value != inserted_cell.value && (missing_cell.value.to_s == inserted_cell.value.to_s))
|
|
477
|
+
missing_cell.inspect!
|
|
478
|
+
inserted_cell.inspect!
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
def create_cell_matrix(raw) #:nodoc:
|
|
484
|
+
@cell_matrix = raw.map do |raw_row|
|
|
485
|
+
line = raw_row.line rescue -1
|
|
486
|
+
raw_row.map do |raw_cell|
|
|
487
|
+
new_cell(raw_cell, line)
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def convert_columns! #:nodoc:
|
|
493
|
+
cell_matrix.transpose.each do |col|
|
|
494
|
+
conversion_proc = @conversion_procs[col[0].value]
|
|
495
|
+
col[1..-1].each do |cell|
|
|
496
|
+
cell.value = conversion_proc.call(cell.value)
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
def require_diff_lcs #:nodoc:
|
|
502
|
+
begin
|
|
503
|
+
require 'diff/lcs'
|
|
504
|
+
rescue LoadError => e
|
|
505
|
+
e.message << "\n Please gem install diff-lcs\n"
|
|
506
|
+
raise e
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
def clear_cache! #:nodoc:
|
|
511
|
+
@hashes = @rows_hash = @rows = @columns = nil
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
def columns #:nodoc:
|
|
515
|
+
@columns ||= cell_matrix.transpose.map do |cell_row|
|
|
516
|
+
@cells_class.new(self, cell_row)
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
def new_cell(raw_cell, line) #:nodoc:
|
|
521
|
+
@cell_class.new(raw_cell, self, line)
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
# Pads our own cell_matrix and returns a cell matrix of same
|
|
525
|
+
# column width that can be used for diffing
|
|
526
|
+
def pad!(other_cell_matrix) #:nodoc:
|
|
527
|
+
clear_cache!
|
|
528
|
+
cols = cell_matrix.transpose
|
|
529
|
+
unmapped_cols = other_cell_matrix.transpose
|
|
530
|
+
|
|
531
|
+
mapped_cols = []
|
|
532
|
+
|
|
533
|
+
cols.each_with_index do |col, col_index|
|
|
534
|
+
header = col[0]
|
|
535
|
+
candidate_cols, unmapped_cols = unmapped_cols.partition do |other_col|
|
|
536
|
+
other_col[0] == header
|
|
537
|
+
end
|
|
538
|
+
raise "More than one column has the header #{header}" if candidate_cols.size > 2
|
|
539
|
+
|
|
540
|
+
other_padded_col = if candidate_cols.size == 1
|
|
541
|
+
# Found a matching column
|
|
542
|
+
candidate_cols[0]
|
|
543
|
+
else
|
|
544
|
+
mark_as_missing(cols[col_index])
|
|
545
|
+
(0...other_cell_matrix.length).map do |row|
|
|
546
|
+
val = row == 0 ? header.value : nil
|
|
547
|
+
SurplusCell.new(val, self, -1)
|
|
548
|
+
end
|
|
549
|
+
end
|
|
550
|
+
mapped_cols.insert(col_index, other_padded_col)
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
unmapped_cols.each_with_index do |col, col_index|
|
|
554
|
+
empty_col = (0...cell_matrix.length).map do |row|
|
|
555
|
+
SurplusCell.new(nil, self, -1)
|
|
556
|
+
end
|
|
557
|
+
cols << empty_col
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
@cell_matrix = cols.transpose
|
|
561
|
+
(mapped_cols + unmapped_cols).transpose
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def ensure_table(table_or_array) #:nodoc:
|
|
565
|
+
return table_or_array if Table === table_or_array
|
|
566
|
+
Table.new(table_or_array)
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def ensure_array_of_array(array)
|
|
570
|
+
Hash === array[0] ? hashes_to_array(array) : array
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
def hashes_to_array(hashes) #:nodoc:
|
|
574
|
+
header = hashes[0].keys
|
|
575
|
+
[header] + hashes.map{|hash| header.map{|key| hash[key]}}
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
def ensure_green! #:nodoc:
|
|
579
|
+
each_cell{|cell| cell.status = :passed}
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
def each_cell(&proc) #:nodoc:
|
|
583
|
+
cell_matrix.each{|row| row.each(&proc)}
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
def mark_as_missing(col) #:nodoc:
|
|
587
|
+
col.each do |cell|
|
|
588
|
+
cell.status = :undefined
|
|
589
|
+
end
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
# Represents a row of cells or columns of cells
|
|
593
|
+
class Cells #:nodoc:
|
|
594
|
+
include Enumerable
|
|
595
|
+
include Gherkin::Formatter::Escaping
|
|
596
|
+
|
|
597
|
+
attr_reader :exception
|
|
598
|
+
|
|
599
|
+
def initialize(table, cells)
|
|
600
|
+
@table, @cells = table, cells
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
def accept(visitor)
|
|
604
|
+
return if Cucumber.wants_to_quit
|
|
605
|
+
each do |cell|
|
|
606
|
+
visitor.visit_table_cell(cell)
|
|
607
|
+
end
|
|
608
|
+
nil
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
# For testing only
|
|
612
|
+
def to_sexp #:nodoc:
|
|
613
|
+
[:row, line, *@cells.map{|cell| cell.to_sexp}]
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
def to_hash #:nodoc:
|
|
617
|
+
@to_hash ||= @table.to_hash(self)
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
def value(n) #:nodoc:
|
|
621
|
+
self[n].value
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def [](n)
|
|
625
|
+
@cells[n]
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
def line
|
|
629
|
+
@cells[0].line
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
def dom_id
|
|
633
|
+
"row_#{line}"
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
private
|
|
637
|
+
|
|
638
|
+
def index
|
|
639
|
+
@table.index(self)
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
def width
|
|
643
|
+
map{|cell| cell.value ? escape_cell(cell.value.to_s).unpack('U*').length : 0}.max
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
def each(&proc)
|
|
647
|
+
@cells.each(&proc)
|
|
648
|
+
end
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
class Cell #:nodoc:
|
|
652
|
+
attr_reader :line, :table
|
|
653
|
+
attr_accessor :status, :value
|
|
654
|
+
|
|
655
|
+
def initialize(value, table, line)
|
|
656
|
+
@value, @table, @line = value, table, line
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
def accept(visitor)
|
|
660
|
+
return if Cucumber.wants_to_quit
|
|
661
|
+
visitor.visit_table_cell_value(value, status)
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
def inspect!
|
|
665
|
+
@value = "(i) #{value.inspect}"
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
def ==(o)
|
|
669
|
+
SurplusCell === o || value == o.value
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
# For testing only
|
|
673
|
+
def to_sexp #:nodoc:
|
|
674
|
+
[:cell, @value]
|
|
675
|
+
end
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
class SurplusCell < Cell #:nodoc:
|
|
679
|
+
def status
|
|
680
|
+
:comment
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
def ==(o)
|
|
684
|
+
true
|
|
685
|
+
end
|
|
686
|
+
end
|
|
687
|
+
end
|
|
688
|
+
end
|
|
689
|
+
end
|