kosmas58-cucumber 0.1.16.6 → 0.1.99.21
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 +126 -2
- data/License.txt +1 -1
- data/Manifest.txt +0 -270
- data/Rakefile +1 -1
- data/bin/cucumber +2 -2
- data/config/hoe.rb +7 -2
- data/examples/cs/features/step_definitons/calculator_steps.rb +1 -1
- data/examples/i18n/README.textile +1 -1
- data/examples/i18n/Rakefile +3 -3
- data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +1 -6
- data/examples/i18n/da/features/step_definitons/kalkulator_steps.rb +1 -1
- data/examples/i18n/de/features/addition.feature +6 -6
- data/examples/i18n/de/features/step_definitons/calculator_steps.rb +2 -2
- data/examples/i18n/en/features/addition.feature +6 -6
- data/examples/i18n/en/features/step_definitons/calculator_steps.rb +2 -2
- data/examples/i18n/es/features/adicion.feature +11 -12
- data/examples/i18n/es/features/step_definitons/calculador_steps.rb +7 -10
- data/examples/i18n/es/lib/calculador.rb +4 -1
- data/examples/i18n/et/features/liitmine.feature +7 -6
- data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +1 -1
- data/examples/i18n/fi/features/step_definitons/laskin_steps.rb +1 -1
- data/examples/i18n/fi/features/yhteenlasku.feature +2 -2
- data/examples/i18n/fr/features/addition.feature +2 -2
- data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +1 -1
- data/examples/i18n/id/features/addition.feature +6 -6
- data/examples/i18n/id/features/step_definitons/calculator_steps.rb +2 -2
- data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +1 -1
- data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +2 -3
- data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +1 -1
- data/examples/i18n/lt/features/addition.feature +7 -6
- data/examples/i18n/lt/features/step_definitons/calculator_steps.rb +2 -2
- data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +7 -7
- data/examples/i18n/no/features/summering.feature +1 -0
- data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +1 -1
- data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +1 -1
- data/examples/i18n/se/features/step_definitons/kalkulator_steps.rb +1 -1
- data/examples/i18n/zh-CN/features/step_definitons/calculator_steps.rb +2 -2
- data/examples/java/src/cucumber/demo/Hello.java +16 -0
- data/examples/jbehave/README.textile +17 -0
- data/examples/jbehave/features/support/env.rb +7 -0
- data/examples/jbehave/features/trading.feature +24 -0
- data/examples/jbehave/pom.xml +48 -0
- data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/converters/TraderConverter.java +32 -0
- data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/model/Stock.java +42 -0
- data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/model/Trader.java +29 -0
- data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/persistence/TraderPersister.java +22 -0
- data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/scenarios/TraderSteps.java +65 -0
- data/examples/self_test/README.textile +4 -1
- data/examples/{calculator_ruby_features → self_test}/Rakefile +3 -3
- data/examples/self_test/features/background/failing_background.feature +10 -0
- data/examples/self_test/features/background/failing_background_after_success.feature +11 -0
- data/examples/self_test/features/background/multiline_args_background.feature +32 -0
- data/examples/self_test/features/background/passing_background.feature +10 -0
- data/examples/self_test/features/background/pending_background.feature +10 -0
- data/examples/self_test/features/background/scenario_outline_failing_background.feature +16 -0
- data/examples/self_test/features/background/scenario_outline_passing_background.feature +16 -0
- data/examples/self_test/features/call_undefined_step_from_step_def.feature +7 -0
- data/examples/self_test/features/lots_of_undefined.feature +8 -0
- data/examples/self_test/features/outline_sample.feature +11 -5
- data/examples/self_test/features/sample.feature +8 -3
- data/examples/self_test/features/step_definitions/sample_steps.rb +53 -4
- data/examples/self_test/features/support/env.rb +1 -0
- data/examples/self_test/features/support/tag_count_formatter.rb +25 -0
- data/examples/tickets/features/172.feature +28 -0
- data/examples/tickets/features/177/1.feature +29 -0
- data/examples/tickets/features/177/2.feature +21 -0
- data/examples/tickets/features/177/3.feature +18 -0
- data/examples/tickets/features/180.feature +7 -0
- data/examples/tickets/features/scenario_outline.feature +6 -1
- data/examples/tickets/features/step_definitons/tickets_steps.rb +27 -3
- data/examples/tickets/features/tickets.feature +4 -0
- data/features/background.feature +223 -0
- data/features/cucumber_cli.feature +218 -98
- data/features/cucumber_cli_outlines.feature +54 -37
- data/features/custom_formatter.feature +11 -0
- data/features/report_called_undefined_steps.feature +32 -0
- data/features/step_definitions/cucumber_steps.rb +7 -3
- data/features/step_definitions/extra_steps.rb +1 -1
- data/features/support/env.rb +2 -1
- data/gem_tasks/flog.rake +1 -1
- data/gem_tasks/gemspec.rake +2 -2
- data/gem_tasks/jar.rake +67 -0
- data/lib/autotest/cucumber_mixin.rb +17 -23
- data/lib/cucumber.rb +63 -11
- data/lib/cucumber/ast.rb +29 -0
- data/lib/cucumber/ast/background.rb +88 -0
- data/lib/cucumber/ast/comment.rb +26 -0
- data/lib/cucumber/ast/examples.rb +26 -0
- data/lib/cucumber/ast/feature.rb +66 -0
- data/lib/cucumber/ast/features.rb +39 -0
- data/lib/cucumber/ast/filter.rb +22 -0
- data/lib/cucumber/ast/outline_table.rb +49 -0
- data/lib/cucumber/ast/py_string.rb +52 -0
- data/lib/cucumber/ast/scenario.rb +103 -0
- data/lib/cucumber/ast/scenario_outline.rb +92 -0
- data/lib/cucumber/ast/step.rb +161 -0
- data/lib/cucumber/ast/steps.rb +13 -0
- data/lib/cucumber/ast/table.rb +218 -0
- data/lib/cucumber/ast/tags.rb +40 -0
- data/lib/cucumber/ast/visitor.rb +109 -0
- data/lib/cucumber/broadcaster.rb +1 -6
- data/lib/cucumber/cli/configuration.rb +339 -0
- data/lib/cucumber/cli/language_help_formatter.rb +59 -0
- data/lib/cucumber/cli/main.rb +100 -0
- data/lib/cucumber/core_ext/exception.rb +41 -8
- data/lib/cucumber/core_ext/instance_exec.rb +54 -0
- data/lib/cucumber/core_ext/proc.rb +29 -65
- data/lib/cucumber/core_ext/string.rb +19 -0
- data/lib/cucumber/formatter.rb +1 -0
- data/lib/cucumber/{formatters → formatter}/ansicolor.rb +14 -16
- data/lib/cucumber/formatter/color_io.rb +17 -0
- data/lib/cucumber/formatter/console.rb +119 -0
- data/lib/cucumber/formatter/cucumber.css +55 -0
- data/lib/cucumber/formatter/cucumber.sass +49 -0
- data/lib/cucumber/formatter/html.rb +121 -0
- data/lib/cucumber/formatter/pretty.rb +167 -0
- data/lib/cucumber/formatter/profile.rb +77 -0
- data/lib/cucumber/formatter/progress.rb +68 -0
- data/lib/cucumber/formatter/rerun.rb +35 -0
- data/lib/cucumber/formatter/unicode.rb +35 -0
- data/lib/cucumber/formatters/unicode.rb +2 -35
- data/lib/cucumber/jbehave.rb +102 -0
- data/lib/cucumber/languages.yml +128 -75
- data/lib/cucumber/parser.rb +43 -0
- data/lib/cucumber/parser/basic.rb +0 -0
- data/lib/cucumber/parser/feature.rb +1490 -0
- data/lib/cucumber/parser/feature.tt +188 -0
- data/lib/cucumber/parser/i18n.tt +31 -0
- data/lib/cucumber/parser/table.rb +402 -0
- data/lib/cucumber/parser/table.tt +59 -0
- data/lib/cucumber/parser/treetop_ext.rb +75 -0
- data/lib/cucumber/platform.rb +3 -17
- data/lib/cucumber/rails/rspec.rb +5 -2
- data/lib/cucumber/step_definition.rb +87 -0
- data/lib/cucumber/step_mother.rb +151 -66
- data/lib/cucumber/version.rb +2 -2
- data/rails_generators/cucumber/USAGE +3 -2
- data/rails_generators/cucumber/cucumber_generator.rb +33 -23
- data/rails_generators/cucumber/templates/cucumber +2 -1
- data/rails_generators/cucumber/templates/cucumber.rake +6 -1
- data/rails_generators/cucumber/templates/env.rb +1 -1
- data/rails_generators/feature/USAGE +3 -0
- data/rails_generators/feature/feature_generator.rb +30 -6
- data/spec/cucumber/ast/background_spec.rb +58 -0
- data/spec/cucumber/ast/feature_factory.rb +54 -0
- data/spec/cucumber/ast/feature_spec.rb +60 -0
- data/spec/cucumber/ast/py_string_spec.rb +40 -0
- data/spec/cucumber/ast/scenario_outline_spec.rb +64 -0
- data/spec/cucumber/ast/scenario_spec.rb +82 -0
- data/spec/cucumber/ast/step_spec.rb +45 -0
- data/spec/cucumber/ast/table_spec.rb +81 -0
- data/spec/cucumber/ast/tags_spec.rb +23 -0
- data/spec/cucumber/broadcaster_spec.rb +4 -17
- data/spec/cucumber/cli/configuration_spec.rb +239 -0
- data/spec/cucumber/cli/main_spec.rb +164 -0
- data/spec/cucumber/core_ext/proc_spec.rb +27 -35
- data/spec/cucumber/core_ext/string_spec.rb +8 -0
- data/spec/cucumber/{formatters → formatter}/ansicolor_spec.rb +2 -2
- data/spec/cucumber/formatter/html/cucumber.css +37 -0
- data/spec/cucumber/formatter/html/cucumber.js +13 -0
- data/spec/cucumber/formatter/html/index.html +45 -0
- data/spec/cucumber/formatter/html/jquery-1.3.min.js +19 -0
- data/spec/cucumber/formatter/html/jquery.uitableedit.js +100 -0
- data/spec/cucumber/formatters/profile_formatter_spec.rb +17 -16
- data/spec/cucumber/parser/feature_parser_spec.rb +281 -0
- data/spec/cucumber/parser/table_parser_spec.rb +48 -0
- data/spec/cucumber/step_definition_spec.rb +62 -0
- data/spec/cucumber/step_mother_spec.rb +50 -51
- data/spec/cucumber/treetop_parser/empty_feature.feature +1 -1
- data/spec/cucumber/treetop_parser/scenario_outline.feature +1 -1
- data/spec/cucumber/treetop_parser/spaces.feature +3 -1
- data/spec/cucumber/treetop_parser/with_comments.feature +1 -1
- data/spec/cucumber/treetop_parser/with_tags.feature +18 -0
- data/spec/cucumber/world/pending_spec.rb +13 -12
- data/spec/spec_helper.rb +1 -1
- metadata +107 -79
- data/examples/calculator_ruby_features/features/addition.rb +0 -39
- data/examples/calculator_ruby_features/features/step_definitons/calculator_steps.rb +0 -43
- data/gem_tasks/treetop.rake +0 -41
- data/lib/cucumber/cli.rb +0 -355
- data/lib/cucumber/executor.rb +0 -205
- data/lib/cucumber/formatters.rb +0 -1
- data/lib/cucumber/formatters/autotest_formatter.rb +0 -23
- data/lib/cucumber/formatters/cucumber.css +0 -132
- data/lib/cucumber/formatters/cucumber.js +0 -11
- data/lib/cucumber/formatters/html_formatter.rb +0 -152
- data/lib/cucumber/formatters/jquery.js +0 -32
- data/lib/cucumber/formatters/pretty_formatter.rb +0 -285
- data/lib/cucumber/formatters/profile_formatter.rb +0 -92
- data/lib/cucumber/formatters/progress_formatter.rb +0 -61
- data/lib/cucumber/model.rb +0 -1
- data/lib/cucumber/model/table.rb +0 -32
- data/lib/cucumber/step_methods.rb +0 -49
- data/lib/cucumber/tree.rb +0 -16
- data/lib/cucumber/tree/feature.rb +0 -105
- data/lib/cucumber/tree/features.rb +0 -21
- data/lib/cucumber/tree/given_scenario.rb +0 -13
- data/lib/cucumber/tree/scenario.rb +0 -240
- data/lib/cucumber/tree/step.rb +0 -173
- data/lib/cucumber/tree/table.rb +0 -26
- data/lib/cucumber/tree/top_down_visitor.rb +0 -23
- data/lib/cucumber/treetop_parser/feature.treetop.erb +0 -254
- data/lib/cucumber/treetop_parser/feature_ar.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_cy.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_da.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_de.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_en-lol.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_en-tx.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_en.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_es.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_et.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_fi.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_fr.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_id.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_it.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_ja.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_ko.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_lt.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_nl.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_no.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_parser.rb +0 -36
- data/lib/cucumber/treetop_parser/feature_pl.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_pt.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_ro.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_ro2.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_ru.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_se.rb +0 -1951
- data/lib/cucumber/treetop_parser/feature_zh-CN.rb +0 -1951
- data/lib/cucumber/world.rb +0 -1
- data/lib/cucumber/world/pending.rb +0 -22
- data/setup.rb +0 -1585
- data/spec/cucumber/cli_spec.rb +0 -521
- data/spec/cucumber/executor_spec.rb +0 -382
- data/spec/cucumber/formatters/autotest_formatter_spec.rb +0 -26
- data/spec/cucumber/formatters/features.html +0 -269
- data/spec/cucumber/formatters/html_formatter_spec.rb +0 -110
- data/spec/cucumber/formatters/pretty_formatter_spec.rb +0 -410
- data/spec/cucumber/formatters/progress_formatter_spec.rb +0 -81
- data/spec/cucumber/model/table_spec.rb +0 -32
- data/spec/cucumber/tree/feature_spec.rb +0 -122
- data/spec/cucumber/tree/row_scenario_outline_spec.rb +0 -73
- data/spec/cucumber/tree/row_scenario_spec.rb +0 -55
- data/spec/cucumber/tree/row_step_outline_spec.rb +0 -38
- data/spec/cucumber/tree/scenario_outline_spec.rb +0 -50
- data/spec/cucumber/tree/scenario_spec.rb +0 -134
- data/spec/cucumber/tree/step_outline_spec.rb +0 -17
- data/spec/cucumber/tree/step_spec.rb +0 -59
- data/spec/cucumber/treetop_parser/feature_parser_spec.rb +0 -120
@@ -0,0 +1,59 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Parser
|
3
|
+
# TIP: When you hack on the grammar, just delete feature.rb in this directory.
|
4
|
+
# Also make sure you have uninstalled all cucumber gems (don't forget xxx-cucumber
|
5
|
+
# github gems).
|
6
|
+
#
|
7
|
+
# Treetop will then generate the parser in-memory. When you're happy, just generate
|
8
|
+
# the rb file with tt feature.tt
|
9
|
+
grammar Table
|
10
|
+
|
11
|
+
rule table
|
12
|
+
table_row+ {
|
13
|
+
def build
|
14
|
+
Ast::Table.new(raw)
|
15
|
+
end
|
16
|
+
|
17
|
+
def raw
|
18
|
+
elements.map{|e| e.build}
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
rule table_row
|
24
|
+
space* '|' cells:(cell '|')+ space* (eol+ / eof) {
|
25
|
+
def build
|
26
|
+
row = cells.elements.map do |elt|
|
27
|
+
value = elt.cell.text_value.strip
|
28
|
+
value.empty? ? nil : value
|
29
|
+
end
|
30
|
+
|
31
|
+
class << row
|
32
|
+
attr_accessor :line
|
33
|
+
end
|
34
|
+
row.line = cells.line
|
35
|
+
|
36
|
+
row
|
37
|
+
end
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
rule cell
|
42
|
+
(!('|' / eol) .)*
|
43
|
+
end
|
44
|
+
|
45
|
+
rule space
|
46
|
+
[ \t]
|
47
|
+
end
|
48
|
+
|
49
|
+
rule eol
|
50
|
+
"\n" / ("\r" "\n"?)
|
51
|
+
end
|
52
|
+
|
53
|
+
rule eof
|
54
|
+
!.
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
begin
|
2
|
+
require 'treetop'
|
3
|
+
require 'treetop/runtime'
|
4
|
+
require 'treetop/ruby_extensions'
|
5
|
+
rescue LoadError
|
6
|
+
require "rubygems"
|
7
|
+
gem "treetop"
|
8
|
+
require 'treetop'
|
9
|
+
require 'treetop/runtime'
|
10
|
+
require 'treetop/ruby_extensions'
|
11
|
+
end
|
12
|
+
|
13
|
+
module Cucumber
|
14
|
+
module Parser
|
15
|
+
module TreetopExt
|
16
|
+
FILE_LINE_PATTERN = /^([\w\W]*?):([\d:]+)$/
|
17
|
+
|
18
|
+
# Parses a file and returns a Cucumber::Ast
|
19
|
+
def parse_file(file)
|
20
|
+
_, path, lines = *FILE_LINE_PATTERN.match(file)
|
21
|
+
if path
|
22
|
+
lines = lines.split(':').map { |line| line.to_i }
|
23
|
+
else
|
24
|
+
path = file
|
25
|
+
lines = []
|
26
|
+
end
|
27
|
+
|
28
|
+
loader = lambda { |io| parse_or_fail(io.read, path) }
|
29
|
+
feature = if path =~ /^http/
|
30
|
+
require 'open-uri'
|
31
|
+
open(path, &loader)
|
32
|
+
else
|
33
|
+
File.open(path, Cucumber.file_mode('r'), &loader)
|
34
|
+
end
|
35
|
+
feature.lines = lines
|
36
|
+
feature
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class SyntaxError < StandardError
|
41
|
+
def initialize(parser, file, line_offset)
|
42
|
+
tf = parser.terminal_failures
|
43
|
+
expected = tf.size == 1 ? tf[0].expected_string.inspect : "one of #{tf.map{|f| f.expected_string.inspect}.uniq*', '}"
|
44
|
+
line = parser.failure_line + line_offset
|
45
|
+
message = "#{file}:#{line}:#{parser.failure_column}: Parse error, expected #{expected}."
|
46
|
+
super(message)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module Treetop
|
53
|
+
module Runtime
|
54
|
+
class SyntaxNode
|
55
|
+
def line
|
56
|
+
input.line_of(interval.first)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class CompiledParser
|
61
|
+
include Cucumber::Parser::TreetopExt
|
62
|
+
|
63
|
+
def parse_or_fail(s, file=nil, line=0)
|
64
|
+
parse_tree = parse(s)
|
65
|
+
if parse_tree.nil?
|
66
|
+
raise Cucumber::Parser::SyntaxError.new(self, file, line)
|
67
|
+
else
|
68
|
+
ast = parse_tree.build
|
69
|
+
ast.file = file
|
70
|
+
ast
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/cucumber/platform.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# Detect the platform we're running on so we can tweak behaviour
|
2
2
|
# in various places.
|
3
3
|
require 'rbconfig'
|
4
|
+
require 'yaml'
|
4
5
|
|
5
6
|
module Cucumber
|
6
7
|
LANGUAGE_FILE = File.expand_path(File.dirname(__FILE__) + '/languages.yml')
|
8
|
+
LANGUAGES = YAML.load_file(LANGUAGE_FILE)
|
7
9
|
BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
|
8
10
|
JRUBY = defined?(JRUBY_VERSION)
|
9
11
|
IRONRUBY = Config::CONFIG['sitedir'] =~ /IronRuby/
|
@@ -12,21 +14,5 @@ module Cucumber
|
|
12
14
|
RAILS = defined?(Rails)
|
13
15
|
RUBY_BINARY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
|
14
16
|
RUBY_1_9 = RUBY_VERSION =~ /^1\.9/
|
15
|
-
|
16
|
-
class << self
|
17
|
-
attr_reader :language
|
18
|
-
|
19
|
-
def load_language(lang)
|
20
|
-
@language = config[lang]
|
21
|
-
end
|
22
|
-
|
23
|
-
def languages
|
24
|
-
config.keys.sort
|
25
|
-
end
|
26
|
-
|
27
|
-
def config
|
28
|
-
require 'yaml'
|
29
|
-
@config ||= YAML.load_file(LANGUAGE_FILE)
|
30
|
-
end
|
31
|
-
end
|
17
|
+
EXCEPTION_STATUS = Hash.new(:failed)
|
32
18
|
end
|
data/lib/cucumber/rails/rspec.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
require 'cucumber/rails/world'
|
1
2
|
require 'spec/expectations'
|
2
3
|
require 'spec/rails/matchers'
|
3
4
|
|
4
|
-
|
5
|
-
|
5
|
+
Cucumber::Rails::World.class_eval do
|
6
|
+
include Spec::Matchers
|
7
|
+
include Spec::Rails::Matchers
|
8
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'cucumber/core_ext/string'
|
2
|
+
require 'cucumber/core_ext/proc'
|
3
|
+
|
4
|
+
module Cucumber
|
5
|
+
# A Step Definition holds a Regexp and a Proc, and is created
|
6
|
+
# by calling <tt>Given</tt>, <tt>When</tt> or <tt>Then</tt>
|
7
|
+
# in the <tt>step_definitions</tt> ruby files - for example:
|
8
|
+
#
|
9
|
+
# Given /I have (\d+) cucumbers in my belly/ do
|
10
|
+
# # some code here
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
class StepDefinition
|
14
|
+
def self.snippet_text(step_keyword, step_name)
|
15
|
+
escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/')
|
16
|
+
"#{step_keyword} /^#{escaped}$/ do\n pending\nend"
|
17
|
+
end
|
18
|
+
|
19
|
+
class MissingProc < StandardError
|
20
|
+
def message
|
21
|
+
"Step definitions must always have a proc"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :regexp
|
26
|
+
|
27
|
+
def initialize(pattern, &proc)
|
28
|
+
raise MissingProc if proc.nil?
|
29
|
+
if String === pattern
|
30
|
+
p = pattern.gsub(/\$\w+/, '(.*)')
|
31
|
+
pattern = Regexp.new("^#{p}$")
|
32
|
+
end
|
33
|
+
@regexp, @proc = pattern, proc
|
34
|
+
end
|
35
|
+
|
36
|
+
#:stopdoc:
|
37
|
+
|
38
|
+
def match(step_name)
|
39
|
+
case step_name
|
40
|
+
when String then @regexp.match(step_name)
|
41
|
+
when Regexp then @regexp == step_name
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Formats the matched arguments of the associated Step. This method
|
46
|
+
# is usually called from visitors, which render output.
|
47
|
+
#
|
48
|
+
# The +format+ either be a String or a Proc.
|
49
|
+
#
|
50
|
+
# If it is a String it should be a format string according to
|
51
|
+
# <tt>Kernel#sprinf</tt>, for example:
|
52
|
+
#
|
53
|
+
# '<span class="param">%s</span></tt>'
|
54
|
+
#
|
55
|
+
# If it is a Proc, it should take one argument and return the formatted
|
56
|
+
# argument, for example:
|
57
|
+
#
|
58
|
+
# lambda { |param| "[#{param}]" }
|
59
|
+
#
|
60
|
+
def format_args(step_name, format)
|
61
|
+
step_name.gzub(@regexp, format)
|
62
|
+
end
|
63
|
+
|
64
|
+
def matched_args(step_name)
|
65
|
+
step_name.match(@regexp).captures
|
66
|
+
end
|
67
|
+
|
68
|
+
def execute(step_name, world, *args)
|
69
|
+
args = args.map{|arg| Ast::PyString === arg ? arg.to_s : arg}
|
70
|
+
begin
|
71
|
+
world.cucumber_instance_exec(true, @regexp.inspect, *args, &@proc)
|
72
|
+
rescue Cucumber::ArityMismatchError => e
|
73
|
+
e.backtrace.unshift(self.to_backtrace_line)
|
74
|
+
raise e
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_backtrace_line
|
79
|
+
"#{file_colon_line}:in `#{@regexp.inspect}'"
|
80
|
+
end
|
81
|
+
|
82
|
+
def file_colon_line
|
83
|
+
@proc.file_colon_line
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
data/lib/cucumber/step_mother.rb
CHANGED
@@ -1,98 +1,183 @@
|
|
1
|
-
require 'cucumber/
|
1
|
+
require 'cucumber/step_definition'
|
2
|
+
require 'cucumber/core_ext/instance_exec'
|
2
3
|
|
3
4
|
module Cucumber
|
4
|
-
class
|
5
|
-
|
5
|
+
class Undefined < StandardError
|
6
|
+
attr_reader :step_name
|
6
7
|
|
7
|
-
|
8
|
+
def initialize(step_name)
|
9
|
+
super %{Undefined step: "#{step_name}"}
|
10
|
+
@step_name = step_name
|
11
|
+
end
|
12
|
+
Cucumber::EXCEPTION_STATUS[self] = :undefined
|
8
13
|
end
|
9
14
|
|
10
|
-
class
|
15
|
+
class Pending < StandardError
|
16
|
+
Cucumber::EXCEPTION_STATUS[self] = :pending
|
11
17
|
end
|
12
18
|
|
13
|
-
|
19
|
+
# Raised when a step matches 2 or more StepDefinition
|
20
|
+
class Ambiguous < StandardError
|
21
|
+
def initialize(step_name, step_definitions)
|
22
|
+
message = "Ambiguous match of \"#{step_name}\":\n\n"
|
23
|
+
message << step_definitions.map{|sd| sd.to_backtrace_line}.join("\n")
|
24
|
+
message << "\n\n"
|
25
|
+
super(message)
|
26
|
+
end
|
14
27
|
end
|
15
28
|
|
16
|
-
|
17
|
-
|
18
|
-
|
29
|
+
# Raised when 2 or more StepDefinition have the same Regexp
|
30
|
+
class Redundant < StandardError
|
31
|
+
def initialize(step_def_1, step_def_2)
|
32
|
+
message = "Multiple step definitions have the same Regexp:\n\n"
|
33
|
+
message << step_def_1.to_backtrace_line << "\n"
|
34
|
+
message << step_def_2.to_backtrace_line << "\n\n"
|
35
|
+
super(message)
|
19
36
|
end
|
20
37
|
end
|
21
38
|
|
22
|
-
|
23
|
-
|
24
|
-
|
39
|
+
# This is the main interface for registering step definitions, which is done
|
40
|
+
# from <tt>*_steps.rb</tt> files. This module is included right at the top-level
|
41
|
+
# so #register_step_definition (and more interestingly - its aliases) are
|
42
|
+
# available from the top-level.
|
43
|
+
module StepMother
|
44
|
+
attr_writer :snippet_generator
|
45
|
+
attr_writer :options
|
46
|
+
|
47
|
+
# Registers a new StepDefinition. This method is aliased
|
48
|
+
# to <tt>Given</tt>, <tt>When</tt> and <tt>Then</tt>.
|
49
|
+
#
|
50
|
+
# See Cucumber#alias_steps for details on how to
|
51
|
+
# create your own aliases.
|
52
|
+
#
|
53
|
+
# The +&proc+ gets executed in the context of a <tt>world</tt>
|
54
|
+
# object, which is defined by #World. A new <tt>world</tt>
|
55
|
+
# object is created for each scenario and is shared across
|
56
|
+
# step definitions within that scenario.
|
57
|
+
def register_step_definition(regexp, &proc)
|
58
|
+
step_definition = StepDefinition.new(regexp, &proc)
|
59
|
+
step_definitions.each do |already|
|
60
|
+
raise Redundant.new(already, step_definition) if already.match(regexp)
|
61
|
+
end
|
62
|
+
step_definitions << step_definition
|
63
|
+
step_definition
|
25
64
|
end
|
26
|
-
require 'cucumber/core_ext/proc'
|
27
|
-
PENDING.extend(CoreExt::CallIn)
|
28
|
-
PENDING.name = "PENDING"
|
29
65
|
|
30
|
-
def
|
31
|
-
|
66
|
+
def world(scenario, prior_world = nil, &proc)
|
67
|
+
world = prior_world || new_world
|
68
|
+
begin
|
69
|
+
(@before_procs ||= []).each do |proc|
|
70
|
+
world.cucumber_instance_exec(false, 'Before', scenario, &proc)
|
71
|
+
end
|
72
|
+
yield world
|
73
|
+
ensure
|
74
|
+
(@after_procs ||= []).each do |proc|
|
75
|
+
world.cucumber_instance_exec(false, 'After', scenario, &proc)
|
76
|
+
end
|
77
|
+
end
|
32
78
|
end
|
33
79
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
pattern = key.gsub(/\$\w+/, '(.*)')
|
40
|
-
Regexp.new("^#{pattern}$")
|
41
|
-
when Regexp
|
42
|
-
key
|
43
|
-
else
|
44
|
-
raise "Step patterns must be Regexp or String, but was: #{key.inspect}"
|
45
|
-
end
|
46
|
-
proc.extend(CoreExt::CallIn)
|
47
|
-
proc.name = key.inspect
|
80
|
+
# Registers a Before proc. You can call this method as many times as you
|
81
|
+
# want (typically from ruby scripts under <tt>support</tt>).
|
82
|
+
def Before(&proc)
|
83
|
+
(@before_procs ||= []) << proc
|
84
|
+
end
|
48
85
|
|
49
|
-
|
50
|
-
|
51
|
-
|
86
|
+
def After(&proc)
|
87
|
+
(@after_procs ||= []) << proc
|
88
|
+
end
|
52
89
|
|
53
|
-
#
|
54
|
-
#
|
90
|
+
# Registers a World proc. You can call this method as many times as you
|
91
|
+
# want (typically from ruby scripts under <tt>support</tt>).
|
92
|
+
def World(&proc)
|
93
|
+
(@world_procs ||= []) << proc
|
94
|
+
end
|
55
95
|
|
56
|
-
|
57
|
-
|
96
|
+
# Creates a new world instance
|
97
|
+
def new_world #:nodoc:
|
98
|
+
world = Object.new
|
99
|
+
(@world_procs ||= []).each do |proc|
|
100
|
+
world = proc.call(world)
|
58
101
|
end
|
59
102
|
|
60
|
-
|
61
|
-
|
103
|
+
world.extend(WorldMethods)
|
104
|
+
world.__cucumber_step_mother = self
|
62
105
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
[regexp, $~.captures, proc]
|
67
|
-
end
|
68
|
-
end.compact
|
69
|
-
|
70
|
-
case(candidates.length)
|
71
|
-
when 0
|
72
|
-
[nil, [], PENDING]
|
73
|
-
when 1
|
74
|
-
candidates[0]
|
75
|
-
else
|
76
|
-
message = %{Multiple step definitions match #{step_name.inspect}:
|
106
|
+
world.extend(::Spec::Matchers) if defined?(::Spec::Matchers)
|
107
|
+
world
|
108
|
+
end
|
77
109
|
|
78
|
-
#
|
110
|
+
# Looks up the StepDefinition that matches +step_name+
|
111
|
+
def step_definition(step_name) #:nodoc:
|
112
|
+
found = step_definitions.select do |step_definition|
|
113
|
+
step_definition.match(step_name)
|
114
|
+
end
|
115
|
+
raise Undefined.new(step_name) if found.empty?
|
116
|
+
found = best_matches(step_name, found) if found.size > 1 && options[:guess]
|
117
|
+
raise Ambiguous.new(step_name, found) if found.size > 1
|
118
|
+
found[0]
|
119
|
+
end
|
79
120
|
|
80
|
-
|
81
|
-
|
121
|
+
def best_matches(step_name, step_definitions)
|
122
|
+
top_group_score = step_definitions.map {|s| s.match(step_name).captures.length }.sort.last
|
123
|
+
top_groups = step_definitions.select {|s| s.match(step_name).captures.length == top_group_score }
|
124
|
+
if top_groups.size > 1
|
125
|
+
shortest_capture_length = top_groups.map {|s| s.match(step_name).captures.inject(0) {|sum, c| sum + c.length } }.sort.first
|
126
|
+
top_groups.select {|s| s.match(step_name).captures.inject(0) {|sum, c| sum + c.length } == shortest_capture_length }
|
127
|
+
else
|
128
|
+
top_groups
|
82
129
|
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def proc_for(regexp)
|
86
|
-
@step_procs[regexp]
|
87
130
|
end
|
88
131
|
|
89
|
-
def
|
90
|
-
|
91
|
-
proc != PENDING
|
132
|
+
def step_definitions
|
133
|
+
@step_definitions ||= []
|
92
134
|
end
|
135
|
+
|
136
|
+
def snippet_text(step_keyword, step_name)
|
137
|
+
@snippet_generator.snippet_text(step_keyword, step_name)
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
93
141
|
|
94
|
-
|
95
|
-
|
142
|
+
def options
|
143
|
+
@options || {}
|
144
|
+
end
|
145
|
+
|
146
|
+
module WorldMethods #:nodoc:
|
147
|
+
attr_writer :__cucumber_step_mother, :__cucumber_current_step
|
148
|
+
|
149
|
+
# Call a step from within a step definition
|
150
|
+
def __cucumber_invoke(name, *multiline_arguments)
|
151
|
+
begin
|
152
|
+
# TODO: Very similar to code in Step. Refactor. Get back StepInvocation?
|
153
|
+
# Make more similar to JBehave?
|
154
|
+
step_definition = @__cucumber_step_mother.step_definition(name)
|
155
|
+
matched_args = step_definition.matched_args(name)
|
156
|
+
args = (matched_args + multiline_arguments)
|
157
|
+
step_definition.execute(name, self, *args)
|
158
|
+
rescue Exception => e
|
159
|
+
@__cucumber_current_step.exception = e
|
160
|
+
raise e
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def table(text, file=nil, line=0)
|
165
|
+
@table_parser ||= Parser::TableParser.new
|
166
|
+
@table_parser.parse_or_fail(text.strip, file, line)
|
167
|
+
end
|
168
|
+
|
169
|
+
def pending(message = "TODO")
|
170
|
+
if block_given?
|
171
|
+
begin
|
172
|
+
yield
|
173
|
+
rescue Exception => e
|
174
|
+
raise Pending.new(message)
|
175
|
+
end
|
176
|
+
raise Pending.new("Expected pending '#{message}' to fail. No Error was raised. No longer pending?")
|
177
|
+
else
|
178
|
+
raise Pending.new(message)
|
179
|
+
end
|
180
|
+
end
|
96
181
|
end
|
97
182
|
end
|
98
183
|
end
|