shingara-blather 0.4.8

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 (100) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +162 -0
  3. data/examples/echo.rb +18 -0
  4. data/examples/execute.rb +16 -0
  5. data/examples/ping_pong.rb +37 -0
  6. data/examples/print_hierarchy.rb +76 -0
  7. data/examples/rosterprint.rb +14 -0
  8. data/examples/stream_only.rb +27 -0
  9. data/examples/xmpp4r/echo.rb +35 -0
  10. data/lib/blather/client/client.rb +310 -0
  11. data/lib/blather/client/dsl/pubsub.rb +170 -0
  12. data/lib/blather/client/dsl.rb +264 -0
  13. data/lib/blather/client.rb +87 -0
  14. data/lib/blather/core_ext/nokogiri.rb +40 -0
  15. data/lib/blather/errors/sasl_error.rb +43 -0
  16. data/lib/blather/errors/stanza_error.rb +107 -0
  17. data/lib/blather/errors/stream_error.rb +82 -0
  18. data/lib/blather/errors.rb +69 -0
  19. data/lib/blather/jid.rb +142 -0
  20. data/lib/blather/roster.rb +111 -0
  21. data/lib/blather/roster_item.rb +122 -0
  22. data/lib/blather/stanza/disco/disco_info.rb +176 -0
  23. data/lib/blather/stanza/disco/disco_items.rb +132 -0
  24. data/lib/blather/stanza/disco.rb +25 -0
  25. data/lib/blather/stanza/iq/query.rb +53 -0
  26. data/lib/blather/stanza/iq/roster.rb +179 -0
  27. data/lib/blather/stanza/iq.rb +138 -0
  28. data/lib/blather/stanza/message.rb +332 -0
  29. data/lib/blather/stanza/presence/status.rb +212 -0
  30. data/lib/blather/stanza/presence/subscription.rb +101 -0
  31. data/lib/blather/stanza/presence.rb +163 -0
  32. data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
  33. data/lib/blather/stanza/pubsub/create.rb +65 -0
  34. data/lib/blather/stanza/pubsub/errors.rb +18 -0
  35. data/lib/blather/stanza/pubsub/event.rb +123 -0
  36. data/lib/blather/stanza/pubsub/items.rb +103 -0
  37. data/lib/blather/stanza/pubsub/publish.rb +103 -0
  38. data/lib/blather/stanza/pubsub/retract.rb +92 -0
  39. data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
  40. data/lib/blather/stanza/pubsub/subscription.rb +134 -0
  41. data/lib/blather/stanza/pubsub/subscriptions.rb +81 -0
  42. data/lib/blather/stanza/pubsub/unsubscribe.rb +68 -0
  43. data/lib/blather/stanza/pubsub.rb +129 -0
  44. data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
  45. data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
  46. data/lib/blather/stanza/pubsub_owner.rb +51 -0
  47. data/lib/blather/stanza.rb +149 -0
  48. data/lib/blather/stream/client.rb +31 -0
  49. data/lib/blather/stream/component.rb +38 -0
  50. data/lib/blather/stream/features/resource.rb +63 -0
  51. data/lib/blather/stream/features/sasl.rb +187 -0
  52. data/lib/blather/stream/features/session.rb +44 -0
  53. data/lib/blather/stream/features/tls.rb +28 -0
  54. data/lib/blather/stream/features.rb +53 -0
  55. data/lib/blather/stream/parser.rb +102 -0
  56. data/lib/blather/stream.rb +231 -0
  57. data/lib/blather/xmpp_node.rb +218 -0
  58. data/lib/blather.rb +78 -0
  59. data/spec/blather/client/client_spec.rb +559 -0
  60. data/spec/blather/client/dsl/pubsub_spec.rb +462 -0
  61. data/spec/blather/client/dsl_spec.rb +143 -0
  62. data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
  63. data/spec/blather/errors/sasl_error_spec.rb +33 -0
  64. data/spec/blather/errors/stanza_error_spec.rb +129 -0
  65. data/spec/blather/errors/stream_error_spec.rb +108 -0
  66. data/spec/blather/errors_spec.rb +33 -0
  67. data/spec/blather/jid_spec.rb +87 -0
  68. data/spec/blather/roster_item_spec.rb +96 -0
  69. data/spec/blather/roster_spec.rb +103 -0
  70. data/spec/blather/stanza/discos/disco_info_spec.rb +226 -0
  71. data/spec/blather/stanza/discos/disco_items_spec.rb +148 -0
  72. data/spec/blather/stanza/iq/query_spec.rb +64 -0
  73. data/spec/blather/stanza/iq/roster_spec.rb +140 -0
  74. data/spec/blather/stanza/iq_spec.rb +45 -0
  75. data/spec/blather/stanza/message_spec.rb +132 -0
  76. data/spec/blather/stanza/presence/status_spec.rb +132 -0
  77. data/spec/blather/stanza/presence/subscription_spec.rb +105 -0
  78. data/spec/blather/stanza/presence_spec.rb +66 -0
  79. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  80. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  81. data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
  82. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  83. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  84. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  85. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  86. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  87. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  88. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
  89. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  90. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  91. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  92. data/spec/blather/stanza/pubsub_spec.rb +67 -0
  93. data/spec/blather/stanza_spec.rb +116 -0
  94. data/spec/blather/stream/client_spec.rb +1011 -0
  95. data/spec/blather/stream/component_spec.rb +95 -0
  96. data/spec/blather/stream/parser_spec.rb +145 -0
  97. data/spec/blather/xmpp_node_spec.rb +231 -0
  98. data/spec/fixtures/pubsub.rb +311 -0
  99. data/spec/spec_helper.rb +43 -0
  100. metadata +249 -0
@@ -0,0 +1,226 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
2
+
3
+ def disco_info_xml
4
+ <<-XML
5
+ <iq type='result'
6
+ from='romeo@montague.net/orchard'
7
+ to='juliet@capulet.com/balcony'
8
+ id='info4'>
9
+ <query xmlns='http://jabber.org/protocol/disco#info'>
10
+ <identity
11
+ category='client'
12
+ type='pc'
13
+ name='Gabber'/>
14
+ <feature var='jabber:iq:time'/>
15
+ <feature var='jabber:iq:version'/>
16
+ </query>
17
+ </iq>
18
+ XML
19
+ end
20
+
21
+ describe Blather::Stanza::Iq::DiscoInfo do
22
+ it 'registers itself' do
23
+ Blather::XMPPNode.class_from_registration(:query, 'http://jabber.org/protocol/disco#info').must_equal Blather::Stanza::Iq::DiscoInfo
24
+ end
25
+
26
+ it 'must be importable' do
27
+ doc = parse_stanza disco_info_xml
28
+ Blather::XMPPNode.import(doc.root).must_be_instance_of Blather::Stanza::Iq::DiscoInfo
29
+ end
30
+
31
+ it 'has a node attribute' do
32
+ n = Blather::Stanza::Iq::DiscoInfo.new nil, 'music', [], []
33
+ n.node.must_equal 'music'
34
+ n.node = :foo
35
+ n.node.must_equal 'foo'
36
+ end
37
+
38
+ it 'inherits a list of identities' do
39
+ n = parse_stanza disco_info_xml
40
+ r = Blather::Stanza::Iq::DiscoInfo.new.inherit n.root
41
+ r.identities.size.must_equal 1
42
+ r.identities.map { |i| i.class }.uniq.must_equal [Blather::Stanza::Iq::DiscoInfo::Identity]
43
+ end
44
+
45
+ it 'inherits a list of features' do
46
+ n = parse_stanza disco_info_xml
47
+ r = Blather::Stanza::Iq::DiscoInfo.new.inherit n.root
48
+ r.features.size.must_equal 2
49
+ r.features.map { |i| i.class }.uniq.must_equal [Blather::Stanza::Iq::DiscoInfo::Feature]
50
+ end
51
+
52
+ it 'is constructed properly' do
53
+ n = Blather::Stanza::Iq::DiscoInfo.new :get, '/path/to/node'
54
+ n.to = 'to@jid.com'
55
+ n.find("/iq[@to='to@jid.com' and @type='get' and @id='#{n.id}']/ns:query[@node='/path/to/node']", :ns => Blather::Stanza::Iq::DiscoInfo.registered_ns).wont_be_empty
56
+ end
57
+ end
58
+
59
+ describe 'Blather::Stanza::Iq::DiscoInfo identities' do
60
+ it 'takes a list of hashes for identities' do
61
+ ids = [
62
+ {:name => 'name', :type => 'type', :category => 'category'},
63
+ {:name => 'name1', :type => 'type1', :category => 'category1'},
64
+ ]
65
+
66
+ control = [ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category]),
67
+ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1])]
68
+
69
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, ids
70
+ di.identities.size.must_equal 2
71
+ di.identities.each { |i| control.include?(i).must_equal true }
72
+ end
73
+
74
+ it 'takes a list of Identity objects as identities' do
75
+ control = [ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category]),
76
+ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1])]
77
+
78
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, control
79
+ di.identities.size.must_equal 2
80
+ di.identities.each { |i| control.include?(i).must_equal true }
81
+ end
82
+
83
+ it 'takes a single hash as identity' do
84
+ control = [Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category])]
85
+
86
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, {:name => 'name', :type => 'type', :category => 'category'}
87
+ di.identities.size.must_equal 1
88
+ di.identities.each { |i| control.include?(i).must_equal true }
89
+ end
90
+
91
+ it 'takes a single identity object as identity' do
92
+ control = [Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category])]
93
+
94
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, control.first
95
+ di.identities.size.must_equal 1
96
+ di.identities.each { |i| control.include?(i).must_equal true }
97
+ end
98
+
99
+ it 'takes a mix of hashes and identity objects as identities' do
100
+ ids = [
101
+ {:name => 'name', :type => 'type', :category => 'category'},
102
+ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1]),
103
+ ]
104
+
105
+ control = [ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category]),
106
+ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1])]
107
+
108
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, ids
109
+ di.identities.size.must_equal 2
110
+ di.identities.each { |i| control.include?(i).must_equal true }
111
+ end
112
+ end
113
+
114
+ describe 'Blather::Stanza::Iq::DiscoInfo features' do
115
+ it 'takes a list of features as strings' do
116
+ features = %w[feature1 feature2 feature3]
117
+ control = features.map { |f| Blather::Stanza::Iq::DiscoInfo::Feature.new f }
118
+
119
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], features
120
+ di.features.size.must_equal 3
121
+ di.features.each { |f| control.include?(f).must_equal true }
122
+ end
123
+
124
+ it 'takes a list of features as Feature objects' do
125
+ features = %w[feature1 feature2 feature3]
126
+ control = features.map { |f| Blather::Stanza::Iq::DiscoInfo::Feature.new f }
127
+
128
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], control
129
+ di.features.size.must_equal 3
130
+ di.features.each { |f| control.include?(f).must_equal true }
131
+ end
132
+
133
+ it 'takes a single string' do
134
+ control = [Blather::Stanza::Iq::DiscoInfo::Feature.new('feature1')]
135
+
136
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], 'feature1'
137
+ di.features.size.must_equal 1
138
+ di.features.each { |f| control.include?(f).must_equal true }
139
+ end
140
+
141
+ it 'takes a single Feature object' do
142
+ control = [Blather::Stanza::Iq::DiscoInfo::Feature.new('feature1')]
143
+
144
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], control.first
145
+ di.features.size.must_equal 1
146
+ di.features.each { |f| control.include?(f).must_equal true }
147
+ end
148
+
149
+ it 'takes a mixed list of features as Feature objects and strings' do
150
+ features = %w[feature1 feature2 feature3]
151
+ control = features.map { |f| Blather::Stanza::Iq::DiscoInfo::Feature.new f }
152
+ features[1] = control[1]
153
+
154
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], features
155
+ di.features.size.must_equal 3
156
+ di.features.each { |f| control.include?(f).must_equal true }
157
+ end
158
+ end
159
+
160
+ describe Blather::Stanza::Iq::DiscoInfo::Identity do
161
+ it 'will auto-inherit nodes' do
162
+ n = parse_stanza "<identity name='Personal Events' type='pep' category='pubsub' node='publish' />"
163
+ i = Blather::Stanza::Iq::DiscoInfo::Identity.new n.root
164
+ i.name.must_equal 'Personal Events'
165
+ i.type.must_equal :pep
166
+ i.category.must_equal :pubsub
167
+ end
168
+
169
+ it 'has a category attribute' do
170
+ n = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
171
+ n.category.must_equal :cat
172
+ n.category = :foo
173
+ n.category.must_equal :foo
174
+ end
175
+
176
+ it 'has a type attribute' do
177
+ n = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
178
+ n.type.must_equal :type
179
+ n.type = :foo
180
+ n.type.must_equal :foo
181
+ end
182
+
183
+ it 'has a name attribute' do
184
+ n = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
185
+ n.name.must_equal 'name'
186
+ n.name = :foo
187
+ n.name.must_equal 'foo'
188
+ end
189
+
190
+ it 'raises an error if equality is sent a non DiscoInfo::Identity object' do
191
+ a = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
192
+ lambda { a == 'foo' }.must_raise RuntimeError
193
+ end
194
+
195
+ it 'can determine equality' do
196
+ a = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
197
+ a.must_equal Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
198
+ a.wont_equal Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[not-name not-type not-cat])
199
+ end
200
+ end
201
+
202
+ describe Blather::Stanza::Iq::DiscoInfo::Feature do
203
+ it 'will auto-inherit nodes' do
204
+ n = parse_stanza "<feature var='ipv6' />"
205
+ i = Blather::Stanza::Iq::DiscoInfo::Feature.new n.root
206
+ i.var.must_equal 'ipv6'
207
+ end
208
+
209
+ it 'has a var attribute' do
210
+ n = Blather::Stanza::Iq::DiscoInfo::Feature.new 'var'
211
+ n.var.must_equal 'var'
212
+ n.var = :foo
213
+ n.var.must_equal 'foo'
214
+ end
215
+
216
+ it 'raises an error if equality is sent a non DiscoInfo::Feature object' do
217
+ a = Blather::Stanza::Iq::DiscoInfo::Feature.new('var')
218
+ lambda { a == 'foo' }.must_raise RuntimeError
219
+ end
220
+
221
+ it 'can determine equality' do
222
+ a = Blather::Stanza::Iq::DiscoInfo::Feature.new('var')
223
+ a.must_equal Blather::Stanza::Iq::DiscoInfo::Feature.new('var')
224
+ a.wont_equal Blather::Stanza::Iq::DiscoInfo::Feature.new('not-var')
225
+ end
226
+ end
@@ -0,0 +1,148 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
2
+
3
+ def disco_items_xml
4
+ <<-XML
5
+ <iq type='result'
6
+ from='catalog.shakespeare.lit'
7
+ to='romeo@montague.net/orchard'
8
+ id='items2'>
9
+ <query xmlns='http://jabber.org/protocol/disco#items'>
10
+ <item jid='catalog.shakespeare.lit'
11
+ node='books'
12
+ name='Books by and about Shakespeare'/>
13
+ <item jid='catalog.shakespeare.lit'
14
+ node='clothing'
15
+ name='Wear your literary taste with pride'/>
16
+ <item jid='catalog.shakespeare.lit'
17
+ node='music'
18
+ name='Music from the time of Shakespeare'/>
19
+ </query>
20
+ </iq>
21
+ XML
22
+ end
23
+
24
+ describe Blather::Stanza::Iq::DiscoItems do
25
+ it 'registers itself' do
26
+ Blather::XMPPNode.class_from_registration(:query, 'http://jabber.org/protocol/disco#items').must_equal Blather::Stanza::Iq::DiscoItems
27
+ end
28
+
29
+ it 'must be importable' do
30
+ Blather::XMPPNode.import(parse_stanza(disco_items_xml).root).must_be_instance_of Blather::Stanza::Iq::DiscoItems
31
+ end
32
+
33
+ it 'is constructed properly' do
34
+ n = Blather::Stanza::Iq::DiscoItems.new :get, '/path/to/node'
35
+ n.to = 'to@jid.com'
36
+ n.find("/iq[@to='to@jid.com' and @type='get' and @id='#{n.id}']/ns:query[@node='/path/to/node']", :ns => Blather::Stanza::Iq::DiscoItems.registered_ns).wont_be_empty
37
+ end
38
+
39
+ it 'has a node attribute' do
40
+ n = Blather::Stanza::Iq::DiscoItems.new nil, 'music', []
41
+ n.node.must_equal 'music'
42
+ n.node = :foo
43
+ n.node.must_equal 'foo'
44
+ end
45
+
46
+ it 'inherits a list of identities' do
47
+ n = parse_stanza disco_items_xml
48
+ r = Blather::Stanza::Iq::DiscoItems.new.inherit n.root
49
+ r.items.size.must_equal 3
50
+ r.items.map { |i| i.class }.uniq.must_equal [Blather::Stanza::Iq::DiscoItems::Item]
51
+ end
52
+
53
+ it 'takes a list of hashes for items' do
54
+ items = [
55
+ {:jid => 'foo@bar/baz', :node => 'node', :name => 'name'},
56
+ {:jid => 'baz@foo/bar', :node => 'node1', :name => 'name1'},
57
+ ]
58
+
59
+ control = [ Blather::Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name]),
60
+ Blather::Stanza::Iq::DiscoItems::Item.new(*%w[baz@foo/bar node1 name1])]
61
+
62
+ di = Blather::Stanza::Iq::DiscoItems.new nil, nil, items
63
+ di.items.size.must_equal 2
64
+ di.items.each { |i| control.include?(i).must_equal true }
65
+ end
66
+
67
+ it 'takes a list of Item objects as items' do
68
+ control = [ Blather::Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name]),
69
+ Blather::Stanza::Iq::DiscoItems::Item.new(*%w[baz@foo/bar node1 name1])]
70
+
71
+ di = Blather::Stanza::Iq::DiscoItems.new nil, nil, control
72
+ di.items.size.must_equal 2
73
+ di.items.each { |i| control.include?(i).must_equal true }
74
+ end
75
+
76
+ it 'takes a single hash as identity' do
77
+ control = [Blather::Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name])]
78
+
79
+ di = Blather::Stanza::Iq::DiscoItems.new nil, nil, {:jid => 'foo@bar/baz', :node => 'node', :name => 'name'}
80
+ di.items.size.must_equal 1
81
+ di.items.each { |i| control.include?(i).must_equal true }
82
+ end
83
+
84
+ it 'takes a single identity object as identity' do
85
+ control = [Blather::Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name])]
86
+
87
+ di = Blather::Stanza::Iq::DiscoItems.new nil, nil, control.first
88
+ di.items.size.must_equal 1
89
+ di.items.each { |i| control.include?(i).must_equal true }
90
+ end
91
+
92
+ it 'takes a mix of hashes and identity objects as items' do
93
+ items = [
94
+ {:jid => 'foo@bar/baz', :node => 'node', :name => 'name'},
95
+ Blather::Stanza::Iq::DiscoItems::Item.new(*%w[baz@foo/bar node1 name1]),
96
+ ]
97
+
98
+ control = [ Blather::Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name]),
99
+ Blather::Stanza::Iq::DiscoItems::Item.new(*%w[baz@foo/bar node1 name1])]
100
+
101
+ di = Blather::Stanza::Iq::DiscoItems.new nil, nil, items
102
+ di.items.size.must_equal 2
103
+ di.items.each { |i| control.include?(i).must_equal true }
104
+ end
105
+ end
106
+
107
+ describe Blather::Stanza::Iq::DiscoItems::Item do
108
+ it 'will auto-inherit nodes' do
109
+ n = parse_stanza "<item jid='foo@bar/baz' node='music' name='Music from the time of Shakespeare' />"
110
+ i = Blather::Stanza::Iq::DiscoItems::Item.new n.root
111
+ i.jid.must_equal Blather::JID.new('foo@bar/baz')
112
+ i.node.must_equal 'music'
113
+ i.name.must_equal 'Music from the time of Shakespeare'
114
+ end
115
+
116
+ it 'has a jid attribute' do
117
+ n = Blather::Stanza::Iq::DiscoItems::Item.new 'foo@bar/baz'
118
+ n.jid.must_be_kind_of Blather::JID
119
+ n.jid.must_equal Blather::JID.new('foo@bar/baz')
120
+ n.jid = 'baz@foo/bar'
121
+ n.jid.must_equal Blather::JID.new('baz@foo/bar')
122
+ end
123
+
124
+ it 'has a node attribute' do
125
+ n = Blather::Stanza::Iq::DiscoItems::Item.new 'foo@bar/baz', 'music'
126
+ n.node.must_equal 'music'
127
+ n.node = 'book'
128
+ n.node.must_equal 'book'
129
+ end
130
+
131
+ it 'has a name attribute' do
132
+ n = Blather::Stanza::Iq::DiscoItems::Item.new 'foo@bar/baz', nil, 'Music from the time of Shakespeare'
133
+ n.name.must_equal 'Music from the time of Shakespeare'
134
+ n.name = 'Books by and about Shakespeare'
135
+ n.name.must_equal 'Books by and about Shakespeare'
136
+ end
137
+
138
+ it 'raises an error when compared against a non DiscoItems::Item' do
139
+ a = Blather::Stanza::Iq::DiscoItems::Item.new('foo@bar/baz')
140
+ lambda { a == 'test' }.must_raise RuntimeError
141
+ end
142
+
143
+ it 'can determine equality' do
144
+ a = Blather::Stanza::Iq::DiscoItems::Item.new('foo@bar/baz')
145
+ a.must_equal Blather::Stanza::Iq::DiscoItems::Item.new('foo@bar/baz')
146
+ a.wont_equal Blather::Stanza::Iq::DiscoItems::Item.new('not-foo@bar/baz')
147
+ end
148
+ end
@@ -0,0 +1,64 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
2
+
3
+ describe Blather::Stanza::Iq::Query do
4
+ it 'registers itself' do
5
+ Blather::XMPPNode.class_from_registration(:query, nil).must_equal Blather::Stanza::Iq::Query
6
+ end
7
+
8
+ it 'can be imported' do
9
+ doc = parse_stanza <<-XML
10
+ <iq from='juliet@example.com/balcony' type='set' id='roster_4'>
11
+ <query>
12
+ <item jid='nurse@example.com' subscription='remove'/>
13
+ </query>
14
+ </iq>
15
+ XML
16
+ Blather::XMPPNode.import(doc.root).must_be_instance_of Blather::Stanza::Iq::Query
17
+ end
18
+
19
+ it 'ensures a query node is present on create' do
20
+ query = Blather::Stanza::Iq::Query.new
21
+ query.xpath('query').wont_be_empty
22
+ end
23
+
24
+ it 'ensures a query node exists when calling #query' do
25
+ query = Blather::Stanza::Iq::Query.new
26
+ query.remove_child :query
27
+ query.xpath('query').must_be_empty
28
+
29
+ query.query.wont_be_nil
30
+ query.xpath('query').wont_be_empty
31
+ end
32
+
33
+ [:get, :set, :result, :error].each do |type|
34
+ it "can be set as \"#{type}\"" do
35
+ query = Blather::Stanza::Iq::Query.new type
36
+ query.type.must_equal type
37
+ end
38
+ end
39
+
40
+ it 'sets type to "result" on reply' do
41
+ query = Blather::Stanza::Iq::Query.new
42
+ query.type.must_equal :get
43
+ reply = query.reply.type.must_equal :result
44
+ end
45
+
46
+ it 'sets type to "result" on reply!' do
47
+ query = Blather::Stanza::Iq::Query.new
48
+ query.type.must_equal :get
49
+ query.reply!
50
+ query.type.must_equal :result
51
+ end
52
+
53
+ it 'can be registered under a namespace' do
54
+ class QueryNs < Blather::Stanza::Iq::Query; register :query_ns, nil, 'query:ns'; end
55
+ Blather::XMPPNode.class_from_registration(:query, 'query:ns').must_equal QueryNs
56
+ query_ns = QueryNs.new
57
+ query_ns.xpath('query').must_be_empty
58
+ query_ns.xpath('ns:query', :ns => 'query:ns').size.must_equal 1
59
+
60
+ query_ns.query
61
+ query_ns.query
62
+ query_ns.xpath('ns:query', :ns => 'query:ns').size.must_equal 1
63
+ end
64
+ end
@@ -0,0 +1,140 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
2
+
3
+ def roster_xml
4
+ <<-XML
5
+ <iq to='juliet@example.com/balcony' type='result' id='roster_1'>
6
+ <query xmlns='jabber:iq:roster'>
7
+ <item jid='romeo@example.net'
8
+ name='Romeo'
9
+ subscription='both'>
10
+ <group>Friends</group>
11
+ </item>
12
+ <item jid='mercutio@example.org'
13
+ name='Mercutio'
14
+ subscription='from'>
15
+ <group>Friends</group>
16
+ </item>
17
+ <item jid='benvolio@example.org'
18
+ name='Benvolio'
19
+ subscription='both'>
20
+ <group>Friends</group>
21
+ </item>
22
+ </query>
23
+ </iq>
24
+ XML
25
+ end
26
+
27
+ describe Blather::Stanza::Iq::Roster do
28
+ it 'registers itself' do
29
+ Blather::XMPPNode.class_from_registration(:query, 'jabber:iq:roster').must_equal Blather::Stanza::Iq::Roster
30
+ end
31
+
32
+ it 'ensures newly inherited items are RosterItem objects' do
33
+ n = parse_stanza roster_xml
34
+ r = Blather::Stanza::Iq::Roster.new.inherit n.root
35
+ r.items.map { |i| i.class }.uniq.must_equal [Blather::Stanza::Iq::Roster::RosterItem]
36
+ end
37
+
38
+ it 'can be created with #import' do
39
+ doc = parse_stanza roster_xml
40
+ Blather::XMPPNode.import(doc.root).must_be_instance_of Blather::Stanza::Iq::Roster
41
+ end
42
+ end
43
+
44
+ describe Blather::Stanza::Iq::Roster::RosterItem do
45
+ it 'can be initialized with just a Blather::JID' do
46
+ i = Blather::Stanza::Iq::Roster::RosterItem.new 'n@d/r'
47
+ i.jid.must_equal Blather::JID.new('n@d/r')
48
+ end
49
+
50
+ it 'can be initialized with a name' do
51
+ i = Blather::Stanza::Iq::Roster::RosterItem.new nil, 'foobar'
52
+ i.name.must_equal 'foobar'
53
+ end
54
+
55
+ it 'can be initialized with a subscription' do
56
+ i = Blather::Stanza::Iq::Roster::RosterItem.new nil, nil, :both
57
+ i.subscription.must_equal :both
58
+ end
59
+
60
+ it 'can be initialized with ask (subscription sub-type)' do
61
+ i = Blather::Stanza::Iq::Roster::RosterItem.new nil, nil, nil, :subscribe
62
+ i.ask.must_equal :subscribe
63
+ end
64
+
65
+ it 'can be initailized with a hash' do
66
+ control = { :jid => 'j@d/r',
67
+ :name => 'name',
68
+ :subscription => :both,
69
+ :ask => :subscribe }
70
+ i = Blather::Stanza::Iq::Roster::RosterItem.new control
71
+ i.jid.must_equal Blather::JID.new(control[:jid])
72
+ i.name.must_equal control[:name]
73
+ i.subscription.must_equal control[:subscription]
74
+ i.ask.must_equal control[:ask]
75
+ end
76
+
77
+ it 'inherits a node when initialized with one' do
78
+ n = Blather::XMPPNode.new 'item'
79
+ n[:jid] = 'n@d/r'
80
+ n[:subscription] = 'both'
81
+
82
+ i = Blather::Stanza::Iq::Roster::RosterItem.new n
83
+ i.jid.must_equal Blather::JID.new('n@d/r')
84
+ i.subscription.must_equal :both
85
+ end
86
+
87
+ it 'has a #groups helper that gives an array of groups' do
88
+ n = parse_stanza "<item jid='romeo@example.net' subscription='both'><group>foo</group><group>bar</group><group>baz</group></item>"
89
+ i = Blather::Stanza::Iq::Roster::RosterItem.new n.root
90
+ i.must_respond_to :groups
91
+ i.groups.sort.must_equal %w[bar baz foo]
92
+ end
93
+
94
+ it 'has a helper to set the groups' do
95
+ n = parse_stanza "<item jid='romeo@example.net' subscription='both'><group>foo</group><group>bar</group><group>baz</group></item>"
96
+ i = Blather::Stanza::Iq::Roster::RosterItem.new n.root
97
+ i.must_respond_to :groups=
98
+ i.groups.sort.must_equal %w[bar baz foo]
99
+ i.groups = %w[a b c]
100
+ i.groups.sort.must_equal %w[a b c]
101
+ end
102
+
103
+ it 'can be easily converted into a proper stanza' do
104
+ xml = "<item jid='romeo@example.net' subscription='both'><group>foo</group><group>bar</group><group>baz</group></item>"
105
+ n = parse_stanza xml
106
+ i = Blather::Stanza::Iq::Roster::RosterItem.new n.root
107
+ i.must_respond_to :to_stanza
108
+ s = i.to_stanza
109
+ s.must_be_kind_of Blather::Stanza::Iq::Roster
110
+ s.items.first.jid.must_equal Blather::JID.new('romeo@example.net')
111
+ s.items.first.groups.sort.must_equal %w[bar baz foo]
112
+ end
113
+
114
+ it 'has an "attr_accessor" for jid' do
115
+ i = Blather::Stanza::Iq::Roster::RosterItem.new
116
+ i.must_respond_to :jid
117
+ i.jid.must_be_nil
118
+ i.must_respond_to :jid=
119
+ i.jid = 'n@d/r'
120
+ i.jid.must_equal Blather::JID.new('n@d/r')
121
+ end
122
+
123
+ it 'has a name attribute' do
124
+ i = Blather::Stanza::Iq::Roster::RosterItem.new
125
+ i.name = 'name'
126
+ i.name.must_equal 'name'
127
+ end
128
+
129
+ it 'has a subscription attribute' do
130
+ i = Blather::Stanza::Iq::Roster::RosterItem.new
131
+ i.subscription = :both
132
+ i.subscription.must_equal :both
133
+ end
134
+
135
+ it 'has an ask attribute' do
136
+ i = Blather::Stanza::Iq::Roster::RosterItem.new
137
+ i.ask = :subscribe
138
+ i.ask.must_equal :subscribe
139
+ end
140
+ end
@@ -0,0 +1,45 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
2
+
3
+ describe Blather::Stanza::Iq do
4
+ it 'registers itself' do
5
+ Blather::XMPPNode.class_from_registration(:iq, nil).must_equal Blather::Stanza::Iq
6
+ end
7
+
8
+ it 'must be importable' do
9
+ doc = parse_stanza "<iq from='juliet@example.com/balcony' type='set' id='roster_4'></iq>"
10
+ Blather::XMPPNode.import(doc.root).must_be_instance_of Blather::Stanza::Iq
11
+ end
12
+
13
+ it 'creates a new Iq stanza defaulted as a get' do
14
+ Blather::Stanza::Iq.new.type.must_equal :get
15
+ end
16
+
17
+ it 'sets the id when created' do
18
+ Blather::Stanza::Iq.new.id.wont_be_nil
19
+ end
20
+
21
+ it 'creates a new Stanza::Iq object on import' do
22
+ Blather::Stanza::Iq.import(Blather::XMPPNode.new('iq')).must_be_kind_of Blather::Stanza::Iq
23
+ end
24
+
25
+ it 'creates a proper object based on its children' do
26
+ n = Blather::XMPPNode.new('iq')
27
+ n << Blather::XMPPNode.new('query', n.document)
28
+ Blather::Stanza::Iq.import(n).must_be_kind_of Blather::Stanza::Iq::Query
29
+ end
30
+
31
+ it 'ensures type is one of Stanza::Iq::VALID_TYPES' do
32
+ lambda { Blather::Stanza::Iq.new :invalid_type_name }.must_raise(Blather::ArgumentError)
33
+
34
+ Blather::Stanza::Iq::VALID_TYPES.each do |valid_type|
35
+ n = Blather::Stanza::Iq.new valid_type
36
+ n.type.must_equal valid_type
37
+ end
38
+ end
39
+
40
+ Blather::Stanza::Iq::VALID_TYPES.each do |valid_type|
41
+ it "provides a helper (#{valid_type}?) for type #{valid_type}" do
42
+ Blather::Stanza::Iq.new.must_respond_to :"#{valid_type}?"
43
+ end
44
+ end
45
+ end