punchblock 1.8.2 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +8 -0
- data/lib/punchblock/component/asterisk/agi/command.rb +0 -11
- data/lib/punchblock/connection/asterisk.rb +3 -3
- data/lib/punchblock/translator/asterisk/agi_command.rb +40 -0
- data/lib/punchblock/translator/asterisk/call.rb +56 -47
- data/lib/punchblock/translator/asterisk/component/asterisk/agi_command.rb +13 -37
- data/lib/punchblock/translator/asterisk/component/asterisk/ami_action.rb +24 -41
- data/lib/punchblock/translator/asterisk/component/input.rb +2 -1
- data/lib/punchblock/translator/asterisk/component/output.rb +16 -21
- data/lib/punchblock/translator/asterisk/component/record.rb +11 -19
- data/lib/punchblock/translator/asterisk/component.rb +12 -9
- data/lib/punchblock/translator/asterisk.rb +16 -22
- data/lib/punchblock/translator/dtmf_recognizer.rb +4 -4
- data/lib/punchblock/translator/freeswitch/component/input.rb +2 -1
- data/lib/punchblock/translator/input_component.rb +2 -2
- data/lib/punchblock/version.rb +1 -1
- data/punchblock.gemspec +1 -1
- data/spec/punchblock/connection/asterisk_spec.rb +8 -7
- data/spec/punchblock/translator/asterisk/call_spec.rb +262 -229
- data/spec/punchblock/translator/asterisk/component/asterisk/agi_command_spec.rb +57 -29
- data/spec/punchblock/translator/asterisk/component/asterisk/ami_action_spec.rb +40 -46
- data/spec/punchblock/translator/asterisk/component/input_spec.rb +7 -7
- data/spec/punchblock/translator/asterisk/component/output_spec.rb +84 -53
- data/spec/punchblock/translator/asterisk/component/record_spec.rb +55 -83
- data/spec/punchblock/translator/asterisk/component/stop_by_redirect_spec.rb +5 -1
- data/spec/punchblock/translator/asterisk/component_spec.rb +2 -10
- data/spec/punchblock/translator/asterisk_spec.rb +73 -100
- metadata +5 -10
|
@@ -11,8 +11,9 @@ module Punchblock
|
|
|
11
11
|
|
|
12
12
|
let(:media_engine) { nil }
|
|
13
13
|
let(:channel) { 'SIP/foo' }
|
|
14
|
-
let(:
|
|
15
|
-
let(:
|
|
14
|
+
let(:ami_client) { stub('AMI Client').as_null_object }
|
|
15
|
+
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection, media_engine }
|
|
16
|
+
let(:mock_call) { Punchblock::Translator::Asterisk::Call.new channel, translator, ami_client, connection }
|
|
16
17
|
|
|
17
18
|
let :original_command do
|
|
18
19
|
Punchblock::Component::Record.new command_options
|
|
@@ -40,7 +41,7 @@ module Punchblock
|
|
|
40
41
|
before { mock_call.stub(:answered?).and_return(true) }
|
|
41
42
|
|
|
42
43
|
it "sets command response to a reference to the component" do
|
|
43
|
-
|
|
44
|
+
ami_client.should_receive(:send_action)
|
|
44
45
|
subject.execute
|
|
45
46
|
original_command.response(0.1).should be_a Ref
|
|
46
47
|
original_command.component_id.should be == subject.id
|
|
@@ -48,17 +49,15 @@ module Punchblock
|
|
|
48
49
|
|
|
49
50
|
it "starts a recording via AMI, using the component ID as the filename" do
|
|
50
51
|
filename = "#{Record::RECORDING_BASE_PATH}/#{subject.id}"
|
|
51
|
-
|
|
52
|
+
ami_client.should_receive(:send_action).once.with('Monitor', 'Channel' => channel, 'File' => filename, 'Format' => 'wav', 'Mix' => true)
|
|
52
53
|
subject.execute
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
it "sends a success complete event when the recording ends" do
|
|
56
57
|
full_filename = "file://#{Record::RECORDING_BASE_PATH}/#{subject.id}.wav"
|
|
57
|
-
|
|
58
|
+
ami_client.should_receive(:send_action)
|
|
58
59
|
subject.execute
|
|
59
|
-
monitor_stop_event = RubyAMI::Event.new
|
|
60
|
-
e['Channel'] = channel
|
|
61
|
-
end
|
|
60
|
+
monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
|
|
62
61
|
mock_call.process_ami_event monitor_stop_event
|
|
63
62
|
reason.should be_a Punchblock::Component::Record::Complete::Success
|
|
64
63
|
recording.uri.should be == full_filename
|
|
@@ -66,17 +65,15 @@ module Punchblock
|
|
|
66
65
|
end
|
|
67
66
|
|
|
68
67
|
it "can be called multiple times on the same call" do
|
|
69
|
-
|
|
68
|
+
ami_client.should_receive(:send_action).twice
|
|
70
69
|
subject.execute
|
|
71
70
|
|
|
72
|
-
monitor_stop_event = RubyAMI::Event.new
|
|
73
|
-
e['Channel'] = channel
|
|
74
|
-
end
|
|
71
|
+
monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
|
|
75
72
|
|
|
76
73
|
mock_call.process_ami_event monitor_stop_event
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
Record.new(original_command, mock_call).execute
|
|
76
|
+
Punchblock::Component::Record.new(command_options).request!
|
|
80
77
|
mock_call.process_ami_event monitor_stop_event
|
|
81
78
|
end
|
|
82
79
|
|
|
@@ -84,7 +81,7 @@ module Punchblock
|
|
|
84
81
|
context "set to nil" do
|
|
85
82
|
let(:command_options) { { :start_paused => nil } }
|
|
86
83
|
it "should execute normally" do
|
|
87
|
-
|
|
84
|
+
ami_client.should_receive(:send_action).once
|
|
88
85
|
subject.execute
|
|
89
86
|
original_command.response(0.1).should be_a Ref
|
|
90
87
|
end
|
|
@@ -93,7 +90,7 @@ module Punchblock
|
|
|
93
90
|
context "set to false" do
|
|
94
91
|
let(:command_options) { { :start_paused => false } }
|
|
95
92
|
it "should execute normally" do
|
|
96
|
-
|
|
93
|
+
ami_client.should_receive(:send_action).once
|
|
97
94
|
subject.execute
|
|
98
95
|
original_command.response(0.1).should be_a Ref
|
|
99
96
|
end
|
|
@@ -102,7 +99,7 @@ module Punchblock
|
|
|
102
99
|
context "set to true" do
|
|
103
100
|
let(:command_options) { { :start_paused => true } }
|
|
104
101
|
it "should return an error and not execute any actions" do
|
|
105
|
-
mock_call.
|
|
102
|
+
mock_call.should_receive(:execute_agi_command).never
|
|
106
103
|
subject.execute
|
|
107
104
|
error = ProtocolError.new.setup 'option error', 'A start-paused value of true is unsupported.'
|
|
108
105
|
original_command.response(0.1).should be == error
|
|
@@ -114,7 +111,7 @@ module Punchblock
|
|
|
114
111
|
context "set to nil" do
|
|
115
112
|
let(:command_options) { { :initial_timeout => nil } }
|
|
116
113
|
it "should execute normally" do
|
|
117
|
-
|
|
114
|
+
ami_client.should_receive(:send_action).once
|
|
118
115
|
subject.execute
|
|
119
116
|
original_command.response(0.1).should be_a Ref
|
|
120
117
|
end
|
|
@@ -123,7 +120,7 @@ module Punchblock
|
|
|
123
120
|
context "set to -1" do
|
|
124
121
|
let(:command_options) { { :initial_timeout => -1 } }
|
|
125
122
|
it "should execute normally" do
|
|
126
|
-
|
|
123
|
+
ami_client.should_receive(:send_action).once
|
|
127
124
|
subject.execute
|
|
128
125
|
original_command.response(0.1).should be_a Ref
|
|
129
126
|
end
|
|
@@ -132,7 +129,7 @@ module Punchblock
|
|
|
132
129
|
context "set to a positive number" do
|
|
133
130
|
let(:command_options) { { :initial_timeout => 10 } }
|
|
134
131
|
it "should return an error and not execute any actions" do
|
|
135
|
-
mock_call.
|
|
132
|
+
mock_call.should_receive(:execute_agi_command).never
|
|
136
133
|
subject.execute
|
|
137
134
|
error = ProtocolError.new.setup 'option error', 'An initial-timeout value is unsupported.'
|
|
138
135
|
original_command.response(0.1).should be == error
|
|
@@ -144,7 +141,7 @@ module Punchblock
|
|
|
144
141
|
context "set to nil" do
|
|
145
142
|
let(:command_options) { { :final_timeout => nil } }
|
|
146
143
|
it "should execute normally" do
|
|
147
|
-
|
|
144
|
+
ami_client.should_receive(:send_action).once
|
|
148
145
|
subject.execute
|
|
149
146
|
original_command.response(0.1).should be_a Ref
|
|
150
147
|
end
|
|
@@ -153,7 +150,7 @@ module Punchblock
|
|
|
153
150
|
context "set to -1" do
|
|
154
151
|
let(:command_options) { { :final_timeout => -1 } }
|
|
155
152
|
it "should execute normally" do
|
|
156
|
-
|
|
153
|
+
ami_client.should_receive(:send_action).once
|
|
157
154
|
subject.execute
|
|
158
155
|
original_command.response(0.1).should be_a Ref
|
|
159
156
|
end
|
|
@@ -162,7 +159,7 @@ module Punchblock
|
|
|
162
159
|
context "set to a positive number" do
|
|
163
160
|
let(:command_options) { { :final_timeout => 10 } }
|
|
164
161
|
it "should return an error and not execute any actions" do
|
|
165
|
-
mock_call.
|
|
162
|
+
mock_call.should_receive(:execute_agi_command).never
|
|
166
163
|
subject.execute
|
|
167
164
|
error = ProtocolError.new.setup 'option error', 'A final-timeout value is unsupported.'
|
|
168
165
|
original_command.response(0.1).should be == error
|
|
@@ -174,17 +171,15 @@ module Punchblock
|
|
|
174
171
|
context "set to nil" do
|
|
175
172
|
let(:command_options) { { :format => nil } }
|
|
176
173
|
it "should execute as 'wav'" do
|
|
177
|
-
|
|
174
|
+
ami_client.should_receive(:send_action).once.with('Monitor', hash_including('Format' => 'wav'))
|
|
178
175
|
subject.execute
|
|
179
176
|
original_command.response(0.1).should be_a Ref
|
|
180
177
|
end
|
|
181
178
|
|
|
182
179
|
it "provides the correct filename in the recording" do
|
|
183
|
-
|
|
180
|
+
ami_client.should_receive(:send_action)
|
|
184
181
|
subject.execute
|
|
185
|
-
monitor_stop_event = RubyAMI::Event.new
|
|
186
|
-
e['Channel'] = channel
|
|
187
|
-
end
|
|
182
|
+
monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
|
|
188
183
|
mock_call.process_ami_event monitor_stop_event
|
|
189
184
|
recording.uri.should match(/.*\.wav$/)
|
|
190
185
|
end
|
|
@@ -193,17 +188,15 @@ module Punchblock
|
|
|
193
188
|
context "set to 'mp3'" do
|
|
194
189
|
let(:command_options) { { :format => 'mp3' } }
|
|
195
190
|
it "should execute as 'mp3'" do
|
|
196
|
-
|
|
191
|
+
ami_client.should_receive(:send_action).once.with('Monitor', hash_including('Format' => 'mp3'))
|
|
197
192
|
subject.execute
|
|
198
193
|
original_command.response(0.1).should be_a Ref
|
|
199
194
|
end
|
|
200
195
|
|
|
201
196
|
it "provides the correct filename in the recording" do
|
|
202
|
-
|
|
197
|
+
ami_client.should_receive(:send_action)
|
|
203
198
|
subject.execute
|
|
204
|
-
monitor_stop_event = RubyAMI::Event.new
|
|
205
|
-
e['Channel'] = channel
|
|
206
|
-
end
|
|
199
|
+
monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
|
|
207
200
|
mock_call.process_ami_event monitor_stop_event
|
|
208
201
|
recording.uri.should match(/.*\.mp3$/)
|
|
209
202
|
end
|
|
@@ -214,8 +207,8 @@ module Punchblock
|
|
|
214
207
|
context "set to nil" do
|
|
215
208
|
let(:command_options) { { :start_beep => nil } }
|
|
216
209
|
it "should execute normally" do
|
|
217
|
-
mock_call.
|
|
218
|
-
|
|
210
|
+
mock_call.should_receive(:execute_agi_command).never.with('STREAM FILE', 'beep', '""')
|
|
211
|
+
ami_client.should_receive(:send_action).once
|
|
219
212
|
subject.execute
|
|
220
213
|
original_command.response(0.1).should be_a Ref
|
|
221
214
|
end
|
|
@@ -224,8 +217,8 @@ module Punchblock
|
|
|
224
217
|
context "set to false" do
|
|
225
218
|
let(:command_options) { { :start_beep => false } }
|
|
226
219
|
it "should execute normally" do
|
|
227
|
-
mock_call.
|
|
228
|
-
|
|
220
|
+
mock_call.should_receive(:execute_agi_command).never.with('STREAM FILE', 'beep', '""')
|
|
221
|
+
ami_client.should_receive(:send_action).once
|
|
229
222
|
subject.execute
|
|
230
223
|
original_command.response(0.1).should be_a Ref
|
|
231
224
|
end
|
|
@@ -235,21 +228,22 @@ module Punchblock
|
|
|
235
228
|
let(:command_options) { { :start_beep => true } }
|
|
236
229
|
|
|
237
230
|
it "should play a beep before recording" do
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
mock_call.async.should_receive(:send_ami_action).once.ordered
|
|
231
|
+
mock_call.should_receive(:execute_agi_command).once.with('STREAM FILE', 'beep', '""').ordered.and_return code: 200
|
|
232
|
+
ami_client.should_receive(:send_action).once.ordered
|
|
241
233
|
subject.execute
|
|
242
234
|
original_command.response(0.1).should be_a Ref
|
|
243
235
|
end
|
|
244
236
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
237
|
+
context "when we get a RubyAMI Error" do
|
|
238
|
+
it "should send an error complete event" do
|
|
239
|
+
error = RubyAMI::Error.new.tap { |e| e.message = 'FooBar' }
|
|
240
|
+
mock_call.should_receive(:execute_agi_command).and_raise error
|
|
241
|
+
ami_client.should_receive(:send_action).never
|
|
242
|
+
subject.execute
|
|
243
|
+
complete_reason = original_command.complete_event(0.1).reason
|
|
244
|
+
complete_reason.should be_a Punchblock::Event::Complete::Error
|
|
245
|
+
complete_reason.details.should == "Terminated due to AMI error 'FooBar'"
|
|
249
246
|
end
|
|
250
|
-
mock_call.async.should_receive(:send_ami_action).once
|
|
251
|
-
subject.execute
|
|
252
|
-
original_command.response(0.1).should be_a Ref
|
|
253
247
|
end
|
|
254
248
|
end
|
|
255
249
|
end
|
|
@@ -258,7 +252,7 @@ module Punchblock
|
|
|
258
252
|
context "set to nil" do
|
|
259
253
|
let(:command_options) { { :max_duration => nil } }
|
|
260
254
|
it "should execute normally" do
|
|
261
|
-
|
|
255
|
+
ami_client.should_receive(:send_action).once
|
|
262
256
|
subject.execute
|
|
263
257
|
original_command.response(0.1).should be_a Ref
|
|
264
258
|
end
|
|
@@ -267,7 +261,7 @@ module Punchblock
|
|
|
267
261
|
context "set to -1" do
|
|
268
262
|
let(:command_options) { { :max_duration => -1 } }
|
|
269
263
|
it "should execute normally" do
|
|
270
|
-
|
|
264
|
+
ami_client.should_receive(:send_action).once
|
|
271
265
|
subject.execute
|
|
272
266
|
original_command.response(0.1).should be_a Ref
|
|
273
267
|
end
|
|
@@ -289,24 +283,18 @@ module Punchblock
|
|
|
289
283
|
let(:command_options) { { :max_duration => 1000 } }
|
|
290
284
|
|
|
291
285
|
it "executes a StopMonitor action" do
|
|
292
|
-
|
|
293
|
-
|
|
286
|
+
ami_client.should_receive :send_action
|
|
287
|
+
ami_client.should_receive(:send_action).once.with('StopMonitor', 'Channel' => channel)
|
|
294
288
|
subject.execute
|
|
295
289
|
sleep 1.2
|
|
296
290
|
end
|
|
297
291
|
|
|
298
292
|
it "sends the correct complete event" do
|
|
299
|
-
async_proxy = mock_call.async
|
|
300
|
-
def async_proxy.send_ami_action(*args, &block)
|
|
301
|
-
block.call Punchblock::Component::Asterisk::AMI::Action::Complete::Success.new if block
|
|
302
|
-
end
|
|
303
293
|
full_filename = "file://#{Record::RECORDING_BASE_PATH}/#{subject.id}.wav"
|
|
304
294
|
subject.execute
|
|
305
295
|
sleep 1.2
|
|
306
296
|
|
|
307
|
-
monitor_stop_event = RubyAMI::Event.new
|
|
308
|
-
e['Channel'] = channel
|
|
309
|
-
end
|
|
297
|
+
monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
|
|
310
298
|
mock_call.process_ami_event monitor_stop_event
|
|
311
299
|
|
|
312
300
|
reason.should be_a Punchblock::Component::Record::Complete::Success
|
|
@@ -335,7 +323,7 @@ module Punchblock
|
|
|
335
323
|
let(:command) { Punchblock::Component::Stop.new }
|
|
336
324
|
|
|
337
325
|
before do
|
|
338
|
-
|
|
326
|
+
ami_client.should_receive :send_action
|
|
339
327
|
mock_call.should_receive(:answered?).and_return(true)
|
|
340
328
|
command.request!
|
|
341
329
|
original_command.request!
|
|
@@ -343,34 +331,24 @@ module Punchblock
|
|
|
343
331
|
end
|
|
344
332
|
|
|
345
333
|
let :send_stop_event do
|
|
346
|
-
monitor_stop_event = RubyAMI::Event.new
|
|
347
|
-
e['Channel'] = channel
|
|
348
|
-
end
|
|
334
|
+
monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
|
|
349
335
|
mock_call.process_ami_event monitor_stop_event
|
|
350
336
|
end
|
|
351
337
|
|
|
352
338
|
it "sets the command response to true" do
|
|
353
|
-
|
|
339
|
+
ami_client.should_receive :send_action
|
|
354
340
|
subject.execute_command command
|
|
355
341
|
send_stop_event
|
|
356
342
|
command.response(0.1).should be == true
|
|
357
343
|
end
|
|
358
344
|
|
|
359
345
|
it "executes a StopMonitor action" do
|
|
360
|
-
|
|
346
|
+
ami_client.should_receive(:send_action).once.with('StopMonitor', 'Channel' => channel)
|
|
361
347
|
subject.execute_command command
|
|
362
348
|
end
|
|
363
349
|
|
|
364
350
|
it "sends the correct complete event" do
|
|
365
|
-
|
|
366
|
-
class << self
|
|
367
|
-
undef :send_ami_action # This is here because mocha has already defined #send_ami_action above. We need to undef it to prevent a warning on redefinition.
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
def send_ami_action(*args, &block)
|
|
371
|
-
block.call ::Punchblock::Component::Asterisk::AMI::Action::Complete::Success.new if block
|
|
372
|
-
end
|
|
373
|
-
end
|
|
351
|
+
ami_client.should_receive(:send_action).and_return RubyAMI::Response.new
|
|
374
352
|
|
|
375
353
|
full_filename = "file://#{Record::RECORDING_BASE_PATH}/#{subject.id}.wav"
|
|
376
354
|
subject.execute_command command
|
|
@@ -391,16 +369,13 @@ module Punchblock
|
|
|
391
369
|
end
|
|
392
370
|
|
|
393
371
|
it "sets the command response to true" do
|
|
394
|
-
|
|
395
|
-
def async_proxy.send_ami_action(*args, &block)
|
|
396
|
-
block.call Punchblock::Component::Asterisk::AMI::Action::Complete::Success.new if block
|
|
397
|
-
end
|
|
372
|
+
ami_client.should_receive(:send_action).and_return RubyAMI::Response.new
|
|
398
373
|
subject.execute_command command
|
|
399
374
|
command.response(0.1).should be == true
|
|
400
375
|
end
|
|
401
376
|
|
|
402
377
|
it "pauses the recording via AMI" do
|
|
403
|
-
|
|
378
|
+
ami_client.should_receive(:send_action).once.with('PauseMonitor', 'Channel' => channel)
|
|
404
379
|
subject.execute_command command
|
|
405
380
|
end
|
|
406
381
|
end
|
|
@@ -415,16 +390,13 @@ module Punchblock
|
|
|
415
390
|
end
|
|
416
391
|
|
|
417
392
|
it "sets the command response to true" do
|
|
418
|
-
|
|
419
|
-
def async_proxy.send_ami_action(*args, &block)
|
|
420
|
-
block.call Punchblock::Component::Asterisk::AMI::Action::Complete::Success.new if block
|
|
421
|
-
end
|
|
393
|
+
ami_client.should_receive(:send_action).and_return RubyAMI::Response.new
|
|
422
394
|
subject.execute_command command
|
|
423
395
|
command.response(0.1).should be == true
|
|
424
396
|
end
|
|
425
397
|
|
|
426
398
|
it "resumes the recording via AMI" do
|
|
427
|
-
|
|
399
|
+
ami_client.should_receive(:send_action).once.with('ResumeMonitor', 'Channel' => channel)
|
|
428
400
|
subject.execute_command command
|
|
429
401
|
end
|
|
430
402
|
end
|
|
@@ -15,7 +15,11 @@ module Punchblock
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
let(:
|
|
18
|
+
let(:connection) { stub 'Connection' }
|
|
19
|
+
let(:ami_client) { stub('AMI Client').as_null_object }
|
|
20
|
+
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection }
|
|
21
|
+
let(:mock_call) { Call.new 'SIP/foo', translator, ami_client, connection }
|
|
22
|
+
|
|
19
23
|
subject { MockComponent.new Hash.new, mock_call }
|
|
20
24
|
|
|
21
25
|
describe "#execute_command" do
|
|
@@ -13,7 +13,8 @@ module Punchblock
|
|
|
13
13
|
describe Component do
|
|
14
14
|
let(:connection) { Punchblock::Connection::Asterisk.new }
|
|
15
15
|
let(:translator) { connection.translator }
|
|
16
|
-
let(:
|
|
16
|
+
let(:ami_client) { connection.ami_client }
|
|
17
|
+
let(:call) { Punchblock::Translator::Asterisk::Call.new 'foo', translator, ami_client, connection }
|
|
17
18
|
let(:command) { Punchblock::Component::Input.new }
|
|
18
19
|
|
|
19
20
|
subject { Component.new command, call }
|
|
@@ -38,15 +39,6 @@ module Punchblock
|
|
|
38
39
|
connection.should_receive(:handle_event).once.with expected_event
|
|
39
40
|
subject.send_event event
|
|
40
41
|
end
|
|
41
|
-
|
|
42
|
-
context "when marked internal" do
|
|
43
|
-
before { subject.internal = true }
|
|
44
|
-
|
|
45
|
-
it "should add the event to the command" do
|
|
46
|
-
command.should_receive(:add_event).once.with expected_event
|
|
47
|
-
subject.send_event event
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
42
|
end
|
|
51
43
|
|
|
52
44
|
describe "#send_complete_event" do
|