cucumber-core 3.2.1 → 4.0.0
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +52 -0
- data/lib/cucumber/core/compiler.rb +37 -145
- data/lib/cucumber/core/events.rb +1 -4
- data/lib/cucumber/core/gherkin/parser.rb +14 -22
- data/lib/cucumber/core/report/summary.rb +1 -23
- data/lib/cucumber/core/test/action.rb +2 -2
- data/lib/cucumber/core/test/around_hook.rb +4 -0
- data/lib/cucumber/core/test/case.rb +15 -121
- data/lib/cucumber/core/{ast → test}/data_table.rb +6 -8
- data/lib/cucumber/core/{ast → test}/doc_string.rb +5 -9
- data/lib/cucumber/core/{ast → test}/empty_multiline_argument.rb +1 -2
- data/lib/cucumber/core/test/filters/locations_filter.rb +2 -2
- data/lib/cucumber/core/{ast → test}/location.rb +10 -17
- data/lib/cucumber/core/test/runner.rb +5 -3
- data/lib/cucumber/core/test/step.rb +20 -36
- data/lib/cucumber/core/{ast → test}/tag.rb +1 -1
- data/lib/cucumber/core/version.rb +1 -1
- metadata +12 -26
- data/lib/cucumber/core/ast.rb +0 -14
- data/lib/cucumber/core/ast/background.rb +0 -41
- data/lib/cucumber/core/ast/comment.rb +0 -28
- data/lib/cucumber/core/ast/describes_itself.rb +0 -21
- data/lib/cucumber/core/ast/empty_background.rb +0 -17
- data/lib/cucumber/core/ast/examples_table.rb +0 -119
- data/lib/cucumber/core/ast/feature.rb +0 -88
- data/lib/cucumber/core/ast/names.rb +0 -25
- data/lib/cucumber/core/ast/outline_step.rb +0 -53
- data/lib/cucumber/core/ast/scenario.rb +0 -42
- data/lib/cucumber/core/ast/scenario_outline.rb +0 -45
- data/lib/cucumber/core/ast/step.rb +0 -83
- data/lib/cucumber/core/gherkin/ast_builder.rb +0 -403
- data/lib/cucumber/core/gherkin/tag_expression.rb +0 -65
@@ -1,83 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'cucumber/core/ast/describes_itself'
|
3
|
-
require 'cucumber/core/ast/location'
|
4
|
-
|
5
|
-
module Cucumber
|
6
|
-
module Core
|
7
|
-
module Ast
|
8
|
-
class Step
|
9
|
-
include HasLocation
|
10
|
-
include DescribesItself
|
11
|
-
|
12
|
-
attr_reader :keyword, :text, :language, :comments, :exception, :multiline_arg
|
13
|
-
|
14
|
-
def initialize(language, location, comments, keyword, text, multiline_arg)
|
15
|
-
@language, @location, @comments, @keyword, @text, @multiline_arg = language, location, comments, keyword, text, multiline_arg
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_s
|
19
|
-
text
|
20
|
-
end
|
21
|
-
|
22
|
-
def backtrace_line
|
23
|
-
"#{location}:in `#{keyword}#{text}'"
|
24
|
-
end
|
25
|
-
|
26
|
-
def actual_keyword(previous_step_keyword = nil)
|
27
|
-
if [language.and_keywords, language.but_keywords].flatten.uniq.include? keyword
|
28
|
-
if previous_step_keyword.nil?
|
29
|
-
language.given_keywords.reject{|kw| kw == '* '}[0]
|
30
|
-
else
|
31
|
-
previous_step_keyword
|
32
|
-
end
|
33
|
-
else
|
34
|
-
keyword
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def original_location
|
39
|
-
location
|
40
|
-
end
|
41
|
-
|
42
|
-
def inspect
|
43
|
-
keyword_and_text = [keyword, text].join(": ")
|
44
|
-
%{#<#{self.class} "#{keyword_and_text}" (#{location})>}
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def children
|
51
|
-
[@multiline_arg]
|
52
|
-
end
|
53
|
-
|
54
|
-
def description_for_visitors
|
55
|
-
:step
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class ExpandedOutlineStep < Step
|
60
|
-
|
61
|
-
def initialize(outline_step, language, location, comments, keyword, text, multiline_arg)
|
62
|
-
@outline_step, @language, @location, @comments, @keyword, @text, @multiline_arg = outline_step, language, location, comments, keyword, text, multiline_arg
|
63
|
-
end
|
64
|
-
|
65
|
-
def all_locations
|
66
|
-
@outline_step.all_locations
|
67
|
-
end
|
68
|
-
|
69
|
-
def original_location
|
70
|
-
@outline_step.location
|
71
|
-
end
|
72
|
-
|
73
|
-
alias :step_backtrace_line :backtrace_line
|
74
|
-
|
75
|
-
def backtrace_line
|
76
|
-
"#{step_backtrace_line}\n" +
|
77
|
-
"#{@outline_step.location}:in `#{@outline_step.keyword}#{@outline_step.text}'"
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
@@ -1,403 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'cucumber/core/ast'
|
3
|
-
require 'cucumber/core/platform'
|
4
|
-
|
5
|
-
module Cucumber
|
6
|
-
module Core
|
7
|
-
module Gherkin
|
8
|
-
# Builds an AST of a feature by listening to events from the
|
9
|
-
# Gherkin parser.
|
10
|
-
class AstBuilder
|
11
|
-
|
12
|
-
def initialize(uri)
|
13
|
-
@uri = uri
|
14
|
-
end
|
15
|
-
|
16
|
-
def feature(attributes)
|
17
|
-
DocumentBuilder.new(file, attributes).feature
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def file
|
23
|
-
@uri
|
24
|
-
end
|
25
|
-
|
26
|
-
class Builder
|
27
|
-
attr_reader :file, :attributes, :comments, :line
|
28
|
-
private :file, :attributes, :comments, :line
|
29
|
-
|
30
|
-
def initialize(file, attributes)
|
31
|
-
@file = file
|
32
|
-
@attributes = rubify_keys(attributes.dup)
|
33
|
-
@comments = []
|
34
|
-
@line = @attributes[:location][:line]
|
35
|
-
end
|
36
|
-
|
37
|
-
def handle_comments(comments)
|
38
|
-
remaining_comments = []
|
39
|
-
comments.each do |comment|
|
40
|
-
if line > comment.location.line
|
41
|
-
@comments << comment
|
42
|
-
else
|
43
|
-
remaining_comments << comment
|
44
|
-
end
|
45
|
-
end
|
46
|
-
children.each { |child| remaining_comments = child.handle_comments(remaining_comments) }
|
47
|
-
remaining_comments
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def keyword
|
53
|
-
attributes[:keyword]
|
54
|
-
end
|
55
|
-
|
56
|
-
def name
|
57
|
-
attributes[:name]
|
58
|
-
end
|
59
|
-
|
60
|
-
def description
|
61
|
-
attributes[:description] ||= ""
|
62
|
-
end
|
63
|
-
|
64
|
-
def tags
|
65
|
-
attributes[:tags].map do |tag|
|
66
|
-
Ast::Tag.new(
|
67
|
-
Ast::Location.new(file, tag[:location][:line]),
|
68
|
-
tag[:name])
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def location
|
73
|
-
Ast::Location.new(file, attributes[:location][:line])
|
74
|
-
end
|
75
|
-
|
76
|
-
def children
|
77
|
-
[]
|
78
|
-
end
|
79
|
-
|
80
|
-
def rubify_keys(hash)
|
81
|
-
hash.keys.each do |key|
|
82
|
-
if key.downcase != key
|
83
|
-
hash[underscore(key).to_sym] = hash.delete(key)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
return hash
|
87
|
-
end
|
88
|
-
|
89
|
-
def underscore(string)
|
90
|
-
string.to_s.gsub(/::/, '/').
|
91
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
92
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
93
|
-
tr("-", "_").
|
94
|
-
downcase
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
class DocumentBuilder < Builder
|
99
|
-
def initialize(file, attributes)
|
100
|
-
@file = file
|
101
|
-
@attributes = rubify_keys(attributes.dup)
|
102
|
-
end
|
103
|
-
|
104
|
-
def feature
|
105
|
-
return Ast::NullFeature.new unless attributes[:feature]
|
106
|
-
feature_builder = FeatureBuilder.new(file, attributes[:feature])
|
107
|
-
feature_builder.handle_comments(all_comments)
|
108
|
-
feature_builder.result
|
109
|
-
end
|
110
|
-
|
111
|
-
def all_comments
|
112
|
-
attributes[:comments].map do |comment|
|
113
|
-
Ast::Comment.new(
|
114
|
-
Ast::Location.new(file, comment[:location][:line]),
|
115
|
-
comment[:text]
|
116
|
-
)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
class FeatureBuilder < Builder
|
122
|
-
attr_reader :language, :feature_element_builders
|
123
|
-
|
124
|
-
def initialize(*)
|
125
|
-
super
|
126
|
-
@language = Ast::LanguageDelegator.new(attributes[:language], ::Gherkin::Dialect.for(attributes[:language]))
|
127
|
-
@feature_element_builders = attributes[:children].map do |child|
|
128
|
-
case child[:type]
|
129
|
-
when :Background
|
130
|
-
BackgroundBuilder.new(file, child)
|
131
|
-
when :Scenario
|
132
|
-
ScenarioBuilder.new(file, child)
|
133
|
-
else
|
134
|
-
ScenarioOutlineBuilder.new(file, child)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def result
|
140
|
-
Ast::Feature.new(
|
141
|
-
language,
|
142
|
-
location,
|
143
|
-
comments,
|
144
|
-
tags,
|
145
|
-
keyword,
|
146
|
-
name,
|
147
|
-
description,
|
148
|
-
feature_elements
|
149
|
-
)
|
150
|
-
end
|
151
|
-
|
152
|
-
private
|
153
|
-
|
154
|
-
def feature_elements
|
155
|
-
feature_element_builders.map { |builder| builder.result(language) }
|
156
|
-
end
|
157
|
-
|
158
|
-
def children
|
159
|
-
feature_element_builders
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
class BackgroundBuilder < Builder
|
164
|
-
attr_reader :step_builders
|
165
|
-
|
166
|
-
def initialize(*)
|
167
|
-
super
|
168
|
-
@step_builders = attributes[:steps].map { |step| StepBuilder.new(file, step) }
|
169
|
-
end
|
170
|
-
|
171
|
-
def result(language)
|
172
|
-
Ast::Background.new(
|
173
|
-
location,
|
174
|
-
comments,
|
175
|
-
keyword,
|
176
|
-
name,
|
177
|
-
description,
|
178
|
-
steps(language)
|
179
|
-
)
|
180
|
-
end
|
181
|
-
|
182
|
-
def steps(language)
|
183
|
-
step_builders.map { |builder| builder.result(language) }
|
184
|
-
end
|
185
|
-
|
186
|
-
def children
|
187
|
-
step_builders
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
class ScenarioBuilder < Builder
|
192
|
-
attr_reader :step_builders
|
193
|
-
|
194
|
-
def initialize(*)
|
195
|
-
super
|
196
|
-
@step_builders = attributes[:steps].map { |step| StepBuilder.new(file, step) }
|
197
|
-
end
|
198
|
-
|
199
|
-
def result(language)
|
200
|
-
Ast::Scenario.new(
|
201
|
-
location,
|
202
|
-
comments,
|
203
|
-
tags,
|
204
|
-
keyword,
|
205
|
-
name,
|
206
|
-
description,
|
207
|
-
steps(language)
|
208
|
-
)
|
209
|
-
end
|
210
|
-
|
211
|
-
def steps(language)
|
212
|
-
step_builders.map { |builder| builder.result(language) }
|
213
|
-
end
|
214
|
-
|
215
|
-
def children
|
216
|
-
step_builders
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
class StepBuilder < Builder
|
221
|
-
attr_reader :multiline_argument_builder
|
222
|
-
|
223
|
-
def initialize(*)
|
224
|
-
super
|
225
|
-
@multiline_argument_builder = attributes[:argument] ? argument_builder(attributes[:argument]) : nil
|
226
|
-
end
|
227
|
-
|
228
|
-
def result(language)
|
229
|
-
Ast::Step.new(
|
230
|
-
language,
|
231
|
-
location,
|
232
|
-
comments,
|
233
|
-
keyword,
|
234
|
-
attributes[:text],
|
235
|
-
multiline_argument
|
236
|
-
)
|
237
|
-
end
|
238
|
-
|
239
|
-
def multiline_argument
|
240
|
-
return Ast::EmptyMultilineArgument.new unless multiline_argument_builder
|
241
|
-
multiline_argument_builder.result
|
242
|
-
end
|
243
|
-
|
244
|
-
def children
|
245
|
-
return [] unless multiline_argument_builder
|
246
|
-
[multiline_argument_builder]
|
247
|
-
end
|
248
|
-
|
249
|
-
private
|
250
|
-
|
251
|
-
def argument_builder(attributes)
|
252
|
-
attributes[:type] == :DataTable ? DataTableBuilder.new(file, attributes) : DocStringBuilder.new(file, attributes)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
class OutlineStepBuilder < StepBuilder
|
257
|
-
def result(language)
|
258
|
-
Ast::OutlineStep.new(
|
259
|
-
language,
|
260
|
-
location,
|
261
|
-
comments,
|
262
|
-
keyword,
|
263
|
-
attributes[:text],
|
264
|
-
multiline_argument
|
265
|
-
)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
class ScenarioOutlineBuilder < Builder
|
270
|
-
attr_reader :step_builders, :example_builders
|
271
|
-
|
272
|
-
def initialize(*)
|
273
|
-
super
|
274
|
-
@step_builders = attributes[:steps].map { |step| OutlineStepBuilder.new(file, step) }
|
275
|
-
@example_builders = attributes[:examples] ? attributes[:examples].map { |example| ExamplesTableBuilder.new(file, example) } : []
|
276
|
-
end
|
277
|
-
|
278
|
-
def result(language)
|
279
|
-
Ast::ScenarioOutline.new(
|
280
|
-
location,
|
281
|
-
comments,
|
282
|
-
tags,
|
283
|
-
keyword,
|
284
|
-
name,
|
285
|
-
description,
|
286
|
-
steps(language),
|
287
|
-
examples(language)
|
288
|
-
)
|
289
|
-
end
|
290
|
-
|
291
|
-
def steps(language)
|
292
|
-
step_builders.map { |builder| builder.result(language) }
|
293
|
-
end
|
294
|
-
|
295
|
-
def examples(language)
|
296
|
-
example_builders.map { |builder| builder.result(language) }
|
297
|
-
end
|
298
|
-
|
299
|
-
def children
|
300
|
-
step_builders + example_builders
|
301
|
-
end
|
302
|
-
end
|
303
|
-
|
304
|
-
class ExamplesTableBuilder < Builder
|
305
|
-
attr_reader :header_builder, :example_rows_builders
|
306
|
-
|
307
|
-
def initialize(*)
|
308
|
-
super
|
309
|
-
@header_builder = attributes[:table_header] ? HeaderBuilder.new(file, attributes[:table_header]) : NullHeaderBuilder.new
|
310
|
-
@example_rows_builders = attributes[:table_body] ? attributes[:table_body].map { |row_attributes| ExampleRowBuilder.new(file, row_attributes) } : []
|
311
|
-
end
|
312
|
-
|
313
|
-
def result(language)
|
314
|
-
Ast::Examples.new(
|
315
|
-
location,
|
316
|
-
comments,
|
317
|
-
tags,
|
318
|
-
keyword,
|
319
|
-
name,
|
320
|
-
description,
|
321
|
-
header,
|
322
|
-
example_rows(language)
|
323
|
-
)
|
324
|
-
end
|
325
|
-
|
326
|
-
private
|
327
|
-
|
328
|
-
def header
|
329
|
-
@header = header_builder.result
|
330
|
-
end
|
331
|
-
|
332
|
-
def example_rows(language)
|
333
|
-
example_rows_builders.each.with_index.map { |builder, index| builder.result(language, header, index) }
|
334
|
-
end
|
335
|
-
|
336
|
-
class HeaderBuilder < Builder
|
337
|
-
def result
|
338
|
-
cells = attributes[:cells].map { |c| c[:value] }
|
339
|
-
Ast::ExamplesTable::Header.new(cells, location, comments)
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
343
|
-
class NullHeaderBuilder < Builder
|
344
|
-
def initialize
|
345
|
-
@line = -1 # this inhibits Builder#handle_comments to put any comments in this object.
|
346
|
-
end
|
347
|
-
|
348
|
-
def result
|
349
|
-
nil
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
|
-
def children
|
354
|
-
[header_builder] + example_rows_builders
|
355
|
-
end
|
356
|
-
|
357
|
-
class ExampleRowBuilder < Builder
|
358
|
-
def result(language, header, index)
|
359
|
-
cells = attributes[:cells].map { |c| c[:value] }
|
360
|
-
header.build_row(cells, index + 1, location, language, comments)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
class DataTableBuilder < Builder
|
366
|
-
def result
|
367
|
-
Ast::DataTable.new(
|
368
|
-
rows,
|
369
|
-
location
|
370
|
-
)
|
371
|
-
end
|
372
|
-
|
373
|
-
def rows
|
374
|
-
attributes[:rows] = attributes[:rows].map { |r| r[:cells].map { |c| c[:value] } }
|
375
|
-
end
|
376
|
-
|
377
|
-
def location
|
378
|
-
first_line = attributes[:location][:line]
|
379
|
-
last_line = first_line + attributes[:rows].length - 1
|
380
|
-
Ast::Location.new(file, first_line..last_line)
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
class DocStringBuilder < Builder
|
385
|
-
def result
|
386
|
-
Ast::DocString.new(
|
387
|
-
attributes[:content],
|
388
|
-
attributes[:content_type],
|
389
|
-
doc_string_location
|
390
|
-
)
|
391
|
-
end
|
392
|
-
|
393
|
-
def doc_string_location
|
394
|
-
start_line = attributes[:location][:line]
|
395
|
-
end_line = start_line + attributes[:content].each_line.to_a.length + 1
|
396
|
-
Ast::Location.new(file, start_line..end_line)
|
397
|
-
end
|
398
|
-
end
|
399
|
-
|
400
|
-
end
|
401
|
-
end
|
402
|
-
end
|
403
|
-
end
|