adhearsion 2.1.3 → 2.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.
- data/CHANGELOG.md +87 -0
- data/Guardfile +1 -1
- data/Rakefile +1 -2
- data/adhearsion.gemspec +1 -1
- data/features/cli_create.feature +1 -0
- data/features/step_definitions/cli_steps.rb +0 -10
- data/lib/adhearsion.rb +11 -0
- data/lib/adhearsion/call.rb +27 -12
- data/lib/adhearsion/call_controller.rb +1 -1
- data/lib/adhearsion/call_controller/dial.rb +3 -1
- data/lib/adhearsion/call_controller/input.rb +4 -4
- data/lib/adhearsion/call_controller/menu_dsl.rb +1 -0
- data/lib/adhearsion/call_controller/menu_dsl/array_match_calculator.rb +26 -0
- data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +2 -14
- data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +6 -6
- data/lib/adhearsion/call_controller/output.rb +20 -14
- data/lib/adhearsion/call_controller/output/abstract_player.rb +5 -5
- data/lib/adhearsion/call_controller/output/formatter.rb +68 -68
- data/lib/adhearsion/call_controller/record.rb +91 -28
- data/lib/adhearsion/call_controller/utility.rb +12 -5
- data/lib/adhearsion/calls.rb +1 -1
- data/lib/adhearsion/configuration.rb +4 -0
- data/lib/adhearsion/events.rb +2 -1
- data/lib/adhearsion/generators/app/app_generator.rb +2 -2
- data/lib/adhearsion/generators/app/templates/Gemfile.erb +4 -0
- data/lib/adhearsion/generators/app/templates/Rakefile +5 -0
- data/lib/adhearsion/generators/app/templates/lib/simon_game.rb +3 -0
- data/lib/adhearsion/generators/app/templates/rspec +2 -0
- data/lib/adhearsion/generators/app/templates/spec/call_controllers/simon_game_spec.rb +142 -0
- data/lib/adhearsion/generators/controller/templates/lib/controller.rb +1 -1
- data/lib/adhearsion/generators/controller/templates/spec/controller_spec.rb +2 -0
- data/lib/adhearsion/initializer.rb +3 -2
- data/lib/adhearsion/outbound_call.rb +5 -2
- data/lib/adhearsion/router/route.rb +13 -2
- data/lib/adhearsion/rspec.rb +1 -1
- data/lib/adhearsion/statistics.rb +138 -0
- data/lib/adhearsion/tasks/environment.rb +1 -1
- data/lib/adhearsion/version.rb +1 -1
- data/spec/adhearsion/call_controller/dial_spec.rb +26 -0
- data/spec/adhearsion/call_controller/input_spec.rb +13 -1
- data/spec/adhearsion/call_controller/menu_dsl/array_match_calculator_spec.rb +76 -0
- data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +8 -6
- data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +4 -4
- data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +6 -6
- data/spec/adhearsion/call_controller/output/formatter_spec.rb +3 -5
- data/spec/adhearsion/call_controller/output_spec.rb +59 -25
- data/spec/adhearsion/call_controller/record_spec.rb +123 -2
- data/spec/adhearsion/call_controller/utility_spec.rb +31 -11
- data/spec/adhearsion/call_spec.rb +77 -36
- data/spec/adhearsion/calls_spec.rb +13 -0
- data/spec/adhearsion/initializer_spec.rb +7 -0
- data/spec/adhearsion/outbound_call_spec.rb +14 -0
- data/spec/adhearsion/punchblock_plugin_spec.rb +5 -2
- data/spec/adhearsion/router/openended_route_spec.rb +2 -1
- data/spec/adhearsion/router/route_spec.rb +9 -1
- data/spec/adhearsion/router/unaccepting_route_spec.rb +2 -1
- data/spec/adhearsion/statistics/dump_spec.rb +38 -0
- data/spec/adhearsion/statistics_spec.rb +61 -0
- data/spec/adhearsion_spec.rb +21 -1
- data/spec/spec_helper.rb +2 -0
- metadata +16 -7
@@ -10,15 +10,15 @@ module Adhearsion
|
|
10
10
|
it "matching with a Range should handle the case of two potential matches in the range" do
|
11
11
|
digits_that_begin_with_eleven = [110..119, 1100..1111].map { |x| Array(x) }.flatten
|
12
12
|
calculator = RangeMatchCalculator.new 11..1111, :match_payload_doesnt_matter
|
13
|
-
match = calculator.match 11
|
14
|
-
match.exact_matches.should be == [11]
|
13
|
+
match = calculator.match '11'
|
14
|
+
match.exact_matches.should be == ['11']
|
15
15
|
match.potential_matches.should be == digits_that_begin_with_eleven
|
16
16
|
end
|
17
17
|
|
18
18
|
it "return values of #match should be an instance of CalculatedMatch" do
|
19
19
|
calculator = RangeMatchCalculator.new 1..9, :match_payload_doesnt_matter
|
20
|
-
calculator.match(0).should be_an_instance_of CalculatedMatch
|
21
|
-
calculator.match(1000).should be_an_instance_of CalculatedMatch
|
20
|
+
calculator.match('0').should be_an_instance_of CalculatedMatch
|
21
|
+
calculator.match('1000').should be_an_instance_of CalculatedMatch
|
22
22
|
end
|
23
23
|
|
24
24
|
it "returns a failed match if the query is not numeric or coercible to numeric" do
|
@@ -14,13 +14,13 @@ module Adhearsion
|
|
14
14
|
calculator = StringMatchCalculator.new str, match_payload
|
15
15
|
|
16
16
|
match_case = calculator.match str[0,2]
|
17
|
-
match_case.
|
18
|
-
match_case.
|
17
|
+
match_case.should_not be_exact_match
|
18
|
+
match_case.should be_potential_match
|
19
19
|
match_case.potential_matches.should be == [str]
|
20
20
|
|
21
21
|
match_case = calculator.match str
|
22
|
-
match_case.
|
23
|
-
match_case.
|
22
|
+
match_case.should be_exact_match
|
23
|
+
match_case.should_not be_potential_match
|
24
24
|
match_case.exact_matches.should be == [str]
|
25
25
|
end
|
26
26
|
end
|
@@ -29,9 +29,9 @@ module Adhearsion
|
|
29
29
|
%w[* #].each do |special_digit|
|
30
30
|
calculator = StringMatchCalculator.new(special_digit, match_payload)
|
31
31
|
match_case = calculator.match special_digit
|
32
|
-
match_case.potential_match?.should_not be true
|
33
|
-
match_case.exact_match?.should be true
|
34
32
|
match_case.exact_matches.first.should be == special_digit
|
33
|
+
match_case.should be_exact_match
|
34
|
+
match_case.should_not be_potential_match
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -6,9 +6,7 @@ module Adhearsion
|
|
6
6
|
class CallController
|
7
7
|
module Output
|
8
8
|
describe Formatter do
|
9
|
-
|
10
|
-
|
11
|
-
describe ".ssml_for" do
|
9
|
+
describe "#ssml_for" do
|
12
10
|
let(:prompt) { "Please stand by" }
|
13
11
|
|
14
12
|
let(:ssml) do
|
@@ -24,7 +22,7 @@ module Adhearsion
|
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
|
-
describe "
|
25
|
+
describe "#ssml_for_collection" do
|
28
26
|
let(:collection) { ["/foo/bar.wav", 1, Time.now] }
|
29
27
|
let :ssml do
|
30
28
|
file = collection[0]
|
@@ -42,7 +40,7 @@ module Adhearsion
|
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
45
|
-
describe "
|
43
|
+
describe "#detect_type" do
|
46
44
|
it "detects an HTTP path" do
|
47
45
|
http_path = "http://adhearsion.com/sounds/hello.mp3"
|
48
46
|
subject.detect_type(http_path).should be :audio
|
@@ -7,12 +7,12 @@ module Adhearsion
|
|
7
7
|
describe Output do
|
8
8
|
include CallControllerTestHelpers
|
9
9
|
|
10
|
-
def expect_ssml_output(ssml)
|
11
|
-
expect_component_execution Punchblock::Component::Output.new(:ssml => ssml)
|
10
|
+
def expect_ssml_output(ssml, options = {})
|
11
|
+
expect_component_execution Punchblock::Component::Output.new(options.merge(:ssml => ssml))
|
12
12
|
end
|
13
13
|
|
14
|
-
def expect_async_ssml_output(ssml)
|
15
|
-
expect_message_waiting_for_response Punchblock::Component::Output.new(:ssml => ssml)
|
14
|
+
def expect_async_ssml_output(ssml, options = {})
|
15
|
+
expect_message_waiting_for_response Punchblock::Component::Output.new(options.merge(:ssml => ssml))
|
16
16
|
end
|
17
17
|
|
18
18
|
describe "#player" do
|
@@ -350,6 +350,25 @@ module Adhearsion
|
|
350
350
|
end
|
351
351
|
end
|
352
352
|
|
353
|
+
describe "with a collection of arguments" do
|
354
|
+
let(:args) { ["/foo/bar.wav", 1, Time.now] }
|
355
|
+
let :ssml do
|
356
|
+
file = args[0]
|
357
|
+
n = args[1].to_s
|
358
|
+
t = args[2].to_s
|
359
|
+
RubySpeech::SSML.draw do
|
360
|
+
audio :src => file
|
361
|
+
say_as(:interpret_as => 'cardinal') { n }
|
362
|
+
say_as(:interpret_as => 'time') { t }
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
it 'plays all arguments in one document' do
|
367
|
+
expect_ssml_output ssml
|
368
|
+
subject.play(args).should be true
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
353
372
|
describe "with a number" do
|
354
373
|
let(:argument) { 123 }
|
355
374
|
|
@@ -413,7 +432,7 @@ module Adhearsion
|
|
413
432
|
end
|
414
433
|
end
|
415
434
|
|
416
|
-
describe "with an
|
435
|
+
describe "with an hash containing a Date/DateTime/Time object and format options" do
|
417
436
|
let(:date) { Date.parse '2011-01-23' }
|
418
437
|
let(:format) { "d-m-y" }
|
419
438
|
let(:strftime) { "%d-%m%Y" }
|
@@ -619,42 +638,31 @@ module Adhearsion
|
|
619
638
|
:grammar => { :value => grammar.to_s }
|
620
639
|
}
|
621
640
|
|
641
|
+
def expect_component_complete_event
|
642
|
+
complete_event = Punchblock::Event::Complete.new
|
643
|
+
flexmock(complete_event).should_receive(:reason => flexmock(:utterance => 'dtmf-5'))
|
644
|
+
flexmock(Punchblock::Component::Input).new_instances do |input|
|
645
|
+
input.should_receive(:complete?).and_return(false)
|
646
|
+
input.should_receive(:complete_event).and_return(complete_event)
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
622
650
|
#test does pass and method works, but not sure if the empty method is a good idea
|
623
651
|
it "plays the correct output" do
|
624
652
|
def controller.write_and_await_response(input_component)
|
625
653
|
# it is actually a no-op here
|
626
654
|
end
|
627
655
|
|
628
|
-
def expect_component_complete_event
|
629
|
-
complete_event = Punchblock::Event::Complete.new
|
630
|
-
flexmock(complete_event).should_receive(:reason => flexmock(:interpretation => 'dtmf-5', :name => :input))
|
631
|
-
flexmock(Punchblock::Component::Input).new_instances do |input|
|
632
|
-
input.should_receive(:complete?).and_return(false)
|
633
|
-
input.should_receive(:complete_event).and_return(complete_event)
|
634
|
-
end
|
635
|
-
end
|
636
|
-
|
637
656
|
expect_component_complete_event
|
638
657
|
expect_component_execution Punchblock::Component::Output.new(:ssml => ssml.to_s)
|
639
658
|
subject.stream_file prompt, allowed_digits
|
640
659
|
end
|
641
660
|
|
642
661
|
it "returns a single digit amongst the allowed when pressed" do
|
643
|
-
flexmock(Punchblock::Event::Complete).new_instances.should_receive(:reason => flexmock(:interpretation => 'dtmf-5', :name => :input))
|
644
|
-
|
645
662
|
def controller.write_and_await_response(input_component)
|
646
663
|
input_component.trigger_event_handler Punchblock::Event::Complete.new
|
647
664
|
end
|
648
665
|
|
649
|
-
def expect_component_complete_event
|
650
|
-
complete_event = Punchblock::Event::Complete.new
|
651
|
-
flexmock(complete_event).should_receive(:reason => flexmock(:interpretation => 'dtmf-5', :name => :input))
|
652
|
-
flexmock(Punchblock::Component::Input).new_instances do |input|
|
653
|
-
input.should_receive(:complete?).and_return(false)
|
654
|
-
input.should_receive(:complete_event).and_return(complete_event)
|
655
|
-
end
|
656
|
-
end
|
657
|
-
|
658
666
|
expect_component_complete_event
|
659
667
|
flexmock(Punchblock::Component::Output).new_instances.should_receive(:stop!)
|
660
668
|
expect_component_execution output_component
|
@@ -680,6 +688,19 @@ module Adhearsion
|
|
680
688
|
end
|
681
689
|
end
|
682
690
|
|
691
|
+
describe "with a default voice set" do
|
692
|
+
before { Adhearsion.config.punchblock.default_voice = 'foo' }
|
693
|
+
|
694
|
+
it 'sets the voice on the output component' do
|
695
|
+
str = "Hello world"
|
696
|
+
ssml = RubySpeech::SSML.draw { string str }
|
697
|
+
expect_ssml_output ssml, voice: 'foo'
|
698
|
+
subject.say(str)
|
699
|
+
end
|
700
|
+
|
701
|
+
after { Adhearsion.config.punchblock.default_voice = nil }
|
702
|
+
end
|
703
|
+
|
683
704
|
describe "converts the argument to a string" do
|
684
705
|
it 'calls output with a string' do
|
685
706
|
argument = 123
|
@@ -714,6 +735,19 @@ module Adhearsion
|
|
714
735
|
end
|
715
736
|
end
|
716
737
|
|
738
|
+
describe "with a default voice set" do
|
739
|
+
before { Adhearsion.config.punchblock.default_voice = 'foo' }
|
740
|
+
|
741
|
+
it 'sets the voice on the output component' do
|
742
|
+
str = "Hello world"
|
743
|
+
ssml = RubySpeech::SSML.draw { string str }
|
744
|
+
expect_async_ssml_output ssml, voice: 'foo'
|
745
|
+
subject.say!(str)
|
746
|
+
end
|
747
|
+
|
748
|
+
after { Adhearsion.config.punchblock.default_voice = nil }
|
749
|
+
end
|
750
|
+
|
717
751
|
describe "converts the argument to a string" do
|
718
752
|
it 'calls output with a string' do
|
719
753
|
argument = 123
|
@@ -7,8 +7,129 @@ module Adhearsion
|
|
7
7
|
describe Record do
|
8
8
|
include CallControllerTestHelpers
|
9
9
|
|
10
|
+
describe Recorder do
|
11
|
+
let(:interruptible) { false }
|
12
|
+
let(:async) { false }
|
13
|
+
let(:component_options) { { :start_beep => true } }
|
14
|
+
let :options do
|
15
|
+
component_options.merge :interruptible => interruptible,
|
16
|
+
:async => async
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:component) { Punchblock::Component::Record.new component_options }
|
20
|
+
let :stopper_grammar do
|
21
|
+
RubySpeech::GRXML.draw :mode => 'dtmf', :root => 'inputdigits' do
|
22
|
+
rule id: 'inputdigits', scope: 'public' do
|
23
|
+
one_of do
|
24
|
+
item { '0' }
|
25
|
+
item { '1' }
|
26
|
+
item { '2' }
|
27
|
+
item { '3' }
|
28
|
+
item { '4' }
|
29
|
+
item { '5' }
|
30
|
+
item { '6' }
|
31
|
+
item { '7' }
|
32
|
+
item { '8' }
|
33
|
+
item { '9' }
|
34
|
+
item { '#' }
|
35
|
+
item { '*' }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
let(:input_component) { Punchblock::Component::Input.new mode: :dtmf, grammar: { :value => stopper_grammar } }
|
41
|
+
|
42
|
+
subject { Recorder.new controller, options }
|
43
|
+
|
44
|
+
its(:record_component) { should == component }
|
45
|
+
|
46
|
+
context "when passing time related options" do
|
47
|
+
let :component_options do
|
48
|
+
{ :max_duration => 5.5, :initial_timeout => 6.5, :final_timeout => 3.2 }
|
49
|
+
end
|
50
|
+
|
51
|
+
let :component do
|
52
|
+
Punchblock::Component::Record.new :max_duration => 5500,
|
53
|
+
:initial_timeout => 6500,
|
54
|
+
:final_timeout => 3200
|
55
|
+
end
|
56
|
+
|
57
|
+
it "takes seconds but sets milliseconds on the command" do
|
58
|
+
subject.record_component.should == component
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#run" do
|
63
|
+
context "with :async => false" do
|
64
|
+
it "executes the component synchronously" do
|
65
|
+
expect_component_execution subject.record_component
|
66
|
+
subject.run
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "with :async => true" do
|
71
|
+
let(:async) { true }
|
72
|
+
|
73
|
+
it "executes the component asynchronously" do
|
74
|
+
expect_message_waiting_for_response subject.record_component
|
75
|
+
subject.run
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "with :interruptible => false" do
|
80
|
+
its(:stopper_component) { should be_nil }
|
81
|
+
|
82
|
+
it "does not use an Input component" do
|
83
|
+
controller.should_receive(:execute_component_and_await_completion).once.with(component)
|
84
|
+
controller.should_receive(:write_and_await_response).never.with(input_component)
|
85
|
+
subject.run
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "with :interruptible => true" do
|
90
|
+
let(:interruptible) { true }
|
91
|
+
|
92
|
+
its(:stopper_component) { should == input_component }
|
93
|
+
|
94
|
+
describe "when the input component completes" do
|
95
|
+
let(:complete_event) { Punchblock::Event::Complete.new }
|
96
|
+
|
97
|
+
before do
|
98
|
+
subject.stopper_component.request!
|
99
|
+
subject.stopper_component.execute!
|
100
|
+
end
|
101
|
+
|
102
|
+
it "stops the recording" do
|
103
|
+
flexmock(subject.record_component).should_receive(:stop!).once
|
104
|
+
subject.stopper_component.trigger_event_handler complete_event
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "when the recording completes" do
|
109
|
+
it "stops the input component" do
|
110
|
+
controller.should_receive(:execute_component_and_await_completion).once.with(component)
|
111
|
+
controller.should_receive(:write_and_await_response).once.with(input_component)
|
112
|
+
flexmock(subject.stopper_component).should_receive(:stop!).once
|
113
|
+
subject.run
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "setting completion handlers" do
|
120
|
+
let(:complete_event) { Punchblock::Event::Complete.new }
|
121
|
+
|
122
|
+
it "should execute those handlers when recording completes" do
|
123
|
+
foo = flexmock 'foo'
|
124
|
+
foo.should_receive(:call).once.with Punchblock::Event::Complete
|
125
|
+
subject.handle_record_completion { |e| foo.call e }
|
126
|
+
subject.record_component.trigger_event_handler complete_event
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
10
131
|
describe "#record" do
|
11
|
-
let(:max_duration) { 5 }
|
132
|
+
let(:max_duration) { 5.5 }
|
12
133
|
let(:options) do
|
13
134
|
{
|
14
135
|
:start_beep => true,
|
@@ -104,7 +225,7 @@ module Adhearsion
|
|
104
225
|
complete_event = Punchblock::Event::Complete.new
|
105
226
|
flexmock(complete_event).should_receive(:reason => flexmock(:name => :input))
|
106
227
|
flexmock(Punchblock::Component::Input).new_instances do |input|
|
107
|
-
input.should_receive(:complete?).and_return(
|
228
|
+
input.should_receive(:complete?).and_return(true)
|
108
229
|
input.should_receive(:complete_event).and_return(complete_event)
|
109
230
|
end
|
110
231
|
flexmock(Punchblock::Component::Record).new_instances.should_receive(:stop!)
|
@@ -47,21 +47,41 @@ module Adhearsion
|
|
47
47
|
end
|
48
48
|
end # grammar_accept
|
49
49
|
|
50
|
-
describe "#
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
describe "#parse_dtmf" do
|
51
|
+
context "with a single digit" do
|
52
|
+
it "correctly returns the parsed input" do
|
53
|
+
subject.parse_dtmf("dtmf-3").should be == '3'
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
56
|
+
it "correctly returns star as *" do
|
57
|
+
subject.parse_dtmf("dtmf-star").should be == '*'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "correctly returns * as *" do
|
61
|
+
subject.parse_dtmf("*").should be == '*'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "correctly returns pound as #" do
|
65
|
+
subject.parse_dtmf("dtmf-pound").should be == '#'
|
66
|
+
end
|
67
|
+
|
68
|
+
it "correctly returns # as #" do
|
69
|
+
subject.parse_dtmf("#").should be == '#'
|
70
|
+
end
|
58
71
|
|
59
|
-
|
60
|
-
|
72
|
+
it "correctly parses digits without the dtmf- prefix" do
|
73
|
+
subject.parse_dtmf('1').should be == '1'
|
74
|
+
end
|
75
|
+
|
76
|
+
it "correctly returns nil when input is nil" do
|
77
|
+
subject.parse_dtmf(nil).should be == nil
|
78
|
+
end
|
61
79
|
end
|
62
80
|
|
63
|
-
|
64
|
-
|
81
|
+
context "with multiple digits separated by spaces" do
|
82
|
+
it "returns the digits without space separation" do
|
83
|
+
subject.parse_dtmf('1 dtmf-5 dtmf-star # 2').should be == '15*#2'
|
84
|
+
end
|
65
85
|
end
|
66
86
|
end # describe #grammar_accept
|
67
87
|
end
|
@@ -43,47 +43,45 @@ module Adhearsion
|
|
43
43
|
its(:id) { should be == call_id }
|
44
44
|
its(:to) { should be == to }
|
45
45
|
its(:from) { should be == from }
|
46
|
-
its(:offer) { should be offer }
|
47
|
-
its(:client) { should be mock_client }
|
48
|
-
|
49
|
-
its(:after_end_hold_time) { should be == 30 }
|
50
46
|
|
51
47
|
describe "its variables" do
|
52
|
-
context "with an offer
|
53
|
-
|
54
|
-
|
48
|
+
context "with an offer" do
|
49
|
+
context "with headers" do
|
50
|
+
let(:headers) { {:x_foo => 'bar'} }
|
51
|
+
its(:variables) { should be == headers }
|
55
52
|
|
56
|
-
|
57
|
-
|
58
|
-
|
53
|
+
it "should be made available via []" do
|
54
|
+
subject[:x_foo].should be == 'bar'
|
55
|
+
end
|
59
56
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
it "should be alterable using []=" do
|
58
|
+
subject[:x_foo] = 'baz'
|
59
|
+
subject[:x_foo].should be == 'baz'
|
60
|
+
end
|
64
61
|
|
65
|
-
|
66
|
-
|
62
|
+
context "when receiving an event with headers" do
|
63
|
+
let(:event) { Punchblock::Event::End.new :headers => {:x_bar => 'foo'} }
|
67
64
|
|
68
|
-
|
69
|
-
|
70
|
-
|
65
|
+
it "should merge later headers" do
|
66
|
+
subject << event
|
67
|
+
subject.variables.should be == {:x_foo => 'bar', :x_bar => 'foo'}
|
68
|
+
end
|
71
69
|
end
|
72
|
-
end
|
73
70
|
|
74
|
-
|
75
|
-
|
71
|
+
context "when sending a command with headers" do
|
72
|
+
let(:command) { Punchblock::Command::Accept.new :headers => {:x_bar => 'foo'} }
|
76
73
|
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
it "should merge later headers" do
|
75
|
+
subject.write_command command
|
76
|
+
subject.variables.should be == {:x_foo => 'bar', :x_bar => 'foo'}
|
77
|
+
end
|
80
78
|
end
|
81
79
|
end
|
82
|
-
end
|
83
80
|
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
context "without headers" do
|
82
|
+
let(:headers) { nil }
|
83
|
+
its(:variables) { should be == {} }
|
84
|
+
end
|
87
85
|
end
|
88
86
|
|
89
87
|
context "without an offer" do
|
@@ -273,6 +271,49 @@ module Adhearsion
|
|
273
271
|
end
|
274
272
|
end
|
275
273
|
|
274
|
+
context "peer registry" do
|
275
|
+
let(:other_call_id) { 'foobar' }
|
276
|
+
let(:other_call) { flexmock Call.new, :id => other_call_id }
|
277
|
+
|
278
|
+
let :joined_event do
|
279
|
+
Punchblock::Event::Joined.new :call_id => other_call_id
|
280
|
+
end
|
281
|
+
|
282
|
+
let :unjoined_event do
|
283
|
+
Punchblock::Event::Unjoined.new :call_id => other_call_id
|
284
|
+
end
|
285
|
+
|
286
|
+
context "when we know about the joined call" do
|
287
|
+
before { Adhearsion.active_calls << other_call }
|
288
|
+
|
289
|
+
it "should add the peer to its registry" do
|
290
|
+
subject << joined_event
|
291
|
+
subject.peers.should == {'foobar' => other_call}
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
context "when we don't know about the joined call" do
|
296
|
+
it "should add a nil entry to its registry" do
|
297
|
+
subject << joined_event
|
298
|
+
subject.peers.should == {'foobar' => nil}
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
it "should not return the same registry every call" do
|
303
|
+
subject.peers.should_not be subject.peers
|
304
|
+
end
|
305
|
+
|
306
|
+
context "when being unjoined from a previously joined call" do
|
307
|
+
before { subject << joined_event }
|
308
|
+
|
309
|
+
it "should remove the peer from its registry" do
|
310
|
+
subject.peers.should_not eql({})
|
311
|
+
subject << unjoined_event
|
312
|
+
subject.peers.should eql({})
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
276
317
|
describe "#<<" do
|
277
318
|
describe "with a Punchblock End" do
|
278
319
|
let :end_event do
|
@@ -307,7 +348,7 @@ module Adhearsion
|
|
307
348
|
end
|
308
349
|
|
309
350
|
it "shuts down the actor" do
|
310
|
-
|
351
|
+
Adhearsion.config.platform.after_hangup_lifetime = 2
|
311
352
|
subject << end_event
|
312
353
|
sleep 2.1
|
313
354
|
subject.should_not be_alive
|
@@ -539,6 +580,12 @@ module Adhearsion
|
|
539
580
|
subject.reject nil, headers
|
540
581
|
end
|
541
582
|
end
|
583
|
+
|
584
|
+
it "should immediately fire the :call_rejected event giving the call and the reason" do
|
585
|
+
expect_message_waiting_for_response Punchblock::Command::Reject
|
586
|
+
flexmock(Adhearsion::Events).should_receive(:trigger_immediately).once.with(:call_rejected, :call => subject, :reason => :decline)
|
587
|
+
subject.reject :decline
|
588
|
+
end
|
542
589
|
end
|
543
590
|
|
544
591
|
describe "#hangup" do
|
@@ -760,12 +807,6 @@ module Adhearsion
|
|
760
807
|
lambda { subject.execute_controller(mock_controller) { foo } }.should raise_error(ArgumentError)
|
761
808
|
end
|
762
809
|
|
763
|
-
it "should add the controller thread to the important threads" do
|
764
|
-
flexmock(CallController).should_receive(:exec)
|
765
|
-
controller_thread = subject.execute_controller mock_controller, lambda { |call| latch.countdown! }
|
766
|
-
Adhearsion::Process.important_threads.should include controller_thread
|
767
|
-
end
|
768
|
-
|
769
810
|
it "should pass the exception to the events system" do
|
770
811
|
latch = CountDownLatch.new 1
|
771
812
|
Adhearsion::Events.exception do |e, l|
|