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,206 +1,229 @@
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 RosterTest < MiniTest::Unit::TestCase
8
- def setup
9
- @stream = MiniTest::Mock.new
10
- end
5
+ describe Vines::Stanza::Iq::Roster do
6
+ subject { Vines::Stanza::Iq::Roster.new(xml, stream) }
7
+ let(:stream) { MiniTest::Mock.new }
8
+ let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
11
9
 
12
- def test_roster_get_with_empty_roster
13
- alice = Vines::User.new(:jid => 'alice@wonderland.lit')
14
- expected = node(%q{<iq id="42" type="result"><query xmlns="jabber:iq:roster"/></iq>})
15
- @stream.expect(:write, nil, [expected])
16
- @stream.expect(:requested_roster!, nil)
17
- @stream.expect(:user, alice)
18
-
19
- node = node(%q{<iq id="42" type="get"><query xmlns='jabber:iq:roster'/></iq>})
20
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
21
- stanza.process
22
- assert @stream.verify
10
+ before do
11
+ class << stream
12
+ attr_accessor :domain, :user
13
+ end
14
+ stream.user = alice
15
+ stream.domain = 'wonderland.lit'
23
16
  end
24
17
 
25
- def test_roster_get_with_non_empty_roster
26
- alice = Vines::User.new(:jid => 'alice@wonderland.lit')
27
- alice.roster << Vines::Contact.new(:jid => 'hatter@wonderland.lit')
28
- alice.roster << Vines::Contact.new(:jid => 'cat@wonderland.lit', :groups => ['Friends', 'Cats'])
29
-
30
- expected = node(%q{
31
- <iq id="42" type="result">
32
- <query xmlns="jabber:iq:roster">
33
- <item jid="cat@wonderland.lit" subscription="none">
34
- <group>Cats</group>
35
- <group>Friends</group>
36
- </item>
37
- <item jid="hatter@wonderland.lit" subscription="none"/>
38
- </query>
39
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
40
-
41
- @stream.expect(:write, nil, [expected])
42
- @stream.expect(:requested_roster!, nil)
43
- @stream.expect(:user, alice)
44
-
45
- node = node(%q{<iq id="42" type="get"><query xmlns='jabber:iq:roster'/></iq>})
46
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
47
- stanza.process
48
- assert @stream.verify
18
+ describe 'when retrieving an empty roster' do
19
+ let(:xml) { node(%q{<iq id="42" type="get"><query xmlns='jabber:iq:roster'/></iq>}) }
20
+ let(:expected) { node(%q{<iq id="42" type="result"><query xmlns="jabber:iq:roster"/></iq>}) }
21
+
22
+ before do
23
+ stream.expect :write, nil, [expected]
24
+ stream.expect :requested_roster!, nil
25
+ end
26
+
27
+ it 'returns an empty stanza' do
28
+ subject.process
29
+ stream.verify
30
+ end
49
31
  end
50
32
 
51
- def test_roster_get_with_invalid_to_address
52
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
53
- @stream.expect(:user, alice)
33
+ describe 'when retrieving a non-empty roster' do
34
+ let(:xml) { node(%q{<iq id="42" type="get"><query xmlns='jabber:iq:roster'/></iq>}) }
35
+ let(:expected) do
36
+ node(%q{
37
+ <iq id="42" type="result">
38
+ <query xmlns="jabber:iq:roster">
39
+ <item jid="cat@wonderland.lit" subscription="none">
40
+ <group>Cats</group>
41
+ <group>Friends</group>
42
+ </item>
43
+ <item jid="hatter@wonderland.lit" subscription="none"/>
44
+ </query>
45
+ </iq>})
46
+ end
54
47
 
55
- node = node(%q{
56
- <iq id="42" type="get" to="romeo@verona.lit">
57
- <query xmlns="jabber:iq:roster"/>
58
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
48
+ before do
49
+ alice.roster << Vines::Contact.new(jid: 'hatter@wonderland.lit')
50
+ alice.roster << Vines::Contact.new(jid: 'cat@wonderland.lit', :groups => ['Friends', 'Cats'])
59
51
 
60
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
61
- assert_raises(Vines::StanzaErrors::Forbidden) { stanza.process }
62
- assert @stream.verify
63
- end
52
+ stream.expect :write, nil, [expected]
53
+ stream.expect :requested_roster!, nil
54
+ end
64
55
 
65
- def test_roster_set_with_invalid_to_address
66
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
67
- @stream.expect(:user, alice)
56
+ it 'sorts groups alphabetically' do
57
+ subject.process
58
+ stream.verify
59
+ end
60
+ end
68
61
 
69
- node = node(%q{
70
- <iq id="42" type="set" to="romeo@verona.lit">
71
- <query xmlns="jabber:iq:roster"/>
72
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
62
+ describe 'when requesting a roster for another user' do
63
+ let(:xml) do
64
+ node(%q{
65
+ <iq id="42" type="get" to="romeo@verona.lit">
66
+ <query xmlns="jabber:iq:roster"/>
67
+ </iq>})
68
+ end
73
69
 
74
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
75
- assert_raises(Vines::StanzaErrors::Forbidden) { stanza.process }
76
- assert @stream.verify
70
+ it 'raises a forbidden stanza error' do
71
+ -> { subject.process }.must_raise Vines::StanzaErrors::Forbidden
72
+ stream.verify
73
+ end
77
74
  end
78
75
 
79
- def test_roster_set_with_no_items
80
- node = node(%q{
81
- <iq id="42" type="set">
82
- <query xmlns="jabber:iq:roster"/>
83
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
76
+ describe 'when saving a roster for another user' do
77
+ let(:xml) do
78
+ node(%q{
79
+ <iq id="42" type="set" to="romeo@verona.lit">
80
+ <query xmlns="jabber:iq:roster"/>
81
+ </iq>})
82
+ end
84
83
 
85
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
86
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
87
- assert @stream.verify
84
+ it 'raises a forbidden stanza error' do
85
+ -> { subject.process }.must_raise Vines::StanzaErrors::Forbidden
86
+ stream.verify
87
+ end
88
88
  end
89
89
 
90
- def test_roster_set_with_two_items
91
- node = node(%q{
92
- <iq id="42" type="set">
93
- <query xmlns="jabber:iq:roster">
94
- <item jid="hatter@wonderland.lit"/>
95
- <item jid="cat@wonderland.lit"/>
96
- </query>
97
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
98
-
99
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
100
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
101
- assert @stream.verify
90
+ describe 'when saving a roster with no items' do
91
+ let(:xml) do
92
+ node(%q{
93
+ <iq id="42" type="set">
94
+ <query xmlns="jabber:iq:roster"/>
95
+ </iq>})
96
+ end
97
+
98
+ it 'raises a bad-request stanza error' do
99
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
100
+ stream.verify
101
+ end
102
102
  end
103
103
 
104
- def test_roster_set_missing_jid
105
- node = node(%q{
106
- <iq id="42" type="set">
107
- <query xmlns="jabber:iq:roster">
108
- <item name="Mad Hatter"/>
109
- </query>
110
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
111
-
112
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
113
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
114
- assert @stream.verify
104
+ describe 'when updating a roster with more than one item' do
105
+ let(:xml) do
106
+ node(%q{
107
+ <iq id="42" type="set">
108
+ <query xmlns="jabber:iq:roster">
109
+ <item jid="hatter@wonderland.lit"/>
110
+ <item jid="cat@wonderland.lit"/>
111
+ </query>
112
+ </iq>})
113
+ end
114
+
115
+ it 'raises a bad-request stanza error' do
116
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
117
+ stream.verify
118
+ end
115
119
  end
116
120
 
117
- def test_roster_set_with_duplicate_groups
118
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
119
- @stream.expect(:user, alice)
120
-
121
- node = node(%q{
122
- <iq id="42" type="set">
123
- <query xmlns="jabber:iq:roster">
124
- <item jid="hatter@wonderland.lit" name="Mad Hatter">
125
- <group>Friends</group>
126
- <group>Friends</group>
127
- </item>
128
- </query>
129
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
130
-
131
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
132
- assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
133
- assert @stream.verify
121
+ describe 'when adding a roster item without a jid attribute' do
122
+ let(:xml) do
123
+ node(%q{
124
+ <iq id="42" type="set">
125
+ <query xmlns="jabber:iq:roster">
126
+ <item name="Mad Hatter"/>
127
+ </query>
128
+ </iq>})
129
+ end
130
+
131
+ it 'raises a bad-request stanza error' do
132
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
133
+ stream.verify
134
+ end
134
135
  end
135
136
 
136
- def test_roster_set_with_empty_group
137
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
138
- @stream.expect(:user, alice)
139
-
140
- node = node(%q{
141
- <iq id="42" type="set">
142
- <query xmlns="jabber:iq:roster">
143
- <item jid="hatter@wonderland.lit" name="Mad Hatter">
144
- <group></group>
145
- </item>
146
- </query>
147
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
148
-
149
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
150
- assert_raises(Vines::StanzaErrors::NotAcceptable) { stanza.process }
151
- assert @stream.verify
137
+ describe 'when adding a roster item with duplicate groups' do
138
+ let(:xml) do
139
+ node(%q{
140
+ <iq id="42" type="set">
141
+ <query xmlns="jabber:iq:roster">
142
+ <item jid="hatter@wonderland.lit" name="Mad Hatter">
143
+ <group>Friends</group>
144
+ <group>Friends</group>
145
+ </item>
146
+ </query>
147
+ </iq>})
148
+ end
149
+
150
+ it 'raises a bad-request stanza error' do
151
+ -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
152
+ stream.verify
153
+ end
152
154
  end
153
155
 
154
- def test_roster_set_sends_results
155
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
156
- storage = MiniTest::Mock.new
157
- storage.expect(:save_user, nil, [alice])
158
-
159
- recipient = MiniTest::Mock.new
160
- recipient.expect(:user, alice)
161
- def recipient.nodes; @nodes; end
162
- def recipient.write(node)
163
- @nodes ||= []
164
- @nodes << node
165
- end
166
-
167
- @stream.expect(:user, alice)
168
- @stream.expect(:interested_resources, [recipient], [alice.jid])
169
- @stream.expect(:update_user_streams, nil, [alice])
170
- @stream.expect(:domain, 'wonderland.lit')
171
- @stream.expect(:storage, storage, ['wonderland.lit'])
172
- expected = node(%Q{<iq id="42" to="#{alice.jid}" type="result"/>})
173
- @stream.expect(:write, nil, [expected])
174
-
175
- node = node(%q{
176
- <iq id="42" type="set">
177
- <query xmlns="jabber:iq:roster">
178
- <item jid="hatter@wonderland.lit" name="Mad Hatter">
179
- <group>Friends</group>
180
- </item>
181
- </query>
182
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
183
-
184
- stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
185
- stanza.process
186
- assert @stream.verify
187
- assert storage.verify
188
-
189
- expected = node(%q{
190
- <iq to="alice@wonderland.lit/tea" type="set">
191
- <query xmlns="jabber:iq:roster">
192
- <item jid="hatter@wonderland.lit" name="Mad Hatter" subscription="none">
193
- <group>Friends</group>
194
- </item>
195
- </query>
196
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
197
- recipient.nodes[0].remove_attribute('id') # id is random
198
- assert_equal expected, recipient.nodes[0]
156
+ describe 'when adding a roster item with an empty group name' do
157
+ let(:xml) do
158
+ node(%q{
159
+ <iq id="42" type="set">
160
+ <query xmlns="jabber:iq:roster">
161
+ <item jid="hatter@wonderland.lit" name="Mad Hatter">
162
+ <group></group>
163
+ </item>
164
+ </query>
165
+ </iq>})
166
+ end
167
+
168
+ it 'raises a not-acceptable stanza error' do
169
+ -> { subject.process }.must_raise Vines::StanzaErrors::NotAcceptable
170
+ stream.verify
171
+ end
199
172
  end
200
173
 
201
- private
174
+ describe 'when saving a roster successfully' do
175
+ let(:xml) do
176
+ node(%q{
177
+ <iq id="42" type="set">
178
+ <query xmlns="jabber:iq:roster">
179
+ <item jid="hatter@wonderland.lit" name="Mad Hatter">
180
+ <group>Friends</group>
181
+ </item>
182
+ </query>
183
+ </iq>})
184
+ end
185
+
186
+ let(:expected) do
187
+ node(%q{
188
+ <iq to="alice@wonderland.lit/tea" type="set">
189
+ <query xmlns="jabber:iq:roster">
190
+ <item jid="hatter@wonderland.lit" name="Mad Hatter" subscription="none">
191
+ <group>Friends</group>
192
+ </item>
193
+ </query>
194
+ </iq>})
195
+ end
196
+
197
+ let(:storage) { MiniTest::Mock.new }
198
+ let(:recipient) { MiniTest::Mock.new }
199
+ let(:result) { node(%Q{<iq id="42" to="#{alice.jid}" type="result"/>}) }
200
+
201
+ before do
202
+ storage.expect :save_user, nil, [alice]
203
+
204
+ recipient.expect :user, alice
205
+ def recipient.nodes; @nodes; end
206
+ def recipient.write(node)
207
+ @nodes ||= []
208
+ @nodes << node
209
+ end
202
210
 
203
- def node(xml)
204
- Nokogiri::XML(xml).root
211
+ stream.expect :interested_resources, [recipient], [alice.jid]
212
+ stream.expect :update_user_streams, nil, [alice]
213
+ stream.expect :storage, storage, ['wonderland.lit']
214
+ stream.expect :write, nil, [result]
215
+ end
216
+
217
+ it 'sends a result to the sender' do
218
+ subject.process
219
+ stream.verify
220
+ storage.verify
221
+ end
222
+
223
+ it 'sends the new roster item to the interested streams' do
224
+ subject.process
225
+ recipient.nodes.first.remove_attribute('id') # id is random
226
+ recipient.nodes.first.must_equal expected
227
+ end
205
228
  end
206
229
  end
@@ -1,26 +1,25 @@
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 SessionTest < MiniTest::Unit::TestCase
8
- def test_session
9
- stream = MiniTest::Mock.new
10
- stream.expect(:domain, 'wonderland.lit')
11
- stream.expect(:user, Vines::User.new(jid: 'alice@wonderland.lit/tea'))
12
- expected = node(%q{<iq from="wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result"/>})
13
- stream.expect(:write, nil, [expected])
5
+ describe Vines::Stanza::Iq::Session do
6
+ subject { Vines::Stanza::Iq::Session.new(xml, stream) }
7
+ let(:stream) { MiniTest::Mock.new }
8
+ let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
14
9
 
15
- node = node(%q{<iq id="42" type="set"><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>})
16
- stanza = Vines::Stanza::Iq::Session.new(node, stream)
17
- stanza.process
18
- assert stream.verify
19
- end
10
+ describe 'when session initiation is requested' do
11
+ let(:xml) { node(%q{<iq id="42" type="set"><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>}) }
12
+ let(:result) { node(%q{<iq from="wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result"/>}) }
20
13
 
21
- private
14
+ before do
15
+ stream.expect :domain, 'wonderland.lit'
16
+ stream.expect :user, alice
17
+ stream.expect :write, nil, [result]
18
+ end
22
19
 
23
- def node(xml)
24
- Nokogiri::XML(xml).root
20
+ it 'just returns a result to satisy older clients' do
21
+ subject.process
22
+ stream.verify
23
+ end
25
24
  end
26
25
  end
@@ -1,14 +1,14 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'tmpdir'
4
- require 'vines'
5
- require 'ext/nokogiri'
6
- require 'minitest/autorun'
7
-
8
- class VcardTest < MiniTest::Unit::TestCase
9
- def setup
10
- @stream = MiniTest::Mock.new
11
- @config = Vines::Config.new do
3
+ require 'test_helper'
4
+
5
+ describe Vines::Stanza::Iq::Vcard do
6
+ subject { Vines::Stanza::Iq::Vcard.new(xml, stream) }
7
+ let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
8
+ let(:stream) { MiniTest::Mock.new }
9
+ let(:storage) { MiniTest::Mock.new }
10
+ let(:config) do
11
+ Vines::Config.new do
12
12
  host 'wonderland.lit' do
13
13
  cross_domain_messages true
14
14
  storage(:fs) { dir Dir.tmpdir }
@@ -16,130 +16,131 @@ class VcardTest < MiniTest::Unit::TestCase
16
16
  end
17
17
  end
18
18
 
19
- def test_vcard_get_on_remote_jid_routes
20
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
21
- node = node(%q{<iq id="42" to="romeo@verona.lit" type="get"><vCard xmlns="vcard-temp"/></iq>})
19
+ before do
20
+ class << stream
21
+ attr_accessor :config, :domain, :user
22
+ end
23
+ stream.config = config
24
+ stream.domain = 'wonderland.lit'
25
+ stream.user = alice
26
+ end
22
27
 
23
- router = MiniTest::Mock.new
24
- router.expect(:route, nil, [node])
28
+ describe 'when getting vcard' do
29
+ describe 'and addressed to a remote jid' do
30
+ let(:xml) { get('romeo@verona.lit') }
31
+ let(:router) { MiniTest::Mock.new }
25
32
 
26
- @stream.expect(:config, @config)
27
- @stream.expect(:user, alice)
28
- @stream.expect(:router, router)
33
+ before do
34
+ router.expect :route, nil, [xml]
35
+ stream.expect :router, router
36
+ end
29
37
 
30
- stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
31
- stanza.process
32
- assert @stream.verify
33
- assert router.verify
34
- end
38
+ it 'routes rather than handle locally' do
39
+ subject.process
40
+ stream.verify
41
+ router.verify
42
+ end
43
+ end
35
44
 
36
- def test_vcard_get_missing_to_address
37
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
38
- node = node(%q{<iq id="42" type="get"><vCard xmlns="vcard-temp"/></iq>})
39
-
40
- card = node(%q{<vCard xmlns="vcard-temp"><FN>Alice in Wonderland</FN></vCard>})
41
-
42
- storage = MiniTest::Mock.new
43
- storage.expect(:find_vcard, card, [alice.jid.bare])
44
-
45
- @stream.expect(:config, @config)
46
- @stream.expect(:user, alice)
47
- @stream.expect(:domain, 'wonderland.lit')
48
- @stream.expect(:storage, storage, ['wonderland.lit'])
49
- expected = node(%q{
50
- <iq id="42" to="alice@wonderland.lit/tea" type="result">
51
- <vCard xmlns="vcard-temp">
52
- <FN>Alice in Wonderland</FN>
53
- </vCard>
54
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
55
- @stream.expect(:write, nil, [expected])
56
-
57
- stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
58
- stanza.process
59
- assert @stream.verify
60
- assert storage.verify
61
- end
45
+ describe 'and missing to address' do
46
+ let(:xml) { get('') }
47
+ let(:card) { vcard('Alice') }
48
+ let(:expected) { result(alice.jid, '', card) }
62
49
 
63
- def test_vcard_get_another_user_includes_from_address
64
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
65
- node = node(%q{<iq id="42" to="hatter@wonderland.lit" type="get"><vCard xmlns="vcard-temp"/></iq>})
66
-
67
- card = node(%q{<vCard xmlns="vcard-temp"><FN>Mad Hatter</FN></vCard>})
68
-
69
- storage = MiniTest::Mock.new
70
- storage.expect(:find_vcard, card, [Vines::JID.new('hatter@wonderland.lit')])
71
-
72
- @stream.expect(:config, @config)
73
- @stream.expect(:user, alice)
74
- @stream.expect(:storage, storage, ['wonderland.lit'])
75
- expected = node(%q{
76
- <iq from="hatter@wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result">
77
- <vCard xmlns="vcard-temp">
78
- <FN>Mad Hatter</FN>
79
- </vCard>
80
- </iq>}.strip.gsub(/\n|\s{2,}/, ''))
81
- @stream.expect(:write, nil, [expected])
82
-
83
- stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
84
- stanza.process
85
- assert @stream.verify
86
- assert storage.verify
87
- end
50
+ before do
51
+ storage.expect :find_vcard, card, [alice.jid.bare]
52
+ stream.expect :storage, storage, ['wonderland.lit']
53
+ stream.expect :write, nil, [expected]
54
+ end
88
55
 
89
- def test_missing_vcard_get_returns_item_not_found
90
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
91
- node = node(%q{<iq id="42" type="get"><vCard xmlns="vcard-temp"/></iq>})
56
+ it 'sends vcard for authenticated jid' do
57
+ subject.process
58
+ stream.verify
59
+ storage.verify
60
+ end
61
+ end
92
62
 
93
- storage = MiniTest::Mock.new
94
- storage.expect(:find_vcard, nil, [alice.jid.bare])
63
+ describe 'for another user' do
64
+ let(:xml) { get(hatter) }
65
+ let(:card) { vcard('Hatter') }
66
+ let(:hatter) { Vines::JID.new('hatter@wonderland.lit') }
67
+ let(:expected) { result(alice.jid, hatter, card) }
95
68
 
96
- @stream.expect(:config, @config)
97
- @stream.expect(:user, alice)
98
- @stream.expect(:domain, 'wonderland.lit')
99
- @stream.expect(:storage, storage, ['wonderland.lit'])
69
+ before do
70
+ storage.expect :find_vcard, card, [hatter]
71
+ stream.expect :storage, storage, ['wonderland.lit']
72
+ stream.expect :write, nil, [expected]
73
+ end
100
74
 
101
- stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
102
- assert_raises(Vines::StanzaErrors::ItemNotFound) { stanza.process }
103
- assert @stream.verify
104
- assert storage.verify
105
- end
75
+ it 'succeeds and returns vcard with from address' do
76
+ subject.process
77
+ stream.verify
78
+ storage.verify
79
+ end
80
+ end
106
81
 
107
- def test_vcard_set_on_another_user_returns_forbidden
108
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
109
- node = node(%q{<iq id="42" to="hatter@wonderland.lit" type="set"><vCard xmlns="vcard-temp"><FN>Alice</FN></vCard></iq>})
82
+ describe 'for missing vcard' do
83
+ let(:xml) { get('') }
110
84
 
111
- @stream.expect(:config, @config)
112
- @stream.expect(:user, alice)
85
+ before do
86
+ storage.expect :find_vcard, nil, [alice.jid.bare]
87
+ stream.expect :storage, storage, ['wonderland.lit']
88
+ end
113
89
 
114
- stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
115
- assert_raises(Vines::StanzaErrors::Forbidden) { stanza.process }
116
- assert @stream.verify
90
+ it 'returns an item-not-found stanza error' do
91
+ -> { subject.process }.must_raise Vines::StanzaErrors::ItemNotFound
92
+ stream.verify
93
+ storage.verify
94
+ end
95
+ end
117
96
  end
118
97
 
119
- def test_vcard_set_returns_result
120
- alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
121
- node = node(%q{<iq id="42" type="set"><vCard xmlns="vcard-temp"><FN>Alice</FN></vCard></iq>})
122
- card = node(%q{<vCard xmlns="vcard-temp"><FN>Alice</FN></vCard>})
123
-
124
- storage = MiniTest::Mock.new
125
- storage.expect(:save_vcard, nil, [alice.jid, card])
126
-
127
- @stream.expect(:config, @config)
128
- @stream.expect(:user, alice)
129
- @stream.expect(:domain, 'wonderland.lit')
130
- @stream.expect(:storage, storage, ['wonderland.lit'])
131
- expected = node(%q{<iq id="42" to="alice@wonderland.lit/tea" type="result"/>})
132
- @stream.expect(:write, nil, [expected])
133
-
134
- stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
135
- stanza.process
136
- assert @stream.verify
137
- assert storage.verify
98
+ describe 'when setting vcard' do
99
+ describe 'and addressed to another user' do
100
+ let(:xml) { set('hatter@wonderland.lit') }
101
+
102
+ it 'raises a forbidden stanza error' do
103
+ -> { subject.process }.must_raise Vines::StanzaErrors::Forbidden
104
+ stream.verify
105
+ end
106
+ end
107
+
108
+ describe 'and missing to address' do
109
+ let(:xml) { set('') }
110
+ let(:card) { vcard('Alice') }
111
+ let(:expected) { result(alice.jid) }
112
+
113
+ before do
114
+ storage.expect :save_vcard, nil, [alice.jid, card]
115
+ stream.expect :storage, storage, ['wonderland.lit']
116
+ stream.expect :write, nil, [expected]
117
+ end
118
+
119
+ it 'succeeds and returns an iq result' do
120
+ subject.process
121
+ stream.verify
122
+ storage.verify
123
+ end
124
+ end
138
125
  end
139
126
 
140
127
  private
141
128
 
142
- def node(xml)
143
- Nokogiri::XML(xml).root
129
+ def vcard(name)
130
+ node(%Q{<vCard xmlns="vcard-temp"><FN>#{name}</FN></vCard>})
131
+ end
132
+
133
+ def get(to)
134
+ card = '<vCard xmlns="vcard-temp"/>'
135
+ iq(id: 42, to: to, type: 'get', body: card)
136
+ end
137
+
138
+ def set(to)
139
+ card = '<vCard xmlns="vcard-temp"><FN>Alice</FN></vCard>'
140
+ iq(id: 42, to: to, type: 'set', body: card)
141
+ end
142
+
143
+ def result(to, from=nil, card=nil)
144
+ iq(from: from, id: 42, to: to, type: 'result', body: card)
144
145
  end
145
146
  end