adhearsion 2.0.0.alpha2 → 2.0.0.alpha3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +16 -14
  2. data/CHANGELOG.md +17 -1
  3. data/adhearsion.gemspec +14 -13
  4. data/features/cli_basic.feature +30 -0
  5. data/features/cli_create.feature +24 -0
  6. data/features/cli_daemon.feature +21 -0
  7. data/features/cli_generate.feature +9 -0
  8. data/features/cli_start.feature +33 -0
  9. data/features/cli_stop.feature +38 -0
  10. data/features/controller_generator.feature +19 -0
  11. data/features/plugin_generator.feature +55 -0
  12. data/lib/adhearsion.rb +5 -1
  13. data/lib/adhearsion/call.rb +57 -51
  14. data/lib/adhearsion/call_controller.rb +4 -20
  15. data/lib/adhearsion/call_controller/dial.rb +34 -4
  16. data/lib/adhearsion/calls.rb +4 -1
  17. data/lib/adhearsion/cli_commands.rb +31 -6
  18. data/lib/adhearsion/configuration.rb +2 -6
  19. data/lib/adhearsion/console.rb +56 -17
  20. data/lib/adhearsion/generators.rb +53 -2
  21. data/lib/adhearsion/generators/app/app_generator.rb +2 -24
  22. data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +1 -1
  23. data/lib/adhearsion/generators/controller/controller_generator.rb +18 -0
  24. data/lib/adhearsion/generators/controller/templates/lib/controller.rb +4 -0
  25. data/lib/adhearsion/generators/controller/templates/spec/controller_spec.rb +3 -0
  26. data/lib/adhearsion/generators/generator.rb +77 -0
  27. data/lib/adhearsion/generators/plugin/plugin_generator.rb +33 -0
  28. data/lib/adhearsion/generators/plugin/templates/.gitignore +9 -0
  29. data/lib/adhearsion/generators/plugin/templates/Gemfile.tt +4 -0
  30. data/lib/adhearsion/generators/plugin/templates/README.md.tt +2 -0
  31. data/lib/adhearsion/generators/plugin/templates/Rakefile.tt +1 -0
  32. data/lib/adhearsion/generators/plugin/templates/lib/plugin-template.rb.tt +5 -0
  33. data/lib/adhearsion/generators/plugin/templates/lib/plugin-template/controller_methods.rb.tt +10 -0
  34. data/lib/adhearsion/generators/plugin/templates/lib/plugin-template/plugin.rb.tt +29 -0
  35. data/lib/adhearsion/generators/plugin/templates/lib/plugin-template/version.rb.tt +3 -0
  36. data/lib/adhearsion/generators/plugin/templates/plugin-template.gemspec.tt +35 -0
  37. data/lib/adhearsion/generators/plugin/templates/spec/plugin-template/controller_methods_spec.rb.tt +26 -0
  38. data/lib/adhearsion/generators/plugin/templates/spec/spec_helper.rb.tt +13 -0
  39. data/lib/adhearsion/initializer.rb +14 -22
  40. data/lib/adhearsion/logging.rb +25 -16
  41. data/lib/adhearsion/outbound_call.rb +3 -3
  42. data/lib/adhearsion/plugin.rb +14 -0
  43. data/lib/adhearsion/punchblock_plugin.rb +6 -1
  44. data/lib/adhearsion/punchblock_plugin/initializer.rb +8 -8
  45. data/lib/adhearsion/tasks/configuration.rb +1 -1
  46. data/lib/adhearsion/version.rb +1 -1
  47. data/spec/adhearsion/call_controller/dial_spec.rb +108 -17
  48. data/spec/adhearsion/call_controller_spec.rb +7 -64
  49. data/spec/adhearsion/call_spec.rb +48 -29
  50. data/spec/adhearsion/calls_spec.rb +7 -0
  51. data/spec/adhearsion/configuration_spec.rb +14 -14
  52. data/spec/adhearsion/console_spec.rb +124 -4
  53. data/spec/adhearsion/generators_spec.rb +17 -0
  54. data/spec/adhearsion/initializer_spec.rb +22 -18
  55. data/spec/adhearsion/logging_spec.rb +78 -48
  56. data/spec/adhearsion/outbound_call_spec.rb +6 -15
  57. data/spec/adhearsion/plugin_spec.rb +18 -0
  58. data/spec/adhearsion/process_spec.rb +10 -1
  59. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +8 -6
  60. data/spec/spec_helper.rb +5 -2
  61. data/spec/support/call_controller_test_helpers.rb +1 -1
  62. data/spec/support/initializer_stubs.rb +1 -1
  63. metadata +106 -66
  64. data/features/cli.feature +0 -108
  65. data/lib/adhearsion/initializer/logging.rb +0 -33
  66. data/spec/adhearsion/initializer/logging_spec.rb +0 -55
@@ -89,15 +89,6 @@ module Adhearsion
89
89
  end
90
90
  end
91
91
 
92
- it 'a hungup call removes itself from the active calls' do
93
- size_before = Adhearsion.active_calls.size
94
-
95
- call = Adhearsion.active_calls.from_offer offer
96
- Adhearsion.active_calls.size.should > size_before
97
- call.hangup
98
- Adhearsion.active_calls.size.should == size_before
99
- end
100
-
101
92
  it 'allows the registration of event handlers which are called when messages are delivered' do
102
93
  event = flexmock 'Event'
103
94
  event.should_receive(:foo?).and_return true
@@ -134,7 +125,6 @@ module Adhearsion
134
125
  end
135
126
 
136
127
  it "should mark the call as ended" do
137
- flexmock(subject).should_receive(:hangup).once
138
128
  subject << end_event
139
129
  subject.should_not be_active
140
130
  end
@@ -148,6 +138,22 @@ module Adhearsion
148
138
  flexmock(subject.commands).should_receive(:terminate).once
149
139
  subject << end_event
150
140
  end
141
+
142
+ it "removes itself from the active calls" do
143
+ size_before = Adhearsion.active_calls.size
144
+
145
+ Adhearsion.active_calls << subject
146
+ Adhearsion.active_calls.size.should > size_before
147
+
148
+ subject << end_event
149
+ Adhearsion.active_calls.size.should == size_before
150
+ end
151
+
152
+ it "shuts down the actor" do
153
+ subject << end_event
154
+ sleep 5.1
155
+ subject.should_not be_alive
156
+ end
151
157
  end
152
158
  end
153
159
 
@@ -203,14 +209,14 @@ module Adhearsion
203
209
 
204
210
  it "should asynchronously write the command to the Punchblock connection" do
205
211
  mock_client = flexmock('Client')
206
- flexmock(subject).should_receive(:client).once.and_return mock_client
212
+ flexmock(subject.wrapped_object).should_receive(:client).once.and_return mock_client
207
213
  mock_client.should_receive(:execute_command).once.with(mock_command, :call_id => subject.id).and_return true
208
214
  subject.write_command mock_command
209
215
  end
210
216
 
211
217
  describe "with a hungup call" do
212
218
  before do
213
- flexmock(subject).should_receive(:active?).and_return(false)
219
+ flexmock(subject.wrapped_object).should_receive(:active?).and_return(false)
214
220
  end
215
221
 
216
222
  it "should raise a Hangup exception" do
@@ -237,7 +243,7 @@ module Adhearsion
237
243
  end
238
244
 
239
245
  it "writes a command to the call" do
240
- flexmock(subject).should_receive(:write_command).once.with(message)
246
+ flexmock(subject.wrapped_object).should_receive(:write_command).once.with(message)
241
247
  subject.write_and_await_response message
242
248
  end
243
249
 
@@ -270,13 +276,25 @@ module Adhearsion
270
276
  lambda { subject.write_and_await_response message }.should raise_error Exception
271
277
  end
272
278
  end
279
+
280
+ describe "when the response times out" do
281
+ before do
282
+ message.should_receive(:response).and_raise Timeout::Error
283
+ end
284
+
285
+ it "should raise the error in the caller but not crash the actor" do
286
+ lambda { subject.write_and_await_response message }.should raise_error Timeout::Error
287
+ sleep 0.5
288
+ subject.should be_alive
289
+ end
290
+ end
273
291
  end
274
292
 
275
293
  describe "basic control commands" do
276
294
  include FlexMock::ArgumentTypes
277
295
 
278
296
  def expect_message_waiting_for_response(message)
279
- flexmock(subject).should_receive(:write_and_await_response).once.with(message).and_return(message)
297
+ flexmock(subject.wrapped_object).should_receive(:write_and_await_response).once.with(message).and_return(message)
280
298
  end
281
299
 
282
300
  describe '#accept' do
@@ -294,6 +312,14 @@ module Adhearsion
294
312
  subject.accept headers
295
313
  end
296
314
  end
315
+
316
+ describe "a second time" do
317
+ it "should only send one Accept message" do
318
+ expect_message_waiting_for_response Punchblock::Command::Accept.new
319
+ subject.accept
320
+ subject.accept
321
+ end
322
+ end
297
323
  end
298
324
 
299
325
  describe '#answer' do
@@ -344,29 +370,29 @@ module Adhearsion
344
370
  end
345
371
  end
346
372
 
347
- describe "#hangup!" do
373
+ describe "#hangup" do
348
374
  describe "if the call is not active" do
349
375
  before do
350
- flexmock(subject).should_receive(:active?).and_return false
376
+ flexmock(subject.wrapped_object).should_receive(:active?).and_return false
351
377
  end
352
378
 
353
379
  it "should do nothing and return false" do
354
380
  flexmock(subject).should_receive(:write_and_await_response).never
355
- subject.hangup!.should be false
381
+ subject.hangup.should be false
356
382
  end
357
383
  end
358
384
 
359
385
  describe "if the call is active" do
360
386
  it "should mark the call inactive" do
361
387
  expect_message_waiting_for_response Punchblock::Command::Hangup.new
362
- subject.hangup!
388
+ subject.hangup
363
389
  subject.should_not be_active
364
390
  end
365
391
 
366
392
  describe "with no headers" do
367
393
  it 'should send a Hangup message' do
368
394
  expect_message_waiting_for_response Punchblock::Command::Hangup.new
369
- subject.hangup!
395
+ subject.hangup
370
396
  end
371
397
  end
372
398
 
@@ -374,7 +400,7 @@ module Adhearsion
374
400
  it 'should send a Hangup message with the correct headers' do
375
401
  headers = {:foo => 'bar'}
376
402
  expect_message_waiting_for_response Punchblock::Command::Hangup.new(:headers => headers)
377
- subject.hangup! headers
403
+ subject.hangup headers
378
404
  end
379
405
  end
380
406
  end
@@ -484,7 +510,7 @@ module Adhearsion
484
510
  let(:mock_controller) { flexmock 'CallController' }
485
511
 
486
512
  before do
487
- flexmock subject, :write_and_await_response => true
513
+ flexmock subject.wrapped_object, :write_and_await_response => true
488
514
  end
489
515
 
490
516
  it "should call #execute on the controller instance" do
@@ -495,7 +521,7 @@ module Adhearsion
495
521
 
496
522
  it "should hangup the call after all controllers have executed" do
497
523
  flexmock(CallController).should_receive(:exec).once.with mock_controller
498
- subject.should_receive(:hangup!).once
524
+ subject.should_receive(:hangup).once
499
525
  subject.execute_controller mock_controller, latch
500
526
  latch.wait(3).should be_true
501
527
  end
@@ -548,12 +574,5 @@ module Adhearsion
548
574
  end
549
575
  end
550
576
  end
551
-
552
- describe Call::Registry do
553
- it "should set a value and retrieve it" do
554
- Adhearsion::Call::Registry[:test_value] = '123'
555
- Adhearsion::Call::Registry[:test_value].should == '123'
556
- end
557
- end
558
577
  end
559
578
  end
@@ -47,5 +47,12 @@ module Adhearsion
47
47
 
48
48
  subject.with_tag(:moderator).should == [tagged_call]
49
49
  end
50
+
51
+ describe "#<<" do
52
+ it "should allow chaining" do
53
+ subject << Call.new(new_offer) << Call.new(new_offer)
54
+ subject.size.should == 2
55
+ end
56
+ end
50
57
  end
51
58
  end
@@ -24,9 +24,9 @@ describe Adhearsion::Configuration do
24
24
  end
25
25
 
26
26
  it "should allow to update a config value" do
27
- subject.platform.automatically_accept_incoming_calls.should == true
28
- subject.platform.automatically_accept_incoming_calls = false
29
- subject.platform.automatically_accept_incoming_calls.should == false
27
+ subject.platform.environment.should == :development
28
+ subject.platform.environment = :production
29
+ subject.platform.environment.should == :production
30
30
  end
31
31
 
32
32
  it "should allow to create new config values" do
@@ -39,7 +39,7 @@ describe Adhearsion::Configuration do
39
39
  subject do
40
40
  Adhearsion::Configuration.new do
41
41
  root "foo", :desc => "Adhearsion application root folder"
42
- automatically_accept_incoming_calls false, :desc => "Adhearsion will not accept automatically any inbound call"
42
+ environment :development, :desc => "Active environment. Supported values: development, production, staging, test"
43
43
  end
44
44
  end
45
45
 
@@ -47,8 +47,8 @@ describe Adhearsion::Configuration do
47
47
  subject.platform.root.should == "foo"
48
48
  end
49
49
 
50
- it "should return the automatically_accept_incoming_calls value" do
51
- subject.platform.automatically_accept_incoming_calls.should == false
50
+ it "should return the environment value" do
51
+ subject.platform.environment.should == :development
52
52
  end
53
53
 
54
54
  it "should return a description for the platform configuration" do
@@ -56,9 +56,9 @@ describe Adhearsion::Configuration do
56
56
  end
57
57
 
58
58
  it "should allow to update a config value" do
59
- subject.platform.automatically_accept_incoming_calls.should == false
60
- subject.platform.automatically_accept_incoming_calls = true
61
- subject.platform.automatically_accept_incoming_calls.should == true
59
+ subject.platform.environment.should == :development
60
+ subject.platform.environment = :production
61
+ subject.platform.environment.should == :production
62
62
  end
63
63
 
64
64
  it "should allow to create new config values" do
@@ -87,7 +87,7 @@ describe Adhearsion::Configuration do
87
87
  end
88
88
 
89
89
  it "should allow to retrieve any platform configuration value" do
90
- subject.automatically_accept_incoming_calls.should == true
90
+ subject.environment.should == :development
91
91
  end
92
92
 
93
93
  describe "if configuration has a named environment" do
@@ -187,14 +187,14 @@ describe Adhearsion::Configuration do
187
187
  it "should retrieve a string with the platform configuration" do
188
188
  desc = subject.description :platform, :show_values => false
189
189
  desc.length.should > 0
190
- desc.should match /^.*automatically_accept_incoming_calls.*$/
190
+ desc.should match /^.*environment.*$/
191
191
  desc.should match /^.*root.*$/
192
192
  end
193
193
 
194
194
  it "should retrieve a string with the platform configuration and values" do
195
195
  desc = subject.description :platform
196
196
  desc.length.should > 0
197
- desc.should match /^.*automatically_accept_incoming_calls.*true.*$/
197
+ desc.should match /^.*environment.*:development.*$/
198
198
  desc.should match /^.*root.*$/
199
199
  end
200
200
 
@@ -284,7 +284,7 @@ describe Adhearsion::Configuration do
284
284
  it "should retrieve both platform and plugin configuration" do
285
285
  desc = subject.description :all
286
286
  desc.length.should > 0
287
- desc.should match /^.*automatically_accept_incoming_calls.*true.*$/
287
+ desc.should match /^.*environment.*:development.*$/
288
288
  desc.should match /^.*root.*$/
289
289
  desc.should match /^.*name.*user.*$/
290
290
  desc.should match /^.*password.*password.*$/
@@ -295,7 +295,7 @@ describe Adhearsion::Configuration do
295
295
  desc = subject.description :all, :show_values => false
296
296
  desc.length.should > 0
297
297
  desc.should match /^.*Configuration for platform.*$/
298
- desc.should match /^.*automatically_accept_incoming_calls.*$/
298
+ desc.should match /^.*environment.*$/
299
299
  desc.should match /^.*root.*$/
300
300
  desc.should match /^.*Configuration for my_plugin.*$/
301
301
  desc.should match /^.*name.*$/
@@ -2,22 +2,142 @@ require 'spec_helper'
2
2
 
3
3
  module Adhearsion
4
4
  describe Console do
5
+ include FlexMock::ArgumentTypes
5
6
  describe "providing hooks to include console functionality" do
6
7
  it "should allow mixing in a module globally on all CallController classes" do
7
- Adhearsion::Console.mixin TestBiscuit
8
- Adhearsion::Console.throwadogabone.should be true
8
+ Console.mixin TestBiscuit
9
+ Console.throwadogabone.should be true
9
10
  end
10
11
  end
11
12
 
12
13
  describe 'testing for libedit vs. readline' do
13
14
  it 'should return true when detecting readline' do
14
15
  flexmock(Readline).should_receive(:emacs_editing_mode).once.and_return true
15
- Adhearsion::Console.libedit?.should be false
16
+ Console.libedit?.should be false
16
17
  end
17
18
 
18
19
  it 'should return false when detecting libedit' do
19
20
  flexmock(Readline).should_receive(:emacs_editing_mode).once.and_raise NotImplementedError
20
- Adhearsion::Console.libedit?.should be true
21
+ Console.libedit?.should be true
22
+ end
23
+ end
24
+
25
+ describe "#log_level" do
26
+ context "with a value" do
27
+ it "should set the log level via Adhearsion::Logging" do
28
+ flexmock(Adhearsion::Logging).should_receive(:level=).once.with(:foo)
29
+ Console.log_level :foo
30
+ end
31
+ end
32
+
33
+ context "without a value" do
34
+ it "should return the current level as a symbol" do
35
+ Adhearsion::Logging.level = :fatal
36
+ Console.log_level.should == :fatal
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#silence!" do
42
+ it "should delegate to Adhearsion::Logging" do
43
+ flexmock(Adhearsion::Logging).should_receive(:silence!).once
44
+ Console.silence!
45
+ end
46
+ end
47
+
48
+ describe "#unsilence!" do
49
+ it "should delegate to Adhearsion::Logging" do
50
+ flexmock(Adhearsion::Logging).should_receive(:unsilence!).once
51
+ Console.unsilence!
52
+ end
53
+ end
54
+
55
+ describe "#shutdown!" do
56
+ it "should tell the process to shutdown" do
57
+ flexmock(Adhearsion::Process).should_receive(:shutdown!).once
58
+ Console.shutdown!
59
+ end
60
+ end
61
+
62
+ describe "#take" do
63
+ let(:call) { Call.new }
64
+ let(:call_id) { rand.to_s }
65
+
66
+ before do
67
+ Adhearsion.active_calls.clear!
68
+ flexmock(call).should_receive(:id => call_id)
69
+ end
70
+
71
+ context "with a call" do
72
+ it "should interact with the call" do
73
+ flexmock(Console.instance).should_receive(:interact_with_call).once.with call
74
+ Console.take call
75
+ end
76
+ end
77
+
78
+ context "with no argument" do
79
+ context "with one currently active call" do
80
+ before do
81
+ Adhearsion.active_calls << call
82
+ end
83
+
84
+ it "should interact with the current call" do
85
+ flexmock(Console.instance).should_receive(:interact_with_call).once.with call
86
+ Console.take
87
+ end
88
+ end
89
+
90
+ context "with multiple current calls" do
91
+ let(:call2) { Call.new }
92
+
93
+ before do
94
+ flexmock(call2).should_receive :id => rand.to_s
95
+ Adhearsion.active_calls << call << call2
96
+ end
97
+
98
+ it "should allow selection of the call to use" do
99
+ mock_io = StringIO.new
100
+ Console.input = mock_io
101
+ flexmock(mock_io).should_receive(:gets).once.and_return "1\n"
102
+ flexmock(Console.instance).should_receive(:interact_with_call).once.with call2
103
+ Console.take
104
+ end
105
+ end
106
+ end
107
+
108
+ context "with a call ID" do
109
+ context "if an active call with that ID exists" do
110
+ before do
111
+ Adhearsion.active_calls << call
112
+ end
113
+
114
+ it "should interact with that call" do
115
+ flexmock(Console.instance).should_receive(:interact_with_call).once.with call
116
+ Console.take call_id
117
+ end
118
+ end
119
+
120
+ context "if an active call with that ID does not exist" do
121
+ it "should log an error explaining that the call does not exist" do
122
+ flexmock(Console.logger).should_receive(:error).once.with /does not exist/
123
+ flexmock(Console.instance).should_receive(:interact_with_call).never
124
+ Console.take call_id
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ describe "#interact_with_call" do
131
+ let(:call) { Call.new }
132
+
133
+ it "should suspend the call's controller"
134
+
135
+ it "should execute an interactive call controller on the call" do
136
+ flexmock(CallController).should_receive(:exec).once.with(on do |c|
137
+ c.should be_a Console::InteractiveController
138
+ c.call.should be call
139
+ end)
140
+ Console.interact_with_call call
21
141
  end
22
142
  end
23
143
  end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ require 'adhearsion/generators'
3
+
4
+ module Adhearsion
5
+ describe Generators do
6
+ describe "storing generator mappings" do
7
+ let(:generator_key) { "example_gen" }
8
+
9
+ it "adds a generator to the mappings and returns it" do
10
+ DummyGenerator = Class.new
11
+
12
+ Generators.add_generator generator_key, DummyGenerator
13
+ Generators.mappings[generator_key].should == DummyGenerator
14
+ end
15
+ end
16
+ end
17
+ end