agent_xmpp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+