shingara-blather 0.4.9 → 0.4.14
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.
- 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
|