tp-blather 0.8.2

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 (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,266 @@
1
+ require 'spec_helper'
2
+ require 'blather/client/dsl'
3
+
4
+ describe Blather::DSL do
5
+ before do
6
+ @client = Blather::Client.new
7
+ @stream = mock()
8
+ @stream.stubs(:send)
9
+ @client.post_init @stream, Blather::JID.new('n@d/r')
10
+ @dsl = Class.new { include Blather::DSL }.new
11
+ Blather::Client.stubs(:new).returns(@client)
12
+ end
13
+
14
+ it 'wraps the setup' do
15
+ args = ['jid', 'pass', 'host', 0000]
16
+ @client.expects(:setup).with *(args + [nil, nil, nil])
17
+ @dsl.setup *args
18
+ end
19
+
20
+ it 'allows host to be nil in setup' do
21
+ args = ['jid', 'pass']
22
+ @client.expects(:setup).with *(args + [nil, nil, nil, nil])
23
+ @dsl.setup *args
24
+ end
25
+
26
+ it 'allows port to be nil in setup' do
27
+ args = ['jid', 'pass', 'host']
28
+ @client.expects(:setup).with *(args + [nil, nil, nil])
29
+ @dsl.setup *args
30
+ end
31
+
32
+ it 'allows certs to be nil in setup' do
33
+ args = ['jid', 'pass', 'host', 'port']
34
+ @client.expects(:setup).with *(args + [nil, nil])
35
+ @dsl.setup *args
36
+ end
37
+
38
+ it 'accepts certs in setup' do
39
+ args = ['jid', 'pass', 'host', 'port', 'certs']
40
+ @client.expects(:setup).with *(args + [nil])
41
+ @dsl.setup *args
42
+ end
43
+
44
+ it 'accepts connection timeout in setup' do
45
+ args = ['jid', 'pass', 'host', 'port', 'certs', 30]
46
+ @client.expects(:setup).with *args
47
+ @dsl.setup *args
48
+ end
49
+
50
+ it 'stops when shutdown is called' do
51
+ @client.expects(:close)
52
+ @dsl.shutdown
53
+ end
54
+
55
+ it 'can throw a halt' do
56
+ catch(:halt) { @dsl.halt }
57
+ end
58
+
59
+ it 'can throw a pass' do
60
+ catch(:pass) { @dsl.pass }
61
+ end
62
+
63
+ it 'can setup before filters' do
64
+ guards = [:chat?, {:body => 'exit'}]
65
+ @client.expects(:register_filter).with :before, nil, *guards
66
+ @dsl.before nil, *guards
67
+ end
68
+
69
+ it 'can setup after filters' do
70
+ guards = [:chat?, {:body => 'exit'}]
71
+ @client.expects(:register_filter).with :after, nil, *guards
72
+ @dsl.after nil, *guards
73
+ end
74
+
75
+ it 'sets up handlers' do
76
+ type = :message
77
+ guards = [:chat?, {:body => 'exit'}]
78
+ @client.expects(:register_handler).with type, *guards
79
+ @dsl.handle type, *guards
80
+ end
81
+
82
+ it 'sets up handler methods' do
83
+ @client.expects(:register_handler).with :presence, :unavailable?
84
+ @dsl.presence :unavailable?
85
+ end
86
+
87
+ it 'provides a helper for ready state' do
88
+ @client.expects(:register_handler).with :ready
89
+ @dsl.when_ready
90
+ end
91
+
92
+ it 'provides a helper for disconnected' do
93
+ @client.expects(:register_handler).with :disconnected
94
+ @dsl.disconnected
95
+ end
96
+
97
+ it 'sets the initial status' do
98
+ state = :away
99
+ msg = 'do not disturb'
100
+ @client.expects(:status=).with [state, msg]
101
+ @dsl.set_status state, msg
102
+ end
103
+
104
+ it 'provides a roster accessor' do
105
+ @client.expects :roster
106
+ @dsl.my_roster
107
+ end
108
+
109
+ it 'provides a << style writer that provides chaining' do
110
+ stanza = Blather::Stanza::Iq.new
111
+ @client.expects(:write).with stanza
112
+ (@dsl << stanza).should == @dsl
113
+ end
114
+
115
+ it 'provides a writer' do
116
+ stanza = Blather::Stanza::Iq.new
117
+ @client.expects(:write).with stanza
118
+ @dsl.write_to_stream stanza
119
+ end
120
+
121
+ describe "#join" do
122
+ context "providing room and service as separate args" do
123
+ it "should join to a muc room with a specified nick" do
124
+ presence = Blather::Stanza::Presence::MUC.new
125
+ presence.to = "rabbit_hole@wonderland.lit/alice"
126
+ @client.expects(:write).with presence
127
+ @dsl.join 'rabbit_hole', 'wonderland.lit', 'alice'
128
+ end
129
+ end
130
+
131
+ context "providing a room JID" do
132
+ it "should join to a muc room with a specified nick" do
133
+ presence = Blather::Stanza::Presence::MUC.new
134
+ presence.to = "rabbit_hole@wonderland.lit/alice"
135
+ @client.expects(:write).with presence
136
+ @dsl.join 'rabbit_hole@wonderland.lit', 'alice'
137
+ end
138
+ end
139
+ end
140
+
141
+ it 'provides a "say" helper' do
142
+ to, msg, type = 'me@me.com', 'hello!', :groupchat
143
+ Blather::Stanza::Message.stubs(:next_id).returns 0
144
+ @client.expects(:write).with Blather::Stanza::Message.new(to, msg, type)
145
+ @dsl.say to, msg, type
146
+ end
147
+
148
+ it 'provides a JID accessor' do
149
+ @client.expects :jid
150
+ @dsl.jid
151
+ end
152
+
153
+ it 'provides a disco helper for items' do
154
+ what, who, where = :items, 'me@me.com', 'my/node'
155
+ Blather::Stanza::Disco::DiscoItems.stubs(:next_id).returns 0
156
+ @client.expects(:register_tmp_handler).with '0'
157
+ expected_stanza = Blather::Stanza::Disco::DiscoItems.new
158
+ expected_stanza.to = who
159
+ expected_stanza.node = where
160
+ @client.expects(:write).with expected_stanza
161
+ @dsl.discover what, who, where
162
+ end
163
+
164
+ it 'provides a disco helper for info' do
165
+ what, who, where = :info, 'me@me.com', 'my/node'
166
+ Blather::Stanza::Disco::DiscoInfo.stubs(:next_id).returns 0
167
+ @client.expects(:register_tmp_handler).with '0'
168
+ expected_stanza = Blather::Stanza::Disco::DiscoInfo.new
169
+ expected_stanza.to = who
170
+ expected_stanza.node = where
171
+ @client.expects(:write).with expected_stanza
172
+ @dsl.discover what, who, where
173
+ end
174
+
175
+ it 'provides a caps set helper' do
176
+ @dsl.should respond_to :set_caps
177
+ node = 'http://code.google.com/p/exodus'
178
+ identities = [Blather::Stanza::Iq::DiscoInfo::Identity.new({:name => 'Exodus 0.9.1', :type => 'pc', :category => 'client'})]
179
+ features = %w{
180
+ http://jabber.org/protocol/caps
181
+ http://jabber.org/protocol/disco#info
182
+ http://jabber.org/protocol/disco#items
183
+ http://jabber.org/protocol/muc
184
+ }
185
+ @dsl.set_caps node, identities, features
186
+ @client.caps.node.should == "#{node}##{@client.caps.ver}"
187
+ @client.caps.identities.should == identities
188
+ @client.caps.features.map{ |f| f.var }.should == features
189
+ end
190
+
191
+ it 'provides a caps send helper' do
192
+ @dsl.should respond_to :send_caps
193
+ @client.caps.node = 'http://code.google.com/p/exodus'
194
+ @client.caps.identities = [Blather::Stanza::Iq::DiscoInfo::Identity.new({:name => 'Exodus 0.9.1', :type => 'pc', :category => 'client'})]
195
+ @client.caps.features = %w{
196
+ http://jabber.org/protocol/caps
197
+ http://jabber.org/protocol/disco#info
198
+ http://jabber.org/protocol/disco#items
199
+ http://jabber.org/protocol/muc
200
+ }
201
+ expected_stanza = Blather::Stanza.parse(<<-XML)
202
+ <presence>
203
+ <c xmlns="http://jabber.org/protocol/caps" hash="sha-1"
204
+ node="http://code.google.com/p/exodus"
205
+ ver="QgayPKawpkPSDYmwT/WM94uAlu0="
206
+ />
207
+ </presence>
208
+ XML
209
+ @client.expects(:write).with expected_stanza
210
+ @client.expects(:register_handler).with(:disco_info, :type => :get, :node => "http://code.google.com/p/exodus#QgayPKawpkPSDYmwT/WM94uAlu0=")
211
+ @dsl.send_caps
212
+ end
213
+
214
+ it 'responds with correct disco stanza after sending caps and receiving query' do
215
+ @client.caps.node = 'http://code.google.com/p/exodus'
216
+ @client.caps.identities = [Blather::Stanza::Iq::DiscoInfo::Identity.new({:name => 'Exodus 0.9.1', :type => 'pc', :category => 'client'})]
217
+ @client.caps.features = %w{
218
+ http://jabber.org/protocol/caps
219
+ http://jabber.org/protocol/disco#info
220
+ http://jabber.org/protocol/disco#items
221
+ http://jabber.org/protocol/muc
222
+ }
223
+ stanza = <<-XML
224
+ <iq from='juliet@capulet.lit/chamber'
225
+ id='disco1'
226
+ to='romeo@montague.lit/orchard'
227
+ type='get'>
228
+ <query xmlns='http://jabber.org/protocol/disco#info'
229
+ node='http://code.google.com/p/exodus#QgayPKawpkPSDYmwT/WM94uAlu0='/>
230
+ </iq>
231
+ XML
232
+ @stanza = Blather::Stanza.parse(stanza)
233
+
234
+ expected_stanza = Blather::Stanza.parse(<<-XML)
235
+ <iq type="result" id="disco1" to="juliet@capulet.lit/chamber">
236
+ <query xmlns="http://jabber.org/protocol/disco#info" node="http://code.google.com/p/exodus#QgayPKawpkPSDYmwT/WM94uAlu0=">
237
+ <identity name="Exodus 0.9.1" category="client" type="pc"/>
238
+ <feature var="http://jabber.org/protocol/caps"/>
239
+ <feature var="http://jabber.org/protocol/disco#info"/>
240
+ <feature var="http://jabber.org/protocol/disco#items"/>
241
+ <feature var="http://jabber.org/protocol/muc"/>
242
+ </query>
243
+ </iq>
244
+ XML
245
+ @dsl.send_caps
246
+ # client writes a Client::Cap object but it's the same as a DiscoInfo
247
+ # this is a hack to pass the same-class check in XMPPNode#eql?
248
+ @client.expects(:write).with { |n| Blather::Stanza.import(n) == expected_stanza }
249
+ @client.receive_data @stanza
250
+ end
251
+
252
+ Blather::Stanza.handler_list.each do |handler_method|
253
+ it "provides a helper method for #{handler_method}" do
254
+ guards = [:chat?, {:body => 'exit'}]
255
+ @client.expects(:register_handler).with handler_method, *guards
256
+ @dsl.__send__(handler_method, *guards)
257
+ end
258
+ end
259
+
260
+ it 'has a pubsub helper set to the jid domain' do
261
+ jid = Blather::JID.new('jid@domain/resource')
262
+ @client.stubs(:jid).returns jid
263
+ @dsl.pubsub.should be_instance_of Blather::DSL::PubSub
264
+ @dsl.pubsub.host.should == jid.domain
265
+ end
266
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ def sasl_error_node(err_name = 'aborted')
4
+ node = Blather::XMPPNode.new 'failure'
5
+ node.namespace = Blather::SASLError::SASL_ERR_NS
6
+
7
+ node << Blather::XMPPNode.new(err_name, node.document)
8
+ node
9
+ end
10
+
11
+ describe Blather::SASLError do
12
+ it 'can import a node' do
13
+ Blather::SASLError.should respond_to :import
14
+ e = Blather::SASLError.import sasl_error_node
15
+ e.should be_kind_of Blather::SASLError
16
+ end
17
+
18
+ describe 'each XMPP SASL error type' do
19
+ %w[ aborted
20
+ incorrect-encoding
21
+ invalid-authzid
22
+ invalid-mechanism
23
+ mechanism-too-weak
24
+ not-authorized
25
+ temporary-auth-failure
26
+ ].each do |error_type|
27
+ it "handles the name for #{error_type}" do
28
+ e = Blather::SASLError.import sasl_error_node(error_type)
29
+ e.name.should == error_type.gsub('-','_').to_sym
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ def stanza_error_node(type = 'cancel', error = 'internal-server-error', msg = nil)
4
+ node = Blather::Stanza::Message.new 'error@jabber.local', 'test message', :error
5
+
6
+ node << (error_node = Blather::XMPPNode.new('error'))
7
+ error_node['type'] = type.to_s
8
+
9
+ error_node << (err = Blather::XMPPNode.new(error, error_node.document))
10
+ err.namespace = 'urn:ietf:params:xml:ns:xmpp-stanzas'
11
+
12
+ if msg
13
+ error_node << (text = Blather::XMPPNode.new('text', error_node.document))
14
+ text.namespace = 'urn:ietf:params:xml:ns:xmpp-stanzas'
15
+ text.content = msg
16
+ end
17
+
18
+ error_node << (extra = Blather::XMPPNode.new('extra-error', error_node.document))
19
+ extra.namespace = 'blather:stanza:error'
20
+ extra.content = 'Blather Error'
21
+
22
+ node
23
+ end
24
+
25
+ describe Blather::StanzaError do
26
+ it 'can import a node' do
27
+ Blather::StanzaError.should respond_to :import
28
+ e = Blather::StanzaError.import stanza_error_node
29
+ e.should be_kind_of Blather::StanzaError
30
+ end
31
+
32
+ describe 'valid types' do
33
+ before { @original = Blather::Stanza::Message.new 'error@jabber.local', 'test message', :error }
34
+
35
+ it 'ensures type is one of Stanza::Message::VALID_TYPES' do
36
+ lambda { Blather::StanzaError.new @original, :gone, :invalid_type_name }.should raise_error(Blather::ArgumentError)
37
+
38
+ Blather::StanzaError::VALID_TYPES.each do |valid_type|
39
+ msg = Blather::StanzaError.new @original, :gone, valid_type
40
+ msg.type.should == valid_type
41
+ end
42
+ end
43
+ end
44
+
45
+ describe 'when instantiated' do
46
+ before do
47
+ @type = 'cancel'
48
+ @err_name = 'internal-server-error'
49
+ @msg = 'the server has experienced a misconfiguration'
50
+ @err = Blather::StanzaError.import stanza_error_node(@type, @err_name, @msg)
51
+ end
52
+
53
+ it 'provides a type attribute' do
54
+ @err.should respond_to :type
55
+ @err.type.should == @type.to_sym
56
+ end
57
+
58
+ it 'provides a name attribute' do
59
+ @err.should respond_to :name
60
+ @err.name.should == @err_name.gsub('-','_').to_sym
61
+ end
62
+
63
+ it 'provides a text attribute' do
64
+ @err.should respond_to :text
65
+ @err.text.should == @msg
66
+ end
67
+
68
+ it 'provides a reader to the original node' do
69
+ @err.should respond_to :original
70
+ @err.original.should be_instance_of Blather::Stanza::Message
71
+ end
72
+
73
+ it 'provides an extras attribute' do
74
+ @err.should respond_to :extras
75
+ @err.extras.should be_instance_of Array
76
+ @err.extras.first.element_name.should == 'extra-error'
77
+ end
78
+
79
+ it 'describes itself' do
80
+ @err.to_s.should match(/#{@err_name}/)
81
+ @err.to_s.should match(/#{@msg}/)
82
+
83
+ @err.inspect.should match(/#{@err_name}/)
84
+ @err.inspect.should match(/#{@msg}/)
85
+ end
86
+
87
+ it 'can be turned into xml' do
88
+ @err.should respond_to :to_xml
89
+ doc = parse_stanza @err.to_xml
90
+
91
+ doc.xpath("/message[@from='error@jabber.local' and @type='error']").should_not be_empty
92
+ doc.xpath("/message/error").should_not be_empty
93
+ doc.xpath("/message/error/err_ns:internal-server-error", :err_ns => Blather::StanzaError::STANZA_ERR_NS).should_not be_empty
94
+ doc.xpath("/message/error/err_ns:text[.='the server has experienced a misconfiguration']", :err_ns => Blather::StanzaError::STANZA_ERR_NS).should_not be_empty
95
+ doc.xpath("/message/error/extra_ns:extra-error[.='Blather Error']", :extra_ns => 'blather:stanza:error').should_not be_empty
96
+ end
97
+ end
98
+
99
+ describe 'each XMPP stanza error type' do
100
+ %w[ bad-request
101
+ conflict
102
+ feature-not-implemented
103
+ forbidden
104
+ gone
105
+ internal-server-error
106
+ item-not-found
107
+ jid-malformed
108
+ not-acceptable
109
+ not-allowed
110
+ not-authorized
111
+ payment-required
112
+ recipient-unavailable
113
+ redirect
114
+ registration-required
115
+ remote-server-not-found
116
+ remote-server-timeout
117
+ resource-constraint
118
+ service-unavailable
119
+ subscription-required
120
+ undefined-condition
121
+ unexpected-request
122
+ ].each do |error_type|
123
+ it "handles the name for #{error_type}" do
124
+ e = Blather::StanzaError.import stanza_error_node(:cancel, error_type)
125
+ e.name.should == error_type.gsub('-','_').to_sym
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ def stream_error_node(error = 'internal-server-error', msg = nil)
4
+ node = Blather::XMPPNode.new('error')
5
+ node.namespace = {'stream' => Blather::Stream::STREAM_NS}
6
+
7
+ node << (err = Blather::XMPPNode.new(error, node.document))
8
+ err.namespace = 'urn:ietf:params:xml:ns:xmpp-streams'
9
+
10
+ if msg
11
+ node << (text = Blather::XMPPNode.new('text', node.document))
12
+ text.namespace = 'urn:ietf:params:xml:ns:xmpp-streams'
13
+ text.content = msg
14
+ end
15
+
16
+ node << (extra = Blather::XMPPNode.new('extra-error', node.document))
17
+ extra.namespace = 'blather:stream:error'
18
+ extra.content = 'Blather Error'
19
+
20
+ node
21
+ end
22
+
23
+ describe 'Blather::StreamError' do
24
+ it 'can import a node' do
25
+ err = stream_error_node 'internal-server-error', 'the message'
26
+ Blather::StreamError.should respond_to :import
27
+ e = Blather::StreamError.import err
28
+ e.should be_kind_of Blather::StreamError
29
+
30
+ e.name.should == :internal_server_error
31
+ e.text.should == 'the message'
32
+ e.extras.should == err.find('descendant::*[name()="extra-error"]', 'blather:stream:error').map {|n|n}
33
+ end
34
+ end
35
+
36
+ describe 'Blather::StreamError when instantiated' do
37
+ before do
38
+ @err_name = 'internal-server-error'
39
+ @msg = 'the server has experienced a misconfiguration'
40
+ @err = Blather::StreamError.import stream_error_node(@err_name, @msg)
41
+ end
42
+
43
+ it 'provides a err_name attribute' do
44
+ @err.should respond_to :name
45
+ @err.name.should == @err_name.gsub('-','_').to_sym
46
+ end
47
+
48
+ it 'provides a text attribute' do
49
+ @err.should respond_to :text
50
+ @err.text.should == @msg
51
+ end
52
+
53
+ it 'provides an extras attribute' do
54
+ @err.should respond_to :extras
55
+ @err.extras.should be_instance_of Array
56
+ @err.extras.size.should == 1
57
+ @err.extras.first.element_name.should == 'extra-error'
58
+ end
59
+
60
+ it 'describes itself' do
61
+ @err.to_s.should match(/#{@type}/)
62
+ @err.to_s.should match(/#{@msg}/)
63
+
64
+ @err.inspect.should match(/#{@type}/)
65
+ @err.inspect.should match(/#{@msg}/)
66
+ end
67
+
68
+ it 'can be turned into xml' do
69
+ @err.should respond_to :to_xml
70
+ doc = parse_stanza @err.to_xml
71
+ doc.xpath("//err_ns:internal-server-error", :err_ns => Blather::StreamError::STREAM_ERR_NS).should_not be_empty
72
+ doc.xpath("//err_ns:text[.='the server has experienced a misconfiguration']", :err_ns => Blather::StreamError::STREAM_ERR_NS).should_not be_empty
73
+ doc.xpath("//err_ns:extra-error[.='Blather Error']", :err_ns => 'blather:stream:error').should_not be_empty
74
+ end
75
+ end
76
+
77
+ describe 'Each XMPP stream error type' do
78
+ %w[ bad-format
79
+ bad-namespace-prefix
80
+ conflict
81
+ connection-timeout
82
+ host-gone
83
+ host-unknown
84
+ improper-addressing
85
+ internal-server-error
86
+ invalid-from
87
+ invalid-id
88
+ invalid-namespace
89
+ invalid-xml
90
+ not-authorized
91
+ policy-violation
92
+ remote-connection-failed
93
+ resource-constraint
94
+ restricted-xml
95
+ see-other-host
96
+ system-shutdown
97
+ undefined-condition
98
+ unsupported-encoding
99
+ unsupported-stanza-type
100
+ unsupported-version
101
+ xml-not-well-formed
102
+ ].each do |error_type|
103
+ it "handles the name for #{error_type}" do
104
+ e = Blather::StreamError.import stream_error_node(error_type)
105
+ e.name.should == error_type.gsub('-','_').to_sym
106
+ end
107
+ end
108
+ end