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.
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
@@ -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) { mock('RubyFS::Stream') }
14
+ let(:mock_stream) { double('RubyFS::Stream') }
15
15
  let(:mock_call) { Punchblock::Translator::Freeswitch::Call.new id, translator, nil, mock_stream }
16
16
 
17
17
  let :original_command do
@@ -48,7 +48,7 @@ module Punchblock
48
48
  subject.execute
49
49
  end
50
50
 
51
- it "sends a success complete event when the recording ends" do
51
+ it "sends a maxduration complete event when the recording ends" do
52
52
  full_filename = "file://#{filename}"
53
53
  subject.execute
54
54
  record_stop_event = RubyFS::Event.new nil, {
@@ -56,7 +56,7 @@ module Punchblock
56
56
  :record_file_path => filename
57
57
  }
58
58
  mock_call.handle_es_event record_stop_event
59
- reason.should be_a Punchblock::Component::Record::Complete::Success
59
+ reason.should be_a Punchblock::Component::Record::Complete::MaxDuration
60
60
  recording.uri.should be == full_filename
61
61
  original_command.should be_complete
62
62
  end
@@ -94,8 +94,9 @@ module Punchblock
94
94
  describe 'initial_timeout' do
95
95
  context "set to nil" do
96
96
  let(:command_options) { { :initial_timeout => nil } }
97
- it "should execute normally" do
98
- mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/)
97
+ it "should setvar RECORD_INITIAL_TIMEOUT_MS with a 0 value" do
98
+ mock_call.should_receive(:uuid_foo).once.with(:setvar, "RECORD_INITIAL_TIMEOUT_MS 0").ordered
99
+ mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/).ordered
99
100
  subject.execute
100
101
  original_command.response(0.1).should be_a Ref
101
102
  end
@@ -103,8 +104,9 @@ module Punchblock
103
104
 
104
105
  context "set to -1" do
105
106
  let(:command_options) { { :initial_timeout => -1 } }
106
- it "should execute normally" do
107
- mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/)
107
+ it "should setvar RECORD_INITIAL_TIMEOUT_MS with a 0 value" do
108
+ mock_call.should_receive(:uuid_foo).once.with(:setvar, "RECORD_INITIAL_TIMEOUT_MS 0").ordered
109
+ mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/).ordered
108
110
  subject.execute
109
111
  original_command.response(0.1).should be_a Ref
110
112
  end
@@ -112,11 +114,11 @@ module Punchblock
112
114
 
113
115
  context "set to a positive number" do
114
116
  let(:command_options) { { :initial_timeout => 10 } }
115
- it "should return an error and not execute any actions" do
116
- mock_call.should_receive(:uuid_foo).never
117
+ it "should setvar RECORD_INITIAL_TIMEOUT_MS with a value in ms" do
118
+ mock_call.should_receive(:uuid_foo).once.with(:setvar, "RECORD_INITIAL_TIMEOUT_MS 10").ordered
119
+ mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/).ordered
117
120
  subject.execute
118
- error = ProtocolError.new.setup 'option error', 'An initial-timeout value is unsupported.'
119
- original_command.response(0.1).should be == error
121
+ original_command.response(0.1).should be_a Ref
120
122
  end
121
123
  end
122
124
  end
@@ -124,8 +126,9 @@ module Punchblock
124
126
  describe 'final_timeout' do
125
127
  context "set to nil" do
126
128
  let(:command_options) { { :final_timeout => nil } }
127
- it "should execute normally" do
128
- mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/)
129
+ it "should setvar RECORD_FINAL_TIMEOUT_MS with a 0 value" do
130
+ mock_call.should_receive(:uuid_foo).once.with(:setvar, "RECORD_FINAL_TIMEOUT_MS 0").ordered
131
+ mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/).ordered
129
132
  subject.execute
130
133
  original_command.response(0.1).should be_a Ref
131
134
  end
@@ -133,8 +136,9 @@ module Punchblock
133
136
 
134
137
  context "set to -1" do
135
138
  let(:command_options) { { :final_timeout => -1 } }
136
- it "should execute normally" do
137
- mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/)
139
+ it "should setvar RECORD_FINAL_TIMEOUT_MS with a 0 value" do
140
+ mock_call.should_receive(:uuid_foo).once.with(:setvar, "RECORD_FINAL_TIMEOUT_MS 0").ordered
141
+ mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/).ordered
138
142
  subject.execute
139
143
  original_command.response(0.1).should be_a Ref
140
144
  end
@@ -142,11 +146,11 @@ module Punchblock
142
146
 
143
147
  context "set to a positive number" do
144
148
  let(:command_options) { { :final_timeout => 10 } }
145
- it "should return an error and not execute any actions" do
146
- mock_call.should_receive(:uuid_foo).never
149
+ it "should setvar RECORD_FINAL_TIMEOUT_MS with a value in ms" do
150
+ mock_call.should_receive(:uuid_foo).once.with(:setvar, "RECORD_FINAL_TIMEOUT_MS 10").ordered
151
+ mock_call.should_receive(:uuid_foo).once.with(:record, /.wav$/).ordered
147
152
  subject.execute
148
- error = ProtocolError.new.setup 'option error', 'A final-timeout value is unsupported.'
149
- original_command.response(0.1).should be == error
153
+ original_command.response(0.1).should be_a Ref
150
154
  end
151
155
  end
152
156
  end
@@ -25,7 +25,7 @@ module Punchblock
25
25
  end
26
26
 
27
27
  let :command_options do
28
- { :ssml => ssml_doc }
28
+ { :render_document => {:value => ssml_doc} }
29
29
  end
30
30
 
31
31
  def execute
@@ -49,16 +49,17 @@ module Punchblock
49
49
  let(:command_opts) { {} }
50
50
 
51
51
  let :command_options do
52
- { :ssml => ssml_doc }.merge(command_opts)
52
+ { :render_document => {:value => ssml_doc} }.merge(command_opts)
53
53
  end
54
54
 
55
55
  let :original_command do
56
56
  Punchblock::Component::Output.new command_options
57
57
  end
58
58
 
59
- describe 'ssml' do
59
+ describe 'document' do
60
60
  context 'unset' do
61
- let(:command_opts) { { :ssml => nil } }
61
+ let(:ssml_doc) { nil }
62
+
62
63
  it "should return an error and not execute any actions" do
63
64
  execute
64
65
  error = ProtocolError.new.setup 'option error', 'An SSML document is required.'
@@ -76,7 +77,16 @@ module Punchblock
76
77
  expect_playback
77
78
  execute
78
79
  subject.handle_es_event RubyFS::Event.new(nil, :event_name => "CHANNEL_EXECUTE_COMPLETE")
79
- original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success
80
+ original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Finish
81
+ end
82
+ end
83
+
84
+ context 'with multiple documents' do
85
+ let(:command_opts) { { :render_documents => [{:value => ssml_doc}, {:value => ssml_doc}] } }
86
+ it "should return an error and not execute any actions" do
87
+ subject.execute
88
+ error = ProtocolError.new.setup 'option error', 'Only a single document is supported.'
89
+ original_command.response(0.1).should be == error
80
90
  end
81
91
  end
82
92
  end
@@ -221,11 +231,11 @@ module Punchblock
221
231
  end
222
232
  end
223
233
 
224
- context "set to :speech" do
225
- let(:command_opts) { { :interrupt_on => :speech } }
234
+ context "set to :voice" do
235
+ let(:command_opts) { { :interrupt_on => :voice } }
226
236
  it "should return an error and not execute any actions" do
227
237
  execute
228
- error = ProtocolError.new.setup 'option error', 'An interrupt-on value of speech is unsupported.'
238
+ error = ProtocolError.new.setup 'option error', 'An interrupt-on value of voice is unsupported.'
229
239
  original_command.response(0.1).should be == error
230
240
  end
231
241
  end
@@ -26,7 +26,7 @@ module Punchblock
26
26
  RubyFS::Event.new nil, :event_name => 'CHANNEL_EXECUTE'
27
27
  end
28
28
 
29
- let(:response) { mock 'Response' }
29
+ let(:response) { double 'Response' }
30
30
 
31
31
  it 'should execute the handler' do
32
32
  response.should_receive(:call).once.with es_event
@@ -46,10 +46,8 @@ module Punchblock
46
46
  end
47
47
 
48
48
  let :expected_event do
49
- Punchblock::Event::Complete.new.tap do |e|
50
- e.target_call_id = call.id
51
- e.component_id = subject.id
52
- end
49
+ Punchblock::Event::Complete.new target_call_id: call.id,
50
+ component_id: subject.id
53
51
  end
54
52
 
55
53
  it "should send the event to the connection" do
@@ -63,9 +61,7 @@ module Punchblock
63
61
 
64
62
  let(:reason) { Punchblock::Event::Complete::Stop.new }
65
63
  let :expected_event do
66
- Punchblock::Event::Complete.new.tap do |c|
67
- c.reason = Punchblock::Event::Complete::Stop.new
68
- end
64
+ Punchblock::Event::Complete.new reason: reason
69
65
  end
70
66
 
71
67
  it "should send a complete event with the specified reason" do
@@ -5,12 +5,12 @@ require 'spec_helper'
5
5
  module Punchblock
6
6
  module Translator
7
7
  describe Freeswitch do
8
- let(:connection) { mock 'Connection::Freeswitch' }
8
+ let(:connection) { double 'Connection::Freeswitch' }
9
9
  let(:media_engine) { :flite }
10
10
  let(:default_voice) { :hal }
11
11
 
12
12
  let(:translator) { described_class.new connection, media_engine, default_voice }
13
- let(:stream) { mock 'RubyFS::Stream' }
13
+ let(:stream) { double 'RubyFS::Stream' }
14
14
 
15
15
  before { connection.should_receive(:stream).at_most(:once).and_return stream }
16
16
 
@@ -88,14 +88,14 @@ module Punchblock
88
88
 
89
89
  it 'should make the call inaccessible by ID' do
90
90
  subject.call_with_id(call_id).should be call
91
- subject.deregister_call call
91
+ subject.deregister_call call_id
92
92
  subject.call_with_id(call_id).should be_nil
93
93
  end
94
94
  end
95
95
 
96
96
  describe '#register_component' do
97
97
  let(:component_id) { 'abc123' }
98
- let(:component) { mock 'Foo', :id => component_id }
98
+ let(:component) { double 'Foo', :id => component_id }
99
99
 
100
100
  it 'should make the component accessible by ID' do
101
101
  subject.register_component component
@@ -105,7 +105,7 @@ module Punchblock
105
105
 
106
106
  describe '#execute_call_command' do
107
107
  let(:call_id) { 'abc123' }
108
- let(:command) { Command::Answer.new.tap { |c| c.target_call_id = call_id } }
108
+ let(:command) { Command::Answer.new target_call_id: call_id }
109
109
 
110
110
  context "with a known call ID" do
111
111
  let(:call) { described_class::Call.new 'SIP/foo', subject }
@@ -123,16 +123,13 @@ module Punchblock
123
123
  end
124
124
 
125
125
  let :end_error_event do
126
- Punchblock::Event::End.new.tap do |e|
127
- e.target_call_id = call_id
128
- e.reason = :error
129
- end
126
+ Punchblock::Event::End.new reason: :error, target_call_id: call_id
130
127
  end
131
128
 
132
129
  context "for an outgoing call which began executing but crashed" do
133
130
  let(:dial_command) { Command::Dial.new :to => 'SIP/1234', :from => 'abc123' }
134
131
 
135
- let(:call_id) { dial_command.response.id }
132
+ let(:call_id) { dial_command.response.call_id }
136
133
 
137
134
  before do
138
135
  stream.as_null_object
@@ -205,7 +202,7 @@ module Punchblock
205
202
  let(:component_node) { Component::Output.new }
206
203
  let(:component) { Translator::Freeswitch::Component::Output.new(component_node, call) }
207
204
 
208
- let(:command) { Component::Stop.new.tap { |c| c.component_id = component.id } }
205
+ let(:command) { Component::Stop.new component_id: component.id }
209
206
 
210
207
  before do
211
208
  command.request!
@@ -256,7 +253,7 @@ module Punchblock
256
253
  end
257
254
 
258
255
  it 'should instruct the call to send a dial' do
259
- mock_call = stub('Freeswitch::Call').as_null_object
256
+ mock_call = double('Freeswitch::Call').as_null_object
260
257
  Freeswitch::Call.should_receive(:new_link).once.and_return mock_call
261
258
  mock_call.async.should_receive(:dial).once.with command
262
259
  subject.execute_global_command command
@@ -277,7 +274,7 @@ module Punchblock
277
274
 
278
275
  describe '#handle_pb_event' do
279
276
  it 'should forward the event to the connection' do
280
- event = mock 'Punchblock::Event'
277
+ event = double 'Punchblock::Event'
281
278
  subject.connection.should_receive(:handle_event).once.with event
282
279
  subject.handle_pb_event event
283
280
  end
@@ -530,7 +527,7 @@ module Punchblock
530
527
 
531
528
  describe 'with a CHANNEL_PARK event' do
532
529
  it 'should instruct the call to send an offer' do
533
- mock_call = stub('Freeswitch::Call').as_null_object
530
+ mock_call = double('Freeswitch::Call').as_null_object
534
531
  Freeswitch::Call.should_receive(:new).once.and_return mock_call
535
532
  subject.wrapped_object.should_receive(:link)
536
533
  mock_call.async.should_receive(:send_offer).once
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Punchblock::URIList do
6
+ its(:size) { should == 0 }
7
+
8
+ context "created with a set of entries" do
9
+ subject { described_class.new 'http://example.com/hello.mp3', 'http://example.com/goodbye.mp3' }
10
+
11
+ its(:size) { should == 2 }
12
+ its(:to_ary) { should == ['http://example.com/hello.mp3', 'http://example.com/goodbye.mp3'] }
13
+
14
+ its(:to_s) { should == "http://example.com/hello.mp3\nhttp://example.com/goodbye.mp3" }
15
+ end
16
+
17
+ context "created with an array of entries" do
18
+ subject { described_class.new ['http://example.com/hello.mp3', 'http://example.com/goodbye.mp3'] }
19
+
20
+ its(:size) { should == 2 }
21
+ its(:to_ary) { should == ['http://example.com/hello.mp3', 'http://example.com/goodbye.mp3'] }
22
+ its(:to_s) { should == "http://example.com/hello.mp3\nhttp://example.com/goodbye.mp3" }
23
+ end
24
+
25
+ context "imported from a string" do
26
+ let(:string) do
27
+ <<-STRING
28
+ http://example.com/hello.mp3
29
+ http://example.com/goodbye.mp3
30
+ STRING
31
+ end
32
+
33
+ subject { described_class.import string }
34
+
35
+ its(:size) { should == 2 }
36
+ its(:to_ary) { should == ['http://example.com/hello.mp3', 'http://example.com/goodbye.mp3'] }
37
+ its(:to_s) { should == "http://example.com/hello.mp3\nhttp://example.com/goodbye.mp3" }
38
+ end
39
+
40
+ describe "comparisons" do
41
+ context "when the elements are the same" do
42
+ described_class.new('foo', 'bar').should == described_class.new('foo', 'bar')
43
+ end
44
+
45
+ context "when the elements are different" do
46
+ described_class.new('foo', 'baz').should_not == described_class.new('bar', 'baz')
47
+ end
48
+ end
49
+ end
@@ -2,7 +2,17 @@ require 'spec_helper'
2
2
 
3
3
  describe Punchblock do
4
4
  describe '#client_with_connection' do
5
- let(:mock_connection) { stub('Connection').as_null_object }
5
+ let(:mock_connection) { double('Connection').as_null_object }
6
+
7
+ context 'with :xmpp' do
8
+ it 'sets up an XMPP connection, passing options, and a client with the connection attached' do
9
+ options = {:username => 'foo', :password => 'bar'}
10
+ Punchblock::Connection::XMPP.should_receive(:new).once.with(options).and_return mock_connection
11
+ client = Punchblock.client_with_connection :xmpp, options
12
+ client.should be_a Punchblock::Client
13
+ client.connection.should be mock_connection
14
+ end
15
+ end
6
16
 
7
17
  context 'with :XMPP' do
8
18
  it 'sets up an XMPP connection, passing options, and a client with the connection attached' do
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,9 @@
3
3
  require 'punchblock'
4
4
  require 'countdownlatch'
5
5
  require 'logger'
6
+ require 'celluloid'
7
+ require 'coveralls'
8
+ Coveralls.wear!
6
9
 
7
10
  Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
8
11
 
@@ -12,6 +15,10 @@ RSpec.configure do |config|
12
15
  config.filter_run :focus => true
13
16
  config.run_all_when_everything_filtered = true
14
17
 
18
+ config.mock_with :rspec do |mocks|
19
+ mocks.add_stub_and_should_receive_to Celluloid::AbstractProxy
20
+ end
21
+
15
22
  config.before :suite do |variable|
16
23
  Punchblock.logger = Logger.new(STDOUT)
17
24
  Punchblock.logger.define_singleton_method :trace, Punchblock.logger.method(:debug)
@@ -42,20 +49,9 @@ shared_examples_for 'event' do
42
49
  end
43
50
 
44
51
  shared_examples_for 'command_headers' do
45
- it 'takes a hash of keys and values for headers' do
46
- headers = { :x_skill => 'agent', :x_customer_id => '8877' }
47
-
48
- control = [ Punchblock::Header.new(:x_skill, 'agent'), Punchblock::Header.new(:x_customer_id, '8877')]
49
-
50
- di = subject.class.new :headers => headers
51
- di.headers.should have(2).items
52
- di.headers.each { |i| control.include?(i).should be_true }
53
- end
54
52
  end
55
53
 
56
54
  shared_examples_for 'event_headers' do
57
- its(:headers) { should be == [Punchblock::Header.new('X-skill', 'agent'), Punchblock::Header.new('X-customer-id', '8877')]}
58
- its(:headers_hash) { should be == {:x_skill => 'agent', :x_customer_id => '8877'} }
59
55
  end
60
56
 
61
57
  shared_examples_for 'key_value_pairs' do
@@ -3,7 +3,7 @@
3
3
  module HasMockCallbackConnection
4
4
  def self.included(test_case)
5
5
  test_case.let(:connection) do
6
- mock('Connection').tap do |mc|
6
+ double('Connection').tap do |mc|
7
7
  mc.stub :handle_event do |event|
8
8
  original_command.add_event event
9
9
  end