vines 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/Gemfile +3 -0
  2. data/README.md +48 -0
  3. data/Rakefile +6 -58
  4. data/bin/vines +12 -2
  5. data/conf/certs/ca-bundle.crt +568 -39
  6. data/conf/config.rb +9 -42
  7. data/lib/vines.rb +1 -8
  8. data/lib/vines/command/cert.rb +4 -4
  9. data/lib/vines/command/init.rb +3 -3
  10. data/lib/vines/config.rb +9 -0
  11. data/lib/vines/kit.rb +2 -7
  12. data/lib/vines/storage/local.rb +50 -17
  13. data/lib/vines/store.rb +6 -4
  14. data/lib/vines/stream.rb +1 -1
  15. data/lib/vines/stream/http/session.rb +0 -0
  16. data/lib/vines/stream/http/sessions.rb +0 -0
  17. data/lib/vines/stream/parser.rb +3 -2
  18. data/lib/vines/token_bucket.rb +19 -10
  19. data/lib/vines/version.rb +1 -1
  20. data/test/cluster/publisher_test.rb +45 -33
  21. data/test/cluster/sessions_test.rb +32 -39
  22. data/test/cluster/subscriber_test.rb +93 -78
  23. data/test/config/host_test.rb +2 -4
  24. data/test/config/pubsub_test.rb +132 -126
  25. data/test/config_test.rb +2 -4
  26. data/test/contact_test.rb +80 -66
  27. data/test/error_test.rb +54 -55
  28. data/test/jid_test.rb +1 -2
  29. data/test/kit_test.rb +22 -17
  30. data/test/router_test.rb +187 -146
  31. data/test/stanza/iq/disco_info_test.rb +59 -59
  32. data/test/stanza/iq/disco_items_test.rb +36 -34
  33. data/test/stanza/iq/private_storage_test.rb +138 -143
  34. data/test/stanza/iq/roster_test.rb +198 -175
  35. data/test/stanza/iq/session_test.rb +17 -18
  36. data/test/stanza/iq/vcard_test.rb +117 -116
  37. data/test/stanza/iq/version_test.rb +47 -46
  38. data/test/stanza/iq_test.rb +53 -49
  39. data/test/stanza/message_test.rb +92 -89
  40. data/test/stanza/presence/probe_test.rb +2 -5
  41. data/test/stanza/presence/subscribe_test.rb +67 -54
  42. data/test/stanza/pubsub/create_test.rb +86 -108
  43. data/test/stanza/pubsub/delete_test.rb +141 -114
  44. data/test/stanza/pubsub/publish_test.rb +256 -320
  45. data/test/stanza/pubsub/subscribe_test.rb +169 -150
  46. data/test/stanza/pubsub/unsubscribe_test.rb +111 -142
  47. data/test/stanza_test.rb +61 -54
  48. data/test/storage/ldap_test.rb +1 -2
  49. data/test/storage/local_test.rb +3 -5
  50. data/test/storage/null_test.rb +3 -4
  51. data/test/storage/storage_tests.rb +1 -3
  52. data/test/storage_test.rb +1 -2
  53. data/test/store_test.rb +1 -2
  54. data/test/stream/client/auth_test.rb +61 -63
  55. data/test/stream/client/ready_test.rb +7 -8
  56. data/test/stream/client/session_test.rb +19 -18
  57. data/test/stream/component/handshake_test.rb +40 -37
  58. data/test/stream/component/ready_test.rb +76 -61
  59. data/test/stream/component/start_test.rb +7 -8
  60. data/test/stream/http/auth_test.rb +3 -4
  61. data/test/stream/http/ready_test.rb +52 -60
  62. data/test/stream/http/request_test.rb +1 -3
  63. data/test/stream/http/sessions_test.rb +2 -3
  64. data/test/stream/http/start_test.rb +3 -4
  65. data/test/stream/parser_test.rb +3 -4
  66. data/test/stream/sasl_test.rb +105 -86
  67. data/test/stream/server/auth_test.rb +40 -36
  68. data/test/stream/server/outbound/auth_test.rb +3 -4
  69. data/test/stream/server/ready_test.rb +51 -51
  70. data/test/test_helper.rb +42 -0
  71. data/test/token_bucket_test.rb +38 -18
  72. data/test/user_test.rb +79 -49
  73. data/vines.gemspec +33 -0
  74. data/web/chat/javascripts/app.js +1 -1
  75. data/web/lib/coffeescripts/layout.coffee +1 -1
  76. data/web/lib/javascripts/base.js +10 -10
  77. data/web/lib/javascripts/jquery.js +4 -4
  78. metadata +31 -128
  79. data/README +0 -35
  80. data/lib/vines/storage/couchdb.rb +0 -129
  81. data/lib/vines/storage/mongodb.rb +0 -132
  82. data/lib/vines/storage/redis.rb +0 -127
  83. data/lib/vines/storage/sql.rb +0 -220
  84. data/test/rake_test_loader.rb +0 -17
  85. data/test/storage/couchdb_test.rb +0 -107
  86. data/test/storage/mock_mongo.rb +0 -40
  87. data/test/storage/mongodb_test.rb +0 -81
  88. data/test/storage/redis_test.rb +0 -51
  89. data/test/storage/sql_test.rb +0 -62
@@ -1,373 +1,309 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'tmpdir'
4
- require 'vines'
5
- require 'ext/nokogiri'
6
- require 'minitest/autorun'
7
-
8
- class PublishPubSubTest < MiniTest::Unit::TestCase
9
- def setup
10
- @user = Vines::User.new(jid: 'alice@wonderland.lit/tea')
11
- @config = Vines::Config.new do
3
+ require 'test_helper'
4
+
5
+ describe Vines::Stanza::PubSub::Publish do
6
+ subject { Vines::Stanza::PubSub::Publish.new(xml, stream) }
7
+ let(:user) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
8
+ let(:stream) { MiniTest::Mock.new }
9
+ let(:config) do
10
+ Vines::Config.new do
12
11
  host 'wonderland.lit' do
13
12
  storage(:fs) { dir Dir.tmpdir }
14
13
  pubsub 'games'
15
14
  end
16
15
  end
17
- @stream = MiniTest::Mock.new
18
- @stream.expect(:config, @config)
19
- @stream.expect(:user, @user)
20
16
  end
21
17
 
22
- def test_missing_to_address_raises
23
- node = node(%q{
24
- <iq type='set' id='42'>
25
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
26
- <publish node='game_13'>
27
- <item id='item_42'>
28
- <entry xmlns='http://www.w3.org/2005/Atom'>
29
- <title>Test</title>
30
- <summary>This is a summary.</summary>
31
- </entry>
32
- </item>
33
- </publish>
34
- </pubsub>
35
- </iq>
36
- }.strip.gsub(/\n|\s{2,}/, ''))
18
+ before do
19
+ class << stream
20
+ attr_accessor :config, :nodes, :user
21
+ def write(node)
22
+ @nodes ||= []
23
+ @nodes << node
24
+ end
25
+ end
26
+ stream.config = config
27
+ stream.user = user
28
+ end
37
29
 
38
- @stream.expect(:domain, 'wonderland.lit')
30
+ describe 'when missing a to address' do
31
+ let(:xml) { publish('') }
39
32
 
40
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
41
- assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
42
- assert @stream.verify
33
+ it 'raises a feature-not-implemented stanza error' do
34
+ stream.expect(:domain, 'wonderland.lit')
35
+ -> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
36
+ stream.verify
37
+ end
43
38
  end
44
39
 
45
- def test_server_domain_to_address_raises
46
- node = node(%q{
47
- <iq type='set' to='wonderland.lit' id='42'>
48
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
49
- <publish node='game_13'>
50
- <item id='item_42'>
51
- <entry xmlns='http://www.w3.org/2005/Atom'>
52
- <title>Test</title>
53
- <summary>This is a summary.</summary>
54
- </entry>
55
- </item>
56
- </publish>
57
- </pubsub>
58
- </iq>
59
- }.strip.gsub(/\n|\s{2,}/, ''))
60
-
61
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
62
- assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
63
- assert @stream.verify
40
+ describe 'when addressed to bare server domain' do
41
+ let(:xml) { publish('wonderland.lit') }
42
+
43
+ it 'raises a feature-not-implemented stanza error' do
44
+ -> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
45
+ stream.verify
46
+ end
64
47
  end
65
48
 
66
- def test_non_pubsub_to_address_routes
67
- node = node(%q{
68
- <iq type='set' to='bogus.wonderland.lit' id='42'>
69
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
70
- <publish node='game_13'>
71
- <item id='item_42'>
72
- <entry xmlns='http://www.w3.org/2005/Atom'>
73
- <title>Test</title>
74
- <summary>This is a summary.</summary>
75
- </entry>
76
- </item>
77
- </publish>
78
- </pubsub>
79
- </iq>
80
- }.strip.gsub(/\n|\s{2,}/, ''))
81
-
82
- router = MiniTest::Mock.new
83
- router.expect(:route, nil, [node])
84
- @stream.expect(:router, router)
85
-
86
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
87
- stanza.process
88
- assert @stream.verify
89
- assert router.verify
49
+ describe 'when addressed to a non-pubsub component' do
50
+ let(:router) { MiniTest::Mock.new }
51
+ let(:xml) { publish('bogus.wonderland.lit') }
52
+
53
+ before do
54
+ router.expect :route, nil, [xml]
55
+ stream.expect :router, router
56
+ end
57
+
58
+ it 'routes rather than handle locally' do
59
+ subject.process
60
+ stream.verify
61
+ router.verify
62
+ end
90
63
  end
91
64
 
92
- def test_multiple_publish_elements_raises
93
- node = node(%q{
94
- <iq type='set' to='games.wonderland.lit' id='42'>
95
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
96
- <publish node='game_13'>
97
- <item id='item_42'>
98
- <entry xmlns='http://www.w3.org/2005/Atom'>
99
- <title>Test</title>
100
- <summary>This is a summary.</summary>
101
- </entry>
102
- </item>
103
- </publish>
104
- <publish node='game_13'>
105
- <item id='item_42'>
106
- <entry xmlns='http://www.w3.org/2005/Atom'>
107
- <title>Test</title>
108
- <summary>This is a summary.</summary>
109
- </entry>
110
- </item>
111
- </publish>
112
- </pubsub>
113
- </iq>
114
- }.strip.gsub(/\n|\s{2,}/, ''))
115
-
116
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
117
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
118
- assert @stream.verify
65
+ describe 'when publishing to multiple nodes' do
66
+ let(:xml) do
67
+ node(%q{
68
+ <iq type='set' to='games.wonderland.lit' id='42'>
69
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
70
+ <publish node='game_13'>
71
+ <item id='item_42'>
72
+ <entry xmlns='http://www.w3.org/2005/Atom'>
73
+ <title>Test</title>
74
+ <summary>This is a summary.</summary>
75
+ </entry>
76
+ </item>
77
+ </publish>
78
+ <publish node='game_13'>
79
+ <item id='item_42'>
80
+ <entry xmlns='http://www.w3.org/2005/Atom'>
81
+ <title>Test</title>
82
+ <summary>This is a summary.</summary>
83
+ </entry>
84
+ </item>
85
+ </publish>
86
+ </pubsub>
87
+ </iq>
88
+ })
89
+ end
90
+
91
+ it 'raises a bad-request stanza error' do
92
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
93
+ stream.verify
94
+ end
119
95
  end
120
96
 
121
- def test_multiple_item_elements_raises
122
- node = node(%q{
123
- <iq type='set' to='games.wonderland.lit' id='42'>
124
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
125
- <publish node='game_13'>
126
- <item id='item_42'>
127
- <entry xmlns='http://www.w3.org/2005/Atom'>
128
- <title>Test</title>
129
- <summary>This is a summary.</summary>
130
- </entry>
131
- </item>
132
- <item id="item_43">bad</item>
133
- </publish>
134
- </pubsub>
135
- </iq>
136
- }.strip.gsub(/\n|\s{2,}/, ''))
137
-
138
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
139
- def stanza.mock_pubsub; @mock_pubsub; end
140
- def stanza.pubsub
141
- unless @mock_pubsub
142
- @mock_pubsub = MiniTest::Mock.new
143
- @mock_pubsub.expect(:node?, true, ['game_13'])
97
+ describe 'when publishing multiple items' do
98
+ let(:pubsub) { MiniTest::Mock.new }
99
+ let(:xml) do
100
+ node(%q{
101
+ <iq type='set' to='games.wonderland.lit' id='42'>
102
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
103
+ <publish node='game_13'>
104
+ <item id='item_42'>
105
+ <entry xmlns='http://www.w3.org/2005/Atom'>
106
+ <title>Test</title>
107
+ <summary>This is a summary.</summary>
108
+ </entry>
109
+ </item>
110
+ <item id="item_43">bad</item>
111
+ </publish>
112
+ </pubsub>
113
+ </iq>
114
+ })
115
+ end
116
+
117
+ it 'raises a bad-request stanza error' do
118
+ pubsub.expect :node?, true, ['game_13']
119
+ subject.stub :pubsub, pubsub do
120
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
144
121
  end
145
- @mock_pubsub
122
+ stream.verify
123
+ pubsub.verify
146
124
  end
147
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
148
- assert @stream.verify
149
- assert stanza.mock_pubsub.verify
150
125
  end
151
126
 
152
- def test_multiple_payload_elements_raises
153
- node = node(%q{
154
- <iq type='set' to='games.wonderland.lit' id='42'>
155
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
156
- <publish node='game_13'>
157
- <item id='item_42'>
158
- <entry xmlns='http://www.w3.org/2005/Atom'>
159
- <title>Test</title>
160
- <summary>This is a summary.</summary>
161
- </entry>
162
- <entry>bad</entry>
163
- </item>
164
- </publish>
165
- </pubsub>
166
- </iq>
167
- }.strip.gsub(/\n|\s{2,}/, ''))
168
-
169
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
170
- def stanza.mock_pubsub; @mock_pubsub; end
171
- def stanza.pubsub
172
- unless @mock_pubsub
173
- @mock_pubsub = MiniTest::Mock.new
174
- @mock_pubsub.expect(:node?, true, ['game_13'])
127
+ describe 'when publishing one item with multiple payloads' do
128
+ let(:pubsub) { MiniTest::Mock.new }
129
+ let(:xml) do
130
+ node(%q{
131
+ <iq type='set' to='games.wonderland.lit' id='42'>
132
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
133
+ <publish node='game_13'>
134
+ <item id='item_42'>
135
+ <entry xmlns='http://www.w3.org/2005/Atom'>
136
+ <title>Test</title>
137
+ <summary>This is a summary.</summary>
138
+ </entry>
139
+ <entry>bad</entry>
140
+ </item>
141
+ </publish>
142
+ </pubsub>
143
+ </iq>
144
+ })
145
+ end
146
+
147
+ it 'raises a bad-request stanza error' do
148
+ pubsub.expect :node?, true, ['game_13']
149
+ subject.stub :pubsub, pubsub do
150
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
175
151
  end
176
- @mock_pubsub
152
+ stream.verify
153
+ pubsub.verify
177
154
  end
178
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
179
- assert @stream.verify
180
- assert stanza.mock_pubsub.verify
181
155
  end
182
156
 
183
- def test_no_payload_elements_raises
184
- node = node(%q{
185
- <iq type='set' to='games.wonderland.lit' id='42'>
186
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
187
- <publish node='game_13'>
188
- <item id='item_42'>
189
- </item>
190
- </publish>
191
- </pubsub>
192
- </iq>
193
- }.strip.gsub(/\n|\s{2,}/, ''))
194
-
195
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
196
- def stanza.mock_pubsub; @mock_pubsub; end
197
- def stanza.pubsub
198
- unless @mock_pubsub
199
- @mock_pubsub = MiniTest::Mock.new
200
- @mock_pubsub.expect(:node?, true, ['game_13'])
201
- end
202
- @mock_pubsub
157
+ describe 'when publishing with no payload' do
158
+ let(:pubsub) { MiniTest::Mock.new }
159
+ let(:xml) do
160
+ node(%q{
161
+ <iq type='set' to='games.wonderland.lit' id='42'>
162
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
163
+ <publish node='game_13'>
164
+ <item id='item_42'>
165
+ </item>
166
+ </publish>
167
+ </pubsub>
168
+ </iq>
169
+ })
203
170
  end
204
171
 
205
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
206
- assert @stream.verify
207
- assert stanza.mock_pubsub.verify
172
+ it 'raises a bad-request stanza error' do
173
+ pubsub.expect :node?, true, ['game_13']
174
+ subject.stub :pubsub, pubsub do
175
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
176
+ end
177
+ stream.verify
178
+ pubsub.verify
179
+ end
208
180
  end
209
181
 
210
- def test_publish_to_missing_node_raises
211
- node = node(%q{
212
- <iq type='set' to='games.wonderland.lit' id='42'>
213
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
214
- <publish node='game_13'>
215
- <item id='item_42'>
216
- <entry xmlns='http://www.w3.org/2005/Atom'>
217
- <title>Test</title>
218
- <summary>This is a summary.</summary>
219
- </entry>
220
- </item>
221
- </publish>
222
- </pubsub>
223
- </iq>
224
- }.strip.gsub(/\n|\s{2,}/, ''))
225
-
226
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
227
- assert_raises(Vines::StanzaErrors::ItemNotFound) { stanza.process }
228
- assert @stream.verify
182
+ describe 'when publishing to a missing node' do
183
+ let(:xml) { publish('games.wonderland.lit') }
184
+
185
+ it 'raises an item-not-found stanza error' do
186
+ -> { subject.process }.must_raise Vines::StanzaErrors::ItemNotFound
187
+ stream.verify
188
+ end
229
189
  end
230
190
 
231
- def test_generate_item_id
232
- node = node(%q{
233
- <iq type='set' to='games.wonderland.lit' id='42'>
234
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
235
- <publish node='game_13'>
236
- <item>
237
- <entry xmlns='http://www.w3.org/2005/Atom'>
238
- <title>Test</title>
239
- <summary>This is a summary.</summary>
240
- </entry>
241
- </item>
242
- </publish>
243
- </pubsub>
244
- </iq>
245
- }.strip.gsub(/\n|\s{2,}/, ''))
246
-
247
- def @stream.nodes; @nodes; end
248
- def @stream.write(node)
249
- @nodes ||= []
250
- @nodes << node
191
+ describe 'when publishing an item without an id' do
192
+ let(:pubsub) { MiniTest::Mock.new }
193
+ let(:xml) { publish('games.wonderland.lit', '') }
194
+ let(:broadcast) { message_broadcast('') }
195
+ let(:response) do
196
+ node(%q{
197
+ <iq from="games.wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result">
198
+ <pubsub xmlns="http://jabber.org/protocol/pubsub">
199
+ <publish node="game_13">
200
+ <item/>
201
+ </publish>
202
+ </pubsub>
203
+ </iq>})
251
204
  end
252
205
 
253
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
254
- def stanza.mock_pubsub; @mock_pubsub; end
255
- def stanza.pubsub
256
- unless @mock_pubsub
257
- @mock_pubsub = MiniTest::Mock.new
258
- @mock_pubsub.expect(:node?, true, ['game_13'])
259
- def @mock_pubsub.published; @published; end
260
- def @mock_pubsub.publish(node, message)
261
- @published ||= []
262
- @published << [node, message]
263
- end
206
+ before do
207
+ pubsub.expect :node?, true, ['game_13']
208
+ def pubsub.published; @published; end
209
+ def pubsub.publish(node, message)
210
+ @published ||= []
211
+ @published << [node, message]
264
212
  end
265
- @mock_pubsub
266
213
  end
267
- stanza.process
268
-
269
- assert @stream.verify
270
- assert stanza.mock_pubsub.verify
271
- assert_equal 1, @stream.nodes.size
272
-
273
- # test result stanza contains generated item id
274
- expected = node(%q{
275
- <iq from="games.wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result">
276
- <pubsub xmlns="http://jabber.org/protocol/pubsub">
277
- <publish node="game_13">
278
- <item/>
279
- </publish>
280
- </pubsub>
281
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
214
+
215
+ it 'generates an item id in the response' do
216
+ subject.stub :pubsub, pubsub do
217
+ subject.process
218
+ end
219
+ stream.verify
220
+ pubsub.verify
221
+ stream.nodes.size.must_equal 1
222
+
282
223
  # id is random
283
- item = @stream.nodes[0].xpath('ns:pubsub/ns:publish/ns:item', 'ns' => 'http://jabber.org/protocol/pubsub').first
284
- refute_nil item['id']
224
+ item = stream.nodes.first.xpath('ns:pubsub/ns:publish/ns:item',
225
+ 'ns' => 'http://jabber.org/protocol/pubsub').first
226
+ item['id'].wont_be_nil
285
227
  item.remove_attribute('id')
286
- assert_equal expected, @stream.nodes[0]
287
-
288
- # test published message has a generated item id
289
- expected = node(%q{
290
- <message>
291
- <event xmlns="http://jabber.org/protocol/pubsub#event">
292
- <items node="game_13">
293
- <item publisher="alice@wonderland.lit/tea">
294
- <entry xmlns="http://www.w3.org/2005/Atom">
295
- <title>Test</title>
296
- <summary>This is a summary.</summary>
297
- </entry>
298
- </item>
299
- </items>
300
- </event>
301
- </message>
302
- }.strip.gsub(/\n|\s{2,}/, ''))
303
- published_node, published_message = *stanza.mock_pubsub.published[0]
304
- assert_equal 'game_13', published_node
228
+ stream.nodes.first.must_equal response
229
+ end
230
+
231
+ it 'broadcasts the message with the generated item id' do
232
+ subject.stub :pubsub, pubsub do
233
+ subject.process
234
+ end
235
+ stream.verify
236
+ pubsub.verify
237
+ stream.nodes.size.must_equal 1
238
+
239
+ published_node, published_message = *pubsub.published[0]
240
+ published_node.must_equal 'game_13'
305
241
  # id is random
306
- item = published_message.xpath('ns:event/ns:items/ns:item', 'ns' => 'http://jabber.org/protocol/pubsub#event').first
307
- refute_nil item['id']
242
+ item = published_message.xpath('ns:event/ns:items/ns:item',
243
+ 'ns' => 'http://jabber.org/protocol/pubsub#event').first
244
+ item['id'].wont_be_nil
308
245
  item.remove_attribute('id')
309
- assert_equal expected, published_message
246
+ published_message.must_equal broadcast
247
+ end
310
248
  end
311
249
 
312
- def test_good_stanza_processes
313
- node = node(%q{
314
- <iq type='set' to='games.wonderland.lit' id='42'>
315
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
316
- <publish node='game_13'>
317
- <item id='item_42'>
318
- <entry xmlns='http://www.w3.org/2005/Atom'>
319
- <title>Test</title>
320
- <summary>This is a summary.</summary>
321
- </entry>
322
- </item>
323
- </publish>
324
- </pubsub>
325
- </iq>
326
- }.strip.gsub(/\n|\s{2,}/, ''))
327
-
328
- def @stream.nodes; @nodes; end
329
- def @stream.write(node)
330
- @nodes ||= []
331
- @nodes << node
332
- end
250
+ describe 'when publishing a valid stanza' do
251
+ let(:pubsub) { MiniTest::Mock.new }
252
+ let(:xml) { publish('games.wonderland.lit') }
253
+ let(:response) { result(user.jid, 'games.wonderland.lit') }
254
+ let(:broadcast) { message_broadcast('item_42') }
255
+
256
+ it 'broadcasts and returns result to sender' do
257
+ pubsub.expect :node?, true, ['game_13']
258
+ pubsub.expect :publish, nil, ['game_13', broadcast]
333
259
 
334
- stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
335
- def stanza.mock_pubsub; @mock_pubsub; end
336
- def stanza.pubsub
337
- unless @mock_pubsub
338
- xml = %q{
339
- <message>
340
- <event xmlns="http://jabber.org/protocol/pubsub#event">
341
- <items node="game_13">
342
- <item id="item_42" publisher="alice@wonderland.lit/tea">
343
- <entry xmlns="http://www.w3.org/2005/Atom">
344
- <title>Test</title>
345
- <summary>This is a summary.</summary>
346
- </entry>
347
- </item>
348
- </items>
349
- </event>
350
- </message>
351
- }.strip.gsub(/\n|\s{2,}/, '')
352
- @mock_pubsub = MiniTest::Mock.new
353
- @mock_pubsub.expect(:node?, true, ['game_13'])
354
- @mock_pubsub.expect(:publish, nil, ['game_13', Nokogiri::XML(xml).root])
260
+ subject.stub :pubsub, pubsub do
261
+ subject.process
355
262
  end
356
- @mock_pubsub
263
+
264
+ stream.nodes.size.must_equal 1
265
+ stream.nodes.first.must_equal response
266
+ stream.verify
267
+ pubsub.verify
357
268
  end
358
- stanza.process
269
+ end
359
270
 
360
- assert @stream.verify
361
- assert stanza.mock_pubsub.verify
362
- assert_equal 1, @stream.nodes.size
271
+ private
363
272
 
364
- expected = node(%q{<iq from="games.wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result"/>})
365
- assert_equal expected, @stream.nodes[0]
273
+ def message_broadcast(item_id)
274
+ item_id = (item_id.nil? || item_id.empty?) ? ' ' : " id='#{item_id}' "
275
+ node(%Q{
276
+ <message>
277
+ <event xmlns="http://jabber.org/protocol/pubsub#event">
278
+ <items node="game_13">
279
+ <item#{item_id}publisher="alice@wonderland.lit/tea">
280
+ <entry xmlns="http://www.w3.org/2005/Atom">
281
+ <title>Test</title>
282
+ <summary>This is a summary.</summary>
283
+ </entry>
284
+ </item>
285
+ </items>
286
+ </event>
287
+ </message>})
366
288
  end
367
289
 
368
- private
290
+ def publish(to, item_id='item_42')
291
+ item_id = "id='#{item_id}'" unless item_id.nil? || item_id.empty?
292
+ body = %Q{
293
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
294
+ <publish node='game_13'>
295
+ <item #{item_id}>
296
+ <entry xmlns='http://www.w3.org/2005/Atom'>
297
+ <title>Test</title>
298
+ <summary>This is a summary.</summary>
299
+ </entry>
300
+ </item>
301
+ </publish>
302
+ </pubsub>}
303
+ iq(type: 'set', to: to, id: 42, body: body)
304
+ end
369
305
 
370
- def node(xml)
371
- Nokogiri::XML(xml).root
306
+ def result(to, from)
307
+ iq(from: from, id: 42, to: to, type: 'result')
372
308
  end
373
309
  end