vines 0.4.5 → 0.4.6

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 (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,186 +1,205 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'tmpdir'
4
- require 'vines'
5
- require 'ext/nokogiri'
6
- require 'minitest/autorun'
7
-
8
- class SubscribePubSubTest < 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::Subscribe do
6
+ subject { Vines::Stanza::PubSub::Subscribe.new(xml, stream) }
7
+ let(:alice) { 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
- <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
27
- </pubsub>
28
- </iq>
29
- }.strip.gsub(/\n|\s{2,}/, ''))
18
+ before do
19
+ class << stream
20
+ attr_accessor :config, :domain, :nodes, :user
21
+ def write(node)
22
+ @nodes ||= []
23
+ @nodes << node
24
+ end
25
+ end
26
+ stream.config = config
27
+ stream.user = alice
28
+ stream.domain = 'wonderland.lit'
29
+ end
30
30
 
31
- @stream.expect(:domain, 'wonderland.lit')
31
+ describe 'when missing a to address' do
32
+ let(:xml) do
33
+ node(%q{
34
+ <iq type='set' id='42'>
35
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
36
+ <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
37
+ </pubsub>
38
+ </iq>
39
+ })
40
+ end
32
41
 
33
- stanza = Vines::Stanza::PubSub::Subscribe.new(node, @stream)
34
- assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
35
- assert @stream.verify
42
+ it 'raises a feature-not-implemented stanza error' do
43
+ -> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
44
+ stream.verify
45
+ end
36
46
  end
37
47
 
38
- def test_server_domain_to_address_raises
39
- node = node(%q{
40
- <iq type='set' to='wonderland.lit' id='42'>
41
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
42
- <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
43
- </pubsub>
44
- </iq>
45
- }.strip.gsub(/\n|\s{2,}/, ''))
46
-
47
- stanza = Vines::Stanza::PubSub::Subscribe.new(node, @stream)
48
- assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
49
- assert @stream.verify
50
- end
48
+ describe 'when addressed to a bare server domain' do
49
+ let(:xml) do
50
+ node(%q{
51
+ <iq type='set' to='wonderland.lit' id='42'>
52
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
53
+ <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
54
+ </pubsub>
55
+ </iq>
56
+ })
57
+ end
51
58
 
52
- def test_non_pubsub_to_address_routes
53
- node = node(%q{
54
- <iq type='set' to='bogus.wonderland.lit' id='42'>
55
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
56
- <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
57
- </pubsub>
58
- </iq>
59
- }.strip.gsub(/\n|\s{2,}/, ''))
59
+ it 'raises a feature-not-implemented stanza error' do
60
+ -> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
61
+ stream.verify
62
+ end
63
+ end
60
64
 
61
- router = MiniTest::Mock.new
62
- router.expect(:route, nil, [node])
65
+ describe 'when addressed to a non-pubsub address' do
66
+ let(:router) { MiniTest::Mock.new }
67
+ let(:xml) do
68
+ node(%q{
69
+ <iq type='set' to='bogus.wonderland.lit' id='42'>
70
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
71
+ <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
72
+ </pubsub>
73
+ </iq>
74
+ })
75
+ end
63
76
 
64
- @stream.expect(:router, router)
77
+ it 'routes rather than handle locally' do
78
+ router.expect :route, nil, [xml]
79
+ stream.expect :router, router
65
80
 
66
- stanza = Vines::Stanza::PubSub::Subscribe.new(node, @stream)
67
- stanza.process
68
- assert @stream.verify
69
- assert router.verify
81
+ subject.process
82
+ stream.verify
83
+ router.verify
84
+ end
70
85
  end
71
86
 
72
- def test_multiple_subscribe_elements_raises
73
- node = node(%q{
74
- <iq type='set' to='games.wonderland.lit' id='42'>
75
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
76
- <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
77
- <subscribe node='game_14' jid="alice@wonderland.lit/tea"/>
78
- </pubsub>
79
- </iq>
80
- }.strip.gsub(/\n|\s{2,}/, ''))
81
-
82
- stanza = Vines::Stanza::PubSub::Subscribe.new(node, @stream)
83
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
84
- assert @stream.verify
87
+ describe 'when stanza contains multiple subscribe elements' do
88
+ let(:xml) do
89
+ node(%q{
90
+ <iq type='set' to='games.wonderland.lit' id='42'>
91
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
92
+ <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
93
+ <subscribe node='game_14' jid="alice@wonderland.lit/tea"/>
94
+ </pubsub>
95
+ </iq>
96
+ })
97
+ end
98
+
99
+ it 'raises a bad-request stanza error' do
100
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
101
+ stream.verify
102
+ end
85
103
  end
86
104
 
87
- def test_subscribe_missing_node_raises
88
- node = node(%q{
89
- <iq type='set' to='games.wonderland.lit' id='42'>
90
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
91
- <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
92
- </pubsub>
93
- </iq>
94
- }.strip.gsub(/\n|\s{2,}/, ''))
95
-
96
- stanza = Vines::Stanza::PubSub::Subscribe.new(node, @stream)
97
- assert_raises(Vines::StanzaErrors::ItemNotFound) { stanza.process }
98
- assert @stream.verify
105
+ describe 'when stanza is missing a subscribe element' do
106
+ let(:xml) do
107
+ node(%q{
108
+ <iq type='set' to='games.wonderland.lit' id='42'>
109
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
110
+ <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
111
+ </pubsub>
112
+ </iq>
113
+ })
114
+ end
115
+
116
+ it 'raises an item-not-found stanza error' do
117
+ -> { subject.process }.must_raise Vines::StanzaErrors::ItemNotFound
118
+ stream.verify
119
+ end
99
120
  end
100
121
 
101
- def test_subscribe_twice_raises
102
- node = node(%q{
103
- <iq type='set' to='games.wonderland.lit' id='42'>
104
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
105
- <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
106
- </pubsub>
107
- </iq>
108
- }.strip.gsub(/\n|\s{2,}/, ''))
109
-
110
- stanza = Vines::Stanza::PubSub::Subscribe.new(node, @stream)
111
- def stanza.mock_pubsub; @mock_pubsub; end
112
- def stanza.pubsub
113
- unless @mock_pubsub
114
- @mock_pubsub = MiniTest::Mock.new
115
- @mock_pubsub.expect(:node?, true, ['game_13'])
116
- @mock_pubsub.expect(:subscribed?, true, ['game_13', Vines::JID.new('alice@wonderland.lit/tea')])
122
+ describe 'when attempting to subscribe to a node twice' do
123
+ let(:pubsub) { MiniTest::Mock.new }
124
+ let(:xml) do
125
+ node(%q{
126
+ <iq type='set' to='games.wonderland.lit' id='42'>
127
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
128
+ <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
129
+ </pubsub>
130
+ </iq>
131
+ })
132
+ end
133
+
134
+ before do
135
+ pubsub.expect :node?, true, ['game_13']
136
+ pubsub.expect :subscribed?, true, ['game_13', alice.jid]
137
+ end
138
+
139
+ it 'raises a policy-violation stanza error' do
140
+ subject.stub :pubsub, pubsub do
141
+ -> { subject.process }.must_raise Vines::StanzaErrors::PolicyViolation
117
142
  end
118
- @mock_pubsub
143
+ stream.verify
144
+ pubsub.verify
119
145
  end
120
- assert_raises(Vines::StanzaErrors::PolicyViolation) { stanza.process }
121
- assert @stream.verify
122
- assert stanza.mock_pubsub.verify
123
146
  end
124
147
 
125
- def test_subscribe_illegal_jid_raises
126
- node = node(%q{
127
- <iq type='set' to='games.wonderland.lit' id='42'>
128
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
129
- <subscribe node='game_13' jid="not_alice@wonderland.lit/tea"/>
130
- </pubsub>
131
- </iq>
132
- }.strip.gsub(/\n|\s{2,}/, ''))
133
-
134
- stanza = Vines::Stanza::PubSub::Subscribe.new(node, @stream)
135
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
136
- assert @stream.verify
148
+ describe 'when subscribing with an illegal jid' do
149
+ let(:xml) do
150
+ node(%q{
151
+ <iq type='set' to='games.wonderland.lit' id='42'>
152
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
153
+ <subscribe node='game_13' jid="not_alice@wonderland.lit/tea"/>
154
+ </pubsub>
155
+ </iq>
156
+ })
157
+ end
158
+
159
+ it 'raises a bad-request stanza error' do
160
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
161
+ stream.verify
162
+ end
137
163
  end
138
164
 
139
- def test_good_stanza_processes
140
- node = node(%q{
141
- <iq type='set' to='games.wonderland.lit' id='42'>
142
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
143
- <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
144
- </pubsub>
145
- </iq>
146
- }.strip.gsub(/\n|\s{2,}/, ''))
147
-
148
- def @stream.nodes; @nodes; end
149
- def @stream.write(node)
150
- @nodes ||= []
151
- @nodes << node
152
- end
153
-
154
- stanza = Vines::Stanza::PubSub::Subscribe.new(node, @stream)
155
- def stanza.mock_pubsub; @mock_pubsub; end
156
- def stanza.pubsub
157
- unless @mock_pubsub
158
- @mock_pubsub = MiniTest::Mock.new
159
- @mock_pubsub.expect(:node?, true, ['game_13'])
160
- @mock_pubsub.expect(:subscribed?, false, ['game_13', Vines::JID.new('alice@wonderland.lit/tea')])
161
- @mock_pubsub.expect(:subscribe, nil, ['game_13', Vines::JID.new('alice@wonderland.lit/tea')])
162
- end
163
- @mock_pubsub
165
+ describe 'when subscribing with a valid stanza' do
166
+ let(:xml) do
167
+ node(%q{
168
+ <iq type='set' to='games.wonderland.lit' id='42'>
169
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
170
+ <subscribe node='game_13' jid="alice@wonderland.lit/tea"/>
171
+ </pubsub>
172
+ </iq>
173
+ })
164
174
  end
165
- stanza.process
166
175
 
167
- assert @stream.verify
168
- assert stanza.mock_pubsub.verify
169
- assert_equal 1, @stream.nodes.size
176
+ let(:expected) do
177
+ node(%q{
178
+ <iq from="games.wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result">
179
+ <pubsub xmlns="http://jabber.org/protocol/pubsub">
180
+ <subscription node="game_13" jid="alice@wonderland.lit/tea" subscription="subscribed"/>
181
+ </pubsub>
182
+ </iq>
183
+ })
184
+ end
170
185
 
171
- expected = node(%q{
172
- <iq from="games.wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result">
173
- <pubsub xmlns="http://jabber.org/protocol/pubsub">
174
- <subscription node="game_13" jid="alice@wonderland.lit/tea" subscription="subscribed"/>
175
- </pubsub>
176
- </iq>
177
- }.strip.gsub(/\n|\s{2,}/, ''))
178
- assert_equal expected, @stream.nodes[0]
179
- end
186
+ let(:pubsub) { MiniTest::Mock.new }
180
187
 
181
- private
188
+ before do
189
+ pubsub.expect :node?, true, ['game_13']
190
+ pubsub.expect :subscribed?, false, ['game_13', alice.jid]
191
+ pubsub.expect :subscribe, nil, ['game_13', alice.jid]
192
+ end
193
+
194
+ it 'writes a result stanza to the stream' do
195
+ subject.stub :pubsub, pubsub do
196
+ subject.process
197
+ end
182
198
 
183
- def node(xml)
184
- Nokogiri::XML(xml).root
199
+ stream.verify
200
+ pubsub.verify
201
+ stream.nodes.size.must_equal 1
202
+ stream.nodes.first.must_equal expected
203
+ end
185
204
  end
186
205
  end
@@ -1,179 +1,148 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'tmpdir'
4
- require 'vines'
5
- require 'ext/nokogiri'
6
- require 'minitest/autorun'
7
-
8
- class UnsubscribePubSubTest < 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::Unsubscribe do
6
+ subject { Vines::Stanza::PubSub::Unsubscribe.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
- <unsubscribe node='game_13' jid="alice@wonderland.lit/tea"/>
27
- </pubsub>
28
- </iq>
29
- }.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
30
29
 
31
- @stream.expect(:domain, 'wonderland.lit')
30
+ describe 'when missing a to address' do
31
+ let(:xml) { unsubscribe('') }
32
32
 
33
- stanza = Vines::Stanza::PubSub::Unsubscribe.new(node, @stream)
34
- assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
35
- 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
36
38
  end
37
39
 
38
- def test_server_domain_to_address_raises
39
- node = node(%q{
40
- <iq type='set' to='wonderland.lit' id='42'>
41
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
42
- <unsubscribe node='game_13' jid="alice@wonderland.lit/tea"/>
43
- </pubsub>
44
- </iq>
45
- }.strip.gsub(/\n|\s{2,}/, ''))
46
-
47
- stanza = Vines::Stanza::PubSub::Unsubscribe.new(node, @stream)
48
- assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
49
- assert @stream.verify
40
+ describe 'when addressed to bare server domain' do
41
+ let(:xml) { unsubscribe('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
50
47
  end
51
48
 
52
- def test_non_pubsub_to_address_routes
53
- node = node(%q{
54
- <iq type='set' to='bogus.wonderland.lit' id='42'>
55
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
56
- <unsubscribe node='game_13' jid="alice@wonderland.lit/tea"/>
57
- </pubsub>
58
- </iq>
59
- }.strip.gsub(/\n|\s{2,}/, ''))
60
-
61
- router = MiniTest::Mock.new
62
- router.expect(:route, nil, [node])
63
- @stream.expect(:router, router)
64
-
65
- stanza = Vines::Stanza::PubSub::Unsubscribe.new(node, @stream)
66
- stanza.process
67
- assert @stream.verify
68
- assert router.verify
49
+ describe 'when addressed to a non-pubsub component' do
50
+ let(:router) { MiniTest::Mock.new }
51
+ let(:xml) { unsubscribe('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
69
63
  end
70
64
 
71
- def test_multiple_unsubscribe_elements_raises
72
- node = node(%q{
73
- <iq type='set' to='games.wonderland.lit' id='42'>
74
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
75
- <unsubscribe node='game_13' jid="alice@wonderland.lit/tea"/>
76
- <unsubscribe node='game_14' jid="alice@wonderland.lit/tea"/>
77
- </pubsub>
78
- </iq>
79
- }.strip.gsub(/\n|\s{2,}/, ''))
80
-
81
- stanza = Vines::Stanza::PubSub::Unsubscribe.new(node, @stream)
82
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
83
- assert @stream.verify
65
+ describe 'when attempting to unsubscribe from multiple nodes' do
66
+ let(:xml) { unsubscribe('games.wonderland.lit', true) }
67
+
68
+ it 'raises a bad-request stanza error' do
69
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
70
+ stream.verify
71
+ end
84
72
  end
85
73
 
86
- def test_unsubscribe_missing_node_raises
87
- node = node(%q{
88
- <iq type='set' to='games.wonderland.lit' id='42'>
89
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
90
- <unsubscribe node='game_13' jid="alice@wonderland.lit/tea"/>
91
- </pubsub>
92
- </iq>
93
- }.strip.gsub(/\n|\s{2,}/, ''))
94
-
95
- stanza = Vines::Stanza::PubSub::Unsubscribe.new(node, @stream)
96
- assert_raises(Vines::StanzaErrors::ItemNotFound) { stanza.process }
97
- assert @stream.verify
74
+ describe 'when unsubscribing from a missing node' do
75
+ let(:xml) { unsubscribe('games.wonderland.lit') }
76
+
77
+ it 'raises an item-not-found stanza error' do
78
+ -> { subject.process }.must_raise Vines::StanzaErrors::ItemNotFound
79
+ stream.verify
80
+ end
98
81
  end
99
82
 
100
- def test_unsubscribe_without_subscription_raises
101
- node = node(%q{
102
- <iq type='set' to='games.wonderland.lit' id='42'>
103
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
104
- <unsubscribe node='game_13' jid="alice@wonderland.lit/tea"/>
105
- </pubsub>
106
- </iq>
107
- }.strip.gsub(/\n|\s{2,}/, ''))
108
-
109
- stanza = Vines::Stanza::PubSub::Unsubscribe.new(node, @stream)
110
- def stanza.mock_pubsub; @mock_pubsub; end
111
- def stanza.pubsub
112
- unless @mock_pubsub
113
- @mock_pubsub = MiniTest::Mock.new
114
- @mock_pubsub.expect(:node?, true, ['game_13'])
115
- @mock_pubsub.expect(:subscribed?, false, ['game_13', Vines::JID.new('alice@wonderland.lit/tea')])
83
+ describe 'when unsubscribing without a subscription' do
84
+ let(:pubsub) { MiniTest::Mock.new }
85
+ let(:xml) { unsubscribe('games.wonderland.lit') }
86
+
87
+ before do
88
+ pubsub.expect :node?, true, ['game_13']
89
+ pubsub.expect :subscribed?, false, ['game_13', user.jid]
90
+ end
91
+
92
+ it 'raises an unexpected-request stanza error' do
93
+ subject.stub :pubsub, pubsub do
94
+ -> { subject.process }.must_raise Vines::StanzaErrors::UnexpectedRequest
116
95
  end
117
- @mock_pubsub
96
+ stream.verify
97
+ pubsub.verify
118
98
  end
119
- assert_raises(Vines::StanzaErrors::UnexpectedRequest) { stanza.process }
120
- assert @stream.verify
121
- assert stanza.mock_pubsub.verify
122
99
  end
123
100
 
124
- def test_unsubscribe_illegal_jid_raises
125
- node = node(%q{
126
- <iq type='set' to='games.wonderland.lit' id='42'>
127
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
128
- <unsubscribe node='game_13' jid="not_alice@wonderland.lit/tea"/>
129
- </pubsub>
130
- </iq>
131
- }.strip.gsub(/\n|\s{2,}/, ''))
132
-
133
- stanza = Vines::Stanza::PubSub::Unsubscribe.new(node, @stream)
134
- assert_raises(Vines::StanzaErrors::Forbidden) { stanza.process }
135
- assert @stream.verify
136
- end
101
+ describe 'when unsubscribing an illegal jid' do
102
+ let(:xml) { unsubscribe('games.wonderland.lit', false, 'not_alice@wonderland.lit/tea') }
137
103
 
138
- def test_good_stanza_processes
139
- node = node(%q{
140
- <iq type='set' to='games.wonderland.lit' id='42'>
141
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
142
- <unsubscribe node='game_13' jid="alice@wonderland.lit/tea"/>
143
- </pubsub>
144
- </iq>
145
- }.strip.gsub(/\n|\s{2,}/, ''))
146
-
147
- def @stream.nodes; @nodes; end
148
- def @stream.write(node)
149
- @nodes ||= []
150
- @nodes << node
104
+ it 'raises a forbidden stanza error' do
105
+ -> { subject.process }.must_raise Vines::StanzaErrors::Forbidden
106
+ stream.verify
151
107
  end
108
+ end
152
109
 
153
- stanza = Vines::Stanza::PubSub::Unsubscribe.new(node, @stream)
154
- def stanza.mock_pubsub; @mock_pubsub; end
155
- def stanza.pubsub
156
- unless @mock_pubsub
157
- @mock_pubsub = MiniTest::Mock.new
158
- @mock_pubsub.expect(:node?, true, ['game_13'])
159
- @mock_pubsub.expect(:subscribed?, true, ['game_13', Vines::JID.new('alice@wonderland.lit/tea')])
160
- @mock_pubsub.expect(:unsubscribe, nil, ['game_13', Vines::JID.new('alice@wonderland.lit/tea')])
161
- end
162
- @mock_pubsub
110
+ describe 'when given a valid stanza' do
111
+ let(:pubsub) { MiniTest::Mock.new }
112
+ let(:xml) { unsubscribe('games.wonderland.lit') }
113
+ let(:expected) { result(user.jid, 'games.wonderland.lit') }
114
+
115
+ before do
116
+ pubsub.expect :node?, true, ['game_13']
117
+ pubsub.expect :subscribed?, true, ['game_13', user.jid]
118
+ pubsub.expect :unsubscribe, nil, ['game_13', user.jid]
163
119
  end
164
- stanza.process
165
120
 
166
- assert @stream.verify
167
- assert stanza.mock_pubsub.verify
168
- assert_equal 1, @stream.nodes.size
121
+ it 'sends an iq result stanza to sender' do
122
+ subject.stub :pubsub, pubsub do
123
+ subject.process
124
+ end
169
125
 
170
- expected = node(%q{<iq from="games.wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result"/>})
171
- assert_equal expected, @stream.nodes[0]
126
+ stream.nodes.size.must_equal 1
127
+ stream.nodes.first.must_equal expected
128
+ stream.verify
129
+ pubsub.verify
130
+ end
172
131
  end
173
132
 
174
133
  private
175
134
 
176
- def node(xml)
177
- Nokogiri::XML(xml).root
135
+ def unsubscribe(to, multiple=false, jid=user.jid)
136
+ extra = "<unsubscribe node='game_14' jid='#{jid}'/>" if multiple
137
+ body = %Q{
138
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
139
+ <unsubscribe node='game_13' jid="#{jid}"/>
140
+ #{extra}
141
+ </pubsub>}
142
+ iq(type: 'set', to: to, id: 42, body: body)
143
+ end
144
+
145
+ def result(to, from)
146
+ iq(from: from, id: 42, to: to, type: 'result')
178
147
  end
179
148
  end