elight-cucumber 0.1.9
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 +150 -0
- data/License.txt +20 -0
- data/Manifest.txt +186 -0
- data/README.txt +41 -0
- data/Rakefile +5 -0
- data/TODO.txt +26 -0
- data/bin/cucumber +4 -0
- data/config/hoe.rb +69 -0
- data/config/requirements.rb +15 -0
- data/cucumber.yml +1 -0
- data/examples/calculator/README.txt +5 -0
- data/examples/calculator/Rakefile +5 -0
- data/examples/calculator/features/addition.feature +17 -0
- data/examples/calculator/features/division.feature +10 -0
- data/examples/calculator/features/steps/calculator_steps.rb +31 -0
- data/examples/calculator/lib/calculator.rb +16 -0
- data/examples/calculator_ruby_features/Rakefile +6 -0
- data/examples/calculator_ruby_features/features/addition.rb +23 -0
- data/examples/calculator_ruby_features/features/steps/calculator_steps.rb +43 -0
- data/examples/calculatrice_francaise_avec_soit_scenario/Rakefile +6 -0
- data/examples/calculatrice_francaise_avec_soit_scenario/features/addition.feature +13 -0
- data/examples/calculatrice_francaise_avec_soit_scenario/features/calculatrice_steps.rb +31 -0
- data/examples/chinese_simplified_calculator/Rakefile +6 -0
- data/examples/chinese_simplified_calculator/features/addition.feature +17 -0
- data/examples/chinese_simplified_calculator/features/steps/calculator_steps.rb +24 -0
- data/examples/chinese_simplified_calculator/lib/calculator.rb +10 -0
- data/examples/cs/README.textile +22 -0
- data/examples/cs/Rakefile +12 -0
- data/examples/cs/features/hello.feature +11 -0
- data/examples/cs/features/steps/hello_steps.rb +25 -0
- data/examples/cs/features/steps/tree_steps.rb +14 -0
- data/examples/cs/features/tree.feature +9 -0
- data/examples/cs/src/Hello.cs +18 -0
- data/examples/danish_calculator/Rakefile +6 -0
- data/examples/danish_calculator/features/steps/kalkulator_steps.rb +22 -0
- data/examples/danish_calculator/features/summering.feature +17 -0
- data/examples/danish_calculator/lib/kalkulator.rb +11 -0
- data/examples/dos_line_endings/Rakefile +6 -0
- data/examples/dos_line_endings/features/dos_line_endings.feature +9 -0
- data/examples/estonian_calculator/Rakefile +6 -0
- data/examples/estonian_calculator/features/kalkulaator_steps.rb +35 -0
- data/examples/estonian_calculator/features/liitmine.feature +16 -0
- data/examples/japanese_calculator/README.txt +5 -0
- data/examples/japanese_calculator/Rakefile +6 -0
- data/examples/japanese_calculator/features/addition.feature +17 -0
- data/examples/japanese_calculator/features/division.feature +10 -0
- data/examples/japanese_calculator/features/steps/calculator_steps.rb +30 -0
- data/examples/japanese_calculator/lib/calculator.rb +16 -0
- data/examples/java/README.textile +22 -0
- data/examples/java/Rakefile +12 -0
- data/examples/java/features/hello.feature +11 -0
- data/examples/java/features/steps/hello_steps.rb +25 -0
- data/examples/java/features/steps/tree_steps.rb +14 -0
- data/examples/java/features/tree.feature +9 -0
- data/examples/java/src/cucumber/demo/Hello.java +16 -0
- data/examples/norwegian_calculator/Rakefile +6 -0
- data/examples/norwegian_calculator/features/steps/kalkulator_steps.rb +22 -0
- data/examples/norwegian_calculator/features/summering.feature +17 -0
- data/examples/norwegian_calculator/lib/kalkulator.rb +11 -0
- data/examples/portuguese_calculator/Rakefile +6 -0
- data/examples/portuguese_calculator/features/adicao.feature +10 -0
- data/examples/portuguese_calculator/features/calculadora_steps.rb +31 -0
- data/examples/selenium/Rakefile +6 -0
- data/examples/selenium/features/search.feature +9 -0
- data/examples/selenium/features/steps/stories_steps.rb +41 -0
- data/examples/spanish_calculator/Rakefile +6 -0
- data/examples/spanish_calculator/features/adicion.feature +17 -0
- data/examples/spanish_calculator/features/steps/calculador_steps.rb +22 -0
- data/examples/swedish_calculator/Rakefile +5 -0
- data/examples/swedish_calculator/features/steps/kalkulator_steps.rb +22 -0
- data/examples/swedish_calculator/features/summering.feature +17 -0
- data/examples/swedish_calculator/lib/kalkulator.rb +11 -0
- data/examples/tickets/Rakefile +11 -0
- data/examples/tickets/cucumber.yml +2 -0
- data/examples/tickets/features/steps/tickets_steps.rb +32 -0
- data/examples/tickets/features/tickets.feature +22 -0
- data/examples/watir/Rakefile +6 -0
- data/examples/watir/features/search.feature +9 -0
- data/examples/watir/features/steps/stories_steps.rb +51 -0
- data/features/see_features.feature +8 -0
- data/features/steps/features_steps.rb +9 -0
- data/gem_tasks/deployment.rake +34 -0
- data/gem_tasks/environment.rake +7 -0
- data/gem_tasks/features.rake +6 -0
- data/gem_tasks/fix_cr_lf.rake +10 -0
- data/gem_tasks/flog.rake +4 -0
- data/gem_tasks/gemspec.rake +6 -0
- data/gem_tasks/rspec.rake +21 -0
- data/gem_tasks/treetop.rake +49 -0
- data/lib/cucumber.rb +35 -0
- data/lib/cucumber/cli.rb +191 -0
- data/lib/cucumber/core_ext/proc.rb +55 -0
- data/lib/cucumber/core_ext/string.rb +22 -0
- data/lib/cucumber/executor.rb +143 -0
- data/lib/cucumber/formatters.rb +1 -0
- data/lib/cucumber/formatters/ansicolor.rb +112 -0
- data/lib/cucumber/formatters/cucumber.css +132 -0
- data/lib/cucumber/formatters/cucumber.js +11 -0
- data/lib/cucumber/formatters/html_formatter.rb +128 -0
- data/lib/cucumber/formatters/jquery.js +32 -0
- data/lib/cucumber/formatters/pretty_formatter.rb +211 -0
- data/lib/cucumber/formatters/profile_formatter.rb +92 -0
- data/lib/cucumber/formatters/progress_formatter.rb +51 -0
- data/lib/cucumber/languages.yml +142 -0
- data/lib/cucumber/model.rb +1 -0
- data/lib/cucumber/model/table.rb +28 -0
- data/lib/cucumber/rails/rspec.rb +12 -0
- data/lib/cucumber/rails/world.rb +73 -0
- data/lib/cucumber/rake/task.rb +75 -0
- data/lib/cucumber/step_methods.rb +49 -0
- data/lib/cucumber/step_mother.rb +83 -0
- data/lib/cucumber/tree.rb +18 -0
- data/lib/cucumber/tree/feature.rb +60 -0
- data/lib/cucumber/tree/features.rb +21 -0
- data/lib/cucumber/tree/given_scenario.rb +13 -0
- data/lib/cucumber/tree/scenario.rb +150 -0
- data/lib/cucumber/tree/step.rb +133 -0
- data/lib/cucumber/tree/table.rb +26 -0
- data/lib/cucumber/tree/top_down_visitor.rb +23 -0
- data/lib/cucumber/treetop_parser/feature.treetop.erb +201 -0
- data/lib/cucumber/treetop_parser/feature_da.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_de.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_en-tx.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_en.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_es.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_et.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_fr.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_ja.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_nl.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_no.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_parser.rb +34 -0
- data/lib/cucumber/treetop_parser/feature_pt.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_ru.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_se.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_zh-CN.rb +1593 -0
- data/lib/cucumber/version.rb +9 -0
- data/rails_generators/cucumber/cucumber_generator.rb +29 -0
- data/rails_generators/cucumber/templates/common_webrat.rb +42 -0
- data/rails_generators/cucumber/templates/cucumber +2 -0
- data/rails_generators/cucumber/templates/cucumber.rake +12 -0
- data/rails_generators/cucumber/templates/cucumber.yml +1 -0
- data/rails_generators/cucumber/templates/env.rb +8 -0
- data/rails_generators/feature/feature_generator.rb +17 -0
- data/rails_generators/feature/templates/feature.erb +28 -0
- data/rails_generators/feature/templates/steps.erb +22 -0
- data/script/console +10 -0
- data/script/console.cmd +1 -0
- data/script/destroy +14 -0
- data/script/destroy.cmd +1 -0
- data/script/generate +14 -0
- data/script/generate.cmd +1 -0
- data/script/txt2html +74 -0
- data/script/txt2html.cmd +1 -0
- data/setup.rb +1585 -0
- data/spec/cucumber/cli_spec.rb +56 -0
- data/spec/cucumber/core_ext/proc_spec.rb +45 -0
- data/spec/cucumber/core_ext/string_spec.rb +34 -0
- data/spec/cucumber/executor_spec.rb +130 -0
- data/spec/cucumber/formatters/ansicolor_spec.rb +35 -0
- data/spec/cucumber/formatters/features.html +269 -0
- data/spec/cucumber/formatters/html_formatter_spec.rb +74 -0
- data/spec/cucumber/formatters/pretty_formatter_spec.rb +111 -0
- data/spec/cucumber/formatters/profile_formatter_spec.rb +193 -0
- data/spec/cucumber/formatters/progress_formatter_spec.rb +45 -0
- data/spec/cucumber/model/table_spec.rb +20 -0
- data/spec/cucumber/rails/stubs/mini_rails.rb +17 -0
- data/spec/cucumber/rails/stubs/test_help.rb +1 -0
- data/spec/cucumber/rails/world_spec.rb +11 -0
- data/spec/cucumber/sell_cucumbers.feature +9 -0
- data/spec/cucumber/step_mother_spec.rb +53 -0
- data/spec/cucumber/tree/feature_spec.rb +12 -0
- data/spec/cucumber/tree/scenario_spec.rb +37 -0
- data/spec/cucumber/tree/step_spec.rb +31 -0
- data/spec/cucumber/treetop_parser/empty_feature.feature +4 -0
- data/spec/cucumber/treetop_parser/empty_scenario.feature +9 -0
- data/spec/cucumber/treetop_parser/feature_parser_spec.rb +96 -0
- data/spec/cucumber/treetop_parser/fit_scenario.feature +8 -0
- data/spec/cucumber/treetop_parser/given_scenario.feature +9 -0
- data/spec/cucumber/treetop_parser/multiline_steps.feature +13 -0
- data/spec/cucumber/treetop_parser/multiple_tables.feature +29 -0
- data/spec/cucumber/treetop_parser/spaces.feature +10 -0
- data/spec/cucumber/treetop_parser/test_dos.feature +25 -0
- data/spec/cucumber/treetop_parser/with_comments.feature +10 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +19 -0
- metadata +288 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'cucumber/step_mother'
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
# Defines "global" methods that may be used in *_steps.rb files.
|
|
5
|
+
module StepMethods
|
|
6
|
+
# Each scenario will execute in the context of what the supplied block returns.
|
|
7
|
+
def World(&proc)
|
|
8
|
+
executor.register_world_proc(&proc)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def Before(&proc)
|
|
12
|
+
executor.register_before_scenario_proc(&proc)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def After(&proc)
|
|
16
|
+
executor.register_after_scenario_proc(&proc)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def AfterStep(&proc)
|
|
20
|
+
executor.register_after_step_proc(&proc)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def Given(key, &proc)
|
|
24
|
+
step_mother.register_step_proc(key, &proc)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def When(key, &proc)
|
|
28
|
+
step_mother.register_step_proc(key, &proc)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def Then(key, &proc)
|
|
32
|
+
step_mother.register_step_proc(key, &proc)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Simple workaround for old skool steps
|
|
36
|
+
def steps_for(*_)
|
|
37
|
+
STDERR.puts "WARNING: In Cucumber the steps_for method is obsolete"
|
|
38
|
+
yield
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def step_mother #:nodoc:
|
|
42
|
+
@step_mother ||= StepMother.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def executor
|
|
46
|
+
@executor ||= Executor.new(step_mother)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'cucumber/tree/top_down_visitor'
|
|
2
|
+
require 'cucumber/core_ext/proc'
|
|
3
|
+
|
|
4
|
+
module Cucumber
|
|
5
|
+
class Pending < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class Duplicate < StandardError
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Multiple < StandardError
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class StepMother
|
|
15
|
+
PENDING = lambda do |*_|
|
|
16
|
+
raise Pending
|
|
17
|
+
end
|
|
18
|
+
PENDING.extend(CoreExt::CallIn)
|
|
19
|
+
PENDING.name = "PENDING"
|
|
20
|
+
|
|
21
|
+
def initialize
|
|
22
|
+
@step_procs = Hash.new(PENDING)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def register_step_proc(key, &proc)
|
|
26
|
+
regexp = case(key)
|
|
27
|
+
when String
|
|
28
|
+
# Replace the $foo and $bar style parameters
|
|
29
|
+
pattern = key.gsub(/\$\w+/, '(.*)')
|
|
30
|
+
Regexp.new("^#{pattern}$")
|
|
31
|
+
when Regexp
|
|
32
|
+
key
|
|
33
|
+
else
|
|
34
|
+
raise "Step patterns must be Regexp or String, but was: #{key.inspect}"
|
|
35
|
+
end
|
|
36
|
+
proc.extend(CoreExt::CallIn)
|
|
37
|
+
proc.name = key.inspect
|
|
38
|
+
|
|
39
|
+
if @step_procs.has_key?(regexp)
|
|
40
|
+
first_proc = @step_procs[regexp]
|
|
41
|
+
message = %{Duplicate step definitions:
|
|
42
|
+
|
|
43
|
+
#{first_proc.to_backtrace_line}
|
|
44
|
+
#{proc.to_backtrace_line}
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
raise Duplicate.new(message)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
@step_procs[regexp] = proc
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def regexp_args_proc(step_name)
|
|
54
|
+
candidates = @step_procs.map do |regexp, proc|
|
|
55
|
+
if step_name =~ regexp
|
|
56
|
+
[regexp, $~.captures, proc]
|
|
57
|
+
end
|
|
58
|
+
end.compact
|
|
59
|
+
|
|
60
|
+
case(candidates.length)
|
|
61
|
+
when 0
|
|
62
|
+
[nil, [], PENDING]
|
|
63
|
+
when 1
|
|
64
|
+
candidates[0]
|
|
65
|
+
else
|
|
66
|
+
message = %{Multiple step definitions match #{step_name.inspect}:
|
|
67
|
+
|
|
68
|
+
#{candidates.map{|regexp, args, proc| proc.to_backtrace_line}.join("\n")}
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
raise Multiple.new(message)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def proc_for(regexp)
|
|
76
|
+
@step_procs[regexp]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# TODO - move execute here?
|
|
80
|
+
def execute(step)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
%w{features feature scenario step given_scenario table top_down_visitor}.each{|f| require "cucumber/tree/#{f}"}
|
|
2
|
+
require 'cucumber/core_ext/proc'
|
|
3
|
+
require 'cucumber/core_ext/string'
|
|
4
|
+
|
|
5
|
+
module Cucumber
|
|
6
|
+
module Tree
|
|
7
|
+
def Feature(header, &proc)
|
|
8
|
+
feature = Feature.new("Feature: " + header, &proc)
|
|
9
|
+
feature.file, _, _ = *caller[0].split(':')
|
|
10
|
+
features << feature
|
|
11
|
+
feature
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def features #:nodoc:
|
|
15
|
+
@features ||= Tree::Features.new
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
module Tree
|
|
3
|
+
class Feature
|
|
4
|
+
attr_reader :header
|
|
5
|
+
MIN_PADDING = 2
|
|
6
|
+
|
|
7
|
+
attr_accessor :file
|
|
8
|
+
|
|
9
|
+
def initialize(header, &proc)
|
|
10
|
+
@header = header
|
|
11
|
+
@scenarios = []
|
|
12
|
+
instance_eval(&proc) if block_given?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def add_scenario(name, line, &proc)
|
|
16
|
+
scenario = Scenario.new(self, name, line, &proc)
|
|
17
|
+
@scenarios << scenario
|
|
18
|
+
scenario
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_row_scenario(template_scenario, values, line)
|
|
22
|
+
scenario = RowScenario.new(self, template_scenario, values, line)
|
|
23
|
+
@scenarios << scenario
|
|
24
|
+
scenario
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def scenario_named(name)
|
|
28
|
+
@scenarios.find {|s| s.name == name}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def padding_length
|
|
32
|
+
MIN_PADDING
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def Scenario(name, &proc)
|
|
36
|
+
add_scenario(name, &proc)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def Table(matrix = [], &proc)
|
|
40
|
+
table = Table.new(matrix)
|
|
41
|
+
proc.call(table)
|
|
42
|
+
template_scenario = @scenarios.last
|
|
43
|
+
matrix[1..-1].each do |row|
|
|
44
|
+
add_row_scenario(template_scenario, row, row.line)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def accept(visitor)
|
|
49
|
+
visitor.visit_header(@header)
|
|
50
|
+
@scenarios.each do |scenario|
|
|
51
|
+
if scenario.row?
|
|
52
|
+
visitor.visit_row_scenario(scenario)
|
|
53
|
+
else
|
|
54
|
+
visitor.visit_regular_scenario(scenario)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
module Tree
|
|
3
|
+
class Features
|
|
4
|
+
def initialize
|
|
5
|
+
@features = []
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def length
|
|
9
|
+
@features.length
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def <<(feature)
|
|
13
|
+
@features << feature
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def accept(visitor)
|
|
17
|
+
@features.each{|feature| visitor.visit_feature(feature)}
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
module Tree
|
|
3
|
+
class BaseScenario
|
|
4
|
+
attr_reader :feature
|
|
5
|
+
|
|
6
|
+
def file
|
|
7
|
+
@feature.file
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def accept(visitor)
|
|
11
|
+
steps.each do |step|
|
|
12
|
+
if step.row?
|
|
13
|
+
visitor.visit_row_step(step)
|
|
14
|
+
else
|
|
15
|
+
visitor.visit_regular_step(step)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def at_line?(l)
|
|
21
|
+
line == l || steps.map{|s| s.line}.index(l)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def previous_step(step)
|
|
25
|
+
i = steps.index(step)
|
|
26
|
+
raise "Couldn't find #{step} among #{steps}" if i.nil?
|
|
27
|
+
steps[i-1]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class Scenario < BaseScenario
|
|
32
|
+
MIN_PADDING = 2
|
|
33
|
+
INDENT = 2
|
|
34
|
+
|
|
35
|
+
# If a table follows, the header will be stored here. Weird, but convenient.
|
|
36
|
+
attr_reader :table_header
|
|
37
|
+
attr_accessor :table_column_widths
|
|
38
|
+
attr_reader :name, :line
|
|
39
|
+
|
|
40
|
+
def initialize(feature, name, line, &proc)
|
|
41
|
+
@feature, @name, @line = feature, name, line
|
|
42
|
+
@steps_and_given_scenarios = []
|
|
43
|
+
instance_eval(&proc) if block_given?
|
|
44
|
+
end
|
|
45
|
+
def table_header= header
|
|
46
|
+
@table_header = header
|
|
47
|
+
update_table_column_widths header
|
|
48
|
+
end
|
|
49
|
+
def steps
|
|
50
|
+
@steps ||= @steps_and_given_scenarios.map{|step| step.steps}.flatten
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def given_scenario_steps(name)
|
|
54
|
+
sibling_named(name).steps
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def sibling_named(name)
|
|
58
|
+
@feature.scenario_named(name)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def length
|
|
62
|
+
@length ||= Cucumber.language['scenario'].length + 2 + (@name.nil? ? 0 : @name.length)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def max_line_length
|
|
66
|
+
[length, max_step_length].max
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def padding_length
|
|
70
|
+
padding = (max_line_length - length) + MIN_PADDING
|
|
71
|
+
padding += INDENT if length != max_line_length
|
|
72
|
+
padding
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def step_padding_length(step)
|
|
76
|
+
padding = (max_line_length - step.length) + MIN_PADDING
|
|
77
|
+
padding -= INDENT if length == max_line_length
|
|
78
|
+
padding
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def max_step_length
|
|
82
|
+
@max_step_length ||= (steps.map{|step| step.length}.max || 0)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def update_table_column_widths values
|
|
86
|
+
@table_column_widths ||= [0] * values.size
|
|
87
|
+
@table_column_widths = @table_column_widths.zip(values).map {|max, value| [max, value.size].max}
|
|
88
|
+
end
|
|
89
|
+
def row?
|
|
90
|
+
false
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def create_step(keyword, name, line)
|
|
94
|
+
step = Step.new(self, keyword, name, line)
|
|
95
|
+
@steps_and_given_scenarios << step
|
|
96
|
+
step
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def create_given_scenario(name, line)
|
|
100
|
+
given_scenario = GivenScenario.new(self, name, line)
|
|
101
|
+
@steps_and_given_scenarios << given_scenario
|
|
102
|
+
given_scenario
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def Given(name)
|
|
106
|
+
create_step('Given', name, *caller[0].split(':')[1].to_i)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def When(name)
|
|
110
|
+
create_step('When', name, *caller[0].split(':')[1].to_i)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def Then(name)
|
|
114
|
+
create_step('Then', name, *caller[0].split(':')[1].to_i)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def And(name)
|
|
118
|
+
create_step('And', name, *caller[0].split(':')[1].to_i)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class RowScenario < BaseScenario
|
|
124
|
+
attr_reader :line
|
|
125
|
+
|
|
126
|
+
def initialize(feature, template_scenario, values, line)
|
|
127
|
+
@feature, @template_scenario, @values, @line = feature, template_scenario, values, line
|
|
128
|
+
template_scenario.update_table_column_widths values
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def row?
|
|
132
|
+
true
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def name
|
|
136
|
+
@template_scenario.name
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def steps
|
|
140
|
+
@steps ||= @template_scenario.steps.map do |template_step|
|
|
141
|
+
args = []
|
|
142
|
+
template_step.arity.times do
|
|
143
|
+
args << @values.shift
|
|
144
|
+
end
|
|
145
|
+
RowStep.new(self, template_step, args)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
module Tree
|
|
3
|
+
class BaseStep
|
|
4
|
+
attr_reader :scenario
|
|
5
|
+
attr_accessor :error
|
|
6
|
+
|
|
7
|
+
def self.new_id!
|
|
8
|
+
@next_id ||= -1
|
|
9
|
+
@next_id += 1
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_reader :error
|
|
13
|
+
|
|
14
|
+
def file
|
|
15
|
+
@scenario.file
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def steps
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def length
|
|
23
|
+
keyword.length + 1 + name.length
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if defined?(JRUBY_VERSION)
|
|
27
|
+
PENDING_ADJUSTMENT = 2
|
|
28
|
+
REGULAR_ADJUSTMENT = 1
|
|
29
|
+
else
|
|
30
|
+
PENDING_ADJUSTMENT = 3
|
|
31
|
+
REGULAR_ADJUSTMENT = 2
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def execute_in(world, regexp, args, proc)
|
|
35
|
+
strip_pos = nil
|
|
36
|
+
begin
|
|
37
|
+
proc.call_in(world, *args)
|
|
38
|
+
rescue ArityMismatchError => e
|
|
39
|
+
e.backtrace[0] = proc.to_backtrace_line
|
|
40
|
+
strip_pos = e.backtrace.index("#{__FILE__}:#{__LINE__ - 3}:in `execute_in'")
|
|
41
|
+
format_error(strip_pos, proc, e)
|
|
42
|
+
rescue => e
|
|
43
|
+
method_line = "#{__FILE__}:#{__LINE__ - 6}:in `execute_in'"
|
|
44
|
+
method_line_pos = e.backtrace.index(method_line)
|
|
45
|
+
if method_line_pos
|
|
46
|
+
strip_pos = method_line_pos - (Pending === e ? PENDING_ADJUSTMENT : REGULAR_ADJUSTMENT)
|
|
47
|
+
else
|
|
48
|
+
# This happens with rails, because they screw up the backtrace
|
|
49
|
+
# before we get here (injecting erb stacktrace and such)
|
|
50
|
+
end
|
|
51
|
+
format_error(strip_pos, proc, e)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def format_error(strip_pos, proc, e)
|
|
56
|
+
@error = e
|
|
57
|
+
# Remove lines underneath the plain text step
|
|
58
|
+
e.backtrace[strip_pos..-1] = nil unless strip_pos.nil?
|
|
59
|
+
e.backtrace.flatten
|
|
60
|
+
# Replace the step line with something more readable
|
|
61
|
+
e.backtrace.replace(e.backtrace.map{|l| l.gsub(/`#{proc.meth}'/, "`#{keyword} #{proc.name}'")})
|
|
62
|
+
if row?
|
|
63
|
+
e.backtrace << "#{file}:#{line}:in `#{proc.name}'"
|
|
64
|
+
else
|
|
65
|
+
e.backtrace << "#{file}:#{line}:in `#{keyword} #{name}'"
|
|
66
|
+
end
|
|
67
|
+
raise e
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def id
|
|
71
|
+
@id ||= self.class.new_id!
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def actual_keyword
|
|
75
|
+
keyword == Cucumber.language['and'] ? previous_step.actual_keyword : keyword
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def previous_step
|
|
79
|
+
@scenario.previous_step(self)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def padding_length
|
|
83
|
+
@scenario.step_padding_length(self)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class Step < BaseStep
|
|
88
|
+
attr_reader :keyword, :name, :line
|
|
89
|
+
attr_accessor :arity, :extra_args
|
|
90
|
+
|
|
91
|
+
def row?
|
|
92
|
+
false
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def initialize(scenario, keyword, name, line)
|
|
96
|
+
@scenario, @keyword, @name, @line = scenario, keyword, name, line
|
|
97
|
+
@extra_args = []
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def regexp_args_proc(step_mother)
|
|
101
|
+
regexp, args, proc = step_mother.regexp_args_proc(name)
|
|
102
|
+
@arity = args.length
|
|
103
|
+
[regexp, (args + extra_args), proc]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def format(regexp, format=nil, &proc)
|
|
107
|
+
regexp.nil? ? name : name.gzub(regexp, format, &proc)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
class RowStep < BaseStep
|
|
112
|
+
attr_reader :keyword
|
|
113
|
+
|
|
114
|
+
def initialize(scenario, step, args)
|
|
115
|
+
@scenario, @step, @args = scenario, step, args
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def regexp_args_proc(step_mother)
|
|
119
|
+
regexp, _, proc = @step.regexp_args_proc(step_mother)
|
|
120
|
+
[regexp, @args, proc]
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def row?
|
|
124
|
+
true
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def line
|
|
128
|
+
@scenario.line
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
end
|