cucumber-core 16.2.0 → 18.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 +4 -4
- data/CHANGELOG.md +32 -5
- data/LICENSE +14 -13
- data/lib/cucumber/core/compiler.rb +11 -10
- data/lib/cucumber/core/event.rb +12 -10
- data/lib/cucumber/core/event_bus.rb +1 -1
- data/lib/cucumber/core/events/base.rb +26 -0
- data/lib/cucumber/core/events/envelope.rb +13 -2
- data/lib/cucumber/core/events/gherkin_source_parsed.rb +12 -3
- data/lib/cucumber/core/events/test_case_created.rb +12 -6
- data/lib/cucumber/core/events/test_case_finished.rb +11 -1
- data/lib/cucumber/core/events/test_case_started.rb +12 -3
- data/lib/cucumber/core/events/test_step_created.rb +12 -6
- data/lib/cucumber/core/events/test_step_finished.rb +14 -4
- data/lib/cucumber/core/events/test_step_started.rb +12 -3
- data/lib/cucumber/core/gherkin/document.rb +16 -6
- data/lib/cucumber/core/gherkin/parser.rb +6 -10
- data/lib/cucumber/core/gherkin/writer/accepts_comments.rb +23 -0
- data/lib/cucumber/core/gherkin/writer/background.rb +3 -1
- data/lib/cucumber/core/gherkin/writer/doc_string.rb +3 -1
- data/lib/cucumber/core/gherkin/writer/example.rb +3 -1
- data/lib/cucumber/core/gherkin/writer/examples.rb +3 -1
- data/lib/cucumber/core/gherkin/writer/feature.rb +3 -1
- data/lib/cucumber/core/gherkin/writer/has_description.rb +21 -0
- data/lib/cucumber/core/gherkin/writer/has_elements.rb +47 -0
- data/lib/cucumber/core/gherkin/writer/has_options_initializer.rb +58 -0
- data/lib/cucumber/core/gherkin/writer/has_rows.rb +43 -0
- data/lib/cucumber/core/gherkin/writer/helpers.rb +6 -174
- data/lib/cucumber/core/gherkin/writer/indentation.rb +40 -0
- data/lib/cucumber/core/gherkin/writer/rule.rb +3 -1
- data/lib/cucumber/core/gherkin/writer/scenario.rb +3 -1
- data/lib/cucumber/core/gherkin/writer/scenario_outline.rb +3 -1
- data/lib/cucumber/core/gherkin/writer/step.rb +3 -1
- data/lib/cucumber/core/gherkin/writer/table.rb +4 -1
- data/lib/cucumber/core/report/summary.rb +2 -2
- data/lib/cucumber/core/test/action/defined.rb +3 -3
- data/lib/cucumber/core/test/action.rb +6 -6
- data/lib/cucumber/core/test/around_hook.rb +4 -4
- data/lib/cucumber/core/test/case.rb +27 -26
- data/lib/cucumber/core/test/data_table.rb +37 -39
- data/lib/cucumber/core/test/doc_string.rb +23 -23
- data/lib/cucumber/core/test/empty_multiline_argument.rb +8 -8
- data/lib/cucumber/core/test/filters/locations_filter.rb +1 -1
- data/lib/cucumber/core/test/filters/name_filter.rb +1 -1
- data/lib/cucumber/core/test/filters/tag_filter.rb +1 -1
- data/lib/cucumber/core/test/filters.rb +3 -3
- data/lib/cucumber/core/test/hook_step.rb +1 -1
- data/lib/cucumber/core/test/location.rb +1 -3
- data/lib/cucumber/core/test/result/ambiguous.rb +41 -0
- data/lib/cucumber/core/test/result/boolean_methods.rb +28 -0
- data/lib/cucumber/core/test/result/duration.rb +33 -0
- data/lib/cucumber/core/test/result/failed.rb +72 -0
- data/lib/cucumber/core/test/result/flaky.rb +21 -0
- data/lib/cucumber/core/test/result/passed.rb +57 -0
- data/lib/cucumber/core/test/result/pending.rb +41 -0
- data/lib/cucumber/core/test/result/raisable.rb +46 -0
- data/lib/cucumber/core/test/result/skipped.rb +41 -0
- data/lib/cucumber/core/test/result/summary.rb +89 -0
- data/lib/cucumber/core/test/result/undefined.rb +41 -0
- data/lib/cucumber/core/test/result/unknown.rb +40 -0
- data/lib/cucumber/core/test/result/unknown_duration.rb +26 -0
- data/lib/cucumber/core/test/result.rb +15 -458
- data/lib/cucumber/core/test/runner.rb +25 -22
- data/lib/cucumber/core/test/step.rb +22 -23
- data/lib/cucumber/core/test/tag.rb +2 -0
- data/lib/cucumber/core/test/timer.rb +2 -2
- data/lib/cucumber/core.rb +6 -5
- metadata +32 -16
- data/lib/cucumber/core/platform.rb +0 -17
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Core
|
|
5
|
+
module Gherkin
|
|
6
|
+
module Writer
|
|
7
|
+
module HasElements
|
|
8
|
+
include AcceptsComments
|
|
9
|
+
|
|
10
|
+
def self.included(base)
|
|
11
|
+
base.extend HasElementBuilders
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def build(source = [])
|
|
15
|
+
elements.inject(source + statements) { |acc, el| el.build(acc) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def elements
|
|
21
|
+
@elements ||= []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module HasElementBuilders
|
|
25
|
+
def elements(*names)
|
|
26
|
+
names.each { |name| element(name) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def element(name)
|
|
32
|
+
define_method(name) do |*args, &source|
|
|
33
|
+
factory_name = String(name).split('_').map(&:capitalize).join
|
|
34
|
+
factory = Writer.const_get(factory_name)
|
|
35
|
+
factory.new(slurp_comments, *args).tap do |builder|
|
|
36
|
+
builder.instance_exec(&source) if source
|
|
37
|
+
elements << builder
|
|
38
|
+
end
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Core
|
|
5
|
+
module Gherkin
|
|
6
|
+
module Writer
|
|
7
|
+
module HasOptionsInitializer
|
|
8
|
+
def self.included(base)
|
|
9
|
+
base.extend HasDefaultKeyword
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_reader :name, :options
|
|
13
|
+
private :name, :options
|
|
14
|
+
|
|
15
|
+
def initialize(*args)
|
|
16
|
+
@comments = args.shift if args.first.is_a?(Array)
|
|
17
|
+
@comments ||= []
|
|
18
|
+
@options = args.pop if args.last.is_a?(Hash)
|
|
19
|
+
@options ||= {}
|
|
20
|
+
@name = args.first
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def comments_statement
|
|
26
|
+
@comments
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def keyword
|
|
30
|
+
options.fetch(:keyword) { self.class.keyword }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def name_statement
|
|
34
|
+
"#{keyword}: #{name}".strip
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def tag_statement
|
|
38
|
+
tags
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def tags
|
|
42
|
+
options[:tags]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module HasDefaultKeyword
|
|
46
|
+
def default_keyword(keyword)
|
|
47
|
+
@keyword = keyword
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def keyword
|
|
51
|
+
@keyword
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Core
|
|
5
|
+
module Gherkin
|
|
6
|
+
module Writer
|
|
7
|
+
module HasRows
|
|
8
|
+
def row(*cells)
|
|
9
|
+
rows << cells
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def rows
|
|
13
|
+
@rows ||= []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def row_statements(indent = nil)
|
|
19
|
+
rows.map { |row| indent(table_row(row), indent) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def table_row(row)
|
|
23
|
+
padded = pad(row)
|
|
24
|
+
"| #{padded.join(' | ')} |"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def pad(row)
|
|
28
|
+
row.map.with_index { |text, position| justify_cell(text, position) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def column_length(column)
|
|
32
|
+
lengths = rows.transpose.map { |r| r.map(&:length).max }
|
|
33
|
+
lengths[column]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def justify_cell(cell, position)
|
|
37
|
+
cell.ljust(column_length(position))
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -1,177 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
module Core
|
|
5
|
-
module Gherkin
|
|
6
|
-
module Writer
|
|
7
|
-
module HasOptionsInitializer
|
|
8
|
-
def self.included(base)
|
|
9
|
-
base.extend HasDefaultKeyword
|
|
10
|
-
end
|
|
3
|
+
require_relative 'accepts_comments'
|
|
11
4
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@comments ||= []
|
|
18
|
-
@options = args.pop if args.last.is_a?(Hash)
|
|
19
|
-
@options ||= {}
|
|
20
|
-
@name = args.first
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
def comments_statement
|
|
26
|
-
@comments
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def keyword
|
|
30
|
-
options.fetch(:keyword) { self.class.keyword }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def name_statement
|
|
34
|
-
"#{keyword}: #{name}".strip
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def tag_statement
|
|
38
|
-
tags
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def tags
|
|
42
|
-
options[:tags]
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
module HasDefaultKeyword
|
|
46
|
-
def default_keyword(keyword)
|
|
47
|
-
@keyword = keyword
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def keyword
|
|
51
|
-
@keyword
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
module AcceptsComments
|
|
57
|
-
def comment(line)
|
|
58
|
-
comment_lines << "# #{line}"
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def comment_lines
|
|
62
|
-
@comment_lines ||= []
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def slurp_comments
|
|
66
|
-
comment_lines.tap { @comment_lines = nil }
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
module HasElements
|
|
71
|
-
include AcceptsComments
|
|
72
|
-
|
|
73
|
-
def self.included(base)
|
|
74
|
-
base.extend HasElementBuilders
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def build(source = [])
|
|
78
|
-
elements.inject(source + statements) { |acc, el| el.build(acc) }
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
private
|
|
82
|
-
|
|
83
|
-
def elements
|
|
84
|
-
@elements ||= []
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
module HasElementBuilders
|
|
88
|
-
def elements(*names)
|
|
89
|
-
names.each { |name| element(name) }
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
private
|
|
93
|
-
|
|
94
|
-
def element(name)
|
|
95
|
-
define_method(name) do |*args, &source|
|
|
96
|
-
factory_name = String(name).split('_').map(&:capitalize).join
|
|
97
|
-
factory = Writer.const_get(factory_name)
|
|
98
|
-
factory.new(slurp_comments, *args).tap do |builder|
|
|
99
|
-
builder.instance_exec(&source) if source
|
|
100
|
-
elements << builder
|
|
101
|
-
end
|
|
102
|
-
self
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
module Indentation
|
|
109
|
-
def self.level(number)
|
|
110
|
-
Module.new do
|
|
111
|
-
define_method(:indent) do |string, amount = nil|
|
|
112
|
-
return string if string.nil? || string.empty?
|
|
113
|
-
|
|
114
|
-
amount ||= number
|
|
115
|
-
"#{' ' * amount}#{string}"
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
define_method(:indent_level) do
|
|
119
|
-
number
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
define_method(:prepare_statements) do |*statements|
|
|
123
|
-
statements.flatten.compact.map { |s| indent(s) }
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
module HasDescription
|
|
130
|
-
private
|
|
131
|
-
|
|
132
|
-
def description
|
|
133
|
-
options.fetch(:description, '').split("\n").map(&:strip)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def description_statement
|
|
137
|
-
description.map { |s| indent(s, 2) } unless description.empty?
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
module HasRows
|
|
142
|
-
def row(*cells)
|
|
143
|
-
rows << cells
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def rows
|
|
147
|
-
@rows ||= []
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
private
|
|
151
|
-
|
|
152
|
-
def row_statements(indent = nil)
|
|
153
|
-
rows.map { |row| indent(table_row(row), indent) }
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def table_row(row)
|
|
157
|
-
padded = pad(row)
|
|
158
|
-
"| #{padded.join(' | ')} |"
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def pad(row)
|
|
162
|
-
row.map.with_index { |text, position| justify_cell(text, position) }
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def column_length(column)
|
|
166
|
-
lengths = rows.transpose.map { |r| r.map(&:length).max }
|
|
167
|
-
lengths[column]
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def justify_cell(cell, position)
|
|
171
|
-
cell.ljust(column_length(position))
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
end
|
|
5
|
+
require_relative 'has_description'
|
|
6
|
+
require_relative 'has_elements'
|
|
7
|
+
require_relative 'has_options_initializer'
|
|
8
|
+
require_relative 'has_rows'
|
|
9
|
+
require_relative 'indentation'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Core
|
|
5
|
+
module Gherkin
|
|
6
|
+
module Writer
|
|
7
|
+
module Indentation
|
|
8
|
+
def indentation_level(number)
|
|
9
|
+
create_indent(number)
|
|
10
|
+
create_indent_level(number)
|
|
11
|
+
create_prepare_statements
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def create_indent(number)
|
|
17
|
+
define_method(:indent) do |string, amount = nil|
|
|
18
|
+
return string if string.nil? || string.empty?
|
|
19
|
+
|
|
20
|
+
amount ||= number
|
|
21
|
+
"#{' ' * amount}#{string}"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def create_indent_level(number)
|
|
26
|
+
define_method(:indent_level) do
|
|
27
|
+
number
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def create_prepare_statements
|
|
32
|
+
define_method(:prepare_statements) do |*statements|
|
|
33
|
+
statements.flatten.compact.map { |s| indent(s) }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
require_relative '../location'
|
|
4
|
+
require_relative '../result'
|
|
5
|
+
require_relative '../timer'
|
|
6
6
|
|
|
7
7
|
module Cucumber
|
|
8
8
|
module Core
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
require_relative 'location'
|
|
4
|
+
require_relative 'result'
|
|
5
|
+
require_relative 'timer'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
require_relative 'action/defined'
|
|
8
|
+
require_relative 'action/undefined'
|
|
9
|
+
require_relative 'action/unskippable'
|
|
@@ -13,10 +13,6 @@ module Cucumber
|
|
|
13
13
|
visitor.around_hook(self, *, &)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def hook?
|
|
17
|
-
true
|
|
18
|
-
end
|
|
19
|
-
|
|
20
16
|
def execute(*_args, &continue)
|
|
21
17
|
@timer.start
|
|
22
18
|
@block.call(continue)
|
|
@@ -27,6 +23,10 @@ module Cucumber
|
|
|
27
23
|
failed(e)
|
|
28
24
|
end
|
|
29
25
|
|
|
26
|
+
def hook?
|
|
27
|
+
true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
30
|
private
|
|
31
31
|
|
|
32
32
|
def failed(exception)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'cucumber/core/test/result'
|
|
4
3
|
require 'cucumber/tag_expressions'
|
|
5
4
|
|
|
5
|
+
require_relative 'result'
|
|
6
|
+
|
|
6
7
|
module Cucumber
|
|
7
8
|
module Core
|
|
8
9
|
module Test
|
|
@@ -22,8 +23,8 @@ module Cucumber
|
|
|
22
23
|
@around_hooks = around_hooks
|
|
23
24
|
end
|
|
24
25
|
|
|
25
|
-
def
|
|
26
|
-
|
|
26
|
+
def ==(other)
|
|
27
|
+
eql?(other)
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def describe_to(visitor, *args)
|
|
@@ -37,20 +38,25 @@ module Cucumber
|
|
|
37
38
|
self
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
def
|
|
41
|
-
|
|
41
|
+
def eql?(other)
|
|
42
|
+
other.hash == hash
|
|
42
43
|
end
|
|
43
44
|
|
|
44
|
-
def
|
|
45
|
-
|
|
45
|
+
def hash
|
|
46
|
+
location.hash
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
def
|
|
49
|
-
|
|
49
|
+
def inspect
|
|
50
|
+
"#<#{self.class}: #{location}>"
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
def
|
|
53
|
-
|
|
53
|
+
def matching_locations
|
|
54
|
+
[
|
|
55
|
+
parent_locations,
|
|
56
|
+
location,
|
|
57
|
+
tags.map(&:location),
|
|
58
|
+
test_steps.map(&:matching_locations)
|
|
59
|
+
].flatten
|
|
54
60
|
end
|
|
55
61
|
|
|
56
62
|
def match_locations?(queried_locations)
|
|
@@ -61,29 +67,24 @@ module Cucumber
|
|
|
61
67
|
end
|
|
62
68
|
end
|
|
63
69
|
|
|
64
|
-
def
|
|
65
|
-
|
|
66
|
-
parent_locations,
|
|
67
|
-
location,
|
|
68
|
-
tags.map(&:location),
|
|
69
|
-
test_steps.map(&:matching_locations)
|
|
70
|
-
].flatten
|
|
70
|
+
def match_name?(name_regexp)
|
|
71
|
+
name =~ name_regexp
|
|
71
72
|
end
|
|
72
73
|
|
|
73
|
-
def
|
|
74
|
-
|
|
74
|
+
def match_tags?(*expressions)
|
|
75
|
+
expressions.flatten.all? { |expression| match_single_tag_expression?(expression) }
|
|
75
76
|
end
|
|
76
77
|
|
|
77
|
-
def
|
|
78
|
-
|
|
78
|
+
def step_count
|
|
79
|
+
test_steps.count
|
|
79
80
|
end
|
|
80
81
|
|
|
81
|
-
def
|
|
82
|
-
|
|
82
|
+
def with_around_hooks(around_hooks)
|
|
83
|
+
self.class.new(id, name, test_steps, location, parent_locations, tags, language, around_hooks)
|
|
83
84
|
end
|
|
84
85
|
|
|
85
|
-
def
|
|
86
|
-
|
|
86
|
+
def with_steps(test_steps)
|
|
87
|
+
self.class.new(id, name, test_steps, location, parent_locations, tags, language, around_hooks)
|
|
87
88
|
end
|
|
88
89
|
|
|
89
90
|
private
|