features 0.1.4 → 0.2.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.
Potentially problematic release.
This version of features might be problematic. Click here for more details.
- data/Manifest +59 -0
- data/README.markdown +31 -1
- data/Rakefile +1 -1
- data/features.gemspec +3 -3
- data/generators/features/templates/run_features.rb +27 -0
- data/lib/ObjC/objc_feature.rb +4 -27
- data/lib/ObjC/objc_scenario.rb +1 -58
- data/lib/ObjC/objc_step.rb +0 -31
- data/lib/ObjC/objc_suite.rb +14 -122
- data/lib/Rails/rails_feature.rb +7 -30
- data/lib/Rails/rails_scenario.rb +0 -57
- data/lib/Rails/rails_step.rb +1 -30
- data/lib/Rails/rails_suite.rb +16 -132
- data/lib/feature.rb +29 -1
- data/lib/scenario.rb +99 -0
- data/lib/step.rb +28 -0
- data/lib/suite.rb +124 -0
- data/website/README +10 -0
- data/website/Rakefile +44 -0
- data/website/config.yaml +18 -0
- data/website/deploy.rb +29 -0
- data/website/deploy/1251795725/features/browserfix.css +7 -0
- data/website/deploy/1251795725/features/default.css +257 -0
- data/website/deploy/1251795725/features/images/bodybg.gif +0 -0
- data/website/deploy/1251795725/features/images/header-bg.gif +0 -0
- data/website/deploy/1251795725/features/images/logo.png +0 -0
- data/website/deploy/1251795725/features/images/minus.png +0 -0
- data/website/deploy/1251795725/features/images/plus.png +0 -0
- data/website/deploy/1251795725/features/images/sidebarbg.gif +0 -0
- data/website/deploy/1251795725/features/index.html +229 -0
- data/website/deploy/1251796894/features/browserfix.css +7 -0
- data/website/deploy/1251796894/features/default.css +257 -0
- data/website/deploy/1251796894/features/images/bodybg.gif +0 -0
- data/website/deploy/1251796894/features/images/header-bg.gif +0 -0
- data/website/deploy/1251796894/features/images/logo.png +0 -0
- data/website/deploy/1251796894/features/images/minus.png +0 -0
- data/website/deploy/1251796894/features/images/output-screen-1.png +0 -0
- data/website/deploy/1251796894/features/images/plus.png +0 -0
- data/website/deploy/1251796894/features/images/sidebarbg.gif +0 -0
- data/website/deploy/1251796894/features/index.html +229 -0
- data/website/deploy/1251822430/features/browserfix.css +7 -0
- data/website/deploy/1251822430/features/default.css +257 -0
- data/website/deploy/1251822430/features/images/bodybg.gif +0 -0
- data/website/deploy/1251822430/features/images/header-bg.gif +0 -0
- data/website/deploy/1251822430/features/images/logo.png +0 -0
- data/website/deploy/1251822430/features/images/minus.png +0 -0
- data/website/deploy/1251822430/features/images/output-screen-1.png +0 -0
- data/website/deploy/1251822430/features/images/plus.png +0 -0
- data/website/deploy/1251822430/features/images/sidebarbg.gif +0 -0
- data/website/deploy/1251822430/features/index.html +229 -0
- data/website/ext/init.rb +10 -0
- data/website/out/browserfix.css +7 -0
- data/website/out/default.css +257 -0
- data/website/out/images/bodybg.gif +0 -0
- data/website/out/images/header-bg.gif +0 -0
- data/website/out/images/logo.png +0 -0
- data/website/out/images/minus.png +0 -0
- data/website/out/images/output-screen-1.png +0 -0
- data/website/out/images/plus.png +0 -0
- data/website/out/images/sidebarbg.gif +0 -0
- data/website/out/index.html +229 -0
- data/website/src/browserfix.css +7 -0
- data/website/src/default.css +257 -0
- data/website/src/default.template +92 -0
- data/website/src/images/bodybg.gif +0 -0
- data/website/src/images/deploy.rb +29 -0
- data/website/src/images/header-bg.gif +0 -0
- data/website/src/images/logo.png +0 -0
- data/website/src/images/minus.png +0 -0
- data/website/src/images/output-screen-1.png +0 -0
- data/website/src/images/plus.png +0 -0
- data/website/src/images/sidebarbg.gif +0 -0
- data/website/src/images/webgen.rb +3 -0
- data/website/src/index.page +139 -0
- data/website/webgen.cache +0 -0
- data/website/webgen.rb +3 -0
- metadata +61 -2
data/lib/Rails/rails_feature.rb
CHANGED
@@ -1,36 +1,13 @@
|
|
1
1
|
class RailsFeature < Feature
|
2
|
-
|
3
|
-
:title, :body, :parent, :parser,
|
4
|
-
:given_scenario_keyword, :keyword
|
5
|
-
|
6
|
-
def initialize(hash={})
|
7
|
-
@title = hash[:title]
|
8
|
-
@body = hash[:body]
|
9
|
-
@parent = hash[:parent]
|
10
|
-
@keyword = hash[:keyword] || "Feature:"
|
11
|
-
@scenario_keyword = hash[:scenario_keyword] || "Scenario:"
|
12
|
-
@given_scenario_keyword = hash[:given_scenario_keyword] || "GivenScenario:"
|
13
|
-
|
14
|
-
raise "No title given" unless title
|
15
|
-
raise "No body given" unless body
|
16
|
-
end
|
17
|
-
|
18
|
-
def story
|
19
|
-
body.split(/#{scenario_keyword}/)[0].split(/#{keyword}\s#{title}/).join(" ").strip
|
20
|
-
end
|
21
|
-
|
22
|
-
def story_html
|
23
|
-
story.split("\n").join(" <br />")
|
24
|
-
end
|
25
|
-
|
26
|
-
def parse_scenarios
|
2
|
+
def parse_scenarios(klass=RailsScenario)
|
27
3
|
title_body_arr = Parser.title_and_body_by_keyword_from_string({
|
28
4
|
:string => body,
|
29
5
|
:keyword => scenario_keyword
|
30
6
|
})
|
31
|
-
@scenarios = title_body_arr.map {|hash|
|
7
|
+
@scenarios = title_body_arr.map {|hash| klass.new(hash.update({
|
32
8
|
:parent => self,
|
33
|
-
:given_scenario_keyword => given_scenario_keyword
|
9
|
+
:given_scenario_keyword => given_scenario_keyword,
|
10
|
+
:follow_up_keyword => follow_up_keyword
|
34
11
|
}))}
|
35
12
|
@scenarios.each {|scenario| scenario.collect_steps}
|
36
13
|
self
|
@@ -38,9 +15,9 @@ class RailsFeature < Feature
|
|
38
15
|
|
39
16
|
def to_s
|
40
17
|
<<-END
|
41
|
-
|
42
|
-
|
43
|
-
|
18
|
+
class #{test_case_name} < FeaturesTestCaseClass
|
19
|
+
#{scenarios.map {|s| s.to_s}.join("\n")}
|
20
|
+
end
|
44
21
|
END
|
45
22
|
end
|
46
23
|
|
data/lib/Rails/rails_scenario.rb
CHANGED
@@ -1,34 +1,4 @@
|
|
1
1
|
class RailsScenario < Scenario
|
2
|
-
attr_reader :steps, :lines, :given_scenario_keyword,
|
3
|
-
:title, :body, :parent, :passed
|
4
|
-
|
5
|
-
def initialize(hash)
|
6
|
-
@title = hash[:title]
|
7
|
-
@body = hash[:body]
|
8
|
-
@parent = hash[:parent]
|
9
|
-
@given_scenario_keyword = hash[:given_scenario_keyword] || "GivenScenario:"
|
10
|
-
|
11
|
-
raise "No title given" unless title
|
12
|
-
raise "No body given" unless body
|
13
|
-
end
|
14
|
-
|
15
|
-
def keyword
|
16
|
-
parent.scenario_keyword
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_html
|
20
|
-
<<-END
|
21
|
-
<div class="scenario #{passed? ? "passed" : "failed"}">
|
22
|
-
<h2 class="scenario_title">#{keyword} #{title}</h2>
|
23
|
-
#{steps.map {|s| s.to_html}.join(" \n")}
|
24
|
-
</div>
|
25
|
-
END
|
26
|
-
end
|
27
|
-
|
28
|
-
def passed?
|
29
|
-
!!@passed
|
30
|
-
end
|
31
|
-
|
32
2
|
def verify_status(results="")
|
33
3
|
test_case_name = parent.test_case_name
|
34
4
|
|
@@ -40,37 +10,10 @@ class RailsScenario < Scenario
|
|
40
10
|
@passed = result ? false : true
|
41
11
|
end
|
42
12
|
|
43
|
-
def collect_steps
|
44
|
-
|
45
|
-
if has_given_scenarios?
|
46
|
-
@body = expand_given_scenarios_in_body.strip
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
@lines = body.split(/\n+/).map {|s| s.strip}
|
51
|
-
raise "No Steps found" if lines.empty?
|
52
|
-
|
53
|
-
@steps = parse_lines
|
54
|
-
self
|
55
|
-
end
|
56
|
-
|
57
|
-
def expand_given_scenarios_in_body
|
58
|
-
raise "No associated Feature" unless parent
|
59
|
-
raise "Associated Feature has no Scenarios" unless parent.scenarios
|
60
|
-
body.gsub(/#{given_scenario_keyword}(.*)/) do |m|
|
61
|
-
existing_scenario = parent.scenarios.detect {|s| s.title == $1.strip }
|
62
|
-
existing_scenario ? existing_scenario.body.strip : ""
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
13
|
def parse_lines
|
67
14
|
lines.map {|l| RailsStep.new({:body => l}).aggregate!}
|
68
15
|
end
|
69
16
|
|
70
|
-
def has_given_scenarios?
|
71
|
-
!!(body =~ /#{given_scenario_keyword}(.*)/)
|
72
|
-
end
|
73
|
-
|
74
17
|
def to_s
|
75
18
|
<<-END
|
76
19
|
def #{test_name}
|
data/lib/Rails/rails_step.rb
CHANGED
@@ -1,39 +1,10 @@
|
|
1
1
|
class RailsStep < Step
|
2
|
-
attr_reader :message
|
3
|
-
|
4
|
-
attr_reader :body, :parent
|
5
|
-
def initialize(hash)
|
6
|
-
@body = hash[:body]
|
7
|
-
@parent = hash[:parent]
|
8
|
-
raise "No body given" unless body
|
9
|
-
end
|
10
|
-
|
11
|
-
def to_html
|
12
|
-
s = <<-END
|
13
|
-
<h3 class="step">#{body}</h3>
|
14
|
-
END
|
15
|
-
s.strip
|
16
|
-
end
|
17
|
-
|
18
|
-
def aggregate!
|
19
|
-
@message = first_part + args_string
|
20
|
-
self
|
21
|
-
end
|
22
|
-
|
23
2
|
def first_part
|
24
3
|
body.gsub(/\s+/,"_").gsub(/'[^']*'/, "__").remove_invalid_chars.sub(/./) do |first_char|
|
25
4
|
first_char.downcase
|
26
5
|
end
|
27
6
|
end
|
28
|
-
|
29
|
-
def has_args?
|
30
|
-
!args.empty?
|
31
|
-
end
|
32
|
-
|
33
|
-
def args
|
34
|
-
@args ||= body.scan(/'([^']*)'/).map {|a| a[0]}
|
35
|
-
end
|
36
|
-
|
7
|
+
|
37
8
|
def args_string
|
38
9
|
if has_args?
|
39
10
|
"(" + args.map {|a| '"' + a.to_s + '"'}.join(", ") + ")"
|
data/lib/Rails/rails_suite.rb
CHANGED
@@ -4,7 +4,8 @@ class RailsSuite < Suite
|
|
4
4
|
:features, :test_cases_file,
|
5
5
|
:feature_keyword, :scenario_keyword,
|
6
6
|
:project_name, :passed,
|
7
|
-
:given_scenario_keyword, :features_helper
|
7
|
+
:given_scenario_keyword, :features_helper,
|
8
|
+
:follow_up_keyword
|
8
9
|
|
9
10
|
def initialize(hash)
|
10
11
|
@feature_files_path = hash[:feature_files_path]
|
@@ -15,147 +16,30 @@ class RailsSuite < Suite
|
|
15
16
|
@scenario_keyword = hash[:scenario_keyword] || "Scenario:"
|
16
17
|
@given_scenario_keyword = hash[:given_scenario_keyword] || "GivenScenario:"
|
17
18
|
@project_name = hash[:project_name] || "Features"
|
19
|
+
@follow_up_keyword = hash[:follow_up_keyword] || "And"
|
18
20
|
@feature_files = all_feature_files
|
19
21
|
@feature_files_as_strings = all_feature_files_as_strings
|
20
22
|
end
|
21
23
|
|
22
|
-
def
|
23
|
-
results = ""
|
24
|
-
File.open(file) do |f|
|
25
|
-
f.readlines.each do |l|
|
26
|
-
results << l
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
html = parse_results(results).html
|
31
|
-
|
32
|
-
%x(touch '/tmp/out.html' && echo '#{html}' > /tmp/out.html && open '/tmp/out.html' )
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def parse_results_and_open_in_safari(results)
|
37
|
-
html = parse_results(results).html
|
38
|
-
open_in_safari(html)
|
39
|
-
end
|
40
|
-
|
41
|
-
def open_in_safari(html)
|
42
|
-
%x(touch '/tmp/out.html' && echo '#{html}' > /tmp/out.html && open '/tmp/out.html' )
|
43
|
-
end
|
44
|
-
|
45
|
-
|
46
|
-
def parse_results(results="")
|
47
|
-
parse
|
48
|
-
@passed = true
|
49
|
-
features.each do |f|
|
50
|
-
f.scenarios.each do |s|
|
51
|
-
s.verify_status(results)
|
52
|
-
@passed &&= s.passed?
|
53
|
-
end
|
54
|
-
end
|
55
|
-
self
|
56
|
-
end
|
57
|
-
|
58
|
-
def passed?
|
59
|
-
@passed
|
60
|
-
end
|
61
|
-
|
62
|
-
def html
|
63
|
-
<<-END
|
64
|
-
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
65
|
-
<html>
|
66
|
-
<head>
|
67
|
-
<style type="text/css">
|
68
|
-
body {
|
69
|
-
font-family: Lucida Grande;
|
70
|
-
background-color: #FEFEFE;
|
71
|
-
padding: 5px;
|
72
|
-
}
|
73
|
-
* {-webkit-border-radius: 10px;}
|
74
|
-
body {background-color: #EEE; -webkit-border-radius: 0px;}
|
75
|
-
.feature { background-color: #E0E0E0;padding: 20px; margin: 20px;}
|
76
|
-
.scenario { background-color: #EEE; padding: 20px; margin: 20px}
|
77
|
-
.failed {border: 1px solid #C88; background-color: #B77; }
|
78
|
-
.passed {border: 1px solid #8C8; background-color: #7B7; }
|
79
|
-
.feature_title {font-size: 24pt; }
|
80
|
-
.story { font-size: 18pt; padding-left: 40px;}
|
81
|
-
#indicator { width: 100%; height: 20px; }
|
82
|
-
#wrap { background-color: #EEE; padding: 20px }
|
83
|
-
</style></head>
|
84
|
-
</head>
|
85
|
-
<body>
|
86
|
-
<div id="wrap">
|
87
|
-
<div id="header">
|
88
|
-
<div id="indicator" class="#{passed? ? "passed" : "failed"}"> </div>
|
89
|
-
<h1 class="project_name">#{project_name}</h1>
|
90
|
-
|
91
|
-
</div>
|
92
|
-
#{features.map {|f| f.to_html }.join(" \n")}
|
93
|
-
</div>
|
94
|
-
</body>
|
95
|
-
</html>
|
96
|
-
END
|
97
|
-
end
|
98
|
-
|
99
|
-
def valid?
|
100
|
-
unique_feature_test_case_names?
|
101
|
-
end
|
102
|
-
|
103
|
-
def unique_feature_test_case_names?
|
104
|
-
feature_test_case_name = features.map {|f| f.test_case_name }
|
105
|
-
feature_test_case_name == feature_test_case_name.uniq
|
106
|
-
end
|
107
|
-
|
108
|
-
def run
|
109
|
-
parse
|
110
|
-
raise "Invalid: Duplicated Titles" unless valid?
|
111
|
-
File.open(test_cases_file, "w") { |f| f.puts self }
|
112
|
-
end
|
113
|
-
|
114
|
-
def parse
|
115
|
-
parse_features
|
116
|
-
parse_feature_scenarios
|
117
|
-
end
|
118
|
-
|
119
|
-
def to_s
|
120
|
-
<<-END
|
121
|
-
require "#{features_helper}"
|
122
|
-
#{features.map {|f| f.to_s }.join(" ")}
|
123
|
-
END
|
124
|
-
end
|
125
|
-
|
126
|
-
def parse_features
|
24
|
+
def parse_features(klass=RailsFeature)
|
127
25
|
title_body_arr = Parser.title_and_body_by_keyword_from_string({
|
128
26
|
:string => feature_files_as_strings.join(" "),
|
129
27
|
:keyword => feature_keyword
|
130
28
|
})
|
131
|
-
@features = title_body_arr.map
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def all_feature_files
|
141
|
-
all_entries_in_feature_files_path = Dir.new(feature_files_path).entries
|
142
|
-
feature_entries = all_entries_in_feature_files_path.select do |file|
|
143
|
-
!!(file =~ /\.#{feature_file_suffix}$/)
|
144
|
-
end
|
145
|
-
feature_entries.map do |file|
|
146
|
-
feature_files_path + "/" + file
|
29
|
+
@features = title_body_arr.map do |hash|
|
30
|
+
klass.new(hash.update({
|
31
|
+
:keyword => feature_keyword,
|
32
|
+
:scenario_keyword => scenario_keyword,
|
33
|
+
:given_scenario_keyword => given_scenario_keyword,
|
34
|
+
:follow_up_keyword => follow_up_keyword}))
|
147
35
|
end
|
148
36
|
end
|
149
37
|
|
150
|
-
def
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
end
|
157
|
-
end
|
158
|
-
feature_string
|
159
|
-
end
|
38
|
+
def to_s
|
39
|
+
<<-END
|
40
|
+
require "#{features_helper}"
|
41
|
+
|
42
|
+
#{features.map {|f| f.to_s }.join("\n")}
|
43
|
+
END
|
160
44
|
end
|
161
45
|
end
|
data/lib/feature.rb
CHANGED
@@ -1,2 +1,30 @@
|
|
1
|
-
class Feature
|
1
|
+
class Feature
|
2
|
+
|
3
|
+
attr_reader :scenarios, :scenario_keyword,
|
4
|
+
:title, :body, :parent, :parser,
|
5
|
+
:given_scenario_keyword, :keyword,
|
6
|
+
:follow_up_keyword
|
7
|
+
|
8
|
+
def initialize(hash={})
|
9
|
+
@title = hash[:title]
|
10
|
+
@body = hash[:body]
|
11
|
+
@parent = hash[:parent]
|
12
|
+
@keyword = hash[:keyword] || "Feature:"
|
13
|
+
@scenario_keyword = hash[:scenario_keyword] || "Scenario:"
|
14
|
+
@given_scenario_keyword = hash[:given_scenario_keyword] || "GivenScenario:"
|
15
|
+
@follow_up_keyword = hash[:follow_up_keyword] || "And"
|
16
|
+
|
17
|
+
raise "No title given" unless title
|
18
|
+
raise "No body given" unless body
|
19
|
+
end
|
20
|
+
|
21
|
+
def story
|
22
|
+
body.split(/#{scenario_keyword}/)[0].split(/#{keyword}\s#{title}/).join(" ").strip
|
23
|
+
end
|
24
|
+
|
25
|
+
def story_html
|
26
|
+
story.split("\n").join(" <br />")
|
27
|
+
end
|
28
|
+
|
29
|
+
|
2
30
|
end
|
data/lib/scenario.rb
CHANGED
@@ -1,2 +1,101 @@
|
|
1
1
|
class Scenario
|
2
|
+
attr_reader :steps, :lines, :given_scenario_keyword,
|
3
|
+
:title, :body, :parent, :passed, :follow_up_keyword
|
4
|
+
|
5
|
+
def initialize(hash)
|
6
|
+
@title = hash[:title]
|
7
|
+
@body = hash[:body]
|
8
|
+
@parent = hash[:parent]
|
9
|
+
@given_scenario_keyword = hash[:given_scenario_keyword] || "GivenScenario:"
|
10
|
+
@follow_up_keyword = hash[:follow_up_keyword] || "And"
|
11
|
+
|
12
|
+
raise "No title given" unless title
|
13
|
+
raise "No body given" unless body
|
14
|
+
end
|
15
|
+
|
16
|
+
def keyword
|
17
|
+
parent.scenario_keyword
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_html
|
21
|
+
<<-END
|
22
|
+
<div class="scenario #{passed? ? "passed" : "failed"}">
|
23
|
+
<h2 class="scenario_title">#{keyword} #{title}</h2>
|
24
|
+
#{steps.map {|s| s.to_html}.join(" \n")}
|
25
|
+
</div>
|
26
|
+
END
|
27
|
+
end
|
28
|
+
|
29
|
+
def passed?
|
30
|
+
!!@passed
|
31
|
+
end
|
32
|
+
|
33
|
+
def collect_steps
|
34
|
+
if has_given_scenarios?
|
35
|
+
@body = expand_given_scenarios_in_body.strip
|
36
|
+
end
|
37
|
+
|
38
|
+
if has_follow_ups?
|
39
|
+
@body = expand_follow_ups_in_body.strip
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
@lines = body.split(/\n+/).map {|s| s.strip}
|
44
|
+
raise "No Steps found" if lines.empty?
|
45
|
+
|
46
|
+
@steps = parse_lines
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def expand_given_scenarios_in_body
|
51
|
+
raise "No associated Feature" unless parent
|
52
|
+
raise "Associated Feature has no Scenarios" unless parent.scenarios
|
53
|
+
body.gsub(/#{given_scenario_keyword}(.*)/) do |m|
|
54
|
+
existing_scenario = parent.scenarios.detect {|s| s.title == $1.strip }
|
55
|
+
existing_scenario ? existing_scenario.body.strip : ""
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def expand_follow_ups_in_body
|
60
|
+
lines = body.split("\n")
|
61
|
+
new_lines = []
|
62
|
+
step = ""
|
63
|
+
for line in lines
|
64
|
+
if line =~ follow_up_line_exp
|
65
|
+
args = line.sub(/^\s*#{follow_up_keyword}\s*/, "").split("|").reject {|arg| arg =~ /\A\s*\Z/ }.map {|arg| "'" + arg + "'"}
|
66
|
+
arr = step.split("'").reject {|elt| elt =~ /\A\s*\Z/ }
|
67
|
+
offset = (step =~ /\A\s*'/) ? 0 : 1
|
68
|
+
new_step = ""
|
69
|
+
|
70
|
+
arr.each_with_index do |elt, index|
|
71
|
+
if index % 2 == offset
|
72
|
+
new_step << args[(index - offset) / 2]
|
73
|
+
else
|
74
|
+
new_step << elt
|
75
|
+
end
|
76
|
+
end
|
77
|
+
new_lines << new_step
|
78
|
+
else
|
79
|
+
new_lines << line
|
80
|
+
step = line
|
81
|
+
end
|
82
|
+
end
|
83
|
+
new_lines.join("\n")
|
84
|
+
end
|
85
|
+
|
86
|
+
def given_scenario_line_exp
|
87
|
+
/#{given_scenario_keyword}(.*)/
|
88
|
+
end
|
89
|
+
|
90
|
+
def has_given_scenarios?
|
91
|
+
!!(body =~ given_scenario_line_exp)
|
92
|
+
end
|
93
|
+
|
94
|
+
def follow_up_line_exp
|
95
|
+
/#{follow_up_keyword}\s*\|(.*)\s*\|\s*/
|
96
|
+
end
|
97
|
+
|
98
|
+
def has_follow_ups?
|
99
|
+
!!(body =~ follow_up_line_exp)
|
100
|
+
end
|
2
101
|
end
|