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.
Files changed (186) hide show
  1. data/History.txt +150 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +186 -0
  4. data/README.txt +41 -0
  5. data/Rakefile +5 -0
  6. data/TODO.txt +26 -0
  7. data/bin/cucumber +4 -0
  8. data/config/hoe.rb +69 -0
  9. data/config/requirements.rb +15 -0
  10. data/cucumber.yml +1 -0
  11. data/examples/calculator/README.txt +5 -0
  12. data/examples/calculator/Rakefile +5 -0
  13. data/examples/calculator/features/addition.feature +17 -0
  14. data/examples/calculator/features/division.feature +10 -0
  15. data/examples/calculator/features/steps/calculator_steps.rb +31 -0
  16. data/examples/calculator/lib/calculator.rb +16 -0
  17. data/examples/calculator_ruby_features/Rakefile +6 -0
  18. data/examples/calculator_ruby_features/features/addition.rb +23 -0
  19. data/examples/calculator_ruby_features/features/steps/calculator_steps.rb +43 -0
  20. data/examples/calculatrice_francaise_avec_soit_scenario/Rakefile +6 -0
  21. data/examples/calculatrice_francaise_avec_soit_scenario/features/addition.feature +13 -0
  22. data/examples/calculatrice_francaise_avec_soit_scenario/features/calculatrice_steps.rb +31 -0
  23. data/examples/chinese_simplified_calculator/Rakefile +6 -0
  24. data/examples/chinese_simplified_calculator/features/addition.feature +17 -0
  25. data/examples/chinese_simplified_calculator/features/steps/calculator_steps.rb +24 -0
  26. data/examples/chinese_simplified_calculator/lib/calculator.rb +10 -0
  27. data/examples/cs/README.textile +22 -0
  28. data/examples/cs/Rakefile +12 -0
  29. data/examples/cs/features/hello.feature +11 -0
  30. data/examples/cs/features/steps/hello_steps.rb +25 -0
  31. data/examples/cs/features/steps/tree_steps.rb +14 -0
  32. data/examples/cs/features/tree.feature +9 -0
  33. data/examples/cs/src/Hello.cs +18 -0
  34. data/examples/danish_calculator/Rakefile +6 -0
  35. data/examples/danish_calculator/features/steps/kalkulator_steps.rb +22 -0
  36. data/examples/danish_calculator/features/summering.feature +17 -0
  37. data/examples/danish_calculator/lib/kalkulator.rb +11 -0
  38. data/examples/dos_line_endings/Rakefile +6 -0
  39. data/examples/dos_line_endings/features/dos_line_endings.feature +9 -0
  40. data/examples/estonian_calculator/Rakefile +6 -0
  41. data/examples/estonian_calculator/features/kalkulaator_steps.rb +35 -0
  42. data/examples/estonian_calculator/features/liitmine.feature +16 -0
  43. data/examples/japanese_calculator/README.txt +5 -0
  44. data/examples/japanese_calculator/Rakefile +6 -0
  45. data/examples/japanese_calculator/features/addition.feature +17 -0
  46. data/examples/japanese_calculator/features/division.feature +10 -0
  47. data/examples/japanese_calculator/features/steps/calculator_steps.rb +30 -0
  48. data/examples/japanese_calculator/lib/calculator.rb +16 -0
  49. data/examples/java/README.textile +22 -0
  50. data/examples/java/Rakefile +12 -0
  51. data/examples/java/features/hello.feature +11 -0
  52. data/examples/java/features/steps/hello_steps.rb +25 -0
  53. data/examples/java/features/steps/tree_steps.rb +14 -0
  54. data/examples/java/features/tree.feature +9 -0
  55. data/examples/java/src/cucumber/demo/Hello.java +16 -0
  56. data/examples/norwegian_calculator/Rakefile +6 -0
  57. data/examples/norwegian_calculator/features/steps/kalkulator_steps.rb +22 -0
  58. data/examples/norwegian_calculator/features/summering.feature +17 -0
  59. data/examples/norwegian_calculator/lib/kalkulator.rb +11 -0
  60. data/examples/portuguese_calculator/Rakefile +6 -0
  61. data/examples/portuguese_calculator/features/adicao.feature +10 -0
  62. data/examples/portuguese_calculator/features/calculadora_steps.rb +31 -0
  63. data/examples/selenium/Rakefile +6 -0
  64. data/examples/selenium/features/search.feature +9 -0
  65. data/examples/selenium/features/steps/stories_steps.rb +41 -0
  66. data/examples/spanish_calculator/Rakefile +6 -0
  67. data/examples/spanish_calculator/features/adicion.feature +17 -0
  68. data/examples/spanish_calculator/features/steps/calculador_steps.rb +22 -0
  69. data/examples/swedish_calculator/Rakefile +5 -0
  70. data/examples/swedish_calculator/features/steps/kalkulator_steps.rb +22 -0
  71. data/examples/swedish_calculator/features/summering.feature +17 -0
  72. data/examples/swedish_calculator/lib/kalkulator.rb +11 -0
  73. data/examples/tickets/Rakefile +11 -0
  74. data/examples/tickets/cucumber.yml +2 -0
  75. data/examples/tickets/features/steps/tickets_steps.rb +32 -0
  76. data/examples/tickets/features/tickets.feature +22 -0
  77. data/examples/watir/Rakefile +6 -0
  78. data/examples/watir/features/search.feature +9 -0
  79. data/examples/watir/features/steps/stories_steps.rb +51 -0
  80. data/features/see_features.feature +8 -0
  81. data/features/steps/features_steps.rb +9 -0
  82. data/gem_tasks/deployment.rake +34 -0
  83. data/gem_tasks/environment.rake +7 -0
  84. data/gem_tasks/features.rake +6 -0
  85. data/gem_tasks/fix_cr_lf.rake +10 -0
  86. data/gem_tasks/flog.rake +4 -0
  87. data/gem_tasks/gemspec.rake +6 -0
  88. data/gem_tasks/rspec.rake +21 -0
  89. data/gem_tasks/treetop.rake +49 -0
  90. data/lib/cucumber.rb +35 -0
  91. data/lib/cucumber/cli.rb +191 -0
  92. data/lib/cucumber/core_ext/proc.rb +55 -0
  93. data/lib/cucumber/core_ext/string.rb +22 -0
  94. data/lib/cucumber/executor.rb +143 -0
  95. data/lib/cucumber/formatters.rb +1 -0
  96. data/lib/cucumber/formatters/ansicolor.rb +112 -0
  97. data/lib/cucumber/formatters/cucumber.css +132 -0
  98. data/lib/cucumber/formatters/cucumber.js +11 -0
  99. data/lib/cucumber/formatters/html_formatter.rb +128 -0
  100. data/lib/cucumber/formatters/jquery.js +32 -0
  101. data/lib/cucumber/formatters/pretty_formatter.rb +211 -0
  102. data/lib/cucumber/formatters/profile_formatter.rb +92 -0
  103. data/lib/cucumber/formatters/progress_formatter.rb +51 -0
  104. data/lib/cucumber/languages.yml +142 -0
  105. data/lib/cucumber/model.rb +1 -0
  106. data/lib/cucumber/model/table.rb +28 -0
  107. data/lib/cucumber/rails/rspec.rb +12 -0
  108. data/lib/cucumber/rails/world.rb +73 -0
  109. data/lib/cucumber/rake/task.rb +75 -0
  110. data/lib/cucumber/step_methods.rb +49 -0
  111. data/lib/cucumber/step_mother.rb +83 -0
  112. data/lib/cucumber/tree.rb +18 -0
  113. data/lib/cucumber/tree/feature.rb +60 -0
  114. data/lib/cucumber/tree/features.rb +21 -0
  115. data/lib/cucumber/tree/given_scenario.rb +13 -0
  116. data/lib/cucumber/tree/scenario.rb +150 -0
  117. data/lib/cucumber/tree/step.rb +133 -0
  118. data/lib/cucumber/tree/table.rb +26 -0
  119. data/lib/cucumber/tree/top_down_visitor.rb +23 -0
  120. data/lib/cucumber/treetop_parser/feature.treetop.erb +201 -0
  121. data/lib/cucumber/treetop_parser/feature_da.rb +1593 -0
  122. data/lib/cucumber/treetop_parser/feature_de.rb +1593 -0
  123. data/lib/cucumber/treetop_parser/feature_en-tx.rb +1593 -0
  124. data/lib/cucumber/treetop_parser/feature_en.rb +1593 -0
  125. data/lib/cucumber/treetop_parser/feature_es.rb +1593 -0
  126. data/lib/cucumber/treetop_parser/feature_et.rb +1593 -0
  127. data/lib/cucumber/treetop_parser/feature_fr.rb +1593 -0
  128. data/lib/cucumber/treetop_parser/feature_ja.rb +1593 -0
  129. data/lib/cucumber/treetop_parser/feature_nl.rb +1593 -0
  130. data/lib/cucumber/treetop_parser/feature_no.rb +1593 -0
  131. data/lib/cucumber/treetop_parser/feature_parser.rb +34 -0
  132. data/lib/cucumber/treetop_parser/feature_pt.rb +1593 -0
  133. data/lib/cucumber/treetop_parser/feature_ru.rb +1593 -0
  134. data/lib/cucumber/treetop_parser/feature_se.rb +1593 -0
  135. data/lib/cucumber/treetop_parser/feature_zh-CN.rb +1593 -0
  136. data/lib/cucumber/version.rb +9 -0
  137. data/rails_generators/cucumber/cucumber_generator.rb +29 -0
  138. data/rails_generators/cucumber/templates/common_webrat.rb +42 -0
  139. data/rails_generators/cucumber/templates/cucumber +2 -0
  140. data/rails_generators/cucumber/templates/cucumber.rake +12 -0
  141. data/rails_generators/cucumber/templates/cucumber.yml +1 -0
  142. data/rails_generators/cucumber/templates/env.rb +8 -0
  143. data/rails_generators/feature/feature_generator.rb +17 -0
  144. data/rails_generators/feature/templates/feature.erb +28 -0
  145. data/rails_generators/feature/templates/steps.erb +22 -0
  146. data/script/console +10 -0
  147. data/script/console.cmd +1 -0
  148. data/script/destroy +14 -0
  149. data/script/destroy.cmd +1 -0
  150. data/script/generate +14 -0
  151. data/script/generate.cmd +1 -0
  152. data/script/txt2html +74 -0
  153. data/script/txt2html.cmd +1 -0
  154. data/setup.rb +1585 -0
  155. data/spec/cucumber/cli_spec.rb +56 -0
  156. data/spec/cucumber/core_ext/proc_spec.rb +45 -0
  157. data/spec/cucumber/core_ext/string_spec.rb +34 -0
  158. data/spec/cucumber/executor_spec.rb +130 -0
  159. data/spec/cucumber/formatters/ansicolor_spec.rb +35 -0
  160. data/spec/cucumber/formatters/features.html +269 -0
  161. data/spec/cucumber/formatters/html_formatter_spec.rb +74 -0
  162. data/spec/cucumber/formatters/pretty_formatter_spec.rb +111 -0
  163. data/spec/cucumber/formatters/profile_formatter_spec.rb +193 -0
  164. data/spec/cucumber/formatters/progress_formatter_spec.rb +45 -0
  165. data/spec/cucumber/model/table_spec.rb +20 -0
  166. data/spec/cucumber/rails/stubs/mini_rails.rb +17 -0
  167. data/spec/cucumber/rails/stubs/test_help.rb +1 -0
  168. data/spec/cucumber/rails/world_spec.rb +11 -0
  169. data/spec/cucumber/sell_cucumbers.feature +9 -0
  170. data/spec/cucumber/step_mother_spec.rb +53 -0
  171. data/spec/cucumber/tree/feature_spec.rb +12 -0
  172. data/spec/cucumber/tree/scenario_spec.rb +37 -0
  173. data/spec/cucumber/tree/step_spec.rb +31 -0
  174. data/spec/cucumber/treetop_parser/empty_feature.feature +4 -0
  175. data/spec/cucumber/treetop_parser/empty_scenario.feature +9 -0
  176. data/spec/cucumber/treetop_parser/feature_parser_spec.rb +96 -0
  177. data/spec/cucumber/treetop_parser/fit_scenario.feature +8 -0
  178. data/spec/cucumber/treetop_parser/given_scenario.feature +9 -0
  179. data/spec/cucumber/treetop_parser/multiline_steps.feature +13 -0
  180. data/spec/cucumber/treetop_parser/multiple_tables.feature +29 -0
  181. data/spec/cucumber/treetop_parser/spaces.feature +10 -0
  182. data/spec/cucumber/treetop_parser/test_dos.feature +25 -0
  183. data/spec/cucumber/treetop_parser/with_comments.feature +10 -0
  184. data/spec/spec.opts +2 -0
  185. data/spec/spec_helper.rb +19 -0
  186. 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,13 @@
1
+ module Cucumber
2
+ module Tree
3
+ class GivenScenario
4
+ def initialize(scenario, name, line)
5
+ @scenario, @name, @line = scenario, name, line
6
+ end
7
+
8
+ def steps
9
+ @scenario.given_scenario_steps(@name)
10
+ end
11
+ end
12
+ end
13
+ 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