sprsquish-blather 0.3.4 → 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.
- data/LICENSE +1 -1
- data/README.rdoc +41 -12
- data/examples/echo.rb +1 -1
- data/examples/execute.rb +0 -5
- data/examples/pubsub/cli.rb +64 -0
- data/examples/pubsub/ping_pong.rb +18 -0
- data/examples/rosterprint.rb +14 -0
- data/examples/xmpp4r/echo.rb +35 -0
- data/lib/blather/client/client.rb +19 -13
- data/lib/blather/client/dsl/pubsub.rb +133 -0
- data/lib/blather/client/dsl.rb +16 -0
- data/lib/blather/client.rb +1 -1
- data/lib/blather/core_ext/active_support/inheritable_attributes.rb +117 -0
- data/lib/blather/core_ext/active_support.rb +1 -117
- data/lib/blather/core_ext/nokogiri.rb +35 -0
- data/lib/blather/errors/sasl_error.rb +3 -1
- data/lib/blather/errors/stanza_error.rb +10 -17
- data/lib/blather/errors/stream_error.rb +11 -14
- data/lib/blather/errors.rb +3 -20
- data/lib/blather/jid.rb +1 -0
- data/lib/blather/roster.rb +9 -0
- data/lib/blather/roster_item.rb +6 -1
- data/lib/blather/stanza/disco/disco_info.rb +45 -33
- data/lib/blather/stanza/disco/disco_items.rb +32 -21
- data/lib/blather/stanza/disco.rb +7 -1
- data/lib/blather/stanza/iq/query.rb +16 -8
- data/lib/blather/stanza/iq/roster.rb +33 -22
- data/lib/blather/stanza/iq.rb +13 -8
- data/lib/blather/stanza/message.rb +20 -31
- data/lib/blather/stanza/presence/status.rb +13 -21
- data/lib/blather/stanza/presence/subscription.rb +11 -16
- data/lib/blather/stanza/presence.rb +3 -5
- data/lib/blather/stanza/pubsub/affiliations.rb +50 -0
- data/lib/blather/stanza/pubsub/create.rb +43 -0
- data/lib/blather/stanza/pubsub/errors.rb +9 -0
- data/lib/blather/stanza/pubsub/event.rb +77 -0
- data/lib/blather/stanza/pubsub/items.rb +63 -0
- data/lib/blather/stanza/pubsub/publish.rb +58 -0
- data/lib/blather/stanza/pubsub/retract.rb +53 -0
- data/lib/blather/stanza/pubsub/subscribe.rb +42 -0
- data/lib/blather/stanza/pubsub/subscription.rb +66 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +55 -0
- data/lib/blather/stanza/pubsub/unsubscribe.rb +42 -0
- data/lib/blather/stanza/pubsub.rb +63 -0
- data/lib/blather/stanza/pubsub_owner/delete.rb +34 -0
- data/lib/blather/stanza/pubsub_owner/purge.rb +34 -0
- data/lib/blather/stanza/pubsub_owner.rb +41 -0
- data/lib/blather/stanza.rb +35 -18
- data/lib/blather/stream/client.rb +1 -2
- data/lib/blather/stream/component.rb +9 -5
- data/lib/blather/stream/features/resource.rb +63 -0
- data/lib/blather/stream/{sasl.rb → features/sasl.rb} +53 -52
- data/lib/blather/stream/features/session.rb +44 -0
- data/lib/blather/stream/features/tls.rb +28 -0
- data/lib/blather/stream/features.rb +53 -0
- data/lib/blather/stream/parser.rb +70 -46
- data/lib/blather/stream.rb +76 -168
- data/lib/blather/xmpp_node.rb +113 -52
- data/lib/blather.rb +35 -12
- data/spec/blather/client/client_spec.rb +44 -58
- data/spec/blather/client/dsl/pubsub_spec.rb +465 -0
- data/spec/blather/client/dsl_spec.rb +19 -6
- data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
- data/spec/blather/errors/sasl_error_spec.rb +8 -8
- data/spec/blather/errors/stanza_error_spec.rb +25 -33
- data/spec/blather/errors/stream_error_spec.rb +21 -16
- data/spec/blather/errors_spec.rb +4 -11
- data/spec/blather/jid_spec.rb +31 -30
- data/spec/blather/roster_item_spec.rb +34 -23
- data/spec/blather/roster_spec.rb +27 -12
- data/spec/blather/stanza/discos/disco_info_spec.rb +61 -42
- data/spec/blather/stanza/discos/disco_items_spec.rb +47 -35
- data/spec/blather/stanza/iq/query_spec.rb +34 -11
- data/spec/blather/stanza/iq/roster_spec.rb +47 -30
- data/spec/blather/stanza/iq_spec.rb +19 -14
- data/spec/blather/stanza/message_spec.rb +30 -17
- data/spec/blather/stanza/presence/status_spec.rb +43 -20
- data/spec/blather/stanza/presence/subscription_spec.rb +41 -21
- data/spec/blather/stanza/presence_spec.rb +34 -21
- data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
- data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
- data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
- data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
- data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
- data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
- data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
- data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
- data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
- data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
- data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
- data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
- data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
- data/spec/blather/stanza/pubsub_spec.rb +62 -0
- data/spec/blather/stanza_spec.rb +53 -38
- data/spec/blather/stream/client_spec.rb +231 -88
- data/spec/blather/stream/component_spec.rb +14 -5
- data/spec/blather/stream/parser_spec.rb +145 -0
- data/spec/blather/xmpp_node_spec.rb +192 -96
- data/spec/fixtures/pubsub.rb +311 -0
- data/spec/spec_helper.rb +5 -4
- metadata +53 -17
- data/Rakefile +0 -139
- data/ext/extconf.rb +0 -65
- data/ext/push_parser.c +0 -209
- data/lib/blather/core_ext/libxml.rb +0 -28
- data/lib/blather/stream/resource.rb +0 -48
- data/lib/blather/stream/session.rb +0 -36
- data/lib/blather/stream/stream_handler.rb +0 -39
- data/lib/blather/stream/tls.rb +0 -33
- data/spec/blather/core_ext/libxml_spec.rb +0 -58
@@ -0,0 +1,145 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
|
2
|
+
|
3
|
+
describe Blather::Stream::Parser do
|
4
|
+
before do
|
5
|
+
@client = Class.new do
|
6
|
+
attr_reader :data
|
7
|
+
def stopped?; false; end
|
8
|
+
def receive(data)
|
9
|
+
@data ||= []
|
10
|
+
@data << data
|
11
|
+
end
|
12
|
+
end.new
|
13
|
+
@parser = Blather::Stream::Parser.new @client
|
14
|
+
end
|
15
|
+
|
16
|
+
after { @client = @parser = nil}
|
17
|
+
|
18
|
+
def check_parse(data)
|
19
|
+
@parser.receive_data data
|
20
|
+
@client.data.size.must_equal 1
|
21
|
+
@client.data[0].to_s.gsub(/\n\s*/,'').must_equal data
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'handles fragmented parsing' do
|
25
|
+
@parser.receive_data '<foo>'
|
26
|
+
@parser.receive_data '<bar/>'
|
27
|
+
@parser.receive_data '</foo>'
|
28
|
+
@client.data.size.must_equal 1
|
29
|
+
@client.data[0].to_s.gsub(/\n\s*/,'').must_equal '<foo><bar/></foo>'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'handles a basic example' do
|
33
|
+
check_parse "<foo/>"
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'handles a basic namespace definition' do
|
37
|
+
check_parse '<foo xmlns="bar:baz"/>'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'handles multiple namespace definitions' do
|
41
|
+
check_parse '<foo xmlns="bar:baz" xmlns:bar="baz"/>'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'handles prefix namespacing' do
|
45
|
+
check_parse '<bar:foo xmlns="bar:baz" xmlns:bar="baz"/>'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'handles namespaces with children' do
|
49
|
+
check_parse "<foo xmlns=\"bar:baz\"><bar/></foo>"
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'handles multiple namespaces with children' do
|
53
|
+
check_parse "<foo xmlns=\"bar:baz\" xmlns:bar=\"baz\"><bar/></foo>"
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'handles prefix namespaces with children' do
|
57
|
+
check_parse "<bar:foo xmlns=\"bar:baz\" xmlns:bar=\"baz\"><bar/></bar:foo>"
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'handles prefix namespaces with children in the namespace' do
|
61
|
+
check_parse "<bar:foo xmlns=\"bar:baz\" xmlns:bar=\"baz\"><bar:bar/></bar:foo>"
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'handles prefix namespaces with children in the namespace' do
|
65
|
+
check_parse "<bar:foo xmlns=\"bar:baz\" xmlns:bar=\"baz\"><baz><bar:buz/></baz></bar:foo>"
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'handles attributes' do
|
69
|
+
check_parse '<foo bar="baz"/>'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'handles character input' do
|
73
|
+
check_parse '<foo>bar baz fizbuz</foo>'
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'handles a complex input' do
|
77
|
+
data = [
|
78
|
+
'<message type="error" id="another-id">',
|
79
|
+
'<error type="modify">',
|
80
|
+
'<undefined-condition xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>',
|
81
|
+
'<text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">Some special application diagnostic information...</text>',
|
82
|
+
'<special-application-condition xmlns="application-ns"/>',
|
83
|
+
"</error>",
|
84
|
+
"</message>"
|
85
|
+
]
|
86
|
+
data.each { |d| @parser.receive_data d }
|
87
|
+
@client.data.size.must_equal 1
|
88
|
+
@client.data[0].to_s.split("\n").map{|n|n.strip}.must_equal data
|
89
|
+
@client.data[0].xpath('//*[namespace-uri()="urn:ietf:params:xml:ns:xmpp-stanzas"]').size.must_equal 2
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'responds with stream:stream as a separate response' do
|
93
|
+
data = [
|
94
|
+
'<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" to="example.com" version="1.0">',
|
95
|
+
'<foo/>'
|
96
|
+
]
|
97
|
+
data.each { |d| @parser.receive_data d }
|
98
|
+
@client.data.size.must_equal 2
|
99
|
+
@client.data[0].document.xpath('/stream:stream[@to="example.com" and @version="1.0"]', 'xmlns' => 'jabber:client', 'stream' => 'http://etherx.jabber.org/streams').size.must_equal 1
|
100
|
+
@client.data[1].to_s.must_equal '<foo/>'
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'response with stream:end when receiving </stream:stream>' do
|
104
|
+
@parser.receive_data '<stream:stream xmlns:stream="http://etherx.jabber.org/streams"/>'
|
105
|
+
@client.data.size.must_equal 2
|
106
|
+
@client.data[1].to_s.must_equal '<stream:end xmlns:stream="http://etherx.jabber.org/streams"/>'
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'raises ParseError when an error is sent' do
|
110
|
+
lambda { @parser.receive_data "<stream:stream>" }.must_raise(Blather::ParseError)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'handles stream stanzas without an issue' do
|
114
|
+
data = [
|
115
|
+
'<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" to="example.com" version="1.0">',
|
116
|
+
'<stream:features/>'
|
117
|
+
]
|
118
|
+
data.each { |d| @parser.receive_data d }
|
119
|
+
@client.data.size.must_equal 2
|
120
|
+
@client.data[0].document.xpath('/stream:stream[@to="example.com" and @version="1.0"]', 'xmlns' => 'jabber:client', 'stream' => 'http://etherx.jabber.org/streams').size.must_equal 1
|
121
|
+
@client.data[1].to_s.must_equal '<stream:features xmlns:stream="http://etherx.jabber.org/streams"/>'
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'ignores the client namespace on stanzas' do
|
125
|
+
[ "<message type='chat' to='n@d' from='n@d/r' id='id1' xmlns='jabber:client'>",
|
126
|
+
"<body>exit</body>",
|
127
|
+
"<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>exit</body></html>",
|
128
|
+
"</message>"
|
129
|
+
].each { |d| @parser.receive_data d }
|
130
|
+
@client.data.size.must_equal 1
|
131
|
+
@client.data[0].document.xpath('/message/body[.="exit"]').wont_be_empty
|
132
|
+
@client.data[0].document.xpath('/message/im:html/xhtml:body[.="exit"]', 'im' => 'http://jabber.org/protocol/xhtml-im', 'xhtml' => 'http://www.w3.org/1999/xhtml').wont_be_empty
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'ignores the component namespace on stanzas' do
|
136
|
+
[ "<message type='chat' to='n@d' from='n@d/r' id='id1' xmlns='jabber:component:accept'>",
|
137
|
+
"<body>exit</body>",
|
138
|
+
"<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>exit</body></html>",
|
139
|
+
"</message>"
|
140
|
+
].each { |d| @parser.receive_data d }
|
141
|
+
@client.data.size.must_equal 1
|
142
|
+
@client.data[0].document.xpath('/message/body[.="exit"]').wont_be_empty
|
143
|
+
@client.data[0].document.xpath('/message/im:html/xhtml:body[.="exit"]', 'im' => 'http://jabber.org/protocol/xhtml-im', 'xhtml' => 'http://www.w3.org/1999/xhtml').wont_be_empty
|
144
|
+
end
|
145
|
+
end
|
@@ -1,104 +1,182 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
3
|
+
describe Blather::XMPPNode do
|
4
|
+
before { @doc = Nokogiri::XML::Document.new }
|
5
|
+
|
6
|
+
it 'generates a new node automatically setting the document' do
|
7
|
+
n = Blather::XMPPNode.new 'foo'
|
6
8
|
n.element_name.must_equal 'foo'
|
9
|
+
n.document.wont_equal @doc
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'sets the new document root to the node' do
|
13
|
+
n = Blather::XMPPNode.new 'foo'
|
14
|
+
n.document.root.must_equal n
|
7
15
|
end
|
8
16
|
|
9
|
-
it '
|
10
|
-
|
11
|
-
|
12
|
-
|
17
|
+
it 'does not set the document root if the document is provided' do
|
18
|
+
n = Blather::XMPPNode.new 'foo', @doc
|
19
|
+
n.document.root.wont_equal n
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'generates a new node with the given document' do
|
23
|
+
n = Blather::XMPPNode.new 'foo', @doc
|
24
|
+
n.element_name.must_equal 'foo'
|
25
|
+
n.document.must_equal @doc
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'generates a node based on the registered_name' do
|
29
|
+
foo = Class.new(Blather::XMPPNode)
|
30
|
+
foo.registered_name = 'foo'
|
31
|
+
foo.new.element_name.must_equal 'foo'
|
13
32
|
end
|
14
33
|
|
15
34
|
it 'sets the namespace on creation' do
|
16
|
-
|
17
|
-
|
18
|
-
|
35
|
+
foo = Class.new(Blather::XMPPNode)
|
36
|
+
foo.registered_ns = 'foo'
|
37
|
+
foo.new('foo').namespace.href.must_equal 'foo'
|
19
38
|
end
|
20
39
|
|
21
40
|
it 'registers sub classes' do
|
22
|
-
class
|
23
|
-
|
24
|
-
|
25
|
-
XMPPNode.class_from_registration('foo', 'foo:bar').must_equal
|
41
|
+
class RegistersSubClass < Blather::XMPPNode; register 'foo', 'foo:bar'; end
|
42
|
+
RegistersSubClass.registered_name.must_equal 'foo'
|
43
|
+
RegistersSubClass.registered_ns.must_equal 'foo:bar'
|
44
|
+
Blather::XMPPNode.class_from_registration('foo', 'foo:bar').must_equal RegistersSubClass
|
26
45
|
end
|
27
46
|
|
28
47
|
it 'imports another node' do
|
29
|
-
class
|
30
|
-
n = XMPPNode.new('foo')
|
48
|
+
class ImportSubClass < Blather::XMPPNode; register 'foo', 'foo:bar'; end
|
49
|
+
n = Blather::XMPPNode.new('foo')
|
31
50
|
n.namespace = 'foo:bar'
|
32
|
-
XMPPNode.import(n).must_be_kind_of
|
51
|
+
Blather::XMPPNode.import(n).must_be_kind_of ImportSubClass
|
33
52
|
end
|
34
53
|
|
35
54
|
it 'provides an attribute_reader' do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
f = Foo.new
|
51
|
-
f.must_respond_to :foo
|
52
|
-
f.foo.must_be_nil
|
53
|
-
f.attributes[:foo] = 'bar'
|
54
|
-
f.foo.must_equal 'bar'
|
55
|
+
foo = Class.new(Blather::XMPPNode) { attribute_reader :bar }.new
|
56
|
+
foo.must_respond_to :bar
|
57
|
+
foo.bar.must_be_nil
|
58
|
+
foo[:bar] = 'baz'
|
59
|
+
foo.bar.must_equal 'baz'
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'provides an attribute_reader with converstion' do
|
63
|
+
foo = Class.new(Blather::XMPPNode) { attribute_reader :bar, :call => :to_sym }.new
|
64
|
+
foo.must_respond_to :bar
|
65
|
+
foo.bar.must_be_nil
|
66
|
+
foo[:bar] = 'baz'
|
67
|
+
foo.bar.must_equal :baz
|
55
68
|
end
|
56
69
|
|
57
70
|
it 'provides an attribute_writer' do
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
f.attributes[:foo].must_be_nil
|
63
|
-
f.foo = 'bar'
|
64
|
-
f.attributes[:foo].must_equal 'bar'
|
71
|
+
foo = Class.new(Blather::XMPPNode) { attribute_writer :bar }.new
|
72
|
+
foo[:bar].must_be_nil
|
73
|
+
foo.bar = 'baz'
|
74
|
+
foo[:bar].must_equal 'baz'
|
65
75
|
end
|
66
76
|
|
67
77
|
it 'provides an attribute_accessor' do
|
68
|
-
|
69
|
-
attribute_accessor :
|
70
|
-
attribute_accessor :
|
71
|
-
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
foo = Class.new(Blather::XMPPNode) do
|
79
|
+
attribute_accessor :bar, :call => :to_sym
|
80
|
+
attribute_accessor :baz
|
81
|
+
end.new
|
82
|
+
foo.must_respond_to :bar
|
83
|
+
foo.bar.must_be_nil
|
84
|
+
foo.bar = 'fiz'
|
85
|
+
foo.bar.must_equal :fiz
|
86
|
+
|
87
|
+
foo.must_respond_to :baz
|
88
|
+
foo.baz.must_be_nil
|
89
|
+
foo.baz = 'buz'
|
90
|
+
foo.baz.must_equal 'buz'
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'provides a content reader' do
|
94
|
+
foo = Class.new(Blather::XMPPNode) { content_attr_reader :bar }.new('foo')
|
95
|
+
foo << (bar = Blather::XMPPNode.new('bar', foo.document))
|
96
|
+
bar.content = 'baz'
|
97
|
+
foo.must_respond_to :bar
|
98
|
+
foo.bar.must_equal 'baz'
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'provides a content reader that converts the value' do
|
102
|
+
foo = Class.new(Blather::XMPPNode) { content_attr_reader :bar, :to_sym }.new('foo')
|
103
|
+
foo << (bar = Blather::XMPPNode.new('bar', foo.document))
|
104
|
+
bar.content = 'baz'
|
105
|
+
foo.must_respond_to :bar
|
106
|
+
foo.bar.must_equal :baz
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'provides a content reader with a different node' do
|
110
|
+
foo = Class.new(Blather::XMPPNode) { content_attr_reader :bar, nil, :fiz }.new('foo')
|
111
|
+
foo << (fiz = Blather::XMPPNode.new('fiz', foo.document))
|
112
|
+
fiz.content = 'baz'
|
113
|
+
foo.must_respond_to :bar
|
114
|
+
foo.bar.must_equal 'baz'
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'provides a content writer' do
|
118
|
+
foo = Class.new(Blather::XMPPNode) { content_attr_writer :bar }.new('foo')
|
119
|
+
foo.must_respond_to :bar=
|
120
|
+
foo.bar = 'baz'
|
121
|
+
foo.content_from(:bar).must_equal 'baz'
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'provides a content writer with a different node' do
|
125
|
+
foo = Class.new(Blather::XMPPNode) { content_attr_writer :bar, :fiz }.new('foo')
|
126
|
+
foo.must_respond_to :bar=
|
127
|
+
foo.bar = 'baz'
|
128
|
+
foo.content_from(:fiz).must_equal 'baz'
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'provides a content accessor' do
|
132
|
+
foo = Class.new(Blather::XMPPNode) { content_attr_accessor :bar }.new('foo')
|
133
|
+
foo << (bar = Blather::XMPPNode.new('bar', foo.document))
|
134
|
+
foo.must_respond_to :bar=
|
135
|
+
foo.must_respond_to :bar
|
136
|
+
foo.bar = 'baz'
|
137
|
+
foo.bar.must_equal 'baz'
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'provides a content accessor with conversion' do
|
141
|
+
foo = Class.new(Blather::XMPPNode) { content_attr_accessor :bar, :to_sym }.new('foo')
|
142
|
+
foo << (bar = Blather::XMPPNode.new('bar', foo.document))
|
143
|
+
foo.must_respond_to :bar=
|
144
|
+
foo.must_respond_to :bar
|
145
|
+
foo.bar = 'baz'
|
146
|
+
foo.bar.must_equal :baz
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'provides a content writer that removes a child when set to nil' do
|
150
|
+
foo = Class.new(Blather::XMPPNode) { content_attr_writer :bar }.new('foo')
|
151
|
+
foo << (bar = Blather::XMPPNode.new('bar', foo.document))
|
152
|
+
bar.content = 'baz'
|
153
|
+
foo.content_from(:bar).must_equal 'baz'
|
154
|
+
foo.xpath('bar').wont_be_empty
|
155
|
+
|
156
|
+
foo.must_respond_to :bar=
|
157
|
+
foo.bar = nil
|
158
|
+
foo.content_from(:bar).must_be_nil
|
159
|
+
foo.xpath('bar').must_be_empty
|
82
160
|
end
|
83
161
|
|
84
162
|
it 'can convert itself into a stanza' do
|
85
|
-
class
|
86
|
-
n = XMPPNode.new('foo')
|
87
|
-
n.to_stanza.must_be_kind_of
|
163
|
+
class StanzaConvert < Blather::XMPPNode; register 'foo'; end
|
164
|
+
n = Blather::XMPPNode.new('foo')
|
165
|
+
n.to_stanza.must_be_kind_of StanzaConvert
|
88
166
|
end
|
89
167
|
|
90
168
|
it 'provides "attr_accessor" for namespace' do
|
91
|
-
n = XMPPNode.new('foo')
|
169
|
+
n = Blather::XMPPNode.new('foo')
|
92
170
|
n.namespace.must_be_nil
|
93
171
|
|
94
172
|
n.namespace = 'foo:bar'
|
95
|
-
n.
|
173
|
+
n.namespace_href.must_equal 'foo:bar'
|
96
174
|
end
|
97
175
|
|
98
176
|
it 'will remove a child element' do
|
99
|
-
n = XMPPNode.new 'foo'
|
100
|
-
n << XMPPNode.new('bar')
|
101
|
-
n << XMPPNode.new('bar')
|
177
|
+
n = Blather::XMPPNode.new 'foo'
|
178
|
+
n << Blather::XMPPNode.new('bar', n.document)
|
179
|
+
n << Blather::XMPPNode.new('bar', n.document)
|
102
180
|
|
103
181
|
n.find(:bar).size.must_equal 2
|
104
182
|
n.remove_child 'bar'
|
@@ -106,9 +184,9 @@ describe 'Blather::XMPPNode' do
|
|
106
184
|
end
|
107
185
|
|
108
186
|
it 'will remove a child with a specific xmlns' do
|
109
|
-
n = XMPPNode.new 'foo'
|
110
|
-
n << XMPPNode.new('bar')
|
111
|
-
c = XMPPNode.new('bar')
|
187
|
+
n = Blather::XMPPNode.new 'foo'
|
188
|
+
n << Blather::XMPPNode.new('bar')
|
189
|
+
c = Blather::XMPPNode.new('bar')
|
112
190
|
c.namespace = 'foo:bar'
|
113
191
|
n << c
|
114
192
|
|
@@ -119,31 +197,26 @@ describe 'Blather::XMPPNode' do
|
|
119
197
|
end
|
120
198
|
|
121
199
|
it 'will remove all child elements' do
|
122
|
-
n = XMPPNode.new 'foo'
|
123
|
-
n << XMPPNode.new('bar')
|
124
|
-
n << XMPPNode.new('bar')
|
200
|
+
n = Blather::XMPPNode.new 'foo'
|
201
|
+
n << Blather::XMPPNode.new('bar')
|
202
|
+
n << Blather::XMPPNode.new('bar')
|
125
203
|
|
126
204
|
n.find(:bar).size.must_equal 2
|
127
205
|
n.remove_children 'bar'
|
128
206
|
n.find(:bar).size.must_equal 0
|
129
207
|
end
|
130
208
|
|
131
|
-
it 'provides a helper to grab content from a child' do
|
132
|
-
n = XMPPNode.new 'foo'
|
133
|
-
n << XMPPNode.new('bar', 'baz')
|
134
|
-
n.content_from(:bar).must_equal 'baz'
|
135
|
-
end
|
136
|
-
|
137
209
|
it 'provides a copy mechanism' do
|
138
|
-
n = XMPPNode.new 'foo'
|
210
|
+
n = Blather::XMPPNode.new 'foo'
|
139
211
|
n2 = n.copy
|
140
212
|
n2.object_id.wont_equal n.object_id
|
141
213
|
n2.element_name.must_equal n.element_name
|
142
214
|
end
|
143
215
|
|
144
216
|
it 'provides an inhert mechanism' do
|
145
|
-
n = XMPPNode.new 'foo'
|
146
|
-
n2 = XMPPNode.new 'foo'
|
217
|
+
n = Blather::XMPPNode.new 'foo'
|
218
|
+
n2 = Blather::XMPPNode.new 'foo'
|
219
|
+
n2.content = 'bar'
|
147
220
|
n2['foo'] = 'bar'
|
148
221
|
|
149
222
|
n.inherit(n2)
|
@@ -152,32 +225,55 @@ describe 'Blather::XMPPNode' do
|
|
152
225
|
end
|
153
226
|
|
154
227
|
it 'provides a mechanism to inherit attrs' do
|
155
|
-
n = XMPPNode.new 'foo'
|
156
|
-
n2 = XMPPNode.new 'foo'
|
228
|
+
n = Blather::XMPPNode.new 'foo'
|
229
|
+
n2 = Blather::XMPPNode.new 'foo'
|
157
230
|
n2['foo'] = 'bar'
|
158
231
|
|
159
232
|
n.inherit_attrs(n2.attributes)
|
160
233
|
n['foo'].must_equal 'bar'
|
161
234
|
end
|
162
235
|
|
163
|
-
it '
|
164
|
-
|
165
|
-
|
166
|
-
|
236
|
+
it 'has a content_from helper that pulls the content from a child node' do
|
237
|
+
f = Blather::XMPPNode.new('foo')
|
238
|
+
f << (b = Blather::XMPPNode.new('bar'))
|
239
|
+
b.content = 'content'
|
240
|
+
f.content_from(:bar).must_equal 'content'
|
167
241
|
end
|
168
242
|
|
169
|
-
it '
|
170
|
-
|
171
|
-
|
172
|
-
|
243
|
+
it 'returns nil when sent #content_from and a missing node' do
|
244
|
+
f = Blather::XMPPNode.new('foo')
|
245
|
+
f.content_from(:bar).must_be_nil
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'creates a new node and sets content when sent #set_content_for' do
|
249
|
+
f = Blather::XMPPNode.new('foo')
|
250
|
+
f.must_respond_to :set_content_for
|
251
|
+
f.xpath('bar').must_be_empty
|
252
|
+
f.set_content_for :bar, :baz
|
253
|
+
f.xpath('bar').wont_be_empty
|
254
|
+
f.xpath('bar').first.content.must_equal 'baz'
|
255
|
+
end
|
173
256
|
|
174
|
-
|
175
|
-
|
257
|
+
it 'removes a child node when sent #set_content_for with nil' do
|
258
|
+
f = Blather::XMPPNode.new('foo')
|
259
|
+
f << (b = Blather::XMPPNode.new('bar'))
|
260
|
+
f.must_respond_to :set_content_for
|
261
|
+
f.xpath('bar').wont_be_empty
|
262
|
+
f.set_content_for :bar, nil
|
263
|
+
f.xpath('bar').must_be_empty
|
176
264
|
end
|
177
265
|
|
178
|
-
it '
|
179
|
-
|
180
|
-
|
181
|
-
|
266
|
+
it 'will change the content of an existing node when sent #set_content_for' do
|
267
|
+
f = Blather::XMPPNode.new('foo')
|
268
|
+
f << (b = Blather::XMPPNode.new('bar'))
|
269
|
+
b.content = 'baz'
|
270
|
+
f.must_respond_to :set_content_for
|
271
|
+
f.xpath('bar').wont_be_empty
|
272
|
+
f.xpath('bar').first.content.must_equal 'baz'
|
273
|
+
control = f.xpath('bar').first.pointer_id
|
274
|
+
|
275
|
+
f.set_content_for :bar, 'fiz'
|
276
|
+
f.xpath('bar').first.content.must_equal 'fiz'
|
277
|
+
f.xpath('bar').first.pointer_id.must_equal control
|
182
278
|
end
|
183
279
|
end
|