aslakhellesoy-cucumber 0.3.11.3 → 0.3.11.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/History.txt +35 -0
  2. data/Manifest.txt +5 -0
  3. data/config/hoe.rb +1 -2
  4. data/examples/i18n/ar/Rakefile +1 -1
  5. data/examples/i18n/ar/features/addition.feature +1 -0
  6. data/examples/i18n/bg/Rakefile +1 -1
  7. data/examples/i18n/bg/features/addition.feature +1 -0
  8. data/examples/i18n/bg/features/consecutive_calculations.feature +1 -0
  9. data/examples/i18n/bg/features/division.feature +1 -0
  10. data/examples/i18n/cat/Rakefile +1 -1
  11. data/examples/i18n/cat/features/suma.feature +1 -0
  12. data/examples/i18n/da/Rakefile +1 -1
  13. data/examples/i18n/da/features/summering.feature +1 -0
  14. data/examples/i18n/de/Rakefile +1 -1
  15. data/examples/i18n/de/features/addition.feature +1 -0
  16. data/examples/i18n/de/features/division.feature +1 -0
  17. data/examples/i18n/en-lol/features/stuffing.feature +1 -1
  18. data/examples/i18n/en/Rakefile +1 -1
  19. data/examples/i18n/en/features/addition.feature +1 -0
  20. data/examples/i18n/en/features/division.feature +1 -0
  21. data/examples/i18n/es/Rakefile +1 -1
  22. data/examples/i18n/es/features/adicion.feature +1 -0
  23. data/examples/i18n/et/Rakefile +1 -1
  24. data/examples/i18n/et/features/jagamine.feature +1 -0
  25. data/examples/i18n/et/features/liitmine.feature +1 -0
  26. data/examples/i18n/fi/Rakefile +1 -1
  27. data/examples/i18n/fi/features/jakolasku.feature +1 -0
  28. data/examples/i18n/fr/Rakefile +1 -1
  29. data/examples/i18n/fr/features/addition.feature +2 -1
  30. data/examples/i18n/he/Rakefile +1 -1
  31. data/examples/i18n/he/features/addition.feature +1 -0
  32. data/examples/i18n/he/features/division.feature +1 -0
  33. data/examples/i18n/hu/Rakefile +1 -1
  34. data/examples/i18n/hu/features/addition.feature +1 -0
  35. data/examples/i18n/hu/features/division.feature +1 -0
  36. data/examples/i18n/id/Rakefile +1 -1
  37. data/examples/i18n/id/features/addition.feature +1 -0
  38. data/examples/i18n/id/features/division.feature +1 -0
  39. data/examples/i18n/it/Rakefile +1 -1
  40. data/examples/i18n/it/features/somma.feature +1 -0
  41. data/examples/i18n/ja/Rakefile +1 -1
  42. data/examples/i18n/ja/features/addition.feature +1 -0
  43. data/examples/i18n/ja/features/division.feature +1 -0
  44. data/examples/i18n/ko/Rakefile +1 -1
  45. data/examples/i18n/ko/features/addition.feature +1 -0
  46. data/examples/i18n/ko/features/division.feature +1 -0
  47. data/examples/i18n/lt/Rakefile +1 -1
  48. data/examples/i18n/lt/features/addition.feature +1 -0
  49. data/examples/i18n/lt/features/division.feature +1 -0
  50. data/examples/i18n/lv/Rakefile +1 -1
  51. data/examples/i18n/lv/features/addition.feature +1 -0
  52. data/examples/i18n/lv/features/division.feature +1 -0
  53. data/examples/i18n/no/Rakefile +1 -1
  54. data/examples/i18n/no/features/summering.feature +1 -0
  55. data/examples/i18n/pl/Rakefile +1 -1
  56. data/examples/i18n/pl/features/addition.feature +1 -0
  57. data/examples/i18n/pl/features/division.feature +1 -0
  58. data/examples/i18n/pt/Rakefile +1 -1
  59. data/examples/i18n/pt/features/adicao.feature +1 -0
  60. data/examples/i18n/ro/Rakefile +1 -1
  61. data/examples/i18n/ro/features/suma.feature +1 -0
  62. data/examples/i18n/ru/Rakefile +1 -1
  63. data/examples/i18n/ru/features/addition.feature +1 -0
  64. data/examples/i18n/ru/features/consecutive_calculations.feature +1 -0
  65. data/examples/i18n/ru/features/division.feature +1 -0
  66. data/examples/i18n/se/Rakefile +1 -1
  67. data/examples/i18n/se/features/summering.feature +1 -0
  68. data/examples/i18n/sk/Rakefile +1 -1
  69. data/examples/i18n/sk/features/addition.feature +1 -0
  70. data/examples/i18n/sk/features/division.feature +1 -0
  71. data/examples/i18n/zh-CN/features/addition.feature +1 -0
  72. data/examples/i18n/zh-TW/features/addition.feature +1 -0
  73. data/examples/i18n/zh-TW/features/division.feature +1 -0
  74. data/examples/sinatra/features/step_definitions/add_steps.rb +1 -1
  75. data/examples/sinatra/features/support/env.rb +13 -5
  76. data/features/after_block_exceptions.feature +4 -1
  77. data/features/after_step_block_exceptions.feature +4 -1
  78. data/features/background.feature +6 -0
  79. data/features/bug_371.feature +32 -0
  80. data/features/cucumber_cli.feature +11 -1
  81. data/features/cucumber_cli_diff_disabled.feature +7 -1
  82. data/features/drb_server_integration.feature +5 -4
  83. data/features/expand.feature +2 -1
  84. data/features/html_formatter/a.html +33 -30
  85. data/features/junit_formatter.feature +4 -4
  86. data/features/language_from_header.feature +30 -0
  87. data/features/step_definitions/cucumber_steps.rb +2 -2
  88. data/features/support/env.rb +7 -4
  89. data/features/work_in_progress.feature +3 -0
  90. data/lib/cucumber.rb +0 -57
  91. data/lib/cucumber/ast/comment.rb +1 -1
  92. data/lib/cucumber/ast/feature.rb +2 -2
  93. data/lib/cucumber/ast/feature_element.rb +4 -0
  94. data/lib/cucumber/ast/scenario.rb +5 -3
  95. data/lib/cucumber/ast/scenario_outline.rb +6 -1
  96. data/lib/cucumber/ast/step.rb +4 -0
  97. data/lib/cucumber/ast/step_invocation.rb +6 -1
  98. data/lib/cucumber/cli/configuration.rb +36 -26
  99. data/lib/cucumber/cli/main.rb +4 -5
  100. data/lib/cucumber/feature_file.rb +47 -0
  101. data/lib/cucumber/filter.rb +50 -0
  102. data/lib/cucumber/formatter/console.rb +12 -0
  103. data/lib/cucumber/formatter/cucumber.css +19 -14
  104. data/lib/cucumber/formatter/cucumber.sass +18 -13
  105. data/lib/cucumber/formatter/html.rb +4 -3
  106. data/lib/cucumber/formatter/junit.rb +3 -6
  107. data/lib/cucumber/formatter/pretty.rb +2 -4
  108. data/lib/cucumber/formatter/profile.rb +1 -1
  109. data/lib/cucumber/parser.rb +1 -33
  110. data/lib/cucumber/parser/feature.rb +12 -16
  111. data/lib/cucumber/parser/feature.tt +1 -3
  112. data/lib/cucumber/parser/i18n.tt +30 -23
  113. data/lib/cucumber/parser/i18n/language.rb +80 -0
  114. data/lib/cucumber/parser/treetop_ext.rb +12 -83
  115. data/lib/cucumber/platform.rb +6 -0
  116. data/lib/cucumber/step_mother.rb +3 -3
  117. data/lib/cucumber/version.rb +1 -1
  118. data/rails_generators/cucumber/templates/cucumber.rake +4 -0
  119. data/spec/cucumber/ast/step_collection_spec.rb +5 -4
  120. data/spec/cucumber/cli/configuration_spec.rb +42 -9
  121. data/spec/cucumber/cli/main_spec.rb +2 -10
  122. data/spec/cucumber/parser/feature_parser_spec.rb +11 -9
  123. data/spec/cucumber/parser/table_parser_spec.rb +1 -1
  124. data/spec/spec_helper.rb +0 -1
  125. metadata +8 -13
@@ -0,0 +1,47 @@
1
+ require 'cucumber/parser/i18n/language'
2
+ require 'cucumber/filter'
3
+
4
+ module Cucumber
5
+ class FeatureFile
6
+ FILE_COLON_LINE_PATTERN = /^([\w\W]*?):([\d:]+)$/
7
+ LANGUAGE_PATTERN = /language:\s*(.*)/
8
+
9
+ # The +uri+ argument can ba a path or a path:line1:line2 etc.
10
+ def initialize(uri, source=nil)
11
+ @source = source
12
+ _, @path, @lines = *FILE_COLON_LINE_PATTERN.match(uri)
13
+ if @path
14
+ @lines = @lines.split(':').map { |line| line.to_i }
15
+ else
16
+ @path = uri
17
+ end
18
+ end
19
+
20
+ # Parses a file and returns a Cucumber::Ast
21
+ # If +options+ contains tags, the result will
22
+ # be filtered.
23
+ def parse(options={})
24
+ filter = Filter.new(@lines, options)
25
+ language = Parser::I18n::Language[lang || options[:lang] || 'en']
26
+ language.parse(source, @path, filter)
27
+ end
28
+
29
+ def source
30
+ @source ||= if @path =~ /^http/
31
+ require 'open-uri'
32
+ open(@path).read
33
+ else
34
+ File.open(@path, Cucumber.file_mode('r')).read
35
+ end
36
+ end
37
+
38
+ def lang
39
+ line_one = source.split(/\n/)[0]
40
+ if line_one =~ LANGUAGE_PATTERN
41
+ $1.strip
42
+ else
43
+ nil
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,50 @@
1
+ module Cucumber
2
+ class Filter
3
+ def initialize(lines, options)
4
+ @lines = lines
5
+ @include_tags = options[:include_tags] || []
6
+ @exclude_tags = options[:exclude_tags] || []
7
+ @name_regexps = options[:name_regexps] || []
8
+ end
9
+
10
+ def accept?(syntax_node)
11
+ at_line?(syntax_node) &&
12
+ matches_tags?(syntax_node) &&
13
+ matches_names?(syntax_node)
14
+ end
15
+
16
+ def accept_example?(syntax_node, outline)
17
+ (at_line?(syntax_node) || outline_at_line?(outline)) &&
18
+ (matches_names?(syntax_node) || outline_matches_names?(outline))
19
+ end
20
+
21
+ def at_line?(syntax_node)
22
+ @lines.nil? || @lines.empty? || @lines.detect{|line| syntax_node.at_line?(line)}
23
+ end
24
+
25
+ def outline_at_line?(syntax_node)
26
+ @lines.nil? || @lines.empty? || @lines.detect{|line| syntax_node.outline_at_line?(line)}
27
+ end
28
+
29
+ def matches_tags?(syntax_node)
30
+ !excluded_by_tags?(syntax_node) &&
31
+ included_by_tags?(syntax_node)
32
+ end
33
+
34
+ def included_by_tags?(syntax_node)
35
+ @include_tags.empty? || syntax_node.has_tags?(@include_tags)
36
+ end
37
+
38
+ def excluded_by_tags?(syntax_node)
39
+ @exclude_tags.any? && syntax_node.has_tags?(@exclude_tags)
40
+ end
41
+
42
+ def outline_matches_names?(syntax_node)
43
+ @name_regexps.nil? || @name_regexps.empty? || @name_regexps.detect{|name_regexp| syntax_node.outline_matches_name?(name_regexp)}
44
+ end
45
+
46
+ def matches_names?(syntax_node)
47
+ @name_regexps.nil? || @name_regexps.empty? || @name_regexps.detect{|name_regexp| syntax_node.matches_name?(name_regexp)}
48
+ end
49
+ end
50
+ end
@@ -59,6 +59,18 @@ module Cucumber
59
59
  end
60
60
 
61
61
  def print_stats(features)
62
+
63
+ @failures = step_mother.scenarios(:failed).select { |s| s.is_a?(Cucumber::Ast::Scenario) }
64
+
65
+ if !@failures.empty?
66
+ @io.puts format_string("Failing Scenarios:", :failed)
67
+ @failures.each do |failure|
68
+ @io.puts format_string("cucumber " + failure.file_colon_line, :failed) +
69
+ format_string(" # Scenario: " + failure.name, :comment)
70
+ end
71
+ @io.puts
72
+ end
73
+
62
74
  @io.print dump_count(step_mother.scenarios.length, "scenario")
63
75
  print_status_counts{|status| step_mother.scenarios(status)}
64
76
 
@@ -6,6 +6,22 @@
6
6
  background: white;
7
7
  padding: 1em;
8
8
  }
9
+ .cucumber h1, .cucumber h2, .cucumber h3, .cucumber h4, .cucumber ol, .cucumber li, .cucumber pre, .cucumber p {
10
+ font-size: 1em;
11
+ padding: 0px;
12
+ margin: 0px;
13
+ }
14
+ .cucumber div.feature {
15
+ border: 1px solid;
16
+ padding: 2px;
17
+ margin: 4px;
18
+ }
19
+ .cucumber div.feature div.background, .cucumber div.feature div.scenario, .cucumber div.feature p {
20
+ padding: 0em 0em 0em 1em;
21
+ }
22
+ .cucumber div.feature div.background div.examples, .cucumber div.feature div.scenario div.examples, .cucumber div.feature p div.examples {
23
+ padding: 0em 0em 0em 1em;
24
+ }
9
25
  .cucumber .stats {
10
26
  margin: 2em;
11
27
  }
@@ -27,16 +43,7 @@
27
43
  .cucumber a:visited {
28
44
  font-weight: normal;
29
45
  }
30
- .cucumber div.background, .cucumber div.scenario {
31
- border: 1px solid;
32
- padding: 2px;
33
- margin: 4px;
34
- }
35
- .cucumber div.background h3, .cucumber div.background h4, .cucumber div.scenario h3, .cucumber div.scenario h4 {
36
- padding: 0px;
37
- margin: 0px;
38
- }
39
- .cucumber div.background div.examples, .cucumber div.scenario div.examples {
46
+ .cucumber a div.examples {
40
47
  border: 1px solid;
41
48
  padding: 2px;
42
49
  margin: 4px;
@@ -70,12 +77,10 @@
70
77
  }
71
78
  .cucumber ol {
72
79
  list-style: none;
73
- margin-left: 0;
74
- padding-left: 0;
75
80
  }
76
81
  .cucumber ol li {
77
- margin: 5px 0 5px 5px;
78
- padding: 0.3em;
82
+ margin: 0em 0em 0em 1em;
83
+ padding: 0em 0em 0em 0.2em;
79
84
  }
80
85
  .cucumber ol li span.param {
81
86
  font-weight: bold;
@@ -29,6 +29,21 @@
29
29
  :font-size 0.7em
30
30
  :background white
31
31
  :padding 1em
32
+
33
+ h1, h2, h3, h4, ol, li, pre, p
34
+ :font-size 1em
35
+ :padding 0px
36
+ :margin 0px
37
+
38
+ div.feature
39
+ :border 1px solid
40
+ :padding 2px
41
+ :margin 4px
42
+
43
+ div.background, div.scenario, p
44
+ :padding 0em 0em 0em 1em
45
+ div.examples
46
+ :padding 0em 0em 0em 1em
32
47
 
33
48
  .stats
34
49
  :margin 2em
@@ -52,14 +67,6 @@
52
67
  &:visited
53
68
  :font-weight normal
54
69
 
55
- div.background, div.scenario
56
- :border 1px solid
57
- :padding 2px
58
- :margin 4px
59
-
60
- h3, h4
61
- :padding 0px
62
- :margin 0px
63
70
  div.examples
64
71
  :border 1px solid
65
72
  :padding 2px
@@ -67,7 +74,7 @@
67
74
 
68
75
  table
69
76
  :border-collapse collapse
70
-
77
+
71
78
  td, th
72
79
  :font-size 0.7em
73
80
  :border 1px solid #AAAAAA
@@ -89,12 +96,10 @@
89
96
 
90
97
  ol
91
98
  :list-style none
92
- :margin-left 0
93
- :padding-left 0
94
99
 
95
100
  li
96
- :margin 5px 0 5px 5px
97
- :padding 0.3em
101
+ :margin 0em 0em 0em 1em
102
+ :padding 0em 0em 0em 0.2em
98
103
  span.param
99
104
  :font-weight bold
100
105
  li.failed
@@ -54,7 +54,8 @@ module Cucumber
54
54
  end
55
55
 
56
56
  def visit_comment_line(comment_line)
57
- @builder.text!(comment_line.strip + "\n")
57
+ @builder.text!(comment_line)
58
+ @builder.br
58
59
  end
59
60
 
60
61
  def visit_feature(feature)
@@ -73,7 +74,7 @@ module Cucumber
73
74
  @builder.h2 do |h2|
74
75
  @builder.span(lines[0], :class => 'val')
75
76
  end
76
- @builder.p do
77
+ @builder.p(:class => 'narrative') do
77
78
  lines[1..-1].each do |line|
78
79
  @builder.text!(line.strip)
79
80
  @builder.br
@@ -191,7 +192,7 @@ module Cucumber
191
192
 
192
193
  def visit_py_string(string)
193
194
  @builder.pre(:class => 'val') do |pre|
194
- @builder.text!(string)
195
+ @builder.text!(' ' + string)
195
196
  end
196
197
  end
197
198
 
@@ -31,13 +31,14 @@ module Cucumber
31
31
  @testsuite << @builder.target!
32
32
  end
33
33
 
34
- File.open(@feature_filename, 'w') { |file| file.write(@testsuite.target!) }
34
+ basename = File.basename(feature.file)[0...-File.extname(feature.file).length]
35
+ feature_filename = File.join(@reportdir, "TEST-#{basename}.xml")
36
+ File.open(feature_filename, 'w') { |file| file.write(@testsuite.target!) }
35
37
  end
36
38
 
37
39
  def visit_feature_name(name)
38
40
  lines = name.split(/\r?\n/)
39
41
  @feature_name = lines[0].sub(/Feature\:/, '').strip
40
- @feature_filename = convert_to_file_name(@feature_name)
41
42
  end
42
43
 
43
44
  def visit_scenario_name(keyword, name, file_colon_line, source_indent)
@@ -65,10 +66,6 @@ module Cucumber
65
66
 
66
67
  private
67
68
 
68
- def convert_to_file_name(feature_name)
69
- File.join(@reportdir, "TEST-" + feature_name.gsub(/[^\w_\.]/, '_') + ".xml")
70
- end
71
-
72
69
  def format_exception(exception)
73
70
  (["#{exception.message} (#{exception.class})"] + exception.backtrace).join("\n")
74
71
  end
@@ -48,10 +48,8 @@ module Cucumber
48
48
  end
49
49
 
50
50
  def visit_comment_line(comment_line)
51
- unless comment_line.blank?
52
- @io.puts(comment_line.indent(@indent))
53
- @io.flush
54
- end
51
+ @io.puts(comment_line.indent(@indent))
52
+ @io.flush
55
53
  end
56
54
 
57
55
  def visit_tags(tags)
@@ -17,7 +17,7 @@ module Cucumber
17
17
  super
18
18
  end
19
19
 
20
- def visit_step_name(keyword, step_match, status, source_indent, background)
20
+ def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
21
21
  duration = Time.now - @step_duration
22
22
  super
23
23
 
@@ -3,36 +3,4 @@ require 'cucumber/platform'
3
3
  require 'cucumber/ast'
4
4
  require 'cucumber/parser/treetop_ext'
5
5
  require 'cucumber/parser/table'
6
-
7
- module Cucumber
8
- # Classes in this module parse feature files and translate the parse tree
9
- # (concrete syntax tree) into an abstract syntax tree (AST) using
10
- # <a href="http://martinfowler.com/dslwip/EmbeddedTranslation.html">Embedded translation</a>.
11
- #
12
- # The AST is built by the various <tt>#build</tt> methods in the parse tree.
13
- #
14
- # The AST classes are defined in the Cucumber::Ast module.
15
- module Parser
16
- def self.load_parser(keywords)
17
- Loader.new(keywords)
18
- end
19
-
20
- class Loader
21
- def initialize(keywords)
22
- @keywords = keywords
23
- i18n_tt = File.expand_path(File.dirname(__FILE__) + '/parser/i18n.tt')
24
- template = File.open(i18n_tt, Cucumber.file_mode('r')).read
25
- erb = ERB.new(template)
26
- grammar = erb.result(binding)
27
- Treetop.load_from_string(grammar)
28
- require 'cucumber/parser/feature'
29
- end
30
-
31
- def keywords(key, raw=false)
32
- return @keywords[key] if raw
33
- values = @keywords[key].split('|')
34
- values.map{|value| "'#{value}'"}.join(" / ")
35
- end
36
- end
37
- end
38
- end
6
+ require 'cucumber/parser/feature'
@@ -10,17 +10,13 @@ module Cucumber
10
10
  include Treetop::Runtime
11
11
 
12
12
  def root
13
- @root || :feature
13
+ @root || :feature_sub
14
14
  end
15
15
 
16
- include I18n
17
-
18
- include Table
19
-
20
- module Feature0
16
+ module FeatureSub0
21
17
  end
22
18
 
23
- module Feature1
19
+ module FeatureSub1
24
20
  def white
25
21
  elements[0]
26
22
  end
@@ -55,7 +51,7 @@ module Cucumber
55
51
 
56
52
  end
57
53
 
58
- module Feature2
54
+ module FeatureSub2
59
55
  def has_tags?(tag_names)
60
56
  tags.has_tags?(tag_names)
61
57
  end
@@ -74,10 +70,10 @@ module Cucumber
74
70
  end
75
71
  end
76
72
 
77
- def _nt_feature
73
+ def _nt_feature_sub
78
74
  start_index = index
79
- if node_cache[:feature].has_key?(index)
80
- cached = node_cache[:feature][index]
75
+ if node_cache[:feature_sub].has_key?(index)
76
+ cached = node_cache[:feature_sub][index]
81
77
  @index = cached.interval.end if cached
82
78
  return cached
83
79
  end
@@ -139,7 +135,7 @@ module Cucumber
139
135
  end
140
136
  if s7.last
141
137
  r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
142
- r7.extend(Feature0)
138
+ r7.extend(FeatureSub0)
143
139
  else
144
140
  self.index = i7
145
141
  r7 = nil
@@ -181,14 +177,14 @@ module Cucumber
181
177
  end
182
178
  if s0.last
183
179
  r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
184
- r0.extend(Feature1)
185
- r0.extend(Feature2)
180
+ r0.extend(FeatureSub1)
181
+ r0.extend(FeatureSub2)
186
182
  else
187
183
  self.index = i0
188
184
  r0 = nil
189
185
  end
190
186
 
191
- node_cache[:feature][start_index] = r0
187
+ node_cache[:feature_sub][start_index] = r0
192
188
 
193
189
  return r0
194
190
  end
@@ -1346,7 +1342,7 @@ module Cucumber
1346
1342
 
1347
1343
  module LinesToKeyword2
1348
1344
  def build
1349
- self.text_value.split("\n").map{|s| s.strip }.join("\n")
1345
+ self.text_value.split("\n").map{|s| s.strip}.join("\n")
1350
1346
  end
1351
1347
  end
1352
1348
 
@@ -7,10 +7,8 @@ module Cucumber
7
7
  # Treetop will then generate the parser in-memory. When you're happy, just generate
8
8
  # the rb file with tt feature.tt
9
9
  grammar Feature
10
- include I18n
11
- include Table
12
10
 
13
- rule feature
11
+ rule feature_sub
14
12
  white
15
13
  comment
16
14
  white
@@ -1,35 +1,42 @@
1
1
  module Cucumber
2
2
  module Parser
3
- grammar I18n
3
+ module I18n
4
+ grammar <%= keywords('grammar_name', true) %>
5
+ include Feature
6
+ include Table
4
7
 
5
- rule background_keyword
6
- (<%= keywords('background') %>) ':'
7
- end
8
+ rule feature
9
+ feature_sub
10
+ end
8
11
 
9
- rule scenario_keyword
10
- (<%= keywords('scenario') %>) ':'
11
- end
12
+ rule background_keyword
13
+ (<%= keywords('background') %>) ':'
14
+ end
12
15
 
13
- rule scenario_outline_keyword
14
- (<%= keywords('scenario_outline') %>) ':'
15
- end
16
+ rule scenario_keyword
17
+ (<%= keywords('scenario') %>) ':'
18
+ end
16
19
 
17
- rule step_keyword
18
- (<%= keywords('given') %>) /
19
- (<%= keywords('when') %>) /
20
- (<%= keywords('then') %>) /
21
- (<%= keywords('and') %>) /
22
- (<%= keywords('but') %>)
23
- end
20
+ rule scenario_outline_keyword
21
+ (<%= keywords('scenario_outline') %>) ':'
22
+ end
24
23
 
25
- rule keyword_space
26
- <%= keywords('space_after_keyword', true) ? 'space+' : 'space*' %>
27
- end
24
+ rule step_keyword
25
+ (<%= keywords('given') %>) /
26
+ (<%= keywords('when') %>) /
27
+ (<%= keywords('then') %>) /
28
+ (<%= keywords('and') %>) /
29
+ (<%= keywords('but') %>)
30
+ end
28
31
 
29
- rule examples_keyword
30
- (<%= keywords('examples') %>) ':'?
31
- end
32
+ rule keyword_space
33
+ <%= keywords('space_after_keyword', true) ? 'space+' : 'space*' %>
34
+ end
32
35
 
36
+ rule examples_keyword
37
+ (<%= keywords('examples') %>) ':'?
38
+ end
39
+ end
33
40
  end
34
41
  end
35
42
  end