aslakhellesoy-cucumber 0.2.3.2 → 0.2.3.3

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 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