cucumber-core 1.0.0.beta.2 → 1.0.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,7 @@
1
1
  require 'cucumber/initializer'
2
2
  require 'cucumber/core/ast'
3
3
  require 'cucumber/core/platform'
4
+ require 'gherkin/rubify'
4
5
 
5
6
  module Cucumber
6
7
  module Core
@@ -70,11 +71,7 @@ module Cucumber
70
71
  end
71
72
 
72
73
  def file
73
- if Cucumber::WINDOWS && !ENV['CUCUMBER_FORWARD_SLASH_PATHS']
74
- @path.gsub(/\//, '\\')
75
- else
76
- @path
77
- end
74
+ @path
78
75
  end
79
76
 
80
77
  class Builder
@@ -115,7 +112,9 @@ module Cucumber
115
112
 
116
113
  def result(language)
117
114
  background = background(language)
118
- feature = Ast::Feature.new(
115
+ Ast::Feature.new(
116
+ node,
117
+ language,
119
118
  location,
120
119
  background,
121
120
  comments,
@@ -125,9 +124,6 @@ module Cucumber
125
124
  node.description.rstrip,
126
125
  children.map { |builder| builder.result(background, language, tags) }
127
126
  )
128
- feature.gherkin_statement(node)
129
- feature.language = language
130
- feature
131
127
  end
132
128
 
133
129
  def add_child(child)
@@ -209,15 +205,15 @@ module Cucumber
209
205
 
210
206
  class StepBuilder < Builder
211
207
  def result(language)
212
- step = Ast::Step.new(
208
+ Ast::Step.new(
209
+ node,
213
210
  language,
214
211
  location,
215
212
  node.keyword,
216
213
  node.name,
217
- Ast::MultilineArgument.from(node.doc_string || node.rows, location)
214
+
215
+ MultilineArgument.from(node.doc_string || node.rows, location)
218
216
  )
219
- step.gherkin_statement(node)
220
- step
221
217
  end
222
218
  end
223
219
  end
@@ -225,7 +221,8 @@ module Cucumber
225
221
  class ScenarioOutlineBuilder < Builder
226
222
  def result(background, language, feature_tags)
227
223
  raise ParseError.new("Missing Examples section for Scenario Outline at #{location}") if examples_tables.empty?
228
- scenario_outline = Ast::ScenarioOutline.new(
224
+ Ast::ScenarioOutline.new(
225
+ node,
229
226
  language,
230
227
  location,
231
228
  background,
@@ -238,8 +235,6 @@ module Cucumber
238
235
  steps(language),
239
236
  examples_tables
240
237
  )
241
- scenario_outline.gherkin_statement(node)
242
- scenario_outline
243
238
  end
244
239
 
245
240
  def add_examples(file, node)
@@ -267,7 +262,8 @@ module Cucumber
267
262
  class ExamplesTableBuilder < Builder
268
263
 
269
264
  def result
270
- examples_table = Ast::ExamplesTable.new(
265
+ Ast::ExamplesTable.new(
266
+ node,
271
267
  location,
272
268
  comments,
273
269
  tags,
@@ -277,8 +273,6 @@ module Cucumber
277
273
  header,
278
274
  example_rows
279
275
  )
280
- examples_table.gherkin_statement(node)
281
- examples_table
282
276
  end
283
277
 
284
278
  private
@@ -299,15 +293,34 @@ module Cucumber
299
293
 
300
294
  class StepBuilder < Builder
301
295
  def result(language)
302
- step = Ast::OutlineStep.new(
296
+ Ast::OutlineStep.new(
297
+ node,
303
298
  language,
304
299
  location,
305
300
  node.keyword,
306
301
  node.name,
307
- Ast::MultilineArgument.from(node.doc_string || node.rows, location)
302
+ MultilineArgument.from(node.doc_string || node.rows, location)
308
303
  )
309
- step.gherkin_statement(node)
310
- step
304
+ end
305
+ end
306
+ end
307
+
308
+ module MultilineArgument
309
+ class << self
310
+ include ::Gherkin::Rubify
311
+
312
+ def from(argument, parent_location)
313
+ return Ast::EmptyMultilineArgument.new unless argument
314
+ argument = rubify(argument)
315
+ case argument
316
+ when ::Gherkin::Formatter::Model::DocString
317
+ Ast::DocString.new(argument.value, argument.content_type, parent_location.on_line(argument.line_range))
318
+ when Array
319
+ location = parent_location.on_line(argument.first.line..argument.last.line)
320
+ Ast::DataTable.new(argument.map{|row| row.cells}, location)
321
+ else
322
+ raise ArgumentError, "Don't know how to convert #{argument.inspect} into a MultilineArgument"
323
+ end
311
324
  end
312
325
  end
313
326
  end
@@ -6,21 +6,20 @@ require 'cucumber/core/ast/location'
6
6
  module Cucumber
7
7
  module Core
8
8
  module Test
9
-
10
- class Mapping
9
+ class Action
11
10
  def initialize(&block)
12
11
  raise ArgumentError, "Passing a block to execute the mapping is mandatory." unless block
13
12
  @block = block
14
13
  @timer = Timer.new
15
14
  end
16
15
 
17
- def skip
16
+ def skip(last_result)
18
17
  skipped
19
18
  end
20
19
 
21
- def execute
20
+ def execute(last_result)
22
21
  @timer.start
23
- @block.call
22
+ @block.call(last_result)
24
23
  passed
25
24
  rescue Result::Raisable => exception
26
25
  exception.with_duration(@timer.duration)
@@ -51,18 +50,18 @@ module Cucumber
51
50
  end
52
51
  end
53
52
 
54
- class UnskippableMapping < Mapping
55
- def skip
56
- execute
53
+ class UnskippableAction < Action
54
+ def skip(last_result)
55
+ execute(last_result)
57
56
  end
58
57
  end
59
58
 
60
- class UndefinedMapping
61
- def execute
59
+ class UndefinedAction
60
+ def execute(last_result)
62
61
  undefined
63
62
  end
64
63
 
65
- def skip
64
+ def skip(last_result)
66
65
  undefined
67
66
  end
68
67
 
@@ -110,15 +110,15 @@ module Cucumber
110
110
  include Cucumber.initializer(:source)
111
111
 
112
112
  def after(block)
113
- build_hook_step(block, Hooks::AfterHook, Test::UnskippableMapping)
113
+ build_hook_step(block, Hooks::AfterHook, Test::UnskippableAction)
114
114
  end
115
115
 
116
116
  def before(block)
117
- build_hook_step(block, Hooks::BeforeHook, Test::UnskippableMapping)
117
+ build_hook_step(block, Hooks::BeforeHook, Test::UnskippableAction)
118
118
  end
119
119
 
120
120
  def after_step(block)
121
- build_hook_step(block, Hooks::AfterStepHook, Test::Mapping)
121
+ build_hook_step(block, Hooks::AfterStepHook, Test::Action)
122
122
  end
123
123
 
124
124
  private
@@ -60,7 +60,7 @@ module Cucumber
60
60
  include Cucumber.initializer(:step_result)
61
61
 
62
62
  def execute(test_step, monitor)
63
- result = test_step.execute
63
+ result = test_step.execute(monitor.result)
64
64
  result.describe_to(monitor, result)
65
65
  end
66
66
 
@@ -83,7 +83,7 @@ module Cucumber
83
83
 
84
84
  class Failing < Base
85
85
  def execute(test_step, monitor)
86
- test_step.skip
86
+ test_step.skip(monitor.result)
87
87
  end
88
88
 
89
89
  def result(duration)
@@ -1,6 +1,6 @@
1
1
  require 'cucumber/initializer'
2
2
  require 'cucumber/core/test/result'
3
- require 'cucumber/core/test/mapping'
3
+ require 'cucumber/core/test/action'
4
4
 
5
5
  module Cucumber
6
6
  module Core
@@ -9,7 +9,7 @@ module Cucumber
9
9
  include Cucumber.initializer(:source)
10
10
  attr_reader :source
11
11
 
12
- def initialize(source, mapping = Test::UndefinedMapping.new)
12
+ def initialize(source, mapping = Test::UndefinedAction.new)
13
13
  raise ArgumentError if source.any?(&:nil?)
14
14
  @mapping = mapping
15
15
  super(source)
@@ -26,16 +26,16 @@ module Cucumber
26
26
  self
27
27
  end
28
28
 
29
- def skip
30
- @mapping.skip
29
+ def skip(last_result)
30
+ @mapping.skip(last_result)
31
31
  end
32
32
 
33
- def execute
34
- @mapping.execute
33
+ def execute(last_result)
34
+ @mapping.execute(last_result)
35
35
  end
36
36
 
37
37
  def with_mapping(&block)
38
- self.class.new(source, Test::Mapping.new(&block))
38
+ self.class.new(source, Test::Action.new(&block))
39
39
  end
40
40
 
41
41
  def name
@@ -2,7 +2,7 @@ module Cucumber
2
2
  module Core
3
3
  class Version
4
4
  def self.to_s
5
- "1.0.0.beta.2"
5
+ "1.0.0.beta.3"
6
6
  end
7
7
  end
8
8
  end
@@ -12,43 +12,6 @@ module Cucumber
12
12
  %w{one four seven},
13
13
  %w{4444 55555 666666}
14
14
  ], location)
15
- def @table.cells_rows; super; end
16
- def @table.columns; super; end
17
- end
18
-
19
- it "should have rows" do
20
- expect( @table.cells_rows[0].map{|cell| cell.value} ).to eq %w{one four seven}
21
- end
22
-
23
- it "should have columns" do
24
- expect( @table.columns[1].map{|cell| cell.value} ).to eq %w{four 55555}
25
- end
26
-
27
- it "should have headers" do
28
- expect( @table.headers ).to eq %w{one four seven}
29
- end
30
-
31
- it "should have same cell objects in rows and columns" do
32
- # 666666
33
- expect( @table.cells_rows[1].__send__(:[], 2) ).to eq @table.columns[2].__send__(:[], 1)
34
- end
35
-
36
- it "should know about max width of a row" do
37
- expect( @table.columns[1].__send__(:width) ).to eq 5
38
- end
39
-
40
- it "should be convertible to an array of hashes" do
41
- expect( @table.hashes ).to eq [
42
- {'one' => '4444', 'four' => '55555', 'seven' => '666666'}
43
- ]
44
- end
45
-
46
- it "should accept symbols as keys for the hashes" do
47
- expect( @table.hashes.first[:one] ).to eq '4444'
48
- end
49
-
50
- it "should return the row values in order" do
51
- expect( @table.rows.first ).to eq %w{4444 55555 666666}
52
15
  end
53
16
 
54
17
  describe "equality" do
@@ -86,62 +49,12 @@ module Cucumber
86
49
  ], location)
87
50
  end
88
51
 
89
- it "should be convertible in to an array where each row is a hash" do
90
- expect( @table.transpose.hashes[0] ).to eq({'one' => '1111', 'two' => '22222'})
91
- end
92
- end
93
-
94
- describe "#rows_hash" do
95
-
96
- it "should return a hash of the rows" do
97
- table = DataTable.new([
98
- %w{one 1111},
99
- %w{two 22222}
100
- ], location)
101
- expect( table.rows_hash ).to eq({'one' => '1111', 'two' => '22222'})
102
- end
103
-
104
- it "should fail if the table doesn't have two columns" do
105
- faulty_table = DataTable.new([
106
- %w{one 1111 abc},
107
- %w{two 22222 def}
52
+ it "should transpose the table" do
53
+ transposed = DataTable.new([
54
+ %w{one two},
55
+ %w{1111 22222}
108
56
  ], location)
109
- expect { faulty_table.rows_hash }.to raise_error('The table must have exactly 2 columns')
110
- end
111
- end
112
-
113
- describe "#new" do
114
- it "should allow Array of Hash" do
115
- t1 = DataTable.new([{'name' => 'aslak', 'male' => 'true'}], location)
116
- expect( t1.hashes ).to eq [{'name' => 'aslak', 'male' => 'true'}]
117
- end
118
- end
119
-
120
- it "should convert to sexp" do
121
- sexp_value =
122
- [:table,
123
- [:row, -1,
124
- [:cell, "one"],
125
- [:cell, "four"],
126
- [:cell, "seven"]
127
- ],
128
- [:row, -1,
129
- [:cell, "4444"],
130
- [:cell, "55555"],
131
- [:cell, "666666"]
132
- ]
133
- ]
134
- expect( @table.to_sexp ).to eq sexp_value
135
- end
136
-
137
- describe "#each_cell" do
138
- it "runs the given block on each cell in the table" do
139
- table = DataTable.new([[1,2],[3,4]], location)
140
- values = []
141
- table.each_cell do |cell|
142
- values << cell.value
143
- end
144
- expect( values ).to eq [1,2,3,4]
57
+ expect( @table.transpose ).to eq( transposed )
145
58
  end
146
59
  end
147
60
 
@@ -24,6 +24,14 @@ module Cucumber::Core::Ast
24
24
  end
25
25
  end
26
26
 
27
+ describe "line" do
28
+ it "is an integer" do
29
+ expect(Location.new(file, line).line).to be_kind_of(Integer)
30
+ expect(Location.new(file, 1..2).line).to be_kind_of(Integer)
31
+ expect(Location.of_caller.line).to be_kind_of(Integer)
32
+ end
33
+ end
34
+
27
35
  describe "to_s" do
28
36
  it "is file:line for a precise location" do
29
37
  expect( Location.new("foo.feature", 12).to_s ).to eq "foo.feature:12"
@@ -8,7 +8,8 @@ module Cucumber
8
8
  module Core
9
9
  module Ast
10
10
  describe OutlineStep do
11
- let(:outline_step) { OutlineStep.new(language, location, keyword, name, multiline_arg) }
11
+ let(:outline_step) { OutlineStep.new(node, language, location, keyword, name, multiline_arg) }
12
+ let(:node) { double }
12
13
  let(:language) { double }
13
14
  let(:location) { double }
14
15
  let(:keyword) { double }
@@ -35,16 +36,10 @@ module Cucumber
35
36
  expect( outline_step.to_step(row).name ).to eq 'a green cucumber'
36
37
  end
37
38
 
38
- it "knows the name of the outline step" do
39
- row = ExamplesTable::Row.new({'color' => 'green'}, 1, location)
40
- outline_step.gherkin_statement(double(:name => name))
41
- expect( outline_step.to_step(row).gherkin_statement.name ).to eq name
42
- end
43
-
44
39
  end
45
40
 
46
41
  context "when the step has a DataTable" do
47
- let(:outline_step) { OutlineStep.new(language, location, keyword, name, table) }
42
+ let(:outline_step) { OutlineStep.new(node, language, location, keyword, name, table) }
48
43
  let(:name) { "anything" }
49
44
  let(:table) { DataTable.new([['x', 'y'],['a', 'a <arg>']], Location.new('foo.feature', 23)) }
50
45
 
@@ -62,7 +57,7 @@ module Cucumber
62
57
 
63
58
  context "when the step has a DocString" do
64
59
  let(:location) { double }
65
- let(:outline_step) { OutlineStep.new(language, location, keyword, name, doc_string) }
60
+ let(:outline_step) { OutlineStep.new(node, language, location, keyword, name, doc_string) }
66
61
  let(:doc_string) { DocString.new('a <arg> that needs replacing', '', location) }
67
62
  let(:name) { 'anything' }
68
63
 
@@ -5,9 +5,9 @@ module Cucumber
5
5
  module Ast
6
6
  describe Step do
7
7
  let(:step) do
8
- language, location, keyword, name = *double
8
+ node, language, location, keyword, name = *double
9
9
  multiline_arg = EmptyMultilineArgument.new
10
- Step.new(language, location, keyword, name, multiline_arg)
10
+ Step.new(node, language, location, keyword, name, multiline_arg)
11
11
  end
12
12
 
13
13
  describe "describing itself" do
@@ -26,7 +26,7 @@ module Cucumber
26
26
  end
27
27
 
28
28
  context "with a multiline argument" do
29
- let(:step) { Step.new(double, double, double, double, multiline_arg) }
29
+ let(:step) { Step.new(double, double, double, double, double, multiline_arg) }
30
30
  let(:multiline_arg) { double }
31
31
 
32
32
  it "tells its multiline argument to describe itself" do
@@ -38,6 +38,73 @@ module Cucumber
38
38
 
39
39
  end
40
40
 
41
+ describe "backtrace line" do
42
+ let(:step) { Step.new(double, double, "path/file.feature:10", "Given ", "this step passes", double) }
43
+
44
+ it "knows how to form the backtrace line" do
45
+ expect( step.backtrace_line ).to eq("path/file.feature:10:in `Given this step passes'")
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ describe ExpandedOutlineStep do
53
+ let(:outline_step) { double }
54
+ let(:step) do
55
+ node, language, location, keyword, name = *double
56
+ multiline_arg = EmptyMultilineArgument.new
57
+ ExpandedOutlineStep.new(outline_step, node, language, location, keyword, name, multiline_arg)
58
+ end
59
+
60
+ describe "describing itself" do
61
+ let(:visitor) { double }
62
+
63
+ it "describes itself as a step" do
64
+ expect( visitor ).to receive(:step).with(step)
65
+ step.describe_to(visitor)
66
+ end
67
+
68
+ context "with no multiline argument" do
69
+ it "does not try to describe any children" do
70
+ allow( visitor ).to receive(:step).with(step).and_yield(visitor)
71
+ step.describe_to(visitor)
72
+ end
73
+ end
74
+
75
+ context "with a multiline argument" do
76
+ let(:step) { Step.new(double, double, double, double, double, multiline_arg) }
77
+ let(:multiline_arg) { double }
78
+
79
+ it "tells its multiline argument to describe itself" do
80
+ allow( visitor ).to receive(:step).with(step).and_yield(visitor)
81
+ expect( multiline_arg ).to receive(:describe_to).with(visitor)
82
+ step.describe_to(visitor)
83
+ end
84
+ end
85
+
86
+ end
87
+
88
+ describe "matching location" do
89
+ let(:location) { double }
90
+
91
+ it "also match the outline steps location" do
92
+ allow( location).to receive(:any?).and_return(nil)
93
+ expect( outline_step ).to receive(:match_locations?).with(location)
94
+ step.match_locations?(location)
95
+ end
96
+ end
97
+
98
+ describe "backtrace line" do
99
+ let(:outline_step) { OutlineStep.new(double, double, "path/file.feature:5", "Given ", "this step <state>", double) }
100
+ let(:step) { ExpandedOutlineStep.new(outline_step, double, double, "path/file.feature:10", "Given ", "this step passes", double) }
101
+
102
+ it "includes the outline step in the backtrace line" do
103
+ expect( step.backtrace_line ).to eq("path/file.feature:10:in `Given this step passes'\n" +
104
+ "path/file.feature:5:in `Given this step <state>'")
105
+ end
106
+
107
+ end
41
108
  end
42
109
  end
43
110
  end