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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -2
  4. data/CHANGELOG.md +17 -0
  5. data/Gemfile +1 -0
  6. data/Guardfile +4 -0
  7. data/README.markdown +6 -0
  8. data/Rakefile +16 -0
  9. data/benchmarks/ami_event_name_comparison.rb +14 -0
  10. data/benchmarks/channel.rb +27 -0
  11. data/lib/punchblock/client.rb +2 -6
  12. data/lib/punchblock/command/accept.rb +3 -24
  13. data/lib/punchblock/command/answer.rb +3 -24
  14. data/lib/punchblock/command/dial.rb +24 -76
  15. data/lib/punchblock/command/hangup.rb +3 -19
  16. data/lib/punchblock/command/join.rb +21 -70
  17. data/lib/punchblock/command/mute.rb +3 -3
  18. data/lib/punchblock/command/redirect.rb +6 -39
  19. data/lib/punchblock/command/reject.rb +14 -54
  20. data/lib/punchblock/command/unjoin.rb +8 -40
  21. data/lib/punchblock/command/unmute.rb +3 -3
  22. data/lib/punchblock/command_node.rb +0 -17
  23. data/lib/punchblock/component/asterisk/agi/command.rb +20 -127
  24. data/lib/punchblock/component/asterisk/ami/action.rb +30 -117
  25. data/lib/punchblock/component/component_node.rb +1 -1
  26. data/lib/punchblock/component/input.rb +89 -268
  27. data/lib/punchblock/component/output.rb +106 -154
  28. data/lib/punchblock/component/prompt.rb +51 -0
  29. data/lib/punchblock/component/record.rb +41 -130
  30. data/lib/punchblock/component.rb +1 -0
  31. data/lib/punchblock/connection/asterisk.rb +31 -4
  32. data/lib/punchblock/connection/xmpp.rb +6 -14
  33. data/lib/punchblock/core_ext/blather/stanza.rb +1 -1
  34. data/lib/punchblock/event/active_speaker.rb +2 -10
  35. data/lib/punchblock/event/answered.rb +3 -3
  36. data/lib/punchblock/event/asterisk/ami/event.rb +15 -47
  37. data/lib/punchblock/event/complete.rb +26 -48
  38. data/lib/punchblock/event/dtmf.rb +3 -13
  39. data/lib/punchblock/event/end.rb +10 -11
  40. data/lib/punchblock/event/joined.rb +5 -25
  41. data/lib/punchblock/event/offer.rb +4 -25
  42. data/lib/punchblock/event/ringing.rb +3 -3
  43. data/lib/punchblock/event/unjoined.rb +5 -25
  44. data/lib/punchblock/event.rb +0 -10
  45. data/lib/punchblock/has_headers.rb +20 -26
  46. data/lib/punchblock/rayo_node.rb +46 -23
  47. data/lib/punchblock/ref.rb +39 -18
  48. data/lib/punchblock/translator/asterisk/agi_app.rb +15 -0
  49. data/lib/punchblock/translator/asterisk/agi_command.rb +3 -1
  50. data/lib/punchblock/translator/asterisk/ami_error_converter.rb +20 -0
  51. data/lib/punchblock/translator/asterisk/call.rb +60 -39
  52. data/lib/punchblock/translator/asterisk/channel.rb +41 -0
  53. data/lib/punchblock/translator/asterisk/component/asterisk/agi_command.rb +4 -1
  54. data/lib/punchblock/translator/asterisk/component/asterisk/ami_action.rb +4 -4
  55. data/lib/punchblock/translator/asterisk/component/composed_prompt.rb +62 -0
  56. data/lib/punchblock/translator/asterisk/component/input.rb +1 -0
  57. data/lib/punchblock/translator/asterisk/component/mrcp_native_prompt.rb +56 -0
  58. data/lib/punchblock/translator/asterisk/component/mrcp_prompt.rb +53 -0
  59. data/lib/punchblock/translator/asterisk/component/mrcp_recog_prompt.rb +99 -0
  60. data/lib/punchblock/translator/asterisk/component/output.rb +30 -22
  61. data/lib/punchblock/translator/asterisk/component/record.rb +8 -6
  62. data/lib/punchblock/translator/asterisk/component.rb +6 -5
  63. data/lib/punchblock/translator/asterisk/unimrcp_app.rb +26 -0
  64. data/lib/punchblock/translator/asterisk.rb +24 -28
  65. data/lib/punchblock/translator/dtmf_recognizer.rb +39 -20
  66. data/lib/punchblock/translator/freeswitch/call.rb +15 -14
  67. data/lib/punchblock/translator/freeswitch/component/abstract_output.rb +5 -4
  68. data/lib/punchblock/translator/freeswitch/component/flite_output.rb +1 -1
  69. data/lib/punchblock/translator/freeswitch/component/input.rb +5 -0
  70. data/lib/punchblock/translator/freeswitch/component/output.rb +2 -2
  71. data/lib/punchblock/translator/freeswitch/component/record.rb +19 -13
  72. data/lib/punchblock/translator/freeswitch/component/tts_output.rb +2 -2
  73. data/lib/punchblock/translator/freeswitch/component.rb +2 -5
  74. data/lib/punchblock/translator/freeswitch.rb +2 -2
  75. data/lib/punchblock/translator/input_component.rb +33 -13
  76. data/lib/punchblock/uri_list.rb +21 -0
  77. data/lib/punchblock/version.rb +1 -1
  78. data/lib/punchblock.rb +4 -3
  79. data/punchblock.gemspec +7 -3
  80. data/spec/punchblock/client/component_registry_spec.rb +1 -1
  81. data/spec/punchblock/client_spec.rb +10 -26
  82. data/spec/punchblock/command/accept_spec.rb +41 -7
  83. data/spec/punchblock/command/answer_spec.rb +51 -7
  84. data/spec/punchblock/command/dial_spec.rb +56 -14
  85. data/spec/punchblock/command/hangup_spec.rb +41 -7
  86. data/spec/punchblock/command/join_spec.rb +53 -11
  87. data/spec/punchblock/command/mute_spec.rb +19 -4
  88. data/spec/punchblock/command/redirect_spec.rb +40 -10
  89. data/spec/punchblock/command/reject_spec.rb +43 -11
  90. data/spec/punchblock/command/unjoin_spec.rb +40 -9
  91. data/spec/punchblock/command/unmute_spec.rb +19 -4
  92. data/spec/punchblock/command_node_spec.rb +0 -4
  93. data/spec/punchblock/component/asterisk/agi/command_spec.rb +16 -39
  94. data/spec/punchblock/component/asterisk/ami/action_spec.rb +50 -53
  95. data/spec/punchblock/component/component_node_spec.rb +3 -5
  96. data/spec/punchblock/component/input_spec.rb +194 -61
  97. data/spec/punchblock/component/output_spec.rb +194 -62
  98. data/spec/punchblock/component/prompt_spec.rb +132 -0
  99. data/spec/punchblock/component/record_spec.rb +70 -32
  100. data/spec/punchblock/connection/asterisk_spec.rb +17 -3
  101. data/spec/punchblock/connection/freeswitch_spec.rb +4 -4
  102. data/spec/punchblock/connection/xmpp_spec.rb +20 -38
  103. data/spec/punchblock/event/answered_spec.rb +12 -10
  104. data/spec/punchblock/event/asterisk/ami/event_spec.rb +27 -22
  105. data/spec/punchblock/event/complete_spec.rb +15 -19
  106. data/spec/punchblock/event/dtmf_spec.rb +5 -6
  107. data/spec/punchblock/event/end_spec.rb +20 -10
  108. data/spec/punchblock/event/joined_spec.rb +8 -7
  109. data/spec/punchblock/event/offer_spec.rb +41 -12
  110. data/spec/punchblock/event/ringing_spec.rb +12 -10
  111. data/spec/punchblock/event/started_speaking_spec.rb +5 -6
  112. data/spec/punchblock/event/stopped_speaking_spec.rb +5 -6
  113. data/spec/punchblock/event/unjoined_spec.rb +7 -7
  114. data/spec/punchblock/ref_spec.rb +86 -9
  115. data/spec/punchblock/translator/asterisk/call_spec.rb +317 -154
  116. data/spec/punchblock/translator/asterisk/component/asterisk/agi_command_spec.rb +28 -5
  117. data/spec/punchblock/translator/asterisk/component/asterisk/ami_action_spec.rb +15 -13
  118. data/spec/punchblock/translator/asterisk/component/composed_prompt_spec.rb +237 -0
  119. data/spec/punchblock/translator/asterisk/component/input_spec.rb +171 -14
  120. data/spec/punchblock/translator/asterisk/component/mrcp_native_prompt_spec.rb +652 -0
  121. data/spec/punchblock/translator/asterisk/component/mrcp_prompt_spec.rb +646 -0
  122. data/spec/punchblock/translator/asterisk/component/output_spec.rb +127 -77
  123. data/spec/punchblock/translator/asterisk/component/record_spec.rb +17 -8
  124. data/spec/punchblock/translator/asterisk/component/stop_by_redirect_spec.rb +2 -2
  125. data/spec/punchblock/translator/asterisk/component_spec.rb +3 -7
  126. data/spec/punchblock/translator/asterisk_spec.rb +20 -24
  127. data/spec/punchblock/translator/freeswitch/call_spec.rb +103 -99
  128. data/spec/punchblock/translator/freeswitch/component/flite_output_spec.rb +17 -8
  129. data/spec/punchblock/translator/freeswitch/component/input_spec.rb +26 -14
  130. data/spec/punchblock/translator/freeswitch/component/output_spec.rb +30 -52
  131. data/spec/punchblock/translator/freeswitch/component/record_spec.rb +23 -19
  132. data/spec/punchblock/translator/freeswitch/component/tts_output_spec.rb +18 -8
  133. data/spec/punchblock/translator/freeswitch/component_spec.rb +4 -8
  134. data/spec/punchblock/translator/freeswitch_spec.rb +11 -14
  135. data/spec/punchblock/uri_list_spec.rb +49 -0
  136. data/spec/punchblock_spec.rb +11 -1
  137. data/spec/spec_helper.rb +7 -11
  138. data/spec/support/mock_connection_with_event_handler.rb +1 -1
  139. metadata +104 -24
  140. data/lib/punchblock/header.rb +0 -9
  141. data/lib/punchblock/key_value_pair_node.rb +0 -51
  142. data/spec/punchblock/header_spec.rb +0 -11
@@ -6,18 +6,52 @@ module Punchblock
6
6
  module Command
7
7
  describe Hangup do
8
8
  it 'registers itself' do
9
- RayoNode.class_from_registration(:hangup, 'urn:xmpp:rayo:1').should be == Hangup
9
+ RayoNode.class_from_registration(:hangup, 'urn:xmpp:rayo:1').should be == described_class
10
10
  end
11
11
 
12
- it_should_behave_like 'command_headers'
13
-
14
12
  describe "from a stanza" do
15
- let(:stanza) { '<hangup xmlns="urn:xmpp:rayo:1"/>' }
13
+ let(:stanza) do
14
+ <<-STANZA
15
+ <hangup xmlns="urn:xmpp:rayo:1">
16
+ <header name="X-skill" value="agent" />
17
+ <header name="X-customer-id" value="8877" />
18
+ </hangup>
19
+ STANZA
20
+ end
21
+
22
+ subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
23
+
24
+ it { should be_instance_of described_class }
25
+ its(:headers) { should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
26
+
27
+ context "with no headers provided" do
28
+ let(:stanza) { '<hangup xmlns="urn:xmpp:rayo:1"/>' }
29
+
30
+ its(:headers) { should == {} }
31
+ end
32
+ end
33
+
34
+ describe "when setting options in initializer" do
35
+ subject { described_class.new headers: { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
36
+
37
+ its(:headers) { should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
16
38
 
17
- subject { RayoNode.import parse_stanza(stanza).root, '9f00061', '1' }
39
+ describe "exporting to Rayo" do
40
+ it "should export to XML that can be understood by its parser" do
41
+ new_instance = RayoNode.from_xml subject.to_rayo
42
+ new_instance.should be_instance_of described_class
43
+ new_instance.headers.should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' }
44
+ end
18
45
 
19
- it { should be_instance_of Hangup }
46
+ it "should render to a parent node if supplied" do
47
+ doc = Nokogiri::XML::Document.new
48
+ parent = Nokogiri::XML::Node.new 'foo', doc
49
+ doc.root = parent
50
+ rayo_doc = subject.to_rayo(parent)
51
+ rayo_doc.should == parent
52
+ end
53
+ end
20
54
  end
21
55
  end
22
56
  end
23
- end # Punchblock
57
+ end
@@ -5,59 +5,101 @@ require 'spec_helper'
5
5
  module Punchblock
6
6
  module Command
7
7
  describe Join do
8
-
9
8
  it 'registers itself' do
10
- RayoNode.class_from_registration(:join, 'urn:xmpp:rayo:1').should be == Join
9
+ RayoNode.class_from_registration(:join, 'urn:xmpp:rayo:1').should be == described_class
11
10
  end
12
11
 
13
12
  describe "when setting options in initializer" do
14
- subject { Join.new :call_id => 'abc123', :mixer_name => 'blah', :direction => :duplex, :media => :bridge }
13
+ subject { described_class.new :call_uri => 'abc123', :mixer_name => 'blah', :direction => :duplex, :media => :bridge }
15
14
 
16
- its(:call_id) { should be == 'abc123' }
15
+ its(:call_uri) { should be == 'abc123' }
17
16
  its(:mixer_name) { should be == 'blah' }
18
17
  its(:direction) { should be == :duplex }
19
18
  its(:media) { should be == :bridge }
19
+
20
+ context "with old call_id attribute" do
21
+ subject { described_class.new call_id: 'abc123' }
22
+
23
+ its(:call_uri) { should be == 'abc123' }
24
+ end
25
+
26
+ describe "exporting to Rayo" do
27
+ it "should export to XML that can be understood by its parser" do
28
+ new_instance = RayoNode.from_xml subject.to_rayo
29
+ new_instance.should be_instance_of described_class
30
+ new_instance.call_uri.should == 'abc123'
31
+ new_instance.mixer_name.should == 'blah'
32
+ new_instance.direction.should == :duplex
33
+ new_instance.media.should == :bridge
34
+ end
35
+
36
+ it "should render to a parent node if supplied" do
37
+ doc = Nokogiri::XML::Document.new
38
+ parent = Nokogiri::XML::Node.new 'foo', doc
39
+ doc.root = parent
40
+ rayo_doc = subject.to_rayo(parent)
41
+ rayo_doc.should == parent
42
+ end
43
+
44
+ context "when attributes are not set" do
45
+ subject { described_class.new call_uri: 'abc123' }
46
+
47
+ it "should not include them in the XML representation" do
48
+ subject.to_rayo['call-uri'].should == 'abc123'
49
+ subject.to_rayo['mixer-name'].should be_nil
50
+ end
51
+ end
52
+ end
20
53
  end
21
54
 
22
55
  describe "from a stanza" do
23
56
  let :stanza do
24
57
  <<-MESSAGE
25
58
  <join xmlns="urn:xmpp:rayo:1"
26
- call-id="abc123"
59
+ call-uri="abc123"
27
60
  mixer-name="blah"
28
61
  direction="duplex"
29
62
  media="bridge" />
30
63
  MESSAGE
31
64
  end
32
65
 
33
- subject { RayoNode.import parse_stanza(stanza).root, '9f00061', '1' }
66
+ subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
34
67
 
35
- it { should be_instance_of Join }
68
+ it { should be_instance_of described_class }
36
69
 
37
- its(:call_id) { should be == 'abc123' }
70
+ its(:call_uri) { should be == 'abc123' }
38
71
  its(:mixer_name) { should be == 'blah' }
39
72
  its(:direction) { should be == :duplex }
40
73
  its(:media) { should be == :bridge }
74
+
75
+ context "when no attributes are set" do
76
+ let(:stanza) { '<join xmlns="urn:xmpp:rayo:1" />' }
77
+
78
+ its(:call_uri) { should be_nil }
79
+ its(:mixer_name) { should be_nil }
80
+ its(:direction) { should be_nil }
81
+ its(:media) { should be_nil }
82
+ end
41
83
  end
42
84
 
43
85
  describe "with a direction" do
44
86
  [nil, :duplex, :send, :recv].each do |direction|
45
87
  describe direction do
46
- subject { Join.new :direction => direction }
88
+ subject { described_class.new :direction => direction }
47
89
 
48
90
  its(:direction) { should be == direction }
49
91
  end
50
92
  end
51
93
 
52
94
  describe "no direction" do
53
- subject { Join.new }
95
+ subject { described_class.new }
54
96
 
55
97
  its(:direction) { should be_nil }
56
98
  end
57
99
 
58
100
  describe "blahblahblah" do
59
101
  it "should raise an error" do
60
- expect { Join.new(:direction => :blahblahblah) }.to raise_error ArgumentError
102
+ expect { described_class.new(:direction => :blahblahblah) }.to raise_error ArgumentError
61
103
  end
62
104
  end
63
105
  end
@@ -6,16 +6,31 @@ module Punchblock
6
6
  module Command
7
7
  describe Mute do
8
8
  it 'registers itself' do
9
- RayoNode.class_from_registration(:mute, 'urn:xmpp:rayo:1').should be == Mute
9
+ RayoNode.class_from_registration(:mute, 'urn:xmpp:rayo:1').should be == described_class
10
10
  end
11
11
 
12
12
  describe "from a stanza" do
13
13
  let(:stanza) { '<mute xmlns="urn:xmpp:rayo:1"/>' }
14
14
 
15
- subject { RayoNode.import parse_stanza(stanza).root, '9f00061', '1' }
15
+ subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
16
16
 
17
- it { should be_instance_of Mute }
17
+ it { should be_instance_of described_class }
18
+ end
19
+
20
+ describe "exporting to Rayo" do
21
+ it "should export to XML that can be understood by its parser" do
22
+ new_instance = RayoNode.from_xml subject.to_rayo
23
+ new_instance.should be_instance_of described_class
24
+ end
25
+
26
+ it "should render to a parent node if supplied" do
27
+ doc = Nokogiri::XML::Document.new
28
+ parent = Nokogiri::XML::Node.new 'foo', doc
29
+ doc.root = parent
30
+ rayo_doc = subject.to_rayo(parent)
31
+ rayo_doc.should == parent
32
+ end
18
33
  end
19
34
  end
20
35
  end
21
- end # Punchblock
36
+ end
@@ -6,15 +6,39 @@ module Punchblock
6
6
  module Command
7
7
  describe Redirect do
8
8
  it 'registers itself' do
9
- RayoNode.class_from_registration(:redirect, 'urn:xmpp:rayo:1').should be == Redirect
9
+ RayoNode.class_from_registration(:redirect, 'urn:xmpp:rayo:1').should be == described_class
10
10
  end
11
11
 
12
12
  describe "when setting options in initializer" do
13
- subject { Redirect.new :to => 'tel:+14045551234', :headers => { :x_skill => 'agent', :x_customer_id => 8877 } }
14
-
15
- it_should_behave_like 'command_headers'
13
+ subject { described_class.new to: 'tel:+14045551234', headers: { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
16
14
 
17
15
  its(:to) { should be == 'tel:+14045551234' }
16
+ its(:headers) { should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
17
+
18
+ describe "exporting to Rayo" do
19
+ it "should export to XML that can be understood by its parser" do
20
+ new_instance = RayoNode.from_xml subject.to_rayo
21
+ new_instance.should be_instance_of described_class
22
+ new_instance.to.should == 'tel:+14045551234'
23
+ new_instance.headers.should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' }
24
+ end
25
+
26
+ it "should render to a parent node if supplied" do
27
+ doc = Nokogiri::XML::Document.new
28
+ parent = Nokogiri::XML::Node.new 'foo', doc
29
+ doc.root = parent
30
+ rayo_doc = subject.to_rayo(parent)
31
+ rayo_doc.should == parent
32
+ end
33
+
34
+ context "when attributes are not set" do
35
+ subject { described_class.new }
36
+
37
+ it "should not include them in the XML representation" do
38
+ subject.to_rayo['to'].should be_nil
39
+ end
40
+ end
41
+ end
18
42
  end
19
43
 
20
44
  describe "from a stanza" do
@@ -23,19 +47,25 @@ module Punchblock
23
47
  <redirect xmlns='urn:xmpp:rayo:1'
24
48
  to='tel:+14045551234'>
25
49
  <!-- Signaling (e.g. SIP) Headers -->
26
- <header name="x-skill" value="agent" />
27
- <header name="x-customer-id" value="8877" />
50
+ <header name="X-skill" value="agent" />
51
+ <header name="X-customer-id" value="8877" />
28
52
  </redirect>
29
53
  MESSAGE
30
54
  end
31
55
 
32
- subject { RayoNode.import parse_stanza(stanza).root, '9f00061', '1' }
33
-
34
- it { should be_instance_of Redirect }
56
+ subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
35
57
 
36
- it_should_behave_like 'command_headers'
58
+ it { should be_instance_of described_class }
37
59
 
38
60
  its(:to) { should be == 'tel:+14045551234' }
61
+ its(:headers) { should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
62
+
63
+ context "with no headers or to provided" do
64
+ let(:stanza) { '<redirect xmlns="urn:xmpp:rayo:1"/>' }
65
+
66
+ its(:to) { should be_nil }
67
+ its(:headers) { should == {} }
68
+ end
39
69
  end
40
70
  end # Redirect
41
71
  end # Command
@@ -6,15 +6,39 @@ module Punchblock
6
6
  module Command
7
7
  describe Reject do
8
8
  it 'registers itself' do
9
- RayoNode.class_from_registration(:reject, 'urn:xmpp:rayo:1').should be == Reject
9
+ RayoNode.class_from_registration(:reject, 'urn:xmpp:rayo:1').should be == described_class
10
10
  end
11
11
 
12
12
  describe "when setting options in initializer" do
13
- subject { Reject.new :reason => :busy, :headers => { :x_skill => 'agent', :x_customer_id => 8877 } }
14
-
15
- it_should_behave_like 'command_headers'
13
+ subject { described_class.new reason: :busy, headers: { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
16
14
 
17
15
  its(:reason) { should be == :busy }
16
+ its(:headers) { should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
17
+
18
+ describe "exporting to Rayo" do
19
+ it "should export to XML that can be understood by its parser" do
20
+ new_instance = RayoNode.from_xml subject.to_rayo
21
+ new_instance.should be_instance_of described_class
22
+ new_instance.reason.should == :busy
23
+ new_instance.headers.should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' }
24
+ end
25
+
26
+ it "should render to a parent node if supplied" do
27
+ doc = Nokogiri::XML::Document.new
28
+ parent = Nokogiri::XML::Node.new 'foo', doc
29
+ doc.root = parent
30
+ rayo_doc = subject.to_rayo(parent)
31
+ rayo_doc.should == parent
32
+ end
33
+
34
+ context "when attributes are not set" do
35
+ subject { described_class.new }
36
+
37
+ it "should not include them in the XML representation" do
38
+ subject.to_rayo.children.count.should == 0
39
+ end
40
+ end
41
+ end
18
42
  end
19
43
 
20
44
  describe "from a stanza" do
@@ -23,37 +47,45 @@ module Punchblock
23
47
  <reject xmlns='urn:xmpp:rayo:1'>
24
48
  <busy />
25
49
  <!-- Sample Headers (optional) -->
26
- <header name="x-reason-internal" value="bad-skill" />
50
+ <header name="X-skill" value="agent" />
51
+ <header name="X-customer-id" value="8877" />
27
52
  </reject>
28
53
  MESSAGE
29
54
  end
30
55
 
31
- subject { RayoNode.import parse_stanza(stanza).root, '9f00061', '1' }
56
+ subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
32
57
 
33
- it { should be_instance_of Reject }
58
+ it { should be_instance_of described_class }
34
59
 
35
60
  its(:reason) { should be == :busy }
36
- its(:headers_hash) { should be == { :x_reason_internal => 'bad-skill' } }
61
+ its(:headers) { should == { 'X-skill' => 'agent', 'X-customer-id' => '8877' } }
62
+
63
+ context "with no headers or reason provided" do
64
+ let(:stanza) { '<reject xmlns="urn:xmpp:rayo:1"/>' }
65
+
66
+ its(:reason) { should be_nil }
67
+ its(:headers) { should == {} }
68
+ end
37
69
  end
38
70
 
39
71
  describe "with the reason" do
40
72
  [nil, :decline, :busy, :error].each do |reason|
41
73
  describe reason do
42
- subject { Reject.new :reason => reason }
74
+ subject { described_class.new :reason => reason }
43
75
 
44
76
  its(:reason) { should be == reason }
45
77
  end
46
78
  end
47
79
 
48
80
  describe "no reason" do
49
- subject { Reject.new }
81
+ subject { described_class.new }
50
82
 
51
83
  its(:reason) { should be_nil }
52
84
  end
53
85
 
54
86
  describe "blahblahblah" do
55
87
  it "should raise an error" do
56
- expect { Reject.new(:reason => :blahblahblah) }.to raise_error ArgumentError
88
+ expect { described_class.new(:reason => :blahblahblah) }.to raise_error ArgumentError
57
89
  end
58
90
  end
59
91
  end
@@ -5,34 +5,65 @@ require 'spec_helper'
5
5
  module Punchblock
6
6
  module Command
7
7
  describe Unjoin do
8
-
9
8
  it 'registers itself' do
10
- RayoNode.class_from_registration(:unjoin, 'urn:xmpp:rayo:1').should be == Unjoin
9
+ RayoNode.class_from_registration(:unjoin, 'urn:xmpp:rayo:1').should be == described_class
11
10
  end
12
11
 
13
12
  describe "when setting options in initializer" do
14
- subject { Unjoin.new :call_id => 'abc123', :mixer_name => 'blah' }
13
+ subject { Unjoin.new :call_uri => 'abc123', :mixer_name => 'blah' }
15
14
 
16
- its(:call_id) { should be == 'abc123' }
15
+ its(:call_uri) { should be == 'abc123' }
17
16
  its(:mixer_name) { should be == 'blah' }
17
+
18
+ context "with old call_id attribute" do
19
+ subject { described_class.new call_id: 'abc123' }
20
+
21
+ its(:call_uri) { should be == 'abc123' }
22
+ end
23
+
24
+ describe "exporting to Rayo" do
25
+ it "should export to XML that can be understood by its parser" do
26
+ new_instance = RayoNode.from_xml subject.to_rayo
27
+ new_instance.should be_instance_of described_class
28
+ new_instance.call_uri.should == 'abc123'
29
+ new_instance.mixer_name.should == 'blah'
30
+ end
31
+
32
+ it "should render to a parent node if supplied" do
33
+ doc = Nokogiri::XML::Document.new
34
+ parent = Nokogiri::XML::Node.new 'foo', doc
35
+ doc.root = parent
36
+ rayo_doc = subject.to_rayo(parent)
37
+ rayo_doc.should == parent
38
+ end
39
+
40
+ context "when attributes are not set" do
41
+ subject { described_class.new call_uri: 'abc123' }
42
+
43
+ it "should not include them in the XML representation" do
44
+ subject.to_rayo['call-uri'].should == 'abc123'
45
+ subject.to_rayo['mixer-name'].should be_nil
46
+ end
47
+ end
48
+ end
18
49
  end
19
50
 
20
51
  describe "from a stanza" do
21
52
  let :stanza do
22
53
  <<-MESSAGE
23
54
  <unjoin xmlns="urn:xmpp:rayo:1"
24
- call-id="abc123"
55
+ call-uri="abc123"
25
56
  mixer-name="blah" />
26
57
  MESSAGE
27
58
  end
28
59
 
29
- subject { RayoNode.import parse_stanza(stanza).root, '9f00061', '1' }
60
+ subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
30
61
 
31
- it { should be_instance_of Unjoin }
62
+ it { should be_instance_of described_class }
32
63
 
33
- its(:call_id) { should be == 'abc123' }
64
+ its(:call_uri) { should be == 'abc123' }
34
65
  its(:mixer_name) { should be == 'blah' }
35
66
  end
36
67
  end
37
68
  end
38
- end # Punchblock
69
+ end
@@ -6,16 +6,31 @@ module Punchblock
6
6
  module Command
7
7
  describe Unmute do
8
8
  it 'registers itself' do
9
- RayoNode.class_from_registration(:unmute, 'urn:xmpp:rayo:1').should be == Unmute
9
+ RayoNode.class_from_registration(:unmute, 'urn:xmpp:rayo:1').should be == described_class
10
10
  end
11
11
 
12
12
  describe "from a stanza" do
13
13
  let(:stanza) { '<unmute xmlns="urn:xmpp:rayo:1"/>' }
14
14
 
15
- subject { RayoNode.import parse_stanza(stanza).root, '9f00061', '1' }
15
+ subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
16
16
 
17
- it { should be_instance_of Unmute }
17
+ it { should be_instance_of described_class }
18
+ end
19
+
20
+ describe "exporting to Rayo" do
21
+ it "should export to XML that can be understood by its parser" do
22
+ new_instance = RayoNode.from_xml subject.to_rayo
23
+ new_instance.should be_instance_of described_class
24
+ end
25
+
26
+ it "should render to a parent node if supplied" do
27
+ doc = Nokogiri::XML::Document.new
28
+ parent = Nokogiri::XML::Node.new 'foo', doc
29
+ doc.root = parent
30
+ rayo_doc = subject.to_rayo(parent)
31
+ rayo_doc.should == parent
32
+ end
18
33
  end
19
34
  end
20
35
  end
21
- end # Punchblock
36
+ end
@@ -31,10 +31,6 @@ module Punchblock
31
31
  it "should raise a StateMachine::InvalidTransition when received a second time" do
32
32
  lambda { subject.request! }.should raise_error(StateMachine::InvalidTransition)
33
33
  end
34
-
35
- it "should prevent altering attributes" do
36
- lambda { subject.write_attr :foo, 'bar' }.should raise_error(StandardError, "Cannot alter attributes of a requested command")
37
- end
38
34
  end
39
35
 
40
36
  describe "#execute!" do
@@ -8,7 +8,7 @@ module Punchblock
8
8
  module AGI
9
9
  describe Command do
10
10
  it 'registers itself' do
11
- RayoNode.class_from_registration(:command, 'urn:xmpp:rayo:asterisk:agi:1').should be == Command
11
+ RayoNode.class_from_registration(:command, 'urn:xmpp:rayo:asterisk:agi:1').should be == described_class
12
12
  end
13
13
 
14
14
  describe "from a stanza" do
@@ -20,50 +20,27 @@ module Punchblock
20
20
  MESSAGE
21
21
  end
22
22
 
23
- subject { RayoNode.import parse_stanza(stanza).root, '9f00061', '1' }
23
+ subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
24
24
 
25
25
  it { should be_instance_of Command }
26
26
 
27
27
  it_should_behave_like 'event'
28
28
 
29
- its(:name) { should be == 'GET VARIABLE' }
30
- its(:params) { should be == [Command::Param.new('UNIQUEID')] }
31
- its(:params_array) { should be == ['UNIQUEID'] }
29
+ its(:name) { should be == 'GET VARIABLE' }
30
+ its(:params) { should be == ['UNIQUEID'] }
32
31
  end
33
32
 
34
33
  describe "when setting options in initializer" do
35
34
  subject do
36
- Command.new :name => 'GET VARIABLE',
37
- :params => ['UNIQUEID']
35
+ described_class.new name: 'GET VARIABLE',
36
+ params: ['UNIQUEID']
38
37
  end
39
38
 
40
- its(:name) { should be == 'GET VARIABLE' }
41
- its(:params) { should be == [Command::Param.new('UNIQUEID')] }
42
- its(:params_array) { should be == ['UNIQUEID'] }
39
+ its(:name) { should be == 'GET VARIABLE' }
40
+ its(:params) { should be == ['UNIQUEID'] }
43
41
  end
44
42
 
45
43
  class Command
46
- describe Param do
47
- it 'will auto-inherit nodes' do
48
- n = parse_stanza "<param value='bah' />"
49
- h = Param.new n.root
50
- h.value.should be == 'bah'
51
- end
52
-
53
- it 'has a value attribute' do
54
- n = Param.new 'en'
55
- n.value.should be == 'en'
56
- n.value = 'de'
57
- n.value.should be == 'de'
58
- end
59
-
60
- it 'can determine equality' do
61
- a = Param.new 'bah'
62
- a.should be == Param.new('bah')
63
- a.should_not be == Param.new('boo')
64
- end
65
- end
66
-
67
44
  describe Complete::Success do
68
45
  let :stanza do
69
46
  <<-MESSAGE
@@ -77,9 +54,9 @@ module Punchblock
77
54
  MESSAGE
78
55
  end
79
56
 
80
- subject { RayoNode.import(parse_stanza(stanza).root).reason }
57
+ subject { RayoNode.from_xml(parse_stanza(stanza).root).reason }
81
58
 
82
- it { should be_instance_of Complete::Success }
59
+ it { should be_instance_of described_class }
83
60
 
84
61
  its(:name) { should be == :success }
85
62
  its(:code) { should be == 200 }
@@ -88,7 +65,7 @@ module Punchblock
88
65
 
89
66
  describe "when setting options in initializer" do
90
67
  subject do
91
- Complete::Success.new :code => 200, :result => 0, :data => '1187188485.0'
68
+ Complete::Success.new code: 200, result: 0, data: '1187188485.0'
92
69
  end
93
70
 
94
71
  its(:code) { should be == 200 }
@@ -97,8 +74,8 @@ module Punchblock
97
74
  end
98
75
  end
99
76
  end
100
- end # Command
101
- end # AGI
102
- end # Asterisk
103
- end # Component
104
- end # Punchblock
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end