shingara-blather 0.4.9 → 0.4.14
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +15 -1
- data/lib/blather.rb +5 -0
- data/lib/blather/core_ext/nokogiri.rb +2 -0
- data/lib/blather/roster.rb +3 -3
- data/lib/blather/roster_item.rb +14 -3
- data/lib/blather/stanza/disco/disco_info.rb +20 -2
- data/lib/blather/stanza/disco/disco_items.rb +10 -1
- data/lib/blather/stanza/iq/command.rb +324 -0
- data/lib/blather/stanza/iq/vcard.rb +147 -0
- data/lib/blather/stanza/message.rb +49 -5
- data/lib/blather/stanza/presence/status.rb +11 -3
- data/lib/blather/stanza/pubsub.rb +9 -21
- data/lib/blather/stanza/x.rb +398 -0
- data/lib/blather/stream.rb +3 -2
- data/lib/blather/stream/parser.rb +6 -5
- data/lib/blather/xmpp_node.rb +1 -1
- data/spec/blather/roster_item_spec.rb +39 -1
- data/spec/blather/stanza/discos/disco_info_spec.rb +23 -0
- data/spec/blather/stanza/discos/disco_items_spec.rb +11 -0
- data/spec/blather/stanza/iq/command_spec.rb +206 -0
- data/spec/blather/stanza/iq/vcard_query_spec.rb +96 -0
- data/spec/blather/stanza/message_spec.rb +89 -14
- data/spec/blather/stanza/pubsub/retract_spec.rb +1 -1
- data/spec/blather/stanza/pubsub_spec.rb +0 -5
- data/spec/blather/stanza/x_spec.rb +235 -0
- data/spec/blather/stream/client_spec.rb +14 -1
- data/spec/blather/stream/parser_spec.rb +6 -0
- data/spec/blather/xmpp_node_spec.rb +4 -3
- data/spec/spec_helper.rb +28 -0
- metadata +35 -5
data/lib/blather/stream.rb
CHANGED
@@ -113,8 +113,9 @@ module Blather
|
|
113
113
|
#
|
114
114
|
# @param [#to_xml, #to_s] stanza the stanza to send over the wire
|
115
115
|
def send(stanza)
|
116
|
-
|
117
|
-
|
116
|
+
data = stanza.respond_to?(:to_xml) ? stanza.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XML) : stanza.to_s
|
117
|
+
Blather.logger.debug "SENDING: (#{caller[1]}) #{data}"
|
118
|
+
send_data data
|
118
119
|
end
|
119
120
|
|
120
121
|
# Called by EM.connect to initialize stream variables
|
@@ -16,6 +16,7 @@ class Stream # :nodoc:
|
|
16
16
|
@namespaces = {}
|
17
17
|
@namespace_definitions = []
|
18
18
|
@parser = Nokogiri::XML::SAX::PushParser.new self
|
19
|
+
@parser.options = Nokogiri::XML::ParseOptions::DEFAULT_XML
|
19
20
|
end
|
20
21
|
|
21
22
|
def receive_data(string)
|
@@ -37,11 +38,6 @@ class Stream # :nodoc:
|
|
37
38
|
node[attr.localname] = attr.value
|
38
39
|
end
|
39
40
|
|
40
|
-
if !@receiver.stopped?
|
41
|
-
@current << node if @current
|
42
|
-
@current = node
|
43
|
-
end
|
44
|
-
|
45
41
|
ns_keys = namespaces.map { |pre, href| pre }
|
46
42
|
namespaces.delete_if { |pre, href| NS_TO_IGNORE.include? href }
|
47
43
|
@namespace_definitions.push []
|
@@ -53,6 +49,11 @@ class Stream # :nodoc:
|
|
53
49
|
@namespaces[[prefix, uri]] ||= node.add_namespace(prefix, uri) if prefix && !ns_keys.include?(prefix)
|
54
50
|
node.namespace = @namespaces[[prefix, uri]]
|
55
51
|
|
52
|
+
if !@receiver.stopped?
|
53
|
+
@current << node if @current
|
54
|
+
@current = node
|
55
|
+
end
|
56
|
+
|
56
57
|
deliver(node) if elem == 'stream'
|
57
58
|
|
58
59
|
# $stderr.puts "\n\n"
|
data/lib/blather/xmpp_node.rb
CHANGED
@@ -33,7 +33,7 @@ module Blather
|
|
33
33
|
# @return [Class, nil] the class appropriate for the name/ns combination
|
34
34
|
def self.class_from_registration(name, ns = nil)
|
35
35
|
name = name.to_s
|
36
|
-
@@registrations[[name, ns]]
|
36
|
+
@@registrations[[name, ns]]
|
37
37
|
end
|
38
38
|
|
39
39
|
# Import an XML::Node to the appropriate class
|
@@ -65,7 +65,19 @@ describe Blather::RosterItem do
|
|
65
65
|
|
66
66
|
it 'returns status based on priority' do
|
67
67
|
setup_item_with_presences
|
68
|
-
@i.status.must_equal @
|
68
|
+
@i.status.must_equal @p3
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'returns status based on priority and state' do
|
72
|
+
setup_item_with_presences
|
73
|
+
|
74
|
+
@p4 = Blather::Stanza::Presence::Status.new
|
75
|
+
@p4.type = :unavailable
|
76
|
+
@p4.from = 'n@d/d'
|
77
|
+
@p4.priority = 15
|
78
|
+
@i.status = @p4
|
79
|
+
|
80
|
+
@i.status.must_equal @p3
|
69
81
|
end
|
70
82
|
|
71
83
|
it 'returns status based on resource' do
|
@@ -85,12 +97,38 @@ describe Blather::RosterItem do
|
|
85
97
|
@p2.from = 'n@d/b'
|
86
98
|
@p2.priority = -1
|
87
99
|
|
100
|
+
@p3 = Blather::Stanza::Presence::Status.new(:dnd)
|
101
|
+
@p3.from = 'n@d/c'
|
102
|
+
@p3.priority = 10
|
103
|
+
|
88
104
|
@i.status = @p
|
89
105
|
@i.status = @p2
|
106
|
+
@i.status = @p3
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'removes old unavailable presences' do
|
110
|
+
setup_item_with_presences
|
111
|
+
|
112
|
+
50.times do |i|
|
113
|
+
p = Blather::Stanza::Presence::Status.new
|
114
|
+
p.type = :unavailable
|
115
|
+
p.from = "n@d/#{i}"
|
116
|
+
@i.status = p
|
117
|
+
end
|
118
|
+
|
119
|
+
@i.statuses.size.must_equal 4
|
90
120
|
end
|
91
121
|
|
92
122
|
it 'initializes groups to [nil] if the item is not part of a group' do
|
93
123
|
i = Blather::RosterItem.new 'n@d'
|
94
124
|
i.groups.must_equal [nil]
|
95
125
|
end
|
126
|
+
|
127
|
+
it 'can determine equality' do
|
128
|
+
item1 = Blather::RosterItem.new 'n@d'
|
129
|
+
item2 = Blather::RosterItem.new 'n@d'
|
130
|
+
item1.groups = %w[group1 group2]
|
131
|
+
item2.groups = %w[group1 group2]
|
132
|
+
(item1 == item2).must_equal true
|
133
|
+
end
|
96
134
|
end
|
@@ -54,6 +54,29 @@ describe Blather::Stanza::Iq::DiscoInfo do
|
|
54
54
|
n.to = 'to@jid.com'
|
55
55
|
n.find("/iq[@to='to@jid.com' and @type='get' and @id='#{n.id}']/ns:query[@node='/path/to/node']", :ns => Blather::Stanza::Iq::DiscoInfo.registered_ns).wont_be_empty
|
56
56
|
end
|
57
|
+
|
58
|
+
it 'allows adding of identities' do
|
59
|
+
di = Blather::Stanza::Iq::DiscoInfo.new
|
60
|
+
di.identities.size.must_equal 0
|
61
|
+
di.identities = [{:name => 'name', :type => 'type', :category => 'category'}]
|
62
|
+
di.identities.size.must_equal 1
|
63
|
+
di.identities += [Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category])]
|
64
|
+
di.identities.size.must_equal 2
|
65
|
+
di.identities = nil
|
66
|
+
di.identities.size.must_equal 0
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'allows adding of features' do
|
70
|
+
di = Blather::Stanza::Iq::DiscoInfo.new
|
71
|
+
di.features.size.must_equal 0
|
72
|
+
di.features = ["feature1"]
|
73
|
+
di.features.size.must_equal 1
|
74
|
+
di.features += [Blather::Stanza::Iq::DiscoInfo::Feature.new("feature2")]
|
75
|
+
di.features.size.must_equal 2
|
76
|
+
di.features = nil
|
77
|
+
di.features.size.must_equal 0
|
78
|
+
end
|
79
|
+
|
57
80
|
end
|
58
81
|
|
59
82
|
describe 'Blather::Stanza::Iq::DiscoInfo identities' do
|
@@ -102,6 +102,17 @@ describe Blather::Stanza::Iq::DiscoItems do
|
|
102
102
|
di.items.size.must_equal 2
|
103
103
|
di.items.each { |i| control.include?(i).must_equal true }
|
104
104
|
end
|
105
|
+
|
106
|
+
it 'allows adding of items' do
|
107
|
+
di = Blather::Stanza::Iq::DiscoItems.new
|
108
|
+
di.items.size.must_equal 0
|
109
|
+
di.items = [{:jid => 'foo@bar/baz', :node => 'node', :name => 'name'}]
|
110
|
+
di.items.size.must_equal 1
|
111
|
+
di.items += [Blather::Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name])]
|
112
|
+
di.items.size.must_equal 2
|
113
|
+
di.items = nil
|
114
|
+
di.items.size.must_equal 0
|
115
|
+
end
|
105
116
|
end
|
106
117
|
|
107
118
|
describe Blather::Stanza::Iq::DiscoItems::Item do
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
|
2
|
+
|
3
|
+
def command_xml
|
4
|
+
<<-XML
|
5
|
+
<iq type='result'
|
6
|
+
from='catalog.shakespeare.lit'
|
7
|
+
to='romeo@montague.net/orchard'
|
8
|
+
id='form2'>
|
9
|
+
<command xmlns='http://jabber.org/protocol/commands'
|
10
|
+
node='node1'
|
11
|
+
sessionid='dqjiodmqlmakm'>
|
12
|
+
<x xmlns='jabber:x:data' type='form'>
|
13
|
+
<field var='field-name' type='text-single' label='description' />
|
14
|
+
</x>
|
15
|
+
</command>
|
16
|
+
</iq>
|
17
|
+
XML
|
18
|
+
end
|
19
|
+
|
20
|
+
describe Blather::Stanza::Iq::Command do
|
21
|
+
it 'registers itself' do
|
22
|
+
Blather::XMPPNode.class_from_registration(:command, 'http://jabber.org/protocol/commands').must_equal Blather::Stanza::Iq::Command
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'must be importable' do
|
26
|
+
Blather::XMPPNode.import(parse_stanza(command_xml).root).must_be_instance_of Blather::Stanza::Iq::Command
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'ensures a command node is present on create' do
|
30
|
+
c = Blather::Stanza::Iq::Command.new
|
31
|
+
c.xpath('xmlns:command', :xmlns => Blather::Stanza::Iq::Command.registered_ns).wont_be_empty
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'ensures a command node exists when calling #command' do
|
35
|
+
c = Blather::Stanza::Iq::Command.new
|
36
|
+
c.remove_children :command
|
37
|
+
c.xpath('ns:command', :ns => Blather::Stanza::Iq::Command.registered_ns).must_be_empty
|
38
|
+
|
39
|
+
c.command.wont_be_nil
|
40
|
+
c.xpath('ns:command', :ns => Blather::Stanza::Iq::Command.registered_ns).wont_be_empty
|
41
|
+
end
|
42
|
+
|
43
|
+
Blather::Stanza::Iq::Command::VALID_ACTIONS.each do |valid_action|
|
44
|
+
it "provides a helper (#{valid_action}?) for action #{valid_action}" do
|
45
|
+
Blather::Stanza::Iq::Command.new.must_respond_to :"#{valid_action}?"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Blather::Stanza::Iq::Command::VALID_STATUS.each do |valid_status|
|
50
|
+
it "provides a helper (#{valid_status}?) for status #{valid_status}" do
|
51
|
+
Blather::Stanza::Iq::Command.new.must_respond_to :"#{valid_status}?"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Blather::Stanza::Iq::Command::VALID_NOTE_TYPES.each do |valid_note_type|
|
56
|
+
it "provides a helper (#{valid_note_type}?) for note_type #{valid_note_type}" do
|
57
|
+
Blather::Stanza::Iq::Command.new.must_respond_to :"#{valid_note_type}?"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
[:cancel, :execute, :complete, :next, :prev].each do |action|
|
62
|
+
it "action can be set as \"#{action}\"" do
|
63
|
+
c = Blather::Stanza::Iq::Command.new nil, nil, action
|
64
|
+
c.action.must_equal action
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
[:get, :set, :result, :error].each do |type|
|
69
|
+
it "can be set as \"#{type}\"" do
|
70
|
+
c = Blather::Stanza::Iq::Command.new type
|
71
|
+
c.type.must_equal type
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'sets type to "result" on reply' do
|
76
|
+
c = Blather::Stanza::Iq::Command.new
|
77
|
+
c.type.must_equal :set
|
78
|
+
reply = c.reply.type.must_equal :result
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'sets type to "result" on reply!' do
|
82
|
+
c = Blather::Stanza::Iq::Command.new
|
83
|
+
c.type.must_equal :set
|
84
|
+
c.reply!
|
85
|
+
c.type.must_equal :result
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'removes action on reply' do
|
89
|
+
c = Blather::XMPPNode.import parse_stanza(command_xml).root
|
90
|
+
c.action.must_equal :execute
|
91
|
+
c.reply.action.must_equal nil
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'removes action on reply!' do
|
95
|
+
c = Blather::XMPPNode.import parse_stanza(command_xml).root
|
96
|
+
c.action.must_equal :execute
|
97
|
+
c.reply!
|
98
|
+
c.action.must_equal nil
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'can be registered under a namespace' do
|
102
|
+
class CommandNs < Blather::Stanza::Iq::Command; register :command_ns, nil, 'command:ns'; end
|
103
|
+
Blather::XMPPNode.class_from_registration(:command, 'command:ns').must_equal CommandNs
|
104
|
+
c_ns = CommandNs.new
|
105
|
+
c_ns.xpath('command').must_be_empty
|
106
|
+
c_ns.xpath('ns:command', :ns => 'command:ns').size.must_equal 1
|
107
|
+
|
108
|
+
c_ns.command
|
109
|
+
c_ns.command
|
110
|
+
c_ns.xpath('ns:command', :ns => 'command:ns').size.must_equal 1
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'is constructed properly' do
|
114
|
+
n = Blather::Stanza::Iq::Command.new :set, "node", :execute
|
115
|
+
n.to = 'to@jid.com'
|
116
|
+
n.find("/iq[@to='to@jid.com' and @type='set' and @id='#{n.id}']/ns:command[@node='node' and @action='execute']", :ns => Blather::Stanza::Iq::Command.registered_ns).wont_be_empty
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'has an action attribute' do
|
120
|
+
n = Blather::Stanza::Iq::Command.new
|
121
|
+
n.action.must_equal :execute
|
122
|
+
n.action = :cancel
|
123
|
+
n.action.must_equal :cancel
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'must default action to :execute on import' do
|
127
|
+
n = Blather::XMPPNode.import(parse_stanza(command_xml).root)
|
128
|
+
n.action.must_equal :execute
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'has a status attribute' do
|
132
|
+
n = Blather::Stanza::Iq::Command.new
|
133
|
+
n.status.must_equal :executing
|
134
|
+
n.status = :completed
|
135
|
+
n.status.must_equal :completed
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'has a sessionid attribute' do
|
139
|
+
n = Blather::Stanza::Iq::Command.new
|
140
|
+
n.sessionid.must_equal nil
|
141
|
+
n.sessionid = "somerandomstring"
|
142
|
+
n.sessionid.must_equal Digest::SHA1.hexdigest("somerandomstring")
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'has a sessionid? attribute' do
|
146
|
+
n = Blather::Stanza::Iq::Command.new
|
147
|
+
n.sessionid?.must_equal false
|
148
|
+
n.new_sessionid!
|
149
|
+
n.sessionid?.must_equal true
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'has an allowed_actions attribute' do
|
153
|
+
n = Blather::XMPPNode.import parse_stanza(command_xml).root
|
154
|
+
n.allowed_actions.must_equal [:execute]
|
155
|
+
n.allowed_actions = [:next, :prev]
|
156
|
+
(n.allowed_actions - [:next, :prev, :execute]).must_be_empty
|
157
|
+
n.remove_allowed_actions!
|
158
|
+
n.allowed_actions.must_equal [:execute]
|
159
|
+
n.allowed_actions += [:next]
|
160
|
+
(n.allowed_actions - [:next, :execute]).must_be_empty
|
161
|
+
|
162
|
+
r = Blather::Stanza::Iq::Command.new
|
163
|
+
r.allowed_actions.must_equal [:execute]
|
164
|
+
r.allowed_actions += [:prev]
|
165
|
+
(r.allowed_actions - [:prev, :execute]).must_be_empty
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'has a primary_allowed_action attribute' do
|
169
|
+
n = Blather::XMPPNode.import parse_stanza(command_xml).root
|
170
|
+
n.primary_allowed_action.must_equal :execute
|
171
|
+
n.primary_allowed_action = :next
|
172
|
+
n.primary_allowed_action.must_equal :next
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'has a note_type attribute' do
|
176
|
+
n = Blather::Stanza::Iq::Command.new
|
177
|
+
n.note_type.must_equal nil
|
178
|
+
n.note_type = :info
|
179
|
+
n.note_type.must_equal :info
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'has a note_text attribute' do
|
183
|
+
n = Blather::Stanza::Iq::Command.new
|
184
|
+
n.note_text.must_equal nil
|
185
|
+
n.note_text = "Some text"
|
186
|
+
n.note_text.must_equal "Some text"
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'makes a form child available' do
|
190
|
+
n = Blather::XMPPNode.import(parse_stanza(command_xml).root)
|
191
|
+
n.form.fields.size.must_equal 1
|
192
|
+
n.form.fields.map { |f| f.class }.uniq.must_equal [Blather::Stanza::X::Field]
|
193
|
+
n.form.must_be_instance_of Blather::Stanza::X
|
194
|
+
|
195
|
+
r = Blather::Stanza::Iq::Command.new
|
196
|
+
r.form.type = :form
|
197
|
+
r.form.type.must_equal :form
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'ensures the form child is a child of command' do
|
201
|
+
r = Blather::Stanza::Iq::Command.new
|
202
|
+
r.form
|
203
|
+
r.command.xpath('ns:x', :ns => Blather::Stanza::X.registered_ns).wont_be_empty
|
204
|
+
r.xpath('ns:x', :ns => Blather::Stanza::X.registered_ns).must_be_empty
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
|
2
|
+
|
3
|
+
def vcard_xml
|
4
|
+
<<-XML
|
5
|
+
<iq type="result" id="blather0007" to="romeo@example.net">
|
6
|
+
<vCard xmlns="vcard-temp">
|
7
|
+
<NICKNAME>Romeo</NICKNAME>
|
8
|
+
</vCard>
|
9
|
+
</iq>
|
10
|
+
XML
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Blather::Stanza::Iq::Vcard do
|
14
|
+
it 'registers itself' do
|
15
|
+
Blather::XMPPNode.class_from_registration(:vCard, 'vcard-temp').must_equal Blather::Stanza::Iq::Vcard
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'can be imported' do
|
19
|
+
doc = parse_stanza vcard_xml
|
20
|
+
query = Blather::XMPPNode.import(doc.root)
|
21
|
+
query.must_be_instance_of Blather::Stanza::Iq::Vcard
|
22
|
+
query.vcard.must_be_instance_of Blather::Stanza::Iq::Vcard::Vcard
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'ensures a vcard node is present on create' do
|
26
|
+
query = Blather::Stanza::Iq::Vcard.new
|
27
|
+
query.xpath('ns:vCard', :ns => 'vcard-temp').wont_be_empty
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'ensures a vcard node exists when calling #vcard' do
|
31
|
+
query = Blather::Stanza::Iq::Vcard.new
|
32
|
+
query.vcard.remove
|
33
|
+
query.xpath('ns:vCard', :ns => 'vcard-temp').must_be_empty
|
34
|
+
|
35
|
+
query.vcard.wont_be_nil
|
36
|
+
query.xpath('ns:vCard', :ns => 'vcard-temp').wont_be_empty
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'ensures a vcard node is replaced when calling #vcard=' do
|
40
|
+
doc = parse_stanza vcard_xml
|
41
|
+
query = Blather::XMPPNode.import(doc.root)
|
42
|
+
|
43
|
+
new_vcard = Blather::Stanza::Iq::Vcard::Vcard.new
|
44
|
+
new_vcard["NICKNAME"] = 'Mercutio'
|
45
|
+
|
46
|
+
query.vcard = new_vcard
|
47
|
+
|
48
|
+
query.xpath('ns:vCard', :ns => 'vcard-temp').size.must_equal 1
|
49
|
+
query.find_first('ns:vCard/ns:NICKNAME', :ns => 'vcard-temp').content.must_equal 'Mercutio'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe Blather::Stanza::Iq::Vcard::Vcard do
|
54
|
+
it 'can set vcard elements' do
|
55
|
+
query = Blather::Stanza::Iq::Vcard.new :set
|
56
|
+
query.vcard['NICKNAME'] = 'Romeo'
|
57
|
+
query.find_first('ns:vCard/ns:NICKNAME', :ns => 'vcard-temp').content.must_equal 'Romeo'
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'can set deep vcard elements' do
|
61
|
+
query = Blather::Stanza::Iq::Vcard.new :set
|
62
|
+
query.vcard['PHOTO/TYPE'] = 'image/png'
|
63
|
+
query.vcard['PHOTO/BINVAL'] = '===='
|
64
|
+
query.find_first('ns:vCard/ns:PHOTO', :ns => 'vcard-temp').children.size.must_equal 2
|
65
|
+
query.find_first('ns:vCard/ns:PHOTO', :ns => 'vcard-temp').children.detect { |n| n.element_name == 'TYPE' && n.content == 'image/png' }.wont_be_nil
|
66
|
+
query.find_first('ns:vCard/ns:PHOTO', :ns => 'vcard-temp').children.detect { |n| n.element_name == 'BINVAL' && n.content == '====' }.wont_be_nil
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'can get vcard elements' do
|
70
|
+
query = Blather::Stanza::Iq::Vcard.new :set
|
71
|
+
query.vcard['NICKNAME'] = 'Romeo'
|
72
|
+
query.vcard['NICKNAME'].must_equal 'Romeo'
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'can get deep vcard elements' do
|
76
|
+
query = Blather::Stanza::Iq::Vcard.new :set
|
77
|
+
query.vcard['PHOTO/TYPE'] = 'image/png'
|
78
|
+
query.vcard['PHOTO/BINVAL'] = '===='
|
79
|
+
query.vcard['PHOTO/TYPE'].must_equal 'image/png'
|
80
|
+
query.vcard['PHOTO/BINVAL'].must_equal '===='
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'returns nil on vcard elements which does not exist' do
|
84
|
+
query = Blather::Stanza::Iq::Vcard.new :set
|
85
|
+
query.vcard['NICKNAME'] = 'Romeo'
|
86
|
+
query.vcard['FN'].must_be_nil
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'can update vcard elements' do
|
90
|
+
doc = parse_stanza vcard_xml
|
91
|
+
query = Blather::XMPPNode.import(doc.root)
|
92
|
+
query.vcard['NICKNAME'].must_equal 'Romeo'
|
93
|
+
query.vcard['NICKNAME'] = 'Mercutio'
|
94
|
+
query.vcard['NICKNAME'].must_equal 'Mercutio'
|
95
|
+
end
|
96
|
+
end
|