cucumber-core 1.2.0 → 1.3.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 +4 -4
- data/HISTORY.md +10 -2
- data/cucumber-core.gemspec +1 -1
- data/lib/cucumber/core/ast/background.rb +3 -6
- data/lib/cucumber/core/ast/data_table.rb +2 -7
- data/lib/cucumber/core/ast/describes_itself.rb +5 -1
- data/lib/cucumber/core/ast/doc_string.rb +2 -2
- data/lib/cucumber/core/ast/examples_table.rb +3 -3
- data/lib/cucumber/core/ast/feature.rb +14 -5
- data/lib/cucumber/core/ast/location.rb +19 -6
- data/lib/cucumber/core/ast/outline_step.rb +4 -5
- data/lib/cucumber/core/ast/scenario.rb +4 -8
- data/lib/cucumber/core/ast/scenario_outline.rb +4 -10
- data/lib/cucumber/core/ast/step.rb +9 -8
- data/lib/cucumber/core/gherkin/ast_builder.rb +241 -217
- data/lib/cucumber/core/gherkin/parser.rb +16 -16
- data/lib/cucumber/core/gherkin/tag_expression.rb +64 -0
- data/lib/cucumber/core/test/case.rb +2 -2
- data/lib/cucumber/core/test/runner.rb +9 -4
- data/lib/cucumber/core/test/step.rb +19 -0
- data/lib/cucumber/core/version.rb +1 -1
- data/spec/cucumber/core/ast/background_spec.rb +1 -1
- data/spec/cucumber/core/ast/location_spec.rb +45 -0
- data/spec/cucumber/core/ast/outline_step_spec.rb +3 -4
- data/spec/cucumber/core/ast/step_spec.rb +22 -20
- data/spec/cucumber/core/gherkin/parser_spec.rb +36 -7
- data/spec/cucumber/core/test/case_spec.rb +10 -0
- data/spec/cucumber/core/test/filters/locations_filter_spec.rb +40 -3
- data/spec/cucumber/core/test/runner_spec.rb +16 -0
- metadata +7 -6
@@ -1,5 +1,8 @@
|
|
1
|
+
require 'gherkin3/parser'
|
2
|
+
require 'gherkin3/token_scanner'
|
3
|
+
require 'gherkin3/errors'
|
1
4
|
require 'cucumber/core/gherkin/ast_builder'
|
2
|
-
require '
|
5
|
+
require 'cucumber/core/ast'
|
3
6
|
|
4
7
|
module Cucumber
|
5
8
|
module Core
|
@@ -15,13 +18,18 @@ module Cucumber
|
|
15
18
|
end
|
16
19
|
|
17
20
|
def document(document)
|
18
|
-
|
19
|
-
|
21
|
+
parser = ::Gherkin3::Parser.new
|
22
|
+
scanner = ::Gherkin3::TokenScanner.new(document.body)
|
23
|
+
core_builder = AstBuilder.new(document.uri)
|
24
|
+
|
25
|
+
if document.body.strip.empty?
|
26
|
+
return receiver.feature Ast::NullFeature.new
|
27
|
+
end
|
20
28
|
|
21
29
|
begin
|
22
|
-
parser.parse(
|
23
|
-
|
24
|
-
receiver.feature
|
30
|
+
result = parser.parse(scanner)
|
31
|
+
|
32
|
+
receiver.feature core_builder.feature(result)
|
25
33
|
rescue *PARSER_ERRORS => e
|
26
34
|
raise Core::Gherkin::ParseError.new("#{document.uri}: #{e.message}")
|
27
35
|
end
|
@@ -34,16 +42,8 @@ module Cucumber
|
|
34
42
|
|
35
43
|
private
|
36
44
|
|
37
|
-
PARSER_ERRORS =
|
38
|
-
|
39
|
-
::Java::GherkinLexer::LexingError
|
40
|
-
]
|
41
|
-
else
|
42
|
-
[
|
43
|
-
::Gherkin::Lexer::LexingError,
|
44
|
-
::Gherkin::Parser::ParseError,
|
45
|
-
]
|
46
|
-
end
|
45
|
+
PARSER_ERRORS = ::Gherkin3::ParserError
|
46
|
+
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Core
|
3
|
+
module Gherkin
|
4
|
+
class TagExpression
|
5
|
+
|
6
|
+
attr_reader :limits
|
7
|
+
|
8
|
+
def initialize(tag_expressions)
|
9
|
+
@ands = []
|
10
|
+
@limits = {}
|
11
|
+
tag_expressions.each do |expr|
|
12
|
+
add(expr.strip.split(/\s*,\s*/))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def empty?
|
17
|
+
@ands.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def evaluate(tags)
|
21
|
+
return true if @ands.flatten.empty?
|
22
|
+
vars = Hash[*tags.map{|tag| [tag.name, true]}.flatten]
|
23
|
+
raise "No vars" if vars.nil? # Useless statement to prevent ruby warnings about unused var
|
24
|
+
!!Kernel.eval(ruby_expression)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def add(tags_with_negation_and_limits)
|
30
|
+
negatives, positives = tags_with_negation_and_limits.partition{|tag| tag =~ /^~/}
|
31
|
+
@ands << (store_and_extract_limits(negatives, true) + store_and_extract_limits(positives, false))
|
32
|
+
end
|
33
|
+
|
34
|
+
def store_and_extract_limits(tags_with_negation_and_limits, negated)
|
35
|
+
tags_with_negation = []
|
36
|
+
tags_with_negation_and_limits.each do |tag_with_negation_and_limit|
|
37
|
+
tag_with_negation, limit = tag_with_negation_and_limit.split(':')
|
38
|
+
tags_with_negation << tag_with_negation
|
39
|
+
if limit
|
40
|
+
tag_without_negation = negated ? tag_with_negation[1..-1] : tag_with_negation
|
41
|
+
if @limits[tag_without_negation] && @limits[tag_without_negation] != limit.to_i
|
42
|
+
raise "Inconsistent tag limits for #{tag_without_negation}: #{@limits[tag_without_negation]} and #{limit.to_i}"
|
43
|
+
end
|
44
|
+
@limits[tag_without_negation] = limit.to_i
|
45
|
+
end
|
46
|
+
end
|
47
|
+
tags_with_negation
|
48
|
+
end
|
49
|
+
|
50
|
+
def ruby_expression
|
51
|
+
"(" + @ands.map do |ors|
|
52
|
+
ors.map do |tag|
|
53
|
+
if tag =~ /^~(.*)/
|
54
|
+
"!vars['#{$1}']"
|
55
|
+
else
|
56
|
+
"vars['#{tag}']"
|
57
|
+
end
|
58
|
+
end.join("||")
|
59
|
+
end.join(")&&(") + ")"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'cucumber/core/test/result'
|
2
|
+
require 'cucumber/core/gherkin/tag_expression'
|
2
3
|
|
3
4
|
module Cucumber
|
4
5
|
module Core
|
@@ -55,9 +56,8 @@ module Cucumber
|
|
55
56
|
@tags ||= TagCollector.new(self).result
|
56
57
|
end
|
57
58
|
|
58
|
-
require 'gherkin/tag_expression'
|
59
59
|
def match_tags?(*expressions)
|
60
|
-
::Gherkin::TagExpression.new(expressions.flatten).evaluate(tags
|
60
|
+
Cucumber::Core::Gherkin::TagExpression.new(expressions.flatten).evaluate(tags)
|
61
61
|
end
|
62
62
|
|
63
63
|
def match_name?(name_regexp)
|
@@ -4,8 +4,8 @@ module Cucumber
|
|
4
4
|
module Core
|
5
5
|
module Test
|
6
6
|
class Runner
|
7
|
-
attr_reader :report, :running_test_case
|
8
|
-
private :report, :running_test_case
|
7
|
+
attr_reader :report, :running_test_case, :running_test_step
|
8
|
+
private :report, :running_test_case, :running_test_step
|
9
9
|
|
10
10
|
def initialize(report)
|
11
11
|
@report = report
|
@@ -13,6 +13,7 @@ module Cucumber
|
|
13
13
|
|
14
14
|
def test_case(test_case, &descend)
|
15
15
|
@running_test_case = RunningTestCase.new
|
16
|
+
@running_test_step = nil
|
16
17
|
report.before_test_case(test_case)
|
17
18
|
descend.call(self)
|
18
19
|
report.after_test_case(test_case, running_test_case.result)
|
@@ -20,14 +21,18 @@ module Cucumber
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def test_step(test_step)
|
24
|
+
@running_test_step = test_step
|
23
25
|
report.before_test_step test_step
|
24
26
|
step_result = running_test_case.execute(test_step)
|
25
27
|
report.after_test_step test_step, step_result
|
28
|
+
@running_test_step = nil
|
26
29
|
self
|
27
30
|
end
|
28
31
|
|
29
32
|
def around_hook(hook, &continue)
|
30
|
-
running_test_case.execute(hook, &continue)
|
33
|
+
result = running_test_case.execute(hook, &continue)
|
34
|
+
report.after_test_step running_test_step, result if running_test_step
|
35
|
+
@running_test_step = nil
|
31
36
|
self
|
32
37
|
end
|
33
38
|
|
@@ -98,7 +103,7 @@ module Cucumber
|
|
98
103
|
def execute(test_step, monitor, &continue)
|
99
104
|
result = test_step.execute(monitor.result, &continue)
|
100
105
|
result = result.with_message(%(Undefined step: "#{test_step.name}")) if result.undefined?
|
101
|
-
result = result.with_appended_backtrace(test_step.source.last) if test_step.
|
106
|
+
result = result.with_appended_backtrace(test_step.source.last) if IsStepVisitor.new(test_step).step?
|
102
107
|
result.describe_to(monitor, result)
|
103
108
|
end
|
104
109
|
|
@@ -57,6 +57,25 @@ module Cucumber
|
|
57
57
|
end
|
58
58
|
|
59
59
|
end
|
60
|
+
|
61
|
+
class IsStepVisitor
|
62
|
+
def initialize(test_step)
|
63
|
+
@is_step = false
|
64
|
+
test_step.describe_to(self)
|
65
|
+
end
|
66
|
+
|
67
|
+
def step?
|
68
|
+
@is_step
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_step(*)
|
72
|
+
@is_step = true
|
73
|
+
end
|
74
|
+
|
75
|
+
def method_missing(*)
|
76
|
+
self
|
77
|
+
end
|
78
|
+
end
|
60
79
|
end
|
61
80
|
end
|
62
81
|
end
|
@@ -3,7 +3,7 @@ module Cucumber::Core::Ast
|
|
3
3
|
describe Background do
|
4
4
|
it "has a useful inspect" do
|
5
5
|
location = Location.new("features/a_feature.feature", 3)
|
6
|
-
background = Background.new(
|
6
|
+
background = Background.new(location, double, "Background", "the name", double, [])
|
7
7
|
expect(background.inspect).to eq(%{#<Cucumber::Core::Ast::Background "Background: the name" (#{location})>})
|
8
8
|
end
|
9
9
|
end
|
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'cucumber/core/ast/location'
|
2
2
|
|
3
3
|
module Cucumber::Core::Ast
|
4
|
+
RSpec::Matchers.define :be_included_in do |expected|
|
5
|
+
match do |actual|
|
6
|
+
expected.include? actual
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
4
10
|
describe Location do
|
5
11
|
let(:line) { 12 }
|
6
12
|
let(:file) { "foo.feature" }
|
@@ -115,6 +121,45 @@ module Cucumber::Core::Ast
|
|
115
121
|
end
|
116
122
|
end
|
117
123
|
end
|
124
|
+
|
125
|
+
describe "created from source location" do
|
126
|
+
context "when the location is in the tree below pwd" do
|
127
|
+
it "create a relative path from pwd" do
|
128
|
+
expect( Location.from_source_location(Dir.pwd + "/path/file.rb", 1).file ).to eq "path/file.rb"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when the location is in an installed gem" do
|
133
|
+
it "create a relative path from the gem directory" do
|
134
|
+
expect( Location.from_source_location("/path/gems/gem-name/path/file.rb", 1).file ).to eq "gem-name/path/file.rb"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "when the location is neither below pwd nor in an installed gem" do
|
139
|
+
it "use the absolute path to the file" do
|
140
|
+
expect( Location.from_source_location("/path/file.rb", 1).file ).to eq "/path/file.rb"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "created from file-colon-line" do
|
146
|
+
it "handles also Windows paths" do
|
147
|
+
expect( Location.from_file_colon_line("c:\path\file.rb:123").file ).to eq "c:\path\file.rb"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "created of caller" do
|
152
|
+
it "use the location of the caller" do
|
153
|
+
expect( Location.of_caller.to_s ).to be_included_in caller[0]
|
154
|
+
end
|
155
|
+
|
156
|
+
context "when specifying additional caller depth"do
|
157
|
+
it "use the location of the n:th caller" do
|
158
|
+
expect( Location.of_caller(1).to_s ).to be_included_in caller[1]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
118
163
|
end
|
119
164
|
end
|
120
165
|
|
@@ -8,8 +8,7 @@ module Cucumber
|
|
8
8
|
module Core
|
9
9
|
module Ast
|
10
10
|
describe OutlineStep do
|
11
|
-
let(:outline_step) { OutlineStep.new(
|
12
|
-
let(:node) { double }
|
11
|
+
let(:outline_step) { OutlineStep.new(language, location, comments, keyword, name, multiline_arg) }
|
13
12
|
let(:language) { double }
|
14
13
|
let(:location) { double }
|
15
14
|
let(:comments) { double }
|
@@ -46,7 +45,7 @@ module Cucumber
|
|
46
45
|
end
|
47
46
|
|
48
47
|
context "when the step has a DataTable" do
|
49
|
-
let(:outline_step) { OutlineStep.new(
|
48
|
+
let(:outline_step) { OutlineStep.new(language, location, comments, keyword, name, table) }
|
50
49
|
let(:name) { "anything" }
|
51
50
|
let(:table) { DataTable.new([['x', 'y'],['a', 'a <arg>']], Location.new('foo.feature', 23)) }
|
52
51
|
|
@@ -64,7 +63,7 @@ module Cucumber
|
|
64
63
|
|
65
64
|
context "when the step has a DocString" do
|
66
65
|
let(:location) { double }
|
67
|
-
let(:outline_step) { OutlineStep.new(
|
66
|
+
let(:outline_step) { OutlineStep.new(language, location, comments, keyword, name, doc_string) }
|
68
67
|
let(:doc_string) { DocString.new('a <arg> that needs replacing', '', location) }
|
69
68
|
let(:name) { 'anything' }
|
70
69
|
|
@@ -1,14 +1,16 @@
|
|
1
1
|
require 'cucumber/core/ast/step'
|
2
|
-
require '
|
2
|
+
require 'cucumber/core/ast/outline_step'
|
3
|
+
require 'cucumber/core/ast/empty_multiline_argument'
|
4
|
+
require 'gherkin3/dialect'
|
3
5
|
|
4
6
|
module Cucumber
|
5
7
|
module Core
|
6
8
|
module Ast
|
7
9
|
describe Step do
|
8
10
|
let(:step) do
|
9
|
-
|
11
|
+
language, location, comments, keyword, name = *double
|
10
12
|
multiline_arg = EmptyMultilineArgument.new
|
11
|
-
Step.new(
|
13
|
+
Step.new(language, location, comments, keyword, name, multiline_arg)
|
12
14
|
end
|
13
15
|
|
14
16
|
describe "describing itself" do
|
@@ -27,7 +29,7 @@ module Cucumber
|
|
27
29
|
end
|
28
30
|
|
29
31
|
context "with a multiline argument" do
|
30
|
-
let(:step) { Step.new(double, double, double, double, double,
|
32
|
+
let(:step) { Step.new(double, double, double, double, double, multiline_arg) }
|
31
33
|
let(:multiline_arg) { double }
|
32
34
|
|
33
35
|
it "tells its multiline argument to describe itself" do
|
@@ -46,7 +48,7 @@ module Cucumber
|
|
46
48
|
end
|
47
49
|
|
48
50
|
describe "backtrace line" do
|
49
|
-
let(:step) { Step.new(double,
|
51
|
+
let(:step) { Step.new(double, "path/file.feature:10", double, "Given ", "this step passes", double) }
|
50
52
|
|
51
53
|
it "knows how to form the backtrace line" do
|
52
54
|
expect( step.backtrace_line ).to eq("path/file.feature:10:in `Given this step passes'")
|
@@ -55,12 +57,12 @@ module Cucumber
|
|
55
57
|
end
|
56
58
|
|
57
59
|
describe "actual keyword" do
|
58
|
-
let(:language) { ::
|
60
|
+
let(:language) { ::Gherkin3::Dialect.for('en') }
|
59
61
|
|
60
62
|
context "for keywords 'given', 'when' and 'then'" do
|
61
|
-
let(:given_step) { Step.new(
|
62
|
-
let(:when_step) { Step.new(
|
63
|
-
let(:then_step) { Step.new(
|
63
|
+
let(:given_step) { Step.new(language, double, double, "Given ", double, double) }
|
64
|
+
let(:when_step) { Step.new(language, double, double, "When ", double, double) }
|
65
|
+
let(:then_step) { Step.new(language, double, double, "Then ", double, double) }
|
64
66
|
|
65
67
|
it "returns the keyword itself" do
|
66
68
|
expect( given_step.actual_keyword(nil) ).to eq("Given ")
|
@@ -70,9 +72,9 @@ module Cucumber
|
|
70
72
|
end
|
71
73
|
|
72
74
|
context "for keyword 'and', 'but', and '*'" do
|
73
|
-
let(:and_step) { Step.new(
|
74
|
-
let(:but_step) { Step.new(
|
75
|
-
let(:asterisk_step) { Step.new(
|
75
|
+
let(:and_step) { Step.new(language, double, double, "And ", double, double) }
|
76
|
+
let(:but_step) { Step.new(language, double, double, "But ", double, double) }
|
77
|
+
let(:asterisk_step) { Step.new(language, double, double, "* ", double, double) }
|
76
78
|
|
77
79
|
context "when the previous step keyword exist" do
|
78
80
|
it "returns the previous step keyword" do
|
@@ -93,8 +95,8 @@ module Cucumber
|
|
93
95
|
end
|
94
96
|
|
95
97
|
context "for i18n languages" do
|
96
|
-
let(:language) { ::
|
97
|
-
let(:and_step) { Step.new(
|
98
|
+
let(:language) { ::Gherkin3::Dialect.for('en-lol') }
|
99
|
+
let(:and_step) { Step.new(language, double, double, "AN ", double, double) }
|
98
100
|
|
99
101
|
it "returns the keyword in the correct language" do
|
100
102
|
expect( and_step.actual_keyword(nil) ).to eq("I CAN HAZ ")
|
@@ -106,10 +108,10 @@ module Cucumber
|
|
106
108
|
describe ExpandedOutlineStep do
|
107
109
|
let(:outline_step) { double }
|
108
110
|
let(:step) do
|
109
|
-
|
110
|
-
comments = []
|
111
|
+
language, location, keyword, name = *double
|
111
112
|
multiline_arg = EmptyMultilineArgument.new
|
112
|
-
|
113
|
+
comments = []
|
114
|
+
ExpandedOutlineStep.new(outline_step, language, location, comments, keyword, name, multiline_arg)
|
113
115
|
end
|
114
116
|
|
115
117
|
describe "describing itself" do
|
@@ -128,7 +130,7 @@ module Cucumber
|
|
128
130
|
end
|
129
131
|
|
130
132
|
context "with a multiline argument" do
|
131
|
-
let(:step) {
|
133
|
+
let(:step) { Step.new(double, double, double, double, double, multiline_arg) }
|
132
134
|
let(:multiline_arg) { double }
|
133
135
|
|
134
136
|
it "tells its multiline argument to describe itself" do
|
@@ -157,8 +159,8 @@ module Cucumber
|
|
157
159
|
end
|
158
160
|
|
159
161
|
describe "backtrace line" do
|
160
|
-
let(:outline_step) { OutlineStep.new(double,
|
161
|
-
let(:step) { ExpandedOutlineStep.new(outline_step, double,
|
162
|
+
let(:outline_step) { OutlineStep.new(double, "path/file.feature:5", double, "Given ", "this step <state>", double) }
|
163
|
+
let(:step) { ExpandedOutlineStep.new(outline_step, double, "path/file.feature:10", double, "Given ", "this step passes", double) }
|
162
164
|
|
163
165
|
it "includes the outline step in the backtrace line" do
|
164
166
|
expect( step.backtrace_line ).to eq("path/file.feature:10:in `Given this step passes'\n" +
|
@@ -15,7 +15,7 @@ module Cucumber
|
|
15
15
|
end
|
16
16
|
|
17
17
|
context "for invalid gherkin" do
|
18
|
-
let(:source) { Gherkin::Document.new(path,
|
18
|
+
let(:source) { Gherkin::Document.new(path, "\nnot gherkin\n\nFeature: \n") }
|
19
19
|
let(:path) { 'path_to/the.feature' }
|
20
20
|
|
21
21
|
it "raises an error" do
|
@@ -116,19 +116,48 @@ module Cucumber
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
-
context "a
|
119
|
+
context "a feature file with a comments on different levels" do
|
120
120
|
source do
|
121
|
+
comment 'feature comment'
|
121
122
|
feature do
|
122
|
-
comment '
|
123
|
-
scenario
|
123
|
+
comment 'scenario comment'
|
124
|
+
scenario do
|
125
|
+
comment 'step comment'
|
126
|
+
step
|
127
|
+
end
|
128
|
+
comment 'scenario outline comment'
|
129
|
+
scenario_outline do
|
130
|
+
comment 'outline step comment'
|
131
|
+
step
|
132
|
+
comment 'examples comment'
|
133
|
+
examples do
|
134
|
+
row
|
135
|
+
row
|
136
|
+
end
|
137
|
+
end
|
124
138
|
end
|
125
139
|
end
|
126
140
|
|
127
|
-
it "
|
141
|
+
it "the comments are distibuted to down the ast tree from the feature" do
|
128
142
|
visitor = double
|
129
|
-
|
143
|
+
expect( visitor ).to receive(:feature) do |feature|
|
144
|
+
expect( feature.comments.join ).to eq "# feature comment"
|
145
|
+
visitor
|
146
|
+
end.and_yield(visitor)
|
130
147
|
expect( visitor ).to receive(:scenario) do |scenario|
|
131
|
-
expect( scenario.comments.join ).to eq "#
|
148
|
+
expect( scenario.comments.join ).to eq " # scenario comment"
|
149
|
+
end.and_yield(visitor)
|
150
|
+
expect( visitor ).to receive(:step) do |step|
|
151
|
+
expect( step.comments.join ).to eq " # step comment"
|
152
|
+
end.and_yield(visitor)
|
153
|
+
expect( visitor ).to receive(:scenario_outline) do |scenario_outline|
|
154
|
+
expect( scenario_outline.comments.join ).to eq " # scenario outline comment"
|
155
|
+
end.and_yield(visitor)
|
156
|
+
expect( visitor ).to receive(:outline_step) do |outline_step|
|
157
|
+
expect( outline_step.comments.join ).to eq " # outline step comment"
|
158
|
+
end.and_yield(visitor)
|
159
|
+
expect( visitor ).to receive(:examples_table) do |examples_table|
|
160
|
+
expect( examples_table.comments.join ).to eq " # examples comment"
|
132
161
|
end
|
133
162
|
feature.describe_to(visitor)
|
134
163
|
end
|