macros4cuke 0.3.42 → 0.4.00
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 +8 -8
- data/.rubocop.yml +20 -3
- data/CHANGELOG.md +15 -1
- data/examples/i18n/fr/features/step_definitions/use_macro_steps.rb +1 -1
- data/features/demo06.feature +75 -75
- data/features/demo07.feature +15 -0
- data/features/support/env.rb +6 -0
- data/features/support/macro_support.rb +2 -2
- data/lib/macro_steps.rb +19 -2
- data/lib/macros4cuke/coll-walker-factory.rb +119 -0
- data/lib/macros4cuke/constants.rb +1 -1
- data/lib/macros4cuke/exceptions.rb +23 -1
- data/lib/macros4cuke/formatter/all-notifications.rb +30 -0
- data/lib/macros4cuke/formatter/to-gherkin.rb +80 -0
- data/lib/macros4cuke/formatter/to-null.rb +86 -0
- data/lib/macros4cuke/formatter/to-trace.rb +100 -0
- data/lib/macros4cuke/formatting-service.rb +74 -0
- data/lib/macros4cuke/macro-collection.rb +3 -3
- data/lib/macros4cuke/macro-step-support.rb +1 -1
- data/lib/macros4cuke/macro-step.rb +10 -26
- data/lib/macros4cuke/templating/engine.rb +74 -29
- data/spec/macros4cuke/coll-walker-factory_spec.rb +269 -0
- data/spec/macros4cuke/formatter/to-gherkin_spec.rb +129 -0
- data/spec/macros4cuke/formatter/to-null_spec.rb +62 -0
- data/spec/macros4cuke/formatter/to-trace_spec.rb +155 -0
- data/spec/macros4cuke/formatting-service_spec.rb +138 -0
- data/spec/macros4cuke/macro-collection_spec.rb +7 -4
- data/spec/macros4cuke/macro-step-support_spec.rb +41 -24
- data/spec/macros4cuke/macro-step_spec.rb +13 -6
- data/spec/macros4cuke/templating/engine_spec.rb +11 -7
- data/spec/macros4cuke/templating/placeholder_spec.rb +1 -1
- data/spec/macros4cuke/templating/section_spec.rb +3 -1
- data/spec/macros4cuke/use-sample-collection.rb +79 -0
- data/spec/spec_helper.rb +3 -0
- metadata +15 -2
|
@@ -23,6 +23,9 @@ class MacroStep
|
|
|
23
23
|
# A template engine that expands the sub-steps upon request.
|
|
24
24
|
attr_reader(:renderer)
|
|
25
25
|
|
|
26
|
+
# The sentence fragment that defines the syntax of the macro-step
|
|
27
|
+
attr_reader(:phrase)
|
|
28
|
+
|
|
26
29
|
# Unique key of the macro as derived from the macro phrase.
|
|
27
30
|
attr_reader(:key)
|
|
28
31
|
|
|
@@ -30,7 +33,7 @@ class MacroStep
|
|
|
30
33
|
attr_reader(:phrase_args)
|
|
31
34
|
|
|
32
35
|
# The list of macro argument names (as appearing in the substeps
|
|
33
|
-
#
|
|
36
|
+
# AND in the macro phrase).
|
|
34
37
|
attr_reader(:args)
|
|
35
38
|
|
|
36
39
|
# Constructor.
|
|
@@ -41,15 +44,12 @@ class MacroStep
|
|
|
41
44
|
# @param useTable [boolean] A flag indicating whether a data table
|
|
42
45
|
# must be used to pass actual values.
|
|
43
46
|
def initialize(aMacroPhrase, theSubsteps, useTable)
|
|
47
|
+
@phrase = aMacroPhrase
|
|
44
48
|
@key = self.class.macro_key(aMacroPhrase, useTable, :definition)
|
|
45
49
|
|
|
46
50
|
# Retrieve the macro arguments embedded in the phrase.
|
|
47
51
|
@phrase_args = scan_arguments(aMacroPhrase, :definition)
|
|
48
|
-
|
|
49
|
-
# Manipulate the substeps source text
|
|
50
|
-
substeps_processed = preprocess(theSubsteps)
|
|
51
|
-
|
|
52
|
-
@renderer = Templating::Engine.new(substeps_processed)
|
|
52
|
+
@renderer = Templating::Engine.new(theSubsteps)
|
|
53
53
|
substeps_vars = renderer.variables
|
|
54
54
|
|
|
55
55
|
|
|
@@ -165,17 +165,15 @@ private
|
|
|
165
165
|
# @param params [Hash] The pairs phrase argument name => value
|
|
166
166
|
def validate_row(a_row, params)
|
|
167
167
|
(a_key, value) = a_row
|
|
168
|
-
|
|
168
|
+
fail(UnknownArgumentError.new(a_key)) unless args.include? a_key
|
|
169
169
|
if (phrase_args.include? a_key) && (params[a_key] != value)
|
|
170
|
-
|
|
170
|
+
fail(AmbiguousArgumentValue.new(a_key, params[a_key], value))
|
|
171
171
|
end
|
|
172
172
|
|
|
173
173
|
return a_row
|
|
174
174
|
end
|
|
175
175
|
|
|
176
176
|
|
|
177
|
-
|
|
178
|
-
|
|
179
177
|
# Retrieve from the macro phrase, all the text between <..> or double quotes.
|
|
180
178
|
# Returns an array. Each of its elements corresponds to quoted text.
|
|
181
179
|
# Example:
|
|
@@ -201,20 +199,6 @@ private
|
|
|
201
199
|
|
|
202
200
|
return args
|
|
203
201
|
end
|
|
204
|
-
|
|
205
|
-
# Return the substeps text after some transformation
|
|
206
|
-
# [theSubstepsSource] The source text of the steps
|
|
207
|
-
# to be expanded upon macro invokation.
|
|
208
|
-
def preprocess(theSubstepsSource)
|
|
209
|
-
# Split text into lines
|
|
210
|
-
lines = theSubstepsSource.split(/\r\n?|\n/)
|
|
211
|
-
|
|
212
|
-
# Reject comment lines. This is necessary because
|
|
213
|
-
# Cucumber::RbSupport::RbWorld#steps complains when it sees a comment.
|
|
214
|
-
processed = lines.reject { |a_line| a_line =~ /\s*#/ }
|
|
215
|
-
|
|
216
|
-
return processed.join("\n")
|
|
217
|
-
end
|
|
218
202
|
|
|
219
203
|
# Check for inconsistencies between the argument names
|
|
220
204
|
# in the phrase and the substeps part.
|
|
@@ -222,7 +206,7 @@ private
|
|
|
222
206
|
# Error when the phrase names an argument that never occurs in the substeps
|
|
223
207
|
thePhraseArgs.each do |phrase_arg|
|
|
224
208
|
unless substepsVars.include? phrase_arg
|
|
225
|
-
|
|
209
|
+
fail(UselessPhraseArgument.new(phrase_arg))
|
|
226
210
|
end
|
|
227
211
|
end
|
|
228
212
|
# Error when a substep has an argument that never appears in the phrase
|
|
@@ -231,7 +215,7 @@ private
|
|
|
231
215
|
substepsVars.each do |substep_arg|
|
|
232
216
|
unless thePhraseArgs.include?(substep_arg) ||
|
|
233
217
|
BuiltinParameters.include?(substep_arg)
|
|
234
|
-
|
|
218
|
+
fail(UnreachableSubstepArgument.new(substep_arg))
|
|
235
219
|
end
|
|
236
220
|
end
|
|
237
221
|
end
|
|
@@ -38,6 +38,34 @@ class StaticText
|
|
|
38
38
|
end # class
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
# Class used internally by the template engine.
|
|
42
|
+
# Represents a comment from a template.
|
|
43
|
+
# A static text is a text that is reproduced verbatim
|
|
44
|
+
# when rendering a template.
|
|
45
|
+
class Comment
|
|
46
|
+
# The comment as extracted from the original template.
|
|
47
|
+
attr_reader(:source)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# @param aSourceText [String] A piece of text extracted
|
|
51
|
+
# from the template that must be rendered verbatim.
|
|
52
|
+
def initialize(aSourceText)
|
|
53
|
+
@source = aSourceText
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
public
|
|
57
|
+
|
|
58
|
+
# Render the comment.
|
|
59
|
+
# Comments are rendered as empty text. This is necessary because
|
|
60
|
+
# Cucumber::RbSupport::RbWorld#steps complains when it sees a comment.
|
|
61
|
+
# This method has the same signature as the {Engine#render} method.
|
|
62
|
+
# @return [String] Empty string ("as is")
|
|
63
|
+
def render(aContextObject, theLocals)
|
|
64
|
+
return ''
|
|
65
|
+
end
|
|
66
|
+
end # class
|
|
67
|
+
|
|
68
|
+
|
|
41
69
|
# Class used internally by the template engine.
|
|
42
70
|
# Represents an end of line that must be rendered as such.
|
|
43
71
|
class EOLine
|
|
@@ -160,7 +188,7 @@ class Section < UnaryElement
|
|
|
160
188
|
# Returns an empty string when no value is assigned to the placeholder.
|
|
161
189
|
def render(aContextObject, theLocals)
|
|
162
190
|
msg = "Method Section.#{__method__} must be implemented in subclass."
|
|
163
|
-
|
|
191
|
+
fail(NotImplementedError, msg)
|
|
164
192
|
end
|
|
165
193
|
|
|
166
194
|
end # class
|
|
@@ -239,6 +267,9 @@ class Engine
|
|
|
239
267
|
# The original text of the template is kept here.
|
|
240
268
|
attr_reader(:source)
|
|
241
269
|
|
|
270
|
+
# The internal representation of the template text
|
|
271
|
+
attr_reader(:representation)
|
|
272
|
+
|
|
242
273
|
# Builds an Engine and compiles the given template text into
|
|
243
274
|
# an internal representation.
|
|
244
275
|
# @param aSourceTemplate [String] The template source text.
|
|
@@ -260,11 +291,19 @@ public
|
|
|
260
291
|
# the passed argument values.
|
|
261
292
|
def render(aContextObject = Object.new, theLocals)
|
|
262
293
|
return '' if @representation.empty?
|
|
263
|
-
|
|
294
|
+
|
|
295
|
+
prev = nil
|
|
264
296
|
result = @representation.each_with_object('') do |element, subResult|
|
|
265
|
-
|
|
297
|
+
# Output compaction rules:
|
|
298
|
+
# -In case of consecutive eol's only one is rendered.
|
|
299
|
+
# -In case of comment followed by one eol, both aren't rendered
|
|
300
|
+
unless element.is_a?(EOLine) &&
|
|
301
|
+
(prev.is_a?(EOLine) || prev.is_a?(Comment))
|
|
302
|
+
subResult << element.render(aContextObject, theLocals)
|
|
303
|
+
end
|
|
304
|
+
prev = element
|
|
266
305
|
end
|
|
267
|
-
|
|
306
|
+
|
|
268
307
|
return result
|
|
269
308
|
end
|
|
270
309
|
|
|
@@ -295,24 +334,28 @@ public
|
|
|
295
334
|
|
|
296
335
|
# Class method. Parse the given line text into a raw representation.
|
|
297
336
|
# @return [Array] Couples of the form:
|
|
298
|
-
# [:static, text] or [:dynamic, tag text]
|
|
337
|
+
# [:static, text], [:comment, text] or [:dynamic, tag text]
|
|
299
338
|
def self.parse(aTextLine)
|
|
300
339
|
scanner = StringScanner.new(aTextLine)
|
|
301
340
|
result = []
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
341
|
+
|
|
342
|
+
if scanner.check(/\s*#/) # Detect comment line
|
|
343
|
+
result << [:comment, aTextLine]
|
|
344
|
+
else
|
|
345
|
+
until scanner.eos?
|
|
346
|
+
# Scan tag at current position...
|
|
347
|
+
tag_literal = scanner.scan(/<(?:[^\\<>]|\\.)*>/)
|
|
348
|
+
unless tag_literal.nil?
|
|
349
|
+
result << [:dynamic, tag_literal.gsub(/^<|>$/, '')]
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# ... or scan plain text at current position
|
|
353
|
+
literal = scanner.scan(/(?:[^\\<>]|\\.)+/)
|
|
354
|
+
result << [:static, literal] unless literal.nil?
|
|
355
|
+
identify_parse_error(aTextLine) if tag_literal.nil? && literal.nil?
|
|
308
356
|
end
|
|
309
|
-
|
|
310
|
-
# ... or scan plain text at current position
|
|
311
|
-
text_literal = scanner.scan(/(?:[^\\<>]|\\.)+/)
|
|
312
|
-
result << [:static, text_literal] unless text_literal.nil?
|
|
313
|
-
identify_parse_error(aTextLine) if tag_literal.nil? && text_literal.nil?
|
|
314
357
|
end
|
|
315
|
-
|
|
358
|
+
|
|
316
359
|
return result
|
|
317
360
|
end
|
|
318
361
|
|
|
@@ -336,11 +379,11 @@ private
|
|
|
336
379
|
when '>' then unbalance -= 1
|
|
337
380
|
end
|
|
338
381
|
|
|
339
|
-
|
|
340
|
-
|
|
382
|
+
fail(StandardError, "Nested opening chevron '<'.") if unbalance > 1
|
|
383
|
+
fail(StandardError, "Missing opening chevron '<'.") if unbalance < 0
|
|
341
384
|
end
|
|
342
385
|
|
|
343
|
-
|
|
386
|
+
fail(StandardError, "Missing closing chevron '>'.") if unbalance == 1
|
|
344
387
|
end
|
|
345
388
|
|
|
346
389
|
|
|
@@ -355,7 +398,7 @@ private
|
|
|
355
398
|
line_items.each do |(kind, text)|
|
|
356
399
|
# A tag text cannot be empty nor blank
|
|
357
400
|
if (kind == :dynamic) && text.strip.empty?
|
|
358
|
-
|
|
401
|
+
fail(EmptyArgumentError.new(line.strip))
|
|
359
402
|
end
|
|
360
403
|
end
|
|
361
404
|
|
|
@@ -390,7 +433,7 @@ private
|
|
|
390
433
|
false
|
|
391
434
|
end
|
|
392
435
|
end
|
|
393
|
-
if line_to_squeeze && !
|
|
436
|
+
if line_to_squeeze && !section_item.nil?
|
|
394
437
|
line_rep = [section_item]
|
|
395
438
|
else
|
|
396
439
|
line_rep_ending(line_rep)
|
|
@@ -398,7 +441,7 @@ private
|
|
|
398
441
|
|
|
399
442
|
return line_rep
|
|
400
443
|
end
|
|
401
|
-
|
|
444
|
+
|
|
402
445
|
|
|
403
446
|
# Apply rule: if last item in line is an end of section marker,
|
|
404
447
|
# then place eoline before that item.
|
|
@@ -418,15 +461,17 @@ private
|
|
|
418
461
|
# Where kind must be one of :static, :dynamic
|
|
419
462
|
def compile_couple(aCouple)
|
|
420
463
|
(kind, text) = aCouple
|
|
421
|
-
|
|
464
|
+
|
|
422
465
|
result = case kind
|
|
423
466
|
when :static then StaticText.new(text)
|
|
467
|
+
when :comment then Comment.new(text)
|
|
424
468
|
when :dynamic then parse_tag(text)
|
|
425
469
|
end
|
|
426
470
|
|
|
427
471
|
return result
|
|
428
472
|
end
|
|
429
|
-
|
|
473
|
+
|
|
474
|
+
|
|
430
475
|
# Parse the contents of a tag entry.
|
|
431
476
|
# @param aText [String] The text that is enclosed between chevrons.
|
|
432
477
|
def parse_tag(aText)
|
|
@@ -437,7 +482,7 @@ private
|
|
|
437
482
|
# Disallow punctuation and delimiter signs in tags.
|
|
438
483
|
matching = DisallowedSigns.match(aText)
|
|
439
484
|
end
|
|
440
|
-
|
|
485
|
+
fail(InvalidCharError.new(aText, matching[0])) if matching
|
|
441
486
|
|
|
442
487
|
result = case aText[0, 1]
|
|
443
488
|
when '?'
|
|
@@ -477,7 +522,7 @@ private
|
|
|
477
522
|
|
|
478
523
|
unless open_sections.empty?
|
|
479
524
|
error_message = "Unterminated section #{open_sections.last}."
|
|
480
|
-
|
|
525
|
+
fail(StandardError, error_message)
|
|
481
526
|
end
|
|
482
527
|
|
|
483
528
|
return compiled
|
|
@@ -490,11 +535,11 @@ private
|
|
|
490
535
|
|
|
491
536
|
if sections.empty?
|
|
492
537
|
msg = 'found while no corresponding section is open.'
|
|
493
|
-
|
|
538
|
+
fail(StandardError, msg_prefix + msg)
|
|
494
539
|
end
|
|
495
540
|
if marker.name != sections.last.name
|
|
496
541
|
msg = "doesn't match current section '#{sections.last.name}'."
|
|
497
|
-
|
|
542
|
+
fail(StandardError, msg_prefix + msg)
|
|
498
543
|
end
|
|
499
544
|
end
|
|
500
545
|
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# File: collection-walker_spec.rb
|
|
2
|
+
|
|
3
|
+
require_relative '../spec_helper'
|
|
4
|
+
|
|
5
|
+
# Load mix-in module for creating a sample collection of macro-steps
|
|
6
|
+
require_relative 'use-sample-collection'
|
|
7
|
+
|
|
8
|
+
# Load the class under test
|
|
9
|
+
require_relative '../../lib/macros4cuke/coll-walker-factory'
|
|
10
|
+
|
|
11
|
+
module Macros4Cuke # Open this namespace to avoid module qualifier prefixes
|
|
12
|
+
|
|
13
|
+
describe CollWalkerFactory do
|
|
14
|
+
include UseSampleCollection # Add convenience methods for sample collection
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
before(:all) do
|
|
18
|
+
# Fill the collection of macro-steps with sample steps
|
|
19
|
+
fill_collection
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
after(:all) do
|
|
23
|
+
# Clear the collection to prevent interference between spec files
|
|
24
|
+
macro_coll.clear
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context 'Initialization:' do
|
|
28
|
+
it 'should be created without parameter' do
|
|
29
|
+
expect { CollWalkerFactory.new }.not_to raise_error
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end # context
|
|
33
|
+
|
|
34
|
+
context 'Provided factory services:' do
|
|
35
|
+
# Default factory instantiation
|
|
36
|
+
subject { CollWalkerFactory.new }
|
|
37
|
+
|
|
38
|
+
it 'should build a walker for the given macro collection' do
|
|
39
|
+
walker = subject.build_walker(macro_coll)
|
|
40
|
+
expect(walker).to be_kind_of(Enumerator)
|
|
41
|
+
end
|
|
42
|
+
end # context
|
|
43
|
+
|
|
44
|
+
context 'Provided walker services:' do
|
|
45
|
+
# Default walker instantiation
|
|
46
|
+
subject do
|
|
47
|
+
factory = CollWalkerFactory.new
|
|
48
|
+
factory.build_walker(macro_coll)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
it 'should notify the start of the visit of the collection' do
|
|
53
|
+
initial_event = subject.next
|
|
54
|
+
expect(initial_event).to eq([:on_collection, 0, macro_coll])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'should notify the visit of a first macro step' do
|
|
58
|
+
1.times { subject.next }
|
|
59
|
+
first_step = subject.next
|
|
60
|
+
step1 = macro_coll.macro_steps.values[0]
|
|
61
|
+
expect(first_step).to eq([:on_step, 1, step1])
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'should notify the visit of the phrase of the first macro step' do
|
|
65
|
+
2.times { subject.next }
|
|
66
|
+
first_phrase = subject.next
|
|
67
|
+
sample_phrase1 = UseSampleCollection::SamplePhrase1
|
|
68
|
+
expect(first_phrase).to eq([:on_phrase, 2, sample_phrase1, true])
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'should notify the visit of the substeps renderer of the first step' do
|
|
72
|
+
3.times { subject.next }
|
|
73
|
+
first_step = macro_coll.macro_steps.values[0]
|
|
74
|
+
first_renderer = subject.next
|
|
75
|
+
expectation = [:on_renderer, 2, first_step.renderer]
|
|
76
|
+
expect(first_renderer).to eq(expectation)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'should notify the visit of the internal representation of substeps' do
|
|
80
|
+
first_step = macro_coll.macro_steps.values[0]
|
|
81
|
+
substep_chunks = first_step.renderer.representation
|
|
82
|
+
4.times { subject.next }
|
|
83
|
+
text_representation = subject.next
|
|
84
|
+
expectation = [:on_source, 3, first_step.renderer.source]
|
|
85
|
+
expect(text_representation).to eq(expectation)
|
|
86
|
+
|
|
87
|
+
first_substep_piece = subject.next
|
|
88
|
+
expectation = [:on_static_text, 3, substep_chunks[0].source]
|
|
89
|
+
expect(first_substep_piece).to eq(expectation)
|
|
90
|
+
|
|
91
|
+
second_substep_piece = subject.next
|
|
92
|
+
expect(second_substep_piece).to eq([:on_eol, 3, nil])
|
|
93
|
+
|
|
94
|
+
third_substep_piece = subject.next
|
|
95
|
+
expectation = [:on_static_text, 3, substep_chunks[2].source]
|
|
96
|
+
expect(third_substep_piece).to eq(expectation)
|
|
97
|
+
|
|
98
|
+
fourth_substep_piece = subject.next
|
|
99
|
+
expect(fourth_substep_piece).to eq([:on_eol, 3, nil])
|
|
100
|
+
|
|
101
|
+
fifth_substep_piece = subject.next
|
|
102
|
+
expectation = [:on_static_text, 3, substep_chunks[4].source]
|
|
103
|
+
expect(fifth_substep_piece).to eq(expectation)
|
|
104
|
+
|
|
105
|
+
sixth_substep_piece = subject.next
|
|
106
|
+
expectation = [:on_placeholder, 3, substep_chunks[5].name]
|
|
107
|
+
expect(sixth_substep_piece).to eq(expectation)
|
|
108
|
+
|
|
109
|
+
seventh_substep_piece = subject.next
|
|
110
|
+
expectation = [:on_static_text, 3, substep_chunks[6].source]
|
|
111
|
+
expect(seventh_substep_piece).to eq(expectation)
|
|
112
|
+
|
|
113
|
+
eighth_substep_piece = subject.next
|
|
114
|
+
expect(eighth_substep_piece).to eq([:on_eol, 3, nil])
|
|
115
|
+
|
|
116
|
+
ninth_substep_piece = subject.next
|
|
117
|
+
expectation = [:on_static_text, 3, substep_chunks[8].source]
|
|
118
|
+
expect(ninth_substep_piece).to eq(expectation)
|
|
119
|
+
|
|
120
|
+
tenth_substep_piece = subject.next
|
|
121
|
+
expectation = [:on_placeholder, 3, substep_chunks[9].name]
|
|
122
|
+
expect(tenth_substep_piece).to eq(expectation)
|
|
123
|
+
|
|
124
|
+
eleventh_substep_piece = subject.next
|
|
125
|
+
expectation = [:on_static_text, 3, substep_chunks[10].source]
|
|
126
|
+
expect(eleventh_substep_piece).to eq(expectation)
|
|
127
|
+
|
|
128
|
+
twelfth_substep_piece = subject.next
|
|
129
|
+
expect(twelfth_substep_piece).to eq([:on_eol, 3, nil])
|
|
130
|
+
|
|
131
|
+
thirtieth_substep_piece = subject.next
|
|
132
|
+
expectation = [:on_static_text, 3, substep_chunks[12].source]
|
|
133
|
+
expect(thirtieth_substep_piece).to eq(expectation)
|
|
134
|
+
|
|
135
|
+
fourteenth_substep_piece = subject.next
|
|
136
|
+
expect(fourteenth_substep_piece).to eq([:on_eol, 3, nil])
|
|
137
|
+
|
|
138
|
+
fifteenth_substep_piece = subject.next
|
|
139
|
+
expect(fifteenth_substep_piece).to eq([:on_renderer_end, 2, nil])
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'should notify the visit of a following macro step' do
|
|
143
|
+
(4 + 15 + 1).times { subject.next }
|
|
144
|
+
end_step = subject.next
|
|
145
|
+
expect(end_step).to eq([:on_step_end, 1, nil])
|
|
146
|
+
a_step = subject.next
|
|
147
|
+
expect(a_step).to eq([:on_step, 1, macro_coll.macro_steps.values[1]])
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'should notify the visit of the phrase of a following macro step' do
|
|
151
|
+
(4 + 16 + 2).times { subject.next }
|
|
152
|
+
phrase = subject.next
|
|
153
|
+
sample_phrase = UseSampleCollection::SamplePhrase2
|
|
154
|
+
expect(phrase).to eq([:on_phrase, 2, sample_phrase, true])
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'should notify the visit of the substeps of a following step' do
|
|
158
|
+
(4 + 16 + 3).times { subject.next }
|
|
159
|
+
a_renderer = subject.next
|
|
160
|
+
second_step = macro_coll.macro_steps.values[1]
|
|
161
|
+
expect(a_renderer).to eq([:on_renderer, 2, second_step.renderer])
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it 'should notify the visit in substeps of following step' do
|
|
165
|
+
second_step = macro_coll.macro_steps.values[1]
|
|
166
|
+
substep_chunks = second_step.renderer.representation.dup
|
|
167
|
+
substep_chunks.map! do |ck|
|
|
168
|
+
if ck.kind_of?(Templating::Section)
|
|
169
|
+
[ck, ck.children, ck].flatten
|
|
170
|
+
else
|
|
171
|
+
ck
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
substep_chunks.flatten!
|
|
175
|
+
|
|
176
|
+
(4 + 16 + 4).times { subject.next }
|
|
177
|
+
substeps_text = subject.next
|
|
178
|
+
expectation = [:on_source, 3, second_step.renderer.source]
|
|
179
|
+
expect(substeps_text).to eq(expectation)
|
|
180
|
+
|
|
181
|
+
first_substep_piece = subject.next
|
|
182
|
+
expectation = [:on_static_text, 3, substep_chunks[0].source]
|
|
183
|
+
expect(first_substep_piece).to eq(expectation)
|
|
184
|
+
|
|
185
|
+
[
|
|
186
|
+
[:on_placeholder, 3, :name], # 0
|
|
187
|
+
[:on_static_text, 3, :source], # 1
|
|
188
|
+
[:on_eol, 3, nil], # 2
|
|
189
|
+
[:on_static_text, 3, :source], # 3
|
|
190
|
+
[:on_placeholder, 3, :name], # 4
|
|
191
|
+
[:on_static_text, 3, :source], # 5
|
|
192
|
+
[:on_eol, 3, nil], # 6
|
|
193
|
+
[:on_static_text, 3, :source], # 7
|
|
194
|
+
[:on_placeholder, 3, :name], # 8
|
|
195
|
+
[:on_static_text, 3, :source], # 9
|
|
196
|
+
[:on_eol, 3, nil], # 10
|
|
197
|
+
[:on_static_text, 3, :source], # 11
|
|
198
|
+
[:on_placeholder, 3, :name], # 12
|
|
199
|
+
[:on_static_text, 3, :source], # 13
|
|
200
|
+
[:on_eol, 3, nil], # 14
|
|
201
|
+
[:on_static_text, 3, :source], # 15
|
|
202
|
+
[:on_placeholder, 3, :name], # 16
|
|
203
|
+
[:on_static_text, 3, :source], # 17
|
|
204
|
+
[:on_eol, 3, nil], # 18
|
|
205
|
+
[:on_static_text, 3, :source], # 19
|
|
206
|
+
[:on_placeholder, 3, :name], # 20
|
|
207
|
+
[:on_static_text, 3, :source], # 21
|
|
208
|
+
[:on_eol, 3, nil], # 22
|
|
209
|
+
[:on_eol, 3, nil], # 23
|
|
210
|
+
[:on_comment, 3, :source], # 24
|
|
211
|
+
[:on_eol, 3, nil], # 25
|
|
212
|
+
[:on_comment, 3, :source], # 26
|
|
213
|
+
[:on_eol, 3, nil], # 27
|
|
214
|
+
[:on_comment, 3, :source], # 28
|
|
215
|
+
[:on_eol, 3, nil], # 29
|
|
216
|
+
[:on_section, 3, :name], # 30
|
|
217
|
+
[:on_static_text, 4, :source], # 31
|
|
218
|
+
[:on_placeholder, 4, :name], # 32
|
|
219
|
+
[:on_static_text, 4, :source], # 33
|
|
220
|
+
[:on_eol, 4, nil], # 34
|
|
221
|
+
[:on_section_end, 3, nil], # 35
|
|
222
|
+
[:on_eol, 3, nil], # 36
|
|
223
|
+
[:on_comment, 3, :source], # 37
|
|
224
|
+
[:on_eol, 3, nil], # 38
|
|
225
|
+
[:on_comment, 3, :source], # 39
|
|
226
|
+
[:on_eol, 3, nil], # 40
|
|
227
|
+
[:on_comment, 3, :source], # 41
|
|
228
|
+
[:on_eol, 3, nil], # 42
|
|
229
|
+
[:on_section, 3, :name], # 43
|
|
230
|
+
[:on_static_text, 4, :source], # 44
|
|
231
|
+
[:on_placeholder, 4, :name], # 45
|
|
232
|
+
[:on_static_text, 4, :source], # 46
|
|
233
|
+
[:on_eol, 4, nil], # 47
|
|
234
|
+
[:on_section_end, 3, nil], # 48
|
|
235
|
+
[:on_static_text, 3, :source], # 49
|
|
236
|
+
[:on_eol, 3, nil], # 50
|
|
237
|
+
[:on_renderer_end, 2, nil], # 51
|
|
238
|
+
[:on_step_end, 1, nil], # 52
|
|
239
|
+
[:on_collection_end, 0, nil] # 53
|
|
240
|
+
].each_with_index do |event, i|
|
|
241
|
+
actual = subject.next
|
|
242
|
+
expect(actual[0]).to eq(event[0])
|
|
243
|
+
expect(actual[1]).to eq(event[1])
|
|
244
|
+
unless event[2].nil?
|
|
245
|
+
expected_obj = substep_chunks[i + 1]
|
|
246
|
+
expect(actual[2]).to eq(expected_obj.send(event[2]))
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
expect { subject.next }.to raise_error(StopIteration)
|
|
250
|
+
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Must be last test script since it pollutes the macro-collection
|
|
254
|
+
it 'should complain when visiting an unsupported node' do
|
|
255
|
+
first_step = macro_coll.macro_steps.values[0]
|
|
256
|
+
first_step.renderer.representation.insert(2, :not_a_valid_element)
|
|
257
|
+
err_type = Macros4Cuke::InternalError
|
|
258
|
+
err_msg = "Don't know how to format a Symbol."
|
|
259
|
+
expect { subject.each { |x| } }.to raise_error(err_type, err_msg)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
end # context
|
|
263
|
+
|
|
264
|
+
end # describe
|
|
265
|
+
|
|
266
|
+
end # module
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# End of file
|