adhearsion 1.1.1 → 1.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.
Files changed (83) hide show
  1. data/.gitignore +3 -0
  2. data/.rspec +3 -0
  3. data/CHANGELOG +12 -0
  4. data/README.markdown +1 -10
  5. data/Rakefile +6 -28
  6. data/adhearsion.gemspec +21 -38
  7. data/app_generators/ahn/ahn_generator.rb +3 -4
  8. data/app_generators/ahn/templates/config/environment.rb +4 -0
  9. data/app_generators/ahn/templates/config/startup.rb +11 -5
  10. data/app_generators/ahn/templates/script/ahn +8 -0
  11. data/lib/adhearsion/cli.rb +5 -298
  12. data/lib/adhearsion/commands.rb +308 -0
  13. data/lib/adhearsion/events_support.rb +0 -20
  14. data/lib/adhearsion/initializer/asterisk.rb +0 -1
  15. data/lib/adhearsion/initializer/configuration.rb +4 -1
  16. data/lib/adhearsion/logging.rb +18 -3
  17. data/lib/adhearsion/script_ahn_loader.rb +30 -0
  18. data/lib/adhearsion/tasks/testing.rb +39 -8
  19. data/lib/adhearsion/version.rb +2 -2
  20. data/lib/adhearsion/voip/asterisk/agi_server.rb +15 -8
  21. data/lib/adhearsion/voip/asterisk/commands.rb +340 -86
  22. data/lib/adhearsion/voip/asterisk/manager_interface.rb +0 -2
  23. data/lib/adhearsion/voip/call.rb +11 -3
  24. data/lib/adhearsion/voip/commands.rb +5 -1
  25. data/lib/adhearsion/voip/dial_plan.rb +4 -0
  26. data/lib/theatre/invocation.rb +3 -0
  27. data/spec/{ahn_command_spec.rb → adhearsion/cli_spec.rb} +11 -0
  28. data/spec/{component_manager_spec.rb → adhearsion/component_manager_spec.rb} +0 -0
  29. data/spec/{constants_spec.rb → adhearsion/constants_spec.rb} +0 -0
  30. data/spec/{drb_spec.rb → adhearsion/drb_spec.rb} +0 -0
  31. data/spec/{fixtures → adhearsion/fixtures}/dialplan.rb +0 -0
  32. data/spec/{foundation → adhearsion/foundation}/event_socket_spec.rb +0 -0
  33. data/spec/{host_definitions_spec.rb → adhearsion/host_definitions_spec.rb} +0 -0
  34. data/spec/{initializer → adhearsion/initializer}/configuration_spec.rb +21 -0
  35. data/spec/{initializer → adhearsion/initializer}/loading_spec.rb +0 -0
  36. data/spec/{initializer → adhearsion/initializer}/paths_spec.rb +0 -0
  37. data/spec/{initialization_spec.rb → adhearsion/initializer_spec.rb} +0 -0
  38. data/spec/{logging_spec.rb → adhearsion/logging_spec.rb} +6 -0
  39. data/spec/{relationship_properties_spec.rb → adhearsion/relationship_properties_spec.rb} +0 -0
  40. data/spec/{voip → adhearsion/voip}/asterisk/agi_server_spec.rb +0 -0
  41. data/spec/{voip → adhearsion/voip}/asterisk/ami/ami_spec.rb +1 -0
  42. data/spec/{voip → adhearsion/voip}/asterisk/ami/lexer/ami_fixtures.yml +0 -0
  43. data/spec/{voip → adhearsion/voip}/asterisk/ami/lexer/lexer_story +0 -0
  44. data/spec/{voip → adhearsion/voip}/asterisk/ami/lexer/lexer_story.rb +0 -0
  45. data/spec/{voip → adhearsion/voip}/asterisk/ami/lexer/story_helper.rb +0 -0
  46. data/spec/{voip → adhearsion/voip}/asterisk/commands_spec.rb +549 -47
  47. data/spec/{voip → adhearsion/voip}/asterisk/config_file_generators/agents_spec.rb +0 -0
  48. data/spec/{voip → adhearsion/voip}/asterisk/config_file_generators/queues_spec.rb +0 -0
  49. data/spec/{voip → adhearsion/voip}/asterisk/config_file_generators/voicemail_spec.rb +0 -0
  50. data/spec/{voip → adhearsion/voip}/asterisk/config_manager_spec.rb +0 -0
  51. data/spec/{voip → adhearsion/voip}/asterisk/menu_command/calculated_match_spec.rb +0 -0
  52. data/spec/{voip → adhearsion/voip}/asterisk/menu_command/matchers_spec.rb +0 -0
  53. data/spec/{voip → adhearsion/voip}/call_routing_spec.rb +0 -0
  54. data/spec/{voip → adhearsion/voip}/dialplan_manager_spec.rb +0 -0
  55. data/spec/{voip → adhearsion/voip}/dsl/dialing_dsl_spec.rb +1 -1
  56. data/spec/{voip → adhearsion/voip}/dsl/dispatcher_spec.rb +0 -0
  57. data/spec/{voip → adhearsion/voip}/dsl/dispatcher_spec_helper.rb +0 -0
  58. data/spec/{voip → adhearsion/voip}/dsl/parser_spec.rb +0 -0
  59. data/spec/{voip → adhearsion/voip}/freeswitch/basic_connection_manager_spec.rb +0 -0
  60. data/spec/{voip → adhearsion/voip}/freeswitch/inbound_connection_manager_spec.rb +0 -0
  61. data/spec/{voip → adhearsion/voip}/freeswitch/oes_server_spec.rb +0 -0
  62. data/spec/{voip → adhearsion/voip}/numerical_string_spec.rb +0 -0
  63. data/spec/{voip → adhearsion/voip}/phone_number_spec.rb +0 -0
  64. data/spec/spec_helper.rb +36 -89
  65. data/spec/support/initializer_stubs.rb +47 -0
  66. data/spec/support/the_following_code.rb +3 -0
  67. data/{theatre-spec → spec/theatre}/dsl_examples/simple_before_call.rb +0 -0
  68. data/{theatre-spec → spec/theatre}/dsl_spec.rb +26 -0
  69. data/{theatre-spec → spec/theatre}/invocation_spec.rb +6 -10
  70. data/{theatre-spec → spec/theatre}/namespace_spec.rb +0 -0
  71. data/{theatre-spec → spec/theatre}/spec_helper_spec.rb +0 -0
  72. data/{theatre-spec → spec/theatre}/theatre_class_spec.rb +2 -5
  73. metadata +254 -271
  74. data/app_generators/ahn/templates/components/disabled/sandbox/sandbox.rb +0 -104
  75. data/app_generators/ahn/templates/components/disabled/sandbox/sandbox.yml +0 -2
  76. data/lib/adhearsion/voip/asterisk/super_manager.rb +0 -19
  77. data/spec/silence.rb +0 -10
  78. data/spec/voip/asterisk/ami/old_tests.rb +0 -204
  79. data/spec/voip/asterisk/ami/super_manager/super_manager_story +0 -25
  80. data/spec/voip/asterisk/ami/super_manager/super_manager_story.rb +0 -15
  81. data/spec/voip/asterisk/ami/super_manager/super_manager_story_helper.rb +0 -5
  82. data/theatre-spec/dsl_examples/dynamic_stomp.rb +0 -7
  83. data/theatre-spec/spec_helper.rb +0 -37
@@ -0,0 +1,308 @@
1
+ require 'fileutils'
2
+ require 'adhearsion/script_ahn_loader'
3
+
4
+ module Adhearsion
5
+ module CLI
6
+ module AhnCommand
7
+ USAGE = <<USAGE
8
+ Usage:
9
+ ahn create /path/to/directory
10
+ ahn start [console|daemon] [/path/to/directory]
11
+ ahn version|-v|--v|-version|--version
12
+ ahn help|-h|--h|--help|-help
13
+
14
+ ahn enable component COMPONENT_NAME
15
+ ahn disable component COMPONENT_NAME
16
+ ahn create component COMPONENT_NAME
17
+ USAGE
18
+ class << self
19
+
20
+ def execute!
21
+ if ARGV.first == 'start' && !(ScriptAhnLoader.in_ahn_application? || ScriptAhnLoader.in_ahn_application_subdirectory?)
22
+ args = parse_arguments
23
+ Dir.chdir args[1] do
24
+ args = args.compact.map(&:to_s)
25
+ args[1], args[2] = args[2], '.'
26
+ ScriptAhnLoader.exec_script_ahn! args
27
+ end
28
+ end
29
+ CommandHandler.send(*parse_arguments)
30
+ rescue CommandHandler::CLIException => error
31
+ fail_and_print_usage error
32
+ end
33
+
34
+ ##
35
+ # Provides a small abstraction of Kernel::abort().
36
+ #
37
+ def fail_and_print_usage(error)
38
+ Kernel.abort "#{error.message}\n\n#{USAGE}"
39
+ end
40
+
41
+ def parse_arguments(args=ARGV.clone)
42
+ action = args.shift
43
+ case action
44
+ when /^-?-?h(elp)?$/, nil then [:help]
45
+ when /^-?-?v(ersion)?$/ then [:version]
46
+ when "create"
47
+ [:create, *args]
48
+ when 'start'
49
+ pid_file_regexp = /^--pid-file=(.+)$/
50
+ if args.size > 3
51
+ raise CommandHandler::CLIException, "Too many arguments supplied!" if args.size > 3
52
+ else
53
+ pid_file = nil
54
+ pid_file = args.pop[pid_file_regexp, 1] if args.last =~ pid_file_regexp
55
+ raise CommandHandler::CLIException, "Unrecognized final argument #{args.last}" unless args.size <= 2
56
+ end
57
+
58
+ if args.size == 2
59
+ path = args.last
60
+ if args.first =~ /foreground|daemon|console/
61
+ mode = args.first.to_sym
62
+ else
63
+ raise CommandHandler::CLIException, "Invalid start mode requested: #{args.first}"
64
+ end
65
+ elsif args.size == 1
66
+ path, mode = args.first, :foreground
67
+ else
68
+ raise CommandHandler::CLIException, "Invalid format for the start CLI command!"
69
+ end
70
+ [:start, path, mode, pid_file]
71
+ when '-'
72
+ [:start, Dir.pwd]
73
+ when "enable", "disable"
74
+ if args.size == 1
75
+ raise CommandHandler::UnknownCommand, "Must supply an argument for what you wish to #{action}"
76
+ elsif args.size == 2
77
+ [action, *args]
78
+ else
79
+ raise CommandHandler::UnknownCommand, "Too many arguments supplied!"
80
+ end
81
+ else
82
+ [action, *args]
83
+ end
84
+ end
85
+ end
86
+
87
+ module CommandHandler
88
+ class << self
89
+
90
+ def create(*args)
91
+ if args.size.zero?
92
+ raise CommandHandler::UnknownCommand.new("Must specify something to create!")
93
+ elsif args.size == 1
94
+ # We're creating a project
95
+ path = args.first
96
+ require 'rubigen'
97
+ require 'rubigen/scripts/generate'
98
+ source = RubiGen::PathSource.new(:application,
99
+ File.join(File.dirname(__FILE__), "../../app_generators"))
100
+ RubiGen::Base.reset_sources
101
+ RubiGen::Base.append_sources source
102
+ RubiGen::Scripts::Generate.new.run([path], :generator => 'ahn')
103
+ elsif args.size == 2
104
+ # We're creating a feature (e.g. a component)
105
+ feature_type, component_name = args
106
+
107
+ if feature_type != "component"
108
+ # At the moment, only components can be created.
109
+ raise CommandHandler::UnknownCommand.new("Don't know how to create '#{feature_type}'")
110
+ end
111
+
112
+ if component_name !~ /^[a-z][\w_]+$/
113
+ raise CommandHandler::ComponentError.new("Component name must be lowercase alphanumeric characters " +
114
+ "and begin with a character")
115
+ end
116
+
117
+ app_path = PathString.from_application_subdirectory Dir.pwd
118
+
119
+ if app_path.nil?
120
+ new_component_dir = File.join Dir.pwd, component_name
121
+ else
122
+ puts "Adhearsion application detected. Creating new component at components/#{component_name}"
123
+ new_component_dir = File.join app_path, "components", component_name
124
+ end
125
+
126
+ raise ComponentError.new("Component #{component_name} already exists!") if File.exists?(new_component_dir)
127
+
128
+ # Everything's good. Let's create the component
129
+ Dir.mkdir new_component_dir
130
+
131
+ # Initial component code file
132
+ Dir.mkdir File.join(new_component_dir, "lib")
133
+ fn = File.join("lib", "#{component_name}.rb")
134
+ puts "- #{fn}: Initial component code file"
135
+ File.open(File.join(new_component_dir, fn),"w") do |file|
136
+ file.puts <<-RUBY
137
+ # See http://docs.adhearsion.com for more information on how to write components or
138
+ # look at the examples in newly-created projects.
139
+ RUBY
140
+ end
141
+
142
+ # Component configuration
143
+ Dir.mkdir File.join(new_component_dir, "config")
144
+ fn = File.join("config", "#{component_name}.yml")
145
+ puts "- #{fn}: Example component configuration YAML"
146
+ File.open(File.join(new_component_dir, fn),"w") do |file|
147
+ file.puts '# You can use this file for component-specific configuration.'
148
+ end
149
+
150
+ # Component example gemspec
151
+ fn = File.join("#{component_name}.gemspec")
152
+ puts "- #{fn}: Example component gemspec"
153
+ File.open(File.join(new_component_dir, fn), "w") do |file|
154
+ file.puts <<-RUBY
155
+ GEM_FILES = %w{
156
+ #{component_name}.gemspec
157
+ lib/#{component_name}.rb
158
+ config/#{component_name}.yml
159
+ }
160
+
161
+ Gem::Specification.new do |s|
162
+ s.name = "#{component_name}"
163
+ s.version = "0.0.1"
164
+
165
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
166
+ s.authors = ["Your Name Here!"]
167
+
168
+ s.date = Date.today.to_s
169
+ s.description = "This Adhearsion component gem has not yet been described."
170
+ s.email = "noreply@example.com"
171
+
172
+ s.files = GEM_FILES
173
+
174
+ s.has_rdoc = false
175
+ s.homepage = "http://adhearsion.com"
176
+ s.require_paths = ["lib"]
177
+ s.rubygems_version = "1.2.0"
178
+ s.summary = "This Adhearsion component gem has no summary."
179
+
180
+ s.specification_version = 2
181
+ end
182
+ RUBY
183
+ end
184
+
185
+ # Component example spec
186
+ Dir.mkdir File.join(new_component_dir, "spec")
187
+ fn = File.join("spec", "#{component_name}_spec.rb")
188
+ puts "- #{fn}: Example component spec"
189
+ File.open(File.join(new_component_dir, fn), "w") do |file|
190
+ file.puts <<-RUBY
191
+ require 'rubygems'
192
+ require 'bundler'
193
+ Bundler.setup
194
+ Bundler.require
195
+
196
+ require 'adhearsion/component_manager/spec_framework'
197
+
198
+ component_name.upcase = ComponentTester.new("#{component_name}", File.dirname(__FILE__) + "/../..")
199
+ RUBY
200
+ end
201
+ puts "Created blank component '#{component_name}' at #{new_component_dir}"
202
+ else
203
+ raise CommandHandler::UnknownCommand.new("Provided too many arguments to 'create'")
204
+ end
205
+ end
206
+
207
+ def start(path, mode=:foreground, pid_file=nil)
208
+ raise PathInvalid, path unless File.exists? path + "/.ahnrc"
209
+ Adhearsion::Initializer.start path, :mode => mode, :pid_file => pid_file
210
+ end
211
+
212
+ def version
213
+ puts "Adhearsion v#{Adhearsion::VERSION::STRING}"
214
+ end
215
+
216
+ def help
217
+ puts USAGE
218
+ end
219
+
220
+ def enable(type, name)
221
+ case type
222
+ when "component"
223
+ app_path = PathString.from_application_subdirectory Dir.pwd
224
+ if app_path
225
+ disabled_component_path = File.join app_path, "components", "disabled", name
226
+ disabled_components_path = File.join app_path, "components", "disabled"
227
+ enabled_component_path = File.join app_path, "components", name
228
+ if File.directory? disabled_component_path
229
+ FileUtils.mv disabled_component_path, enabled_component_path
230
+ puts "Enabled component #{name}"
231
+ elsif File.directory? enabled_component_path
232
+ raise ComponentError.new("This component is already enabled.")
233
+ elsif !File.directory? disabled_components_path
234
+ raise ComponentError.new("There is no components/disabled directory!")
235
+ else
236
+ raise ComponentError.new("The requested component was not found.")
237
+ end
238
+ else
239
+ raise PathInvalid.new(Dir.pwd)
240
+ end
241
+ else
242
+ raise UnknownCommand.new("enable #{type}")
243
+ end
244
+ end
245
+
246
+ def disable(type, name)
247
+ case type
248
+ when "component"
249
+ app_path = PathString.from_application_subdirectory Dir.pwd
250
+ if app_path
251
+ disabled_dir = File.join app_path, "components", "disabled"
252
+
253
+ disabled_component_path = File.join disabled_dir, name
254
+ enabled_component_path = File.join app_path, "components", name
255
+
256
+ Dir.mkdir disabled_dir unless File.directory?(disabled_dir)
257
+
258
+ if File.directory? enabled_component_path
259
+ if File.directory?(disabled_component_path)
260
+ raise ComponentError.new("There is already a disabled component at #{disabled_component_path}")
261
+ else
262
+ FileUtils.mv enabled_component_path, disabled_component_path
263
+ puts "Disabled component #{name}"
264
+ end
265
+ else
266
+ raise ComponentError.new("Could not find component #{name} at #{enabled_component_path} !")
267
+ end
268
+ else
269
+ raise PathInvalid.new(Dir.pwd)
270
+ end
271
+ else
272
+ raise UnknownCommand.new("disable #{type}")
273
+ end
274
+ end
275
+
276
+ def method_missing(action, *args)
277
+ raise UnknownCommand, [action, *args] * " "
278
+ end
279
+
280
+ private
281
+
282
+ end
283
+
284
+ class CLIException < StandardError; end
285
+
286
+ class UnknownCommand < CLIException
287
+ def initialize(cmd)
288
+ super "Unknown command: #{cmd}"
289
+ end
290
+ end
291
+
292
+ class ComponentError < CLIException; end
293
+
294
+ class UnknownProject < CLIException
295
+ def initialize(project)
296
+ super "Application #{project} does not exist! Have you installed it?"
297
+ end
298
+ end
299
+
300
+ class PathInvalid < CLIException
301
+ def initialize(path)
302
+ super "Directory #{path} does not belong to an Adhearsion project!"
303
+ end
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end
@@ -1,25 +1,5 @@
1
- %w[theatre jicksta-theatre].each do |theatre_gem_name|
2
- # Some older versions of the master branch required the theatre gem be installed. This is deprecation logic to inform the
3
- # user to uninstall the gem if they happened to have used theatre in the past.
4
- begin
5
- gem theatre_gem_name
6
- rescue LoadError
7
- # Good. It should not be installed.
8
- else
9
- abort <<-MESSAGE
10
- It seems you have the "#{theatre_gem_name}" gem installed. As of Dec. 7th, 2008 Theatre has been rolled into Adhearsion
11
- and will be distributed with it.
12
-
13
- Please uninstall the gem by doing "sudo gem uninstall #{theatre_gem_name}".
14
-
15
- You will not need to install it again in the future. Sorry for the inconvenience.
16
- MESSAGE
17
- end
18
- end
19
-
20
1
  require 'theatre'
21
2
 
22
-
23
3
  module Adhearsion
24
4
  module Events
25
5
 
@@ -41,7 +41,6 @@ module Adhearsion
41
41
  ahn_log.warn "Asterisk.manager_interface already initialized?"
42
42
  else
43
43
  def manager_interface
44
- # ahn_log.ami.warn "Warning! This Asterisk.manager_interface() notation is for Adhearsion version 0.8.0 only. Subsequent versions of Adhearsion will use a feature called SuperManager. Migrating to use SuperManager will be very simple. See http://docs.adhearsion.com/AMI for more information."
45
44
  Adhearsion::Initializer::AsteriskInitializer.ami_client
46
45
  end
47
46
  end
@@ -66,7 +66,10 @@ module Adhearsion
66
66
  end
67
67
 
68
68
  def logging(options)
69
- Adhearsion::Logging.logging_level = options[:level]
69
+ Adhearsion::Logging.logging_level = options[:level] if options.has_key? :level
70
+ Adhearsion::Logging::AdhearsionLogger.outputters = Array(options[:outputters]) if options.has_key? :outputters
71
+ Adhearsion::Logging::AdhearsionLogger.formatters = Array(options[:formatters]) if options.has_key? :formatters
72
+ Adhearsion::Logging::AdhearsionLogger.formatters = Array(options[:formatter]) * Adhearsion::Logging::AdhearsionLogger.outputters.count if options.has_key? :formatter
70
73
  end
71
74
 
72
75
  def add_component(*list)
@@ -40,6 +40,10 @@ module Adhearsion
40
40
  @@outputters = [Log4r::Outputter.stdout]
41
41
 
42
42
  class << self
43
+ def sanitized_logger_name(name)
44
+ name.to_s.gsub(/\W/, '').downcase
45
+ end
46
+
43
47
  def outputters
44
48
  @@outputters
45
49
  end
@@ -47,6 +51,17 @@ module Adhearsion
47
51
  def outputters=(other)
48
52
  @@outputters = other
49
53
  end
54
+
55
+ def formatters
56
+ @@outputters.map &:formatter
57
+ end
58
+
59
+ def formatters=(other)
60
+ other.each_with_index do |formatter, i|
61
+ outputter = @@outputters[i]
62
+ outputter.formatter = formatter if outputter
63
+ end
64
+ end
50
65
  end
51
66
 
52
67
  def initialize(*args)
@@ -59,8 +74,8 @@ module Adhearsion
59
74
  end
60
75
 
61
76
  def method_missing(logger_name, *args, &block)
62
- define_logging_method(logger_name, self.class.new(logger_name.to_s))
63
- send(logger_name, *args, &block)
77
+ define_logging_method logger_name, self.class.new(logger_name.to_s)
78
+ send self.class.sanitized_logger_name(logger_name), *args, &block
64
79
  end
65
80
 
66
81
  private
@@ -69,7 +84,7 @@ module Adhearsion
69
84
  # Can't use Module#define_method() because blocks in Ruby 1.8.x can't
70
85
  # have their own block arguments.
71
86
  self.class.class_eval(<<-CODE, __FILE__, __LINE__)
72
- def #{name}(*args, &block)
87
+ def #{self.class.sanitized_logger_name name}(*args, &block)
73
88
  logger = Log4r::Logger['#{name}']
74
89
  if args.any? || block_given?
75
90
  logger.info(*args, &block)
@@ -0,0 +1,30 @@
1
+ require 'pathname'
2
+ require 'rbconfig'
3
+
4
+ module Adhearsion
5
+ module ScriptAhnLoader
6
+ RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"]
7
+ SCRIPT_AHN = File.join('script', 'ahn')
8
+
9
+ def self.exec_script_ahn!(args = ARGV)
10
+ cwd = Dir.pwd
11
+ return unless in_ahn_application? || in_ahn_application_subdirectory?
12
+ exec RUBY, SCRIPT_AHN, *args if in_ahn_application?
13
+ Dir.chdir("..") do
14
+ # Recurse in a chdir block: if the search fails we want to be sure
15
+ # the application is generated in the original working directory.
16
+ exec_script_ahn! unless cwd == Dir.pwd
17
+ end
18
+ rescue SystemCallError
19
+ # could not chdir, no problem just return
20
+ end
21
+
22
+ def self.in_ahn_application?
23
+ File.exists? SCRIPT_AHN
24
+ end
25
+
26
+ def self.in_ahn_application_subdirectory?(path = Pathname.new(Dir.pwd))
27
+ File.exists?(File.join(path, SCRIPT_AHN)) || !path.root? && in_ahn_application_subdirectory?(path.parent)
28
+ end
29
+ end
30
+ end
@@ -1,10 +1,21 @@
1
- namespace:test do
1
+ begin
2
+ require 'rspec/core/rake_task'
3
+ rescue LoadError
4
+ end
5
+
6
+ desc 'Run app tests, including components'
7
+ task :test => 'test:component'
8
+
9
+ desc 'Run app specs, including components'
10
+ task :spec => :test
11
+
12
+ namespace :test do
2
13
  desc "Run tests for a component specified by COMPONENT=<component_name>. If no component is specified, tests will be executed for all components"
3
14
  task :component do
4
15
  component = ENV['COMPONENT']
5
16
  components_to_test = component.nil? ? all_component_directories : [full_path_for(component)]
6
17
  components_to_test.each do |component_name|
7
- setup_and_execute(component_name)
18
+ setup_and_execute component_name
8
19
  end
9
20
  end
10
21
 
@@ -12,15 +23,35 @@ namespace:test do
12
23
 
13
24
  def setup_and_execute(component_path)
14
25
  task = create_test_task_for(component_path)
15
- Rake::Task[task.name].execute
26
+ Rake::Task[task.name].execute if task
16
27
  end
17
28
 
18
29
  def create_test_task_for(component_path)
19
- Rake::TestTask.new(task_name_for(component_path)) do |t|
20
- t.libs = ["lib", "test"].map{|subdir| File.join(component_path, subdir)}
21
- t.test_files = FileList["#{component_path}/test/test_*.rb"]
22
- t.verbose = true
23
- end
30
+ case task_type_for(component_path)
31
+ when :test_unit
32
+ Rake::TestTask.new task_name_for(component_path) do |t|
33
+ t.libs = ["lib", "test"].map { |subdir| File.join component_path, subdir }
34
+ t.test_files = FileList["#{component_path}/test/test_*.rb"]
35
+ t.verbose = true
36
+ end
37
+ when :rspec
38
+ if defined?(RSpec)
39
+ RSpec::Core::RakeTask.new task_name_for(component_path) do |spec|
40
+ spec.pattern = "#{component_path}/spec/**/*_spec.rb"
41
+ spec.rspec_opts = '--color'
42
+ end
43
+ else
44
+ puts "It looks like you have components with RSpec tests. You can run them by adding RSpec to your Gemfile."
45
+ end
46
+ end
47
+ end
48
+
49
+ def task_type_for(component_path)
50
+ if Dir.exists?("#{component_path}/test")
51
+ :test_unit
52
+ elsif Dir.exists?("#{component_path}/spec")
53
+ :rspec
54
+ end
24
55
  end
25
56
 
26
57
  def task_name_for(component_path)