adhearsion-asterisk 0.1.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.
Files changed (33) hide show
  1. data/.gitignore +10 -0
  2. data/.rspec +3 -0
  3. data/CHANGELOG.md +14 -0
  4. data/Gemfile +6 -0
  5. data/Guardfile +5 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +143 -0
  8. data/Rakefile +23 -0
  9. data/adhearsion-asterisk.gemspec +35 -0
  10. data/lib/adhearsion-asterisk.rb +1 -0
  11. data/lib/adhearsion/asterisk.rb +12 -0
  12. data/lib/adhearsion/asterisk/config_generator.rb +103 -0
  13. data/lib/adhearsion/asterisk/config_generator/agents.rb +138 -0
  14. data/lib/adhearsion/asterisk/config_generator/queues.rb +247 -0
  15. data/lib/adhearsion/asterisk/config_generator/voicemail.rb +238 -0
  16. data/lib/adhearsion/asterisk/config_manager.rb +60 -0
  17. data/lib/adhearsion/asterisk/plugin.rb +464 -0
  18. data/lib/adhearsion/asterisk/queue_proxy.rb +177 -0
  19. data/lib/adhearsion/asterisk/queue_proxy/agent_proxy.rb +81 -0
  20. data/lib/adhearsion/asterisk/queue_proxy/queue_agents_list_proxy.rb +132 -0
  21. data/lib/adhearsion/asterisk/version.rb +5 -0
  22. data/spec/adhearsion/asterisk/config_generators/agents_spec.rb +258 -0
  23. data/spec/adhearsion/asterisk/config_generators/queues_spec.rb +322 -0
  24. data/spec/adhearsion/asterisk/config_generators/voicemail_spec.rb +306 -0
  25. data/spec/adhearsion/asterisk/config_manager_spec.rb +125 -0
  26. data/spec/adhearsion/asterisk/plugin_spec.rb +618 -0
  27. data/spec/adhearsion/asterisk/queue_proxy/agent_proxy_spec.rb +90 -0
  28. data/spec/adhearsion/asterisk/queue_proxy/queue_agents_list_proxy_spec.rb +145 -0
  29. data/spec/adhearsion/asterisk/queue_proxy_spec.rb +156 -0
  30. data/spec/adhearsion/asterisk_spec.rb +9 -0
  31. data/spec/spec_helper.rb +23 -0
  32. data/spec/support/the_following_code.rb +3 -0
  33. metadata +229 -0
@@ -0,0 +1,177 @@
1
+ module Adhearsion
2
+ module Asterisk
3
+ class QueueProxy
4
+
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :AgentProxy
8
+ autoload :QueueAgentsListProxy
9
+
10
+ class << self
11
+ def format_join_hash_key_arguments(options)
12
+ bad_argument = lambda do |(key, value)|
13
+ raise ArgumentError, "Unrecognize value for #{key.inspect} -- #{value.inspect}"
14
+ end
15
+
16
+ # Direct Queue() arguments:
17
+ timeout = options.delete :timeout
18
+ announcement = options.delete :announce
19
+
20
+ # Terse single-character options
21
+ ring_style = options.delete :play
22
+ allow_hangup = options.delete :allow_hangup
23
+ allow_transfer = options.delete :allow_transfer
24
+ agi = options.delete :agi
25
+
26
+ raise ArgumentError, "Unrecognized args to join!: #{options.inspect}" if options.any?
27
+
28
+ ring_style = case ring_style
29
+ when :ringing then 'r'
30
+ when :music then ''
31
+ when nil
32
+ else bad_argument[:play => ring_style]
33
+ end.to_s
34
+
35
+ allow_hangup = case allow_hangup
36
+ when :caller then 'H'
37
+ when :agent then 'h'
38
+ when :everyone then 'Hh'
39
+ when nil
40
+ else bad_argument[:allow_hangup => allow_hangup]
41
+ end.to_s
42
+
43
+ allow_transfer = case allow_transfer
44
+ when :caller then 'T'
45
+ when :agent then 't'
46
+ when :everyone then 'Tt'
47
+ when nil
48
+ else bad_argument[:allow_transfer => allow_transfer]
49
+ end.to_s
50
+
51
+ terse_character_options = ring_style + allow_transfer + allow_hangup
52
+
53
+ [terse_character_options, '', announcement, timeout, agi].map(&:to_s)
54
+ end
55
+ end
56
+
57
+ attr_reader :name, :environment
58
+
59
+ def initialize(name, environment)
60
+ @name, @environment = name, environment
61
+ end
62
+
63
+ # Makes the current channel join the queue.
64
+ #
65
+ # @param [Hash] options
66
+ #
67
+ # :timeout - The number of seconds to wait for an agent to answer
68
+ # :play - Can be :ringing or :music.
69
+ # :announce - A sound file to play instead of the normal queue announcement.
70
+ # :allow_transfer - Can be :caller, :agent, or :everyone. Allow someone to transfer the call.
71
+ # :allow_hangup - Can be :caller, :agent, or :everyone. Allow someone to hangup with the * key.
72
+ # :agi - An AGI script to be called on the calling parties channel just before being connected.
73
+ #
74
+ # @example
75
+ # queue('sales').join!
76
+ # @example
77
+ # queue('sales').join! :timeout => 1.minute
78
+ # @example
79
+ # queue('sales').join! :play => :music
80
+ # @example
81
+ # queue('sales').join! :play => :ringing
82
+ # @example
83
+ # queue('sales').join! :announce => "custom/special-queue-announcement"
84
+ # @example
85
+ # queue('sales').join! :allow_transfer => :caller
86
+ # @example
87
+ # queue('sales').join! :allow_transfer => :agent
88
+ # @example
89
+ # queue('sales').join! :allow_hangup => :caller
90
+ # @example
91
+ # queue('sales').join! :allow_hangup => :agent
92
+ # @example
93
+ # queue('sales').join! :allow_hangup => :everyone
94
+ # @example
95
+ # queue('sales').join! :agi => 'agi://localhost/sales_queue_callback'
96
+ # @example
97
+ # queue('sales').join! :allow_transfer => :agent, :timeout => 30.seconds,
98
+ def join!(options = {})
99
+ environment.execute("queue", name, *self.class.format_join_hash_key_arguments(options))
100
+ normalize_queue_status_variable environment.get_variable("QUEUESTATUS")
101
+ end
102
+
103
+ # Get the agents associated with a queue
104
+ #
105
+ # @param [Hash] options
106
+ # @return [QueueAgentsListProxy]
107
+ def agents(options = {})
108
+ cached = options.has_key?(:cache) ? options.delete(:cache) : true
109
+ raise ArgumentError, "Unrecognized arguments to #agents: #{options.inspect}" if options.keys.any?
110
+ if cached
111
+ @cached_proxy ||= QueueAgentsListProxy.new(self, true)
112
+ else
113
+ @uncached_proxy ||= QueueAgentsListProxy.new(self, false)
114
+ end
115
+ end
116
+
117
+ # Check how many channels are waiting in the queue
118
+ # @return [Integer]
119
+ # @raise QueueDoesNotExistError
120
+ def waiting_count
121
+ raise QueueDoesNotExistError.new(name) unless exists?
122
+ environment.get_variable("QUEUE_WAITING_COUNT(#{name})").to_i
123
+ end
124
+
125
+ # Check whether the waiting count is zero
126
+ # @return [Boolean]
127
+ def empty?
128
+ waiting_count == 0
129
+ end
130
+
131
+ # Check whether any calls are waiting in the queue
132
+ # @return [Boolean]
133
+ def any?
134
+ waiting_count > 0
135
+ end
136
+
137
+ # Check whether a queue exists/is defined in Asterisk
138
+ # @return [Boolean]
139
+ def exists?
140
+ environment.execute('RemoveQueueMember', name, 'SIP/AdhearsionQueueExistenceCheck')
141
+ environment.get_variable("RQMSTATUS") != 'NOSUCHQUEUE'
142
+ end
143
+
144
+ private
145
+
146
+ # Ensure the queue exists by interpreting the QUEUESTATUS variable
147
+ #
148
+ # According to http://www.voip-info.org/wiki/view/Asterisk+cmd+Queue
149
+ # possible values are:
150
+ #
151
+ # TIMEOUT => :timeout
152
+ # FULL => :full
153
+ # JOINEMPTY => :joinempty
154
+ # LEAVEEMPTY => :leaveempty
155
+ # JOINUNAVAIL => :joinunavail
156
+ # LEAVEUNAVAIL => :leaveunavail
157
+ # CONTINUE => :continue
158
+ #
159
+ # If the QUEUESTATUS variable is not set the call was successfully connected,
160
+ # and Adhearsion will return :completed.
161
+ #
162
+ # @param [String] QUEUESTATUS variable from Asterisk
163
+ # @return [Symbol] Symbolized version of QUEUESTATUS
164
+ # @raise QueueDoesNotExistError
165
+ def normalize_queue_status_variable(variable)
166
+ variable = "COMPLETED" if variable.nil?
167
+ variable.downcase.to_sym
168
+ end
169
+
170
+ class QueueDoesNotExistError < StandardError
171
+ def initialize(queue_name)
172
+ super "Queue #{queue_name} does not exist!"
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,81 @@
1
+ module Adhearsion
2
+ module Asterisk
3
+ class QueueProxy
4
+ class AgentProxy
5
+
6
+ SUPPORTED_METADATA_NAMES = %w[status password name mohclass exten channel] unless defined? SUPPORTED_METADATA_NAMES
7
+
8
+ class << self
9
+ def id_from_agent_channel(id)
10
+ id = id.to_s
11
+ id.starts_with?('Agent/') ? id[%r[^Agent/(.+)$],1] : id
12
+ end
13
+ end
14
+
15
+ attr_reader :interface, :proxy, :queue_name, :id
16
+ def initialize(interface, proxy)
17
+ @interface, @proxy = interface, proxy
18
+ @id = self.class.id_from_agent_channel interface
19
+ @queue_name = proxy.name
20
+ end
21
+
22
+ def remove!
23
+ proxy.environment.execute 'RemoveQueueMember', queue_name, interface
24
+ case proxy.environment.get_variable("RQMSTATUS")
25
+ when "REMOVED" then true
26
+ when "NOTINQUEUE" then false
27
+ when "NOSUCHQUEUE"
28
+ raise QueueDoesNotExistError.new(queue_name)
29
+ else
30
+ raise "Unrecognized RQMSTATUS variable!"
31
+ end
32
+ end
33
+
34
+ # Pauses the given agent for this queue only. If you wish to pause this agent
35
+ # for all queues, pass in :everywhere => true. Returns true if the agent was
36
+ # successfully paused and false if the agent was not found.
37
+ def pause!(options = {})
38
+ args = [(options.delete(:everywhere) ? nil : queue_name), interface]
39
+ proxy.environment.execute 'PauseQueueMember', *args
40
+ case proxy.environment.get_variable("PQMSTATUS")
41
+ when "PAUSED" then true
42
+ when "NOTFOUND" then false
43
+ else
44
+ raise "Unrecognized PQMSTATUS value!"
45
+ end
46
+ end
47
+
48
+ # Pauses the given agent for this queue only. If you wish to pause this agent
49
+ # for all queues, pass in :everywhere => true. Returns true if the agent was
50
+ # successfully paused and false if the agent was not found.
51
+ def unpause!(options = {})
52
+ args = [(options.delete(:everywhere) ? nil : queue_name), interface]
53
+ proxy.environment.execute 'UnpauseQueueMember', *args
54
+ case proxy.environment.get_variable("UPQMSTATUS")
55
+ when "UNPAUSED" then true
56
+ when "NOTFOUND" then false
57
+ else
58
+ raise "Unrecognized UPQMSTATUS value!"
59
+ end
60
+ end
61
+
62
+ # Returns true/false depending on whether this agent is logged in.
63
+ def logged_in?
64
+ status == 'LOGGEDIN'
65
+ end
66
+
67
+ private
68
+
69
+ def status
70
+ agent_metadata 'status'
71
+ end
72
+
73
+ def agent_metadata(data_name)
74
+ data_name = data_name.to_s.downcase
75
+ raise ArgumentError, "unrecognized agent metadata name #{data_name}" unless SUPPORTED_METADATA_NAMES.include? data_name
76
+ proxy.environment.variable "AGENT(#{id}:#{data_name})"
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,132 @@
1
+ module Adhearsion
2
+ module Asterisk
3
+ class QueueProxy
4
+ class QueueAgentsListProxy
5
+ include Enumerable
6
+
7
+ attr_reader :proxy, :agents
8
+
9
+ def initialize(proxy, cached = false)
10
+ @proxy = proxy
11
+ @cached = cached
12
+ end
13
+
14
+ def count
15
+ if cached? && @cached_count
16
+ @cached_count
17
+ else
18
+ @cached_count = proxy.environment.get_variable("QUEUE_MEMBER_COUNT(#{proxy.name})").to_i
19
+ end
20
+ end
21
+ alias size count
22
+ alias length count
23
+
24
+ # @param [Hash] args
25
+ # :name value will be viewable in the queue_log
26
+ # :penalty is the penalty assigned to this agent for answering calls on this queue
27
+ def new(*args)
28
+ options = args.last.kind_of?(Hash) ? args.pop : {}
29
+ interface = args.shift
30
+
31
+ raise ArgumentError, "You must specify an interface to add." if interface.nil?
32
+ raise ArgumentError, "You may only supply an interface and a Hash argument!" if args.any?
33
+
34
+ penalty = options.delete(:penalty) || ''
35
+ name = options.delete(:name) || ''
36
+ state_interface = options.delete(:state_interface) || ''
37
+
38
+ raise ArgumentError, "Unrecognized argument(s): #{options.inspect}" if options.any?
39
+
40
+ proxy.environment.execute "AddQueueMember", proxy.name, interface, penalty, '', name, state_interface
41
+
42
+ added = case proxy.environment.get_variable("AQMSTATUS")
43
+ when "ADDED" then true
44
+ when "MEMBERALREADY" then false
45
+ when "NOSUCHQUEUE" then raise QueueDoesNotExistError.new(proxy.name)
46
+ else
47
+ raise "UNRECOGNIZED AQMSTATUS VALUE!"
48
+ end
49
+
50
+ if added
51
+ check_agent_cache!
52
+ AgentProxy.new(interface, proxy).tap do |agent_proxy|
53
+ @agents << agent_proxy
54
+ end
55
+ else
56
+ false
57
+ end
58
+ end
59
+
60
+ # Logs a pre-defined agent into this queue and waits for calls. Pass in :silent => true to stop
61
+ # the message which says "Agent logged in".
62
+ def login!(*args)
63
+ options = args.last.kind_of?(Hash) ? args.pop : {}
64
+
65
+ silent = options.delete(:silent).equal?(false) ? '' : 's'
66
+ id = args.shift
67
+ id &&= AgentProxy.id_from_agent_channel(id)
68
+ raise ArgumentError, "Unrecognized Hash options to #login: #{options.inspect}" if options.any?
69
+ raise ArgumentError, "Unrecognized argument to #login: #{args.inspect}" if args.any?
70
+
71
+ proxy.environment.execute 'AgentLogin', id, silent
72
+ end
73
+
74
+ # Removes the current channel from this queue
75
+ def logout!
76
+ # TODO: DRY this up. Repeated in the AgentProxy...
77
+ proxy.environment.execute 'RemoveQueueMember', proxy.name
78
+ case proxy.environment.get_variable("RQMSTATUS")
79
+ when "REMOVED" then true
80
+ when "NOTINQUEUE" then false
81
+ when "NOSUCHQUEUE"
82
+ raise QueueDoesNotExistError.new(proxy.name)
83
+ else
84
+ raise "Unrecognized RQMSTATUS variable!"
85
+ end
86
+ end
87
+
88
+ def each(&block)
89
+ check_agent_cache!
90
+ agents.each &block
91
+ end
92
+
93
+ def first
94
+ check_agent_cache!
95
+ agents.first
96
+ end
97
+
98
+ def last
99
+ check_agent_cache!
100
+ agents.last
101
+ end
102
+
103
+ def cached?
104
+ @cached
105
+ end
106
+
107
+ def to_a
108
+ check_agent_cache!
109
+ @agents
110
+ end
111
+
112
+ private
113
+
114
+ def check_agent_cache!
115
+ if cached?
116
+ load_agents! unless agents
117
+ else
118
+ load_agents!
119
+ end
120
+ end
121
+
122
+ def load_agents!
123
+ raw_data = proxy.environment.get_variable "QUEUE_MEMBER_LIST(#{proxy.name})"
124
+ @agents = raw_data.split(',').map(&:strip).reject(&:empty?).map do |agent|
125
+ AgentProxy.new agent, proxy
126
+ end
127
+ @cached_count = @agents.size
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,5 @@
1
+ module Adhearsion
2
+ module Asterisk
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,258 @@
1
+ require 'spec_helper'
2
+ require 'adhearsion/asterisk/config_generator/agents'
3
+
4
+ module AgentsConfigGeneratorTestHelper
5
+
6
+ def reset_agents!
7
+ @agents = Adhearsion::Asterisk::ConfigGenerator::Agents.new
8
+ end
9
+
10
+ def generated_config_has_pair(pair)
11
+ agents.conf.split("\n").grep(/=[^>]/).each do |line|
12
+ key, value = line.strip.split('=')
13
+ return true if pair == {key.to_sym => value}
14
+ end
15
+ false
16
+ end
17
+
18
+ end
19
+
20
+ describe "The agents.conf config file agents" do
21
+
22
+ include AgentsConfigGeneratorTestHelper
23
+
24
+ attr_reader :agents
25
+ before(:each) do
26
+ reset_agents!
27
+ end
28
+ it "The agent() method should enqueue a Hash into Agents#agent_definitions" do
29
+ agents.agent 1337, :password => 9876, :name => "Jay Phillips"
30
+ agents.agent_definitions.size.should be 1
31
+ agents.agent_definitions.first.should == {:id => 1337, :password => 9876, :name => "Jay Phillips"}
32
+ end
33
+
34
+ it 'should add the warning message to the to_s output' do
35
+ agents.conf.should =~ /^\s*;.{10}/
36
+ end
37
+
38
+ it "The conf() method should always create a general section" do
39
+ agents.conf.should =~ /^\[general\]/
40
+ end
41
+
42
+ it "The agent() method should generate a proper String" do
43
+ agents.agent 123, :name => "Otto Normalverbraucher", :password => "007"
44
+ agents.agent 889, :name => "John Doe", :password => "998"
45
+
46
+ agents.conf.split("\n").grep(/^agent =>/).map(&:strip).should == [
47
+ "agent => 123,007,Otto Normalverbraucher",
48
+ "agent => 889,998,John Doe"
49
+ ]
50
+ end
51
+
52
+ it "The persistent_agents() method should generate a persistentagents yes/no pair" do
53
+ agents.persistent_agents true
54
+ generated_config_has_pair(:persistentagents => "yes").should be true
55
+
56
+ reset_agents!
57
+
58
+ agents.persistent_agents false
59
+ generated_config_has_pair(:persistentagents => "no").should be true
60
+ end
61
+
62
+ it "The persistent_agents() method should be in the [general] section" do
63
+ agents.persistent_agents true
64
+ agents.general_section.should == {:persistentagents => "yes"}
65
+
66
+ end
67
+
68
+ it "max_login_tries() should generate a 'maxlogintries' numerical pair" do
69
+ agents.max_login_tries 50
70
+ generated_config_has_pair(:maxlogintries => "50").should be true
71
+ end
72
+
73
+ it "max_login_tries() should be in the agents section" do
74
+ agents.max_login_tries 0
75
+ agents.agent_section.should == {:maxlogintries => 0}
76
+ end
77
+
78
+ it "log_off_after_duration should generate autologoff" do
79
+ agents.log_off_after_duration 15.seconds
80
+ generated_config_has_pair(:autologoff => "15").should be true
81
+ end
82
+
83
+ it "log_off_if_unavailable should add autologoffunavail to the agents section" do
84
+ agents.log_off_if_unavailable false
85
+ agents.agent_section.should == {:autologoffunavail => "no"}
86
+ end
87
+
88
+ it "require_hash_to_acknowledge() should generate a 'ackcall' yes/no pair" do
89
+ agents.require_hash_to_acknowledge false
90
+ agents.agent_section.should == {:ackcall => "no"}
91
+ end
92
+
93
+ it "allow_star_to_hangup should generate a 'endcall' yes/no pair" do
94
+ agents.allow_star_to_hangup false
95
+ agents.agent_section.should == {:endcall => "no"}
96
+ end
97
+
98
+ it "time_between_calls should convert its argument to milliseconds" do
99
+ agents.time_between_calls 1.hour
100
+ agents.agent_section.should == {:wrapuptime => 1.hour * 1_000}
101
+ end
102
+
103
+ it "hold_music_class should convert its argument to a String" do
104
+ agents.hold_music_class :podcast
105
+ agents.agent_section_special.should == {:musiconhold => "podcast"}
106
+ end
107
+
108
+ it "play_on_agent_goodbye should generate 'agentgoodbye'" do
109
+ agents.play_on_agent_goodbye "tt-monkeys"
110
+ agents.agent_section_special.should == {:agentgoodbye => "tt-monkeys"}
111
+ end
112
+
113
+ it "change_cdr_source should generate updatecdr" do
114
+ agents.change_cdr_source false
115
+ agents.agent_section.should == {:updatecdr => "no"}
116
+ end
117
+
118
+ it "play_for_waiting_keep_alive" do
119
+ agents.play_for_waiting_keep_alive "tt-weasels"
120
+ agents.agent_section.should == {:custom_beep => "tt-weasels"}
121
+ end
122
+
123
+ it "save_recordings_in should generate 'savecallsin'" do
124
+ agents.save_recordings_in "/second/star/on/the/right"
125
+ agents.agent_section.should == {:savecallsin => "/second/star/on/the/right"}
126
+ end
127
+
128
+ it "recording_prefix should generate 'urlprefix'" do
129
+ agents.recording_prefix "ohai"
130
+ agents.agent_section.should == {:urlprefix => "ohai"}
131
+ end
132
+
133
+ it "recording_format should only allow a few symbols as an argument" do
134
+ the_following_code {
135
+ agents.recording_format :wav
136
+ agents.agent_section.should == {:recordformat => :wav}
137
+ }.should_not raise_error
138
+
139
+ reset_agents!
140
+
141
+ the_following_code {
142
+ agents.recording_format :wav49
143
+ agents.agent_section.should == {:recordformat => :wav49}
144
+ }.should_not raise_error
145
+
146
+ reset_agents!
147
+
148
+ the_following_code {
149
+ agents.recording_format :gsm
150
+ agents.agent_section.should == {:recordformat => :gsm}
151
+ }.should_not raise_error
152
+
153
+ reset_agents!
154
+
155
+ the_following_code {
156
+ agents.recording_format :mp3
157
+ agents.agent_section.should == {:recordformat => :mp3}
158
+ }.should raise_error ArgumentError
159
+
160
+ end
161
+
162
+ it "record_agent_calls should generate a 'recordagentcalls' yes/no pair" do
163
+ agents.record_agent_calls false
164
+ agents.agent_section.should == {:recordagentcalls => 'no'}
165
+ end
166
+
167
+ it "allow_multiple_logins_per_extension should generate 'multiplelogin' in [general]" do
168
+ agents.allow_multiple_logins_per_extension true
169
+ agents.general_section.should == {:multiplelogin => 'yes'}
170
+ end
171
+
172
+ end
173
+
174
+ describe "The default agents.conf config file converted to this syntax" do
175
+
176
+ include AgentsConfigGeneratorTestHelper
177
+
178
+ attr_reader :default_config, :agents
179
+ before(:each) do
180
+ reset_agents!
181
+ @default_config = <<-CONFIG
182
+ [general]
183
+ persistentagents=yes
184
+
185
+ [agents]
186
+ maxlogintries=5
187
+ autologoff=15
188
+ ackcall=no
189
+ endcall=yes
190
+ wrapuptime=5000
191
+ musiconhold => default
192
+ agentgoodbye => goodbye_file
193
+ updatecdr=no
194
+ group=1,2
195
+ recordagentcalls=yes
196
+ recordformat=gsm
197
+ urlprefix=http://localhost/calls/
198
+ savecallsin=/var/calls
199
+ custom_beep=beep
200
+
201
+ agent => 1001,4321,Mark Spencer
202
+ agent => 1002,4321,Will Meadows
203
+ CONFIG
204
+ end
205
+
206
+ it "they're basically the same" do
207
+ agents.persistent_agents true
208
+ agents.max_login_tries 5
209
+ agents.log_off_after_duration 15
210
+ agents.require_hash_to_acknowledge false
211
+ agents.allow_star_to_hangup true
212
+ agents.time_between_calls 5
213
+ agents.hold_music_class :default
214
+ agents.play_on_agent_goodbye "goodbye_file"
215
+ agents.change_cdr_source false
216
+ agents.groups 1,2
217
+ agents.record_agent_calls true
218
+ agents.recording_format :gsm
219
+ agents.recording_prefix "http://localhost/calls/"
220
+ agents.save_recordings_in "/var/calls"
221
+ agents.play_for_waiting_keep_alive "beep"
222
+
223
+ agents.agent 1001, :password => 4321, :name => "Mark Spencer"
224
+ agents.agent 1002, :password => 4321, :name => "Will Meadows"
225
+
226
+ cleaned_up_default_config =
227
+ Adhearsion::Asterisk::ConfigGenerator.create_sanitary_hash_from(default_config)
228
+
229
+ cleaned_up_generated_config = agents.to_sanitary_hash
230
+
231
+ cleaned_up_generated_config.should == cleaned_up_default_config
232
+ end
233
+
234
+ end
235
+
236
+
237
+ describe "AgentsConfigGeneratorTestHelper" do
238
+
239
+ include AgentsConfigGeneratorTestHelper
240
+
241
+ attr_reader :agents
242
+ before(:each) do
243
+ reset_agents!
244
+ end
245
+
246
+ it "generated_config_has_pair() works properly with one pair" do
247
+ @agents = mock "A fake agents with just one pair", :conf => "foo=bar"
248
+ generated_config_has_pair(:foo => "bar").should be true
249
+ end
250
+
251
+ it "generated_config_has_pair() works properly with two pairs" do
252
+ @agents = mock "A fake agents with just one pair"
253
+ @agents.expects(:conf).twice.returns("[general]\n\nqaz=qwerty\nagent => 1,2,3")
254
+
255
+ generated_config_has_pair(:qaz => "qwerty").should be true
256
+ generated_config_has_pair(:foo => "bar").should be false
257
+ end
258
+ end