sevenscale-adhearsion 0.7.1000

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 (150) hide show
  1. data/CHANGELOG +3 -0
  2. data/LICENSE +456 -0
  3. data/Manifest.txt +149 -0
  4. data/README.txt +6 -0
  5. data/Rakefile +48 -0
  6. data/ahn_generators/component/USAGE +5 -0
  7. data/ahn_generators/component/component_generator.rb +57 -0
  8. data/ahn_generators/component/templates/configuration.rb +0 -0
  9. data/ahn_generators/component/templates/lib/lib.rb.erb +3 -0
  10. data/ahn_generators/component/templates/test/test.rb.erb +12 -0
  11. data/ahn_generators/component/templates/test/test_helper.rb +14 -0
  12. data/app_generators/ahn/USAGE +5 -0
  13. data/app_generators/ahn/ahn_generator.rb +76 -0
  14. data/app_generators/ahn/templates/.ahnrc +12 -0
  15. data/app_generators/ahn/templates/README +8 -0
  16. data/app_generators/ahn/templates/Rakefile +3 -0
  17. data/app_generators/ahn/templates/components/simon_game/configuration.rb +0 -0
  18. data/app_generators/ahn/templates/components/simon_game/lib/simon_game.rb +61 -0
  19. data/app_generators/ahn/templates/components/simon_game/test/test_helper.rb +14 -0
  20. data/app_generators/ahn/templates/components/simon_game/test/test_simon_game.rb +31 -0
  21. data/app_generators/ahn/templates/config/startup.rb +53 -0
  22. data/app_generators/ahn/templates/dialplan.rb +4 -0
  23. data/bin/ahn +28 -0
  24. data/bin/ahnctl +68 -0
  25. data/bin/jahn +32 -0
  26. data/lib/adhearsion/blank_slate.rb +5 -0
  27. data/lib/adhearsion/cli.rb +106 -0
  28. data/lib/adhearsion/component_manager.rb +277 -0
  29. data/lib/adhearsion/core_extensions/all.rb +9 -0
  30. data/lib/adhearsion/core_extensions/array.rb +0 -0
  31. data/lib/adhearsion/core_extensions/custom_daemonizer.rb +45 -0
  32. data/lib/adhearsion/core_extensions/global.rb +1 -0
  33. data/lib/adhearsion/core_extensions/guid.rb +5 -0
  34. data/lib/adhearsion/core_extensions/hash.rb +0 -0
  35. data/lib/adhearsion/core_extensions/metaprogramming.rb +17 -0
  36. data/lib/adhearsion/core_extensions/numeric.rb +4 -0
  37. data/lib/adhearsion/core_extensions/proc.rb +0 -0
  38. data/lib/adhearsion/core_extensions/pseudo_uuid.rb +11 -0
  39. data/lib/adhearsion/core_extensions/publishable.rb +73 -0
  40. data/lib/adhearsion/core_extensions/relationship_properties.rb +40 -0
  41. data/lib/adhearsion/core_extensions/string.rb +26 -0
  42. data/lib/adhearsion/core_extensions/thread.rb +13 -0
  43. data/lib/adhearsion/core_extensions/thread_safety.rb +7 -0
  44. data/lib/adhearsion/core_extensions/time.rb +0 -0
  45. data/lib/adhearsion/distributed/gateways/dbus_gateway.rb +0 -0
  46. data/lib/adhearsion/distributed/gateways/osa_gateway.rb +0 -0
  47. data/lib/adhearsion/distributed/gateways/rest_gateway.rb +9 -0
  48. data/lib/adhearsion/distributed/gateways/soap_gateway.rb +9 -0
  49. data/lib/adhearsion/distributed/gateways/xmlrpc_gateway.rb +9 -0
  50. data/lib/adhearsion/distributed/peer_finder.rb +0 -0
  51. data/lib/adhearsion/distributed/remote_cli.rb +0 -0
  52. data/lib/adhearsion/hooks.rb +57 -0
  53. data/lib/adhearsion/host_definitions.rb +63 -0
  54. data/lib/adhearsion/initializer/asterisk.rb +59 -0
  55. data/lib/adhearsion/initializer/configuration.rb +202 -0
  56. data/lib/adhearsion/initializer/database.rb +92 -0
  57. data/lib/adhearsion/initializer/drb.rb +25 -0
  58. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  59. data/lib/adhearsion/initializer/paths.rb +55 -0
  60. data/lib/adhearsion/initializer/rails.rb +40 -0
  61. data/lib/adhearsion/initializer.rb +217 -0
  62. data/lib/adhearsion/logging.rb +92 -0
  63. data/lib/adhearsion/services/scheduler.rb +5 -0
  64. data/lib/adhearsion/tasks/database.rb +5 -0
  65. data/lib/adhearsion/tasks/generating.rb +20 -0
  66. data/lib/adhearsion/tasks/lint.rb +4 -0
  67. data/lib/adhearsion/tasks/testing.rb +37 -0
  68. data/lib/adhearsion/tasks.rb +15 -0
  69. data/lib/adhearsion/version.rb +9 -0
  70. data/lib/adhearsion/voip/asterisk/agi_server.rb +78 -0
  71. data/lib/adhearsion/voip/asterisk/ami/actions.rb +238 -0
  72. data/lib/adhearsion/voip/asterisk/ami/machine.rb +871 -0
  73. data/lib/adhearsion/voip/asterisk/ami/machine.rl +109 -0
  74. data/lib/adhearsion/voip/asterisk/ami/parser.rb +262 -0
  75. data/lib/adhearsion/voip/asterisk/ami.rb +147 -0
  76. data/lib/adhearsion/voip/asterisk/commands.rb +1186 -0
  77. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  78. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
  79. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  80. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  81. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  82. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  83. data/lib/adhearsion/voip/asterisk.rb +4 -0
  84. data/lib/adhearsion/voip/call.rb +402 -0
  85. data/lib/adhearsion/voip/call_routing.rb +64 -0
  86. data/lib/adhearsion/voip/commands.rb +9 -0
  87. data/lib/adhearsion/voip/constants.rb +39 -0
  88. data/lib/adhearsion/voip/conveniences.rb +18 -0
  89. data/lib/adhearsion/voip/dial_plan.rb +205 -0
  90. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  91. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  92. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  93. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  94. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +75 -0
  95. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  96. data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
  97. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  98. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  99. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  100. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  101. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  102. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  103. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  104. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
  105. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  106. data/lib/adhearsion.rb +31 -0
  107. data/script/destroy +14 -0
  108. data/script/generate +14 -0
  109. data/spec/fixtures/dialplan.rb +3 -0
  110. data/spec/initializer/test_configuration.rb +267 -0
  111. data/spec/initializer/test_loading.rb +162 -0
  112. data/spec/initializer/test_paths.rb +43 -0
  113. data/spec/silence.rb +10 -0
  114. data/spec/test_ahn_command.rb +149 -0
  115. data/spec/test_code_quality.rb +87 -0
  116. data/spec/test_component_manager.rb +97 -0
  117. data/spec/test_constants.rb +8 -0
  118. data/spec/test_drb.rb +104 -0
  119. data/spec/test_helper.rb +94 -0
  120. data/spec/test_hooks.rb +37 -0
  121. data/spec/test_host_definitions.rb +79 -0
  122. data/spec/test_initialization.rb +105 -0
  123. data/spec/test_logging.rb +80 -0
  124. data/spec/test_relationship_properties.rb +54 -0
  125. data/spec/voip/asterisk/ami_response_definitions.rb +23 -0
  126. data/spec/voip/asterisk/config_file_generators/test_agents.rb +253 -0
  127. data/spec/voip/asterisk/config_file_generators/test_queues.rb +325 -0
  128. data/spec/voip/asterisk/config_file_generators/test_voicemail.rb +306 -0
  129. data/spec/voip/asterisk/menu_command/test_calculated_match.rb +111 -0
  130. data/spec/voip/asterisk/menu_command/test_matchers.rb +98 -0
  131. data/spec/voip/asterisk/mock_ami_server.rb +176 -0
  132. data/spec/voip/asterisk/test_agi_server.rb +453 -0
  133. data/spec/voip/asterisk/test_ami.rb +227 -0
  134. data/spec/voip/asterisk/test_commands.rb +2006 -0
  135. data/spec/voip/asterisk/test_config_manager.rb +129 -0
  136. data/spec/voip/dsl/dispatcher_spec_helper.rb +45 -0
  137. data/spec/voip/dsl/test_dialing_dsl.rb +268 -0
  138. data/spec/voip/dsl/test_dispatcher.rb +82 -0
  139. data/spec/voip/dsl/test_parser.rb +87 -0
  140. data/spec/voip/freeswitch/test_basic_connection_manager.rb +39 -0
  141. data/spec/voip/freeswitch/test_inbound_connection_manager.rb +39 -0
  142. data/spec/voip/freeswitch/test_oes_server.rb +9 -0
  143. data/spec/voip/test_call_routing.rb +127 -0
  144. data/spec/voip/test_dialplan_manager.rb +372 -0
  145. data/spec/voip/test_numerical_string.rb +48 -0
  146. data/spec/voip/test_phone_number.rb +36 -0
  147. data/test/test_ahn_generator.rb +59 -0
  148. data/test/test_component_generator.rb +52 -0
  149. data/test/test_generator_helper.rb +20 -0
  150. metadata +254 -0
@@ -0,0 +1,253 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. test_helper])
2
+ require 'adhearsion/voip/asterisk/config_generators/agents.conf'
3
+
4
+ context "The agents.conf config file agents" do
5
+
6
+ include AgentsConfigFileGeneratorTestHelper
7
+
8
+ attr_reader :agents
9
+ before:each do
10
+ reset_agents!
11
+ end
12
+ test "The agent() method should enqueue a Hash into Agents#agent_definitions" do
13
+ agents.agent 1337, :password => 9876, :name => "Jay Phillips"
14
+ agents.agent_definitions.size.should.be 1
15
+ agents.agent_definitions.first.should == {:id => 1337, :password => 9876, :name => "Jay Phillips"}
16
+ end
17
+
18
+ test 'should add the warning message to the to_s output' do
19
+ agents.conf.should =~ /^\s*;.{10}/
20
+ end
21
+
22
+ test "The conf() method should always create a general section" do
23
+ agents.conf.should =~ /^\[general\]/
24
+ end
25
+
26
+ test "The agent() method should generate a proper String" do
27
+ agents.agent 123, :name => "Otto Normalverbraucher", :password => "007"
28
+ agents.agent 889, :name => "John Doe", :password => "998"
29
+
30
+ agents.conf.grep(/^agent =>/).map(&:strip).should == [
31
+ "agent => 123,007,Otto Normalverbraucher",
32
+ "agent => 889,998,John Doe"
33
+ ]
34
+ end
35
+
36
+ test "The persistent_agents() method should generate a persistentagents yes/no pair" do
37
+ agents.persistent_agents true
38
+ generated_config_has_pair(:persistentagents => "yes").should.be true
39
+
40
+ reset_agents!
41
+
42
+ agents.persistent_agents false
43
+ generated_config_has_pair(:persistentagents => "no").should.be true
44
+ end
45
+
46
+ test "The persistent_agents() method should be in the [general] section" do
47
+ agents.persistent_agents true
48
+ agents.general_section.should == {:persistentagents => "yes"}
49
+
50
+ end
51
+
52
+ test "max_login_tries() should generate a 'maxlogintries' numerical pair" do
53
+ agents.max_login_tries 50
54
+ generated_config_has_pair(:maxlogintries => "50").should.be true
55
+ end
56
+
57
+ test "max_login_tries() should be in the agents section" do
58
+ agents.max_login_tries 0
59
+ agents.agent_section.should == {:maxlogintries => 0}
60
+ end
61
+
62
+ test "log_off_after_duration should generate autologoff" do
63
+ agents.log_off_after_duration 15.seconds
64
+ generated_config_has_pair(:autologoff => "15").should.be true
65
+ end
66
+
67
+ test "log_off_if_unavailable should add autologoffunavail to the agents section" do
68
+ agents.log_off_if_unavailable false
69
+ agents.agent_section.should == {:autologoffunavail => "no"}
70
+ end
71
+
72
+ test "require_hash_to_acknowledge() should generate a 'ackcall' yes/no pair" do
73
+ agents.require_hash_to_acknowledge false
74
+ agents.agent_section.should == {:ackcall => "no"}
75
+ end
76
+
77
+ test "allow_star_to_hangup should generate a 'endcall' yes/no pair" do
78
+ agents.allow_star_to_hangup false
79
+ agents.agent_section.should == {:endcall => "no"}
80
+ end
81
+
82
+ test "time_between_calls should convert its argument to milliseconds" do
83
+ agents.time_between_calls 1.hour
84
+ agents.agent_section.should == {:wrapuptime => 1.hour * 1_000}
85
+ end
86
+
87
+ test "hold_music_class should convert its argument to a String" do
88
+ agents.hold_music_class :podcast
89
+ agents.agent_section_special.should == {:musiconhold => "podcast"}
90
+ end
91
+
92
+ test "play_on_agent_goodbye should generate 'agentgoodbye'" do
93
+ agents.play_on_agent_goodbye "tt-monkeys"
94
+ agents.agent_section_special.should == {:agentgoodbye => "tt-monkeys"}
95
+ end
96
+
97
+ test "change_cdr_source should generate updatecdr" do
98
+ agents.change_cdr_source false
99
+ agents.agent_section.should == {:updatecdr => "no"}
100
+ end
101
+
102
+ test "play_for_waiting_keep_alive" do
103
+ agents.play_for_waiting_keep_alive "tt-weasels"
104
+ agents.agent_section.should == {:custom_beep => "tt-weasels"}
105
+ end
106
+
107
+ test "save_recordings_in should generate 'savecallsin'" do
108
+ agents.save_recordings_in "/second/star/on/the/right"
109
+ agents.agent_section.should == {:savecallsin => "/second/star/on/the/right"}
110
+ end
111
+
112
+ test "recording_prefix should generate 'urlprefix'" do
113
+ agents.recording_prefix "ohai"
114
+ agents.agent_section.should == {:urlprefix => "ohai"}
115
+ end
116
+
117
+ test "recording_format should only allow a few symbols as an argument" do
118
+ the_following_code {
119
+ agents.recording_format :wav
120
+ agents.agent_section.should == {:recordformat => :wav}
121
+ }.should.not.raise
122
+
123
+ reset_agents!
124
+
125
+ the_following_code {
126
+ agents.recording_format :wav49
127
+ agents.agent_section.should == {:recordformat => :wav49}
128
+ }.should.not.raise
129
+
130
+ reset_agents!
131
+
132
+ the_following_code {
133
+ agents.recording_format :gsm
134
+ agents.agent_section.should == {:recordformat => :gsm}
135
+ }.should.not.raise
136
+
137
+ reset_agents!
138
+
139
+ the_following_code {
140
+ agents.recording_format :mp3
141
+ agents.agent_section.should == {:recordformat => :mp3}
142
+ }.should.raise ArgumentError
143
+
144
+ end
145
+
146
+ test "record_agent_calls should generate a 'recordagentcalls' yes/no pair" do
147
+ agents.record_agent_calls false
148
+ agents.agent_section.should == {:recordagentcalls => 'no'}
149
+ end
150
+
151
+ test "allow_multiple_logins_per_extension should generate 'multiplelogin' in [general]" do
152
+ agents.allow_multiple_logins_per_extension true
153
+ agents.general_section.should == {:multiplelogin => 'yes'}
154
+ end
155
+
156
+ end
157
+
158
+ context "The default agents.conf config file converted to this syntax" do
159
+
160
+ include AgentsConfigFileGeneratorTestHelper
161
+
162
+ attr_reader :default_config, :agents
163
+ before:each do
164
+ reset_agents!
165
+ @default_config = <<-CONFIG
166
+ [general]
167
+ persistentagents=yes
168
+
169
+ [agents]
170
+ maxlogintries=5
171
+ autologoff=15
172
+ ackcall=no
173
+ endcall=yes
174
+ wrapuptime=5000
175
+ musiconhold => default
176
+ agentgoodbye => goodbye_file
177
+ updatecdr=no
178
+ group=1,2
179
+ recordagentcalls=yes
180
+ recordformat=gsm
181
+ urlprefix=http://localhost/calls/
182
+ savecallsin=/var/calls
183
+ custom_beep=beep
184
+
185
+ agent => 1001,4321,Mark Spencer
186
+ agent => 1002,4321,Will Meadows
187
+ CONFIG
188
+ end
189
+
190
+ test "they're basically the same" do
191
+ agents.persistent_agents true
192
+ agents.max_login_tries 5
193
+ agents.log_off_after_duration 15
194
+ agents.require_hash_to_acknowledge false
195
+ agents.allow_star_to_hangup true
196
+ agents.time_between_calls 5
197
+ agents.hold_music_class :default
198
+ agents.play_on_agent_goodbye "goodbye_file"
199
+ agents.change_cdr_source false
200
+ agents.groups 1,2
201
+ agents.record_agent_calls true
202
+ agents.recording_format :gsm
203
+ agents.recording_prefix "http://localhost/calls/"
204
+ agents.save_recordings_in "/var/calls"
205
+ agents.play_for_waiting_keep_alive "beep"
206
+
207
+ agents.agent 1001, :password => 4321, :name => "Mark Spencer"
208
+ agents.agent 1002, :password => 4321, :name => "Will Meadows"
209
+
210
+ cleaned_up_default_config = Adhearsion::VoIP::Asterisk::ConfigFileGenerators::
211
+ AsteriskConfigGenerator.create_sanitary_hash_from(default_config)
212
+
213
+ cleaned_up_generated_config = agents.to_sanitary_hash
214
+
215
+ cleaned_up_generated_config.should == cleaned_up_default_config
216
+ end
217
+
218
+ end
219
+
220
+
221
+ context "AgentsConfigFileGeneratorTestHelper" do
222
+
223
+ include AgentsConfigFileGeneratorTestHelper
224
+
225
+ attr_reader :agents
226
+
227
+ test "generated_config_has_pair() works properly" do
228
+ @agents = flexmock "A fake agents with just one pair", :conf => "foo=bar"
229
+ generated_config_has_pair(:foo => "bar").should.be true
230
+
231
+ @agents = flexmock "A fake agents with just one pair", :conf => "[general]\n\nqaz=qwerty\nagent => 1,2,3"
232
+ generated_config_has_pair(:qaz => "qwerty").should.be true
233
+ generated_config_has_pair(:foo => "bar").should.be false
234
+ end
235
+ end
236
+
237
+ BEGIN {
238
+ module AgentsConfigFileGeneratorTestHelper
239
+
240
+ def reset_agents!
241
+ @agents = Adhearsion::VoIP::Asterisk::ConfigFileGenerators::Agents.new
242
+ end
243
+
244
+ def generated_config_has_pair(pair)
245
+ agents.conf.grep(/=[^>]/).each do |line|
246
+ key, value = line.strip.split('=')
247
+ return true if pair == {key.to_sym => value}
248
+ end
249
+ false
250
+ end
251
+
252
+ end
253
+ }
@@ -0,0 +1,325 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. test_helper])
2
+ require 'adhearsion/voip/asterisk/config_generators/queues.conf'
3
+
4
+ context "The queues.conf config file generator" do
5
+
6
+ include QueuesConfigFileGeneratorTestHelper
7
+
8
+ attr_reader :queues
9
+ before:each do
10
+ reset_queues!
11
+ end
12
+
13
+ test 'should set autofill=yes by default' do
14
+ generated_config_should_have_pair :autofill => 'yes'
15
+ end
16
+
17
+ test 'should have a [general] section' do
18
+ queues.conf.should.include "[general]\n"
19
+ end
20
+
21
+ test 'should yield a Queues object in its constructor' do
22
+ Adhearsion::VoIP::Asterisk::ConfigFileGenerators::Queues.new do |config|
23
+ config.should.be.kind_of Adhearsion::VoIP::Asterisk::ConfigFileGenerators::Queues
24
+ end
25
+ end
26
+
27
+ test 'should add the warning message to the to_s output' do
28
+ queues.conf.should =~ /^\s*;.{10}/
29
+ end
30
+
31
+ end
32
+
33
+ context "The queues.conf config file queues's QueueDefinition" do
34
+
35
+ include QueuesConfigFileGeneratorTestHelper
36
+
37
+ attr_reader :queues
38
+ before:each do
39
+ reset_queues!
40
+ end
41
+
42
+ test 'should include [queue_name]' do
43
+ name_of_queue = "leet_hax0rz"
44
+ queues.queue(name_of_queue).to_s.should.include "[#{name_of_queue}]"
45
+ end
46
+
47
+ test '#member should create a valid Agent "channel driver" to the member definition list' do
48
+ sample_queue = queues.queue "sales" do |sales|
49
+ sales.member 123
50
+ sales.member "Jay"
51
+ sales.member 'SIP/jay-desk-650'
52
+ sales.member 'IAX2/12345@voipms/15554443333'
53
+ end
54
+ sample_queue.members.should == %w[Agent/123 Agent/Jay SIP/jay-desk-650 IAX2/12345@voipms/15554443333]
55
+ end
56
+
57
+ test 'should automatically enable the two AMI-related events' do
58
+ @queues = queues.queue 'name'
59
+ generated_config_should_have_pair :eventwhencalled => 'vars'
60
+ generated_config_should_have_pair :eventmemberstatus => 'yes'
61
+ end
62
+
63
+ test '#strategy should only allow the pre-defined settings' do
64
+ [:ringall, :roundrobin, :leastrecent, :fewestcalls, :random, :rrmemory].each do |strategy|
65
+ the_following_code {
66
+ q = queues.queue 'foobar'
67
+ q.strategy strategy
68
+ }.should.not.raise
69
+ end
70
+
71
+ the_following_code {
72
+ queues.queue('qwerty').strategy :this_is_not_a_valid_strategy
73
+ }.should.raise ArgumentError
74
+
75
+ end
76
+
77
+ test '#sound_files raises an argument error when it sees an unrecognized key' do
78
+ the_following_code {
79
+ queues.queue 'foobar' do |foobar|
80
+ foobar.sound_files \
81
+ :you_are_next => rand.to_s,
82
+ :there_are => rand.to_s,
83
+ :calls_waiting => rand.to_s,
84
+ :hold_time => rand.to_s,
85
+ :minutes => rand.to_s,
86
+ :seconds => rand.to_s,
87
+ :thank_you => rand.to_s,
88
+ :less_than => rand.to_s,
89
+ :report_hold => rand.to_s,
90
+ :periodic_announcement => rand.to_s
91
+ end
92
+ }.should.not.raise
93
+
94
+ [:x_you_are_next, :x_there_are, :x_calls_waiting, :x_hold_time, :x_minutes,
95
+ :x_seconds, :x_thank_you, :x_less_than, :x_report_hold, :x_periodic_announcement].each do |bad_key|
96
+ the_following_code {
97
+ queues.queue("foobar") do |foobar|
98
+ foobar.sound_files bad_key => rand.to_s
99
+ end
100
+ }.should.raise ArgumentError
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+ context "The private, helper methods in QueueDefinition" do
108
+
109
+ include QueuesConfigFileGeneratorTestHelper
110
+
111
+ attr_reader :queue
112
+ before:each do
113
+ reset_queues!
114
+ @queue = @queues.queue "doesn't matter"
115
+ end
116
+
117
+ test '#boolean should convert a boolean into "yes" or "no"' do
118
+ mock_of_properties = flexmock "mock of the properties instance variable of a QueueDefinition"
119
+ mock_of_properties.should_receive(:[]=).once.with("icanhascheezburger", "yes")
120
+ flexmock(queue).should_receive(:properties).and_return mock_of_properties
121
+ queue.send(:boolean, "icanhascheezburger" => true)
122
+ end
123
+
124
+ test '#int should raise an argument error when its argument is not Numeric' do
125
+ the_following_code {
126
+ queue.send(:int, "eisley" => :i_break_things!)
127
+ }.should.raise ArgumentError
128
+ end
129
+
130
+ test '#int should coerce a String into a Numeric if possible' do
131
+ mock_of_properties = flexmock "mock of the properties instance variable of a QueueDefinition"
132
+ mock_of_properties.should_receive(:[]=).once.with("chimpanzee", 1337)
133
+ flexmock(queue).should_receive(:properties).and_return mock_of_properties
134
+ queue.send(:int, "chimpanzee" => "1337")
135
+ end
136
+
137
+ test '#string should add the argument directly to the properties' do
138
+ mock_of_properties = flexmock "mock of the properties instance variable of a QueueDefinition"
139
+ mock_of_properties.should_receive(:[]=).once.with("eins", "zwei")
140
+ flexmock(queue).should_receive(:properties).and_return mock_of_properties
141
+ queue.send(:string, "eins" => "zwei")
142
+ end
143
+
144
+ test '#one_of() should add its successful match to the properties attribute' do
145
+ mock_properties = flexmock "mock of the properties instance variable of a QueueDefinition"
146
+ mock_properties.should_receive(:[]=).once.with(:doesnt_matter, 5)
147
+ flexmock(queue).should_receive(:properties).once.and_return mock_properties
148
+
149
+ queue.send(:one_of, 1..100, :doesnt_matter => 5)
150
+ end
151
+
152
+ test "one_of() should convert booleans to yes/no" do
153
+ mock_properties = flexmock "mock of the properties instance variable of a QueueDefinition"
154
+ mock_properties.should_receive(:[]=).once.with(:doesnt_matter, 'yes')
155
+ flexmock(queue).should_receive(:properties).once.and_return mock_properties
156
+ queue.send(:one_of, [true, false, :strict], :doesnt_matter => true)
157
+
158
+ mock_properties = flexmock "mock of the properties instance variable of a QueueDefinition"
159
+ mock_properties.should_receive(:[]=).once.with(:doesnt_matter, :strict)
160
+ flexmock(queue).should_receive(:properties).once.and_return mock_properties
161
+ queue.send(:one_of, [true, false, :strict], :doesnt_matter => :strict)
162
+
163
+ mock_properties = flexmock "mock of the properties instance variable of a QueueDefinition"
164
+ mock_properties.should_receive(:[]=).once.with(:doesnt_matter, 'no')
165
+ flexmock(queue).should_receive(:properties).once.and_return mock_properties
166
+ queue.send(:one_of, [true, false, :strict], :doesnt_matter => false)
167
+ end
168
+
169
+ test '#one_of() should raise an ArgumentError if a value is not in the criteria' do
170
+ the_following_code {
171
+ queue.send(:one_of, [:jay, :thomas, :phillips], :sister => :jill)
172
+ }.should.raise ArgumentError
173
+ end
174
+ end
175
+
176
+ context 'The queues.conf config file generator when ran against a really big example' do
177
+
178
+ include QueuesConfigFileGeneratorTestHelper
179
+
180
+ attr_reader :queues, :default_config
181
+ before:each do
182
+ reset_queues!
183
+ @default_config = default_config = <<-CONFIG
184
+ [general]
185
+ persistentmembers=yes
186
+ autofill=yes
187
+ monitor-type=MixMonitor
188
+
189
+ [markq]
190
+ musicclass=default
191
+ announce=queue-markq
192
+ strategy=ringall
193
+ servicelevel=60
194
+ context=qoutcon
195
+ timeout=15
196
+ retry=5
197
+ weight=0
198
+ wrapuptime=15
199
+ autofill=yes
200
+ autopause=yes
201
+ maxlen=0
202
+ setinterfacevar=yes
203
+ announce-frequency=90
204
+ periodic-announce-frequency=60
205
+ announce-holdtime=once
206
+ announce-round-seconds=10
207
+ queue-youarenext=queue-youarenext
208
+ queue-thereare=queue-thereare
209
+ queue-callswaiting=queue-callswaiting
210
+ queue-holdtime=queue-holdtime
211
+ queue-minutes=queue-minutes
212
+ queue-seconds=queue-seconds
213
+ queue-thankyou=queue-thankyou
214
+ queue-lessthan=queue-less-than
215
+ queue-reporthold=queue-reporthold
216
+ periodic-announce=queue-periodic-announce
217
+ monitor-format=gsm
218
+ monitor-type=MixMonitor
219
+ joinempty=yes
220
+ leavewhenempty=yes
221
+ eventwhencalled=vars
222
+ eventmemberstatus=yes
223
+ reportholdtime=no
224
+ ringinuse=no
225
+ memberdelay=0
226
+ timeoutrestart=no
227
+
228
+ member => Zap/1
229
+ member => Agent/007
230
+ CONFIG
231
+ end
232
+
233
+ test "a sample config with multiple queues" do
234
+
235
+ generated = Adhearsion::VoIP::Asterisk::ConfigFileGenerators::Queues.new do |config|
236
+ config.persistent_members true
237
+ config.monitor_type :mix_monitor
238
+
239
+ config.queue 'markq' do |markq|
240
+ markq.music_class :default
241
+ markq.play_on_connect 'queue-markq'
242
+ markq.strategy :ringall
243
+ markq.service_level 60
244
+ markq.exit_to_context_on_digit_press 'qoutcon'
245
+ markq.ring_timeout 15
246
+ markq.retry_after_waiting 5
247
+ markq.weight 0
248
+ markq.wrapup_time 15
249
+ markq.autopause true
250
+ markq.maximum_length 0
251
+ markq.queue_status_announce_frequency 90
252
+ markq.announce_hold_time :once
253
+ markq.announce_round_seconds 10
254
+ markq.sound_files \
255
+ :you_are_next => "queue-youarenext",
256
+ :there_are => "queue-thereare",
257
+ :calls_waiting => "queue-callswaiting",
258
+ :hold_time => "queue-holdtime",
259
+ :minutes => "queue-minutes",
260
+ :seconds => "queue-seconds",
261
+ :thank_you => "queue-thankyou",
262
+ :less_than => "queue-less-than",
263
+ :report_hold => "queue-reporthold"
264
+ markq.periodically_announce "queue-periodic-announce"
265
+ markq.monitor_format :gsm
266
+ markq.monitor_type :mix_monitor
267
+ markq.join_empty true
268
+ markq.leave_when_empty true
269
+ markq.report_hold_time false
270
+ markq.ring_in_use false
271
+ markq.delay_connection_by 0
272
+ markq.timeout_restart false
273
+
274
+ markq.member 'Zap/1'
275
+ markq.member '007'
276
+ end
277
+ end
278
+
279
+ cleaned_up_default_config = Adhearsion::VoIP::Asterisk::ConfigFileGenerators::
280
+ AsteriskConfigGenerator.create_sanitary_hash_from(default_config)
281
+
282
+ cleaned_up_generated_config = generated.to_sanitary_hash
283
+
284
+ cleaned_up_generated_config.should == cleaned_up_default_config
285
+ end
286
+
287
+ end
288
+
289
+ context "ConfigFileGeneratorTestHelper" do
290
+
291
+ include QueuesConfigFileGeneratorTestHelper
292
+
293
+ attr_reader :queues
294
+
295
+ test "generated_config_has_pair() works properly" do
296
+ @queues = flexmock "A fake queues with just one pair", :to_s => "foo=bar"
297
+ generated_config_has_pair(:foo => "bar").should.be true
298
+
299
+ @queues = flexmock "A fake queues with just one pair", :to_s => "[general]\n\nqaz=qwerty\nagent => 1,2,3"
300
+ generated_config_has_pair(:qaz => "qwerty").should.be true
301
+ generated_config_has_pair(:foo => "bar").should.be false
302
+ end
303
+
304
+ end
305
+
306
+ BEGIN {
307
+ module QueuesConfigFileGeneratorTestHelper
308
+
309
+ def reset_queues!
310
+ @queues = Adhearsion::VoIP::Asterisk::ConfigFileGenerators::Queues.new
311
+ end
312
+
313
+ def generated_config_should_have_pair(pair)
314
+ generated_config_has_pair(pair).should.equal true
315
+ end
316
+
317
+ def generated_config_has_pair(pair)
318
+ queues.to_s.grep(/=[^>]/).each do |line|
319
+ key, value = line.strip.split('=')
320
+ return true if pair == {key.to_sym => value}
321
+ end
322
+ false
323
+ end
324
+ end
325
+ }