call_center 1.0.1 → 1.0.3
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/lib/call_center.rb +1 -0
- data/lib/call_center/test/dsl.rb +11 -2
- data/lib/call_center/test/minitest/dsl.rb +9 -2
- metadata +45 -256
- data/.document +0 -5
- data/.rvmrc +0 -1
- data/.travis.yml +0 -5
- data/Gemfile +0 -19
- data/Gemfile.lock +0 -71
- data/Guardfile +0 -5
- data/Guardfile.minitest +0 -9
- data/LICENSE +0 -176
- data/README.md +0 -212
- data/Rakefile +0 -48
- data/VERSION +0 -1
- data/call_center.gemspec +0 -110
- data/init.rb +0 -1
- data/minitest/call_center/test/minitest_test.rb +0 -42
- data/minitest/helper.rb +0 -20
- data/minitest/run.rb +0 -15
- data/test/call_center_test.rb +0 -492
- data/test/core_ext_test.rb +0 -17
- data/test/examples/call.rb +0 -65
- data/test/examples/dynamic_transition_call.rb +0 -43
- data/test/examples/legacy_call.rb +0 -26
- data/test/examples/multiple_flow_call.rb +0 -21
- data/test/examples/non_standard_call.rb +0 -12
- data/test/helper.rb +0 -30
data/Rakefile
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'rubygems'
|
3
|
-
require 'bundler/setup'
|
4
|
-
|
5
|
-
require 'jeweler'
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
8
|
-
gem.name = "call_center"
|
9
|
-
gem.homepage = "http://github.com/zendesk/call_center"
|
10
|
-
gem.license = "MIT"
|
11
|
-
gem.summary = %Q{Support for describing call center workflows}
|
12
|
-
gem.description = %Q{Support for describing call center workflows}
|
13
|
-
gem.email = "hhsu@zendesk.com"
|
14
|
-
gem.authors = ["Henry Hsu"]
|
15
|
-
gem.license = "Apache License Version 2.0"
|
16
|
-
end
|
17
|
-
Jeweler::RubygemsDotOrgTasks.new
|
18
|
-
|
19
|
-
require 'rake/testtask'
|
20
|
-
Rake::TestTask.new(:test) do |test|
|
21
|
-
test.pattern = 'test/**/*_test.rb'
|
22
|
-
test.verbose = true
|
23
|
-
end
|
24
|
-
|
25
|
-
require 'rcov/rcovtask'
|
26
|
-
Rcov::RcovTask.new do |test|
|
27
|
-
test.pattern = 'test/**/*_test.rb'
|
28
|
-
test.verbose = true
|
29
|
-
test.rcov_opts << '--exclude "gems/*,lib/call_center/core_ext/object_instance_exec.rb"'
|
30
|
-
end
|
31
|
-
|
32
|
-
namespace :test do
|
33
|
-
Rake::TestTask.new(:dsl) do |t|
|
34
|
-
t.pattern = "minitest/**/*_test.rb"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
task :default => ['test', 'test:dsl']
|
39
|
-
|
40
|
-
require 'rake/rdoctask'
|
41
|
-
Rake::RDocTask.new do |rdoc|
|
42
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
43
|
-
|
44
|
-
rdoc.rdoc_dir = 'rdoc'
|
45
|
-
rdoc.title = "twilio_flow #{version}"
|
46
|
-
rdoc.rdoc_files.include('README*')
|
47
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
-
end
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
1.0.1
|
data/call_center.gemspec
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
-
# -*- encoding: utf-8 -*-
|
5
|
-
|
6
|
-
Gem::Specification.new do |s|
|
7
|
-
s.name = "call_center"
|
8
|
-
s.version = "1.0.1"
|
9
|
-
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Henry Hsu"]
|
12
|
-
s.date = "2013-02-21"
|
13
|
-
s.description = "Support for describing call center workflows"
|
14
|
-
s.email = "hhsu@zendesk.com"
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"LICENSE",
|
17
|
-
"README.md"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
".document",
|
21
|
-
".rvmrc",
|
22
|
-
".travis.yml",
|
23
|
-
"Gemfile",
|
24
|
-
"Gemfile.lock",
|
25
|
-
"Guardfile",
|
26
|
-
"Guardfile.minitest",
|
27
|
-
"LICENSE",
|
28
|
-
"README.md",
|
29
|
-
"Rakefile",
|
30
|
-
"VERSION",
|
31
|
-
"call_center.gemspec",
|
32
|
-
"init.rb",
|
33
|
-
"lib/call_center.rb",
|
34
|
-
"lib/call_center/conditional_stack.rb",
|
35
|
-
"lib/call_center/core_ext/object_instance_exec.rb",
|
36
|
-
"lib/call_center/deferred_callbacks.rb",
|
37
|
-
"lib/call_center/flow_callback.rb",
|
38
|
-
"lib/call_center/state_machine_ext.rb",
|
39
|
-
"lib/call_center/test/dsl.rb",
|
40
|
-
"lib/call_center/test/minitest/dsl.rb",
|
41
|
-
"minitest/call_center/test/minitest_test.rb",
|
42
|
-
"minitest/helper.rb",
|
43
|
-
"minitest/run.rb",
|
44
|
-
"test/call_center_test.rb",
|
45
|
-
"test/core_ext_test.rb",
|
46
|
-
"test/examples/call.rb",
|
47
|
-
"test/examples/dynamic_transition_call.rb",
|
48
|
-
"test/examples/legacy_call.rb",
|
49
|
-
"test/examples/multiple_flow_call.rb",
|
50
|
-
"test/examples/non_standard_call.rb",
|
51
|
-
"test/helper.rb"
|
52
|
-
]
|
53
|
-
s.homepage = "http://github.com/zendesk/call_center"
|
54
|
-
s.licenses = ["Apache License Version 2.0"]
|
55
|
-
s.require_paths = ["lib"]
|
56
|
-
s.rubygems_version = "1.8.24"
|
57
|
-
s.summary = "Support for describing call center workflows"
|
58
|
-
|
59
|
-
if s.respond_to? :specification_version then
|
60
|
-
s.specification_version = 3
|
61
|
-
|
62
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
63
|
-
s.add_runtime_dependency(%q<builder>, [">= 0"])
|
64
|
-
s.add_runtime_dependency(%q<hsume2-state_machine>, ["~> 1.0.5"])
|
65
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
66
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
67
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
68
|
-
s.add_development_dependency(%q<guard>, [">= 0"])
|
69
|
-
s.add_development_dependency(%q<guard-test>, [">= 0"])
|
70
|
-
s.add_development_dependency(%q<actionpack>, ["~> 2.3.15"])
|
71
|
-
s.add_development_dependency(%q<mocha>, [">= 0"])
|
72
|
-
s.add_development_dependency(%q<bourne>, [">= 1.2.0"])
|
73
|
-
s.add_development_dependency(%q<pre-commit>, [">= 0"])
|
74
|
-
s.add_development_dependency(%q<minitest>, ["~> 3.3.0"])
|
75
|
-
s.add_development_dependency(%q<minitest-reporters>, [">= 0"])
|
76
|
-
s.add_development_dependency(%q<guard-shell>, [">= 0"])
|
77
|
-
else
|
78
|
-
s.add_dependency(%q<builder>, [">= 0"])
|
79
|
-
s.add_dependency(%q<hsume2-state_machine>, ["~> 1.0.5"])
|
80
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
81
|
-
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
82
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
83
|
-
s.add_dependency(%q<guard>, [">= 0"])
|
84
|
-
s.add_dependency(%q<guard-test>, [">= 0"])
|
85
|
-
s.add_dependency(%q<actionpack>, ["~> 2.3.15"])
|
86
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
87
|
-
s.add_dependency(%q<bourne>, [">= 1.2.0"])
|
88
|
-
s.add_dependency(%q<pre-commit>, [">= 0"])
|
89
|
-
s.add_dependency(%q<minitest>, ["~> 3.3.0"])
|
90
|
-
s.add_dependency(%q<minitest-reporters>, [">= 0"])
|
91
|
-
s.add_dependency(%q<guard-shell>, [">= 0"])
|
92
|
-
end
|
93
|
-
else
|
94
|
-
s.add_dependency(%q<builder>, [">= 0"])
|
95
|
-
s.add_dependency(%q<hsume2-state_machine>, ["~> 1.0.5"])
|
96
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
97
|
-
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
98
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
99
|
-
s.add_dependency(%q<guard>, [">= 0"])
|
100
|
-
s.add_dependency(%q<guard-test>, [">= 0"])
|
101
|
-
s.add_dependency(%q<actionpack>, ["~> 2.3.15"])
|
102
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
103
|
-
s.add_dependency(%q<bourne>, [">= 1.2.0"])
|
104
|
-
s.add_dependency(%q<pre-commit>, [">= 0"])
|
105
|
-
s.add_dependency(%q<minitest>, ["~> 3.3.0"])
|
106
|
-
s.add_dependency(%q<minitest-reporters>, [">= 0"])
|
107
|
-
s.add_dependency(%q<guard-shell>, [">= 0"])
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'call_center'
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require File.expand_path('../../helper', File.dirname(__FILE__))
|
2
|
-
require 'call_center/test/minitest/dsl'
|
3
|
-
|
4
|
-
require File.expand_path('../../../test/examples/call', File.dirname(__FILE__))
|
5
|
-
require File.expand_path('../../../test/examples/dynamic_transition_call', File.dirname(__FILE__))
|
6
|
-
|
7
|
-
describe CallCenter::Test::MiniTest::DSL do
|
8
|
-
describe Call do
|
9
|
-
subject { Call.new }
|
10
|
-
let(:call_center_state_field) { :state }
|
11
|
-
|
12
|
-
it_should_flow { on(:incoming_call).from(:initial).to(:routing).if(:agents_available?) }
|
13
|
-
it_should_flow { on(:incoming_call).from(:initial).to(:voicemail).unless(:agents_available?) }
|
14
|
-
it_should_render { is(:initial).expects(:notify).selects("Response>Say", "Hello World") }
|
15
|
-
|
16
|
-
it_should_flow { on(:customer_hangs_up).from(:voicemail).to(:voicemail_completed) }
|
17
|
-
it_should_render { is(:voicemail).expects(:notify).selects("Response>Say", "Hello World").selects("Response>Record[action=/voice/calls/flow?event=voicemail_complete&actor=customer]") }
|
18
|
-
|
19
|
-
it_should_flow { on(:something_crazy_happens).from(:initial).to(:uh_oh) }
|
20
|
-
|
21
|
-
it_should_flow { on(:customer_hangs_up).from(:cancelled).to(:cancelled).expects(:cancelled) { |e| e.never } }
|
22
|
-
|
23
|
-
it_should_not_flow { on(:incoming_call).from(:voicemail) }
|
24
|
-
end
|
25
|
-
|
26
|
-
describe DynamicTransitionCall do
|
27
|
-
subject { DynamicTransitionCall.new }
|
28
|
-
let(:call_center_state_field) { :state }
|
29
|
-
|
30
|
-
it_should_flow { on(:incoming_call).from(:initial).to(:routing_on_client).if(:agents_available?).unless(:via_phone?).if(:prefer_flash?) }
|
31
|
-
it_should_flow { on(:incoming_call).from(:initial).to(:routing_on_client).if(:agents_available?).unless(:via_phone?).unless(:on_mobile?).if(:prefer_flash?) }
|
32
|
-
it_should_flow { on(:incoming_call).from(:initial).to(:routing_on_mobile_client).if(:agents_available?).unless(:via_phone?).if(:on_mobile?) }
|
33
|
-
it_should_flow { on(:incoming_call).from(:initial).to(:routing_on_webrtc).if(:agents_available?).unless(:via_phone?).unless(:on_mobile?).unless(:prefer_flash?) }
|
34
|
-
it_should_flow { on(:incoming_call).from(:initial).to(:routing_on_phone).if(:agents_available?).if(:via_phone?) }
|
35
|
-
|
36
|
-
it_should_flow { on(:incoming_call).from(:initial).to(:voicemail).unless(:agents_available?).unless(:voicemail_full?) }
|
37
|
-
it_should_flow { on(:incoming_call).from(:initial).to(:cancelled).unless(:agents_available?).if(:voicemail_full?) }
|
38
|
-
|
39
|
-
it_should_flow { on(:picks_up).from(:routing_on_client).to(:in_conference).unless(:out_of_area?) }
|
40
|
-
it_should_flow { on(:picks_up).from(:routing_on_client).to(:cancelled).if(:out_of_area?) }
|
41
|
-
end
|
42
|
-
end
|
data/minitest/helper.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'minitest/autorun'
|
4
|
-
require 'mocha'
|
5
|
-
require 'active_support'
|
6
|
-
|
7
|
-
if RUBY_VERSION > "1.9.0"
|
8
|
-
require 'minitest/reporters'
|
9
|
-
MiniTest::Reporters.use! MiniTest::Reporters::DefaultReporter.new
|
10
|
-
end
|
11
|
-
|
12
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
|
-
require 'call_center'
|
14
|
-
|
15
|
-
module CommonCallMethods
|
16
|
-
def agents_available?; end
|
17
|
-
def voicemail; end
|
18
|
-
def voicemail_completed; end
|
19
|
-
def routing; end
|
20
|
-
end
|
data/minitest/run.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
project_root = File.expand_path('..', File.dirname(__FILE__))
|
2
|
-
lib_dir = File.join(project_root, 'lib')
|
3
|
-
test_dir = File.join(project_root, 'minitest')
|
4
|
-
|
5
|
-
begin
|
6
|
-
require 'minitest/reporters'
|
7
|
-
MiniTest::Unit.runner = MiniTest::SuiteRunner.new
|
8
|
-
MiniTest::Unit.runner.reporters << MiniTest::Reporters::ProgressReporter.new
|
9
|
-
rescue LoadError
|
10
|
-
puts "MiniTest::Reporters not available."
|
11
|
-
end
|
12
|
-
|
13
|
-
puts "\n\n"
|
14
|
-
test_files = File.join(test_dir, '**/*_test.rb')
|
15
|
-
Dir[test_files].each { |file| require file }
|
data/test/call_center_test.rb
DELETED
@@ -1,492 +0,0 @@
|
|
1
|
-
require File.expand_path("../helper", __FILE__)
|
2
|
-
|
3
|
-
require 'call_center/test/dsl'
|
4
|
-
|
5
|
-
require File.expand_path('../test/examples/legacy_call', File.dirname(__FILE__))
|
6
|
-
require File.expand_path('../test/examples/call', File.dirname(__FILE__))
|
7
|
-
require File.expand_path('../test/examples/non_standard_call', File.dirname(__FILE__))
|
8
|
-
require File.expand_path('../test/examples/multiple_flow_call', File.dirname(__FILE__))
|
9
|
-
require File.expand_path('../test/examples/dynamic_transition_call', File.dirname(__FILE__))
|
10
|
-
|
11
|
-
class CallCenterTest < Test::Unit::TestCase
|
12
|
-
include CallCenter::Test::DSL
|
13
|
-
|
14
|
-
context "dynamic transition workflow" do
|
15
|
-
setup do
|
16
|
-
@call = DynamicTransitionCall.new
|
17
|
-
@call.stubs(:notify)
|
18
|
-
@call.stubs(:on_mobile?).returns(false)
|
19
|
-
@call.stubs(:prefer_flash?).returns(true)
|
20
|
-
end
|
21
|
-
|
22
|
-
context "agents available on phone" do
|
23
|
-
setup do
|
24
|
-
@call.stubs(:agents_available?).returns(true)
|
25
|
-
@call.stubs(:via_phone?).returns(true)
|
26
|
-
end
|
27
|
-
|
28
|
-
should "transition to routing on phone" do
|
29
|
-
@call.incoming_call!
|
30
|
-
assert_equal 'routing_on_phone', @call.state
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "agents available on client" do
|
35
|
-
setup do
|
36
|
-
@call.stubs(:agents_available?).returns(true)
|
37
|
-
@call.stubs(:via_phone?).returns(false)
|
38
|
-
end
|
39
|
-
|
40
|
-
should "transition to routing on client" do
|
41
|
-
@call.incoming_call!
|
42
|
-
assert_equal 'routing_on_client', @call.state
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context "agents available who do not prefer flash" do
|
47
|
-
setup do
|
48
|
-
@call.stubs(:agents_available?).returns(true)
|
49
|
-
@call.stubs(:via_phone?).returns(false)
|
50
|
-
@call.stubs(:prefer_flash?).returns(false)
|
51
|
-
end
|
52
|
-
|
53
|
-
should "transition to routing on client" do
|
54
|
-
@call.incoming_call!
|
55
|
-
assert_equal 'routing_on_webrtc', @call.state
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context "agents available on mobile client" do
|
60
|
-
setup do
|
61
|
-
@call.stubs(:agents_available?).returns(true)
|
62
|
-
@call.stubs(:via_phone?).returns(false)
|
63
|
-
@call.stubs(:on_mobile?).returns(true)
|
64
|
-
end
|
65
|
-
|
66
|
-
should "transition to routing on client" do
|
67
|
-
@call.incoming_call!
|
68
|
-
assert_equal 'routing_on_mobile_client', @call.state
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context "no agents available" do
|
73
|
-
setup do
|
74
|
-
@call.stubs(:agents_available?).returns(false)
|
75
|
-
@call.stubs(:via_phone?).returns(true)
|
76
|
-
@call.stubs(:voicemail_full?).returns(false)
|
77
|
-
end
|
78
|
-
|
79
|
-
should "transition to voicemail" do
|
80
|
-
@call.incoming_call!
|
81
|
-
assert_equal 'voicemail', @call.state
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context "no agents available when voicemail is full" do
|
86
|
-
setup do
|
87
|
-
@call.stubs(:agents_available?).returns(false)
|
88
|
-
@call.stubs(:via_phone?).returns(false) # Doesn't matter
|
89
|
-
@call.stubs(:voicemail_full?).returns(true)
|
90
|
-
end
|
91
|
-
|
92
|
-
should "transition to voicemail" do
|
93
|
-
@call.incoming_call!
|
94
|
-
assert_equal 'cancelled', @call.state
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
context "out of area" do
|
99
|
-
setup do
|
100
|
-
@call.state = 'routing_on_client'
|
101
|
-
@call.stubs(:out_of_area?).returns(true)
|
102
|
-
end
|
103
|
-
|
104
|
-
should "transition to cancelled" do
|
105
|
-
@call.picks_up!
|
106
|
-
assert_equal 'cancelled', @call.state
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
context "not out of area" do
|
111
|
-
setup do
|
112
|
-
@call.state = 'routing_on_client'
|
113
|
-
@call.stubs(:out_of_area?).returns(false)
|
114
|
-
end
|
115
|
-
|
116
|
-
should "transition to in_conference" do
|
117
|
-
@call.picks_up!
|
118
|
-
assert_equal 'in_conference', @call.state
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
[:call, :legacy_call].each do |call_type|
|
124
|
-
context "#{call_type.to_s.gsub('_', ' ')} workflow" do
|
125
|
-
setup do
|
126
|
-
klass = call_type.to_s.gsub('_', ' ').titleize.gsub(' ', '').constantize
|
127
|
-
@call = klass.new
|
128
|
-
@call.stubs(:notify)
|
129
|
-
end
|
130
|
-
|
131
|
-
context "agents available" do
|
132
|
-
setup do
|
133
|
-
@call.stubs(:agents_available?).returns(true)
|
134
|
-
end
|
135
|
-
|
136
|
-
should "transition to routing" do
|
137
|
-
@call.incoming_call!
|
138
|
-
assert_equal 'routing', @call.state
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
context "no agents available "do
|
143
|
-
setup do
|
144
|
-
@call.stubs(:agents_available?).returns(false)
|
145
|
-
end
|
146
|
-
|
147
|
-
should "transition to voicemail" do
|
148
|
-
@call.incoming_call!
|
149
|
-
assert_equal 'voicemail', @call.state
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
context "in voicemail" do
|
154
|
-
setup do
|
155
|
-
@call.stubs(:agents_available?).returns(false)
|
156
|
-
@call.incoming_call!
|
157
|
-
end
|
158
|
-
|
159
|
-
context "and customer hangs up" do
|
160
|
-
should "transition to voicemail_completed" do
|
161
|
-
@call.customer_hangs_up!
|
162
|
-
assert @call.voicemail_completed?
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
context "something crazy happens" do
|
168
|
-
# It's going to try to call the after transition method, but since it doesn't exist...
|
169
|
-
should "be ok" do
|
170
|
-
@call.something_crazy_happens!
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
context "cancelled" do
|
175
|
-
should "stay in cancelled" do
|
176
|
-
@call.stubs(:cancelled)
|
177
|
-
@call.state = 'cancelled'
|
178
|
-
|
179
|
-
@call.customer_hangs_up!
|
180
|
-
|
181
|
-
assert @call.cancelled?
|
182
|
-
assert_received(@call, :cancelled) { |e| e.never }
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
context "using test DSL:" do
|
187
|
-
should_flow :on => :incoming_call, :initial => :routing, :when => Proc.new {
|
188
|
-
@call.stubs(:agents_available?).returns(true)
|
189
|
-
}
|
190
|
-
|
191
|
-
should_flow :on => :incoming_call, :initial => :voicemail, :when => Proc.new {
|
192
|
-
@call.stubs(:agents_available?).returns(false)
|
193
|
-
} do
|
194
|
-
should_flow :on => :customer_hangs_up, :voicemail => :voicemail_completed
|
195
|
-
end
|
196
|
-
|
197
|
-
should_flow :on => :something_crazy_happens, :initial => :uh_oh
|
198
|
-
|
199
|
-
should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
|
200
|
-
should_also { assert_received(@call, :cancelled) { |e| e.never } }
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
context "call" do
|
207
|
-
setup do
|
208
|
-
@call = Call.new
|
209
|
-
end
|
210
|
-
|
211
|
-
should "render xml for initial state" do
|
212
|
-
@call.expects(:notify).with(:rendering_initial)
|
213
|
-
body @call.render
|
214
|
-
assert_select "Response>Say", "Hello World"
|
215
|
-
end
|
216
|
-
|
217
|
-
should "return customer url for event" do
|
218
|
-
assert_equal("/voice/calls/flow?event=voicemail_complete&actor=customer", @call.customer(:voicemail_complete))
|
219
|
-
end
|
220
|
-
|
221
|
-
should "return agent url for event" do
|
222
|
-
assert_equal("/voice/calls/flow?event=voicemail_complete&actor=agent", @call.agent(:voicemail_complete))
|
223
|
-
end
|
224
|
-
|
225
|
-
should "render xml for voicemail state" do
|
226
|
-
@call.stubs(:agents_available?).returns(false)
|
227
|
-
@call.incoming_call!
|
228
|
-
@call.expects(:notify).with(:rendering_voicemail)
|
229
|
-
|
230
|
-
body @call.render
|
231
|
-
assert_select "Response>Say"
|
232
|
-
assert_select "Response>Record[action=/voice/calls/flow?event=voicemail_complete&actor=customer]"
|
233
|
-
end
|
234
|
-
|
235
|
-
should "render noop when no render block" do
|
236
|
-
@call.stubs(:agents_available?).returns(true)
|
237
|
-
@call.incoming_call!
|
238
|
-
|
239
|
-
body @call.render
|
240
|
-
assert_select "Response"
|
241
|
-
end
|
242
|
-
|
243
|
-
should "execute callbacks" do
|
244
|
-
@call.state = 'cancelled'
|
245
|
-
|
246
|
-
@call.expects(:notify).with(:before_always).times(3)
|
247
|
-
@call.expects(:notify).with(:before_always_uniq).times(1)
|
248
|
-
|
249
|
-
@call.expects(:notify).with(:after_always).times(4)
|
250
|
-
@call.expects(:notify).with(:after_success).times(3)
|
251
|
-
@call.expects(:notify).with(:after_failure).times(1)
|
252
|
-
|
253
|
-
@call.expects(:notify).with(:after_always_uniq).times(1)
|
254
|
-
@call.expects(:notify).with { |notification, transition| notification == :after_success_uniq && transition.kind_of?(StateMachine::Transition) }.times(1)
|
255
|
-
@call.expects(:notify).with(:after_failure_uniq).times(0)
|
256
|
-
|
257
|
-
@call.customer_end!
|
258
|
-
@call.customer_end!
|
259
|
-
@call.customer_end!
|
260
|
-
assert(!@call.customer_hangs_up)
|
261
|
-
end
|
262
|
-
|
263
|
-
should "execute callbacks in sequence" do
|
264
|
-
seq = sequence('callback_sequence')
|
265
|
-
@call.state = 'cancelled'
|
266
|
-
|
267
|
-
@call.expects(:notify).with(:before_always).in_sequence(seq)
|
268
|
-
@call.expects(:notify).with(:before_always_uniq).in_sequence(seq)
|
269
|
-
|
270
|
-
@call.expects(:notify).with(:after_always).in_sequence(seq)
|
271
|
-
@call.expects(:notify).with(:after_success).in_sequence(seq)
|
272
|
-
|
273
|
-
@call.expects(:notify).with(:after_always_uniq).in_sequence(seq)
|
274
|
-
@call.expects(:notify).with(:after_success_uniq, anything).in_sequence(seq)
|
275
|
-
|
276
|
-
@call.customer_end!
|
277
|
-
end
|
278
|
-
|
279
|
-
should "defer callbacks" do
|
280
|
-
(class << @call; self; end).class_eval do
|
281
|
-
include CallCenter::DeferredCallbacks
|
282
|
-
end
|
283
|
-
@call.state = 'cancelled'
|
284
|
-
|
285
|
-
@call.expects(:notify).with(:before_always).never
|
286
|
-
@call.expects(:notify).with(:before_always_uniq).never
|
287
|
-
|
288
|
-
@call.expects(:notify).with(:after_always).never
|
289
|
-
@call.expects(:notify).with(:after_success).never
|
290
|
-
@call.expects(:notify).with(:after_failure).never
|
291
|
-
|
292
|
-
@call.expects(:notify).with(:after_always_uniq).never
|
293
|
-
@call.expects(:notify).with(:after_success_uniq, anything).never
|
294
|
-
|
295
|
-
@call.customer_end!
|
296
|
-
assert(!@call.customer_hangs_up)
|
297
|
-
|
298
|
-
# Ready for deferred callbacks
|
299
|
-
|
300
|
-
seq = sequence('callback_sequence')
|
301
|
-
|
302
|
-
@call.expects(:notify).with(:before_always)
|
303
|
-
@call.expects(:notify).with(:before_always_uniq)
|
304
|
-
|
305
|
-
@call.call_flow_run_deferred(:before_transition)
|
306
|
-
|
307
|
-
@call.expects(:notify).with(:after_always).times(2)
|
308
|
-
@call.expects(:notify).with(:after_success)
|
309
|
-
|
310
|
-
@call.expects(:notify).with(:after_always_uniq)
|
311
|
-
@call.expects(:notify).with(:after_success_uniq, anything)
|
312
|
-
|
313
|
-
@call.call_flow_run_deferred(:after_transition)
|
314
|
-
|
315
|
-
@call.expects(:notify).with(:after_always).times(2)
|
316
|
-
@call.expects(:notify).with(:after_failure)
|
317
|
-
@call.expects(:notify).with(:after_always_uniq)
|
318
|
-
|
319
|
-
@call.call_flow_run_deferred(:after_failure)
|
320
|
-
|
321
|
-
# Empty
|
322
|
-
@call.call_flow_run_deferred(:before_transition)
|
323
|
-
@call.call_flow_run_deferred(:after_transition)
|
324
|
-
@call.call_flow_run_deferred(:after_failure)
|
325
|
-
end
|
326
|
-
|
327
|
-
should "asynchronously perform event" do
|
328
|
-
@call.stubs(:agents_available?).returns(true)
|
329
|
-
@call.incoming_call!
|
330
|
-
@call.expects(:redirect_to).with(:start_conference)
|
331
|
-
|
332
|
-
@call.redirect_and_start_conference!
|
333
|
-
end
|
334
|
-
|
335
|
-
should "asynchronously perform event with options" do
|
336
|
-
@call.stubs(:agents_available?).returns(true)
|
337
|
-
@call.incoming_call!
|
338
|
-
@call.expects(:redirect_to).with(:start_conference, :status => 'completed')
|
339
|
-
|
340
|
-
@call.redirect_and_start_conference!(:status => 'completed')
|
341
|
-
end
|
342
|
-
|
343
|
-
should "raise error on missing method" do
|
344
|
-
assert_raises {
|
345
|
-
@call.i_am_missing!
|
346
|
-
}
|
347
|
-
end
|
348
|
-
|
349
|
-
should "draw state machine digraph" do
|
350
|
-
Call.state_machines[:state].expects(:draw).with(:name => 'call_workflow', :font => 'Helvetica Neue')
|
351
|
-
@call.draw_call_flow(:name => 'call_workflow', :font => 'Helvetica Neue')
|
352
|
-
end
|
353
|
-
|
354
|
-
context "using test DSL:" do
|
355
|
-
should_flow :on => :incoming_call, :initial => :voicemail, :when => Proc.new {
|
356
|
-
@call.stubs(:agents_available?).returns(false)
|
357
|
-
@call.stubs(:notify)
|
358
|
-
@call.stubs(:customer).returns('the_flow')
|
359
|
-
} do
|
360
|
-
should_also { assert_received(@call, :notify) { |e| e.with(:rendering_voicemail) } }
|
361
|
-
and_also { assert_received(@call, :customer) { |e| e.with(:voicemail_complete) } }
|
362
|
-
and_render { "Response>Say" }
|
363
|
-
and_render { "Response>Record[action=the_flow]" }
|
364
|
-
end
|
365
|
-
|
366
|
-
should_flow :on => :incoming_call, :initial => :routing, :when => Proc.new {
|
367
|
-
@call.stubs(:agents_available?).returns(true)
|
368
|
-
} do
|
369
|
-
should_render { "Response" }
|
370
|
-
end
|
371
|
-
|
372
|
-
should_flow :on => :customer_hangs_up, :routing => :cancelled, :when => Proc.new {
|
373
|
-
@call.stubs(:notify)
|
374
|
-
} do
|
375
|
-
should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } }
|
376
|
-
and_also { assert @call.cancelled? }
|
377
|
-
|
378
|
-
should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
|
379
|
-
should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
|
380
|
-
and_also { assert @call.cancelled? }
|
381
|
-
|
382
|
-
should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
|
383
|
-
should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
|
384
|
-
and_also { assert @call.cancelled? }
|
385
|
-
end
|
386
|
-
end
|
387
|
-
end
|
388
|
-
end
|
389
|
-
|
390
|
-
context "deferred and using test DSL:" do
|
391
|
-
setup do
|
392
|
-
(class << @call; self; end).class_eval do
|
393
|
-
include CallCenter::DeferredCallbacks
|
394
|
-
end
|
395
|
-
end
|
396
|
-
|
397
|
-
should_flow :on => :incoming_call, :initial => :voicemail, :when => Proc.new {
|
398
|
-
@call.stubs(:agents_available?).returns(false)
|
399
|
-
@call.stubs(:notify)
|
400
|
-
@call.stubs(:customer).returns('the_flow')
|
401
|
-
} do
|
402
|
-
should_also { assert_received(@call, :notify) { |e| e.with(:rendering_voicemail) } }
|
403
|
-
and_also { assert_received(@call, :customer) { |e| e.with(:voicemail_complete) } }
|
404
|
-
and_render { "Response>Say" }
|
405
|
-
and_render { "Response>Record[action=the_flow]" }
|
406
|
-
end
|
407
|
-
|
408
|
-
should_flow :on => :incoming_call, :initial => :routing, :when => Proc.new {
|
409
|
-
@call.stubs(:agents_available?).returns(true)
|
410
|
-
} do
|
411
|
-
should_render { "Response" }
|
412
|
-
end
|
413
|
-
|
414
|
-
should_flow :on => :customer_hangs_up, :routing => :cancelled, :when => Proc.new {
|
415
|
-
@call.stubs(:notify)
|
416
|
-
} do
|
417
|
-
should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } }
|
418
|
-
and_also { assert @call.cancelled? }
|
419
|
-
|
420
|
-
should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
|
421
|
-
should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
|
422
|
-
and_also { assert @call.cancelled? }
|
423
|
-
|
424
|
-
should_flow :on => :customer_hangs_up, :cancelled => :cancelled do
|
425
|
-
should_also { assert_received(@call, :notify) { |e| e.with(:cancelled).once } } # For above
|
426
|
-
and_also { assert @call.cancelled? }
|
427
|
-
end
|
428
|
-
end
|
429
|
-
end
|
430
|
-
end
|
431
|
-
end
|
432
|
-
|
433
|
-
context "non-standard call" do
|
434
|
-
setup do
|
435
|
-
@call = NonStandardCall.new
|
436
|
-
end
|
437
|
-
|
438
|
-
should "render xml for initial state" do
|
439
|
-
assert_equal 'ready', @call.status
|
440
|
-
body @call.render
|
441
|
-
assert_select "Response>Say", "Hello World"
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
|
-
context "cache call" do
|
446
|
-
should "re-apply state machine and render xml for initial state" do
|
447
|
-
Object.send(:remove_const, :NonStandardCall)
|
448
|
-
Object.const_set(:NonStandardCall, Class.new)
|
449
|
-
NonStandardCall.class_eval do
|
450
|
-
include CallCenter
|
451
|
-
call_flow :status, :initial => :ready do
|
452
|
-
raise Exception, "Should not be called"
|
453
|
-
end
|
454
|
-
end
|
455
|
-
|
456
|
-
@call = NonStandardCall.new
|
457
|
-
|
458
|
-
assert_equal 'ready', @call.status
|
459
|
-
body @call.render
|
460
|
-
assert_select "Response>Say", "Hello World"
|
461
|
-
assert @call.go!
|
462
|
-
end
|
463
|
-
end
|
464
|
-
|
465
|
-
context "cache multiple call flows" do
|
466
|
-
should "re-apply state machine and render xml for initial state" do
|
467
|
-
Object.send(:remove_const, :MultipleFlowCall)
|
468
|
-
Object.const_set(:MultipleFlowCall, Class.new)
|
469
|
-
MultipleFlowCall.class_eval do
|
470
|
-
include CallCenter
|
471
|
-
call_flow :status, :initial => :ready do
|
472
|
-
raise Exception, "Should not be called"
|
473
|
-
end
|
474
|
-
call_flow :outgoing_status, :initial => :outgoing_ready do
|
475
|
-
raise Exception, "Should not be called"
|
476
|
-
end
|
477
|
-
end
|
478
|
-
|
479
|
-
@call = MultipleFlowCall.new
|
480
|
-
|
481
|
-
assert_equal 'ready', @call.status
|
482
|
-
body @call.render
|
483
|
-
assert_select "Response>Say", "Hello World"
|
484
|
-
assert @call.go!
|
485
|
-
|
486
|
-
assert_equal 'outgoing_ready', @call.outgoing_status
|
487
|
-
body @call.render(:outgoing_status)
|
488
|
-
assert_select "Response>Say", "Hello Outgoing World"
|
489
|
-
assert @call.outgoing_go!
|
490
|
-
end
|
491
|
-
end
|
492
|
-
end
|