vines 0.3.2 → 0.4.0

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 (115) hide show
  1. data/README +5 -9
  2. data/Rakefile +11 -9
  3. data/conf/config.rb +30 -4
  4. data/lib/vines/cluster/connection.rb +26 -0
  5. data/lib/vines/cluster/publisher.rb +55 -0
  6. data/lib/vines/cluster/pubsub.rb +92 -0
  7. data/lib/vines/cluster/sessions.rb +125 -0
  8. data/lib/vines/cluster/subscriber.rb +108 -0
  9. data/lib/vines/cluster.rb +246 -0
  10. data/lib/vines/command/init.rb +21 -24
  11. data/lib/vines/config/host.rb +48 -8
  12. data/lib/vines/config/port.rb +5 -0
  13. data/lib/vines/config/pubsub.rb +108 -0
  14. data/lib/vines/config.rb +74 -20
  15. data/lib/vines/jid.rb +14 -0
  16. data/lib/vines/router.rb +69 -55
  17. data/lib/vines/stanza/iq/disco_info.rb +22 -9
  18. data/lib/vines/stanza/iq/disco_items.rb +6 -3
  19. data/lib/vines/stanza/iq/ping.rb +1 -1
  20. data/lib/vines/stanza/iq/private_storage.rb +4 -8
  21. data/lib/vines/stanza/iq/roster.rb +6 -14
  22. data/lib/vines/stanza/iq/session.rb +2 -7
  23. data/lib/vines/stanza/iq/vcard.rb +4 -6
  24. data/lib/vines/stanza/iq/version.rb +1 -1
  25. data/lib/vines/stanza/iq.rb +8 -10
  26. data/lib/vines/stanza/presence/subscribe.rb +3 -11
  27. data/lib/vines/stanza/presence/subscribed.rb +16 -29
  28. data/lib/vines/stanza/presence/unsubscribe.rb +3 -15
  29. data/lib/vines/stanza/presence/unsubscribed.rb +3 -16
  30. data/lib/vines/stanza/presence.rb +30 -0
  31. data/lib/vines/stanza/pubsub/create.rb +39 -0
  32. data/lib/vines/stanza/pubsub/delete.rb +41 -0
  33. data/lib/vines/stanza/pubsub/publish.rb +66 -0
  34. data/lib/vines/stanza/pubsub/subscribe.rb +44 -0
  35. data/lib/vines/stanza/pubsub/unsubscribe.rb +30 -0
  36. data/lib/vines/stanza/pubsub.rb +22 -0
  37. data/lib/vines/stanza.rb +72 -22
  38. data/lib/vines/storage/couchdb.rb +46 -65
  39. data/lib/vines/storage/local.rb +20 -14
  40. data/lib/vines/storage/mongodb.rb +132 -0
  41. data/lib/vines/storage/null.rb +39 -0
  42. data/lib/vines/storage/redis.rb +61 -68
  43. data/lib/vines/storage/sql.rb +73 -69
  44. data/lib/vines/storage.rb +1 -1
  45. data/lib/vines/stream/client/bind.rb +2 -2
  46. data/lib/vines/stream/client/session.rb +71 -16
  47. data/lib/vines/stream/component/handshake.rb +1 -0
  48. data/lib/vines/stream/component/ready.rb +2 -2
  49. data/lib/vines/stream/http/session.rb +2 -0
  50. data/lib/vines/stream/http.rb +0 -6
  51. data/lib/vines/stream/server/final_restart.rb +1 -0
  52. data/lib/vines/stream/server/outbound/final_features.rb +1 -0
  53. data/lib/vines/stream/server/ready.rb +6 -2
  54. data/lib/vines/stream/server.rb +4 -3
  55. data/lib/vines/stream.rb +10 -6
  56. data/lib/vines/version.rb +1 -1
  57. data/lib/vines.rb +48 -22
  58. data/test/cluster/publisher_test.rb +45 -0
  59. data/test/cluster/sessions_test.rb +54 -0
  60. data/test/cluster/subscriber_test.rb +94 -0
  61. data/test/config/host_test.rb +100 -21
  62. data/test/config/pubsub_test.rb +181 -0
  63. data/test/config_test.rb +225 -43
  64. data/test/jid_test.rb +7 -0
  65. data/test/router_test.rb +181 -9
  66. data/test/stanza/iq/disco_info_test.rb +8 -6
  67. data/test/stanza/iq/disco_items_test.rb +3 -3
  68. data/test/stanza/iq/private_storage_test.rb +8 -19
  69. data/test/stanza/iq/roster_test.rb +1 -1
  70. data/test/stanza/iq/session_test.rb +3 -6
  71. data/test/stanza/iq/vcard_test.rb +6 -2
  72. data/test/stanza/iq/version_test.rb +3 -2
  73. data/test/stanza/iq_test.rb +5 -5
  74. data/test/stanza/message_test.rb +3 -2
  75. data/test/stanza/presence/probe_test.rb +2 -1
  76. data/test/stanza/pubsub/create_test.rb +138 -0
  77. data/test/stanza/pubsub/delete_test.rb +142 -0
  78. data/test/stanza/pubsub/publish_test.rb +373 -0
  79. data/test/stanza/pubsub/subscribe_test.rb +186 -0
  80. data/test/stanza/pubsub/unsubscribe_test.rb +179 -0
  81. data/test/stanza_test.rb +2 -1
  82. data/test/storage/local_test.rb +26 -25
  83. data/test/storage/mock_mongo.rb +40 -0
  84. data/test/storage/mock_redis.rb +98 -0
  85. data/test/storage/mongodb_test.rb +81 -0
  86. data/test/storage/null_test.rb +30 -0
  87. data/test/storage/redis_test.rb +3 -36
  88. data/test/stream/component/handshake_test.rb +4 -0
  89. data/test/stream/component/ready_test.rb +2 -1
  90. data/test/stream/server/ready_test.rb +7 -1
  91. data/web/404.html +5 -3
  92. data/web/chat/coffeescripts/chat.coffee +9 -5
  93. data/web/chat/javascripts/app.js +1 -1
  94. data/web/chat/javascripts/chat.js +14 -8
  95. data/web/chat/stylesheets/chat.css +4 -1
  96. data/web/lib/coffeescripts/button.coffee +9 -5
  97. data/web/lib/coffeescripts/filter.coffee +1 -1
  98. data/web/lib/coffeescripts/login.coffee +14 -1
  99. data/web/lib/coffeescripts/session.coffee +8 -11
  100. data/web/lib/images/dark-gray.png +0 -0
  101. data/web/lib/images/light-gray.png +0 -0
  102. data/web/lib/images/logo-large.png +0 -0
  103. data/web/lib/images/logo-small.png +0 -0
  104. data/web/lib/images/white.png +0 -0
  105. data/web/lib/javascripts/base.js +9 -8
  106. data/web/lib/javascripts/button.js +20 -12
  107. data/web/lib/javascripts/filter.js +1 -1
  108. data/web/lib/javascripts/icons.js +7 -1
  109. data/web/lib/javascripts/jquery.js +4 -4
  110. data/web/lib/javascripts/login.js +16 -2
  111. data/web/lib/javascripts/raphael.js +5 -7
  112. data/web/lib/javascripts/session.js +10 -14
  113. data/web/lib/stylesheets/base.css +7 -11
  114. data/web/lib/stylesheets/login.css +31 -27
  115. metadata +100 -34
@@ -0,0 +1,138 @@
1
+ # encoding: UTF-8
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
12
+ host 'wonderland.lit' do
13
+ storage(:fs) { dir Dir.tmpdir }
14
+ pubsub 'games'
15
+ end
16
+ end
17
+ @stream = MiniTest::Mock.new
18
+ @stream.expect(:config, @config)
19
+ @stream.expect(:user, @user)
20
+ end
21
+
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,}/, ''))
30
+
31
+ @stream.expect(:domain, 'wonderland.lit')
32
+
33
+ stanza = Vines::Stanza::PubSub::Create.new(node, @stream)
34
+ assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
35
+ assert @stream.verify
36
+ end
37
+
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
51
+
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
69
+ end
70
+
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
85
+
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
100
+ end
101
+ assert_raises(Vines::StanzaErrors::Conflict) { stanza.process }
102
+ assert @stream.verify
103
+ end
104
+
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
118
+ end
119
+
120
+ stanza = Vines::Stanza::PubSub::Create.new(node, @stream)
121
+ stanza.process
122
+
123
+ assert @stream.verify
124
+ assert_equal 1, @stream.nodes.size
125
+
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]
131
+ end
132
+
133
+ private
134
+
135
+ def node(xml)
136
+ Nokogiri::XML(xml).root
137
+ end
138
+ end
@@ -0,0 +1,142 @@
1
+ # encoding: UTF-8
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
12
+ host 'wonderland.lit' do
13
+ storage(:fs) { dir Dir.tmpdir }
14
+ pubsub 'games'
15
+ end
16
+ end
17
+ @stream = MiniTest::Mock.new
18
+ @stream.expect(:config, @config)
19
+ @stream.expect(:user, @user)
20
+ end
21
+
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,}/, ''))
30
+
31
+ @stream.expect(:domain, 'wonderland.lit')
32
+
33
+ stanza = Vines::Stanza::PubSub::Delete.new(node, @stream)
34
+ assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
35
+ assert @stream.verify
36
+ end
37
+
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
50
+ end
51
+
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
69
+ end
70
+
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
84
+ end
85
+
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
98
+ end
99
+
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
126
+ end
127
+ stanza.process
128
+
129
+ assert @stream.verify
130
+ assert stanza.mock_pubsub.verify
131
+ assert_equal 1, @stream.nodes.size
132
+
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
136
+
137
+ private
138
+
139
+ def node(xml)
140
+ Nokogiri::XML(xml).root
141
+ end
142
+ end
@@ -0,0 +1,373 @@
1
+ # encoding: UTF-8
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
12
+ host 'wonderland.lit' do
13
+ storage(:fs) { dir Dir.tmpdir }
14
+ pubsub 'games'
15
+ end
16
+ end
17
+ @stream = MiniTest::Mock.new
18
+ @stream.expect(:config, @config)
19
+ @stream.expect(:user, @user)
20
+ end
21
+
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,}/, ''))
37
+
38
+ @stream.expect(:domain, 'wonderland.lit')
39
+
40
+ stanza = Vines::Stanza::PubSub::Publish.new(node, @stream)
41
+ assert_raises(Vines::StanzaErrors::FeatureNotImplemented) { stanza.process }
42
+ assert @stream.verify
43
+ end
44
+
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
64
+ end
65
+
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
90
+ end
91
+
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
119
+ end
120
+
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'])
144
+ end
145
+ @mock_pubsub
146
+ end
147
+ assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
148
+ assert @stream.verify
149
+ assert stanza.mock_pubsub.verify
150
+ end
151
+
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'])
175
+ end
176
+ @mock_pubsub
177
+ end
178
+ assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
179
+ assert @stream.verify
180
+ assert stanza.mock_pubsub.verify
181
+ end
182
+
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
203
+ end
204
+
205
+ assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
206
+ assert @stream.verify
207
+ assert stanza.mock_pubsub.verify
208
+ end
209
+
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
229
+ end
230
+
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
251
+ end
252
+
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
264
+ end
265
+ @mock_pubsub
266
+ 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,}/, ''))
282
+ # 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']
285
+ 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
305
+ # 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']
308
+ item.remove_attribute('id')
309
+ assert_equal expected, published_message
310
+ end
311
+
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
333
+
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])
355
+ end
356
+ @mock_pubsub
357
+ end
358
+ stanza.process
359
+
360
+ assert @stream.verify
361
+ assert stanza.mock_pubsub.verify
362
+ assert_equal 1, @stream.nodes.size
363
+
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]
366
+ end
367
+
368
+ private
369
+
370
+ def node(xml)
371
+ Nokogiri::XML(xml).root
372
+ end
373
+ end