tp-blather 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. data/.autotest +13 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +8 -0
  6. data/CHANGELOG.md +249 -0
  7. data/Gemfile +4 -0
  8. data/Guardfile +5 -0
  9. data/LICENSE +22 -0
  10. data/README.md +413 -0
  11. data/Rakefile +20 -0
  12. data/TODO.md +2 -0
  13. data/blather.gemspec +51 -0
  14. data/examples/certs/README +20 -0
  15. data/examples/certs/ca-bundle.crt +3987 -0
  16. data/examples/echo.rb +19 -0
  17. data/examples/execute.rb +17 -0
  18. data/examples/ping_pong.rb +38 -0
  19. data/examples/print_hierarchy.rb +77 -0
  20. data/examples/rosterprint.rb +15 -0
  21. data/examples/stream_only.rb +28 -0
  22. data/examples/trusted_echo.rb +21 -0
  23. data/examples/xmpp4r/echo.rb +36 -0
  24. data/lib/blather.rb +112 -0
  25. data/lib/blather/cert_store.rb +53 -0
  26. data/lib/blather/client.rb +95 -0
  27. data/lib/blather/client/client.rb +345 -0
  28. data/lib/blather/client/dsl.rb +320 -0
  29. data/lib/blather/client/dsl/pubsub.rb +174 -0
  30. data/lib/blather/core_ext/eventmachine.rb +125 -0
  31. data/lib/blather/core_ext/ipaddr.rb +20 -0
  32. data/lib/blather/errors.rb +69 -0
  33. data/lib/blather/errors/sasl_error.rb +44 -0
  34. data/lib/blather/errors/stanza_error.rb +110 -0
  35. data/lib/blather/errors/stream_error.rb +84 -0
  36. data/lib/blather/file_transfer.rb +107 -0
  37. data/lib/blather/file_transfer/ibb.rb +68 -0
  38. data/lib/blather/file_transfer/s5b.rb +114 -0
  39. data/lib/blather/jid.rb +141 -0
  40. data/lib/blather/roster.rb +118 -0
  41. data/lib/blather/roster_item.rb +146 -0
  42. data/lib/blather/stanza.rb +167 -0
  43. data/lib/blather/stanza/disco.rb +32 -0
  44. data/lib/blather/stanza/disco/capabilities.rb +161 -0
  45. data/lib/blather/stanza/disco/disco_info.rb +205 -0
  46. data/lib/blather/stanza/disco/disco_items.rb +134 -0
  47. data/lib/blather/stanza/iq.rb +144 -0
  48. data/lib/blather/stanza/iq/command.rb +339 -0
  49. data/lib/blather/stanza/iq/ibb.rb +86 -0
  50. data/lib/blather/stanza/iq/ping.rb +50 -0
  51. data/lib/blather/stanza/iq/query.rb +53 -0
  52. data/lib/blather/stanza/iq/roster.rb +185 -0
  53. data/lib/blather/stanza/iq/s5b.rb +208 -0
  54. data/lib/blather/stanza/iq/si.rb +415 -0
  55. data/lib/blather/stanza/iq/vcard.rb +149 -0
  56. data/lib/blather/stanza/message.rb +428 -0
  57. data/lib/blather/stanza/message/muc_user.rb +119 -0
  58. data/lib/blather/stanza/muc/muc_user_base.rb +54 -0
  59. data/lib/blather/stanza/presence.rb +172 -0
  60. data/lib/blather/stanza/presence/c.rb +100 -0
  61. data/lib/blather/stanza/presence/muc.rb +35 -0
  62. data/lib/blather/stanza/presence/muc_user.rb +147 -0
  63. data/lib/blather/stanza/presence/status.rb +218 -0
  64. data/lib/blather/stanza/presence/subscription.rb +100 -0
  65. data/lib/blather/stanza/pubsub.rb +119 -0
  66. data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
  67. data/lib/blather/stanza/pubsub/create.rb +65 -0
  68. data/lib/blather/stanza/pubsub/errors.rb +18 -0
  69. data/lib/blather/stanza/pubsub/event.rb +139 -0
  70. data/lib/blather/stanza/pubsub/items.rb +103 -0
  71. data/lib/blather/stanza/pubsub/publish.rb +103 -0
  72. data/lib/blather/stanza/pubsub/retract.rb +92 -0
  73. data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
  74. data/lib/blather/stanza/pubsub/subscription.rb +135 -0
  75. data/lib/blather/stanza/pubsub/subscriptions.rb +83 -0
  76. data/lib/blather/stanza/pubsub/unsubscribe.rb +84 -0
  77. data/lib/blather/stanza/pubsub_owner.rb +51 -0
  78. data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
  79. data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
  80. data/lib/blather/stanza/x.rb +416 -0
  81. data/lib/blather/stream.rb +266 -0
  82. data/lib/blather/stream/client.rb +32 -0
  83. data/lib/blather/stream/component.rb +39 -0
  84. data/lib/blather/stream/features.rb +70 -0
  85. data/lib/blather/stream/features/register.rb +38 -0
  86. data/lib/blather/stream/features/resource.rb +63 -0
  87. data/lib/blather/stream/features/sasl.rb +190 -0
  88. data/lib/blather/stream/features/session.rb +45 -0
  89. data/lib/blather/stream/features/tls.rb +29 -0
  90. data/lib/blather/stream/parser.rb +102 -0
  91. data/lib/blather/version.rb +3 -0
  92. data/lib/blather/xmpp_node.rb +94 -0
  93. data/spec/blather/client/client_spec.rb +687 -0
  94. data/spec/blather/client/dsl/pubsub_spec.rb +492 -0
  95. data/spec/blather/client/dsl_spec.rb +266 -0
  96. data/spec/blather/errors/sasl_error_spec.rb +33 -0
  97. data/spec/blather/errors/stanza_error_spec.rb +129 -0
  98. data/spec/blather/errors/stream_error_spec.rb +108 -0
  99. data/spec/blather/errors_spec.rb +33 -0
  100. data/spec/blather/file_transfer_spec.rb +135 -0
  101. data/spec/blather/jid_spec.rb +87 -0
  102. data/spec/blather/roster_item_spec.rb +134 -0
  103. data/spec/blather/roster_spec.rb +107 -0
  104. data/spec/blather/stanza/discos/disco_info_spec.rb +247 -0
  105. data/spec/blather/stanza/discos/disco_items_spec.rb +154 -0
  106. data/spec/blather/stanza/iq/command_spec.rb +206 -0
  107. data/spec/blather/stanza/iq/ibb_spec.rb +124 -0
  108. data/spec/blather/stanza/iq/ping_spec.rb +45 -0
  109. data/spec/blather/stanza/iq/query_spec.rb +64 -0
  110. data/spec/blather/stanza/iq/roster_spec.rb +139 -0
  111. data/spec/blather/stanza/iq/s5b_spec.rb +57 -0
  112. data/spec/blather/stanza/iq/si_spec.rb +98 -0
  113. data/spec/blather/stanza/iq/vcard_spec.rb +93 -0
  114. data/spec/blather/stanza/iq_spec.rb +61 -0
  115. data/spec/blather/stanza/message/muc_user_spec.rb +152 -0
  116. data/spec/blather/stanza/message_spec.rb +282 -0
  117. data/spec/blather/stanza/presence/c_spec.rb +56 -0
  118. data/spec/blather/stanza/presence/muc_spec.rb +37 -0
  119. data/spec/blather/stanza/presence/muc_user_spec.rb +83 -0
  120. data/spec/blather/stanza/presence/status_spec.rb +144 -0
  121. data/spec/blather/stanza/presence/subscription_spec.rb +102 -0
  122. data/spec/blather/stanza/presence_spec.rb +125 -0
  123. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  124. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  125. data/spec/blather/stanza/pubsub/event_spec.rb +98 -0
  126. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  127. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  128. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  129. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  130. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  131. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  132. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +74 -0
  133. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  134. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  135. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  136. data/spec/blather/stanza/pubsub_spec.rb +68 -0
  137. data/spec/blather/stanza/x_spec.rb +231 -0
  138. data/spec/blather/stanza_spec.rb +134 -0
  139. data/spec/blather/stream/client_spec.rb +1090 -0
  140. data/spec/blather/stream/component_spec.rb +108 -0
  141. data/spec/blather/stream/parser_spec.rb +152 -0
  142. data/spec/blather/stream/ssl_spec.rb +32 -0
  143. data/spec/blather/xmpp_node_spec.rb +47 -0
  144. data/spec/blather_spec.rb +34 -0
  145. data/spec/fixtures/pubsub.rb +311 -0
  146. data/spec/spec_helper.rb +17 -0
  147. data/yard/templates/default/class/html/handlers.erb +18 -0
  148. data/yard/templates/default/class/setup.rb +10 -0
  149. data/yard/templates/default/class/text/handlers.erb +1 -0
  150. metadata +459 -0
@@ -0,0 +1,247 @@
1
+ require '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
+ xml:lang='en'/>
15
+ <feature var='jabber:iq:time'/>
16
+ <feature var='jabber:iq:version'/>
17
+ </query>
18
+ </iq>
19
+ XML
20
+ end
21
+
22
+ describe Blather::Stanza::Iq::DiscoInfo do
23
+ it 'registers itself' do
24
+ Blather::XMPPNode.class_from_registration(:query, 'http://jabber.org/protocol/disco#info').should == Blather::Stanza::Iq::DiscoInfo
25
+ end
26
+
27
+ it 'must be importable' do
28
+ Blather::XMPPNode.parse(disco_info_xml).should 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.should == 'music'
34
+ n.node = :foo
35
+ n.node.should == '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.should == 1
42
+ r.identities.map { |i| i.class }.uniq.should == [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.should == 2
49
+ r.features.map { |i| i.class }.uniq.should == [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).should_not be_empty
56
+ end
57
+
58
+ it 'allows adding of identities' do
59
+ di = Blather::Stanza::Iq::DiscoInfo.new
60
+ di.identities.size.should == 0
61
+ di.identities = [{:name => 'name', :type => 'type', :category => 'category'}]
62
+ di.identities.size.should == 1
63
+ di.identities += [Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category])]
64
+ di.identities.size.should == 2
65
+ di.identities = nil
66
+ di.identities.size.should == 0
67
+ end
68
+
69
+ it 'allows adding of features' do
70
+ di = Blather::Stanza::Iq::DiscoInfo.new
71
+ di.features.size.should == 0
72
+ di.features = ["feature1"]
73
+ di.features.size.should == 1
74
+ di.features += [Blather::Stanza::Iq::DiscoInfo::Feature.new("feature2")]
75
+ di.features.size.should == 2
76
+ di.features = nil
77
+ di.features.size.should == 0
78
+ end
79
+
80
+ end
81
+
82
+ describe 'Blather::Stanza::Iq::DiscoInfo identities' do
83
+ it 'takes a list of hashes for identities' do
84
+ ids = [
85
+ {:name => 'name', :type => 'type', :category => 'category'},
86
+ {:name => 'name1', :type => 'type1', :category => 'category1'},
87
+ ]
88
+
89
+ control = [ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category]),
90
+ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1])]
91
+
92
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, ids
93
+ di.identities.size.should == 2
94
+ di.identities.each { |i| control.include?(i).should == true }
95
+ end
96
+
97
+ it 'takes a list of Identity objects as identities' do
98
+ control = [ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category]),
99
+ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1])]
100
+
101
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, control
102
+ di.identities.size.should == 2
103
+ di.identities.each { |i| control.include?(i).should == true }
104
+ end
105
+
106
+ it 'takes a single hash as identity' do
107
+ control = [Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category])]
108
+
109
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, {:name => 'name', :type => 'type', :category => 'category'}
110
+ di.identities.size.should == 1
111
+ di.identities.each { |i| control.include?(i).should == true }
112
+ end
113
+
114
+ it 'takes a single identity object as identity' do
115
+ control = [Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category])]
116
+
117
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, control.first
118
+ di.identities.size.should == 1
119
+ di.identities.each { |i| control.include?(i).should == true }
120
+ end
121
+
122
+ it 'takes a mix of hashes and identity objects as identities' do
123
+ ids = [
124
+ {:name => 'name', :type => 'type', :category => 'category'},
125
+ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1]),
126
+ ]
127
+
128
+ control = [ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category]),
129
+ Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1])]
130
+
131
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, ids
132
+ di.identities.size.should == 2
133
+ di.identities.each { |i| control.include?(i).should == true }
134
+ end
135
+ end
136
+
137
+ describe 'Blather::Stanza::Iq::DiscoInfo features' do
138
+ it 'takes a list of features as strings' do
139
+ features = %w[feature1 feature2 feature3]
140
+ control = features.map { |f| Blather::Stanza::Iq::DiscoInfo::Feature.new f }
141
+
142
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], features
143
+ di.features.size.should == 3
144
+ di.features.each { |f| control.include?(f).should == true }
145
+ end
146
+
147
+ it 'takes a list of features as Feature objects' do
148
+ features = %w[feature1 feature2 feature3]
149
+ control = features.map { |f| Blather::Stanza::Iq::DiscoInfo::Feature.new f }
150
+
151
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], control
152
+ di.features.size.should == 3
153
+ di.features.each { |f| control.include?(f).should == true }
154
+ end
155
+
156
+ it 'takes a single string' do
157
+ control = [Blather::Stanza::Iq::DiscoInfo::Feature.new('feature1')]
158
+
159
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], 'feature1'
160
+ di.features.size.should == 1
161
+ di.features.each { |f| control.include?(f).should == true }
162
+ end
163
+
164
+ it 'takes a single Feature object' do
165
+ control = [Blather::Stanza::Iq::DiscoInfo::Feature.new('feature1')]
166
+
167
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], control.first
168
+ di.features.size.should == 1
169
+ di.features.each { |f| control.include?(f).should == true }
170
+ end
171
+
172
+ it 'takes a mixed list of features as Feature objects and strings' do
173
+ features = %w[feature1 feature2 feature3]
174
+ control = features.map { |f| Blather::Stanza::Iq::DiscoInfo::Feature.new f }
175
+ features[1] = control[1]
176
+
177
+ di = Blather::Stanza::Iq::DiscoInfo.new nil, nil, [], features
178
+ di.features.size.should == 3
179
+ di.features.each { |f| control.include?(f).should == true }
180
+ end
181
+ end
182
+
183
+ describe Blather::Stanza::Iq::DiscoInfo::Identity do
184
+ it 'will auto-inherit nodes' do
185
+ n = parse_stanza "<identity name='Personal Events' type='pep' category='pubsub' node='publish' xml:lang='en' />"
186
+ i = Blather::Stanza::Iq::DiscoInfo::Identity.new n.root
187
+ i.name.should == 'Personal Events'
188
+ i.type.should == :pep
189
+ i.category.should == :pubsub
190
+ i.xml_lang.should == 'en'
191
+ end
192
+
193
+ it 'has a category attribute' do
194
+ n = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
195
+ n.category.should == :cat
196
+ n.category = :foo
197
+ n.category.should == :foo
198
+ end
199
+
200
+ it 'has a type attribute' do
201
+ n = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
202
+ n.type.should == :type
203
+ n.type = :foo
204
+ n.type.should == :foo
205
+ end
206
+
207
+ it 'has a name attribute' do
208
+ n = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
209
+ n.name.should == 'name'
210
+ n.name = :foo
211
+ n.name.should == 'foo'
212
+ end
213
+
214
+ it 'has an xml:lang attribute' do
215
+ n = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat en])
216
+ n.xml_lang.should == 'en'
217
+ n.xml_lang = 'de'
218
+ n.xml_lang.should == 'de'
219
+ end
220
+
221
+ it 'can determine equality' do
222
+ a = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
223
+ a.should == Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
224
+ a.should_not equal Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[not-name not-type not-cat])
225
+ end
226
+ end
227
+
228
+ describe Blather::Stanza::Iq::DiscoInfo::Feature do
229
+ it 'will auto-inherit nodes' do
230
+ n = parse_stanza "<feature var='ipv6' />"
231
+ i = Blather::Stanza::Iq::DiscoInfo::Feature.new n.root
232
+ i.var.should == 'ipv6'
233
+ end
234
+
235
+ it 'has a var attribute' do
236
+ n = Blather::Stanza::Iq::DiscoInfo::Feature.new 'var'
237
+ n.var.should == 'var'
238
+ n.var = :foo
239
+ n.var.should == 'foo'
240
+ end
241
+
242
+ it 'can determine equality' do
243
+ a = Blather::Stanza::Iq::DiscoInfo::Feature.new('var')
244
+ a.should == Blather::Stanza::Iq::DiscoInfo::Feature.new('var')
245
+ a.should_not equal Blather::Stanza::Iq::DiscoInfo::Feature.new('not-var')
246
+ end
247
+ end
@@ -0,0 +1,154 @@
1
+ require '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').should == Blather::Stanza::Iq::DiscoItems
27
+ end
28
+
29
+ it 'must be importable' do
30
+ Blather::XMPPNode.parse(disco_items_xml).should 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).should_not be_empty
37
+ end
38
+
39
+ it 'has a node attribute' do
40
+ n = Blather::Stanza::Iq::DiscoItems.new nil, 'music', []
41
+ n.node.should == 'music'
42
+ n.node = :foo
43
+ n.node.should == '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.should == 3
50
+ r.items.map { |i| i.class }.uniq.should == [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.should == 2
64
+ di.items.each { |i| control.include?(i).should == 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.should == 2
73
+ di.items.each { |i| control.include?(i).should == 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.should == 1
81
+ di.items.each { |i| control.include?(i).should == 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.should == 1
89
+ di.items.each { |i| control.include?(i).should == 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.should == 2
103
+ di.items.each { |i| control.include?(i).should == true }
104
+ end
105
+
106
+ it 'allows adding of items' do
107
+ di = Blather::Stanza::Iq::DiscoItems.new
108
+ di.items.size.should == 0
109
+ di.items = [{:jid => 'foo@bar/baz', :node => 'node', :name => 'name'}]
110
+ di.items.size.should == 1
111
+ di.items += [Blather::Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name])]
112
+ di.items.size.should == 2
113
+ di.items = nil
114
+ di.items.size.should == 0
115
+ end
116
+ end
117
+
118
+ describe Blather::Stanza::Iq::DiscoItems::Item do
119
+ it 'will auto-inherit nodes' do
120
+ n = parse_stanza "<item jid='foo@bar/baz' node='music' name='Music from the time of Shakespeare' />"
121
+ i = Blather::Stanza::Iq::DiscoItems::Item.new n.root
122
+ i.jid.should == Blather::JID.new('foo@bar/baz')
123
+ i.node.should == 'music'
124
+ i.name.should == 'Music from the time of Shakespeare'
125
+ end
126
+
127
+ it 'has a jid attribute' do
128
+ n = Blather::Stanza::Iq::DiscoItems::Item.new 'foo@bar/baz'
129
+ n.jid.should be_kind_of Blather::JID
130
+ n.jid.should == Blather::JID.new('foo@bar/baz')
131
+ n.jid = 'baz@foo/bar'
132
+ n.jid.should == Blather::JID.new('baz@foo/bar')
133
+ end
134
+
135
+ it 'has a node attribute' do
136
+ n = Blather::Stanza::Iq::DiscoItems::Item.new 'foo@bar/baz', 'music'
137
+ n.node.should == 'music'
138
+ n.node = 'book'
139
+ n.node.should == 'book'
140
+ end
141
+
142
+ it 'has a name attribute' do
143
+ n = Blather::Stanza::Iq::DiscoItems::Item.new 'foo@bar/baz', nil, 'Music from the time of Shakespeare'
144
+ n.name.should == 'Music from the time of Shakespeare'
145
+ n.name = 'Books by and about Shakespeare'
146
+ n.name.should == 'Books by and about Shakespeare'
147
+ end
148
+
149
+ it 'can determine equality' do
150
+ a = Blather::Stanza::Iq::DiscoItems::Item.new('foo@bar/baz')
151
+ a.should == Blather::Stanza::Iq::DiscoItems::Item.new('foo@bar/baz')
152
+ a.should_not equal Blather::Stanza::Iq::DiscoItems::Item.new('not-foo@bar/baz')
153
+ end
154
+ end
@@ -0,0 +1,206 @@
1
+ require 'spec_helper'
2
+
3
+ def command_xml
4
+ <<-XML
5
+ <iq type='result'
6
+ from='catalog.shakespeare.lit'
7
+ to='romeo@montague.net/orchard'
8
+ id='form2'>
9
+ <command xmlns='http://jabber.org/protocol/commands'
10
+ node='node1'
11
+ sessionid='dqjiodmqlmakm'>
12
+ <x xmlns='jabber:x:data' type='form'>
13
+ <field var='field-name' type='text-single' label='description' />
14
+ </x>
15
+ </command>
16
+ </iq>
17
+ XML
18
+ end
19
+
20
+ describe Blather::Stanza::Iq::Command do
21
+ it 'registers itself' do
22
+ Blather::XMPPNode.class_from_registration(:command, 'http://jabber.org/protocol/commands').should == Blather::Stanza::Iq::Command
23
+ end
24
+
25
+ it 'must be importable' do
26
+ Blather::XMPPNode.parse(command_xml).should be_instance_of Blather::Stanza::Iq::Command
27
+ end
28
+
29
+ it 'ensures a command node is present on create' do
30
+ c = Blather::Stanza::Iq::Command.new
31
+ c.xpath('xmlns:command', :xmlns => Blather::Stanza::Iq::Command.registered_ns).should_not be_empty
32
+ end
33
+
34
+ it 'ensures a command node exists when calling #command' do
35
+ c = Blather::Stanza::Iq::Command.new
36
+ c.remove_children :command
37
+ c.xpath('ns:command', :ns => Blather::Stanza::Iq::Command.registered_ns).should be_empty
38
+
39
+ c.command.should_not be_nil
40
+ c.xpath('ns:command', :ns => Blather::Stanza::Iq::Command.registered_ns).should_not be_empty
41
+ end
42
+
43
+ Blather::Stanza::Iq::Command::VALID_ACTIONS.each do |valid_action|
44
+ it "provides a helper (#{valid_action}?) for action #{valid_action}" do
45
+ Blather::Stanza::Iq::Command.new.should respond_to :"#{valid_action}?"
46
+ end
47
+ end
48
+
49
+ Blather::Stanza::Iq::Command::VALID_STATUS.each do |valid_status|
50
+ it "provides a helper (#{valid_status}?) for status #{valid_status}" do
51
+ Blather::Stanza::Iq::Command.new.should respond_to :"#{valid_status}?"
52
+ end
53
+ end
54
+
55
+ Blather::Stanza::Iq::Command::VALID_NOTE_TYPES.each do |valid_note_type|
56
+ it "provides a helper (#{valid_note_type}?) for note_type #{valid_note_type}" do
57
+ Blather::Stanza::Iq::Command.new.should respond_to :"#{valid_note_type}?"
58
+ end
59
+ end
60
+
61
+ [:cancel, :execute, :complete, :next, :prev].each do |action|
62
+ it "action can be set as \"#{action}\"" do
63
+ c = Blather::Stanza::Iq::Command.new nil, nil, action
64
+ c.action.should == action
65
+ end
66
+ end
67
+
68
+ [:get, :set, :result, :error].each do |type|
69
+ it "can be set as \"#{type}\"" do
70
+ c = Blather::Stanza::Iq::Command.new type
71
+ c.type.should == type
72
+ end
73
+ end
74
+
75
+ it 'sets type to "result" on reply' do
76
+ c = Blather::Stanza::Iq::Command.new
77
+ c.type.should == :set
78
+ reply = c.reply.type.should == :result
79
+ end
80
+
81
+ it 'sets type to "result" on reply!' do
82
+ c = Blather::Stanza::Iq::Command.new
83
+ c.type.should == :set
84
+ c.reply!
85
+ c.type.should == :result
86
+ end
87
+
88
+ it 'removes action on reply' do
89
+ c = Blather::XMPPNode.parse command_xml
90
+ c.action.should == :execute
91
+ c.reply.action.should == nil
92
+ end
93
+
94
+ it 'removes action on reply!' do
95
+ c = Blather::XMPPNode.parse command_xml
96
+ c.action.should == :execute
97
+ c.reply!
98
+ c.action.should == nil
99
+ end
100
+
101
+ it 'can be registered under a namespace' do
102
+ class CommandNs < Blather::Stanza::Iq::Command; register :command_ns, nil, 'command:ns'; end
103
+ Blather::XMPPNode.class_from_registration(:command, 'command:ns').should == CommandNs
104
+ c_ns = CommandNs.new
105
+ c_ns.xpath('command').should be_empty
106
+ c_ns.xpath('ns:command', :ns => 'command:ns').size.should == 1
107
+
108
+ c_ns.command
109
+ c_ns.command
110
+ c_ns.xpath('ns:command', :ns => 'command:ns').size.should == 1
111
+ end
112
+
113
+ it 'is constructed properly' do
114
+ n = Blather::Stanza::Iq::Command.new :set, "node", :execute
115
+ n.to = 'to@jid.com'
116
+ n.find("/iq[@to='to@jid.com' and @type='set' and @id='#{n.id}']/ns:command[@node='node' and @action='execute']", :ns => Blather::Stanza::Iq::Command.registered_ns).should_not be_empty
117
+ end
118
+
119
+ it 'has an action attribute' do
120
+ n = Blather::Stanza::Iq::Command.new
121
+ n.action.should == :execute
122
+ n.action = :cancel
123
+ n.action.should == :cancel
124
+ end
125
+
126
+ it 'must default action to :execute on import' do
127
+ n = Blather::XMPPNode.parse(command_xml)
128
+ n.action.should == :execute
129
+ end
130
+
131
+ it 'has a status attribute' do
132
+ n = Blather::Stanza::Iq::Command.new
133
+ n.status.should == :executing
134
+ n.status = :completed
135
+ n.status.should == :completed
136
+ end
137
+
138
+ it 'has a sessionid attribute' do
139
+ n = Blather::Stanza::Iq::Command.new
140
+ n.sessionid.should == nil
141
+ n.sessionid = "somerandomstring"
142
+ n.sessionid.should == Digest::SHA1.hexdigest("somerandomstring")
143
+ end
144
+
145
+ it 'has a sessionid? attribute' do
146
+ n = Blather::Stanza::Iq::Command.new
147
+ n.sessionid?.should == false
148
+ n.new_sessionid!
149
+ n.sessionid?.should == true
150
+ end
151
+
152
+ it 'has an allowed_actions attribute' do
153
+ n = Blather::XMPPNode.parse command_xml
154
+ n.allowed_actions.should == [:execute]
155
+ n.allowed_actions = [:next, :prev]
156
+ (n.allowed_actions - [:next, :prev, :execute]).should be_empty
157
+ n.remove_allowed_actions!
158
+ n.allowed_actions.should == [:execute]
159
+ n.allowed_actions += [:next]
160
+ (n.allowed_actions - [:next, :execute]).should be_empty
161
+
162
+ r = Blather::Stanza::Iq::Command.new
163
+ r.allowed_actions.should == [:execute]
164
+ r.allowed_actions += [:prev]
165
+ (r.allowed_actions - [:prev, :execute]).should be_empty
166
+ end
167
+
168
+ it 'has a primary_allowed_action attribute' do
169
+ n = Blather::XMPPNode.parse command_xml
170
+ n.primary_allowed_action.should == :execute
171
+ n.primary_allowed_action = :next
172
+ n.primary_allowed_action.should == :next
173
+ end
174
+
175
+ it 'has a note_type attribute' do
176
+ n = Blather::Stanza::Iq::Command.new
177
+ n.note_type.should == nil
178
+ n.note_type = :info
179
+ n.note_type.should == :info
180
+ end
181
+
182
+ it 'has a note_text attribute' do
183
+ n = Blather::Stanza::Iq::Command.new
184
+ n.note_text.should == nil
185
+ n.note_text = "Some text"
186
+ n.note_text.should == "Some text"
187
+ end
188
+
189
+ it 'makes a form child available' do
190
+ n = Blather::XMPPNode.parse(command_xml)
191
+ n.form.fields.size.should == 1
192
+ n.form.fields.map { |f| f.class }.uniq.should == [Blather::Stanza::X::Field]
193
+ n.form.should be_instance_of Blather::Stanza::X
194
+
195
+ r = Blather::Stanza::Iq::Command.new
196
+ r.form.type = :form
197
+ r.form.type.should == :form
198
+ end
199
+
200
+ it 'ensures the form child is a child of command' do
201
+ r = Blather::Stanza::Iq::Command.new
202
+ r.form
203
+ r.command.xpath('ns:x', :ns => Blather::Stanza::X.registered_ns).should_not be_empty
204
+ r.xpath('ns:x', :ns => Blather::Stanza::X.registered_ns).should be_empty
205
+ end
206
+ end