adhearsion 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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)