bryanl-gherkin 2.11.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. data/.gitattributes +2 -0
  2. data/.mailmap +2 -0
  3. data/.rbenv-gemsets +1 -0
  4. data/.rspec +1 -0
  5. data/.rvmrc +1 -0
  6. data/.travis.yml +16 -0
  7. data/.yardopts +5 -0
  8. data/Gemfile +5 -0
  9. data/History.md +788 -0
  10. data/LICENSE +20 -0
  11. data/README.md +272 -0
  12. data/Rakefile +26 -0
  13. data/build_native_gems.sh +7 -0
  14. data/cucumber.yml +4 -0
  15. data/examples/parse_and_output_json.rb +19 -0
  16. data/features/.cucumber/stepdefs.json +244 -0
  17. data/features/escaped_pipes.feature +8 -0
  18. data/features/feature_parser.feature +237 -0
  19. data/features/json_formatter.feature +498 -0
  20. data/features/json_parser.feature +331 -0
  21. data/features/native_lexer.feature +19 -0
  22. data/features/parser_with_native_lexer.feature +205 -0
  23. data/features/pretty_formatter.feature +16 -0
  24. data/features/step_definitions/eyeball_steps.rb +3 -0
  25. data/features/step_definitions/gherkin_steps.rb +29 -0
  26. data/features/step_definitions/json_formatter_steps.rb +30 -0
  27. data/features/step_definitions/json_parser_steps.rb +20 -0
  28. data/features/step_definitions/pretty_formatter_steps.rb +85 -0
  29. data/features/steps_parser.feature +46 -0
  30. data/features/support/env.rb +42 -0
  31. data/gherkin.gemspec +77 -0
  32. data/install_mingw_os_x.sh +7 -0
  33. data/js/.npmignore +1 -0
  34. data/js/lib/gherkin/lexer/.npmignore +0 -0
  35. data/lib/gherkin.rb +2 -0
  36. data/lib/gherkin/c_lexer.rb +17 -0
  37. data/lib/gherkin/formatter/ansi_escapes.rb +97 -0
  38. data/lib/gherkin/formatter/argument.rb +16 -0
  39. data/lib/gherkin/formatter/escaping.rb +15 -0
  40. data/lib/gherkin/formatter/filter_formatter.rb +146 -0
  41. data/lib/gherkin/formatter/hashable.rb +19 -0
  42. data/lib/gherkin/formatter/json_formatter.rb +122 -0
  43. data/lib/gherkin/formatter/line_filter.rb +26 -0
  44. data/lib/gherkin/formatter/model.rb +281 -0
  45. data/lib/gherkin/formatter/pretty_formatter.rb +244 -0
  46. data/lib/gherkin/formatter/regexp_filter.rb +21 -0
  47. data/lib/gherkin/formatter/step_printer.rb +21 -0
  48. data/lib/gherkin/formatter/tag_count_formatter.rb +47 -0
  49. data/lib/gherkin/formatter/tag_filter.rb +19 -0
  50. data/lib/gherkin/i18n.rb +180 -0
  51. data/lib/gherkin/i18n.yml +613 -0
  52. data/lib/gherkin/js_lexer.rb +20 -0
  53. data/lib/gherkin/json_parser.rb +177 -0
  54. data/lib/gherkin/lexer/i18n_lexer.rb +46 -0
  55. data/lib/gherkin/listener/event.rb +45 -0
  56. data/lib/gherkin/listener/formatter_listener.rb +143 -0
  57. data/lib/gherkin/native.rb +7 -0
  58. data/lib/gherkin/native/java.rb +72 -0
  59. data/lib/gherkin/native/null.rb +5 -0
  60. data/lib/gherkin/native/therubyracer.rb +39 -0
  61. data/lib/gherkin/parser/meta.txt +5 -0
  62. data/lib/gherkin/parser/parser.rb +164 -0
  63. data/lib/gherkin/parser/root.txt +11 -0
  64. data/lib/gherkin/parser/steps.txt +4 -0
  65. data/lib/gherkin/rb_lexer.rb +8 -0
  66. data/lib/gherkin/rb_lexer/README.rdoc +8 -0
  67. data/lib/gherkin/rb_lexer/ar.rb +1165 -0
  68. data/lib/gherkin/rb_lexer/bg.rb +1377 -0
  69. data/lib/gherkin/rb_lexer/bm.rb +1081 -0
  70. data/lib/gherkin/rb_lexer/ca.rb +1305 -0
  71. data/lib/gherkin/rb_lexer/cs.rb +1157 -0
  72. data/lib/gherkin/rb_lexer/cy_gb.rb +1027 -0
  73. data/lib/gherkin/rb_lexer/da.rb +1043 -0
  74. data/lib/gherkin/rb_lexer/de.rb +1151 -0
  75. data/lib/gherkin/rb_lexer/en.rb +1151 -0
  76. data/lib/gherkin/rb_lexer/en_au.rb +971 -0
  77. data/lib/gherkin/rb_lexer/en_lol.rb +929 -0
  78. data/lib/gherkin/rb_lexer/en_pirate.rb +1205 -0
  79. data/lib/gherkin/rb_lexer/en_scouse.rb +1357 -0
  80. data/lib/gherkin/rb_lexer/en_tx.rb +1011 -0
  81. data/lib/gherkin/rb_lexer/eo.rb +990 -0
  82. data/lib/gherkin/rb_lexer/es.rb +1135 -0
  83. data/lib/gherkin/rb_lexer/et.rb +985 -0
  84. data/lib/gherkin/rb_lexer/fi.rb +964 -0
  85. data/lib/gherkin/rb_lexer/fr.rb +1223 -0
  86. data/lib/gherkin/rb_lexer/he.rb +1113 -0
  87. data/lib/gherkin/rb_lexer/hr.rb +1061 -0
  88. data/lib/gherkin/rb_lexer/hu.rb +1113 -0
  89. data/lib/gherkin/rb_lexer/id.rb +958 -0
  90. data/lib/gherkin/rb_lexer/is.rb +1115 -0
  91. data/lib/gherkin/rb_lexer/it.rb +1081 -0
  92. data/lib/gherkin/rb_lexer/ja.rb +1413 -0
  93. data/lib/gherkin/rb_lexer/ko.rb +1097 -0
  94. data/lib/gherkin/rb_lexer/lt.rb +1040 -0
  95. data/lib/gherkin/rb_lexer/lu.rb +1127 -0
  96. data/lib/gherkin/rb_lexer/lv.rb +1161 -0
  97. data/lib/gherkin/rb_lexer/nl.rb +1110 -0
  98. data/lib/gherkin/rb_lexer/no.rb +1055 -0
  99. data/lib/gherkin/rb_lexer/pl.rb +1452 -0
  100. data/lib/gherkin/rb_lexer/pt.rb +1425 -0
  101. data/lib/gherkin/rb_lexer/ro.rb +1159 -0
  102. data/lib/gherkin/rb_lexer/ru.rb +1749 -0
  103. data/lib/gherkin/rb_lexer/sk.rb +1041 -0
  104. data/lib/gherkin/rb_lexer/sr_cyrl.rb +1798 -0
  105. data/lib/gherkin/rb_lexer/sr_latn.rb +1289 -0
  106. data/lib/gherkin/rb_lexer/sv.rb +1065 -0
  107. data/lib/gherkin/rb_lexer/tr.rb +1087 -0
  108. data/lib/gherkin/rb_lexer/uk.rb +1641 -0
  109. data/lib/gherkin/rb_lexer/uz.rb +1371 -0
  110. data/lib/gherkin/rb_lexer/vi.rb +1193 -0
  111. data/lib/gherkin/rb_lexer/zh_cn.rb +1053 -0
  112. data/lib/gherkin/rb_lexer/zh_tw.rb +1047 -0
  113. data/lib/gherkin/rubify.rb +24 -0
  114. data/lib/gherkin/tag_expression.rb +62 -0
  115. data/ragel/lexer.c.rl.erb +454 -0
  116. data/ragel/lexer.java.rl.erb +219 -0
  117. data/ragel/lexer.js.rl.erb +227 -0
  118. data/ragel/lexer.rb.rl.erb +174 -0
  119. data/ragel/lexer_common.rl.erb +50 -0
  120. data/spec/gherkin/c_lexer_spec.rb +22 -0
  121. data/spec/gherkin/fixtures/1.feature +8 -0
  122. data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
  123. data/spec/gherkin/fixtures/complex.feature +45 -0
  124. data/spec/gherkin/fixtures/complex.json +139 -0
  125. data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
  126. data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
  127. data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
  128. data/spec/gherkin/fixtures/examples_with_only_header.feature +14 -0
  129. data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
  130. data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
  131. data/spec/gherkin/fixtures/i18n_fr2.feature +8 -0
  132. data/spec/gherkin/fixtures/i18n_no.feature +7 -0
  133. data/spec/gherkin/fixtures/i18n_pt1.feature +44 -0
  134. data/spec/gherkin/fixtures/i18n_pt2.feature +4 -0
  135. data/spec/gherkin/fixtures/i18n_pt3.feature +4 -0
  136. data/spec/gherkin/fixtures/i18n_pt4.feature +4 -0
  137. data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
  138. data/spec/gherkin/fixtures/issue_145.feature +22 -0
  139. data/spec/gherkin/fixtures/scenario_outline_with_tags.feature +13 -0
  140. data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
  141. data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
  142. data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
  143. data/spec/gherkin/fixtures/with_bom.feature +3 -0
  144. data/spec/gherkin/formatter/ansi_escapes_spec.rb +32 -0
  145. data/spec/gherkin/formatter/filter_formatter_spec.rb +204 -0
  146. data/spec/gherkin/formatter/json_formatter_spec.rb +92 -0
  147. data/spec/gherkin/formatter/model_spec.rb +28 -0
  148. data/spec/gherkin/formatter/pretty_formatter_spec.rb +177 -0
  149. data/spec/gherkin/formatter/spaces.feature +9 -0
  150. data/spec/gherkin/formatter/step_printer_spec.rb +55 -0
  151. data/spec/gherkin/formatter/tabs.feature +9 -0
  152. data/spec/gherkin/formatter/tag_count_formatter_spec.rb +30 -0
  153. data/spec/gherkin/i18n_spec.rb +241 -0
  154. data/spec/gherkin/java_lexer_spec.rb +20 -0
  155. data/spec/gherkin/js_lexer_spec.rb +23 -0
  156. data/spec/gherkin/json_parser_spec.rb +176 -0
  157. data/spec/gherkin/lexer/i18n_lexer_spec.rb +43 -0
  158. data/spec/gherkin/output_stream_string_io.rb +20 -0
  159. data/spec/gherkin/parser/parser_spec.rb +16 -0
  160. data/spec/gherkin/rb_lexer_spec.rb +20 -0
  161. data/spec/gherkin/sexp_recorder.rb +59 -0
  162. data/spec/gherkin/shared/bom_group.rb +20 -0
  163. data/spec/gherkin/shared/doc_string_group.rb +163 -0
  164. data/spec/gherkin/shared/lexer_group.rb +591 -0
  165. data/spec/gherkin/shared/row_group.rb +125 -0
  166. data/spec/gherkin/shared/tags_group.rb +54 -0
  167. data/spec/gherkin/tag_expression_spec.rb +142 -0
  168. data/spec/spec_helper.rb +75 -0
  169. data/tasks/bench.rake +184 -0
  170. data/tasks/bench/feature_builder.rb +49 -0
  171. data/tasks/bench/null_listener.rb +4 -0
  172. data/tasks/compile.rake +120 -0
  173. data/tasks/cucumber.rake +22 -0
  174. data/tasks/gems.rake +31 -0
  175. data/tasks/ikvm.rake +124 -0
  176. data/tasks/ragel_task.rb +100 -0
  177. data/tasks/release.rake +49 -0
  178. data/tasks/rspec.rake +8 -0
  179. data/tasks/yard.rake +7 -0
  180. data/tasks/yard/default/layout/html/bubble_32x32.png +0 -0
  181. data/tasks/yard/default/layout/html/bubble_48x48.png +0 -0
  182. data/tasks/yard/default/layout/html/footer.erb +5 -0
  183. data/tasks/yard/default/layout/html/index.erb +1 -0
  184. data/tasks/yard/default/layout/html/layout.erb +25 -0
  185. data/tasks/yard/default/layout/html/logo.erb +1 -0
  186. data/tasks/yard/default/layout/html/setup.rb +4 -0
  187. metadata +473 -0
@@ -0,0 +1,16 @@
1
+ require 'gherkin/native'
2
+ require 'gherkin/formatter/hashable'
3
+
4
+ module Gherkin
5
+ module Formatter
6
+ class Argument < Hashable
7
+ native_impl('gherkin')
8
+ attr_reader :offset, :val
9
+
10
+ # Creates a new Argument that starts at character offset +offset+ with value +val+
11
+ def initialize(offset, val)
12
+ @offset, @val = offset, val
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module Gherkin
2
+ module Formatter
3
+ module Escaping
4
+ # Escapes a pipes and backslashes:
5
+ #
6
+ # * | becomes \|
7
+ # * \ becomes \\
8
+ #
9
+ # This is used in the pretty formatter.
10
+ def escape_cell(s)
11
+ s.gsub(/\\(?!\|)/, "\\\\\\\\").gsub(/\n/, "\\n").gsub(/\|/, "\\|")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,146 @@
1
+ require 'gherkin/tag_expression'
2
+ require 'gherkin/formatter/regexp_filter'
3
+ require 'gherkin/formatter/line_filter'
4
+ require 'gherkin/formatter/tag_filter'
5
+ require 'gherkin/formatter/model'
6
+ require 'gherkin/native'
7
+
8
+ module Gherkin
9
+ module Formatter
10
+ class FilterFormatter
11
+ native_impl('gherkin')
12
+
13
+ def initialize(formatter, filters)
14
+ @formatter = formatter
15
+ @filter = detect_filter(filters)
16
+
17
+ @feature_tags = []
18
+ @feature_element_tags = []
19
+ @examples_tags = []
20
+
21
+ @feature_events = []
22
+ @background_events = []
23
+ @feature_element_events = []
24
+ @examples_events = []
25
+ end
26
+
27
+ def uri(uri)
28
+ @formatter.uri(uri)
29
+ end
30
+
31
+ def feature(feature)
32
+ @feature_tags = feature.tags
33
+ @feature_name = feature.name
34
+ @feature_events = [feature]
35
+ end
36
+
37
+ def background(background)
38
+ @feature_element_name = background.name
39
+ @feature_element_range = background.line_range
40
+ @background_events = [background]
41
+ end
42
+
43
+ def scenario(scenario)
44
+ replay!
45
+ @feature_element_tags = scenario.tags
46
+ @feature_element_name = scenario.name
47
+ @feature_element_range = scenario.line_range
48
+ @feature_element_events = [scenario]
49
+ end
50
+
51
+ def scenario_outline(scenario_outline)
52
+ replay!
53
+ @feature_element_tags = scenario_outline.tags
54
+ @feature_element_name = scenario_outline.name
55
+ @feature_element_range = scenario_outline.line_range
56
+ @feature_element_events = [scenario_outline]
57
+ end
58
+
59
+ def examples(examples)
60
+ replay!
61
+ @examples_tags = examples.tags
62
+ @examples_name = examples.name
63
+
64
+ table_body_range = case(examples.rows.length)
65
+ when 0 then examples.line_range.last..examples.line_range.last
66
+ when 1 then examples.rows[0].line..examples.rows[0].line
67
+ else examples.rows[1].line..examples.rows[-1].line
68
+ end
69
+
70
+ @examples_range = examples.line_range.first..table_body_range.last
71
+ if(@filter.eval([], [], [table_body_range]))
72
+ examples.rows = @filter.filter_table_body_rows(examples.rows)
73
+ end
74
+ @examples_events = [examples]
75
+ end
76
+
77
+ def step(step)
78
+ if @feature_element_events.any?
79
+ @feature_element_events << step
80
+ else
81
+ @background_events << step
82
+ end
83
+
84
+ @feature_element_range = @feature_element_range.first..step.line_range.last
85
+ end
86
+
87
+ def eof
88
+ replay!
89
+ @formatter.eof
90
+ end
91
+
92
+ def done
93
+ @formatter.done
94
+ end
95
+
96
+ private
97
+
98
+ def detect_filter(filters)
99
+ raise "Inconsistent filters: #{filters.inspect}. Only one type [line,name,tag] can be used at once." if filters.map{|filter| filter.class}.uniq.length > 1
100
+ case(filters[0])
101
+ when Fixnum
102
+ LineFilter.new(filters)
103
+ when Regexp
104
+ RegexpFilter.new(filters)
105
+ when String
106
+ TagFilter.new(filters)
107
+ end
108
+ end
109
+
110
+ def replay!
111
+ feature_element_ok = @filter.eval(
112
+ (@feature_tags + @feature_element_tags),
113
+ [@feature_name, @feature_element_name].compact,
114
+ [@feature_element_range].compact
115
+ )
116
+ examples_ok = @filter.eval(
117
+ (@feature_tags + @feature_element_tags + @examples_tags),
118
+ [@feature_name, @feature_element_name, @examples_name].compact,
119
+ [@feature_element_range, @examples_range].compact
120
+ )
121
+
122
+ if feature_element_ok || examples_ok
123
+ replay_events!(@feature_events)
124
+ replay_events!(@background_events)
125
+ replay_events!(@feature_element_events)
126
+
127
+ if examples_ok
128
+ replay_events!(@examples_events)
129
+ end
130
+ end
131
+
132
+ @examples_events.clear
133
+ @examples_tags.clear
134
+ @examples_name = nil
135
+ @examples_range = nil
136
+ end
137
+
138
+ def replay_events!(events)
139
+ events.each do |event|
140
+ event.replay(@formatter)
141
+ end
142
+ events.clear
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,19 @@
1
+ module Gherkin
2
+ module Formatter
3
+ class Hashable
4
+ def to_hash
5
+ instance_variables.inject({}) do |hash, ivar|
6
+ value = instance_variable_get(ivar)
7
+ value = value.to_hash if value.respond_to?(:to_hash)
8
+ if Array === value
9
+ value = value.map do |e|
10
+ e.respond_to?(:to_hash) ? e.to_hash : e
11
+ end
12
+ end
13
+ hash[ivar[1..-1]] = value unless [[], nil].index(value)
14
+ hash
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,122 @@
1
+ require 'json'
2
+ require 'gherkin/formatter/model'
3
+ require 'gherkin/native'
4
+ require 'base64'
5
+
6
+ module Gherkin
7
+ module Formatter
8
+ # This class doesn't really generate JSON - instead it populates an Array that can easily
9
+ # be turned into JSON.
10
+ class JSONFormatter
11
+ native_impl('gherkin')
12
+
13
+ include Base64
14
+
15
+ def initialize(io)
16
+ raise "Must be writeable" unless io.respond_to?(:write)
17
+ @io = io
18
+ @feature_hashes = []
19
+ @current_step_or_hook = nil
20
+ end
21
+
22
+ def done
23
+ @io.write(@feature_hashes.to_json)
24
+ end
25
+
26
+ def uri(uri)
27
+ @uri = uri
28
+ end
29
+
30
+ def feature(feature)
31
+ @feature_hash = feature.to_hash
32
+ @feature_hash['uri'] = @uri
33
+ @feature_hashes << @feature_hash
34
+ end
35
+
36
+ def background(background)
37
+ feature_elements << background.to_hash
38
+ end
39
+
40
+ def scenario(scenario)
41
+ feature_elements << scenario.to_hash
42
+ end
43
+
44
+ def scenario_outline(scenario_outline)
45
+ feature_elements << scenario_outline.to_hash
46
+ end
47
+
48
+ def examples(examples)
49
+ all_examples << examples.to_hash
50
+ end
51
+
52
+ def step(step)
53
+ @current_step_or_hook = step.to_hash
54
+ steps << @current_step_or_hook
55
+ end
56
+
57
+ def match(match)
58
+ @current_step_or_hook['match'] = match.to_hash
59
+ end
60
+
61
+ def result(result)
62
+ @current_step_or_hook['result'] = result.to_hash
63
+ end
64
+
65
+ def before(match, result)
66
+ add_hook(match, result, "before")
67
+ end
68
+
69
+ def after(match, result)
70
+ add_hook(match, result, "after")
71
+ end
72
+
73
+ def embedding(mime_type, data)
74
+ embeddings << {'mime_type' => mime_type, 'data' => encode64s(data)}
75
+ end
76
+
77
+ def write(text)
78
+ output << text
79
+ end
80
+
81
+ def eof
82
+ end
83
+
84
+ private
85
+
86
+ def add_hook(match, result, hook)
87
+ hooks = feature_element[hook] ||= []
88
+ hooks << {'match' => match.to_hash, 'result' => result.to_hash}
89
+ end
90
+
91
+ def feature_elements
92
+ @feature_hash['elements'] ||= []
93
+ end
94
+
95
+ def feature_element
96
+ feature_elements[-1]
97
+ end
98
+
99
+ def all_examples
100
+ feature_element['examples'] ||= []
101
+ end
102
+
103
+ def steps
104
+ feature_element['steps'] ||= []
105
+ end
106
+
107
+ def embeddings
108
+ @current_step_or_hook['embeddings'] ||= []
109
+ end
110
+
111
+ def output
112
+ @current_step_or_hook['output'] ||= []
113
+ end
114
+
115
+ def encode64s(data)
116
+ # Strip newlines
117
+ Base64.encode64(data).gsub(/\n/, '')
118
+ end
119
+ end
120
+ end
121
+ end
122
+
@@ -0,0 +1,26 @@
1
+ module Gherkin
2
+ module Formatter
3
+ class LineFilter
4
+ def initialize(lines)
5
+ @lines = lines
6
+ end
7
+
8
+ def eval(tags, names, ranges)
9
+ ranges.detect do |range|
10
+ @lines.detect do |line|
11
+ range.include?(line)
12
+ end
13
+ end
14
+ end
15
+
16
+ def filter_table_body_rows(rows)
17
+ body = rows.to_a[1..-1].select do |row|
18
+ @lines.detect do |line|
19
+ row.line == line
20
+ end
21
+ end
22
+ [rows[0]] + body
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,281 @@
1
+ require 'gherkin/native'
2
+ require 'gherkin/formatter/hashable'
3
+
4
+ module Gherkin
5
+ module Formatter
6
+ module Model
7
+ class BasicStatement < Hashable
8
+ attr_reader :comments, :keyword, :name, :line
9
+
10
+ def initialize(comments, keyword, name, line)
11
+ @comments, @keyword, @name, @line = comments, keyword, name, line
12
+ end
13
+
14
+ def line_range
15
+ first = @comments.any? ? @comments[0].line : first_non_comment_line
16
+ first..line
17
+ end
18
+
19
+ def first_non_comment_line
20
+ @line
21
+ end
22
+ end
23
+
24
+ class DescribedStatement < BasicStatement
25
+ attr_reader :description
26
+
27
+ def initialize(comments, keyword, name, description, line)
28
+ super(comments, keyword, name, line)
29
+ @description = description
30
+ end
31
+ end
32
+
33
+ class TagStatement < DescribedStatement
34
+ attr_reader :tags, :id
35
+
36
+ def initialize(comments, tags, keyword, name, description, line, id)
37
+ super(comments, keyword, name, description, line)
38
+ @tags = tags
39
+ @id = id
40
+ end
41
+
42
+ def first_non_comment_line
43
+ @tags.any? ? @tags[0].line : @line
44
+ end
45
+ end
46
+
47
+ class Feature < TagStatement
48
+ native_impl('gherkin')
49
+
50
+ def replay(formatter)
51
+ formatter.feature(self)
52
+ end
53
+ end
54
+
55
+ class Background < DescribedStatement
56
+ native_impl('gherkin')
57
+
58
+ def initialize(comments, keyword, name, description, line)
59
+ super(comments, keyword, name, description, line)
60
+ @type = "background"
61
+ end
62
+
63
+ def replay(formatter)
64
+ formatter.background(self)
65
+ end
66
+ end
67
+
68
+ class Scenario < TagStatement
69
+ native_impl('gherkin')
70
+
71
+ def initialize(comments, tags, keyword, name, description, line, id)
72
+ super(comments, tags, keyword, name, description, line, id)
73
+ @type = "scenario"
74
+ end
75
+
76
+ def replay(formatter)
77
+ formatter.scenario(self)
78
+ end
79
+ end
80
+
81
+ class ScenarioOutline < TagStatement
82
+ native_impl('gherkin')
83
+
84
+ def initialize(comments, tags, keyword, name, description, line, id)
85
+ super(comments, tags, keyword, name, description, line, id)
86
+ @type = "scenario_outline"
87
+ end
88
+
89
+ def replay(formatter)
90
+ formatter.scenario_outline(self)
91
+ end
92
+ end
93
+
94
+ class Examples < TagStatement
95
+ native_impl('gherkin')
96
+
97
+ attr_accessor :rows # needs to remain mutable for filters
98
+
99
+ def initialize(comments, tags, keyword, name, description, line, id, rows)
100
+ super(comments, tags, keyword, name, description, line, id)
101
+ @rows = rows
102
+ end
103
+
104
+ def replay(formatter)
105
+ formatter.examples(self)
106
+ end
107
+
108
+ class Builder
109
+ def initialize(*args)
110
+ @args = *args
111
+ @rows = nil
112
+ end
113
+
114
+ def row(comments, cells, line, id)
115
+ @rows ||= []
116
+ @rows << ExamplesTableRow.new(comments, cells, line, id)
117
+ end
118
+
119
+ def replay(formatter)
120
+ build.replay(formatter)
121
+ end
122
+
123
+ def build
124
+ Examples.new(*(@args << @rows))
125
+ end
126
+ end
127
+ end
128
+
129
+ class Step < BasicStatement
130
+ native_impl('gherkin')
131
+
132
+ attr_reader :rows, :doc_string
133
+
134
+ def initialize(comments, keyword, name, line, rows, doc_string)
135
+ super(comments, keyword, name, line)
136
+ @rows, @doc_string = rows, doc_string
137
+ end
138
+
139
+ def line_range
140
+ range = super
141
+ if(rows)
142
+ range = range.first..rows[-1].line
143
+ elsif(doc_string)
144
+ range = range.first..doc_string.line_range.last
145
+ end
146
+ range
147
+ end
148
+
149
+ def replay(formatter)
150
+ formatter.step(self)
151
+ end
152
+
153
+ def outline_args
154
+ offset = 0
155
+ name.scan(/<[^<]*>/).map do |val|
156
+ offset = name.index(val, offset)
157
+ Argument.new(offset, val)
158
+ end
159
+ end
160
+
161
+ class Builder
162
+ def initialize(*args)
163
+ @args = *args
164
+ @rows = nil
165
+ @doc_string = nil
166
+ end
167
+
168
+ def row(comments, cells, line, id)
169
+ @rows ||= []
170
+ @rows << DataTableRow.new(comments, cells, line)
171
+ end
172
+
173
+ def doc_string(string, content_type, line)
174
+ @doc_string = Formatter::Model::DocString.new(string, content_type, line)
175
+ end
176
+
177
+ def replay(formatter)
178
+ build.replay(formatter)
179
+ end
180
+
181
+ def build
182
+ Step.new(*(@args << @rows << @doc_string))
183
+ end
184
+ end
185
+ end
186
+
187
+ class Comment < Hashable
188
+ native_impl('gherkin')
189
+
190
+ attr_reader :value, :line
191
+
192
+ def initialize(value, line)
193
+ @value, @line = value, line
194
+ end
195
+ end
196
+
197
+ class Tag < Hashable
198
+ native_impl('gherkin')
199
+
200
+ attr_reader :name, :line
201
+
202
+ def initialize(name, line)
203
+ @name, @line = name, line
204
+ end
205
+
206
+ def eql?(tag)
207
+ @name.eql?(tag.name)
208
+ end
209
+
210
+ def hash
211
+ @name.hash
212
+ end
213
+ end
214
+
215
+ class DocString < Hashable
216
+ native_impl('gherkin')
217
+
218
+ attr_reader :value, :content_type, :line
219
+
220
+ def initialize(value, content_type, line)
221
+ @value, @content_type, @line = value, content_type, line
222
+ end
223
+
224
+ def line_range
225
+ line_count = value.split(/\r?\n/).length
226
+ line..(line+line_count+1)
227
+ end
228
+ end
229
+
230
+ class Row < Hashable
231
+ attr_reader :comments, :cells, :line
232
+
233
+ def initialize(comments, cells, line)
234
+ @comments, @cells, @line = comments, cells, line
235
+ end
236
+ end
237
+
238
+ class DataTableRow < Row
239
+ native_impl('gherkin')
240
+ end
241
+
242
+ class ExamplesTableRow < Row
243
+ native_impl('gherkin')
244
+ attr_reader :id
245
+
246
+ def initialize(comments, cells, line, id)
247
+ super(comments, cells, line)
248
+ @id = id
249
+ end
250
+ end
251
+
252
+ class Match < Hashable
253
+ native_impl('gherkin')
254
+
255
+ attr_reader :arguments, :location
256
+
257
+ def initialize(arguments, location)
258
+ @arguments, @location = arguments, location
259
+ end
260
+
261
+ def replay(formatter)
262
+ formatter.match(self)
263
+ end
264
+ end
265
+
266
+ class Result < Hashable
267
+ native_impl('gherkin')
268
+
269
+ attr_reader :status, :duration, :error_message
270
+
271
+ def initialize(status, duration, error_message)
272
+ @status, @duration, @error_message = status, duration, error_message
273
+ end
274
+
275
+ def replay(formatter)
276
+ formatter.result(self)
277
+ end
278
+ end
279
+ end
280
+ end
281
+ end