adhearsion 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. data/.gitignore +10 -0
  2. data/CHANGELOG +8 -0
  3. data/README.markdown +33 -0
  4. data/Rakefile +28 -68
  5. data/adhearsion.gemspec +19 -133
  6. data/app_generators/ahn/templates/Gemfile +0 -4
  7. data/app_generators/ahn/templates/components/disabled/restful_rpc/spec/restful_rpc_spec.rb +4 -16
  8. data/lib/adhearsion/cli.rb +17 -0
  9. data/lib/adhearsion/component_manager/component_tester.rb +1 -3
  10. data/lib/adhearsion/component_manager/spec_framework.rb +4 -10
  11. data/lib/adhearsion/foundation/object.rb +10 -0
  12. data/lib/adhearsion/version.rb +1 -1
  13. data/spec/ahn_command_spec.rb +284 -0
  14. data/spec/component_manager_spec.rb +292 -0
  15. data/spec/constants_spec.rb +8 -0
  16. data/spec/drb_spec.rb +65 -0
  17. data/spec/fixtures/dialplan.rb +3 -0
  18. data/spec/foundation/event_socket_spec.rb +168 -0
  19. data/spec/host_definitions_spec.rb +79 -0
  20. data/spec/initialization_spec.rb +163 -0
  21. data/spec/initializer/configuration_spec.rb +270 -0
  22. data/spec/initializer/loading_spec.rb +149 -0
  23. data/spec/initializer/paths_spec.rb +74 -0
  24. data/spec/logging_spec.rb +86 -0
  25. data/spec/relationship_properties_spec.rb +54 -0
  26. data/spec/silence.rb +10 -0
  27. data/spec/spec_helper.rb +101 -0
  28. data/spec/voip/asterisk/agi_server_spec.rb +473 -0
  29. data/spec/voip/asterisk/ami/ami_spec.rb +549 -0
  30. data/spec/voip/asterisk/ami/lexer/ami_fixtures.yml +30 -0
  31. data/spec/voip/asterisk/ami/lexer/lexer_story +291 -0
  32. data/spec/voip/asterisk/ami/lexer/lexer_story.rb +241 -0
  33. data/spec/voip/asterisk/ami/lexer/story_helper.rb +124 -0
  34. data/spec/voip/asterisk/ami/old_tests.rb +204 -0
  35. data/spec/voip/asterisk/ami/super_manager/super_manager_story +25 -0
  36. data/spec/voip/asterisk/ami/super_manager/super_manager_story.rb +15 -0
  37. data/spec/voip/asterisk/ami/super_manager/super_manager_story_helper.rb +5 -0
  38. data/spec/voip/asterisk/commands_spec.rb +2179 -0
  39. data/spec/voip/asterisk/config_file_generators/agents_spec.rb +251 -0
  40. data/spec/voip/asterisk/config_file_generators/queues_spec.rb +323 -0
  41. data/spec/voip/asterisk/config_file_generators/voicemail_spec.rb +306 -0
  42. data/spec/voip/asterisk/config_manager_spec.rb +127 -0
  43. data/spec/voip/asterisk/menu_command/calculated_match_spec.rb +109 -0
  44. data/spec/voip/asterisk/menu_command/matchers_spec.rb +97 -0
  45. data/spec/voip/call_routing_spec.rb +125 -0
  46. data/spec/voip/dialplan_manager_spec.rb +468 -0
  47. data/spec/voip/dsl/dialing_dsl_spec.rb +270 -0
  48. data/spec/voip/dsl/dispatcher_spec.rb +82 -0
  49. data/spec/voip/dsl/dispatcher_spec_helper.rb +45 -0
  50. data/spec/voip/dsl/parser_spec.rb +69 -0
  51. data/spec/voip/freeswitch/basic_connection_manager_spec.rb +39 -0
  52. data/spec/voip/freeswitch/inbound_connection_manager_spec.rb +39 -0
  53. data/spec/voip/freeswitch/oes_server_spec.rb +9 -0
  54. data/spec/voip/numerical_string_spec.rb +61 -0
  55. data/spec/voip/phone_number_spec.rb +45 -0
  56. data/theatre-spec/dsl_examples/dynamic_stomp.rb +7 -0
  57. data/theatre-spec/dsl_examples/simple_before_call.rb +7 -0
  58. data/theatre-spec/dsl_spec.rb +43 -0
  59. data/theatre-spec/invocation_spec.rb +167 -0
  60. data/theatre-spec/namespace_spec.rb +125 -0
  61. data/theatre-spec/spec_helper.rb +37 -0
  62. data/theatre-spec/spec_helper_spec.rb +28 -0
  63. data/theatre-spec/theatre_class_spec.rb +150 -0
  64. metadata +171 -34
@@ -0,0 +1,270 @@
1
+ require 'spec_helper'
2
+ require 'adhearsion/voip/dsl/dialing_dsl'
3
+
4
+ # Keep the monkey patches in a module and load that into Regexp
5
+ # eigenclasses during a before(:all) block?
6
+
7
+ describe "RouteRule Regexp assembling" do
8
+
9
+ it "should compile two Regexps" do
10
+ first, last = /jay/, /phillips/
11
+ r = first | last
12
+ r.patterns.should == [first, last]
13
+ end
14
+
15
+ it "should compile three or more Regexps" do
16
+ first, second, third = /lorem/, /ipsum/, /dolar/
17
+ r = first | second | third
18
+ r.patterns.should == [first, second, third]
19
+ end
20
+
21
+ end
22
+
23
+ describe "RouteRule assembling with one provider definition" do
24
+
25
+ before :each do
26
+ @provider = Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:icanhascheezburger?)
27
+ end
28
+
29
+ it "should store one pattern properly" do
30
+ pattern = /lorem/
31
+ route = pattern >> @provider
32
+ route.patterns.should == [pattern]
33
+ end
34
+
35
+ it "should store three patterns properly" do
36
+ first, second, third = /lorem/, /ipsum/, /dolar/
37
+ route = first | second | third >> @provider
38
+ route.patterns.should == [first, second, third]
39
+ route.providers.should == [@provider]
40
+ end
41
+
42
+ end
43
+
44
+ describe "RouteRule assembling with multiple patterns and multiple provider definitions" do
45
+
46
+ before(:each) do
47
+ 1.upto 3 do |i|
48
+ instance_variable_set "@prov_#{i}",
49
+ Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new("prov_#{i}")
50
+ instance_variable_set "@pattern_#{i}", /^#{i * 100}$/
51
+ end
52
+ end
53
+
54
+ it "should store the patterns properly" do
55
+ route_1 = @pattern_1 | @pattern_2 | @pattern_3 >> @prov_1 >> @prov_2 >> @prov_3
56
+ route_1.patterns.should == [@pattern_1, @pattern_2, @pattern_3]
57
+
58
+ route_2 = @pattern_2 | @pattern_3 | @pattern_1 >> @prov_3 >> @prov_2 >> @prov_1
59
+ route_2.patterns.should == [@pattern_2, @pattern_3, @pattern_1]
60
+ end
61
+
62
+ it "should store the providers properly" do
63
+ route_1 = @pattern_1 | @pattern_2 | @pattern_3 >> @prov_1 >> @prov_2 >> @prov_3
64
+ route_1.providers.should == [@prov_1, @prov_2, @prov_3]
65
+
66
+ route_2 = @pattern_2 | @pattern_3 | @pattern_1 >> @prov_3 >> @prov_2 >> @prov_1
67
+ route_2.patterns.should == [@pattern_2, @pattern_3, @pattern_1]
68
+ end
69
+ end
70
+
71
+ describe "The DialingDSL class internals" do
72
+
73
+ it "should allow Asterisk-like patterns" do
74
+ Adhearsion::VoIP::DSL::DialingDSL.class_eval do
75
+ _('23XX')
76
+ end.should be_an_instance_of Regexp
77
+ end
78
+
79
+ it "should define all of the VoIP constants" do
80
+ lambda do
81
+ Adhearsion::VoIP::Constants.constants.each do |constant|
82
+ eval "Adhearsion::VoIP::DSL::DialingDSL::#{constant}"
83
+ end
84
+ end.should_not raise_error NameError
85
+ end
86
+
87
+ # it "should define a DUNDI constant"
88
+
89
+ it "should synchronize access to the trunking information for Thread safety"
90
+
91
+ end
92
+
93
+ describe "The provider DSL's 'provider' macro" do
94
+
95
+ it "should make the providers available in the order they were received" do
96
+ provider_holder = Class.new Adhearsion::VoIP::DSL::DialingDSL
97
+ provider_holder.class_eval do
98
+ provider(:tweedledee) {}
99
+ provider(:tweedledum) {}
100
+ end
101
+ provider_holder.providers.map { |x| x.name }.should == [:tweedledee, :tweedledum]
102
+ end
103
+ it "should define a singleton method for the provider name given", :focus => true do
104
+ dsl_class = Class.new(Adhearsion::VoIP::DSL::DialingDSL)
105
+ dsl_class.class_eval do
106
+ class_variable_get(:@@providers).size.should == 0
107
+
108
+ provider(:icanhascheezburger?) {}
109
+
110
+ class_variable_get(:@@providers).size.should == 1
111
+ end
112
+ dsl_class.should respond_to(:icanhascheezburger?)
113
+ end
114
+ it "should not define a class-wide method for the provider name given" do
115
+ dsl_class = Class.new(Adhearsion::VoIP::DSL::DialingDSL)
116
+ dsl_class.class_eval do
117
+ provider(:icanhascheezburger?) {}
118
+ end
119
+ Adhearsion::VoIP::DSL::DialingDSL.class_eval do
120
+ class_variable_defined?(:@@providers).should == false
121
+ end
122
+ Adhearsion::VoIP::DSL::DialingDSL.should_not respond_to(:icanhascheezburger?)
123
+ end
124
+ it "should yield a ProviderDefinition object" do
125
+ possible_provider_definition = nil
126
+ Class.new(Adhearsion::VoIP::DSL::DialingDSL).class_eval do
127
+ provider(:blah) { |pd| possible_provider_definition = pd }
128
+ end
129
+ possible_provider_definition.should be_a_kind_of(Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition)
130
+ end
131
+ it "should raise an error when no block is given" do
132
+ the_following_code do
133
+ Class.new(Adhearsion::VoIP::DSL::DialingDSL).class_eval do
134
+ provider :explode
135
+ end
136
+ end.should raise_error ArgumentError
137
+ end
138
+ end
139
+
140
+ describe "The provider DSL's monkey patches to Regexp" do
141
+ it "should return a RouteRule when using Regexp#| with another Regexp" do
142
+ (// | //).should be_a_kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
143
+ end
144
+ it "should return a RouteRule when chaining three Regexp's with the | operator" do
145
+ (// | // | //).should be_a_kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
146
+ end
147
+ it "should return a RouteRule when Regexp#| is given a RouteRule" do
148
+ route_rule = Adhearsion::VoIP::DSL::DialingDSL::RouteRule.new :patterns => //
149
+ (// | route_rule).should be_a_kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
150
+ end
151
+ it "should return a RouteRule when Regexp#>> is given a ProviderDefinition" do
152
+ (/1/ >> Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:foo)).
153
+ should be_a_kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
154
+ end
155
+ it "should return a RouteRule when Regexp#>>() receives a ProviderDefinition" do
156
+ definition = Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:london)
157
+ (/foo/ >> definition).should be_a_kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
158
+ end
159
+ it "should raise an exception when Regexp#| receives something other than a RouteRule" do
160
+ bad_args = [ 0..100, 20, 45.55, {}, [] ]
161
+ bad_args.each do |arg|
162
+ the_following_code { /foo/ | arg }.should raise_error ArgumentError
163
+ end
164
+ end
165
+ it "should raise an exception when Regexp#>>() receives anything other than a ProviderDefintion or RouteRule" do
166
+ bad_args = [ 0..100, 20, 45.55, {}, [] ]
167
+ bad_args.each do |arg|
168
+ the_following_code { /foo/ >> arg }.should raise_error ArgumentError
169
+ end
170
+ end
171
+ end
172
+
173
+ describe "A RouteRule" do
174
+ it "should expose chained ProviderDefinitions properly" do
175
+ one, two, three = definitions = %w"foo bar qaz".map do |name|
176
+ Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new name
177
+ end
178
+ route = /^911$/ >> one >> two >> three
179
+ route.should be_a_kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
180
+ route.providers.should == definitions
181
+ end
182
+ it "should define attr_readers for providers and patterns" do
183
+ route = Adhearsion::VoIP::DSL::DialingDSL::RouteRule.new
184
+ route.should respond_to(:patterns)
185
+ route.should respond_to(:providers)
186
+ end
187
+ end
188
+
189
+ describe "The provider order modifiers" do
190
+ it "should support randomizing trunks", :ignore => true do
191
+ dsl = Class.new Adhearsion::VoIP::DSL::DialingDSL
192
+ dsl.class_eval do
193
+ provider(:l33thost) {}
194
+ provider(:h4xxhost) {}
195
+ route /\d+\*548/ >> random(l33thost, h4xxhost)
196
+ end
197
+ dsl.routes.first.provider_definitions.first.should be_a_kind_of(
198
+ Adhearsion::VoIP::DSL::DialingDSL::RandomRouteRule
199
+ )
200
+ end
201
+ end
202
+
203
+ describe "The provider DSL's 'route' builder" do
204
+ it "should register routes in the order received" do
205
+ dsl = Class.new Adhearsion::VoIP::DSL::DialingDSL
206
+ dsl.class_eval do
207
+ provider(:kewlphone) {}
208
+ [/1?4445556666/, /123/, /\d+\*548/].each do |r|
209
+ route r >> kewlphone
210
+ end
211
+ end
212
+ dsl.routes.map { |x| x.patterns }.flatten.should == [/1?4445556666/, /123/, /\d+\*548/]
213
+ end
214
+ end
215
+
216
+ describe "A ProviderDefinition" do
217
+ it "should store any arbitrary property" do
218
+ definition = Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new :foo
219
+ definition.qaz = :something
220
+ definition.qaz.should == :something
221
+ end
222
+ it "should define a >>() method" do
223
+ Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:arghh).should respond_to(:>>)
224
+ end
225
+
226
+ it "should format numbers properly" do
227
+ definition = Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:arghh)
228
+ definition.protocol = "SIP"
229
+ definition.format_number_for_platform("14445556666", :asterisk).should == "SIP/arghh/14445556666"
230
+ definition.protocol = "SCCP"
231
+ definition.format_number_for_platform("16663331111", :asterisk).should == "SCCP/arghh/16663331111"
232
+
233
+ end
234
+ end
235
+
236
+ describe "Routing with the interpreted route definitions" do
237
+ it "should use the first matching regular expression" do
238
+ dsl = Class.new Adhearsion::VoIP::DSL::DialingDSL
239
+ dsl.class_eval do
240
+ provider(:bad) {}
241
+ provider(:good) {}
242
+ route /^111$/ | /^222$/ | /^333$/ >> good >> bad
243
+ end
244
+
245
+ found = dsl.calculate_routes_for(333)
246
+
247
+ 1.should be found.size
248
+ found.first.size.should be 2
249
+ end
250
+
251
+ end
252
+
253
+ # @example = Class.new Adhearsion::VoIP::DSL::DialingDSL
254
+ # @example.class_eval do
255
+ #
256
+ # provider:kewlphone do |trunk|
257
+ # trunk.protocol :sip
258
+ # trunk.host "voip.nufone.com"
259
+ # trunk.username "phonedude"
260
+ # trunk.password "secret"
261
+ # trunk.enters :internal
262
+ # end
263
+ #
264
+ # route US_NUMBER | US_LOCAL_NUMBER >> voip_ms >> nufone
265
+ #
266
+ # route INTL_NUMBER >> random(voip_ms, nufone)
267
+ #
268
+ # # route _('NXX') >> DUNDI
269
+ #
270
+ # end
@@ -0,0 +1,82 @@
1
+ require File.dirname(__FILE__) + '/dispatcher_spec_helper'
2
+ require 'adhearsion/voip/dsl/dialplan/dispatcher'
3
+
4
+
5
+ describe "A EventCommand" do
6
+
7
+ it "should allow a block that's set to response_block()" do
8
+ block = lambda {}
9
+ cmd = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "foo", &block
10
+ cmd.response_block.should be(block)
11
+ end
12
+
13
+ it "should return specified return type with returns()" do
14
+ return_type = Numeric
15
+ cmd = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "foo", :returns => return_type
16
+ cmd.returns.should be(return_type)
17
+ end
18
+
19
+ end
20
+
21
+ describe "The abstract CommandDispatcher" do
22
+
23
+ it "should make an attribute reader for context()" do
24
+ context = "foo"
25
+ d = Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher.new String, context
26
+ d.context.should be(context)
27
+ end
28
+
29
+ it "should instantiate a new instance of the specified factory" do
30
+ d = Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher.new Hash
31
+ d.factory.should be_a_kind_of(Hash)
32
+ end
33
+
34
+ it "should pass the context to the factory when instantiating it" do
35
+ context = "shazbot"
36
+ klass = flexmock "a class that has one argument in its constructor"
37
+ klass.should_receive(:new).with(context)
38
+ d = Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher.new klass, context
39
+ end
40
+
41
+ it "should not allow calling dispatch!() directly" do
42
+ dispatcher = Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher.new MyFactory
43
+ lambda do
44
+ dispatcher.dispatch! nil
45
+ end.should raise_error(NotImplementedError)
46
+ end
47
+
48
+ it "should pass a method and any args onto its CommandFactory" do
49
+
50
+ weird_args = [1, 2, ["foo", nil], Object.new, 12.3..13.4]
51
+
52
+ bogus_command = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "123"
53
+
54
+ dispatcher = NilDispatcher.new MyFactory
55
+ flexmock(dispatcher.factory).should_receive(:monkey).with(*weird_args).and_return bogus_command
56
+ dispatcher.monkey(*weird_args)
57
+
58
+ end
59
+
60
+ it "should continue executing response_blocks until nil is returned" do
61
+ actual_executions, target_executions = 0, 5
62
+ response = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "1" do |response|
63
+ if response > target_executions
64
+ nil
65
+ else
66
+ actual_executions += 1
67
+ Adhearsion::VoIP::DSL::Dialplan::EventCommand.new(response + 1)
68
+ end
69
+ end
70
+ mock_factory_class = Class.new do
71
+ def initialize(*args)
72
+ end
73
+ def testplz
74
+ response
75
+ end
76
+ end
77
+ dispatcher = EvalDispatcher.new(mock_factory_class)
78
+ flexmock(dispatcher.factory).should_receive(:testplz).and_return(response)
79
+ dispatcher.testplz
80
+ actual_executions.should be(target_executions)
81
+ end
82
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ require 'adhearsion/voip/dsl/dialplan/dispatcher'
4
+
5
+ module StandardDispatcherBehavior
6
+ def xtest_standard_dispatcher_behavior
7
+ #"This it looks bogus. Not finished? Let's not check in failing specs ever if we can help it."
8
+ returned_event_command = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "ilikesexypants"
9
+ linking_event_command = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "ihavesexypants" do
10
+ returned_event_command
11
+ end
12
+
13
+ dispatcher = @dispatcher_class.new MyFactory
14
+ dispatcher.should_receive(:dispatch!).with(linking_event_command, returned_event_command).and_return(linking_event_command, returned_event_command)
15
+ # returned_event_command.should_receive(:command_block).and_return nil
16
+ dispatcher.dispatch! linking_event_command
17
+ end
18
+ end
19
+
20
+ class NilDispatcher < Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher
21
+ def dispatch!(string)
22
+ # Would send it off to the PBX here (or prepend something to the String)
23
+ end
24
+ end
25
+
26
+ class EvalDispatcher < Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher
27
+ def dispatch!(event)
28
+ eval event.app.to_s
29
+ end
30
+ end
31
+
32
+ class MyFactory
33
+
34
+ def initialize(context)
35
+ @context = context
36
+ end
37
+
38
+ def sequence
39
+ all = []
40
+ EventCommand.new("2", :response => Numeric) do |response|
41
+ all << response
42
+ all.size > 3 ? all : nil
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ require 'adhearsion/voip/dsl/dialplan/parser'
4
+
5
+ describe "The Adhearsion VoIP dialplan parser" do
6
+
7
+ it "should return a list of dialplans properly from dialplan code" do
8
+ file = "foobar.rb"
9
+ flexstub(Adhearsion::AHN_CONFIG).should_receive(:files_from_setting).once.with("paths", "dialplan").and_return [file]
10
+
11
+ flexmock(File).should_receive(:exists?).with(file).and_return true
12
+ flexmock(File).should_receive(:read).once.with(file).and_return <<-DIALPLAN
13
+ internal {
14
+ play "hello-world"
15
+ }
16
+ monkeys {
17
+ play "tt-monkeys"
18
+ }
19
+ DIALPLAN
20
+ contexts = Adhearsion::VoIP::DSL::Dialplan::DialplanParser.get_contexts
21
+ contexts.keys.size.should be(2)
22
+ contexts.keys.should include(:internal)
23
+ contexts.keys.should include(:monkeys)
24
+ contexts.each_pair do |context, struct|
25
+ struct.should be_a_kind_of(OpenStruct)
26
+ %w"file name block".each do |method|
27
+ struct.should respond_to(method)
28
+ end
29
+ end
30
+ end
31
+
32
+ it "should warn when no dialplan paths were in the .ahnrc file" do
33
+ flexmock(Adhearsion::AHN_CONFIG).should_receive(:files_from_setting).once.with("paths", "dialplan").and_return []
34
+ flexmock(ahn_log.dialplan).should_receive(:warn).once.with(String)
35
+
36
+ # Not loading it here is the same as it not existing in the "paths" sub-Hash
37
+ Adhearsion::VoIP::DSL::Dialplan::DialplanParser.get_contexts
38
+ end
39
+
40
+ end
41
+
42
+ describe "The Adhearsion VoIP dialplan interpreter" do
43
+
44
+ it "should make dialplan contexts available within the context's block" do
45
+ file = "contexts_from_code_helper_pseudo_dialplan.rb"
46
+ flexstub(Adhearsion::AHN_CONFIG).should_receive(:files_from_setting).once.with("paths", "dialplan").and_return [file]
47
+
48
+ flexmock(File).should_receive(:exists?).with(file).and_return true
49
+ flexmock(File).should_receive(:read).with(file).and_return "foo { cool_method }"
50
+
51
+ contexts = Adhearsion::VoIP::DSL::Dialplan::DialplanParser.get_contexts
52
+
53
+ contexts.each_pair do |name, struct|
54
+ contexts.meta_def(name) { struct.code }
55
+ end
56
+
57
+ # Simulate incoming request
58
+ contexts = contexts.clone
59
+
60
+ call_variables = { "callerid" => "14445556666", "context" => "foo" }
61
+
62
+ call_variables.each_pair do |key, value|
63
+ contexts.meta_def(key) { value }
64
+ contexts.instance_variable_set "@#{key}", value
65
+ end
66
+
67
+ end
68
+
69
+ end