aslakhellesoy-cucumber 0.2.3.2 → 0.2.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -21,6 +21,12 @@ still work.
21
21
  * Snippets for steps that use Step Tables or PyStrings include block param and object type hint comment (#247 Joseph Wilk)
22
22
  * Support description string for Backgrounds (#271 Joseph Wilk)
23
23
 
24
+ === Bugfixes
25
+ * Fixed Background runs twice (#255 Aslak Hellesøy)
26
+ * Fixed Background Transactions and :xx (#270 Aslak Hellesøy)
27
+ * Fixed Autospec failing with cucumber 0.2 (#254 Aslak Hellesøy)
28
+ * Sibling file detecting not working (#278 Aslak Hellesøy)
29
+
24
30
  === Removed/changed features
25
31
  * The visitor API has changed slightly:
26
32
  ** #visit_step_name, #visit_multiline_arg and #visit_exception are no longer official API methods.
data/Manifest.txt CHANGED
@@ -179,6 +179,8 @@ examples/tickets/features/236.feature
179
179
  examples/tickets/features/241.feature
180
180
  examples/tickets/features/246.feature
181
181
  examples/tickets/features/248.feature
182
+ examples/tickets/features/270/back.feature
183
+ examples/tickets/features/270/back.steps.rb
182
184
  examples/tickets/features/lib/eatting_machine.rb
183
185
  examples/tickets/features/lib/pantry.rb
184
186
  examples/tickets/features/scenario_outline.feature
@@ -259,7 +261,6 @@ lib/cucumber/formatter/usage.rb
259
261
  lib/cucumber/formatters/unicode.rb
260
262
  lib/cucumber/languages.yml
261
263
  lib/cucumber/parser.rb
262
- lib/cucumber/parser/basic.rb
263
264
  lib/cucumber/parser/feature.rb
264
265
  lib/cucumber/parser/feature.tt
265
266
  lib/cucumber/parser/i18n.tt
@@ -25,9 +25,9 @@ Given /^call step "(.*)"$/ do |step|
25
25
  end
26
26
 
27
27
  Given /^'(.+)' cukes$/ do |cukes|
28
+ raise "We already have #{@cukes} cukes!" if @cukes
28
29
  @cukes = cukes
29
30
  end
30
-
31
31
  Then /^I should have '(.+)' cukes$/ do |cukes|
32
32
  @cukes.should == cukes
33
33
  end
@@ -52,7 +52,7 @@ Given /^multiline string$/ do |string|
52
52
  end
53
53
 
54
54
  Then /^the table should be$/ do |table|
55
- @table.to_sexp.should == table.to_sexp
55
+ @table.raw.should == table.raw
56
56
  end
57
57
 
58
58
  Then /^the multiline string should be$/ do |string|
@@ -0,0 +1,14 @@
1
+ Feature: Background
2
+ In for background to work properly
3
+ As a user
4
+ I want it to run transactionally and only once when I call an individual scenario
5
+
6
+ Background:
7
+ Given plop
8
+
9
+ Scenario: Barping
10
+ When I barp
11
+
12
+
13
+ Scenario: Wibbling
14
+ When I wibble
@@ -0,0 +1,14 @@
1
+ require 'spec/expectations'
2
+
3
+ Given /^plop$/ do
4
+ raise "Only one plop!" if @plop
5
+ @plop = true
6
+ end
7
+
8
+ When /^I barp$/ do
9
+ @plop.should == true
10
+ end
11
+
12
+ When /^I wibble$/ do
13
+ @plop.should == true
14
+ end
@@ -16,7 +16,7 @@ Feature: backgrounds
16
16
  Then I should have '10' cukes
17
17
 
18
18
  1 scenario
19
- 3 passed steps
19
+ 2 passed steps
20
20
 
21
21
  """
22
22
 
@@ -64,7 +64,7 @@ Feature: backgrounds
64
64
  | 10 |
65
65
 
66
66
  2 scenarios
67
- 5 passed steps
67
+ 4 passed steps
68
68
 
69
69
  """
70
70
 
@@ -123,7 +123,7 @@ Feature: backgrounds
123
123
 
124
124
  2 scenarios
125
125
  1 failed step
126
- 4 skipped steps
126
+ 3 skipped steps
127
127
 
128
128
  """
129
129
 
@@ -41,7 +41,7 @@ Feature: Cucumber command line
41
41
  Feature: Outline Sample
42
42
 
43
43
  Scenario Outline: Test state # features/outline_sample.feature:5
44
- Given <state> without a table # features/step_definitions/sample_steps.rb:12
44
+ Given <state> without a table # features/step_definitions/sample_steps.rb:15
45
45
  Given <other_state> without a table # features/step_definitions/sample_steps.rb:12
46
46
 
47
47
  Examples: Rainbow colours
@@ -26,10 +26,6 @@ module Cucumber
26
26
  @outline_table.cells_rows[1..-1].each(&proc)
27
27
  end
28
28
 
29
- def matches_lines?(lines)
30
- lines.index(@line) || @outline_table.matches_lines?(lines)
31
- end
32
-
33
29
  def to_sexp
34
30
  [:examples, @keyword, @name, @outline_table.to_sexp]
35
31
  end
@@ -3,11 +3,10 @@ module Cucumber
3
3
  # Represents the root node of a parsed feature.
4
4
  class Feature
5
5
  attr_accessor :file
6
- attr_writer :features, :lines
6
+ attr_writer :features
7
7
 
8
8
  def initialize(background, comment, tags, name, feature_elements)
9
9
  @background, @comment, @tags, @name, @feature_elements = background, comment, tags, name, feature_elements
10
- @lines = []
11
10
 
12
11
  @feature_elements.each do |feature_element|
13
12
  feature_element.feature = self
@@ -15,7 +14,6 @@ module Cucumber
15
14
  end
16
15
 
17
16
  def accept(visitor)
18
- visitor.current_feature_lines = @lines
19
17
  visitor.visit_comment(@comment)
20
18
  visitor.visit_tags(@tags)
21
19
  visitor.visit_feature_name(@name)
@@ -12,10 +12,6 @@ module Cucumber
12
12
  @keyword.jlength + @name.jlength
13
13
  end
14
14
 
15
- def matches_lines?(lines)
16
- lines.index(@line) || @steps.matches_lines?(lines) || @tags.matches_lines?(lines)
17
- end
18
-
19
15
  def has_tags?(tags)
20
16
  @tags.has_tags?(tags) || @feature.has_tags?(tags)
21
17
  end
@@ -5,10 +5,7 @@ module Cucumber
5
5
  super(raw)
6
6
  @scenario_outline = scenario_outline
7
7
  @cells_class = ExampleCells
8
-
9
- cells_rows.each do |cells|
10
- cells.create_step_invocations!(scenario_outline)
11
- end
8
+ create_step_invocations_for_example_rows!(scenario_outline)
12
9
  end
13
10
 
14
11
  def accept(visitor)
@@ -25,16 +22,25 @@ module Cucumber
25
22
  end
26
23
 
27
24
  def matches?(visitor, cells)
28
- @scenario_outline.matches_tags_and_name?(visitor) &&
29
- (visitor.matches_lines?(cells) || visitor.matches_lines?(@scenario_outline))
25
+ @scenario_outline.matches_tags_and_name?(visitor)
30
26
  end
31
27
 
32
28
  def skip_invoke!
33
- cells_rows.each do |cells|
29
+ example_rows.each do |cells|
34
30
  cells.skip_invoke!
35
31
  end
36
32
  end
37
33
 
34
+ def create_step_invocations_for_example_rows!(scenario_outline)
35
+ example_rows.each do |cells|
36
+ cells.create_step_invocations!(scenario_outline)
37
+ end
38
+ end
39
+
40
+ def example_rows
41
+ cells_rows[1..-1]
42
+ end
43
+
38
44
  class ExampleCells < Cells
39
45
  def create_step_invocations!(scenario_outline)
40
46
  @step_invocations = scenario_outline.step_invocations(self)
@@ -31,10 +31,6 @@ module Cucumber
31
31
  @string.indent(-@quotes_indent)
32
32
  end
33
33
 
34
- def matches_lines?(lines)
35
- lines.detect{|l| l >= @start_line && l <= @end_line}
36
- end
37
-
38
34
  def accept(visitor)
39
35
  visitor.visit_py_string(to_s)
40
36
  end
@@ -8,7 +8,7 @@ module Cucumber
8
8
  def initialize(background, comment, tags, line, keyword, name, steps)
9
9
  @background, @comment, @tags, @line, @keyword, @name = background, comment, tags, line, keyword, name
10
10
  attach_steps(steps)
11
-
11
+
12
12
  step_invocations = steps.map{|step| step.step_invocation}
13
13
  if @background
14
14
  @steps = @background.step_collection(step_invocations)
@@ -23,7 +23,6 @@ module Cucumber
23
23
  end
24
24
 
25
25
  def descend?(visitor)
26
- visitor.matches_lines?(self) &&
27
26
  visitor.included_by_tags?(self) &&
28
27
  !visitor.excluded_by_tags?(self) &&
29
28
  visitor.matches_scenario_names?(self)
@@ -56,10 +56,6 @@ module Cucumber
56
56
  [:step, @line, @keyword, @name, (@multiline_arg.nil? ? nil : @multiline_arg.to_sexp)].compact
57
57
  end
58
58
 
59
- def matches_lines?(lines)
60
- lines.index(@line) || (@multiline_arg && @multiline_arg.matches_lines?(lines))
61
- end
62
-
63
59
  def source_indent
64
60
  @feature_element.source_indent(text_length)
65
61
  end
@@ -41,10 +41,6 @@ module Cucumber
41
41
  @steps[i-1]
42
42
  end
43
43
 
44
- def matches_lines?(lines)
45
- @steps.detect {|step| step.matches_lines?(lines)}
46
- end
47
-
48
44
  def empty?
49
45
  @steps.empty?
50
46
  end
@@ -85,10 +85,6 @@ module Cucumber
85
85
  end
86
86
  end
87
87
 
88
- def matches_lines?(lines)
89
- @step.matches_lines?(lines)
90
- end
91
-
92
88
  def text_length
93
89
  @step.text_length
94
90
  end
@@ -105,10 +105,6 @@ module Cucumber
105
105
  cells_rows.each(&proc)
106
106
  end
107
107
 
108
- def matches_lines?(lines)
109
- cells_rows.detect{|row| row.matches_lines?(lines)}
110
- end
111
-
112
108
  def accept(visitor)
113
109
  cells_rows.each do |row|
114
110
  visitor.visit_table_row(row)
@@ -251,10 +247,6 @@ module Cucumber
251
247
  @table, @cells = table, cells
252
248
  end
253
249
 
254
- def matches_lines?(lines)
255
- lines.index(line)
256
- end
257
-
258
250
  def accept(visitor)
259
251
  each do |cell|
260
252
  visitor.visit_table_cell(cell)
@@ -264,7 +256,7 @@ module Cucumber
264
256
 
265
257
  # For testing only
266
258
  def to_sexp #:nodoc:
267
- [:row, *@cells.map{|cell| cell.to_sexp}]
259
+ [:row, line, *@cells.map{|cell| cell.to_sexp}]
268
260
  end
269
261
 
270
262
  def to_hash #:nodoc:
@@ -15,10 +15,6 @@ module Cucumber
15
15
  (@tag_names & tags).any?
16
16
  end
17
17
 
18
- def matches_lines?(lines)
19
- lines.index(@line)
20
- end
21
-
22
18
  def accept(visitor)
23
19
  @tag_names.each do |tag_name|
24
20
  visitor.visit_tag_name(tag_name)
@@ -8,15 +8,6 @@ module Cucumber
8
8
  def initialize(step_mother)
9
9
  @options = {}
10
10
  @step_mother = step_mother
11
- @current_feature_lines = []
12
- end
13
-
14
- def current_feature_lines=(lines)
15
- @current_feature_lines = lines
16
- end
17
-
18
- def matches_lines?(node)
19
- @current_feature_lines.empty? || node.matches_lines?(@current_feature_lines)
20
11
  end
21
12
 
22
13
  def included_by_tags?(node)
@@ -257,11 +257,11 @@ module Cucumber
257
257
 
258
258
  potential_feature_files
259
259
  end
260
-
260
+
261
261
  protected
262
262
 
263
263
  def feature_dirs
264
- feature_files.map { |f| File.directory?(f) ? f : File.dirname(f) }.uniq
264
+ @paths.map { |f| File.directory?(f) ? f : File.dirname(f) }.uniq
265
265
  end
266
266
 
267
267
  def constantize(camel_cased_word)
@@ -19,6 +19,7 @@ module Cucumber
19
19
  @options = options
20
20
  @delim = delim
21
21
  @indent = 0
22
+ @exceptions = []
22
23
  end
23
24
 
24
25
  def visit_features(features)
@@ -120,30 +121,32 @@ module Cucumber
120
121
  end
121
122
 
122
123
  def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
124
+ if exception
125
+ return if @exceptions.index(exception)
126
+ @exceptions << exception
127
+ end
128
+ return if status != :failed && @in_background ^ background
129
+
130
+ # @step_matches ||= []
131
+ # return if @step_matches.index(step_match)
132
+ # @step_matches << step_match
133
+
123
134
  @status = status
124
135
  super
125
136
  end
126
137
 
127
138
  def visit_step_name(keyword, step_match, status, source_indent, background)
128
- @step_matches ||= []
129
- non_failed_background_step_outside_background = !@in_background && background && (status != :failed)
130
- @skip_step = @step_matches.index(step_match) || non_failed_background_step_outside_background
131
- @step_matches << step_match
132
-
133
- unless(@skip_step)
134
- source_indent = nil unless @options[:source]
135
- formatted_step_name = format_step(keyword, step_match, status, source_indent)
136
- @io.puts(" " + formatted_step_name)
137
- end
139
+ source_indent = nil unless @options[:source]
140
+ formatted_step_name = format_step(keyword, step_match, status, source_indent)
141
+ @io.puts(" " + formatted_step_name)
138
142
  end
139
143
 
140
144
  def visit_multiline_arg(multiline_arg)
141
- return if @options[:no_multiline] || @skip_step
145
+ return if @options[:no_multiline]
142
146
  super
143
147
  end
144
148
 
145
149
  def visit_exception(exception, status)
146
- return if @skip_step
147
150
  print_exception(exception, status, @indent)
148
151
  @io.flush
149
152
  end
@@ -152,7 +155,9 @@ module Cucumber
152
155
  @io.print @delim.indent(@indent)
153
156
  super
154
157
  @io.puts
155
- print_exception(table_row.exception, :failed, @indent) if table_row.exception
158
+ if table_row.exception && !@exceptions.index(table_row.exception)
159
+ print_exception(table_row.exception, :failed, @indent)
160
+ end
156
161
  end
157
162
 
158
163
  def visit_py_string(string)
@@ -56,14 +56,14 @@ module Cucumber
56
56
  end
57
57
 
58
58
  module Feature2
59
- def build
59
+ def build(filter)
60
60
  background = bg.respond_to?(:build) ? bg.build : nil
61
61
  Ast::Feature.new(
62
62
  background,
63
63
  comment.build,
64
64
  tags.build,
65
65
  header.text_value,
66
- feature_elements.build(background)
66
+ feature_elements.build(background, filter)
67
67
  )
68
68
  end
69
69
  end
@@ -205,6 +205,10 @@ module Cucumber
205
205
  end
206
206
 
207
207
  module Tags2
208
+ def at_line?(line)
209
+ ts.elements.detect{|e| e.tag.line == line}
210
+ end
211
+
208
212
  def build
209
213
  tag_names = ts.elements.map{|e| e.tag.tag_name.text_value}
210
214
  Ast::Tags.new(ts.line, tag_names)
@@ -565,8 +569,12 @@ module Cucumber
565
569
  end
566
570
 
567
571
  module FeatureElements0
568
- def build(background)
569
- elements.map{|s| s.build(background)}
572
+ def build(background, filter)
573
+ elements.map do |feature_element|
574
+ if filter.nil? || filter.accept?(feature_element)
575
+ feature_element.build(background, filter)
576
+ end
577
+ end.compact
570
578
  end
571
579
  end
572
580
 
@@ -642,7 +650,13 @@ module Cucumber
642
650
  end
643
651
 
644
652
  module Scenario1
645
- def build(background)
653
+ def at_line?(line)
654
+ scenario_keyword.line == line ||
655
+ steps.at_line?(line) ||
656
+ tags.at_line?(line)
657
+ end
658
+
659
+ def build(background, filter)
646
660
  Ast::Scenario.new(
647
661
  background,
648
662
  comment.build,
@@ -760,7 +774,18 @@ module Cucumber
760
774
  end
761
775
 
762
776
  module ScenarioOutline1
763
- def build(background)
777
+ def at_line?(line)
778
+ outline_at_line?(line) ||
779
+ examples_sections.at_line?(line) ||
780
+ tags.at_line?(line)
781
+ end
782
+
783
+ def outline_at_line?(line)
784
+ scenario_outline_keyword.line == line ||
785
+ steps.at_line?(line)
786
+ end
787
+
788
+ def build(background, filter)
764
789
  Ast::ScenarioOutline.new(
765
790
  background,
766
791
  comment.build,
@@ -769,7 +794,7 @@ module Cucumber
769
794
  scenario_outline_keyword.text_value,
770
795
  name.text_value,
771
796
  steps.build,
772
- examples_sections.build
797
+ examples_sections.build(filter, self)
773
798
  )
774
799
  end
775
800
  end
@@ -845,6 +870,10 @@ module Cucumber
845
870
  end
846
871
 
847
872
  module Steps0
873
+ def at_line?(line)
874
+ elements.detect{|e| e.at_line?(line)}
875
+ end
876
+
848
877
  def build
849
878
  elements.map{|e| e.build}
850
879
  end
@@ -902,6 +931,11 @@ module Cucumber
902
931
  end
903
932
 
904
933
  module Step1
934
+ def at_line?(line)
935
+ step_keyword.line == line ||
936
+ (multi.respond_to?(:at_line?) && multi.at_line?(line))
937
+ end
938
+
905
939
  def build
906
940
  if multi.respond_to?(:build)
907
941
  Ast::Step.new(step_keyword.line, step_keyword.text_value, name.text_value.strip, multi.build)
@@ -1005,8 +1039,16 @@ module Cucumber
1005
1039
  end
1006
1040
 
1007
1041
  module ExamplesSections0
1008
- def build
1009
- elements.map{|e| e.build}
1042
+ def at_line?(line)
1043
+ elements.detect { |e| e.at_line?(line) }
1044
+ end
1045
+
1046
+ def build(filter, scenario_outline)
1047
+ elements.map do |e|
1048
+ if(filter.nil? || filter.accept?(e) || filter.outline_at_line?(scenario_outline))
1049
+ e.build(filter, scenario_outline)
1050
+ end
1051
+ end.compact
1010
1052
  end
1011
1053
  end
1012
1054
 
@@ -1058,8 +1100,13 @@ module Cucumber
1058
1100
  end
1059
1101
 
1060
1102
  module Examples1
1061
- def build
1062
- [examples_keyword.line, examples_keyword.text_value, name.text_value, table.raw]
1103
+ def at_line?(line)
1104
+ examples_keyword.line == line ||
1105
+ table.at_line?(line)
1106
+ end
1107
+
1108
+ def build(filter, scenario_outline)
1109
+ [examples_keyword.line, examples_keyword.text_value, name.text_value, table.raw(filter, scenario_outline)]
1063
1110
  end
1064
1111
  end
1065
1112
 
@@ -1233,6 +1280,10 @@ module Cucumber
1233
1280
  end
1234
1281
 
1235
1282
  module PyString2
1283
+ def at_line?(line)
1284
+ line >= open_py_string.line && line <= close_py_string.line
1285
+ end
1286
+
1236
1287
  def build
1237
1288
  Ast::PyString.new(open_py_string.line, close_py_string.line, s.text_value, open_py_string.indentation)
1238
1289
  end
@@ -20,14 +20,14 @@ module Cucumber
20
20
  bg:background?
21
21
  feature_elements
22
22
  comment? {
23
- def build
23
+ def build(filter)
24
24
  background = bg.respond_to?(:build) ? bg.build : nil
25
25
  Ast::Feature.new(
26
26
  background,
27
27
  comment.build,
28
28
  tags.build,
29
29
  header.text_value,
30
- feature_elements.build(background)
30
+ feature_elements.build(background, filter)
31
31
  )
32
32
  end
33
33
  }
@@ -35,6 +35,10 @@ module Cucumber
35
35
 
36
36
  rule tags
37
37
  white ts:(tag (space/eol)+)* {
38
+ def at_line?(line)
39
+ ts.elements.detect{|e| e.tag.line == line}
40
+ end
41
+
38
42
  def build
39
43
  tag_names = ts.elements.map{|e| e.tag.tag_name.text_value}
40
44
  Ast::Tags.new(ts.line, tag_names)
@@ -74,15 +78,25 @@ module Cucumber
74
78
 
75
79
  rule feature_elements
76
80
  (scenario / scenario_outline)* {
77
- def build(background)
78
- elements.map{|s| s.build(background)}
81
+ def build(background, filter)
82
+ elements.map do |feature_element|
83
+ if filter.nil? || filter.accept?(feature_element)
84
+ feature_element.build(background, filter)
85
+ end
86
+ end.compact
79
87
  end
80
88
  }
81
89
  end
82
90
 
83
91
  rule scenario
84
92
  comment tags white scenario_keyword space* name:line_to_eol white steps white {
85
- def build(background)
93
+ def at_line?(line)
94
+ scenario_keyword.line == line ||
95
+ steps.at_line?(line) ||
96
+ tags.at_line?(line)
97
+ end
98
+
99
+ def build(background, filter)
86
100
  Ast::Scenario.new(
87
101
  background,
88
102
  comment.build,
@@ -98,7 +112,18 @@ module Cucumber
98
112
 
99
113
  rule scenario_outline
100
114
  comment tags white scenario_outline_keyword space* name:line_to_eol white steps examples_sections white {
101
- def build(background)
115
+ def at_line?(line)
116
+ outline_at_line?(line) ||
117
+ examples_sections.at_line?(line) ||
118
+ tags.at_line?(line)
119
+ end
120
+
121
+ def outline_at_line?(line)
122
+ scenario_outline_keyword.line == line ||
123
+ steps.at_line?(line)
124
+ end
125
+
126
+ def build(background, filter)
102
127
  Ast::ScenarioOutline.new(
103
128
  background,
104
129
  comment.build,
@@ -107,7 +132,7 @@ module Cucumber
107
132
  scenario_outline_keyword.text_value,
108
133
  name.text_value,
109
134
  steps.build,
110
- examples_sections.build
135
+ examples_sections.build(filter, self)
111
136
  )
112
137
  end
113
138
  }
@@ -115,6 +140,10 @@ module Cucumber
115
140
 
116
141
  rule steps
117
142
  step* {
143
+ def at_line?(line)
144
+ elements.detect{|e| e.at_line?(line)}
145
+ end
146
+
118
147
  def build
119
148
  elements.map{|e| e.build}
120
149
  end
@@ -123,6 +152,11 @@ module Cucumber
123
152
 
124
153
  rule step
125
154
  comment space* step_keyword keyword_space name:line_to_eol (eol+ / eof) multi:multiline_arg? white {
155
+ def at_line?(line)
156
+ step_keyword.line == line ||
157
+ (multi.respond_to?(:at_line?) && multi.at_line?(line))
158
+ end
159
+
126
160
  def build
127
161
  if multi.respond_to?(:build)
128
162
  Ast::Step.new(step_keyword.line, step_keyword.text_value, name.text_value.strip, multi.build)
@@ -135,16 +169,29 @@ module Cucumber
135
169
 
136
170
  rule examples_sections
137
171
  examples* {
138
- def build
139
- elements.map{|e| e.build}
172
+ def at_line?(line)
173
+ elements.detect { |e| e.at_line?(line) }
174
+ end
175
+
176
+ def build(filter, scenario_outline)
177
+ elements.map do |e|
178
+ if(filter.nil? || filter.accept?(e) || filter.outline_at_line?(scenario_outline))
179
+ e.build(filter, scenario_outline)
180
+ end
181
+ end.compact
140
182
  end
141
183
  }
142
184
  end
143
185
 
144
186
  rule examples
145
187
  space* examples_keyword space* name:line_to_eol? eol table white {
146
- def build
147
- [examples_keyword.line, examples_keyword.text_value, name.text_value, table.raw]
188
+ def at_line?(line)
189
+ examples_keyword.line == line ||
190
+ table.at_line?(line)
191
+ end
192
+
193
+ def build(filter, scenario_outline)
194
+ [examples_keyword.line, examples_keyword.text_value, name.text_value, table.raw(filter, scenario_outline)]
148
195
  end
149
196
  }
150
197
  end
@@ -159,6 +206,10 @@ module Cucumber
159
206
 
160
207
  rule py_string
161
208
  open_py_string s:(!close_py_string .)* close_py_string {
209
+ def at_line?(line)
210
+ line >= open_py_string.line && line <= close_py_string.line
211
+ end
212
+
162
213
  def build
163
214
  Ast::PyString.new(open_py_string.line, close_py_string.line, s.text_value, open_py_string.indentation)
164
215
  end
@@ -14,12 +14,20 @@ module Cucumber
14
14
  end
15
15
 
16
16
  module Table0
17
+ def at_line?(line)
18
+ elements.detect{|table_row| table_row.at_line?(line)}
19
+ end
20
+
17
21
  def build
18
22
  Ast::Table.new(raw)
19
23
  end
20
24
 
21
- def raw
22
- elements.map{|e| e.build}
25
+ def raw(filter=nil, scenario_outline=nil)
26
+ elements.map do |table_row|
27
+ if(filter.nil? || table_row == elements[0] || filter.at_line?(table_row) || (scenario_outline && filter.outline_at_line?(scenario_outline)))
28
+ table_row.build
29
+ end
30
+ end.compact
23
31
  end
24
32
  end
25
33
 
@@ -44,7 +52,7 @@ module Cucumber
44
52
  self.index = i0
45
53
  r0 = nil
46
54
  else
47
- r0 = SyntaxNode.new(input, i0...index, s0)
55
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
48
56
  r0.extend(Table0)
49
57
  end
50
58
 
@@ -68,6 +76,10 @@ module Cucumber
68
76
  end
69
77
 
70
78
  module TableRow2
79
+ def at_line?(line)
80
+ cells.line == line
81
+ end
82
+
71
83
  def build
72
84
  row = cells.elements.map do |elt|
73
85
  value = elt.cell.text_value.strip
@@ -101,11 +113,11 @@ module Cucumber
101
113
  break
102
114
  end
103
115
  end
104
- r1 = SyntaxNode.new(input, i1...index, s1)
116
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
105
117
  s0 << r1
106
118
  if r1
107
119
  if input.index('|', index) == index
108
- r3 = (SyntaxNode).new(input, index...(index + 1))
120
+ r3 = instantiate_node(SyntaxNode,input, index...(index + 1))
109
121
  @index += 1
110
122
  else
111
123
  terminal_parse_failure('|')
@@ -120,7 +132,7 @@ module Cucumber
120
132
  s5 << r6
121
133
  if r6
122
134
  if input.index('|', index) == index
123
- r7 = (SyntaxNode).new(input, index...(index + 1))
135
+ r7 = instantiate_node(SyntaxNode,input, index...(index + 1))
124
136
  @index += 1
125
137
  else
126
138
  terminal_parse_failure('|')
@@ -129,7 +141,7 @@ module Cucumber
129
141
  s5 << r7
130
142
  end
131
143
  if s5.last
132
- r5 = (SyntaxNode).new(input, i5...index, s5)
144
+ r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
133
145
  r5.extend(TableRow0)
134
146
  else
135
147
  self.index = i5
@@ -145,7 +157,7 @@ module Cucumber
145
157
  self.index = i4
146
158
  r4 = nil
147
159
  else
148
- r4 = SyntaxNode.new(input, i4...index, s4)
160
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
149
161
  end
150
162
  s0 << r4
151
163
  if r4
@@ -158,7 +170,7 @@ module Cucumber
158
170
  break
159
171
  end
160
172
  end
161
- r8 = SyntaxNode.new(input, i8...index, s8)
173
+ r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
162
174
  s0 << r8
163
175
  if r8
164
176
  i10 = index
@@ -175,7 +187,7 @@ module Cucumber
175
187
  self.index = i11
176
188
  r11 = nil
177
189
  else
178
- r11 = SyntaxNode.new(input, i11...index, s11)
190
+ r11 = instantiate_node(SyntaxNode,input, i11...index, s11)
179
191
  end
180
192
  if r11
181
193
  r10 = r11
@@ -194,7 +206,7 @@ module Cucumber
194
206
  end
195
207
  end
196
208
  if s0.last
197
- r0 = (SyntaxNode).new(input, i0...index, s0)
209
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
198
210
  r0.extend(TableRow1)
199
211
  r0.extend(TableRow2)
200
212
  else
@@ -224,7 +236,7 @@ module Cucumber
224
236
  i2 = index
225
237
  i3 = index
226
238
  if input.index('|', index) == index
227
- r4 = (SyntaxNode).new(input, index...(index + 1))
239
+ r4 = instantiate_node(SyntaxNode,input, index...(index + 1))
228
240
  @index += 1
229
241
  else
230
242
  terminal_parse_failure('|')
@@ -245,12 +257,12 @@ module Cucumber
245
257
  r2 = nil
246
258
  else
247
259
  self.index = i2
248
- r2 = SyntaxNode.new(input, index...index)
260
+ r2 = instantiate_node(SyntaxNode,input, index...index)
249
261
  end
250
262
  s1 << r2
251
263
  if r2
252
264
  if index < input_length
253
- r6 = (SyntaxNode).new(input, index...(index + 1))
265
+ r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
254
266
  @index += 1
255
267
  else
256
268
  terminal_parse_failure("any character")
@@ -259,7 +271,7 @@ module Cucumber
259
271
  s1 << r6
260
272
  end
261
273
  if s1.last
262
- r1 = (SyntaxNode).new(input, i1...index, s1)
274
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
263
275
  r1.extend(Cell0)
264
276
  else
265
277
  self.index = i1
@@ -271,7 +283,7 @@ module Cucumber
271
283
  break
272
284
  end
273
285
  end
274
- r0 = SyntaxNode.new(input, i0...index, s0)
286
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
275
287
 
276
288
  node_cache[:cell][start_index] = r0
277
289
 
@@ -287,7 +299,7 @@ module Cucumber
287
299
  end
288
300
 
289
301
  if input.index(Regexp.new('[ \\t]'), index) == index
290
- r0 = (SyntaxNode).new(input, index...(index + 1))
302
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
291
303
  @index += 1
292
304
  else
293
305
  r0 = nil
@@ -311,7 +323,7 @@ module Cucumber
311
323
 
312
324
  i0 = index
313
325
  if input.index("\n", index) == index
314
- r1 = (SyntaxNode).new(input, index...(index + 1))
326
+ r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
315
327
  @index += 1
316
328
  else
317
329
  terminal_parse_failure("\n")
@@ -322,7 +334,7 @@ module Cucumber
322
334
  else
323
335
  i2, s2 = index, []
324
336
  if input.index("\r", index) == index
325
- r3 = (SyntaxNode).new(input, index...(index + 1))
337
+ r3 = instantiate_node(SyntaxNode,input, index...(index + 1))
326
338
  @index += 1
327
339
  else
328
340
  terminal_parse_failure("\r")
@@ -331,7 +343,7 @@ module Cucumber
331
343
  s2 << r3
332
344
  if r3
333
345
  if input.index("\n", index) == index
334
- r5 = (SyntaxNode).new(input, index...(index + 1))
346
+ r5 = instantiate_node(SyntaxNode,input, index...(index + 1))
335
347
  @index += 1
336
348
  else
337
349
  terminal_parse_failure("\n")
@@ -340,12 +352,12 @@ module Cucumber
340
352
  if r5
341
353
  r4 = r5
342
354
  else
343
- r4 = SyntaxNode.new(input, index...index)
355
+ r4 = instantiate_node(SyntaxNode,input, index...index)
344
356
  end
345
357
  s2 << r4
346
358
  end
347
359
  if s2.last
348
- r2 = (SyntaxNode).new(input, i2...index, s2)
360
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
349
361
  r2.extend(Eol0)
350
362
  else
351
363
  self.index = i2
@@ -374,7 +386,7 @@ module Cucumber
374
386
 
375
387
  i0 = index
376
388
  if index < input_length
377
- r1 = (SyntaxNode).new(input, index...(index + 1))
389
+ r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
378
390
  @index += 1
379
391
  else
380
392
  terminal_parse_failure("any character")
@@ -384,7 +396,7 @@ module Cucumber
384
396
  r0 = nil
385
397
  else
386
398
  self.index = i0
387
- r0 = SyntaxNode.new(input, index...index)
399
+ r0 = instantiate_node(SyntaxNode,input, index...index)
388
400
  end
389
401
 
390
402
  node_cache[:eof][start_index] = r0
@@ -10,18 +10,30 @@ module Cucumber
10
10
 
11
11
  rule table
12
12
  table_row+ {
13
+ def at_line?(line)
14
+ elements.detect{|table_row| table_row.at_line?(line)}
15
+ end
16
+
13
17
  def build
14
18
  Ast::Table.new(raw)
15
19
  end
16
20
 
17
- def raw
18
- elements.map{|e| e.build}
21
+ def raw(filter=nil, scenario_outline=nil)
22
+ elements.map do |table_row|
23
+ if(filter.nil? || table_row == elements[0] || filter.at_line?(table_row) || (scenario_outline && filter.outline_at_line?(scenario_outline)))
24
+ table_row.build
25
+ end
26
+ end.compact
19
27
  end
20
28
  }
21
29
  end
22
30
 
23
31
  rule table_row
24
32
  space* '|' cells:(cell '|')+ space* (eol+ / eof) {
33
+ def at_line?(line)
34
+ cells.line == line
35
+ end
36
+
25
37
  def build
26
38
  row = cells.elements.map do |elt|
27
39
  value = elt.cell.text_value.strip
@@ -12,7 +12,25 @@ end
12
12
 
13
13
  module Cucumber
14
14
  module Parser
15
- module TreetopExt
15
+ class Filter
16
+ def initialize(lines)
17
+ @lines = lines
18
+ end
19
+
20
+ def accept?(syntax_node)
21
+ at_line?(syntax_node) # || more to come...
22
+ end
23
+
24
+ def at_line?(syntax_node)
25
+ @lines.detect{|line| syntax_node.at_line?(line)}
26
+ end
27
+
28
+ def outline_at_line?(syntax_node)
29
+ @lines.detect{|line| syntax_node.outline_at_line?(line)}
30
+ end
31
+ end
32
+
33
+ module TreetopExt
16
34
  FILE_COLON_LINE_PATTERN = /^([\w\W]*?):([\d:]+)$/
17
35
 
18
36
  # Parses a file and returns a Cucumber::Ast
@@ -20,28 +38,28 @@ module Cucumber
20
38
  _, path, lines = *FILE_COLON_LINE_PATTERN.match(file)
21
39
  if path
22
40
  lines = lines.split(':').map { |line| line.to_i }
41
+ filter = Filter.new(lines)
23
42
  else
24
43
  path = file
25
- lines = []
44
+ filter = nil
26
45
  end
27
46
 
28
- loader = lambda { |io| parse_or_fail(io.read, path) }
47
+ loader = lambda { |io| parse_or_fail(io.read, filter, path) }
29
48
  feature = if path =~ /^http/
30
49
  require 'open-uri'
31
50
  open(path, &loader)
32
51
  else
33
52
  File.open(path, Cucumber.file_mode('r'), &loader)
34
53
  end
35
- feature.lines = lines
36
54
  feature
37
55
  end
38
56
 
39
- def parse_or_fail(s, file=nil, line_offset=0)
40
- parse_tree = parse(s)
57
+ def parse_or_fail(string, filter=nil, file=nil, line_offset=0)
58
+ parse_tree = parse(string)
41
59
  if parse_tree.nil?
42
60
  raise Cucumber::Parser::SyntaxError.new(self, file, line_offset)
43
61
  else
44
- ast = parse_tree.build
62
+ ast = parse_tree.build(filter)
45
63
  ast.file = file
46
64
  ast
47
65
  end
@@ -3,7 +3,7 @@ module Cucumber #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 2
5
5
  TINY = 3
6
- PATCH = 2 # Set to nil for official release
6
+ PATCH = 3 # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
9
9
  end
@@ -25,9 +25,9 @@ module Cucumber
25
25
  [:step_invocation, 3, "Given", "a passing step"], # From the background
26
26
  [:step_invocation, 10, "Given", "a passing step with an inline arg:",
27
27
  [:table,
28
- [:row,
28
+ [:row, -1,
29
29
  [:cell, "1"], [:cell, "22"], [:cell, "333"]],
30
- [:row,
30
+ [:row, -1,
31
31
  [:cell, "4444"], [:cell, "55555"], [:cell, "666666"]]]],
32
32
  [:step_invocation, 11, "Given", "a happy step with an inline arg:",
33
33
  [:py_string, "\n I like\nCucumber sandwich\n"]],
@@ -33,33 +33,6 @@ module Cucumber
33
33
  $y.should == nil
34
34
  end
35
35
 
36
- it "should be at exact line" do
37
- s = Scenario.new(background=nil, comment=Comment.new(""),
38
- tags=Tags.new(44, []), 45, keyword="", name="", steps=[])
39
-
40
- s.should be_matches_lines([44])
41
- s.should be_matches_lines([45])
42
- end
43
-
44
- it "should be at line if tags or steps are" do
45
- s = Scenario.new(
46
- background=nil,
47
- comment=Comment.new(""),
48
- tags=Tags.new(43, []),
49
- line=45,
50
- keyword="",
51
- name="",
52
- steps=[
53
- Step.new(46, "Given", ""),
54
- Step.new(47, "Given", ""),
55
- Step.new(48, "Given", ""),
56
- ]
57
- )
58
-
59
- s.should be_matches_lines([43])
60
- s.should be_matches_lines([47])
61
- s.should_not be_matches_lines([49])
62
- end
63
36
  end
64
37
  end
65
38
  end
@@ -155,12 +155,12 @@ module Cucumber
155
155
  it "should convert to sexp" do
156
156
  @table.to_sexp.should ==
157
157
  [:table,
158
- [:row,
158
+ [:row, -1,
159
159
  [:cell, "one"],
160
160
  [:cell, "four"],
161
161
  [:cell, "seven"]
162
162
  ],
163
- [:row,
163
+ [:row, -1,
164
164
  [:cell, "4444"],
165
165
  [:cell, "55555"],
166
166
  [:cell, "666666"]]]
@@ -36,23 +36,6 @@ Feature: hi
36
36
  [:feature, nil, "Feature: hi\n",
37
37
  [:comment, "# My comment\n"]]
38
38
  end
39
-
40
- it "should parse a comment within a scenario" do
41
- pending "Store comment in node and output it in pretty formatter"
42
- parse(%{Feature: Hi
43
- Scenario: Hello
44
- Given foo
45
- # When bar
46
- Then baz
47
- }).to_sexp.should ==
48
- [:feature, nil, "Feature: Hi",
49
- [:scenario, 2, "Scenario:", "Hello",
50
- [:step, 3, "Given", "foo"],
51
- [:comment, "# When bar\n"],
52
- [:step, 5, "Then", "baz"]
53
- ]
54
- ]
55
- end
56
39
 
57
40
  it "should parse a file with only a multiline comment" do
58
41
  parse(%{# Hello
@@ -149,7 +132,7 @@ Given I have a table
149
132
  [:scenario, 2, "Scenario:", "Hello",
150
133
  [:step_invocation, 3, "Given", "I have a table",
151
134
  [:table,
152
- [:row,
135
+ [:row, 4,
153
136
  [:cell, "a"],
154
137
  [:cell, "b"]]]]]]
155
138
  end
@@ -187,9 +170,10 @@ Examples:
187
170
  [:step, 3, "Given", "a <what> cucumber"],
188
171
  [:examples, "Examples:", "",
189
172
  [:table,
190
- [:row,
173
+ [:row, 5,
191
174
  [:cell, "what"]],
192
- [:row, [:cell, "green"]]]]]]
175
+ [:row, 6,
176
+ [:cell, "green"]]]]]]
193
177
  end
194
178
 
195
179
  it "should have line numbered steps with inline table" do
@@ -207,15 +191,15 @@ Examples:
207
191
  [:scenario_outline, "Scenario Outline:", "Hello",
208
192
  [:step, 4, "Given", "I have a table",
209
193
  [:table,
210
- [:row,
194
+ [:row, 6,
211
195
  [:cell, "<a>"],
212
196
  [:cell, "<b>"]]]],
213
197
  [:examples, "Examples:", "",
214
198
  [:table,
215
- [:row,
199
+ [:row, 8,
216
200
  [:cell, "a"],
217
201
  [:cell, "b"]],
218
- [:row,
202
+ [:row, 9,
219
203
  [:cell, "c"],
220
204
  [:cell, "d"]]]]]]
221
205
  end
@@ -237,23 +221,18 @@ Examples:
237
221
  [:scenario_outline, "Scenario Outline:", "Hello",
238
222
  [:step, 5, "Given", "I have a table",
239
223
  [:table,
240
- [:row,
224
+ [:row, 6,
241
225
  [:cell, "1"],
242
226
  [:cell, "2"]]]],
243
227
  [:examples, "Examples:", "",
244
228
  [:table,
245
- [:row,
229
+ [:row, 9,
246
230
  [:cell, "x"],
247
231
  [:cell, "y"]],
248
- [:row,
232
+ [:row, 10,
249
233
  [:cell, "5"],
250
234
  [:cell, "6"]]]]]]
251
235
  end
252
-
253
- it "should set line numbers on feature" do
254
- feature = parse_file("empty_feature.feature:11:12")
255
- feature.instance_variable_get('@lines').should == [11, 12]
256
- end
257
236
  end
258
237
 
259
238
  describe "Syntax" do
@@ -277,6 +256,37 @@ Examples:
277
256
  parse_file("scenario_outline.feature")
278
257
  end
279
258
  end
259
+
260
+ describe "Filtering" do
261
+ it "should filter outline tables" do
262
+ f = parse_example_file('self_test/features/outline_sample.feature:12')
263
+ f.to_sexp.should ==
264
+ [:feature,
265
+ "./spec/cucumber/parser/../../../examples/self_test/features/outline_sample.feature",
266
+ "Feature: Outline Sample",
267
+ [:scenario_outline,
268
+ "Scenario Outline:",
269
+ "Test state",
270
+ [:step, 6, "Given", "<state> without a table"],
271
+ [:step, 7, "Given", "<other_state> without a table"],
272
+ [:examples,
273
+ "Examples:",
274
+ "Rainbow colours",
275
+ [:table,
276
+ [:row, 9, [:cell, "state"], [:cell, "other_state"]],
277
+ # [:row, 10, [:cell, "missing"], [:cell, "passing"]],
278
+ # [:row, 11, [:cell, "passing"], [:cell, "passing"]],
279
+ [:row, 12, [:cell, "failing"], [:cell, "passing"]]]]
280
+ # ,
281
+ # [:examples,
282
+ # "Examples:",
283
+ # "Only passing",
284
+ # [:table,
285
+ # [:row, 14, [:cell, "state"], [:cell, "other_state"]],
286
+ # [:row, 15, [:cell, "passing"], [:cell, "passing"]]]]]
287
+ ]]
288
+ end
289
+ end
280
290
  end
281
291
  end
282
292
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aslakhellesoy-cucumber
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3.2
4
+ version: 0.2.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Aslak Helles\xC3\xB8y"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-06 00:00:00 -07:00
12
+ date: 2009-04-07 00:00:00 -07:00
13
13
  default_executable: cucumber
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -266,6 +266,8 @@ files:
266
266
  - examples/tickets/features/241.feature
267
267
  - examples/tickets/features/246.feature
268
268
  - examples/tickets/features/248.feature
269
+ - examples/tickets/features/270/back.feature
270
+ - examples/tickets/features/270/back.steps.rb
269
271
  - examples/tickets/features/lib/eatting_machine.rb
270
272
  - examples/tickets/features/lib/pantry.rb
271
273
  - examples/tickets/features/scenario_outline.feature
@@ -346,7 +348,6 @@ files:
346
348
  - lib/cucumber/formatters/unicode.rb
347
349
  - lib/cucumber/languages.yml
348
350
  - lib/cucumber/parser.rb
349
- - lib/cucumber/parser/basic.rb
350
351
  - lib/cucumber/parser/feature.rb
351
352
  - lib/cucumber/parser/feature.tt
352
353
  - lib/cucumber/parser/i18n.tt
File without changes