punchblock 1.9.4 → 2.0.0.beta1
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.
- 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
|
@@ -6,27 +6,55 @@ module Punchblock
|
|
|
6
6
|
module Component
|
|
7
7
|
describe Record do
|
|
8
8
|
it 'registers itself' do
|
|
9
|
-
RayoNode.class_from_registration(:record, 'urn:xmpp:rayo:record:1').should be ==
|
|
9
|
+
RayoNode.class_from_registration(:record, 'urn:xmpp:rayo:record:1').should be == described_class
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
describe "when setting options in initializer" do
|
|
13
13
|
subject do
|
|
14
14
|
Record.new :format => 'WAV',
|
|
15
15
|
:start_beep => true,
|
|
16
|
+
:stop_beep => true,
|
|
16
17
|
:start_paused => false,
|
|
17
18
|
:max_duration => 500000,
|
|
18
19
|
:initial_timeout => 10000,
|
|
19
20
|
:final_timeout => 30000,
|
|
20
|
-
:direction => :duplex
|
|
21
|
+
:direction => :duplex,
|
|
22
|
+
:mix => true
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
its(:format) { should be == 'WAV' }
|
|
24
26
|
its(:start_beep) { should be == true }
|
|
27
|
+
its(:stop_beep) { should be == true }
|
|
25
28
|
its(:start_paused) { should be == false }
|
|
26
29
|
its(:max_duration) { should be == 500000 }
|
|
27
30
|
its(:initial_timeout) { should be == 10000 }
|
|
28
31
|
its(:final_timeout) { should be == 30000 }
|
|
29
32
|
its(:direction) { should be == :duplex }
|
|
33
|
+
its(:mix) { should be == true }
|
|
34
|
+
|
|
35
|
+
describe "exporting to Rayo" do
|
|
36
|
+
it "should export to XML that can be understood by its parser" do
|
|
37
|
+
new_instance = RayoNode.from_xml subject.to_rayo
|
|
38
|
+
new_instance.should be_instance_of described_class
|
|
39
|
+
new_instance.format.should be == 'WAV'
|
|
40
|
+
new_instance.start_beep.should be == true
|
|
41
|
+
new_instance.stop_beep.should be == true
|
|
42
|
+
new_instance.start_paused.should be == false
|
|
43
|
+
new_instance.max_duration.should be == 500000
|
|
44
|
+
new_instance.initial_timeout.should be == 10000
|
|
45
|
+
new_instance.final_timeout.should be == 30000
|
|
46
|
+
new_instance.direction.should be == :duplex
|
|
47
|
+
new_instance.mix.should be == true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should render to a parent node if supplied" do
|
|
51
|
+
doc = Nokogiri::XML::Document.new
|
|
52
|
+
parent = Nokogiri::XML::Node.new 'foo', doc
|
|
53
|
+
doc.root = parent
|
|
54
|
+
rayo_doc = subject.to_rayo(parent)
|
|
55
|
+
rayo_doc.should == parent
|
|
56
|
+
end
|
|
57
|
+
end
|
|
30
58
|
end
|
|
31
59
|
|
|
32
60
|
describe "from a stanza" do
|
|
@@ -35,31 +63,35 @@ module Punchblock
|
|
|
35
63
|
<record xmlns="urn:xmpp:rayo:record:1"
|
|
36
64
|
format="WAV"
|
|
37
65
|
start-beep="true"
|
|
66
|
+
stop-beep="true"
|
|
38
67
|
start-paused="false"
|
|
39
68
|
max-duration="500000"
|
|
40
69
|
initial-timeout="10000"
|
|
41
70
|
direction="duplex"
|
|
71
|
+
mix="true"
|
|
42
72
|
final-timeout="30000"/>
|
|
43
73
|
MESSAGE
|
|
44
74
|
end
|
|
45
75
|
|
|
46
|
-
subject { RayoNode.
|
|
76
|
+
subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
|
|
47
77
|
|
|
48
78
|
it { should be_instance_of Record }
|
|
49
79
|
|
|
50
80
|
its(:format) { should be == 'WAV' }
|
|
51
81
|
its(:start_beep) { should be == true }
|
|
82
|
+
its(:stop_beep) { should be == true }
|
|
52
83
|
its(:start_paused) { should be == false }
|
|
53
84
|
its(:max_duration) { should be == 500000 }
|
|
54
85
|
its(:initial_timeout) { should be == 10000 }
|
|
55
86
|
its(:final_timeout) { should be == 30000 }
|
|
56
87
|
its(:direction) { should be == :duplex }
|
|
88
|
+
its(:mix) { should be == true }
|
|
57
89
|
end
|
|
58
90
|
|
|
59
91
|
describe "with a direction" do
|
|
60
92
|
[nil, :duplex, :send, :recv].each do |direction|
|
|
61
93
|
describe direction do
|
|
62
|
-
subject {
|
|
94
|
+
subject { described_class.new :direction => direction }
|
|
63
95
|
|
|
64
96
|
its(:direction) { should be == direction }
|
|
65
97
|
end
|
|
@@ -73,14 +105,14 @@ module Punchblock
|
|
|
73
105
|
|
|
74
106
|
describe "blahblahblah" do
|
|
75
107
|
it "should raise an error" do
|
|
76
|
-
expect {
|
|
108
|
+
expect { described_class.new(:direction => :blahblahblah) }.to raise_error ArgumentError
|
|
77
109
|
end
|
|
78
110
|
end
|
|
79
111
|
end
|
|
80
112
|
|
|
81
113
|
describe "actions" do
|
|
82
|
-
let(:mock_client) {
|
|
83
|
-
let(:command) {
|
|
114
|
+
let(:mock_client) { double 'Client' }
|
|
115
|
+
let(:command) { described_class.new }
|
|
84
116
|
|
|
85
117
|
before do
|
|
86
118
|
command.component_id = 'abc123'
|
|
@@ -185,7 +217,7 @@ module Punchblock
|
|
|
185
217
|
</complete>
|
|
186
218
|
MESSAGE
|
|
187
219
|
end
|
|
188
|
-
let(:event) { RayoNode.
|
|
220
|
+
let(:event) { RayoNode.from_xml(parse_stanza(stanza).root) }
|
|
189
221
|
|
|
190
222
|
before do
|
|
191
223
|
subject.request!
|
|
@@ -235,31 +267,37 @@ module Punchblock
|
|
|
235
267
|
end
|
|
236
268
|
end
|
|
237
269
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
270
|
+
{
|
|
271
|
+
Record::Complete::MaxDuration => :'max-duration',
|
|
272
|
+
Record::Complete::InitialTimeout => :'initial-timeout',
|
|
273
|
+
Record::Complete::FinalTimeout => :'final-timeout',
|
|
274
|
+
}.each do |klass, element_name|
|
|
275
|
+
describe klass do
|
|
276
|
+
let :stanza do
|
|
277
|
+
<<-MESSAGE
|
|
278
|
+
<complete xmlns='urn:xmpp:rayo:ext:1'>
|
|
279
|
+
<#{element_name} xmlns='urn:xmpp:rayo:record:complete:1'/>
|
|
280
|
+
<recording xmlns='urn:xmpp:rayo:record:complete:1' uri="file:/tmp/rayo7451601434771683422.mp3" duration="34000" size="23450"/>
|
|
281
|
+
</complete>
|
|
282
|
+
MESSAGE
|
|
283
|
+
end
|
|
247
284
|
|
|
248
|
-
|
|
249
|
-
|
|
285
|
+
describe "#reason" do
|
|
286
|
+
subject { RayoNode.from_xml(parse_stanza(stanza).root).reason }
|
|
250
287
|
|
|
251
|
-
|
|
288
|
+
it { should be_instance_of klass }
|
|
252
289
|
|
|
253
|
-
|
|
254
|
-
|
|
290
|
+
its(:name) { should be == element_name }
|
|
291
|
+
end
|
|
255
292
|
|
|
256
|
-
|
|
257
|
-
|
|
293
|
+
describe "#recording" do
|
|
294
|
+
subject { RayoNode.from_xml(parse_stanza(stanza).root).recording }
|
|
258
295
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
296
|
+
it { should be_instance_of Record::Recording }
|
|
297
|
+
its(:uri) { should be == "file:/tmp/rayo7451601434771683422.mp3" }
|
|
298
|
+
its(:duration) { should be == 34000 }
|
|
299
|
+
its(:size) { should be == 23450 }
|
|
300
|
+
end
|
|
263
301
|
end
|
|
264
302
|
end
|
|
265
303
|
|
|
@@ -274,7 +312,7 @@ module Punchblock
|
|
|
274
312
|
end
|
|
275
313
|
|
|
276
314
|
describe "#reason" do
|
|
277
|
-
subject { RayoNode.
|
|
315
|
+
subject { RayoNode.from_xml(parse_stanza(stanza).root).reason }
|
|
278
316
|
|
|
279
317
|
it { should be_instance_of Event::Complete::Stop }
|
|
280
318
|
|
|
@@ -282,7 +320,7 @@ module Punchblock
|
|
|
282
320
|
end
|
|
283
321
|
|
|
284
322
|
describe "#recording" do
|
|
285
|
-
subject { RayoNode.
|
|
323
|
+
subject { RayoNode.from_xml(parse_stanza(stanza).root).recording }
|
|
286
324
|
|
|
287
325
|
it { should be_instance_of Record::Recording }
|
|
288
326
|
its(:uri) { should be == "file:/tmp/rayo7451601434771683422.mp3" }
|
|
@@ -300,7 +338,7 @@ module Punchblock
|
|
|
300
338
|
end
|
|
301
339
|
|
|
302
340
|
describe "#reason" do
|
|
303
|
-
subject { RayoNode.
|
|
341
|
+
subject { RayoNode.from_xml(parse_stanza(stanza).root).reason }
|
|
304
342
|
|
|
305
343
|
it { should be_instance_of Event::Complete::Hangup }
|
|
306
344
|
|
|
@@ -308,7 +346,7 @@ module Punchblock
|
|
|
308
346
|
end
|
|
309
347
|
|
|
310
348
|
describe "#recording" do
|
|
311
|
-
subject { RayoNode.
|
|
349
|
+
subject { RayoNode.from_xml(parse_stanza(stanza).root).recording }
|
|
312
350
|
|
|
313
351
|
it { should be_instance_of Record::Recording }
|
|
314
352
|
its(:uri) { should be == "file:/tmp/rayo7451601434771683422.mp3" }
|
|
@@ -15,7 +15,7 @@ module Punchblock
|
|
|
15
15
|
}
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
let(:mock_event_handler) {
|
|
18
|
+
let(:mock_event_handler) { double('Event Handler').as_null_object }
|
|
19
19
|
|
|
20
20
|
let(:connection) { Asterisk.new options }
|
|
21
21
|
|
|
@@ -25,7 +25,8 @@ module Punchblock
|
|
|
25
25
|
subject.event_handler = mock_event_handler
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
its(:ami_client) { should be_a
|
|
28
|
+
its(:ami_client) { should be_a RubyAMIStreamProxy }
|
|
29
|
+
its('ami_client.stream') { should be_a RubyAMI::Stream }
|
|
29
30
|
|
|
30
31
|
it 'should set the connection on the translator' do
|
|
31
32
|
subject.translator.connection.should be subject
|
|
@@ -42,6 +43,19 @@ module Punchblock
|
|
|
42
43
|
end
|
|
43
44
|
lambda { subject.run }.should raise_error DisconnectedError
|
|
44
45
|
end
|
|
46
|
+
|
|
47
|
+
it 'rebuilds the RubyAMI::Stream if dead' do
|
|
48
|
+
subject.ami_client.async.should_receive(:run).once do
|
|
49
|
+
subject.ami_client.terminate
|
|
50
|
+
end
|
|
51
|
+
lambda { subject.run }.should raise_error DisconnectedError
|
|
52
|
+
subject.ami_client.alive?.should be_false
|
|
53
|
+
subject.should_receive(:new_ami_stream).once do
|
|
54
|
+
subject.ami_client.alive?.should be_true
|
|
55
|
+
subject.ami_client.async.should_receive(:run).once
|
|
56
|
+
end
|
|
57
|
+
lambda { subject.run }.should_not raise_error DisconnectedError
|
|
58
|
+
end
|
|
45
59
|
end
|
|
46
60
|
|
|
47
61
|
describe '#stop' do
|
|
@@ -65,7 +79,7 @@ module Punchblock
|
|
|
65
79
|
|
|
66
80
|
describe '#write' do
|
|
67
81
|
it 'sends a command to the translator' do
|
|
68
|
-
command =
|
|
82
|
+
command = double 'Command'
|
|
69
83
|
options = {:foo => :bar}
|
|
70
84
|
subject.translator.async.should_receive(:execute_command).once.with command, options
|
|
71
85
|
subject.write command, options
|
|
@@ -17,11 +17,11 @@ module Punchblock
|
|
|
17
17
|
}
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
let(:mock_event_handler) {
|
|
20
|
+
let(:mock_event_handler) { double('Event Handler').as_null_object }
|
|
21
21
|
|
|
22
22
|
let(:connection) { described_class.new options }
|
|
23
23
|
|
|
24
|
-
let(:mock_stream) {
|
|
24
|
+
let(:mock_stream) { double 'RubyFS::Stream' }
|
|
25
25
|
|
|
26
26
|
subject { connection }
|
|
27
27
|
|
|
@@ -62,7 +62,7 @@ module Punchblock
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
it 'sends events from RubyFS to the translator' do
|
|
65
|
-
event =
|
|
65
|
+
event = double 'RubyFS::Event'
|
|
66
66
|
subject.translator.async.should_receive(:handle_es_event).once.with event
|
|
67
67
|
subject.translator.async.should_receive(:handle_es_event).once.with RubyFS::Stream::Disconnected.new
|
|
68
68
|
subject.stream.fire_event event
|
|
@@ -70,7 +70,7 @@ module Punchblock
|
|
|
70
70
|
|
|
71
71
|
describe '#write' do
|
|
72
72
|
it 'sends a command to the translator' do
|
|
73
|
-
command =
|
|
73
|
+
command = double 'Command'
|
|
74
74
|
options = {:foo => :bar}
|
|
75
75
|
subject.translator.async.should_receive(:execute_command).once.with command, options
|
|
76
76
|
subject.write command, options
|
|
@@ -8,7 +8,7 @@ module Punchblock
|
|
|
8
8
|
let(:options) { { :root_domain => 'rayo.net' } }
|
|
9
9
|
let(:connection) { XMPP.new({:username => '1@app.rayo.net', :password => 1}.merge(options)) }
|
|
10
10
|
|
|
11
|
-
let(:mock_event_handler) {
|
|
11
|
+
let(:mock_event_handler) { double('Event Handler').as_null_object }
|
|
12
12
|
|
|
13
13
|
before do
|
|
14
14
|
connection.event_handler = mock_event_handler
|
|
@@ -21,40 +21,18 @@ module Punchblock
|
|
|
21
21
|
let(:options) { { :username => '1@app.rayo.net' } }
|
|
22
22
|
|
|
23
23
|
its(:root_domain) { should be == 'app.rayo.net' }
|
|
24
|
-
its(:calls_domain) { should be == 'calls.app.rayo.net' }
|
|
25
|
-
its(:mixers_domain) { should be == 'mixers.app.rayo.net' }
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
context "with only a rayo domain set" do
|
|
29
27
|
let(:options) { { :rayo_domain => 'rayo.org' } }
|
|
30
28
|
|
|
31
29
|
its(:root_domain) { should be == 'rayo.org' }
|
|
32
|
-
its(:calls_domain) { should be == 'calls.rayo.org' }
|
|
33
|
-
its(:mixers_domain) { should be == 'mixers.rayo.org' }
|
|
34
30
|
end
|
|
35
31
|
|
|
36
32
|
context "with only a root domain set" do
|
|
37
33
|
let(:options) { { :root_domain => 'rayo.org' } }
|
|
38
34
|
|
|
39
35
|
its(:root_domain) { should be == 'rayo.org' }
|
|
40
|
-
its(:calls_domain) { should be == 'calls.rayo.org' }
|
|
41
|
-
its(:mixers_domain) { should be == 'mixers.rayo.org' }
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
context "with a root domain and calls domain set" do
|
|
45
|
-
let(:options) { { :root_domain => 'rayo.org', :calls_domain => 'phone_calls.rayo.org' } }
|
|
46
|
-
|
|
47
|
-
its(:root_domain) { should be == 'rayo.org' }
|
|
48
|
-
its(:calls_domain) { should be == 'phone_calls.rayo.org' }
|
|
49
|
-
its(:mixers_domain) { should be == 'mixers.rayo.org' }
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
context "with a root domain and mixers domain set" do
|
|
53
|
-
let(:options) { { :root_domain => 'rayo.org', :mixers_domain => 'conferences.rayo.org' } }
|
|
54
|
-
|
|
55
|
-
its(:root_domain) { should be == 'rayo.org' }
|
|
56
|
-
its(:calls_domain) { should be == 'calls.rayo.org' }
|
|
57
|
-
its(:mixers_domain) { should be == 'conferences.rayo.org' }
|
|
58
36
|
end
|
|
59
37
|
end
|
|
60
38
|
|
|
@@ -185,15 +163,10 @@ module Punchblock
|
|
|
185
163
|
event.should be_instance_of Event::Offer
|
|
186
164
|
event.target_call_id.should be == '9f00061'
|
|
187
165
|
event.domain.should be == 'call.rayo.net'
|
|
166
|
+
event.transport.should be == 'xmpp'
|
|
188
167
|
end
|
|
189
168
|
handle_presence
|
|
190
169
|
end
|
|
191
|
-
|
|
192
|
-
it "should populate the call map with the domain for the call ID" do
|
|
193
|
-
handle_presence
|
|
194
|
-
callmap = connection.instance_variable_get(:'@callmap')
|
|
195
|
-
callmap['9f00061'].should be == 'call.rayo.net'
|
|
196
|
-
end
|
|
197
170
|
end
|
|
198
171
|
|
|
199
172
|
describe "from something that's not a real event" do
|
|
@@ -220,7 +193,7 @@ module Punchblock
|
|
|
220
193
|
let(:component_id) { 'abc123' }
|
|
221
194
|
let :error_xml do
|
|
222
195
|
<<-MSG
|
|
223
|
-
<iq type="error" id="blather000e" from="f6d437f4-1e18-457b-99f8-b5d853f50347@
|
|
196
|
+
<iq type="error" id="blather000e" from="f6d437f4-1e18-457b-99f8-b5d853f50347@call.rayo.net/abc123" to="usera@rayo.net">
|
|
224
197
|
<output xmlns="urn:xmpp:rayo:output:1"/>
|
|
225
198
|
<error type="cancel">
|
|
226
199
|
<item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
|
|
@@ -271,17 +244,26 @@ module Punchblock
|
|
|
271
244
|
end
|
|
272
245
|
|
|
273
246
|
context "with a call command" do
|
|
274
|
-
let(:command) { Command::Answer.new
|
|
275
|
-
let(:expected_jid) { 'abc123@
|
|
247
|
+
let(:command) { Command::Answer.new target_call_id: 'abc123' }
|
|
248
|
+
let(:expected_jid) { 'abc123@rayo.net' }
|
|
276
249
|
|
|
277
250
|
it "should use the correct JID" do
|
|
278
251
|
stanza.to.should be == expected_jid
|
|
279
252
|
end
|
|
253
|
+
|
|
254
|
+
context "with a domain specified" do
|
|
255
|
+
let(:expected_jid) { 'abc123@calls.rayo.net' }
|
|
256
|
+
|
|
257
|
+
it "should use the specified domain in the JID" do
|
|
258
|
+
stanza = subject.prep_command_for_execution command, domain: 'calls.rayo.net'
|
|
259
|
+
stanza.to.should be == expected_jid
|
|
260
|
+
end
|
|
261
|
+
end
|
|
280
262
|
end
|
|
281
263
|
|
|
282
264
|
context "with a call component" do
|
|
283
265
|
let(:command) { Component::Output.new :target_call_id => 'abc123' }
|
|
284
|
-
let(:expected_jid) { 'abc123@
|
|
266
|
+
let(:expected_jid) { 'abc123@rayo.net' }
|
|
285
267
|
|
|
286
268
|
it "should use the correct JID" do
|
|
287
269
|
stanza.to.should be == expected_jid
|
|
@@ -290,7 +272,7 @@ module Punchblock
|
|
|
290
272
|
|
|
291
273
|
context "with a call component command" do
|
|
292
274
|
let(:command) { Component::Stop.new :target_call_id => 'abc123', :component_id => 'foobar' }
|
|
293
|
-
let(:expected_jid) { 'abc123@
|
|
275
|
+
let(:expected_jid) { 'abc123@rayo.net/foobar' }
|
|
294
276
|
|
|
295
277
|
it "should use the correct JID" do
|
|
296
278
|
stanza.to.should be == expected_jid
|
|
@@ -299,7 +281,7 @@ module Punchblock
|
|
|
299
281
|
|
|
300
282
|
context "with a mixer component" do
|
|
301
283
|
let(:command) { Component::Output.new :target_mixer_name => 'abc123' }
|
|
302
|
-
let(:expected_jid) { 'abc123@
|
|
284
|
+
let(:expected_jid) { 'abc123@rayo.net' }
|
|
303
285
|
|
|
304
286
|
it "should use the correct JID" do
|
|
305
287
|
stanza.to.should be == expected_jid
|
|
@@ -308,7 +290,7 @@ module Punchblock
|
|
|
308
290
|
|
|
309
291
|
context "with a mixer component command" do
|
|
310
292
|
let(:command) { Component::Stop.new :target_mixer_name => 'abc123', :component_id => 'foobar' }
|
|
311
|
-
let(:expected_jid) { 'abc123@
|
|
293
|
+
let(:expected_jid) { 'abc123@rayo.net/foobar' }
|
|
312
294
|
|
|
313
295
|
it "should use the correct JID" do
|
|
314
296
|
stanza.to.should be == expected_jid
|
|
@@ -325,7 +307,7 @@ module Punchblock
|
|
|
325
307
|
|
|
326
308
|
let :active_speaker_xml do
|
|
327
309
|
<<-MSG
|
|
328
|
-
<presence to='16577@app.rayo.net/1' from='foomixer@
|
|
310
|
+
<presence to='16577@app.rayo.net/1' from='foomixer@rayo.net'>
|
|
329
311
|
<started-speaking xmlns="urn:xmpp:rayo:1" call-id="foocall"/>
|
|
330
312
|
</presence>
|
|
331
313
|
MSG
|
|
@@ -338,7 +320,7 @@ module Punchblock
|
|
|
338
320
|
event.should be_instance_of Event::StartedSpeaking
|
|
339
321
|
event.target_mixer_name.should be == 'foomixer'
|
|
340
322
|
event.target_call_id.should be nil
|
|
341
|
-
event.domain.should be == '
|
|
323
|
+
event.domain.should be == 'rayo.net'
|
|
342
324
|
end
|
|
343
325
|
connection.__send__ :handle_presence, active_speaker_event
|
|
344
326
|
end
|
|
@@ -6,7 +6,7 @@ module Punchblock
|
|
|
6
6
|
class Event
|
|
7
7
|
describe Answered do
|
|
8
8
|
it 'registers itself' do
|
|
9
|
-
RayoNode.class_from_registration(:answered, 'urn:xmpp:rayo:1').should be ==
|
|
9
|
+
RayoNode.class_from_registration(:answered, 'urn:xmpp:rayo:1').should be == described_class
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
describe "from a stanza" do
|
|
@@ -20,23 +20,25 @@ module Punchblock
|
|
|
20
20
|
MESSAGE
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
subject { RayoNode.
|
|
23
|
+
subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
|
|
24
24
|
|
|
25
|
-
it { should be_instance_of
|
|
25
|
+
it { should be_instance_of described_class }
|
|
26
26
|
|
|
27
27
|
it_should_behave_like 'event'
|
|
28
|
-
|
|
28
|
+
its(:headers) { should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
context "with no headers provided" do
|
|
31
|
+
let(:stanza) { '<answered xmlns="urn:xmpp:rayo:1"/>' }
|
|
32
|
+
|
|
33
|
+
its(:headers) { should == {} }
|
|
34
|
+
end
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
describe "when setting options in initializer" do
|
|
34
|
-
subject
|
|
35
|
-
Answered.new :headers => { :x_skill => "agent", :x_customer_id => "8877" }
|
|
36
|
-
end
|
|
38
|
+
subject { described_class.new headers: { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
its(:headers) { should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
|
|
39
41
|
end
|
|
40
42
|
end
|
|
41
43
|
end
|
|
42
|
-
end
|
|
44
|
+
end
|
|
@@ -8,7 +8,7 @@ module Punchblock
|
|
|
8
8
|
module AMI
|
|
9
9
|
describe Event do
|
|
10
10
|
it 'registers itself' do
|
|
11
|
-
RayoNode.class_from_registration(:event, 'urn:xmpp:rayo:asterisk:ami:1').should be ==
|
|
11
|
+
RayoNode.class_from_registration(:event, 'urn:xmpp:rayo:asterisk:ami:1').should be == described_class
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
describe "from a stanza" do
|
|
@@ -17,46 +17,51 @@ module Punchblock
|
|
|
17
17
|
<event xmlns="urn:xmpp:rayo:asterisk:ami:1" name="Newchannel">
|
|
18
18
|
<attribute name="Channel" value="SIP/101-3f3f"/>
|
|
19
19
|
<attribute name="State" value="Ring"/>
|
|
20
|
-
<attribute name="Callerid" value="101"/>
|
|
21
|
-
<attribute name="Uniqueid" value="1094154427.10"/>
|
|
22
20
|
</event>
|
|
23
21
|
MESSAGE
|
|
24
22
|
end
|
|
25
23
|
|
|
26
|
-
subject { RayoNode.
|
|
24
|
+
subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
|
|
27
25
|
|
|
28
26
|
it { should be_instance_of Event }
|
|
29
27
|
|
|
30
28
|
it_should_behave_like 'event'
|
|
31
29
|
|
|
32
|
-
its(:name)
|
|
33
|
-
its(:
|
|
34
|
-
its(:
|
|
30
|
+
its(:name) { should be == 'Newchannel' }
|
|
31
|
+
its(:headers) { should be == {'Channel' => 'SIP/101-3f3f', 'State' => 'Ring'} }
|
|
32
|
+
its(:attributes) { should be == {'Channel' => 'SIP/101-3f3f', 'State' => 'Ring'} } # For BC
|
|
35
33
|
end
|
|
36
34
|
|
|
37
35
|
describe "when setting options in initializer" do
|
|
38
36
|
subject do
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
:state => 'Ring',
|
|
42
|
-
:callerid => '101',
|
|
43
|
-
:uniqueid => '1094154427.10'}
|
|
37
|
+
described_class.new name: 'Newchannel',
|
|
38
|
+
headers: {'Channel' => 'SIP/101-3f3f', 'State' => 'Ring'}
|
|
44
39
|
end
|
|
45
40
|
|
|
46
|
-
its(:name)
|
|
47
|
-
its(:
|
|
48
|
-
its(:
|
|
49
|
-
|
|
41
|
+
its(:name) { should be == 'Newchannel' }
|
|
42
|
+
its(:headers) { should be == {'Channel' => 'SIP/101-3f3f', 'State' => 'Ring'} }
|
|
43
|
+
its(:attributes) { should be == {'Channel' => 'SIP/101-3f3f', 'State' => 'Ring'} } # For BC
|
|
44
|
+
|
|
45
|
+
describe "exporting to Rayo" do
|
|
46
|
+
it "should export to XML that can be understood by its parser" do
|
|
47
|
+
new_instance = RayoNode.from_xml subject.to_rayo
|
|
48
|
+
new_instance.should be_instance_of described_class
|
|
49
|
+
new_instance.name.should == 'Newchannel'
|
|
50
|
+
new_instance.headers.should == {'Channel' => 'SIP/101-3f3f', 'State' => 'Ring'}
|
|
51
|
+
new_instance.attributes.should == {'Channel' => 'SIP/101-3f3f', 'State' => 'Ring'} # For BC
|
|
52
|
+
end
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
it "should render to a parent node if supplied" do
|
|
55
|
+
doc = Nokogiri::XML::Document.new
|
|
56
|
+
parent = Nokogiri::XML::Node.new 'foo', doc
|
|
57
|
+
doc.root = parent
|
|
58
|
+
rayo_doc = subject.to_rayo(parent)
|
|
59
|
+
rayo_doc.should == parent
|
|
60
|
+
end
|
|
56
61
|
end
|
|
57
62
|
end
|
|
58
63
|
end
|
|
59
64
|
end
|
|
60
65
|
end
|
|
61
66
|
end
|
|
62
|
-
end
|
|
67
|
+
end
|
|
@@ -6,11 +6,11 @@ module Punchblock
|
|
|
6
6
|
class Event
|
|
7
7
|
describe Complete do
|
|
8
8
|
it 'registers itself' do
|
|
9
|
-
RayoNode.class_from_registration(:complete, 'urn:xmpp:rayo:ext:1').should be ==
|
|
9
|
+
RayoNode.class_from_registration(:complete, 'urn:xmpp:rayo:ext:1').should be == described_class
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
describe "setting a reason" do
|
|
13
|
-
let(:reason) {
|
|
13
|
+
let(:reason) { Complete::Stop.new }
|
|
14
14
|
|
|
15
15
|
subject { described_class.new }
|
|
16
16
|
|
|
@@ -21,19 +21,15 @@ module Punchblock
|
|
|
21
21
|
|
|
22
22
|
describe "comparing for equality" do
|
|
23
23
|
subject do
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
c.component_id = 'abcd'
|
|
28
|
-
end
|
|
24
|
+
described_class.new reason: Complete::Stop.new,
|
|
25
|
+
target_call_id: '1234',
|
|
26
|
+
component_id: 'abcd'
|
|
29
27
|
end
|
|
30
28
|
|
|
31
29
|
let :other_complete do
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
c.component_id = component_id
|
|
36
|
-
end
|
|
30
|
+
described_class.new reason: reason,
|
|
31
|
+
target_call_id: call_id,
|
|
32
|
+
component_id: component_id
|
|
37
33
|
end
|
|
38
34
|
|
|
39
35
|
context 'with reason, call id and component id the same' do
|
|
@@ -81,18 +77,18 @@ module Punchblock
|
|
|
81
77
|
let :stanza do
|
|
82
78
|
<<-MESSAGE
|
|
83
79
|
<complete xmlns='urn:xmpp:rayo:ext:1'>
|
|
84
|
-
<
|
|
80
|
+
<stop xmlns='urn:xmpp:rayo:ext:complete:1' />
|
|
85
81
|
</complete>
|
|
86
82
|
MESSAGE
|
|
87
83
|
end
|
|
88
84
|
|
|
89
|
-
subject { RayoNode.
|
|
85
|
+
subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
|
|
90
86
|
|
|
91
|
-
it { should be_instance_of
|
|
87
|
+
it { should be_instance_of described_class }
|
|
92
88
|
|
|
93
89
|
it_should_behave_like 'event'
|
|
94
90
|
|
|
95
|
-
its(:reason) { should be_instance_of
|
|
91
|
+
its(:reason) { should be_instance_of Complete::Stop }
|
|
96
92
|
end
|
|
97
93
|
end
|
|
98
94
|
|
|
@@ -105,7 +101,7 @@ module Punchblock
|
|
|
105
101
|
MESSAGE
|
|
106
102
|
end
|
|
107
103
|
|
|
108
|
-
subject { RayoNode.
|
|
104
|
+
subject { RayoNode.from_xml(parse_stanza(stanza).root).reason }
|
|
109
105
|
|
|
110
106
|
it { should be_instance_of Complete::Stop }
|
|
111
107
|
|
|
@@ -121,7 +117,7 @@ module Punchblock
|
|
|
121
117
|
MESSAGE
|
|
122
118
|
end
|
|
123
119
|
|
|
124
|
-
subject { RayoNode.
|
|
120
|
+
subject { RayoNode.from_xml(parse_stanza(stanza).root).reason }
|
|
125
121
|
|
|
126
122
|
it { should be_instance_of Complete::Hangup }
|
|
127
123
|
|
|
@@ -139,7 +135,7 @@ module Punchblock
|
|
|
139
135
|
MESSAGE
|
|
140
136
|
end
|
|
141
137
|
|
|
142
|
-
subject { RayoNode.
|
|
138
|
+
subject { RayoNode.from_xml(parse_stanza(stanza).root).reason }
|
|
143
139
|
|
|
144
140
|
it { should be_instance_of Complete::Error }
|
|
145
141
|
|