cucumber 0.3.95 → 0.3.96
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.
- data/History.txt +21 -0
- data/Manifest.txt +9 -3
- data/examples/sinatra/features/support/env.rb +1 -3
- data/features/cucumber_cli.feature +1 -0
- data/features/drb_server_integration.feature +56 -3
- data/features/junit_formatter.feature +23 -12
- data/features/step_definitions/cucumber_steps.rb +13 -2
- data/features/support/env.rb +19 -3
- data/lib/cucumber/ast/feature_element.rb +1 -1
- data/lib/cucumber/ast/step.rb +1 -1
- data/lib/cucumber/ast/step_invocation.rb +3 -2
- data/lib/cucumber/cli/configuration.rb +9 -25
- data/lib/cucumber/cli/drb_client.rb +7 -3
- data/lib/cucumber/cli/language_help_formatter.rb +4 -4
- data/lib/cucumber/cli/main.rb +26 -46
- data/lib/cucumber/cli/options.rb +3 -0
- data/lib/cucumber/constantize.rb +28 -0
- data/lib/cucumber/feature_file.rb +3 -3
- data/lib/cucumber/formatter/junit.rb +13 -9
- data/lib/cucumber/formatter/pretty.rb +2 -2
- data/lib/cucumber/language_support/hook_methods.rb +9 -0
- data/lib/cucumber/language_support/language_methods.rb +47 -0
- data/lib/cucumber/language_support/step_definition_methods.rb +44 -0
- data/lib/cucumber/parser/natural_language.rb +72 -0
- data/lib/cucumber/rb_support/rb_dsl.rb +73 -0
- data/lib/cucumber/rb_support/rb_hook.rb +19 -0
- data/lib/cucumber/rb_support/rb_language.rb +129 -0
- data/lib/cucumber/rb_support/rb_step_definition.rb +56 -0
- data/lib/cucumber/step_match.rb +2 -2
- data/lib/cucumber/step_mother.rb +87 -206
- data/lib/cucumber/version.rb +1 -1
- data/lib/cucumber/webrat/element_locator.rb +7 -7
- data/lib/cucumber/world.rb +28 -8
- data/rails_generators/cucumber/templates/cucumber_environment.rb +2 -2
- data/rails_generators/cucumber/templates/spork_env.rb +0 -2
- data/rails_generators/cucumber/templates/webrat_steps.rb +17 -0
- data/spec/cucumber/ast/background_spec.rb +8 -5
- data/spec/cucumber/ast/feature_factory.rb +4 -5
- data/spec/cucumber/ast/feature_spec.rb +7 -1
- data/spec/cucumber/ast/scenario_outline_spec.rb +10 -6
- data/spec/cucumber/ast/scenario_spec.rb +8 -3
- data/spec/cucumber/ast/step_collection_spec.rb +2 -2
- data/spec/cucumber/cli/configuration_spec.rb +15 -0
- data/spec/cucumber/cli/drb_client_spec.rb +35 -1
- data/spec/cucumber/cli/main_spec.rb +5 -4
- data/spec/cucumber/cli/options_spec.rb +6 -0
- data/spec/cucumber/parser/feature_parser_spec.rb +6 -5
- data/spec/cucumber/parser/table_parser_spec.rb +1 -1
- data/spec/cucumber/step_definition_spec.rb +26 -25
- data/spec/cucumber/step_mother_spec.rb +46 -41
- data/spec/cucumber/world/pending_spec.rb +4 -5
- metadata +11 -5
- data/lib/cucumber/cli/rb_step_def_loader.rb +0 -14
- data/lib/cucumber/parser/i18n/language.rb +0 -87
- data/lib/cucumber/step_definition.rb +0 -122
@@ -7,14 +7,18 @@ module Cucumber
|
|
7
7
|
end
|
8
8
|
# Runs features on a DRB server, originally created with Spork compatibility in mind.
|
9
9
|
class DRbClient
|
10
|
-
|
10
|
+
DEFAULT_PORT = 8990
|
11
|
+
|
12
|
+
def self.run(args, error_stream, out_stream, port = nil)
|
13
|
+
port ||= ENV["CUCUMBER_DRB"] || DEFAULT_PORT
|
14
|
+
|
11
15
|
# See http://redmine.ruby-lang.org/issues/show/496 as to why we specify localhost:0
|
12
16
|
DRb.start_service("druby://localhost:0")
|
13
|
-
feature_server = DRbObject.new_with_uri("druby://127.0.0.1
|
17
|
+
feature_server = DRbObject.new_with_uri("druby://127.0.0.1:#{port}")
|
14
18
|
cloned_args = [] # I have no idea why this is needed, but if the regular args are sent then DRb magically transforms it into a DRb object - not an array
|
15
19
|
args.each { |arg| cloned_args << arg }
|
16
20
|
feature_server.run(cloned_args, error_stream, out_stream)
|
17
|
-
rescue DRb::DRbConnError
|
21
|
+
rescue DRb::DRbConnError => e
|
18
22
|
raise DRbClientError, "No DRb server is running."
|
19
23
|
end
|
20
24
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'cucumber/formatter/pretty'
|
2
|
-
require 'cucumber/parser/
|
2
|
+
require 'cucumber/parser/natural_language'
|
3
3
|
|
4
4
|
module Cucumber
|
5
5
|
module Cli
|
@@ -23,8 +23,8 @@ http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.list_keywords(io, lang)
|
26
|
-
language = Parser::
|
27
|
-
raw = Parser::
|
26
|
+
language = Parser::NaturalLanguage[lang]
|
27
|
+
raw = Parser::NaturalLanguage::KEYWORD_KEYS.map do |key|
|
28
28
|
[key, language.keywords(key)]
|
29
29
|
end
|
30
30
|
table = Ast::Table.new(raw)
|
@@ -46,7 +46,7 @@ http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages
|
|
46
46
|
def visit_table_cell_value(value, status)
|
47
47
|
if @col == 1
|
48
48
|
if(@options[:check_lang])
|
49
|
-
@incomplete = Parser::
|
49
|
+
@incomplete = Parser::NaturalLanguage.get(nil, value).incomplete?
|
50
50
|
end
|
51
51
|
status = :comment
|
52
52
|
elsif @incomplete
|
data/lib/cucumber/cli/main.rb
CHANGED
@@ -15,17 +15,11 @@ module Cucumber
|
|
15
15
|
|
16
16
|
class << self
|
17
17
|
def step_mother
|
18
|
-
@step_mother
|
19
|
-
end
|
20
|
-
|
21
|
-
def step_mother=(step_mother)
|
22
|
-
@step_mother = step_mother
|
23
|
-
@step_mother.extend(StepMother)
|
24
|
-
@step_mother.snippet_generator = StepDefinition
|
18
|
+
@step_mother ||= StepMother.new
|
25
19
|
end
|
26
20
|
|
27
21
|
def execute(args)
|
28
|
-
new(args).execute!(
|
22
|
+
new(args).execute!(step_mother)
|
29
23
|
end
|
30
24
|
end
|
31
25
|
|
@@ -33,13 +27,15 @@ module Cucumber
|
|
33
27
|
@args = args
|
34
28
|
@out_stream = out_stream == STDOUT ? Formatter::ColorIO.new : out_stream
|
35
29
|
@error_stream = error_stream
|
30
|
+
$err = error_stream
|
31
|
+
@unsupported_programming_languages = []
|
36
32
|
end
|
37
33
|
|
38
34
|
def execute!(step_mother)
|
39
35
|
trap_interrupt
|
40
36
|
if configuration.drb?
|
41
37
|
begin
|
42
|
-
return DRbClient.run(@args, @error_stream, @out_stream)
|
38
|
+
return DRbClient.run(@args, @error_stream, @out_stream, configuration.drb_port)
|
43
39
|
rescue DRbClientError => e
|
44
40
|
@error_stream.puts "WARNING: #{e.message} Running features locally:"
|
45
41
|
end
|
@@ -50,8 +46,8 @@ module Cucumber
|
|
50
46
|
# This is because i18n step methods are only aliased when
|
51
47
|
# features are loaded. If we swap the order, the requires
|
52
48
|
# will fail.
|
53
|
-
features = load_plain_text_features
|
54
|
-
load_step_defs
|
49
|
+
features = load_plain_text_features(step_mother)
|
50
|
+
load_step_defs(step_mother)
|
55
51
|
enable_diffing
|
56
52
|
|
57
53
|
visitor = configuration.build_formatter_broadcaster(step_mother)
|
@@ -64,7 +60,7 @@ module Cucumber
|
|
64
60
|
step_mother.scenarios(:passed).any?
|
65
61
|
else
|
66
62
|
step_mother.scenarios(:failed).any? ||
|
67
|
-
(configuration.strict? && step_mother.steps(:undefined).any?)
|
63
|
+
(configuration.strict? && (step_mother.steps(:undefined).any? || step_mother.steps(:pending).any?))
|
68
64
|
end
|
69
65
|
rescue ProfilesNotDefinedError, YmlLoadError, ProfileNotFound => e
|
70
66
|
@error_stream.puts e.message
|
@@ -84,19 +80,19 @@ module Cucumber
|
|
84
80
|
exceeded
|
85
81
|
end
|
86
82
|
|
87
|
-
def load_plain_text_features
|
83
|
+
def load_plain_text_features(step_mother)
|
88
84
|
features = Ast::Features.new
|
89
85
|
|
90
86
|
verbose_log("Features:")
|
91
87
|
configuration.feature_files.each do |f|
|
92
88
|
feature_file = FeatureFile.new(f)
|
93
|
-
feature = feature_file.parse(configuration.options)
|
89
|
+
feature = feature_file.parse(step_mother, configuration.options)
|
94
90
|
if feature
|
95
91
|
features.add_feature(feature)
|
96
92
|
verbose_log(" * #{f}")
|
97
93
|
end
|
98
94
|
end
|
99
|
-
verbose_log("\n"
|
95
|
+
verbose_log("\n")
|
100
96
|
features
|
101
97
|
end
|
102
98
|
|
@@ -114,50 +110,36 @@ module Cucumber
|
|
114
110
|
|
115
111
|
private
|
116
112
|
|
117
|
-
def load_step_defs
|
113
|
+
def load_step_defs(step_mother)
|
118
114
|
step_def_files = configuration.step_defs_to_load
|
119
|
-
verbose_log("Step Definitions
|
115
|
+
verbose_log("Step Definitions:")
|
120
116
|
step_def_files.each do |step_def_file|
|
121
|
-
load_step_def(step_def_file)
|
117
|
+
load_step_def(step_mother, step_def_file)
|
122
118
|
end
|
119
|
+
verbose_log("\n")
|
123
120
|
end
|
124
121
|
|
125
|
-
def load_step_def(step_def_file)
|
126
|
-
if
|
122
|
+
def load_step_def(step_mother, step_def_file)
|
123
|
+
if programming_language = programming_language_for(step_mother, step_def_file)
|
127
124
|
verbose_log(" * #{step_def_file}")
|
128
|
-
|
125
|
+
programming_language.load_step_def_file(step_def_file)
|
126
|
+
else
|
127
|
+
verbose_log(" * #{step_def_file} [NOT SUPPORTED]")
|
129
128
|
end
|
130
129
|
end
|
131
130
|
|
132
|
-
def
|
133
|
-
@sted_def_loaders ||= {}
|
131
|
+
def programming_language_for(step_mother, step_def_file) # :nodoc:
|
134
132
|
if ext = File.extname(step_def_file)[1..-1]
|
135
|
-
|
136
|
-
return nil if loader == :missing
|
137
|
-
return loader if loader
|
133
|
+
return nil if @unsupported_programming_languages.index(ext)
|
138
134
|
begin
|
139
|
-
|
140
|
-
return @sted_def_loaders[ext] = loader_class.new
|
135
|
+
step_mother.load_programming_language(ext)
|
141
136
|
rescue LoadError
|
142
|
-
@
|
137
|
+
@unsupported_programming_languages << ext
|
143
138
|
nil
|
144
139
|
end
|
140
|
+
else
|
141
|
+
nil
|
145
142
|
end
|
146
|
-
nil
|
147
|
-
end
|
148
|
-
|
149
|
-
def step_def_files
|
150
|
-
main.verbose_log("Ruby files required:")
|
151
|
-
main.verbose_log(requires.map{|lib| " * #{lib}"}.join("\n"))
|
152
|
-
requires.each do |lib|
|
153
|
-
begin
|
154
|
-
require lib
|
155
|
-
rescue LoadError => e
|
156
|
-
e.message << "\nFailed to load #{lib}"
|
157
|
-
raise e
|
158
|
-
end
|
159
|
-
end
|
160
|
-
main.verbose_log("\n")
|
161
143
|
end
|
162
144
|
|
163
145
|
def enable_diffing
|
@@ -186,5 +168,3 @@ module Cucumber
|
|
186
168
|
end
|
187
169
|
end
|
188
170
|
end
|
189
|
-
|
190
|
-
Cucumber::Cli::Main.step_mother = self
|
data/lib/cucumber/cli/options.rb
CHANGED
@@ -218,6 +218,9 @@ module Cucumber
|
|
218
218
|
opts.on(DRB_FLAG, "Run features against a DRb server. (i.e. with the spork gem)") do
|
219
219
|
@options[:drb] = true
|
220
220
|
end
|
221
|
+
opts.on("--port PORT", "Specify DRb port. Ignored without --drb") do |port|
|
222
|
+
@options[:drb_port] = port
|
223
|
+
end
|
221
224
|
opts.on_tail("--version", "Show version.") do
|
222
225
|
@out_stream.puts VERSION::STRING
|
223
226
|
Kernel.exit
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Constantize
|
3
|
+
def constantize(camel_cased_word)
|
4
|
+
begin
|
5
|
+
names = camel_cased_word.split('::')
|
6
|
+
names.shift if names.empty? || names.first.empty?
|
7
|
+
|
8
|
+
constant = Object
|
9
|
+
names.each do |name|
|
10
|
+
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
11
|
+
end
|
12
|
+
constant
|
13
|
+
rescue NameError
|
14
|
+
require underscore(camel_cased_word)
|
15
|
+
retry
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Snagged from active_support
|
20
|
+
def underscore(camel_cased_word)
|
21
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
22
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
23
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
24
|
+
tr("-", "_").
|
25
|
+
downcase
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'cucumber/parser/
|
1
|
+
require 'cucumber/parser/natural_language'
|
2
2
|
require 'cucumber/filter'
|
3
3
|
|
4
4
|
module Cucumber
|
@@ -20,9 +20,9 @@ module Cucumber
|
|
20
20
|
# Parses a file and returns a Cucumber::Ast
|
21
21
|
# If +options+ contains tags, the result will
|
22
22
|
# be filtered.
|
23
|
-
def parse(options
|
23
|
+
def parse(step_mother, options)
|
24
24
|
filter = Filter.new(@lines, options)
|
25
|
-
language = Parser::
|
25
|
+
language = Parser::NaturalLanguage.get(step_mother, (lang || options[:lang] || 'en'))
|
26
26
|
language.parse(source, @path, filter)
|
27
27
|
end
|
28
28
|
|
@@ -45,8 +45,8 @@ module Cucumber
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def visit_scenario_name(keyword, name, file_colon_line, source_indent)
|
48
|
-
scenario_name = name.strip
|
49
|
-
scenario_name = "Unnamed scenario" if name
|
48
|
+
scenario_name = name.strip.delete(".\r\n")
|
49
|
+
scenario_name = "Unnamed scenario" if name.blank?
|
50
50
|
@scenario = scenario_name
|
51
51
|
@outline = keyword.include?('Scenario Outline')
|
52
52
|
@output = "Scenario#{ " outline" if @outline}: #{@scenario}\n\n"
|
@@ -96,16 +96,20 @@ module Cucumber
|
|
96
96
|
@time += duration
|
97
97
|
classname = "#{@feature_name}.#{@scenario}"
|
98
98
|
name = "#{@scenario}#{suffix}"
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
99
|
+
failed = (status == :failed || (status == :pending && @options[:strict]))
|
100
|
+
#puts "FAILED:!!#{failed}"
|
101
|
+
if status == :passed || failed
|
102
|
+
@builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
|
103
|
+
if failed
|
104
|
+
@builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
|
105
|
+
@builder.text! @output
|
106
|
+
@builder.text!(format_exception(exception)) if exception
|
107
|
+
end
|
108
|
+
@failures += 1
|
104
109
|
end
|
105
|
-
@failures += 1
|
106
110
|
end
|
111
|
+
@tests += 1
|
107
112
|
end
|
108
|
-
@tests += 1
|
109
113
|
end
|
110
114
|
|
111
115
|
def format_exception(exception)
|
@@ -97,9 +97,9 @@ module Cucumber
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def visit_examples_name(keyword, name)
|
100
|
-
names = name.empty? ? [name] : name.split("\n")
|
100
|
+
names = name.strip.empty? ? [name.strip] : name.split("\n")
|
101
101
|
@io.puts("\n #{keyword} #{names[0]}")
|
102
|
-
names[1..-1].each {|s| @io.puts " #{s}" }
|
102
|
+
names[1..-1].each {|s| @io.puts " #{s}" } unless names.empty?
|
103
103
|
@io.flush
|
104
104
|
@indent = 6
|
105
105
|
@scenario_indent = 6
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module LanguageSupport
|
3
|
+
module LanguageMethods
|
4
|
+
def before(scenario)
|
5
|
+
step_mother.begin_scenario
|
6
|
+
execute_before(scenario)
|
7
|
+
end
|
8
|
+
|
9
|
+
def after(scenario)
|
10
|
+
execute_after(scenario)
|
11
|
+
step_mother.end_scenario
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute_before(scenario)
|
15
|
+
step_mother.hooks_for(:before, scenario).each do |hook|
|
16
|
+
invoke(hook, 'Before', scenario, true)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute_after(scenario)
|
21
|
+
step_mother.hooks_for(:after, scenario).each do |hook|
|
22
|
+
invoke(hook, 'After', scenario, true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute_after_step(scenario)
|
27
|
+
step_mother.hooks_for(:after_step, scenario).each do |hook|
|
28
|
+
invoke(hook, 'AfterStep', scenario, false)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def invoke(hook, location, scenario, exception_fails_scenario)
|
35
|
+
begin
|
36
|
+
hook.invoke(location, scenario)
|
37
|
+
rescue Exception => exception
|
38
|
+
if exception_fails_scenario
|
39
|
+
scenario.fail!(exception)
|
40
|
+
else
|
41
|
+
raise
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module LanguageSupport
|
3
|
+
module StepDefinitionMethods
|
4
|
+
def step_match(name_to_match, name_to_report)
|
5
|
+
if(match = regexp.match(name_to_match))
|
6
|
+
StepMatch.new(self, name_to_match, name_to_report, match.captures)
|
7
|
+
else
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Formats the matched arguments of the associated Step. This method
|
13
|
+
# is usually called from visitors, which render output.
|
14
|
+
#
|
15
|
+
# The +format+ can either be a String or a Proc.
|
16
|
+
#
|
17
|
+
# If it is a String it should be a format string according to
|
18
|
+
# <tt>Kernel#sprinf</tt>, for example:
|
19
|
+
#
|
20
|
+
# '<span class="param">%s</span></tt>'
|
21
|
+
#
|
22
|
+
# If it is a Proc, it should take one argument and return the formatted
|
23
|
+
# argument, for example:
|
24
|
+
#
|
25
|
+
# lambda { |param| "[#{param}]" }
|
26
|
+
#
|
27
|
+
def format_args(step_name, format)
|
28
|
+
step_name.gzub(regexp, format)
|
29
|
+
end
|
30
|
+
|
31
|
+
def same_regexp?(regexp)
|
32
|
+
self.regexp == regexp
|
33
|
+
end
|
34
|
+
|
35
|
+
def backtrace_line
|
36
|
+
"#{file_colon_line}:in `#{regexp.inspect}'"
|
37
|
+
end
|
38
|
+
|
39
|
+
def text_length
|
40
|
+
regexp.inspect.jlength
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Parser
|
3
|
+
class NaturalLanguage
|
4
|
+
KEYWORD_KEYS = %w{name native encoding feature background scenario scenario_outline examples given when then but}
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def get(step_mother, lang)
|
8
|
+
languages[lang] ||= new(step_mother, lang)
|
9
|
+
end
|
10
|
+
|
11
|
+
def languages
|
12
|
+
@languages ||= {}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(step_mother, lang)
|
17
|
+
@keywords = Cucumber::LANGUAGES[lang]
|
18
|
+
raise "Language not supported: #{lang.inspect}" if @keywords.nil?
|
19
|
+
@keywords['grammar_name'] = @keywords['name'].gsub(/\s/, '')
|
20
|
+
register_adverbs(step_mother) if step_mother
|
21
|
+
end
|
22
|
+
|
23
|
+
def register_adverbs(step_mother)
|
24
|
+
adverbs = %w{given when then and but}.map{|keyword| @keywords[keyword].split('|').map{|w| w.gsub(/\s/, '')}}.flatten
|
25
|
+
step_mother.register_adverbs(adverbs)
|
26
|
+
end
|
27
|
+
|
28
|
+
def parser
|
29
|
+
return @parser if @parser
|
30
|
+
i18n_tt = File.expand_path(File.dirname(__FILE__) + '/i18n.tt')
|
31
|
+
template = File.open(i18n_tt, Cucumber.file_mode('r')).read
|
32
|
+
erb = ERB.new(template)
|
33
|
+
grammar = erb.result(binding)
|
34
|
+
Treetop.load_from_string(grammar)
|
35
|
+
@parser = Parser::I18n.const_get("#{@keywords['grammar_name']}Parser").new
|
36
|
+
def @parser.inspect
|
37
|
+
"#<#{self.class.name}>"
|
38
|
+
end
|
39
|
+
@parser
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse(source, path, filter)
|
43
|
+
feature = parser.parse_or_fail(source, path, filter)
|
44
|
+
feature.language = self if feature
|
45
|
+
feature
|
46
|
+
end
|
47
|
+
|
48
|
+
def keywords(key, raw=false)
|
49
|
+
return @keywords[key] if raw
|
50
|
+
return nil unless @keywords[key]
|
51
|
+
values = @keywords[key].split('|')
|
52
|
+
values.map{|value| "'#{value}'"}.join(" / ")
|
53
|
+
end
|
54
|
+
|
55
|
+
def incomplete?
|
56
|
+
KEYWORD_KEYS.detect{|key| @keywords[key].nil?}
|
57
|
+
end
|
58
|
+
|
59
|
+
def scenario_keyword
|
60
|
+
@keywords['scenario'].split('|')[0] + ':'
|
61
|
+
end
|
62
|
+
|
63
|
+
def but_keywords
|
64
|
+
@keywords['but'].split('|')
|
65
|
+
end
|
66
|
+
|
67
|
+
def and_keywords
|
68
|
+
@keywords['and'].split('|')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|