jubjub 0.0.6 → 0.0.7
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.
- data/README.mdown +47 -1
- data/lib/jubjub/connection/xmpp_gateway/muc.rb +24 -36
- data/lib/jubjub/connection/xmpp_gateway/pubsub.rb +86 -116
- data/lib/jubjub/response/error.rb +33 -0
- data/lib/jubjub/response/proxy.rb +44 -0
- data/lib/jubjub/response/response.rb +33 -0
- data/lib/jubjub/response.rb +3 -0
- data/lib/jubjub/user.rb +1 -0
- data/spec/connection/xmpp_gateway_muc_spec.rb +3 -3
- data/spec/connection/xmpp_gateway_pubsub_spec.rb +8 -8
- data/spec/models/response_error_spec.rb +68 -0
- data/spec/models/response_proxy_spec.rb +143 -0
- data/spec/models/response_spec.rb +113 -0
- data/spec/support/matchers.rb +7 -0
- metadata +16 -4
data/README.mdown
CHANGED
@@ -181,11 +181,57 @@ Examples
|
|
181
181
|
u.pubsub.destroy('old_node', 'pubsub.jabber.ru', 'new_new')
|
182
182
|
=> true
|
183
183
|
|
184
|
+
Dealing with errors
|
185
|
+
===================
|
186
|
+
|
187
|
+
Every returned object from every action is really a Jubjub::Response::Proxy, which delegates to the Jubjub::Response and if the method doesn't exist there to the actual result. As Jubjub::Response only has a few methods it will usually just behaves like the actual result (say a Jubjub::Pubsub::Item). However, you can check what has really happened like so:
|
188
|
+
|
189
|
+
# Attempt to destroy a node that does not exist
|
190
|
+
u.pubsub.destroy('made up')
|
191
|
+
=> false
|
192
|
+
|
193
|
+
# False tells us destroy didn't succeed in this case, but it's not terribly helpful
|
194
|
+
# So we can use methods provided by the Jubjub::Response as well
|
195
|
+
|
196
|
+
response = u.pubsub.destroy('made up')
|
197
|
+
response.success?
|
198
|
+
=> false
|
199
|
+
|
200
|
+
response.stanza.to_s
|
201
|
+
=> "<?xml version=\"1.0\"?>\n<iq type=\"error\" id=\"blather0011\" from=\"pubsub.theo-template.local\" to=\"theozaurus@theo-template.local/42607076141308656900975361\" lang=\"en\">\n <pubsub xmlns=\"http://jabber.org/protocol/pubsub#owner\">\n <delete node=\"made up\"/>\n </pubsub>\n<error code=\"404\" type=\"cancel\"><item-not-found xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/></error></iq>\n"
|
202
|
+
|
203
|
+
# We can get the real result with no proxy sat in front
|
204
|
+
response.result
|
205
|
+
=> false
|
206
|
+
response.result.success?
|
207
|
+
NoMethodError: undefined method `success?' for false:FalseClass
|
208
|
+
from (irb):14
|
209
|
+
|
210
|
+
# We can also get an enhanced error object, Jubjub::Response::Error
|
211
|
+
response.error
|
212
|
+
=> #<Jubjub::Response::Error:0x101ef51f8 @stanza=#<Nokogiri::XML::Element:0x80f7a7bc name="error" attributes=[#<Nokogiri::XML::Attr:0x80f7a654 name="code" value="404">, #<Nokogiri::XML::Attr:0x80f7a640 name="type" value="cancel">] children=[#<Nokogiri::XML::Element:0x80f7a03c name="item-not-found" namespace=#<Nokogiri::XML::Namespace:0x80f79fb0 href="urn:ietf:params:xml:ns:xmpp-stanzas">>]>>
|
213
|
+
|
214
|
+
response.error.stanza.to_s
|
215
|
+
=> "<error code=\"404\" type=\"cancel\">\n <item-not-found xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>\n</error>"
|
216
|
+
|
217
|
+
response.error.condition
|
218
|
+
=> 'item-not-found'
|
219
|
+
|
220
|
+
response.error.type
|
221
|
+
=> 'cancel'
|
222
|
+
|
223
|
+
# If there is any error text this can also be extracted
|
224
|
+
response.error.text
|
225
|
+
=> 'Item not found'
|
226
|
+
|
227
|
+
|
228
|
+
The error `type` and error `condition` are the important factors. The `type` is defined in the [RFC 6121](http://xmpp.org/rfcs/rfc6120.html#stanzas-error-syntax), and helps decide whether the action should be attempted again. The `condition` provides a bit more detail, and will always be part of the [urn:ietf:params:xml:ns:xmpp-stanzas namespace](http://xmpp.org/schemas/stanzaerror.xsd).
|
229
|
+
|
184
230
|
TODO
|
185
231
|
====
|
186
232
|
|
187
|
-
- Error handling
|
188
233
|
- MUC user role and affiliation control
|
234
|
+
- Better exception handling
|
189
235
|
- Service discovery
|
190
236
|
- Operations that are not IQ based, such as rosters and two way messaging
|
191
237
|
- Other backends (for servers that are evented)
|
@@ -46,14 +46,10 @@ module Jubjub
|
|
46
46
|
|
47
47
|
presence full_jid
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
# Check for valid response
|
54
|
-
'//iq[@type="result"]'
|
55
|
-
).any?
|
56
|
-
Jubjub::Muc.new room_jid, nil, @connection if success
|
49
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
50
|
+
success = stanza.xpath( '/iq[@type="result"]' ).any?
|
51
|
+
Jubjub::Muc.new room_jid, nil, @connection if success
|
52
|
+
}.proxy_result
|
57
53
|
end
|
58
54
|
|
59
55
|
# http://xmpp.org/extensions/xep-0045.html#createroom-reserved
|
@@ -212,16 +208,14 @@ module Jubjub
|
|
212
208
|
end
|
213
209
|
|
214
210
|
presence full_jid
|
215
|
-
response = write(
|
216
|
-
# Request room configuration
|
217
|
-
request.to_xml
|
218
|
-
).xpath(
|
219
|
-
# Get fields
|
220
|
-
"//iq[@type='result']/muc_owner:query/x_data:x[@type='form']",
|
221
|
-
namespaces
|
222
|
-
)
|
223
211
|
|
224
|
-
Jubjub::
|
212
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
213
|
+
config = stanza.xpath(
|
214
|
+
"/iq[@type='result']/muc_owner:query/x_data:x[@type='form']",
|
215
|
+
namespaces
|
216
|
+
)
|
217
|
+
Jubjub::Muc::Configuration.new config if config
|
218
|
+
}.proxy_result
|
225
219
|
end
|
226
220
|
|
227
221
|
# http://xmpp.org/extensions/xep-0045.html#destroyroom
|
@@ -250,13 +244,9 @@ module Jubjub
|
|
250
244
|
}
|
251
245
|
end
|
252
246
|
|
253
|
-
write
|
254
|
-
|
255
|
-
|
256
|
-
).xpath(
|
257
|
-
# Check for valid response
|
258
|
-
'//iq[@type="result"]'
|
259
|
-
).any?
|
247
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
248
|
+
stanza.xpath( '/iq[@type="result"]' ).any?
|
249
|
+
}.proxy_result
|
260
250
|
end
|
261
251
|
|
262
252
|
# http://xmpp.org/extensions/xep-0045.html#disco-rooms
|
@@ -289,18 +279,16 @@ module Jubjub
|
|
289
279
|
xml.query_('xmlns' => 'http://jabber.org/protocol/disco#items')
|
290
280
|
}
|
291
281
|
end
|
292
|
-
|
293
|
-
write
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
Jubjub::Muc.new item.attr('jid'), item.attr('name'), @connection
|
303
|
-
}
|
282
|
+
|
283
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
284
|
+
stanza.xpath(
|
285
|
+
'/iq[@type="result"]/disco_items:query/disco_items:item',
|
286
|
+
namespaces
|
287
|
+
).map{|item|
|
288
|
+
# Convert to Jubjub object
|
289
|
+
Jubjub::Muc.new item.attr('jid'), item.attr('name'), @connection
|
290
|
+
}
|
291
|
+
}.proxy_result
|
304
292
|
end
|
305
293
|
|
306
294
|
# http://xmpp.org/extensions/xep-0045.html#exit
|
@@ -40,19 +40,17 @@ module Jubjub
|
|
40
40
|
xml.query_('xmlns' => namespaces['disco_items'])
|
41
41
|
}
|
42
42
|
end
|
43
|
-
|
44
|
-
write
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
Jubjub::Pubsub.new jid, node, @connection
|
55
|
-
}
|
43
|
+
|
44
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
45
|
+
stanza.xpath(
|
46
|
+
'/iq[@type="result"]/disco_items:query/disco_items:item',
|
47
|
+
namespaces
|
48
|
+
).map{|item|
|
49
|
+
jid = item.attr('jid')
|
50
|
+
node = item.attr('node')
|
51
|
+
Jubjub::Pubsub.new jid, node, @connection
|
52
|
+
}
|
53
|
+
}.proxy_result
|
56
54
|
end
|
57
55
|
|
58
56
|
# http://xmpp.org/extensions/xep-0060.html#owner-create-and-configure
|
@@ -93,14 +91,13 @@ module Jubjub
|
|
93
91
|
}
|
94
92
|
end
|
95
93
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
Jubjub::Pubsub.new jid, node, @connection if success
|
94
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
95
|
+
success = stanza.xpath(
|
96
|
+
# Pull out required parts
|
97
|
+
'/iq[@type="result"]'
|
98
|
+
).any?
|
99
|
+
Jubjub::Pubsub.new jid, node, @connection if success
|
100
|
+
}.proxy_result
|
104
101
|
end
|
105
102
|
|
106
103
|
# http://xmpp.org/extensions/xep-0060.html#owner-configure
|
@@ -144,16 +141,14 @@ module Jubjub
|
|
144
141
|
}
|
145
142
|
end
|
146
143
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
Jubjub::Pubsub::Configuration.new response if response
|
144
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
145
|
+
config = stanza.xpath(
|
146
|
+
# Pull out required parts
|
147
|
+
"/iq[@type='result']/pubsub_owner:pubsub/pubsub_owner:default/x_data:x[@type='form']",
|
148
|
+
namespaces
|
149
|
+
)
|
150
|
+
Jubjub::Pubsub::Configuration.new config if config
|
151
|
+
}.proxy_result
|
157
152
|
end
|
158
153
|
|
159
154
|
# http://xmpp.org/extensions/xep-0060.html#owner-delete
|
@@ -183,13 +178,9 @@ module Jubjub
|
|
183
178
|
}
|
184
179
|
end
|
185
180
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
).xpath(
|
190
|
-
# Pull out required parts
|
191
|
-
'//iq[@type="result"]'
|
192
|
-
).any?
|
181
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
182
|
+
stanza.xpath( '/iq[@type="result"]' ).any?
|
183
|
+
}.proxy_result
|
193
184
|
end
|
194
185
|
|
195
186
|
# http://xmpp.org/extensions/xep-0060.html#owner-purge
|
@@ -215,13 +206,9 @@ module Jubjub
|
|
215
206
|
}
|
216
207
|
end
|
217
208
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
).xpath(
|
222
|
-
# Pull out required parts
|
223
|
-
'//iq[@type="result"]'
|
224
|
-
).any?
|
209
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
210
|
+
stanza.xpath( '/iq[@type="result"]' ).any?
|
211
|
+
}.proxy_result
|
225
212
|
end
|
226
213
|
|
227
214
|
# http://xmpp.org/extensions/xep-0060.html#subscriber-subscribe
|
@@ -257,21 +244,19 @@ module Jubjub
|
|
257
244
|
}
|
258
245
|
}
|
259
246
|
end
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
Jubjub::Pubsub::Subscription.new jid, node, subscriber, subid, subscription, @connection
|
274
|
-
end
|
247
|
+
|
248
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
249
|
+
result = stanza.xpath(
|
250
|
+
'/iq[@type="result"]/pubsub:pubsub/pubsub:subscription',
|
251
|
+
namespaces
|
252
|
+
)
|
253
|
+
if result.any?
|
254
|
+
subscriber = Jubjub::Jid.new(result.first.attr('jid'))
|
255
|
+
subid = result.first.attr('subid')
|
256
|
+
subscription = result.first.attr('subscription')
|
257
|
+
Jubjub::Pubsub::Subscription.new jid, node, subscriber, subid, subscription, @connection
|
258
|
+
end
|
259
|
+
}.proxy_result
|
275
260
|
end
|
276
261
|
|
277
262
|
# http://xmpp.org/extensions/xep-0060.html#subscriber-unsubscribe
|
@@ -303,13 +288,9 @@ module Jubjub
|
|
303
288
|
}
|
304
289
|
end
|
305
290
|
|
306
|
-
write
|
307
|
-
|
308
|
-
|
309
|
-
).xpath(
|
310
|
-
# Pull out required parts
|
311
|
-
'//iq[@type="result"]'
|
312
|
-
).any?
|
291
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
292
|
+
stanza.xpath( '/iq[@type="result"]' ).any?
|
293
|
+
}.proxy_result
|
313
294
|
end
|
314
295
|
|
315
296
|
# http://xmpp.org/extensions/xep-0060.html#publisher-publish
|
@@ -357,19 +338,17 @@ module Jubjub
|
|
357
338
|
}
|
358
339
|
end
|
359
340
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
Jubjub::Pubsub::Item.new jid, node, item_id, data, @connection
|
372
|
-
end
|
341
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
342
|
+
result = stanza.xpath(
|
343
|
+
'/iq[@type="result"]/pubsub:pubsub/pubsub:publish/pubsub:item',
|
344
|
+
namespaces
|
345
|
+
)
|
346
|
+
if result.any?
|
347
|
+
item_id = result.first.attr('id')
|
348
|
+
data = request.doc.xpath("//pubsub:item/*", namespaces).to_s
|
349
|
+
Jubjub::Pubsub::Item.new jid, node, item_id, data, @connection
|
350
|
+
end
|
351
|
+
}.proxy_result
|
373
352
|
end
|
374
353
|
|
375
354
|
# http://xmpp.org/extensions/xep-0060.html#publisher-delete
|
@@ -400,10 +379,9 @@ module Jubjub
|
|
400
379
|
}
|
401
380
|
end
|
402
381
|
|
403
|
-
write
|
404
|
-
|
405
|
-
|
406
|
-
).xpath('//iq[@type="result"]').any?
|
382
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
383
|
+
stanza.xpath( '/iq[@type="result"]' ).any?
|
384
|
+
}.proxy_result
|
407
385
|
end
|
408
386
|
|
409
387
|
# http://xmpp.org/extensions/xep-0060.html#subscriber-retrieve
|
@@ -449,19 +427,17 @@ module Jubjub
|
|
449
427
|
}
|
450
428
|
}
|
451
429
|
end
|
452
|
-
|
453
|
-
write
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
Jubjub::Pubsub::Item.new jid, node, item_id, data, @connection
|
464
|
-
}
|
430
|
+
|
431
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
432
|
+
stanza.xpath(
|
433
|
+
'/iq[@type="result"]/pubsub:pubsub/pubsub:items/pubsub:item',
|
434
|
+
namespaces
|
435
|
+
).map{|item|
|
436
|
+
item_id = item.attr('id')
|
437
|
+
data = item.xpath('./*').to_xml
|
438
|
+
Jubjub::Pubsub::Item.new jid, node, item_id, data, @connection
|
439
|
+
}
|
440
|
+
}.proxy_result
|
465
441
|
end
|
466
442
|
|
467
443
|
|
@@ -496,18 +472,16 @@ module Jubjub
|
|
496
472
|
}
|
497
473
|
end
|
498
474
|
|
499
|
-
write
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
Jubjub::Pubsub::Affiliation.new pubsub_jid, pubsub_node, jid, affiliation, @connection
|
510
|
-
}
|
475
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
476
|
+
stanza.xpath(
|
477
|
+
'/iq[@type="result"]/pubsub_owner:pubsub/pubsub_owner:affiliations/pubsub_owner:affiliation',
|
478
|
+
namespaces
|
479
|
+
).map{|item|
|
480
|
+
jid = Jubjub::Jid.new item.attr('jid')
|
481
|
+
affiliation = item.attr('affiliation')
|
482
|
+
Jubjub::Pubsub::Affiliation.new pubsub_jid, pubsub_node, jid, affiliation, @connection
|
483
|
+
}
|
484
|
+
}.proxy_result
|
511
485
|
end
|
512
486
|
|
513
487
|
# http://xmpp.org/extensions/xep-0060.html#owner-affiliations-modify
|
@@ -541,13 +515,9 @@ module Jubjub
|
|
541
515
|
}
|
542
516
|
end
|
543
517
|
|
544
|
-
write
|
545
|
-
|
546
|
-
|
547
|
-
).xpath(
|
548
|
-
# Pull out required parts
|
549
|
-
'//iq[@type="result"]'
|
550
|
-
).any?
|
518
|
+
Jubjub::Response.new( write request.to_xml ){|stanza|
|
519
|
+
stanza.xpath( '/iq[@type="result"]' ).any?
|
520
|
+
}.proxy_result
|
551
521
|
end
|
552
522
|
|
553
523
|
private
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Jubjub
|
2
|
+
class Response
|
3
|
+
class Error
|
4
|
+
|
5
|
+
attr_reader :stanza
|
6
|
+
|
7
|
+
def initialize(xml)
|
8
|
+
@stanza = xml
|
9
|
+
end
|
10
|
+
|
11
|
+
def condition
|
12
|
+
@condition ||= begin
|
13
|
+
condition = @stanza.xpath('//error/ietf:*','ietf' => 'urn:ietf:params:xml:ns:xmpp-stanzas').first
|
14
|
+
condition.name if condition
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def type
|
19
|
+
@error_type ||= stanza.xpath('//error').first.attr('type')
|
20
|
+
end
|
21
|
+
|
22
|
+
def text(language=nil)
|
23
|
+
if language
|
24
|
+
xpath = "//error/text[@xml:lang='#{language}']"
|
25
|
+
else
|
26
|
+
xpath = "//error/text"
|
27
|
+
end
|
28
|
+
stanza.xpath(xpath).text
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Jubjub
|
2
|
+
class Response
|
3
|
+
class Proxy
|
4
|
+
|
5
|
+
# Turn proxy class into a 'BasicObject'
|
6
|
+
instance_methods.each do |m|
|
7
|
+
undef_method(m) if m.to_s !~ /(?:^__|^nil?$|^send$|^object_id$|^should$)/
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :proxy_primary, :proxy_secondary
|
11
|
+
|
12
|
+
def initialize(primary, secondary, primary_method)
|
13
|
+
@proxy_primary = primary
|
14
|
+
@proxy_secondary = secondary
|
15
|
+
@primary_method = primary_method
|
16
|
+
end
|
17
|
+
|
18
|
+
# We really want to show the secondary object
|
19
|
+
# as the primary is just a thin layer on top
|
20
|
+
def inspect
|
21
|
+
proxy_secondary.inspect
|
22
|
+
end
|
23
|
+
|
24
|
+
# Used to give away this is really a proxy
|
25
|
+
def proxy_class
|
26
|
+
Jubjub::Response::Proxy
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def method_missing(name, *args, &block)
|
32
|
+
# If the method exists on the primary use that
|
33
|
+
# unless it's the method name called to create the proxy from the primary, or is a standard object method
|
34
|
+
if name.to_s != @primary_method && (proxy_primary.public_methods - Object.public_methods).include?( name.to_s )
|
35
|
+
proxy_primary.send(name, *args, &block)
|
36
|
+
else
|
37
|
+
# Else use a method on the secondary
|
38
|
+
proxy_secondary.send(name, *args, &block)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Jubjub
|
2
|
+
|
3
|
+
class Response
|
4
|
+
|
5
|
+
attr_reader :stanza, :result
|
6
|
+
|
7
|
+
def initialize(xml,&block)
|
8
|
+
@stanza = xml
|
9
|
+
|
10
|
+
@result = nil
|
11
|
+
@result = yield stanza if block_given?
|
12
|
+
end
|
13
|
+
|
14
|
+
def proxy_result
|
15
|
+
# Allows some syntax sugar. We can chain from the result,
|
16
|
+
# but still get access to the response via the proxy
|
17
|
+
@proxy_result ||= Proxy.new self, result, 'proxy_result'
|
18
|
+
end
|
19
|
+
|
20
|
+
def success?
|
21
|
+
@success ||= stanza.xpath('/iq[@type="result"]|/iq[@type="set"]|/iq[@type="get"]').any?
|
22
|
+
end
|
23
|
+
|
24
|
+
def error
|
25
|
+
@errors ||= begin
|
26
|
+
s = stanza.at_xpath('/iq[@type="error"]/error')
|
27
|
+
Error.new s if s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/jubjub/user.rb
CHANGED
@@ -14,7 +14,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
14
14
|
|
15
15
|
it "return a Jubjub::Muc" do
|
16
16
|
@room = @connection.muc.create( Jubjub::Jid.new 'room@conference.theo-template.local/nick' )
|
17
|
-
@room.should
|
17
|
+
@room.should be_a_kind_of_response_proxied Jubjub::Muc
|
18
18
|
@room.jid.should == Jubjub::Jid.new( 'room@conference.theo-template.local' )
|
19
19
|
end
|
20
20
|
|
@@ -32,7 +32,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
32
32
|
@config = Jubjub::Muc::Configuration.new("allow_query_users" => { :type => "boolean", :value => "1", :label => "Allow users to query other users" })
|
33
33
|
|
34
34
|
@room = @connection.muc.create( Jubjub::Jid.new( 'room@conference.theo-template.local/nick' ), @config )
|
35
|
-
@room.should
|
35
|
+
@room.should be_a_kind_of_response_proxied Jubjub::Muc
|
36
36
|
@room.jid.should == Jubjub::Jid.new( 'room@conference.theo-template.local' )
|
37
37
|
end
|
38
38
|
|
@@ -104,7 +104,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
104
104
|
|
105
105
|
it "return an array of Jubjub::Muc" do
|
106
106
|
list = @connection.muc.list( Jubjub::Jid.new 'conference.theo-template.local' )
|
107
|
-
list.should
|
107
|
+
list.should be_a_kind_of_response_proxied Array
|
108
108
|
|
109
109
|
list.size.should eql(2)
|
110
110
|
list[0].should be_a_kind_of Jubjub::Muc
|
@@ -15,7 +15,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
15
15
|
it "return a Jubjub::Pubsub" do
|
16
16
|
@pubsub = @connection.pubsub.create 'pubsub.theo-template.local', 'node_1'
|
17
17
|
|
18
|
-
@pubsub.should
|
18
|
+
@pubsub.should be_a_kind_of_response_proxied Jubjub::Pubsub
|
19
19
|
@pubsub.jid.should == Jubjub::Jid.new('pubsub.theo-template.local')
|
20
20
|
@pubsub.node.should == 'node_1'
|
21
21
|
end
|
@@ -82,7 +82,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
82
82
|
|
83
83
|
config = @connection.pubsub.default_configuration 'pubsub.theo-template.local'
|
84
84
|
|
85
|
-
config.should
|
85
|
+
config.should be_a_kind_of_response_proxied Jubjub::Pubsub::Configuration
|
86
86
|
config.should == Jubjub::Pubsub::Configuration.new( expected_config )
|
87
87
|
end
|
88
88
|
end
|
@@ -130,7 +130,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
130
130
|
|
131
131
|
it "return an array of Jubjub::Muc" do
|
132
132
|
list = @connection.pubsub.list 'pubsub.theo-template.local'
|
133
|
-
list.should
|
133
|
+
list.should be_a_kind_of_response_proxied Array
|
134
134
|
|
135
135
|
list.size.should eql(2)
|
136
136
|
list[0].should be_a_kind_of Jubjub::Pubsub
|
@@ -173,7 +173,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
173
173
|
it "return a Jubjub::Pubsub::Subscription" do
|
174
174
|
@subscription = @connection.pubsub.subscribe( 'pubsub.theo-template.local', 'node_1' )
|
175
175
|
|
176
|
-
@subscription.should
|
176
|
+
@subscription.should be_a_kind_of_response_proxied Jubjub::Pubsub::Subscription
|
177
177
|
@subscription.jid.should == Jubjub::Jid.new('pubsub.theo-template.local')
|
178
178
|
@subscription.node.should == 'node_1'
|
179
179
|
@subscription.subscriber.should == @jid
|
@@ -239,7 +239,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
239
239
|
|
240
240
|
it "should return a Jubjub::Pubsub::Item" do
|
241
241
|
i = @connection.pubsub.publish 'pubsub.theo-template.local', 'node_1', Jubjub::DataForm.new, '123'
|
242
|
-
i.should
|
242
|
+
i.should be_a_kind_of_response_proxied Jubjub::Pubsub::Item
|
243
243
|
i.item_id.should == '123'
|
244
244
|
i.data.should == "<x xmlns=\"jabber:x:data\" type=\"submit\"/>"
|
245
245
|
end
|
@@ -252,7 +252,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
252
252
|
it "should return a Jubjub::Pubsub::Item" do
|
253
253
|
item = "<x xmlns=\"jabber:x:data\" type=\"submit\"><field var=\"foo\"><value>true</value></field></x>"
|
254
254
|
i = @connection.pubsub.publish 'pubsub.theo-template.local', 'node_1', item
|
255
|
-
i.should
|
255
|
+
i.should be_a_kind_of_response_proxied Jubjub::Pubsub::Item
|
256
256
|
i.item_id.should be_a_kind_of String
|
257
257
|
i.data.should == "<x xmlns=\"jabber:x:data\" type=\"submit\">\n <field var=\"foo\">\n <value>true</value>\n </field>\n</x>"
|
258
258
|
end
|
@@ -264,7 +264,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
264
264
|
|
265
265
|
it "should return a Jubjub::Pubsub::Item" do
|
266
266
|
i = @connection.pubsub.publish 'pubsub.theo-template.local', 'node_1', Jubjub::DataForm.new({ :foo => {:type => "boolean", :value => true }})
|
267
|
-
i.should
|
267
|
+
i.should be_a_kind_of_response_proxied Jubjub::Pubsub::Item
|
268
268
|
i.item_id.should be_a_kind_of String
|
269
269
|
i.data.should == "<x xmlns=\"jabber:x:data\" type=\"submit\">\n <field var=\"foo\">\n <value>true</value>\n </field>\n</x>"
|
270
270
|
end
|
@@ -292,7 +292,7 @@ describe Jubjub::Connection::XmppGateway do
|
|
292
292
|
end
|
293
293
|
|
294
294
|
it "should return false when not successful" do
|
295
|
-
@connection.pubsub.retract( 'pubsub.theo-template.local', 'node_pubsub_retract', "wibble" ).should
|
295
|
+
@connection.pubsub.retract( 'pubsub.theo-template.local', 'node_pubsub_retract', "wibble" ).should equal(false)
|
296
296
|
end
|
297
297
|
|
298
298
|
after do
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Jubjub::Response::Error do
|
4
|
+
|
5
|
+
describe 'creating' do
|
6
|
+
|
7
|
+
it 'should take a stanza' do
|
8
|
+
xml = Nokogiri::XML::Document.parse "<error type='cancel'><feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error>"
|
9
|
+
|
10
|
+
response = Jubjub::Response::Error.new xml
|
11
|
+
|
12
|
+
response.stanza.should == xml
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'instance method' do
|
18
|
+
|
19
|
+
describe 'condition' do
|
20
|
+
it 'should return a "urn:ietf:params:xml:ns:xmpp-stanzas" error condition' do
|
21
|
+
xml = Nokogiri::XML::Document.parse "<error><bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'></error>"
|
22
|
+
Jubjub::Response::Error.new( xml ).condition.should == "bad-request"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should return nil if unknown' do
|
26
|
+
xml = Nokogiri::XML::Document.parse "<error><text>Something went wrong</text><error/>"
|
27
|
+
Jubjub::Response::Error.new( xml ).condition.should equal(nil)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'type' do
|
32
|
+
it 'should return nil if no error type available' do
|
33
|
+
xml = Nokogiri::XML::Document.parse "<error/>"
|
34
|
+
Jubjub::Response::Error.new( xml ).type.should equal(nil)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should return value errors present' do
|
38
|
+
xml = Nokogiri::XML::Document.parse "<error type='cancel'/>"
|
39
|
+
Jubjub::Response::Error.new( xml ).type.should == 'cancel'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'text' do
|
44
|
+
it 'should return empty string if no text is available' do
|
45
|
+
xml = Nokogiri::XML::Document.parse "<error type='cancel'/>"
|
46
|
+
Jubjub::Response::Error.new( xml ).text.should == ""
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should return the text if available' do
|
50
|
+
xml = Nokogiri::XML::Document.parse "<error type='cancel'><text>Hello!</text></error>"
|
51
|
+
Jubjub::Response::Error.new( xml ).text.should == "Hello!"
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should return all text if available if multiple locales available' do
|
55
|
+
xml = Nokogiri::XML::Document.parse "<error type='cancel'><text xml:lang='en'>Hello!</text><text xml:lang='fr'>Bonjour!</text></error>"
|
56
|
+
Jubjub::Response::Error.new( xml ).text.should == "Hello!Bonjour!"
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should return the text in the correct locale if language specified' do
|
60
|
+
xml = Nokogiri::XML::Document.parse "<error type='cancel'><text xml:lang='en'>Hello!</text><text xml:lang='fr'>Bonjour!</text></error>"
|
61
|
+
Jubjub::Response::Error.new( xml ).text('fr').should == "Bonjour!"
|
62
|
+
Jubjub::Response::Error.new( xml ).text('en').should == "Hello!"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
describe Jubjub::Response::Proxy do
|
2
|
+
|
3
|
+
describe "creating" do
|
4
|
+
|
5
|
+
it "should require proxy_primary, proxy_secondary and public_method" do
|
6
|
+
primary = "String"
|
7
|
+
secondary = ["Array"]
|
8
|
+
|
9
|
+
p = Jubjub::Response::Proxy.new primary, secondary, "to_s"
|
10
|
+
|
11
|
+
p.proxy_primary.should equal(primary)
|
12
|
+
p.proxy_secondary.should equal(secondary)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "proxied methods" do
|
18
|
+
|
19
|
+
before do
|
20
|
+
@primary_class = Class.new do
|
21
|
+
def abc() end
|
22
|
+
def efg() end
|
23
|
+
def xyz() end
|
24
|
+
end
|
25
|
+
|
26
|
+
@secondary_class = Class.new do
|
27
|
+
def abc() end # Same as primary
|
28
|
+
def efg() end # Same as primary
|
29
|
+
def cba() end # Does not exist on primary
|
30
|
+
end
|
31
|
+
|
32
|
+
@primary = @primary_class.new
|
33
|
+
@secondary = @secondary_class.new
|
34
|
+
end
|
35
|
+
|
36
|
+
subject { Jubjub::Response::Proxy.new @primary, @secondary, 'efg' }
|
37
|
+
|
38
|
+
describe "that exist on proxy_primary" do
|
39
|
+
|
40
|
+
it "should not defer the primary_method" do
|
41
|
+
@primary.should_receive(:efg).never
|
42
|
+
|
43
|
+
subject.efg
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should not defer methods that belong to Object.public_methods" do
|
47
|
+
@primary.should_receive(:class).never
|
48
|
+
|
49
|
+
subject.class
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should defer to the proxy_primary" do
|
53
|
+
@primary.should_receive(:abc)
|
54
|
+
|
55
|
+
subject.abc
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "that don't defer to proxy_primary" do
|
61
|
+
|
62
|
+
it "should defer to proxy_secondary" do
|
63
|
+
@secondary.should_receive(:cba)
|
64
|
+
|
65
|
+
subject.cba
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should defer Object.public_methods to proxy_secondary" do
|
69
|
+
@secondary.should_receive(:class)
|
70
|
+
|
71
|
+
subject.class
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should defer to proxy_secondary if primary_method" do
|
75
|
+
@secondary.should_receive(:efg)
|
76
|
+
|
77
|
+
subject.efg
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should blow up if it doesn't exist on proxy_secondary either" do
|
81
|
+
expect {
|
82
|
+
subject.explode
|
83
|
+
}.to raise_error(NoMethodError,"undefined method `explode' for #{@secondary.inspect}")
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "instance method" do
|
91
|
+
|
92
|
+
describe "inspect" do
|
93
|
+
|
94
|
+
it "should really inspect proxy_secondary" do
|
95
|
+
# The proxy_primary is just a thin layer over the top of the proxy_secondary
|
96
|
+
# So make sure inspect shows us the proxy_secondary
|
97
|
+
primary = "String"
|
98
|
+
secondary = ["Array"]
|
99
|
+
|
100
|
+
p = Jubjub::Response::Proxy.new primary, secondary, "to_s"
|
101
|
+
|
102
|
+
p.inspect.should == secondary.inspect
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "proxy_primary" do
|
108
|
+
|
109
|
+
it "should return the proxy_primary object" do
|
110
|
+
primary = "p"
|
111
|
+
|
112
|
+
proxy = Jubjub::Response::Proxy.new primary, "s", "to_s"
|
113
|
+
|
114
|
+
proxy.proxy_primary.should equal(primary)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "proxy_secondary" do
|
120
|
+
|
121
|
+
it "should return the proxy_secondary object" do
|
122
|
+
secondary = "p"
|
123
|
+
|
124
|
+
proxy = Jubjub::Response::Proxy.new "p", secondary, "to_s"
|
125
|
+
|
126
|
+
proxy.proxy_secondary.should equal(secondary)
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "proxy_class" do
|
132
|
+
|
133
|
+
it "should return Jubjub::Response::Proxy" do
|
134
|
+
p = Jubjub::Response::Proxy.new "p", "s", "to_s"
|
135
|
+
|
136
|
+
p.proxy_class.should equal(Jubjub::Response::Proxy)
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Jubjub::Response do
|
4
|
+
|
5
|
+
describe 'creating' do
|
6
|
+
|
7
|
+
it 'should take a stanza' do
|
8
|
+
stanza = xml_fixture 'dataform_1'
|
9
|
+
|
10
|
+
response = Jubjub::Response.new stanza
|
11
|
+
|
12
|
+
response.stanza.should == stanza
|
13
|
+
response.result.should == nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should take a block to define result' do
|
17
|
+
stanza = xml_fixture 'dataform_1'
|
18
|
+
|
19
|
+
namespaces = {
|
20
|
+
'commands' => 'http://jabber.org/protocol/commands',
|
21
|
+
'x_data' => 'jabber:x:data'
|
22
|
+
}
|
23
|
+
|
24
|
+
response = Jubjub::Response.new( stanza ) do |s|
|
25
|
+
s.xpath(
|
26
|
+
"//iq[@type='result']/commands:command/x_data:x[@type='form']/x_data:instructions",
|
27
|
+
namespaces
|
28
|
+
).text
|
29
|
+
end
|
30
|
+
|
31
|
+
response.result.should == 'Fill out this form to configure your new bot!'
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'instance method' do
|
37
|
+
|
38
|
+
describe 'result' do
|
39
|
+
|
40
|
+
before { @stanza = xml_fixture 'dataform_1' }
|
41
|
+
|
42
|
+
it 'should return result of block used in initialization if specified' do
|
43
|
+
Jubjub::Response.new( @stanza ){ "Result" }.result.should == "Result"
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should return nil if no block provided' do
|
47
|
+
Jubjub::Response.new( @stanza ).result.should == nil
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'proxy_result' do
|
53
|
+
|
54
|
+
before { @stanza = xml_fixture 'dataform_1' }
|
55
|
+
|
56
|
+
it 'should return proxy of result' do
|
57
|
+
result = "Result"
|
58
|
+
Jubjub::Response.new( @stanza ){ result }.proxy_result.should be_a_kind_of_response_proxied result.class
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'success?' do
|
64
|
+
it 'should return true when stanza is iq[@type="get"]' do
|
65
|
+
xml = Nokogiri::XML::Document.parse "<iq type='get'/>"
|
66
|
+
Jubjub::Response.new( xml ).success?.should equal(true)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should return true when stanza is iq[@type="result"]' do
|
70
|
+
xml = Nokogiri::XML::Document.parse "<iq type='result'/>"
|
71
|
+
Jubjub::Response.new( xml ).success?.should equal(true)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should return true when stanza is iq[@type="set"]' do
|
75
|
+
xml = Nokogiri::XML::Document.parse "<iq type='set'/>"
|
76
|
+
Jubjub::Response.new( xml ).success?.should equal(true)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should return false when stanza is iq[@type="error"]' do
|
80
|
+
xml = Nokogiri::XML::Document.parse "<iq type='error'/>"
|
81
|
+
Jubjub::Response.new( xml ).success?.should equal(false)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should not look at child iq elements' do
|
85
|
+
xml = Nokogiri::XML::Document.parse "<totally><wrong><iq type='result'/></wrong></totally>"
|
86
|
+
Jubjub::Response.new( xml ).success?.should equal(false)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should return false when stanza is nonsensical' do
|
90
|
+
xml = Nokogiri::XML::Document.parse "<presence/>"
|
91
|
+
Jubjub::Response.new( xml ).success?.should equal(false)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'error' do
|
96
|
+
|
97
|
+
it 'should return Jubjub::Response:Error object if error present' do
|
98
|
+
xml = Nokogiri::XML::Document.parse "<iq type='error'><error><policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'></error></iq>"
|
99
|
+
r = Jubjub::Response.new( xml )
|
100
|
+
r.error.should be_a Jubjub::Response::Error
|
101
|
+
r.error.condition.should == "policy-violation"
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should return nil if error is not present' do
|
105
|
+
xml = Nokogiri::XML::Document.parse "<iq type='set'/>"
|
106
|
+
Jubjub::Response.new( xml ).error.should be_nil
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jubjub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 7
|
10
|
+
version: 0.0.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Theo Cushion
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-06-
|
18
|
+
date: 2011-06-21 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -119,6 +119,10 @@ files:
|
|
119
119
|
- lib/jubjub/pubsub/pubsub.rb
|
120
120
|
- lib/jubjub/pubsub/subscription.rb
|
121
121
|
- lib/jubjub/pubsub.rb
|
122
|
+
- lib/jubjub/response/error.rb
|
123
|
+
- lib/jubjub/response/proxy.rb
|
124
|
+
- lib/jubjub/response/response.rb
|
125
|
+
- lib/jubjub/response.rb
|
122
126
|
- lib/jubjub/user.rb
|
123
127
|
- lib/jubjub.rb
|
124
128
|
- LICENSE
|
@@ -162,8 +166,12 @@ files:
|
|
162
166
|
- spec/models/pubsub_item_spec.rb
|
163
167
|
- spec/models/pubsub_spec.rb
|
164
168
|
- spec/models/pubsub_subscription_spec.rb
|
169
|
+
- spec/models/response_error_spec.rb
|
170
|
+
- spec/models/response_proxy_spec.rb
|
171
|
+
- spec/models/response_spec.rb
|
165
172
|
- spec/spec_helper.rb
|
166
173
|
- spec/support/helpers.rb
|
174
|
+
- spec/support/matchers.rb
|
167
175
|
- spec/support/shared_examples.rb
|
168
176
|
- .rspec
|
169
177
|
- .infinity_test
|
@@ -243,8 +251,12 @@ test_files:
|
|
243
251
|
- spec/models/pubsub_item_spec.rb
|
244
252
|
- spec/models/pubsub_spec.rb
|
245
253
|
- spec/models/pubsub_subscription_spec.rb
|
254
|
+
- spec/models/response_error_spec.rb
|
255
|
+
- spec/models/response_proxy_spec.rb
|
256
|
+
- spec/models/response_spec.rb
|
246
257
|
- spec/spec_helper.rb
|
247
258
|
- spec/support/helpers.rb
|
259
|
+
- spec/support/matchers.rb
|
248
260
|
- spec/support/shared_examples.rb
|
249
261
|
- .rspec
|
250
262
|
- .infinity_test
|