call_center 0.1.1 → 0.1.2

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.
data/README.md CHANGED
@@ -3,6 +3,8 @@ Call Center
3
3
 
4
4
  Support for defining call center workflows.
5
5
 
6
+ [![Build Status](https://secure.travis-ci.org/zendesk/call_center.png)](http://travis-ci.org/zendesk/call_center)
7
+
6
8
  Overview
7
9
  --------
8
10
  Call Center streamlines the process of defining multi-party call workflows in your application. Particularly, with [Twilio](http://www.twilio.com/docs) in mind.
data/Rakefile CHANGED
@@ -40,7 +40,13 @@ Rcov::RcovTask.new do |test|
40
40
  test.rcov_opts << '--exclude "gems/*,lib/call_center/core_ext/object_instance_exec.rb"'
41
41
  end
42
42
 
43
- task :default => :test
43
+ namespace :test do
44
+ Rake::TestTask.new(:dsl) do |t|
45
+ t.pattern = "minitest/**/*_test.rb"
46
+ end
47
+ end
48
+
49
+ task :default => ['test', 'test:dsl']
44
50
 
45
51
  require 'rake/rdoctask'
46
52
  Rake::RDocTask.new do |rdoc|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{call_center}
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Henry Hsu"]
@@ -54,6 +54,10 @@ module CallCenter
54
54
  def current_state_machine
55
55
  self.state_machines[self.call_flow_state_machine_name]
56
56
  end
57
+
58
+ def inherited(subclass)
59
+ subclass.call_flow_state_machine_name ||= self.call_flow_state_machine_name
60
+ end
57
61
  end
58
62
 
59
63
  module InstanceMethods
@@ -4,6 +4,7 @@ require 'call_center/test/dsl'
4
4
 
5
5
  require 'test/examples/legacy_call'
6
6
  require 'test/examples/call'
7
+ require 'test/examples/outbound_call'
7
8
  require 'test/examples/non_standard_call'
8
9
  require 'test/examples/multiple_flow_call'
9
10
  require 'test/examples/dynamic_transition_call'
@@ -175,227 +176,230 @@ class CallCenterTest < Test::Unit::TestCase
175
176
  end
176
177
  end
177
178
 
178
- context "call" do
179
- setup do
180
- @call = Call.new
181
- end
182
-
183
- should "render xml for initial state" do
184
- @call.expects(:notify).with(:rendering_initial)
185
- body @call.render
186
- assert_select "Response>Say", "Hello World"
187
- end
179
+ ['Call', 'SubclassCall'].each do |class_name|
180
+ context class_name do
181
+ setup do
182
+ klass = class_name.constantize
183
+ @call = klass.new
184
+ end
188
185
 
189
- should "return customer url for event" do
190
- assert_equal("/voice/calls/flow?event=voicemail_complete&actor=customer", @call.customer(:voicemail_complete))
191
- end
186
+ should "render xml for initial state" do
187
+ @call.expects(:notify).with(:rendering_initial)
188
+ body @call.render
189
+ assert_select "Response>Say", "Hello World"
190
+ end
192
191
 
193
- should "return agent url for event" do
194
- assert_equal("/voice/calls/flow?event=voicemail_complete&actor=agent", @call.agent(:voicemail_complete))
195
- end
192
+ should "return customer url for event" do
193
+ assert_equal("/voice/calls/flow?event=voicemail_complete&actor=customer", @call.customer(:voicemail_complete))
194
+ end
196
195
 
197
- should "render xml for voicemail state" do
198
- @call.stubs(:agents_available?).returns(false)
199
- @call.incoming_call!
200
- @call.expects(:notify).with(:rendering_voicemail)
196
+ should "return agent url for event" do
197
+ assert_equal("/voice/calls/flow?event=voicemail_complete&actor=agent", @call.agent(:voicemail_complete))
198
+ end
201
199
 
202
- body @call.render
203
- assert_select "Response>Say"
204
- assert_select "Response>Record[action=/voice/calls/flow?event=voicemail_complete&actor=customer]"
205
- end
200
+ should "render xml for voicemail state" do
201
+ @call.stubs(:agents_available?).returns(false)
202
+ @call.incoming_call!
203
+ @call.expects(:notify).with(:rendering_voicemail)
206
204
 
207
- should "render noop when no render block" do
208
- @call.stubs(:agents_available?).returns(true)
209
- @call.incoming_call!
205
+ body @call.render
206
+ assert_select "Response>Say"
207
+ assert_select "Response>Record[action=/voice/calls/flow?event=voicemail_complete&actor=customer]"
208
+ end
210
209
 
211
- body @call.render
212
- assert_select "Response"
213
- end
210
+ should "render noop when no render block" do
211
+ @call.stubs(:agents_available?).returns(true)
212
+ @call.incoming_call!
214
213
 
215
- should "execute callbacks" do
216
- @call.state = 'cancelled'
214
+ body @call.render
215
+ assert_select "Response"
216
+ end
217
217
 
218
- @call.expects(:notify).with(:before_always).times(3)
219
- @call.expects(:notify).with(:before_always_uniq).times(1)
218
+ should "execute callbacks" do
219
+ @call.state = 'cancelled'
220
220
 
221
- @call.expects(:notify).with(:after_always).times(4)
222
- @call.expects(:notify).with(:after_success).times(3)
223
- @call.expects(:notify).with(:after_failure).times(1)
221
+ @call.expects(:notify).with(:before_always).times(3)
222
+ @call.expects(:notify).with(:before_always_uniq).times(1)
224
223
 
225
- @call.expects(:notify).with(:after_always_uniq).times(1)
226
- @call.expects(:notify).with { |notification, transition| notification == :after_success_uniq && transition.kind_of?(StateMachine::Transition) }.times(1)
227
- @call.expects(:notify).with(:after_failure_uniq).times(0)
224
+ @call.expects(:notify).with(:after_always).times(4)
225
+ @call.expects(:notify).with(:after_success).times(3)
226
+ @call.expects(:notify).with(:after_failure).times(1)
228
227
 
229
- @call.customer_end!
230
- @call.customer_end!
231
- @call.customer_end!
232
- assert(!@call.customer_hangs_up)
233
- end
228
+ @call.expects(:notify).with(:after_always_uniq).times(1)
229
+ @call.expects(:notify).with { |notification, transition| notification == :after_success_uniq && transition.kind_of?(StateMachine::Transition) }.times(1)
230
+ @call.expects(:notify).with(:after_failure_uniq).times(0)
234
231
 
235
- should "execute callbacks in sequence" do
236
- seq = sequence('callback_sequence')
237
- @call.state = 'cancelled'
232
+ @call.customer_end!
233
+ @call.customer_end!
234
+ @call.customer_end!
235
+ assert(!@call.customer_hangs_up)
236
+ end
238
237
 
239
- @call.expects(:notify).with(:before_always).in_sequence(seq)
240
- @call.expects(:notify).with(:before_always_uniq).in_sequence(seq)
238
+ should "execute callbacks in sequence" do
239
+ seq = sequence('callback_sequence')
240
+ @call.state = 'cancelled'
241
241
 
242
- @call.expects(:notify).with(:after_always).in_sequence(seq)
243
- @call.expects(:notify).with(:after_success).in_sequence(seq)
242
+ @call.expects(:notify).with(:before_always).in_sequence(seq)
243
+ @call.expects(:notify).with(:before_always_uniq).in_sequence(seq)
244
244
 
245
- @call.expects(:notify).with(:after_always_uniq).in_sequence(seq)
246
- @call.expects(:notify).with(:after_success_uniq, anything).in_sequence(seq)
245
+ @call.expects(:notify).with(:after_always).in_sequence(seq)
246
+ @call.expects(:notify).with(:after_success).in_sequence(seq)
247
247
 
248
- @call.customer_end!
249
- end
248
+ @call.expects(:notify).with(:after_always_uniq).in_sequence(seq)
249
+ @call.expects(:notify).with(:after_success_uniq, anything).in_sequence(seq)
250
250
 
251
- should "defer callbacks" do
252
- (class << @call; self; end).class_eval do
253
- include CallCenter::DeferredCallbacks
251
+ @call.customer_end!
254
252
  end
255
- @call.state = 'cancelled'
256
253
 
257
- @call.expects(:notify).with(:before_always).never
258
- @call.expects(:notify).with(:before_always_uniq).never
259
-
260
- @call.expects(:notify).with(:after_always).never
261
- @call.expects(:notify).with(:after_success).never
262
- @call.expects(:notify).with(:after_failure).never
254
+ should "defer callbacks" do
255
+ (class << @call; self; end).class_eval do
256
+ include CallCenter::DeferredCallbacks
257
+ end
258
+ @call.state = 'cancelled'
263
259
 
264
- @call.expects(:notify).with(:after_always_uniq).never
265
- @call.expects(:notify).with(:after_success_uniq, anything).never
260
+ @call.expects(:notify).with(:before_always).never
261
+ @call.expects(:notify).with(:before_always_uniq).never
266
262
 
267
- @call.customer_end!
268
- assert(!@call.customer_hangs_up)
263
+ @call.expects(:notify).with(:after_always).never
264
+ @call.expects(:notify).with(:after_success).never
265
+ @call.expects(:notify).with(:after_failure).never
269
266
 
270
- # Ready for deferred callbacks
267
+ @call.expects(:notify).with(:after_always_uniq).never
268
+ @call.expects(:notify).with(:after_success_uniq, anything).never
271
269
 
272
- seq = sequence('callback_sequence')
270
+ @call.customer_end!
271
+ assert(!@call.customer_hangs_up)
273
272
 
274
- @call.expects(:notify).with(:before_always)
275
- @call.expects(:notify).with(:before_always_uniq)
273
+ # Ready for deferred callbacks
276
274
 
277
- @call.call_flow_run_deferred(:before_transition)
275
+ seq = sequence('callback_sequence')
278
276
 
279
- @call.expects(:notify).with(:after_always).times(2)
280
- @call.expects(:notify).with(:after_success)
277
+ @call.expects(:notify).with(:before_always)
278
+ @call.expects(:notify).with(:before_always_uniq)
281
279
 
282
- @call.expects(:notify).with(:after_always_uniq)
283
- @call.expects(:notify).with(:after_success_uniq, anything)
280
+ @call.call_flow_run_deferred(:before_transition)
284
281
 
285
- @call.call_flow_run_deferred(:after_transition)
282
+ @call.expects(:notify).with(:after_always).times(2)
283
+ @call.expects(:notify).with(:after_success)
286
284
 
287
- @call.expects(:notify).with(:after_always).times(2)
288
- @call.expects(:notify).with(:after_failure)
289
- @call.expects(:notify).with(:after_always_uniq)
285
+ @call.expects(:notify).with(:after_always_uniq)
286
+ @call.expects(:notify).with(:after_success_uniq, anything)
290
287
 
291
- @call.call_flow_run_deferred(:after_failure)
288
+ @call.call_flow_run_deferred(:after_transition)
292
289
 
293
- # Empty
294
- @call.call_flow_run_deferred(:before_transition)
295
- @call.call_flow_run_deferred(:after_transition)
296
- @call.call_flow_run_deferred(:after_failure)
297
- end
290
+ @call.expects(:notify).with(:after_always).times(2)
291
+ @call.expects(:notify).with(:after_failure)
292
+ @call.expects(:notify).with(:after_always_uniq)
298
293
 
299
- should "asynchronously perform event" do
300
- @call.stubs(:agents_available?).returns(true)
301
- @call.incoming_call!
302
- @call.expects(:redirect_to).with(:start_conference)
294
+ @call.call_flow_run_deferred(:after_failure)
303
295
 
304
- @call.redirect_and_start_conference!
305
- end
296
+ # Empty
297
+ @call.call_flow_run_deferred(:before_transition)
298
+ @call.call_flow_run_deferred(:after_transition)
299
+ @call.call_flow_run_deferred(:after_failure)
300
+ end
306
301
 
307
- should "asynchronously perform event with options" do
308
- @call.stubs(:agents_available?).returns(true)
309
- @call.incoming_call!
310
- @call.expects(:redirect_to).with(:start_conference, :status => 'completed')
302
+ should "asynchronously perform event" do
303
+ @call.stubs(:agents_available?).returns(true)
304
+ @call.incoming_call!
305
+ @call.expects(:redirect_to).with(:start_conference)
311
306
 
312
- @call.redirect_and_start_conference!(:status => 'completed')
313
- end
307
+ @call.redirect_and_start_conference!
308
+ end
314
309
 
315
- should "raise error on missing method" do
316
- assert_raises {
317
- @call.i_am_missing!
318
- }
319
- end
310
+ should "asynchronously perform event with options" do
311
+ @call.stubs(:agents_available?).returns(true)
312
+ @call.incoming_call!
313
+ @call.expects(:redirect_to).with(:start_conference, :status => 'completed')
320
314
 
321
- should "draw state machine digraph" do
322
- Call.state_machines[:state].expects(:draw).with(:name => 'call_workflow', :font => 'Helvetica Neue')
323
- @call.draw_call_flow(:name => 'call_workflow', :font => 'Helvetica Neue')
324
- end
315
+ @call.redirect_and_start_conference!(:status => 'completed')
316
+ end
325
317
 
326
- context "using test DSL:" do
327
- should_flow :on => :incoming_call, :initial => :voicemail, :when => Proc.new {
328
- @call.stubs(:agents_available?).returns(false)
329
- @call.stubs(:notify)
330
- @call.stubs(:customer).returns('the_flow')
331
- } do
332
- should_also { assert_received(@call, :notify) { |e| e.with(:rendering_voicemail) } }
333
- and_also { assert_received(@call, :customer) { |e| e.with(:voicemail_complete) } }
334
- and_render { "Response>Say" }
335
- and_render { "Response>Record[action=the_flow]" }
318
+ should "raise error on missing method" do
319
+ assert_raises {
320
+ @call.i_am_missing!
321
+ }
336
322
  end
337
323
 
338
- should_flow :on => :incoming_call, :initial => :routing, :when => Proc.new {
339
- @call.stubs(:agents_available?).returns(true)
340
- } do
341
- should_render { "Response" }
324
+ should "draw state machine digraph" do
325
+ Call.state_machines[:state].expects(:draw).with(:name => 'call_workflow', :font => 'Helvetica Neue')
326
+ @call.draw_call_flow(:name => 'call_workflow', :font => 'Helvetica Neue')
342
327
  end
343
328
 
344
- should_flow :on => :customer_hangs_up, :routing => :cancelled, :when => Proc.new {
345
- @call.stubs(:notify)
346
- } do
347
- should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } }
348
- and_also { assert @call.cancelled? }
329
+ context "using test DSL:" do
330
+ should_flow :on => :incoming_call, :initial => :voicemail, :when => Proc.new {
331
+ @call.stubs(:agents_available?).returns(false)
332
+ @call.stubs(:notify)
333
+ @call.stubs(:customer).returns('the_flow')
334
+ } do
335
+ should_also { assert_received(@call, :notify) { |e| e.with(:rendering_voicemail) } }
336
+ and_also { assert_received(@call, :customer) { |e| e.with(:voicemail_complete) } }
337
+ and_render { "Response>Say" }
338
+ and_render { "Response>Record[action=the_flow]" }
339
+ end
349
340
 
350
- should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
351
- should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
341
+ should_flow :on => :incoming_call, :initial => :routing, :when => Proc.new {
342
+ @call.stubs(:agents_available?).returns(true)
343
+ } do
344
+ should_render { "Response" }
345
+ end
346
+
347
+ should_flow :on => :customer_hangs_up, :routing => :cancelled, :when => Proc.new {
348
+ @call.stubs(:notify)
349
+ } do
350
+ should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } }
352
351
  and_also { assert @call.cancelled? }
353
352
 
354
353
  should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
355
354
  should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
356
355
  and_also { assert @call.cancelled? }
356
+
357
+ should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
358
+ should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
359
+ and_also { assert @call.cancelled? }
360
+ end
357
361
  end
358
362
  end
359
363
  end
360
- end
361
364
 
362
- context "deferred and using test DSL:" do
363
- setup do
364
- (class << @call; self; end).class_eval do
365
- include CallCenter::DeferredCallbacks
365
+ context "deferred and using test DSL:" do
366
+ setup do
367
+ (class << @call; self; end).class_eval do
368
+ include CallCenter::DeferredCallbacks
369
+ end
366
370
  end
367
- end
368
371
 
369
- should_flow :on => :incoming_call, :initial => :voicemail, :when => Proc.new {
370
- @call.stubs(:agents_available?).returns(false)
371
- @call.stubs(:notify)
372
- @call.stubs(:customer).returns('the_flow')
373
- } do
374
- should_also { assert_received(@call, :notify) { |e| e.with(:rendering_voicemail) } }
375
- and_also { assert_received(@call, :customer) { |e| e.with(:voicemail_complete) } }
376
- and_render { "Response>Say" }
377
- and_render { "Response>Record[action=the_flow]" }
378
- end
379
-
380
- should_flow :on => :incoming_call, :initial => :routing, :when => Proc.new {
381
- @call.stubs(:agents_available?).returns(true)
382
- } do
383
- should_render { "Response" }
384
- end
372
+ should_flow :on => :incoming_call, :initial => :voicemail, :when => Proc.new {
373
+ @call.stubs(:agents_available?).returns(false)
374
+ @call.stubs(:notify)
375
+ @call.stubs(:customer).returns('the_flow')
376
+ } do
377
+ should_also { assert_received(@call, :notify) { |e| e.with(:rendering_voicemail) } }
378
+ and_also { assert_received(@call, :customer) { |e| e.with(:voicemail_complete) } }
379
+ and_render { "Response>Say" }
380
+ and_render { "Response>Record[action=the_flow]" }
381
+ end
385
382
 
386
- should_flow :on => :customer_hangs_up, :routing => :cancelled, :when => Proc.new {
387
- @call.stubs(:notify)
388
- } do
389
- should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } }
390
- and_also { assert @call.cancelled? }
383
+ should_flow :on => :incoming_call, :initial => :routing, :when => Proc.new {
384
+ @call.stubs(:agents_available?).returns(true)
385
+ } do
386
+ should_render { "Response" }
387
+ end
391
388
 
392
- should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
393
- should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
389
+ should_flow :on => :customer_hangs_up, :routing => :cancelled, :when => Proc.new {
390
+ @call.stubs(:notify)
391
+ } do
392
+ should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } }
394
393
  and_also { assert @call.cancelled? }
395
394
 
396
395
  should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
397
396
  should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
398
397
  and_also { assert @call.cancelled? }
398
+
399
+ should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
400
+ should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
401
+ and_also { assert @call.cancelled? }
402
+ end
399
403
  end
400
404
  end
401
405
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: call_center
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Henry Hsu