agent_xmpp 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 (73) hide show
  1. data/.document +5 -0
  2. data/.gitignore +11 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +417 -0
  5. data/Rakefile +75 -0
  6. data/VERSION +1 -0
  7. data/agent_xmpp.gemspec +144 -0
  8. data/lib/agent_xmpp.rb +22 -0
  9. data/lib/agent_xmpp/admin.rb +113 -0
  10. data/lib/agent_xmpp/client.rb +7 -0
  11. data/lib/agent_xmpp/client/boot.rb +83 -0
  12. data/lib/agent_xmpp/client/client.rb +64 -0
  13. data/lib/agent_xmpp/client/connection.rb +108 -0
  14. data/lib/agent_xmpp/client/controller.rb +394 -0
  15. data/lib/agent_xmpp/client/message_delegate.rb +720 -0
  16. data/lib/agent_xmpp/client/message_pipe.rb +193 -0
  17. data/lib/agent_xmpp/client/response.rb +102 -0
  18. data/lib/agent_xmpp/config.rb +48 -0
  19. data/lib/agent_xmpp/main.rb +175 -0
  20. data/lib/agent_xmpp/models.rb +7 -0
  21. data/lib/agent_xmpp/models/contact.rb +85 -0
  22. data/lib/agent_xmpp/models/message.rb +152 -0
  23. data/lib/agent_xmpp/models/publication.rb +53 -0
  24. data/lib/agent_xmpp/models/roster.rb +107 -0
  25. data/lib/agent_xmpp/models/service.rb +91 -0
  26. data/lib/agent_xmpp/models/subscription.rb +61 -0
  27. data/lib/agent_xmpp/models/table_definitions.rb +107 -0
  28. data/lib/agent_xmpp/patches.rb +7 -0
  29. data/lib/agent_xmpp/patches/array.rb +32 -0
  30. data/lib/agent_xmpp/patches/float.rb +10 -0
  31. data/lib/agent_xmpp/patches/hash.rb +13 -0
  32. data/lib/agent_xmpp/patches/object.rb +15 -0
  33. data/lib/agent_xmpp/patches/rexml.rb +69 -0
  34. data/lib/agent_xmpp/patches/string.rb +15 -0
  35. data/lib/agent_xmpp/xmpp.rb +18 -0
  36. data/lib/agent_xmpp/xmpp/element.rb +158 -0
  37. data/lib/agent_xmpp/xmpp/entry.rb +36 -0
  38. data/lib/agent_xmpp/xmpp/error_response.rb +189 -0
  39. data/lib/agent_xmpp/xmpp/iq.rb +90 -0
  40. data/lib/agent_xmpp/xmpp/iq_command.rb +54 -0
  41. data/lib/agent_xmpp/xmpp/iq_disco.rb +206 -0
  42. data/lib/agent_xmpp/xmpp/iq_pubsub.rb +270 -0
  43. data/lib/agent_xmpp/xmpp/iq_roster.rb +183 -0
  44. data/lib/agent_xmpp/xmpp/iq_version.rb +89 -0
  45. data/lib/agent_xmpp/xmpp/jid.rb +150 -0
  46. data/lib/agent_xmpp/xmpp/message.rb +82 -0
  47. data/lib/agent_xmpp/xmpp/presence.rb +127 -0
  48. data/lib/agent_xmpp/xmpp/sasl.rb +241 -0
  49. data/lib/agent_xmpp/xmpp/stanza.rb +107 -0
  50. data/lib/agent_xmpp/xmpp/x_data.rb +357 -0
  51. data/test/app/app.rb +339 -0
  52. data/test/cases/test_application_message_processing.rb +65 -0
  53. data/test/cases/test_errors.rb +24 -0
  54. data/test/cases/test_presence_management.rb +139 -0
  55. data/test/cases/test_roster_management.rb +214 -0
  56. data/test/cases/test_service_discovery.rb +168 -0
  57. data/test/cases/test_session_management.rb +120 -0
  58. data/test/cases/test_version_discovery.rb +67 -0
  59. data/test/helpers/matchers.rb +23 -0
  60. data/test/helpers/mocks.rb +82 -0
  61. data/test/helpers/test_case_extensions.rb +45 -0
  62. data/test/helpers/test_client.rb +44 -0
  63. data/test/helpers/test_delegate.rb +60 -0
  64. data/test/helpers/test_helper.rb +91 -0
  65. data/test/messages/application_messages.rb +206 -0
  66. data/test/messages/error_messages.rb +35 -0
  67. data/test/messages/presence_messages.rb +66 -0
  68. data/test/messages/roster_messages.rb +126 -0
  69. data/test/messages/service_discovery_messages.rb +201 -0
  70. data/test/messages/session_messages.rb +158 -0
  71. data/test/messages/version_discovery_messages.rb +69 -0
  72. data/test/peer/peer.rb +21 -0
  73. metadata +187 -0
@@ -0,0 +1,339 @@
1
+ ##########################################################################################################
2
+ require 'rubygems'
3
+ require "#{File.dirname(__FILE__)}/../../lib/agent_xmpp"
4
+
5
+ ##########################################################################################################
6
+ # before filters
7
+ #.........................................................................................................
8
+ # only online contacts can send command messages
9
+ before :command => :all do
10
+ jid = params[:from]
11
+ AgentXmpp::Roster.find_by_jid(jid) or AgentXmpp.is_account_jid?(jid)
12
+ end
13
+
14
+ ##########################################################################################################
15
+ # callbacks
16
+ #.........................................................................................................
17
+ before_start do
18
+ AgentXmpp.logger.level = Logger::DEBUG
19
+ File.delete("#{AgentXmpp.app_path}/in_memory.db") if File.exists?("#{AgentXmpp.app_path}/in_memory.db")
20
+ AgentXmpp.logger.info "before_start"
21
+ end
22
+
23
+ #.........................................................................................................
24
+ after_connected do |connection|
25
+ AgentXmpp.logger.info "after_connected"
26
+ end
27
+
28
+ #.........................................................................................................
29
+ restarting_client do |connection|
30
+ AgentXmpp.logger.info "restarting_client"
31
+ end
32
+
33
+ #.........................................................................................................
34
+ discovered_pubsub_node do |service, node|
35
+ AgentXmpp.logger.info "discovered_pubsub_node: #{service}, #{node}"
36
+ if node.eql?(AgentXmpp.user_pubsub_root+'/time')
37
+ AgentXmpp.logger.info "LAUNCHING TIME PUBLISH TASK"
38
+ EventMachine::PeriodicTimer.new(600) do
39
+ publish_time(Time.now.to_s)
40
+ AgentXmpp.logger.info "FIRING EVENT TIME: #{Time.now.to_s}"
41
+ end
42
+ elsif node.eql?(AgentXmpp.user_pubsub_root+'/gibberish')
43
+ AgentXmpp.logger.info "LAUNCHING GIBBERISH PUBLISH TASK"
44
+ EventMachine::PeriodicTimer.new(10) do
45
+ letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' ',' ',' ',' ',' ',' ',' ']
46
+ publish_gibberish((0..300).inject(''){|j,i| j+=letters[((letters.length*rand).truncate)]}.gsub(/\s+/,' '))
47
+ AgentXmpp.logger.info "FIRING EVENT GIBBERISH: #{Time.now.to_s}"
48
+ end
49
+ end
50
+ end
51
+
52
+ #.........................................................................................................
53
+ discovered_command_nodes do |jid, nodes|
54
+ AgentXmpp.logger.info "discovered_command_nodes"
55
+ nodes.each do |n|
56
+ AgentXmpp.logger.info "COMMAND NODE: #{jid}, #{n}"
57
+ end
58
+ end
59
+
60
+ #.........................................................................................................
61
+ received_presence do |from, status|
62
+ AgentXmpp.logger.info "received_presence: #{from}, #{status}"
63
+ end
64
+
65
+ ##########################################################################################################
66
+ # command processing: response payloads
67
+ #.........................................................................................................
68
+ command 'data/scalar' do
69
+ AgentXmpp.logger.info "ACTION: scalar"
70
+ 'scalar'
71
+ end
72
+
73
+ #.........................................................................................................
74
+ command 'data/hash' do
75
+ AgentXmpp.logger.info "ACTION: hash"
76
+ {:xyz => 'wuv', :attr1 => 'val1', :attr2 => 'val2', :test1 => 'ans1'}
77
+ end
78
+
79
+ #.........................................................................................................
80
+ command 'data/scalar_array' do
81
+ AgentXmpp.logger.info "ACTION: array"
82
+ ['val1', 'val2','val3', 'val4']
83
+ end
84
+
85
+ #.........................................................................................................
86
+ command 'data/hash_array' do
87
+ AgentXmpp.logger.info "ACTION: hash_array"
88
+ {:attr1 => ['val11', 'val11'], :attr2 => 'val12'}
89
+ end
90
+
91
+ #.........................................................................................................
92
+ command 'data/array_hash' do
93
+ AgentXmpp.logger.info "ACTION: array_hash"
94
+ [{:attr1 => 'val11', :attr2 => 'val12'},
95
+ {:attr1 => 'val21', :attr2 => 'val22'},
96
+ {:attr1 => 'val31', :attr2 => 'val32'}]
97
+ end
98
+
99
+ #.........................................................................................................
100
+ command 'data/array_hash_array' do
101
+ AgentXmpp.logger.info "ACTION: hash_array"
102
+ [{:attr1 => ['val11', 'val11'], :attr2 => 'val12'},
103
+ {:attr1 => ['val21', 'val21'], :attr2 => 'val22'},
104
+ {:attr1 => ['val31', 'val31'], :attr2 => 'val32'}]
105
+ end
106
+
107
+ ##########################################################################################################
108
+ # command processing: data forms
109
+ #.........................................................................................................
110
+ command 'form/text_single' do
111
+ AgentXmpp.logger.info "ACTION: text_single"
112
+ on(:execute) do |form|
113
+ form.add_title('Your Name')
114
+ form.add_instructions('Use the keyboard to enter your name below.')
115
+ form.add_text_single('name', 'enter your name')
116
+ form.add_fixed('State of residence')
117
+ form.add_text_single('state')
118
+ end
119
+ on(:submit) do
120
+ params[:data]
121
+ end
122
+ end
123
+
124
+ #.........................................................................................................
125
+ command 'form/text_private' do
126
+ AgentXmpp.logger.info "ACTION: text_multi"
127
+ on(:execute) do |form|
128
+ form.add_title('Enter a Secret')
129
+ form.add_instructions('Use the keyboard to enter your secret below.')
130
+ form.add_text_private('secret', 'The Secret')
131
+ form.add_fixed('Renter your secret')
132
+ form.add_text_private('another_secret')
133
+ end
134
+ on(:submit) do
135
+ params[:data]
136
+ end
137
+ end
138
+
139
+ #.........................................................................................................
140
+ command 'form/jid_single' do
141
+ AgentXmpp.logger.info "ACTION: text_single"
142
+ on(:execute) do |form|
143
+ form.add_title('The JID')
144
+ form.add_instructions('Use the keyboard to enter a JID below.')
145
+ form.add_jid_single('jid', 'A JID')
146
+ form.add_fixed("Another JID")
147
+ form.add_jid_single('another_jid')
148
+ end
149
+ on(:submit) do
150
+ params[:data]
151
+ end
152
+ end
153
+
154
+ #.........................................................................................................
155
+ command 'form/text_multi' do
156
+ AgentXmpp.logger.info "ACTION: text_multi"
157
+ on(:execute) do |form|
158
+ form.add_title('Tell a Story')
159
+ form.add_instructions('Use the keyboard to enter your story below.')
160
+ form.add_text_multi('story', 'Your Story')
161
+ form.add_fixed("A haiku is required")
162
+ form.add_text_multi('haiku')
163
+ end
164
+ on(:submit) do
165
+ params[:data]
166
+ end
167
+ end
168
+
169
+ #.........................................................................................................
170
+ command 'form/list_single' do
171
+ AgentXmpp.logger.info "ACTION: list_single"
172
+ on(:execute) do |form|
173
+ form.add_title('Fruits')
174
+ form.add_instructions('Select a fruit from the list.')
175
+ form.add_list_single('fruits', [:apple, :orange, :lemon, :lime, :kiwi_fruit], 'available fruits')
176
+ form.add_fixed('Choose a car')
177
+ form.add_list_single('car', [:audi_s4, :bmw_m3, :subaru_wrx_ti, :mitsubishi_evo])
178
+ end
179
+ on(:submit) do
180
+ params[:data]
181
+ end
182
+ end
183
+
184
+ #.........................................................................................................
185
+ command 'form/boolean', :defer => true do
186
+ AgentXmpp.logger.info "ACTION: boolean"
187
+ on(:execute) do |form|
188
+ form.add_title('Hyper Drive Configuration')
189
+ form.add_instructions('Choose the hyperdrive configuration which best suits your needs')
190
+ form.add_boolean('answer', 'On or Off please')
191
+ form.add_boolean('flux_capcitors', 'Enable flux capacitors for superluminal transport')
192
+ form.add_fixed('Enable SQUIDs for enhanced quantum decoherence')
193
+ form.add_boolean('squids')
194
+ end
195
+ on(:submit) do
196
+ params[:data]
197
+ end
198
+ end
199
+
200
+ #.........................................................................................................
201
+ command 'form/long_form' do
202
+ AgentXmpp.logger.info "ACTION: long_form"
203
+ on(:execute) do |form|
204
+ form.add_title('The Long Form')
205
+ form.add_instructions('Make the correct choices and provide the required information.')
206
+ form.add_fixed("Your name is required.")
207
+ form.add_text_single('first_name', 'First Name')
208
+ form.add_text_single('last_name', 'Last Name')
209
+ form.add_fixed("Your address is required.")
210
+ form.add_text_single('street', 'Street')
211
+ form.add_text_single('city', 'City')
212
+ form.add_text_single('state', 'State')
213
+ form.add_text_single('zip', 'Zip Code')
214
+ form.add_fixed("Enter two friends.")
215
+ form.add_jid_single('contact_1', 'contact JID')
216
+ form.add_jid_single('contact_2', 'contact JID')
217
+ form.add_fixed("Your password is required.")
218
+ form.add_text_private('password', 'Password')
219
+ form.add_text_private('renter_password', 'Renter Password')
220
+ form.add_fixed("Choose your food.")
221
+ form.add_list_single('fruits', [:apple, :orange, :lemon, :lime, :kiwi_fruit], 'Select a Fruit')
222
+ form.add_list_single('nuts', [:peanut, :almond, :cashew, :pecan, :walnut], 'Select a Nut')
223
+ form.add_list_single('vegetables', [:broccoli, :carrot, :corn, :tomato, :onion], 'Select a Vegtable')
224
+ form.add_fixed("Answer the questions.")
225
+ form.add_boolean('yes_or_no', 'Yes or No please?')
226
+ form.add_boolean('flux_capcitors', 'Enable flux capacitors for superluminal transport')
227
+ form.add_fixed("A story of at least 250 characters is required")
228
+ form.add_text_multi('story', 'Your Story')
229
+ end
230
+ on(:submit) do
231
+ params[:data]
232
+ end
233
+ end
234
+
235
+ #.........................................................................................................
236
+ command 'form/another_long_form' do
237
+ AgentXmpp.logger.info "ACTION: another_long_form"
238
+ on(:execute) do |form|
239
+ form.add_title('The Other Long Form')
240
+ form.add_instructions('Make the correct choices and provide the required information')
241
+ form.add_fixed("Your nickname is required.")
242
+ form.add_text_single('nickname', 'Nickname')
243
+ form.add_fixed
244
+ form.add_text_single('street', 'Street')
245
+ form.add_text_single('city', 'City')
246
+ form.add_text_single('state', 'State')
247
+ form.add_text_single('zip', 'Zip Code')
248
+ form.add_fixed("Your password is required.")
249
+ form.add_text_private('password', 'Password')
250
+ form.add_text_private('renter_password', 'Renter Password')
251
+ form.add_fixed("A haiku is required")
252
+ form.add_text_multi('haiku')
253
+ form.add_fixed("A limerick is required")
254
+ form.add_text_multi('limericck')
255
+ form.add_fixed("A story of at least 250 characters is required.")
256
+ form.add_text_multi('story', 'Your Story')
257
+ end
258
+ on(:submit) do
259
+ params[:data]
260
+ end
261
+ end
262
+
263
+ #.........................................................................................................
264
+ command 'form/no_title' do
265
+ AgentXmpp.logger.info "ACTION: no_title"
266
+ on(:execute) do |form|
267
+ form.add_instructions('Choose On or Off')
268
+ form.add_boolean('answer', 'On or Off please')
269
+ end
270
+ on(:submit) do
271
+ params[:data]
272
+ end
273
+ end
274
+
275
+ #.........................................................................................................
276
+ command 'form/no_instructions' do
277
+ AgentXmpp.logger.info "ACTION: no_instructions"
278
+ on(:execute) do |form|
279
+ form.add_title('Yes or No')
280
+ form.add_boolean('answer', 'Yes or No please')
281
+ end
282
+ on(:submit) do
283
+ params[:data]
284
+ end
285
+ end
286
+
287
+ #.........................................................................................................
288
+ command 'form/text_view_with_jids' do
289
+ AgentXmpp.logger.info "ACTION: text_view_with_jids"
290
+ on(:execute) do |form|
291
+ form.add_title('Account Information')
292
+ form.add_instructions('Enter and Account below and provide a description')
293
+ form.add_jid_single('jid', 'account JID')
294
+ form.add_text_multi('description', 'Description of Account')
295
+ end
296
+ on(:submit) do
297
+ params[:data]
298
+ end
299
+ end
300
+
301
+ #.........................................................................................................
302
+ command 'form/multiple_steps' do
303
+ AgentXmpp.logger.info "ACTION: multiple_steps"
304
+ on(:execute) do |form|
305
+ form.add_title('Account Features')
306
+ form.add_instructions('Enter and Account')
307
+ form.add_jid_single('jid', 'account JID')
308
+ end
309
+ on(:submit) do |form|
310
+ form.add_title("Account '#{params[:data]['jid']}'")
311
+ form.add_instructions('Enable/Disbale features')
312
+ form.add_boolean('idle_logout', 'On or Off please')
313
+ form.add_boolean('electrocution', 'Electrocute on login failure?')
314
+ form.add_text_multi('mod', 'Message of the day')
315
+ form.add_text_multi('warn', 'Warning message')
316
+ end
317
+ on(:submit) do
318
+ params_list.inject({}){|r,p| r.merge(p[:data])}
319
+ end
320
+ end
321
+
322
+
323
+ ##########################################################################################################
324
+ # chat messages
325
+ #.........................................................................................................
326
+ chat do
327
+ AgentXmpp.logger.info "CHAT MESSAGE: #{params[:from]}, #{params[:body]}"
328
+ params[:body].nil? ? 'what?' : params[:body].reverse
329
+ end
330
+
331
+ ##########################################################################################################
332
+ # pubsub events
333
+ #.........................................................................................................
334
+
335
+ #.........................................................................................................
336
+ # event 'troy@test.local', 'junk' do
337
+ # AgentXmpp.logger.info "EVENT: troy@test.local/junk"
338
+ # send_chat(:to=>params[:from], :body=>'got '+params[:data])
339
+ # end
@@ -0,0 +1,65 @@
1
+ ##############################################################################################################
2
+ require 'test_helper'
3
+
4
+ ##############################################################################################################
5
+ class TestApplicationMessageProcessing < Test::Unit::TestCase
6
+
7
+ #.........................................................................................................
8
+ def setup
9
+ @config = {'jid' => 'test@nowhere.com', 'roster' =>['dev@nowhere.com'], 'password' => 'nopass'}
10
+ @client = TestClient.new(@config)
11
+ AgentXmpp::Xmpp::IdGenerator.set_gen_id
12
+ test_init_roster(@client)
13
+ @delegate = @client.new_delegate
14
+ end
15
+
16
+ #.........................................................................................................
17
+ should "respond to a received message with agent version information if no chat route is specified" do
18
+ @client.receiving(ApplicationMessages.recv_message_chat(@client, 'dev@nowhere.com')).should \
19
+ respond_with(ApplicationMessages.send_message_chat(@client, 'dev@nowhere.com'))
20
+ end
21
+
22
+ #.........................................................................................................
23
+ should "respond to requests with scalars in jabber:x:data format" do
24
+ @client.receiving(ApplicationMessages.recv_iq_set_command_execute(@client, 'scalar', 'dev@nowhere.com')).should \
25
+ respond_with(ApplicationMessages.send_iq_result_command_x_data_scalar(@client, 'dev@nowhere.com'))
26
+ end
27
+
28
+ #.........................................................................................................
29
+ should "respond to requests with arrays of scalars in jabber:x:data format" do
30
+ @client.receiving(ApplicationMessages.recv_iq_set_command_execute(@client, 'scalar_array', 'dev@nowhere.com')).should \
31
+ respond_with(ApplicationMessages.send_iq_result_command_x_data_scalar_array(@client, 'dev@nowhere.com'))
32
+ end
33
+
34
+ #.........................................................................................................
35
+ should "respond to requests with hashes in jabber:x:data format" do
36
+ @client.receiving(ApplicationMessages.recv_iq_set_command_execute(@client, 'hash', 'dev@nowhere.com')).should \
37
+ respond_with(ApplicationMessages.send_iq_result_command_x_data_hash(@client, 'dev@nowhere.com'))
38
+ end
39
+
40
+ #.........................................................................................................
41
+ should "respond to requests with arrays of hashes in jabber:x:data format" do
42
+ @client.receiving(ApplicationMessages.recv_iq_set_command_execute(@client, 'array_hash', 'dev@nowhere.com')).should \
43
+ respond_with(ApplicationMessages.send_iq_result_command_x_data_array_hash(@client, 'dev@nowhere.com'))
44
+ end
45
+
46
+ #.........................................................................................................
47
+ should "respond to requests with hashes of arrays in jabber:x:data format" do
48
+ @client.receiving(ApplicationMessages.recv_iq_set_command_execute(@client, 'hash_array', 'dev@nowhere.com')).should \
49
+ respond_with(ApplicationMessages.send_iq_result_command_x_data_hash_array(@client, 'dev@nowhere.com'))
50
+ end
51
+
52
+ #.........................................................................................................
53
+ should "respond to requests with arrays of hashes of arrays in jabber:x:data format" do
54
+ @client.receiving(ApplicationMessages.recv_iq_set_command_execute(@client, 'array_hash_array', 'dev@nowhere.com')).should \
55
+ respond_with(ApplicationMessages.send_iq_result_command_x_data_array_hash_array(@client, 'dev@nowhere.com'))
56
+ end
57
+
58
+ #.........................................................................................................
59
+ should "return error if command node does not map to a route" do
60
+ @client.receiving(ApplicationMessages.recv_iq_set_command_execute(@client, 'no_route', 'dev@nowhere.com')).should \
61
+ respond_with(ApplicationMessages.send_error_command_routing(@client, 'no_route', 'dev@nowhere.com'))
62
+ end
63
+
64
+ end
65
+
@@ -0,0 +1,24 @@
1
+ ##############################################################################################################
2
+ require 'test_helper'
3
+
4
+ ##############################################################################################################
5
+ class TestErrors < Test::Unit::TestCase
6
+
7
+ #.........................................................................................................
8
+ def setup
9
+ @client = TestClient.new()
10
+ test_init_roster(@client)
11
+ @delegate = @client.new_delegate
12
+ @test = AgentXmpp::Xmpp::Jid.new('test@plan-b.ath.cx/home')
13
+ end
14
+
15
+ #.........................................................................................................
16
+ should "respond with feature-not-implemented when unsupported messages are received" do
17
+ @delegate.on_unsupported_message_method.should_not be_called
18
+ @client.receiving(ErrorMessages.recv_iq_error(@client, @test.to_s)).should \
19
+ respond_with(ErrorMessages.send_iq_error(@client, @test.to_s))
20
+ @delegate.on_unsupported_message_method.should be_called
21
+ end
22
+
23
+ end
24
+
@@ -0,0 +1,139 @@
1
+ ##############################################################################################################
2
+ require 'test_helper'
3
+
4
+ ##############################################################################################################
5
+ class TestPresenceManagement < Test::Unit::TestCase
6
+
7
+ #.........................................................................................................
8
+ def setup
9
+ @config = {'jid' => 'test@nowhere.com', 'roster' =>['dev@nowhere.com', 'troy@nowhere.com'], 'password' => 'nopass'}
10
+ @client = TestClient.new(@config)
11
+ test_init_roster(@client)
12
+ @delegate = @client.new_delegate
13
+ @home = AgentXmpp::Xmpp::Jid.new('troy@nowhere.com/home')
14
+ @work = AgentXmpp::Xmpp::Jid.new('troy@nowhere.com/work')
15
+ @noone = AgentXmpp::Xmpp::Jid.new('noone@nowhere.com/here')
16
+ end
17
+
18
+ ####------------------------------------------------------------------------------------------------------
19
+ context "on receipt of first presence message from jid in configured roster" do
20
+
21
+ #.........................................................................................................
22
+ setup do
23
+ AgentXmpp::Xmpp::IdGenerator.set_gen_id([1,2])
24
+ RosterItemModel.find_all_by_contact_jid(@home).should be_empty
25
+ @delegate.on_presence_method.should_not be_called
26
+ @client.receiving(PresenceMessages.recv_presence_available(@client, @home.to_s)).should \
27
+ respond_with(VersionDiscoveryMessages.send_iq_get_query_version(@client, @home.to_s), \
28
+ ServiceDiscoveryMessages.send_iq_get_query_discoinfo(@client, @home.to_s))
29
+ @delegate.on_presence_method.should be_called
30
+ AgentXmpp::Roster.find_by_jid(@home).should_not be_nil
31
+ end
32
+
33
+ #.........................................................................................................
34
+ should "create presence status entry in roster for resource and send client version request to jid" do
35
+ end
36
+
37
+ #.........................................................................................................
38
+ should "update roster item resource presence status to unavailble on receiving unavailable presence" do
39
+ @delegate = @client.new_delegate
40
+ @delegate.on_presence_unavailable_method.should_not be_called
41
+ AgentXmpp::Roster.find_by_jid(@home).type.should be_nil # nil presence type=available
42
+ @client.receiving(PresenceMessages.recv_presence_unavailable(@client, @home.to_s)).should not_respond
43
+ @delegate.on_presence_unavailable_method.should be_called
44
+ AgentXmpp::Roster.find_by_jid(@home).type.should be(:unavailable)
45
+ end
46
+
47
+ #.........................................................................................................
48
+ should "update existing roster item resource presence status from unavailble to availble on receiving available presence" do
49
+ @delegate = @client.new_delegate
50
+ @client.receiving(PresenceMessages.recv_presence_unavailable(@client, @home.to_s)).should not_respond
51
+ AgentXmpp::Xmpp::IdGenerator.set_gen_id([1,2])
52
+ AgentXmpp::Roster.find_by_jid(@home).type.should be(:unavailable)
53
+ @delegate.on_presence_method.should_not be_called
54
+ @client.receiving(PresenceMessages.recv_presence_available(@client, @home.to_s)).should \
55
+ respond_with(VersionDiscoveryMessages.send_iq_get_query_version(@client, @home.to_s), \
56
+ ServiceDiscoveryMessages.send_iq_get_query_discoinfo(@client, @home.to_s))
57
+ @delegate.on_presence_method.should be_called
58
+ AgentXmpp::Roster.find_by_jid(@home).type.should be_nil # nil presence type=available
59
+ end
60
+
61
+ #.........................................................................................................
62
+ should "maintain multiple presence status entries for multiple resources for a roster item" do
63
+ @delegate = @client.new_delegate
64
+ AgentXmpp::Xmpp::IdGenerator.set_gen_id([1,2])
65
+ @delegate.on_presence_method.should_not be_called
66
+ AgentXmpp::Roster.find_by_jid(@work).should be_nil
67
+ @client.receiving(PresenceMessages.recv_presence_available(@client, @work.to_s)).should \
68
+ respond_with(VersionDiscoveryMessages.send_iq_get_query_version(@client, @work.to_s), \
69
+ ServiceDiscoveryMessages.send_iq_get_query_discoinfo(@client, @work.to_s))
70
+ @delegate.on_presence_method.should be_called
71
+ AgentXmpp::Roster.find_by_jid(@work).should_not be_nil
72
+ AgentXmpp::Roster.find_by_jid(@home).should_not be_nil
73
+ end
74
+
75
+ end
76
+
77
+ #.........................................................................................................
78
+ should "create presence status for resource on receipt of self presence" do
79
+ RosterItemModel.find_all_by_contact_jid(@client.client.jid).should be_empty
80
+ @delegate.on_presence_method.should_not be_called
81
+ @client.receiving(PresenceMessages.recv_presence_self(@client)).should not_respond
82
+ @delegate.on_presence_method.should be_called
83
+ AgentXmpp::Roster.find_by_jid(@client.client.jid).should_not be_nil
84
+ end
85
+
86
+ #.........................................................................................................
87
+ should "ignore presence messages from jids not in configured roster" do
88
+ AgentXmpp::Contact.has_jid?(@noone).should be(false)
89
+ @delegate.on_presence_method.should_not be_called
90
+ @client.receiving(PresenceMessages.recv_presence_available(@client, @noone.to_s)).should not_respond
91
+ @delegate.on_presence_method.should be_called
92
+ AgentXmpp::Contact.has_jid?(@noone).should be(false)
93
+ end
94
+
95
+ #.........................................................................................................
96
+ should "accept subscription requests from jids which are in the configured roster" do
97
+ AgentXmpp::Contact.has_jid?(@home).should be(true)
98
+ @delegate.on_presence_subscribe_method.should_not be_called
99
+ @delegate.on_presence_subscribed_method.should_not be_called
100
+ @client.receiving(PresenceMessages.recv_presence_subscribe(@client, @home.bare.to_s)).should \
101
+ respond_with(PresenceMessages.send_presence_subscribed(@client, @home.bare.to_s))
102
+ @client.receiving(PresenceMessages.recv_presence_subscribed(@client, @home.bare.to_s)).should not_respond
103
+ @delegate.on_presence_subscribe_method.should be_called
104
+ @delegate.on_presence_subscribed_method.should be_called
105
+ AgentXmpp::Contact.has_jid?(@home).should be(true)
106
+ end
107
+
108
+ #.........................................................................................................
109
+ should "remove roster item with jid from configured roster when an unsubscribe resquest is recieved" do
110
+ AgentXmpp::Contact.has_jid?(@home).should be(true)
111
+ @delegate.on_presence_unsubscribed_method.should_not be_called
112
+ @client.receiving(PresenceMessages.recv_presence_unsubscribed(@client, @home.bare.to_s)).should \
113
+ respond_with(RosterMessages.send_iq_set_query_roster_remove(@client, @home.bare.to_s))
114
+ @client.receiving(RosterMessages.recv_iq_result_query_roster_ack(@client)).should not_respond
115
+ @delegate.on_presence_unsubscribed_method.should be_called
116
+ AgentXmpp::Contact.has_jid?(@home).should be(false)
117
+ end
118
+
119
+ #.........................................................................................................
120
+ should "do nothing when an unsubscribe resquest is recieved from a jid not in the configured roster" do
121
+ AgentXmpp::Contact.has_jid?(@noone).should be(false)
122
+ @delegate.on_presence_unsubscribed_method.should_not be_called
123
+ @client.receiving(PresenceMessages.recv_presence_unsubscribed(@client, @noone.bare.to_s)).should not_respond
124
+ @delegate.on_presence_unsubscribed_method.should be_called
125
+ AgentXmpp::Contact.has_jid?(@noone).should be(false)
126
+ end
127
+
128
+ #.........................................................................................................
129
+ should "decline subscription requests from jids which are not in the configured roster" do
130
+ AgentXmpp::Contact.has_jid?(@noone).should be(false)
131
+ @delegate.on_presence_subscribe_method.should_not be_called
132
+ @client.receiving(PresenceMessages.recv_presence_subscribe(@client, @noone.bare.to_s)).should \
133
+ respond_with(PresenceMessages.send_presence_unsubscribed(@client, @noone.bare.to_s))
134
+ @delegate.on_presence_subscribe_method.should be_called
135
+ AgentXmpp::Contact.has_jid?(@noone).should be(false)
136
+ end
137
+
138
+ end
139
+