/
cli.rb
166 lines (144 loc) · 4.25 KB
/
cli.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
require 'optparse'
module Spinach
# The cli is a class responsible of handling all the command line interface
# logic.
#
class Cli
# @param [Array<String>] arguments
# The command line arguments
#
# @api public
def initialize(args = ARGV)
@args = args
end
# Runs all the features.
#
# @return [true, false]
# The exit status - true for success, false for failure.
#
# @api public
def run
options
return true if Spinach.config.generate
Spinach::Runner.new(feature_files).run
end
# @return [Hash]
# A hash of options separated by its type.
#
# @example
# Cli.new.options
# # => { reporter: { backtrace: true } }
#
# @api public
def options
@options ||= parse_options
end
# Uses given args to list the feature files to run. It will find a single
# feature, features in a folder and subfolders or every feature file in the
# feature path.
#
# @return [Array]
# An array with the feature file names.
#
# @api public
def feature_files
files_to_run = []
@args.each do |arg|
if arg.match(/\.feature/)
if File.exists? arg.gsub(/:\d*/, '')
files_to_run << arg
else
fail! "#{arg} could not be found"
end
elsif File.directory?(arg)
files_to_run << Dir.glob(File.join(arg, '**', '*.feature'))
else
fail! "invalid argument - #{arg}"
end
end
if !files_to_run.empty?
files_to_run.flatten
else
Dir.glob(File.join(Spinach.config[:features_path], '**', '*.feature'))
end
end
private
# Parses the arguments into options.
#
# @return [Hash]
# A hash of options separated by its type.
#
# @api private
def parse_options
config = {}
begin
OptionParser.new do |opts|
opts.on('-c', '--config_path PATH',
'Parse options from file (will get overriden by flags)') do |file|
Spinach.config[:config_path] = file
end
opts.on('-b', '--backtrace',
'Show backtrace of errors') do |show_backtrace|
config[:reporter_options] = {backtrace: show_backtrace}
end
opts.on('-t', '--tags TAG',
'Run all scenarios for given tags.') do |tag|
config[:tags] ||= []
tags = tag.delete('@').split(',')
if (config[:tags] + tags).flatten.none? { |t| t =~ /wip$/ }
tags.unshift '~wip'
end
config[:tags] << tags
end
opts.on('-g', '--generate',
'Auto-generate the feature steps files') do
config[:generate] = true
Spinach::Generators.run(feature_files)
end
opts.on_tail('--version', 'Show version') do
puts Spinach::VERSION
exit
end
opts.on('-f', '--features_path PATH',
'Path where your features will be searched for') do |path|
config[:features_path] = path
end
opts.on('-r', '--reporter CLASS_NAME',
'Formatter class name') do |class_name|
config[:reporter_class] = reporter_class(class_name)
end
end.parse!(@args)
Spinach.config.parse_from_file
config.each{|k,v| Spinach.config[k] = v}
if Spinach.config.tags.empty? ||
Spinach.config.tags.flatten.none?{ |t| t =~ /wip$/ }
Spinach.config.tags.unshift ['~wip']
end
rescue OptionParser::ParseError => exception
puts exception.message.capitalize
exit 1
end
end
# exit test run with an optional message to the user
def fail!(message=nil)
puts message if message
exit 1
end
# Builds the class name to use an output reporter.
#
# @param [String] klass
# The class name fo the reporter.
#
# @return [String]
# The full name of the reporter class.
#
# @example
# reporter_class('progress')
# # => Spinach::Reporter::Progress
#
# @api private
def reporter_class(klass)
"Spinach::Reporter::" + Spinach::Support.camelize(klass)
end
end
end