punchblock 1.9.4 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -2
- data/CHANGELOG.md +17 -0
- data/Gemfile +1 -0
- data/Guardfile +4 -0
- data/README.markdown +6 -0
- data/Rakefile +16 -0
- data/benchmarks/ami_event_name_comparison.rb +14 -0
- data/benchmarks/channel.rb +27 -0
- data/lib/punchblock/client.rb +2 -6
- data/lib/punchblock/command/accept.rb +3 -24
- data/lib/punchblock/command/answer.rb +3 -24
- data/lib/punchblock/command/dial.rb +24 -76
- data/lib/punchblock/command/hangup.rb +3 -19
- data/lib/punchblock/command/join.rb +21 -70
- data/lib/punchblock/command/mute.rb +3 -3
- data/lib/punchblock/command/redirect.rb +6 -39
- data/lib/punchblock/command/reject.rb +14 -54
- data/lib/punchblock/command/unjoin.rb +8 -40
- data/lib/punchblock/command/unmute.rb +3 -3
- data/lib/punchblock/command_node.rb +0 -17
- data/lib/punchblock/component/asterisk/agi/command.rb +20 -127
- data/lib/punchblock/component/asterisk/ami/action.rb +30 -117
- data/lib/punchblock/component/component_node.rb +1 -1
- data/lib/punchblock/component/input.rb +89 -268
- data/lib/punchblock/component/output.rb +106 -154
- data/lib/punchblock/component/prompt.rb +51 -0
- data/lib/punchblock/component/record.rb +41 -130
- data/lib/punchblock/component.rb +1 -0
- data/lib/punchblock/connection/asterisk.rb +31 -4
- data/lib/punchblock/connection/xmpp.rb +6 -14
- data/lib/punchblock/core_ext/blather/stanza.rb +1 -1
- data/lib/punchblock/event/active_speaker.rb +2 -10
- data/lib/punchblock/event/answered.rb +3 -3
- data/lib/punchblock/event/asterisk/ami/event.rb +15 -47
- data/lib/punchblock/event/complete.rb +26 -48
- data/lib/punchblock/event/dtmf.rb +3 -13
- data/lib/punchblock/event/end.rb +10 -11
- data/lib/punchblock/event/joined.rb +5 -25
- data/lib/punchblock/event/offer.rb +4 -25
- data/lib/punchblock/event/ringing.rb +3 -3
- data/lib/punchblock/event/unjoined.rb +5 -25
- data/lib/punchblock/event.rb +0 -10
- data/lib/punchblock/has_headers.rb +20 -26
- data/lib/punchblock/rayo_node.rb +46 -23
- data/lib/punchblock/ref.rb +39 -18
- data/lib/punchblock/translator/asterisk/agi_app.rb +15 -0
- data/lib/punchblock/translator/asterisk/agi_command.rb +3 -1
- data/lib/punchblock/translator/asterisk/ami_error_converter.rb +20 -0
- data/lib/punchblock/translator/asterisk/call.rb +60 -39
- data/lib/punchblock/translator/asterisk/channel.rb +41 -0
- data/lib/punchblock/translator/asterisk/component/asterisk/agi_command.rb +4 -1
- data/lib/punchblock/translator/asterisk/component/asterisk/ami_action.rb +4 -4
- data/lib/punchblock/translator/asterisk/component/composed_prompt.rb +62 -0
- data/lib/punchblock/translator/asterisk/component/input.rb +1 -0
- data/lib/punchblock/translator/asterisk/component/mrcp_native_prompt.rb +56 -0
- data/lib/punchblock/translator/asterisk/component/mrcp_prompt.rb +53 -0
- data/lib/punchblock/translator/asterisk/component/mrcp_recog_prompt.rb +99 -0
- data/lib/punchblock/translator/asterisk/component/output.rb +30 -22
- data/lib/punchblock/translator/asterisk/component/record.rb +8 -6
- data/lib/punchblock/translator/asterisk/component.rb +6 -5
- data/lib/punchblock/translator/asterisk/unimrcp_app.rb +26 -0
- data/lib/punchblock/translator/asterisk.rb +24 -28
- data/lib/punchblock/translator/dtmf_recognizer.rb +39 -20
- data/lib/punchblock/translator/freeswitch/call.rb +15 -14
- data/lib/punchblock/translator/freeswitch/component/abstract_output.rb +5 -4
- data/lib/punchblock/translator/freeswitch/component/flite_output.rb +1 -1
- data/lib/punchblock/translator/freeswitch/component/input.rb +5 -0
- data/lib/punchblock/translator/freeswitch/component/output.rb +2 -2
- data/lib/punchblock/translator/freeswitch/component/record.rb +19 -13
- data/lib/punchblock/translator/freeswitch/component/tts_output.rb +2 -2
- data/lib/punchblock/translator/freeswitch/component.rb +2 -5
- data/lib/punchblock/translator/freeswitch.rb +2 -2
- data/lib/punchblock/translator/input_component.rb +33 -13
- data/lib/punchblock/uri_list.rb +21 -0
- data/lib/punchblock/version.rb +1 -1
- data/lib/punchblock.rb +4 -3
- data/punchblock.gemspec +7 -3
- data/spec/punchblock/client/component_registry_spec.rb +1 -1
- data/spec/punchblock/client_spec.rb +10 -26
- data/spec/punchblock/command/accept_spec.rb +41 -7
- data/spec/punchblock/command/answer_spec.rb +51 -7
- data/spec/punchblock/command/dial_spec.rb +56 -14
- data/spec/punchblock/command/hangup_spec.rb +41 -7
- data/spec/punchblock/command/join_spec.rb +53 -11
- data/spec/punchblock/command/mute_spec.rb +19 -4
- data/spec/punchblock/command/redirect_spec.rb +40 -10
- data/spec/punchblock/command/reject_spec.rb +43 -11
- data/spec/punchblock/command/unjoin_spec.rb +40 -9
- data/spec/punchblock/command/unmute_spec.rb +19 -4
- data/spec/punchblock/command_node_spec.rb +0 -4
- data/spec/punchblock/component/asterisk/agi/command_spec.rb +16 -39
- data/spec/punchblock/component/asterisk/ami/action_spec.rb +50 -53
- data/spec/punchblock/component/component_node_spec.rb +3 -5
- data/spec/punchblock/component/input_spec.rb +194 -61
- data/spec/punchblock/component/output_spec.rb +194 -62
- data/spec/punchblock/component/prompt_spec.rb +132 -0
- data/spec/punchblock/component/record_spec.rb +70 -32
- data/spec/punchblock/connection/asterisk_spec.rb +17 -3
- data/spec/punchblock/connection/freeswitch_spec.rb +4 -4
- data/spec/punchblock/connection/xmpp_spec.rb +20 -38
- data/spec/punchblock/event/answered_spec.rb +12 -10
- data/spec/punchblock/event/asterisk/ami/event_spec.rb +27 -22
- data/spec/punchblock/event/complete_spec.rb +15 -19
- data/spec/punchblock/event/dtmf_spec.rb +5 -6
- data/spec/punchblock/event/end_spec.rb +20 -10
- data/spec/punchblock/event/joined_spec.rb +8 -7
- data/spec/punchblock/event/offer_spec.rb +41 -12
- data/spec/punchblock/event/ringing_spec.rb +12 -10
- data/spec/punchblock/event/started_speaking_spec.rb +5 -6
- data/spec/punchblock/event/stopped_speaking_spec.rb +5 -6
- data/spec/punchblock/event/unjoined_spec.rb +7 -7
- data/spec/punchblock/ref_spec.rb +86 -9
- data/spec/punchblock/translator/asterisk/call_spec.rb +317 -154
- data/spec/punchblock/translator/asterisk/component/asterisk/agi_command_spec.rb +28 -5
- data/spec/punchblock/translator/asterisk/component/asterisk/ami_action_spec.rb +15 -13
- data/spec/punchblock/translator/asterisk/component/composed_prompt_spec.rb +237 -0
- data/spec/punchblock/translator/asterisk/component/input_spec.rb +171 -14
- data/spec/punchblock/translator/asterisk/component/mrcp_native_prompt_spec.rb +652 -0
- data/spec/punchblock/translator/asterisk/component/mrcp_prompt_spec.rb +646 -0
- data/spec/punchblock/translator/asterisk/component/output_spec.rb +127 -77
- data/spec/punchblock/translator/asterisk/component/record_spec.rb +17 -8
- data/spec/punchblock/translator/asterisk/component/stop_by_redirect_spec.rb +2 -2
- data/spec/punchblock/translator/asterisk/component_spec.rb +3 -7
- data/spec/punchblock/translator/asterisk_spec.rb +20 -24
- data/spec/punchblock/translator/freeswitch/call_spec.rb +103 -99
- data/spec/punchblock/translator/freeswitch/component/flite_output_spec.rb +17 -8
- data/spec/punchblock/translator/freeswitch/component/input_spec.rb +26 -14
- data/spec/punchblock/translator/freeswitch/component/output_spec.rb +30 -52
- data/spec/punchblock/translator/freeswitch/component/record_spec.rb +23 -19
- data/spec/punchblock/translator/freeswitch/component/tts_output_spec.rb +18 -8
- data/spec/punchblock/translator/freeswitch/component_spec.rb +4 -8
- data/spec/punchblock/translator/freeswitch_spec.rb +11 -14
- data/spec/punchblock/uri_list_spec.rb +49 -0
- data/spec/punchblock_spec.rb +11 -1
- data/spec/spec_helper.rb +7 -11
- data/spec/support/mock_connection_with_event_handler.rb +1 -1
- metadata +104 -24
- data/lib/punchblock/header.rb +0 -9
- data/lib/punchblock/key_value_pair_node.rb +0 -51
- data/spec/punchblock/header_spec.rb +0 -11
@@ -7,10 +7,10 @@ module Punchblock
|
|
7
7
|
class Freeswitch
|
8
8
|
describe Call do
|
9
9
|
let(:id) { Punchblock.new_uuid }
|
10
|
-
let(:stream) {
|
10
|
+
let(:stream) { double('RubyFS::Stream').as_null_object }
|
11
11
|
let(:media_engine) { 'freeswitch' }
|
12
12
|
let(:default_voice) { :hal }
|
13
|
-
let(:translator) { Freeswitch.new
|
13
|
+
let(:translator) { Freeswitch.new double('Connection::Freeswitch').as_null_object }
|
14
14
|
let(:es_env) do
|
15
15
|
{
|
16
16
|
:variable_direction => "inbound",
|
@@ -90,78 +90,78 @@ module Punchblock
|
|
90
90
|
|
91
91
|
let :headers do
|
92
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
|
-
|
93
|
+
'X-variable_direction' => "inbound",
|
94
|
+
'X-variable_uuid' => "3f0e1e18-c056-11e1-b099-fffeda3ce54f",
|
95
|
+
'X-variable_session_id' => "1",
|
96
|
+
'X-variable_sip_local_network_addr' => "109.148.160.137",
|
97
|
+
'X-variable_sip_network_ip' => "192.168.1.74",
|
98
|
+
'X-variable_sip_network_port' => "59253",
|
99
|
+
'X-variable_sip_received_ip' => "192.168.1.74",
|
100
|
+
'X-variable_sip_received_port' => "59253",
|
101
|
+
'X-variable_sip_via_protocol' => "udp",
|
102
|
+
'X-variable_sip_authorized' => "true",
|
103
|
+
'X-variable_sip_number_alias' => "1000",
|
104
|
+
'X-variable_sip_auth_username' => "1000",
|
105
|
+
'X-variable_sip_auth_realm' => "127.0.0.1",
|
106
|
+
'X-variable_number_alias' => "1000",
|
107
|
+
'X-variable_user_name' => "1000",
|
108
|
+
'X-variable_domain_name' => "127.0.0.1",
|
109
|
+
'X-variable_record_stereo' => "true",
|
110
|
+
'X-variable_default_gateway' => "example.com",
|
111
|
+
'X-variable_default_areacode' => "918",
|
112
|
+
'X-variable_transfer_fallback_extension' => "operator",
|
113
|
+
'X-variable_toll_allow' => "domestic,international,local",
|
114
|
+
'X-variable_accountcode' => "1000",
|
115
|
+
'X-variable_user_context' => "default",
|
116
|
+
'X-variable_effective_caller_id_name' => "Extension 1000",
|
117
|
+
'X-variable_effective_caller_id_number' => "1000",
|
118
|
+
'X-variable_outbound_caller_id_name' => "FreeSWITCH",
|
119
|
+
'X-variable_outbound_caller_id_number' => "0000000000",
|
120
|
+
'X-variable_callgroup' => "techsupport",
|
121
|
+
'X-variable_sip_from_user' => "1000",
|
122
|
+
'X-variable_sip_from_uri' => "1000@127.0.0.1",
|
123
|
+
'X-variable_sip_from_host' => "127.0.0.1",
|
124
|
+
'X-variable_sip_from_user_stripped' => "1000",
|
125
|
+
'X-variable_sip_from_tag' => "1248111553",
|
126
|
+
'X-variable_sofia_profile_name' => "internal",
|
127
|
+
'X-variable_sip_full_via' => "SIP/2.0/UDP 192.168.1.74:59253;rport=59253;branch=z9hG4bK2021947958",
|
128
|
+
'X-variable_sip_full_from' => "<sip:1000@127.0.0.1>;tag=1248111553",
|
129
|
+
'X-variable_sip_full_to' => "<sip:10@127.0.0.1>",
|
130
|
+
'X-variable_sip_req_user' => "10",
|
131
|
+
'X-variable_sip_req_uri' => "10@127.0.0.1",
|
132
|
+
'X-variable_sip_req_host' => "127.0.0.1",
|
133
|
+
'X-variable_sip_to_user' => "10",
|
134
|
+
'X-variable_sip_to_uri' => "10@127.0.0.1",
|
135
|
+
'X-variable_sip_to_host' => "127.0.0.1",
|
136
|
+
'X-variable_sip_contact_user' => "1000",
|
137
|
+
'X-variable_sip_contact_port' => "59253",
|
138
|
+
'X-variable_sip_contact_uri' => "1000@192.168.1.74:59253",
|
139
|
+
'X-variable_sip_contact_host' => "192.168.1.74",
|
140
|
+
'X-variable_channel_name' => "sofia/internal/1000@127.0.0.1",
|
141
|
+
'X-variable_sip_call_id' => "1251435211@127.0.0.1",
|
142
|
+
'X-variable_sip_user_agent' => "YATE/4.1.0",
|
143
|
+
'X-variable_sip_via_host' => "192.168.1.74",
|
144
|
+
'X-variable_sip_via_port' => "59253",
|
145
|
+
'X-variable_sip_via_rport' => "59253",
|
146
|
+
'X-variable_max_forwards' => "20",
|
147
|
+
'X-variable_presence_id' => "1000@127.0.0.1",
|
148
|
+
'X-variable_switch_r_sdp' => "v=0\r\no=yate 1340801245 1340801245 IN IP4 172.20.10.3\r\ns=SIP Call\r\nc=IN IP4 172.20.10.3\r\nt=0 0\r\nm=audio 25048 RTP/AVP 0 8 11 98 97 102 103 104 105 106 101\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:11 L16/8000\r\na=rtpmap:98 iLBC/8000\r\na=fmtp:98 mode=20\r\na=rtpmap:97 iLBC/8000\r\na=fmtp:97 mode=30\r\na=rtpmap:102 SPEEX/8000\r\na=rtpmap:103 SPEEX/16000\r\na=rtpmap:104 SPEEX/32000\r\na=rtpmap:105 iSAC/16000\r\na=rtpmap:106 iSAC/32000\r\na=rtpmap:101 telephone-event/8000\r\na=ptime:30\r\n",
|
149
|
+
'X-variable_remote_media_ip' => "172.20.10.3",
|
150
|
+
'X-variable_remote_media_port' => "25048",
|
151
|
+
'X-variable_sip_audio_recv_pt' => "0",
|
152
|
+
'X-variable_sip_use_codec_name' => "PCMU",
|
153
|
+
'X-variable_sip_use_codec_rate' => "8000",
|
154
|
+
'X-variable_sip_use_codec_ptime' => "30",
|
155
|
+
'X-variable_read_codec' => "PCMU",
|
156
|
+
'X-variable_read_rate' => "8000",
|
157
|
+
'X-variable_write_codec' => "PCMU",
|
158
|
+
'X-variable_write_rate' => "8000",
|
159
|
+
'X-variable_endpoint_disposition' => "RECEIVED",
|
160
|
+
'X-variable_call_uuid' => "3f0e1e18-c056-11e1-b099-fffeda3ce54f",
|
161
|
+
'X-variable_open' => "true",
|
162
|
+
'X-variable_rfc2822_date' => "Wed, 27 Jun 2012 13:47:25 +0100",
|
163
|
+
'X-variable_export_vars' => "RFC2822_DATE",
|
164
|
+
'X-variable_current_application' => "park"
|
165
165
|
}
|
166
166
|
end
|
167
167
|
|
@@ -176,7 +176,7 @@ module Punchblock
|
|
176
176
|
describe '#register_component' do
|
177
177
|
it 'should make the component accessible by ID' do
|
178
178
|
component_id = 'abc123'
|
179
|
-
component =
|
179
|
+
component = double 'Translator::Freeswitch::Component', :id => component_id
|
180
180
|
subject.register_component component
|
181
181
|
subject.component_with_id(component_id).should be component
|
182
182
|
end
|
@@ -350,13 +350,13 @@ module Punchblock
|
|
350
350
|
|
351
351
|
it "de-registers the call from the translator" do
|
352
352
|
translator.stub :handle_pb_event
|
353
|
-
translator.should_receive(:deregister_call).once.with(
|
353
|
+
translator.should_receive(:deregister_call).once.with(id)
|
354
354
|
subject.handle_es_event es_event
|
355
355
|
end
|
356
356
|
|
357
357
|
it "should cause all components to send complete events before sending end event" do
|
358
358
|
ssml_doc = RubySpeech::SSML.draw { audio { 'foo.wav' } }
|
359
|
-
comp_command = Punchblock::Component::Output.new :
|
359
|
+
comp_command = Punchblock::Component::Output.new :render_document => {:value => ssml_doc}
|
360
360
|
comp_command.request!
|
361
361
|
component = subject.execute_command comp_command
|
362
362
|
comp_command.response(0.1).should be_a Ref
|
@@ -374,7 +374,6 @@ module Punchblock
|
|
374
374
|
'NORMAL_CLEARING',
|
375
375
|
'ORIGINATOR_CANCEL',
|
376
376
|
'SYSTEM_SHUTDOWN',
|
377
|
-
'MANAGER_REQUEST',
|
378
377
|
'BLIND_TRANSFER',
|
379
378
|
'ATTENDED_TRANSFER',
|
380
379
|
'PICKED_OFF',
|
@@ -392,6 +391,17 @@ module Punchblock
|
|
392
391
|
end
|
393
392
|
end
|
394
393
|
|
394
|
+
context "with a MANAGER_REQUEST cause" do
|
395
|
+
let(:cause) { 'MANAGER_REQUEST' }
|
396
|
+
|
397
|
+
it 'should send an end (hangup-command) event to the translator' do
|
398
|
+
expected_end_event = Punchblock::Event::End.new :reason => :hangup_command,
|
399
|
+
:target_call_id => subject.id
|
400
|
+
translator.should_receive(:handle_pb_event).with expected_end_event
|
401
|
+
subject.handle_es_event es_event
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
395
405
|
context "with a user busy cause" do
|
396
406
|
let(:cause) { 'USER_BUSY' }
|
397
407
|
|
@@ -500,7 +510,7 @@ module Punchblock
|
|
500
510
|
end
|
501
511
|
|
502
512
|
context 'with an event for a known component' do
|
503
|
-
let(:mock_component_node) {
|
513
|
+
let(:mock_component_node) { double 'Punchblock::Component::Output' }
|
504
514
|
let :component do
|
505
515
|
Component::Output.new mock_component_node, subject
|
506
516
|
end
|
@@ -581,7 +591,7 @@ module Punchblock
|
|
581
591
|
RubyFS::Event.new nil, :event_name => 'DTMF'
|
582
592
|
end
|
583
593
|
|
584
|
-
let(:response) {
|
594
|
+
let(:response) { double 'Response' }
|
585
595
|
|
586
596
|
it 'should execute the handler' do
|
587
597
|
response.should_receive(:call).once.with es_event
|
@@ -596,10 +606,8 @@ module Punchblock
|
|
596
606
|
let(:other_call_id) { Punchblock.new_uuid }
|
597
607
|
|
598
608
|
let :expected_joined do
|
599
|
-
Punchblock::Event::Joined.new
|
600
|
-
|
601
|
-
joined.call_id = other_call_id
|
602
|
-
end
|
609
|
+
Punchblock::Event::Joined.new target_call_id: subject.id,
|
610
|
+
call_uri: other_call_id
|
603
611
|
end
|
604
612
|
|
605
613
|
context "where this is the joining call" do
|
@@ -637,10 +645,8 @@ module Punchblock
|
|
637
645
|
let(:other_call_id) { Punchblock.new_uuid }
|
638
646
|
|
639
647
|
let :expected_unjoined do
|
640
|
-
Punchblock::Event::Unjoined.new
|
641
|
-
|
642
|
-
joined.call_id = other_call_id
|
643
|
-
end
|
648
|
+
Punchblock::Event::Unjoined.new target_call_id: subject.id,
|
649
|
+
call_uri: other_call_id
|
644
650
|
end
|
645
651
|
|
646
652
|
context "where this is the unjoining call" do
|
@@ -738,7 +744,7 @@ module Punchblock
|
|
738
744
|
let(:command) { Command::Hangup.new }
|
739
745
|
|
740
746
|
it "should send a hangup message and set the command's response" do
|
741
|
-
expect_hangup_with_reason '
|
747
|
+
expect_hangup_with_reason 'MANAGER_REQUEST'
|
742
748
|
subject.execute_command command
|
743
749
|
command.response(0.5).should be true
|
744
750
|
end
|
@@ -874,7 +880,7 @@ module Punchblock
|
|
874
880
|
end
|
875
881
|
|
876
882
|
let :mock_component do
|
877
|
-
|
883
|
+
double 'Component', :id => component_id
|
878
884
|
end
|
879
885
|
|
880
886
|
context "for a known component ID" do
|
@@ -888,19 +894,17 @@ module Punchblock
|
|
888
894
|
|
889
895
|
context "for a component which began executing but crashed" do
|
890
896
|
let :component_command do
|
891
|
-
Punchblock::Component::Output.new :
|
897
|
+
Punchblock::Component::Output.new :render_document => {:value => RubySpeech::SSML.draw}
|
892
898
|
end
|
893
899
|
|
894
|
-
let(:comp_id) { component_command.response.
|
900
|
+
let(:comp_id) { component_command.response.component_id }
|
895
901
|
|
896
902
|
let(:subsequent_command) { Punchblock::Component::Stop.new :component_id => comp_id }
|
897
903
|
|
898
904
|
let :expected_event do
|
899
|
-
Punchblock::Event::Complete.new
|
900
|
-
|
901
|
-
|
902
|
-
e.reason = Punchblock::Event::Complete::Error.new
|
903
|
-
end
|
905
|
+
Punchblock::Event::Complete.new target_call_id: subject.id,
|
906
|
+
component_id: comp_id,
|
907
|
+
reason: Punchblock::Event::Complete::Error.new
|
904
908
|
end
|
905
909
|
|
906
910
|
before do
|
@@ -951,7 +955,7 @@ module Punchblock
|
|
951
955
|
let(:other_call_id) { Punchblock.new_uuid }
|
952
956
|
|
953
957
|
let :command do
|
954
|
-
Punchblock::Command::Join.new :
|
958
|
+
Punchblock::Command::Join.new :call_uri => other_call_id
|
955
959
|
end
|
956
960
|
|
957
961
|
it "executes the proper uuid_bridge command" do
|
@@ -983,7 +987,7 @@ module Punchblock
|
|
983
987
|
let(:other_call_id) { Punchblock.new_uuid }
|
984
988
|
|
985
989
|
let :command do
|
986
|
-
Punchblock::Command::Unjoin.new :
|
990
|
+
Punchblock::Command::Unjoin.new :call_uri => other_call_id
|
987
991
|
end
|
988
992
|
|
989
993
|
it "executes the unjoin via transfer to park" do
|
@@ -25,7 +25,7 @@ module Punchblock
|
|
25
25
|
end
|
26
26
|
|
27
27
|
let :command_options do
|
28
|
-
{ :
|
28
|
+
{ :render_document => {:value => ssml_doc} }
|
29
29
|
end
|
30
30
|
|
31
31
|
def execute
|
@@ -43,16 +43,16 @@ module Punchblock
|
|
43
43
|
let(:command_opts) { {} }
|
44
44
|
|
45
45
|
let :command_options do
|
46
|
-
{ :
|
46
|
+
{ :render_document => {:value => ssml_doc} }.merge(command_opts)
|
47
47
|
end
|
48
48
|
|
49
49
|
let :original_command do
|
50
50
|
Punchblock::Component::Output.new command_options
|
51
51
|
end
|
52
52
|
|
53
|
-
describe '
|
53
|
+
describe 'document' do
|
54
54
|
context 'unset' do
|
55
|
-
let(:
|
55
|
+
let(:ssml_doc) { nil }
|
56
56
|
it "should return an error and not execute any actions" do
|
57
57
|
execute
|
58
58
|
error = ProtocolError.new.setup 'option error', 'An SSML document is required.'
|
@@ -70,7 +70,16 @@ module Punchblock
|
|
70
70
|
expect_playback
|
71
71
|
execute
|
72
72
|
subject.handle_es_event RubyFS::Event.new(nil, :event_name => "CHANNEL_EXECUTE_COMPLETE")
|
73
|
-
original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::
|
73
|
+
original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Finish
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with multiple documents' do
|
78
|
+
let(:command_opts) { { :render_documents => [{:value => ssml_doc}, {:value => ssml_doc}] } }
|
79
|
+
it "should return an error and not execute any actions" do
|
80
|
+
subject.execute
|
81
|
+
error = ProtocolError.new.setup 'option error', 'Only a single document is supported.'
|
82
|
+
original_command.response(0.1).should be == error
|
74
83
|
end
|
75
84
|
end
|
76
85
|
end
|
@@ -215,11 +224,11 @@ module Punchblock
|
|
215
224
|
end
|
216
225
|
end
|
217
226
|
|
218
|
-
context "set to :
|
219
|
-
let(:command_opts) { { :interrupt_on => :
|
227
|
+
context "set to :voice" do
|
228
|
+
let(:command_opts) { { :interrupt_on => :voice } }
|
220
229
|
it "should return an error and not execute any actions" do
|
221
230
|
execute
|
222
|
-
error = ProtocolError.new.setup 'option error', 'An interrupt-on value of
|
231
|
+
error = ProtocolError.new.setup 'option error', 'An interrupt-on value of voice is unsupported.'
|
223
232
|
original_command.response(0.1).should be == error
|
224
233
|
end
|
225
234
|
end
|
@@ -11,7 +11,7 @@ module Punchblock
|
|
11
11
|
|
12
12
|
let(:id) { Punchblock.new_uuid }
|
13
13
|
let(:translator) { Punchblock::Translator::Freeswitch.new connection }
|
14
|
-
let(:mock_stream) {
|
14
|
+
let(:mock_stream) { double('RubyFS::Stream') }
|
15
15
|
let(:call) { Punchblock::Translator::Freeswitch::Call.new id, translator, nil, mock_stream }
|
16
16
|
|
17
17
|
let(:original_command_options) { {} }
|
@@ -74,13 +74,17 @@ module Punchblock
|
|
74
74
|
sleep 0.5
|
75
75
|
end
|
76
76
|
|
77
|
+
let :expected_nlsml do
|
78
|
+
RubySpeech::NLSML.draw do
|
79
|
+
interpretation confidence: 1 do
|
80
|
+
instance "dtmf-1 dtmf-2"
|
81
|
+
input "12", mode: :dtmf
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
77
86
|
let :expected_event do
|
78
|
-
Punchblock::Component::Input::Complete::
|
79
|
-
:confidence => 1,
|
80
|
-
:utterance => '12',
|
81
|
-
:interpretation => 'dtmf-1 dtmf-2',
|
82
|
-
:component_id => subject.id,
|
83
|
-
:target_call_id => call.id
|
87
|
+
Punchblock::Component::Input::Complete::Match.new nlsml: expected_nlsml
|
84
88
|
end
|
85
89
|
|
86
90
|
it "should send a success complete event with the relevant data" do
|
@@ -100,8 +104,7 @@ module Punchblock
|
|
100
104
|
end
|
101
105
|
|
102
106
|
let :expected_event do
|
103
|
-
Punchblock::Component::Input::Complete::NoMatch.new
|
104
|
-
:target_call_id => call.id
|
107
|
+
Punchblock::Component::Input::Complete::NoMatch.new
|
105
108
|
end
|
106
109
|
|
107
110
|
it "should send a nomatch complete event" do
|
@@ -119,6 +122,15 @@ module Punchblock
|
|
119
122
|
original_command.response(0.1).should be == error
|
120
123
|
end
|
121
124
|
end
|
125
|
+
|
126
|
+
context 'with multiple grammars' do
|
127
|
+
let(:original_command_opts) { { :grammars => [{:value => grammar}, {:value => grammar}] } }
|
128
|
+
it "should return an error and not execute any actions" do
|
129
|
+
subject.execute
|
130
|
+
error = ProtocolError.new.setup 'option error', 'Only a single grammar is supported.'
|
131
|
+
original_command.response(0.1).should be == error
|
132
|
+
end
|
133
|
+
end
|
122
134
|
end
|
123
135
|
|
124
136
|
describe 'mode' do
|
@@ -140,8 +152,8 @@ module Punchblock
|
|
140
152
|
end
|
141
153
|
end
|
142
154
|
|
143
|
-
context '
|
144
|
-
let(:original_command_opts) { { :mode => :
|
155
|
+
context 'voice' do
|
156
|
+
let(:original_command_opts) { { :mode => :voice } }
|
145
157
|
it "should return an error and not execute any actions" do
|
146
158
|
subject.execute
|
147
159
|
error = ProtocolError.new.setup 'option error', 'A mode value other than DTMF is unsupported.'
|
@@ -167,7 +179,7 @@ module Punchblock
|
|
167
179
|
send_dtmf 1
|
168
180
|
sleep 1.5
|
169
181
|
send_dtmf 2
|
170
|
-
reason.should be_a Punchblock::Component::Input::Complete::
|
182
|
+
reason.should be_a Punchblock::Component::Input::Complete::Match
|
171
183
|
end
|
172
184
|
|
173
185
|
it "should cause a NoInput complete event to be sent after the timeout" do
|
@@ -218,10 +230,10 @@ module Punchblock
|
|
218
230
|
send_dtmf 1
|
219
231
|
sleep 0.5
|
220
232
|
send_dtmf 2
|
221
|
-
reason.should be_a Punchblock::Component::Input::Complete::
|
233
|
+
reason.should be_a Punchblock::Component::Input::Complete::Match
|
222
234
|
end
|
223
235
|
|
224
|
-
it "should cause a
|
236
|
+
it "should cause a InterDigitTimeout complete event to be sent after the timeout" do
|
225
237
|
subject.execute
|
226
238
|
sleep 1.5
|
227
239
|
send_dtmf 1
|
@@ -23,7 +23,7 @@ module Punchblock
|
|
23
23
|
end
|
24
24
|
|
25
25
|
let :command_options do
|
26
|
-
{ :
|
26
|
+
{ :render_document => {:value => ssml_doc} }
|
27
27
|
end
|
28
28
|
|
29
29
|
subject { Output.new original_command, mock_call }
|
@@ -45,16 +45,17 @@ module Punchblock
|
|
45
45
|
let(:command_opts) { {} }
|
46
46
|
|
47
47
|
let :command_options do
|
48
|
-
{ :
|
48
|
+
{ :render_document => {:value => ssml_doc} }.merge(command_opts)
|
49
49
|
end
|
50
50
|
|
51
51
|
let :original_command do
|
52
52
|
Punchblock::Component::Output.new command_options
|
53
53
|
end
|
54
54
|
|
55
|
-
describe '
|
55
|
+
describe 'document' do
|
56
56
|
context 'unset' do
|
57
|
-
let(:
|
57
|
+
let(:ssml_doc) { nil }
|
58
|
+
|
58
59
|
it "should return an error and not execute any actions" do
|
59
60
|
subject.execute
|
60
61
|
error = ProtocolError.new.setup 'option error', 'An SSML document is required.'
|
@@ -62,38 +63,10 @@ module Punchblock
|
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
65
|
-
context 'with a string (not SSML)' do
|
66
|
-
let :command_options do
|
67
|
-
{ :text => 'Foo Bar' }
|
68
|
-
end
|
69
|
-
|
70
|
-
it "should return an unrenderable document error" do
|
71
|
-
subject.execute
|
72
|
-
error = ProtocolError.new.setup 'unrenderable document error', 'The provided document could not be rendered. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details.'
|
73
|
-
original_command.response(0.1).should be == error
|
74
|
-
end
|
75
|
-
|
76
|
-
context 'with a single text node without spaces' do
|
77
|
-
let(:audio_filename) { 'http://foo.com/bar.mp3' }
|
78
|
-
let :command_options do
|
79
|
-
{
|
80
|
-
:ssml => RubySpeech::SSML.draw { string audio_filename }
|
81
|
-
}
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'should playback the audio file using the playback application' do
|
85
|
-
expect_playback
|
86
|
-
subject.execute
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
66
|
context 'with a single audio SSML node' do
|
92
67
|
let(:audio_filename) { 'http://foo.com/bar.mp3' }
|
93
|
-
let :
|
94
|
-
{
|
95
|
-
:ssml => RubySpeech::SSML.draw { audio :src => audio_filename }
|
96
|
-
}
|
68
|
+
let :ssml_doc do
|
69
|
+
RubySpeech::SSML.draw { audio :src => audio_filename }
|
97
70
|
end
|
98
71
|
|
99
72
|
it 'should playback the audio file using the playback application' do
|
@@ -105,7 +78,7 @@ module Punchblock
|
|
105
78
|
expect_playback
|
106
79
|
subject.execute
|
107
80
|
subject.handle_es_event RubyFS::Event.new(nil, :event_name => "CHANNEL_EXECUTE_COMPLETE", :application_response => 'FILE PLAYED')
|
108
|
-
original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::
|
81
|
+
original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Finish
|
109
82
|
end
|
110
83
|
|
111
84
|
context "when playback returns an error" do
|
@@ -125,13 +98,11 @@ module Punchblock
|
|
125
98
|
context 'with multiple audio SSML nodes' do
|
126
99
|
let(:audio_filename1) { 'http://foo.com/bar.mp3' }
|
127
100
|
let(:audio_filename2) { 'http://foo.com/baz.mp3' }
|
128
|
-
let :
|
129
|
-
|
130
|
-
:
|
131
|
-
|
132
|
-
|
133
|
-
end
|
134
|
-
}
|
101
|
+
let :ssml_doc do
|
102
|
+
RubySpeech::SSML.draw do
|
103
|
+
audio :src => audio_filename1
|
104
|
+
audio :src => audio_filename2
|
105
|
+
end
|
135
106
|
end
|
136
107
|
|
137
108
|
it 'should playback all audio files using playback' do
|
@@ -143,17 +114,15 @@ module Punchblock
|
|
143
114
|
expect_playback([audio_filename1, audio_filename2].join('!'))
|
144
115
|
subject.execute
|
145
116
|
subject.handle_es_event RubyFS::Event.new(nil, :event_name => "CHANNEL_EXECUTE_COMPLETE", :application_response => "FILE PLAYED")
|
146
|
-
original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::
|
117
|
+
original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Finish
|
147
118
|
end
|
148
119
|
end
|
149
120
|
|
150
121
|
context "with an SSML document containing elements other than <audio/>" do
|
151
|
-
let :
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
end
|
156
|
-
}
|
122
|
+
let :ssml_doc do
|
123
|
+
RubySpeech::SSML.draw do
|
124
|
+
string "Foo Bar"
|
125
|
+
end
|
157
126
|
end
|
158
127
|
|
159
128
|
it "should return an unrenderable document error" do
|
@@ -162,6 +131,15 @@ module Punchblock
|
|
162
131
|
original_command.response(0.1).should be == error
|
163
132
|
end
|
164
133
|
end
|
134
|
+
|
135
|
+
context 'with multiple documents' do
|
136
|
+
let(:command_opts) { { :render_documents => [{:value => ssml_doc}, {:value => ssml_doc}] } }
|
137
|
+
it "should return an error and not execute any actions" do
|
138
|
+
subject.execute
|
139
|
+
error = ProtocolError.new.setup 'option error', 'Only a single document is supported.'
|
140
|
+
original_command.response(0.1).should be == error
|
141
|
+
end
|
142
|
+
end
|
165
143
|
end
|
166
144
|
|
167
145
|
describe 'start-offset' do
|
@@ -304,11 +282,11 @@ module Punchblock
|
|
304
282
|
end
|
305
283
|
end
|
306
284
|
|
307
|
-
context "set to :
|
308
|
-
let(:command_opts) { { :interrupt_on => :
|
285
|
+
context "set to :voice" do
|
286
|
+
let(:command_opts) { { :interrupt_on => :voice } }
|
309
287
|
it "should return an error and not execute any actions" do
|
310
288
|
subject.execute
|
311
|
-
error = ProtocolError.new.setup 'option error', 'An interrupt-on value of
|
289
|
+
error = ProtocolError.new.setup 'option error', 'An interrupt-on value of voice is unsupported.'
|
312
290
|
original_command.response(0.1).should be == error
|
313
291
|
end
|
314
292
|
end
|