call_center 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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