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,70 +1,83 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'vines'
4
- require 'ext/nokogiri'
5
- require 'minitest/autorun'
3
+ require 'test_helper'
6
4
 
7
- class SubscribeTest < MiniTest::Unit::TestCase
8
- def test_outbound_subscribe_to_local_jid_but_missing_contact
9
- alice = Vines::JID.new('alice@wonderland.lit/tea')
10
- hatter = Vines::JID.new('hatter@wonderland.lit')
5
+ describe Vines::Stanza::Presence::Subscribe do
6
+ subject { Vines::Stanza::Presence::Subscribe.new(xml, stream) }
7
+ let(:stream) { MiniTest::Mock.new }
8
+ let(:alice) { Vines::JID.new('alice@wonderland.lit/tea') }
9
+ let(:hatter) { Vines::JID.new('hatter@wonderland.lit') }
10
+ let(:contact) { Vines::Contact.new(jid: hatter) }
11
11
 
12
- contact = Vines::Contact.new(:jid => hatter)
12
+ before do
13
+ class << stream
14
+ attr_accessor :user, :nodes
15
+ def write(node)
16
+ @nodes ||= []
17
+ @nodes << node
18
+ end
19
+ end
20
+ end
13
21
 
14
- user = MiniTest::Mock.new
15
- user.expect(:jid, alice)
16
- user.expect(:request_subscription, nil, [hatter])
17
- user.expect(:contact, contact, [hatter])
22
+ describe 'outbound subscription to a local jid, but missing contact' do
23
+ let(:xml) { node(%q{<presence id="42" to="hatter@wonderland.lit" type="subscribe"/>}) }
24
+ let(:user) { MiniTest::Mock.new }
25
+ let(:storage) { MiniTest::Mock.new }
26
+ let(:recipient) { MiniTest::Mock.new }
18
27
 
19
- storage = MiniTest::Mock.new
20
- storage.expect(:save_user, nil, [user])
21
- storage.expect(:find_user, nil, [hatter])
28
+ before do
29
+ class << user
30
+ attr_accessor :jid
31
+ end
32
+ user.jid = alice
33
+ user.expect :request_subscription, nil, [hatter]
34
+ user.expect :contact, contact, [hatter]
22
35
 
23
- recipient = MiniTest::Mock.new
24
- recipient.expect(:user, user)
25
- def recipient.nodes; @nodes; end
26
- def recipient.write(node)
27
- @nodes ||= []
28
- @nodes << node
29
- end
36
+ storage.expect :save_user, nil, [user]
37
+ storage.expect :find_user, nil, [hatter]
30
38
 
31
- stream = MiniTest::Mock.new
32
- stream.expect(:domain, 'wonderland.lit')
33
- stream.expect(:storage, storage, ['wonderland.lit'])
34
- stream.expect(:user, user)
35
- stream.expect(:interested_resources, [recipient], [alice])
36
- stream.expect(:update_user_streams, nil, [user])
37
- def stream.nodes; @nodes; end
38
- def stream.write(node)
39
- @nodes ||= []
40
- @nodes << node
41
- end
39
+ recipient.expect :user, user
40
+ class << recipient
41
+ attr_accessor :nodes
42
+ def write(node)
43
+ @nodes ||= []
44
+ @nodes << node
45
+ end
46
+ end
42
47
 
43
- node = node(%q{<presence id="42" to="hatter@wonderland.lit" type="subscribe"/>})
44
- stanza = Vines::Stanza::Presence::Subscribe.new(node, stream)
45
- def stanza.route_iq; false; end
46
- def stanza.inbound?; false; end
47
- def stanza.local?; true; end
48
+ stream.user = user
49
+ stream.expect :domain, 'wonderland.lit'
50
+ stream.expect :storage, storage, ['wonderland.lit']
51
+ stream.expect :storage, storage, ['wonderland.lit']
52
+ stream.expect :interested_resources, [recipient], [alice]
53
+ stream.expect :update_user_streams, nil, [user]
48
54
 
49
- stanza.process
50
- assert stream.verify
51
- assert user.verify
52
- assert storage.verify
53
- assert_equal 1, stream.nodes.size
54
- assert_equal 1, recipient.nodes.size
55
+ class << subject
56
+ def route_iq; false; end
57
+ def inbound?; false; end
58
+ def local?; true; end
59
+ end
60
+ end
55
61
 
56
- expected = node(%q{<presence from="hatter@wonderland.lit" id="42" to="alice@wonderland.lit" type="unsubscribed"/>})
57
- assert_equal expected, stream.nodes[0]
62
+ it 'rejects the subscription with an unsubscribed response' do
63
+ subject.process
64
+ stream.verify
65
+ user.verify
66
+ storage.verify
67
+ stream.nodes.size.must_equal 1
58
68
 
59
- query = %q{<query xmlns="jabber:iq:roster"><item jid="hatter@wonderland.lit" subscription="none"/></query>}
60
- expected = node(%Q{<iq to="alice@wonderland.lit/tea" type="set">#{query}</iq>})
61
- recipient.nodes[0].remove_attribute('id') # id is random
62
- assert_equal expected, recipient.nodes[0]
63
- end
69
+ expected = node(%q{<presence from="hatter@wonderland.lit" id="42" to="alice@wonderland.lit" type="unsubscribed"/>})
70
+ stream.nodes.first.must_equal expected
71
+ end
64
72
 
65
- private
73
+ it 'sends a roster set to the interested resources with subscription none' do
74
+ subject.process
75
+ recipient.nodes.size.must_equal 1
66
76
 
67
- def node(xml)
68
- Nokogiri::XML(xml).root
77
+ query = %q{<query xmlns="jabber:iq:roster"><item jid="hatter@wonderland.lit" subscription="none"/></query>}
78
+ expected = node(%Q{<iq to="alice@wonderland.lit/tea" type="set">#{query}</iq>})
79
+ recipient.nodes.first.remove_attribute('id') # id is random
80
+ recipient.nodes.first.must_equal expected
81
+ end
69
82
  end
70
83
  end
@@ -1,138 +1,116 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'tmpdir'
4
- require 'vines'
5
- require 'ext/nokogiri'
6
- require 'minitest/autorun'
7
-
8
- class CreatePubSubTest < 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::Create do
6
+ subject { Vines::Stanza::PubSub::Create.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
- <create node='game_13'/>
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) { create('') }
32
32
 
33
- stanza = Vines::Stanza::PubSub::Create.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
- <create node='game_13'/>
43
- </pubsub>
44
- </iq>
45
- }.strip.gsub(/\n|\s{2,}/, ''))
46
-
47
- stanza = Vines::Stanza::PubSub::Create.new(node, @stream)
48
- assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
49
- assert @stream.verify
50
- end
40
+ describe 'when addressed to bare server domain' do
41
+ let(:xml) { create('wonderland.lit') }
51
42
 
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
- <create node='game_13'/>
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::Create.new(node, @stream)
66
- stanza.process
67
- assert @stream.verify
68
- assert router.verify
43
+ it 'raises a feature-not-implemented stanza error' do
44
+ -> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
45
+ stream.verify
46
+ end
69
47
  end
70
48
 
71
- def test_multiple_create_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
- <create node='game_13'/>
76
- <create node='game_14'/>
77
- </pubsub>
78
- </iq>
79
- }.strip.gsub(/\n|\s{2,}/, ''))
80
-
81
- stanza = Vines::Stanza::PubSub::Create.new(node, @stream)
82
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
83
- assert @stream.verify
84
- end
49
+ describe 'when addressed to a non-pubsub component' do
50
+ let(:router) { MiniTest::Mock.new }
51
+ let(:xml) { create('bogus.wonderland.lit') }
52
+
53
+ before do
54
+ router.expect :route, nil, [xml]
55
+ stream.expect :router, router
56
+ end
85
57
 
86
- def test_create_duplicate_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
- <create node='game_13'/>
91
- </pubsub>
92
- </iq>
93
- }.strip.gsub(/\n|\s{2,}/, ''))
94
-
95
- stanza = Vines::Stanza::PubSub::Create.new(node, @stream)
96
- def stanza.pubsub
97
- pubsub = MiniTest::Mock.new
98
- pubsub.expect(:node?, true, ['game_13'])
99
- pubsub
58
+ it 'routes rather than handle locally' do
59
+ subject.process
60
+ stream.verify
61
+ router.verify
100
62
  end
101
- assert_raises(Vines::StanzaErrors::Conflict) { stanza.process }
102
- assert @stream.verify
103
63
  end
104
64
 
105
- def test_good_stanza_processes
106
- node = node(%q{
107
- <iq type='set' to='games.wonderland.lit' id='42'>
108
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
109
- <create node='game_13'/>
110
- </pubsub>
111
- </iq>
112
- }.strip.gsub(/\n|\s{2,}/, ''))
113
-
114
- def @stream.nodes; @nodes; end
115
- def @stream.write(node)
116
- @nodes ||= []
117
- @nodes << node
65
+ describe 'when attempting to create multiple nodes' do
66
+ let(:xml) { create('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
118
71
  end
72
+ end
119
73
 
120
- stanza = Vines::Stanza::PubSub::Create.new(node, @stream)
121
- stanza.process
74
+ describe 'when attempting to create duplicate nodes' do
75
+ let(:pubsub) { MiniTest::Mock.new }
76
+ let(:xml) { create('games.wonderland.lit') }
122
77
 
123
- assert @stream.verify
124
- assert_equal 1, @stream.nodes.size
78
+ it 'raises a conflict stanza error' do
79
+ pubsub.expect :node?, true, ['game_13']
80
+ subject.stub :pubsub, pubsub do
81
+ -> { subject.process }.must_raise Vines::StanzaErrors::Conflict
82
+ end
83
+ stream.verify
84
+ pubsub.verify
85
+ end
86
+ end
125
87
 
126
- expected = %q{<iq from="games.wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result">}
127
- expected << %q{<pubsub xmlns="http://jabber.org/protocol/pubsub"><create node="game_13"/></pubsub>}
128
- expected << %q{</iq>}
129
- expected = node(expected)
130
- assert_equal expected, @stream.nodes[0]
88
+ describe 'when given a valid stanza' do
89
+ let(:xml) { create('games.wonderland.lit') }
90
+ let(:expected) { result(user.jid, 'games.wonderland.lit') }
91
+
92
+ it 'sends an iq result stanza to sender' do
93
+ subject.process
94
+ stream.nodes.size.must_equal 1
95
+ stream.nodes.first.must_equal expected
96
+ stream.verify
97
+ end
131
98
  end
132
99
 
133
100
  private
134
101
 
135
- def node(xml)
136
- Nokogiri::XML(xml).root
102
+ def create(to, multiple=false)
103
+ extra_create = "<create node='game_14'/>" if multiple
104
+ body = %Q{
105
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
106
+ <create node='game_13'/>
107
+ #{extra_create}
108
+ </pubsub>}
109
+ iq(type: 'set', to: to, id: 42, body: body)
110
+ end
111
+
112
+ def result(to, from)
113
+ body = '<pubsub xmlns="http://jabber.org/protocol/pubsub"><create node="game_13"/></pubsub>'
114
+ iq(from: from, id: 42, to: to, type: 'result', body: body)
137
115
  end
138
116
  end
@@ -1,142 +1,169 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'tmpdir'
4
- require 'vines'
5
- require 'ext/nokogiri'
6
- require 'minitest/autorun'
7
-
8
- class DeletePubSubTest < 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::Delete do
6
+ subject { Vines::Stanza::PubSub::Delete.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
- <delete node='game_13'/>
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.domain = 'wonderland.lit'
28
+ stream.user = alice
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
+ <delete node='game_13'/>
37
+ </pubsub>
38
+ </iq>
39
+ })
40
+ end
32
41
 
33
- stanza = Vines::Stanza::PubSub::Delete.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
- <delete node='game_13'/>
43
- </pubsub>
44
- </iq>
45
- }.strip.gsub(/\n|\s{2,}/, ''))
46
-
47
- stanza = Vines::Stanza::PubSub::Delete.new(node, @stream)
48
- assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
49
- assert @stream.verify
48
+ describe 'when addressed to a bare server domain jid' 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
+ <delete node='game_13'/>
54
+ </pubsub>
55
+ </iq>
56
+ })
57
+ end
58
+
59
+ it 'raises a feature-not-implemented stanza error' do
60
+ -> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
61
+ stream.verify
62
+ end
50
63
  end
51
64
 
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
- <delete node='game_13'/>
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::Delete.new(node, @stream)
66
- stanza.process
67
- assert @stream.verify
68
- assert router.verify
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
+ <delete node='game_13'/>
72
+ </pubsub>
73
+ </iq>
74
+ })
75
+ end
76
+
77
+ before do
78
+ router.expect :route, nil, [xml]
79
+ stream.expect :router, router
80
+ end
81
+
82
+ it 'routes rather than handle locally' do
83
+ subject.process
84
+ stream.verify
85
+ router.verify
86
+ end
69
87
  end
70
88
 
71
- def test_multiple_delete_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
- <delete node='game_13'/>
76
- <delete node='game_14'/>
77
- </pubsub>
78
- </iq>
79
- }.strip.gsub(/\n|\s{2,}/, ''))
80
-
81
- stanza = Vines::Stanza::PubSub::Delete.new(node, @stream)
82
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
83
- assert @stream.verify
89
+ describe 'when stanza contains multiple delete elements' do
90
+ let(:xml) do
91
+ node(%q{
92
+ <iq type='set' to='games.wonderland.lit' id='42'>
93
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
94
+ <delete node='game_13'/>
95
+ <delete node='game_14'/>
96
+ </pubsub>
97
+ </iq>
98
+ })
99
+ end
100
+
101
+ it 'raises a bad-request stanza error' do
102
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
103
+ stream.verify
104
+ end
84
105
  end
85
106
 
86
- def test_delete_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
- <delete node='game_13'/>
91
- </pubsub>
92
- </iq>
93
- }.strip.gsub(/\n|\s{2,}/, ''))
94
-
95
- stanza = Vines::Stanza::PubSub::Delete.new(node, @stream)
96
- assert_raises(Vines::StanzaErrors::ItemNotFound) { stanza.process }
97
- assert @stream.verify
107
+ describe 'when deleting a missing node' do
108
+ let(:xml) do
109
+ node(%q{
110
+ <iq type='set' to='games.wonderland.lit' id='42'>
111
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
112
+ <delete node='game_13'/>
113
+ </pubsub>
114
+ </iq>
115
+ })
116
+ end
117
+
118
+ it 'raises an item-not-found stanza error' do
119
+ -> { subject.process }.must_raise Vines::StanzaErrors::ItemNotFound
120
+ stream.verify
121
+ end
98
122
  end
99
123
 
100
- def test_good_stanza_processes
101
- node = node(%q{
102
- <iq type='set' to='games.wonderland.lit' id='42'>
103
- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
104
- <delete node='game_13'/>
105
- </pubsub>
106
- </iq>
107
- }.strip.gsub(/\n|\s{2,}/, ''))
108
-
109
- def @stream.nodes; @nodes; end
110
- def @stream.write(node)
111
- @nodes ||= []
112
- @nodes << node
113
- end
114
-
115
- stanza = Vines::Stanza::PubSub::Delete.new(node, @stream)
116
- def stanza.mock_pubsub; @mock_pubsub; end
117
- def stanza.pubsub
118
- unless @mock_pubsub
119
- xml = %q{<message><event xmlns="http://jabber.org/protocol/pubsub#event"><delete node="game_13"/></event></message>}
120
- @mock_pubsub = MiniTest::Mock.new
121
- @mock_pubsub.expect(:node?, true, ['game_13'])
122
- @mock_pubsub.expect(:publish, nil, ['game_13', Nokogiri::XML(xml).root])
123
- @mock_pubsub.expect(:delete_node, nil, ['game_13'])
124
- end
125
- @mock_pubsub
124
+ describe 'when valid stanza is received' do
125
+ let(:pubsub) { MiniTest::Mock.new }
126
+ let(:xml) do
127
+ node(%q{
128
+ <iq type='set' to='games.wonderland.lit' id='42'>
129
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
130
+ <delete node='game_13'/>
131
+ </pubsub>
132
+ </iq>
133
+ })
126
134
  end
127
- stanza.process
128
135
 
129
- assert @stream.verify
130
- assert stanza.mock_pubsub.verify
131
- assert_equal 1, @stream.nodes.size
136
+ let(:result) { node(%Q{<iq from="games.wonderland.lit" id="42" to="#{alice.jid}" type="result"/>}) }
132
137
 
133
- expected = node(%q{<iq from="games.wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result"/>})
134
- assert_equal expected, @stream.nodes[0]
135
- end
138
+ let(:broadcast) do
139
+ node(%q{
140
+ <message>
141
+ <event xmlns="http://jabber.org/protocol/pubsub#event">
142
+ <delete node="game_13"/>
143
+ </event>
144
+ </message>})
145
+ end
136
146
 
137
- private
147
+ before do
148
+ pubsub.expect :node?, true, ['game_13']
149
+ pubsub.expect :publish, nil, ['game_13', broadcast]
150
+ pubsub.expect :delete_node, nil, ['game_13']
151
+ end
138
152
 
139
- def node(xml)
140
- Nokogiri::XML(xml).root
153
+ it 'broadcasts the delete to subscribers' do
154
+ subject.stub :pubsub, pubsub do
155
+ subject.process
156
+ end
157
+ stream.verify
158
+ pubsub.verify
159
+ end
160
+
161
+ it 'sends a result stanza to sender' do
162
+ subject.stub :pubsub, pubsub do
163
+ subject.process
164
+ end
165
+ stream.nodes.size.must_equal 1
166
+ stream.nodes.first.must_equal result
167
+ end
141
168
  end
142
169
  end