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.
Files changed (110) hide show
  1. data/LICENSE +1 -1
  2. data/README.rdoc +41 -12
  3. data/examples/echo.rb +1 -1
  4. data/examples/execute.rb +0 -5
  5. data/examples/pubsub/cli.rb +64 -0
  6. data/examples/pubsub/ping_pong.rb +18 -0
  7. data/examples/rosterprint.rb +14 -0
  8. data/examples/xmpp4r/echo.rb +35 -0
  9. data/lib/blather/client/client.rb +19 -13
  10. data/lib/blather/client/dsl/pubsub.rb +133 -0
  11. data/lib/blather/client/dsl.rb +16 -0
  12. data/lib/blather/client.rb +1 -1
  13. data/lib/blather/core_ext/active_support/inheritable_attributes.rb +117 -0
  14. data/lib/blather/core_ext/active_support.rb +1 -117
  15. data/lib/blather/core_ext/nokogiri.rb +35 -0
  16. data/lib/blather/errors/sasl_error.rb +3 -1
  17. data/lib/blather/errors/stanza_error.rb +10 -17
  18. data/lib/blather/errors/stream_error.rb +11 -14
  19. data/lib/blather/errors.rb +3 -20
  20. data/lib/blather/jid.rb +1 -0
  21. data/lib/blather/roster.rb +9 -0
  22. data/lib/blather/roster_item.rb +6 -1
  23. data/lib/blather/stanza/disco/disco_info.rb +45 -33
  24. data/lib/blather/stanza/disco/disco_items.rb +32 -21
  25. data/lib/blather/stanza/disco.rb +7 -1
  26. data/lib/blather/stanza/iq/query.rb +16 -8
  27. data/lib/blather/stanza/iq/roster.rb +33 -22
  28. data/lib/blather/stanza/iq.rb +13 -8
  29. data/lib/blather/stanza/message.rb +20 -31
  30. data/lib/blather/stanza/presence/status.rb +13 -21
  31. data/lib/blather/stanza/presence/subscription.rb +11 -16
  32. data/lib/blather/stanza/presence.rb +3 -5
  33. data/lib/blather/stanza/pubsub/affiliations.rb +50 -0
  34. data/lib/blather/stanza/pubsub/create.rb +43 -0
  35. data/lib/blather/stanza/pubsub/errors.rb +9 -0
  36. data/lib/blather/stanza/pubsub/event.rb +77 -0
  37. data/lib/blather/stanza/pubsub/items.rb +63 -0
  38. data/lib/blather/stanza/pubsub/publish.rb +58 -0
  39. data/lib/blather/stanza/pubsub/retract.rb +53 -0
  40. data/lib/blather/stanza/pubsub/subscribe.rb +42 -0
  41. data/lib/blather/stanza/pubsub/subscription.rb +66 -0
  42. data/lib/blather/stanza/pubsub/subscriptions.rb +55 -0
  43. data/lib/blather/stanza/pubsub/unsubscribe.rb +42 -0
  44. data/lib/blather/stanza/pubsub.rb +63 -0
  45. data/lib/blather/stanza/pubsub_owner/delete.rb +34 -0
  46. data/lib/blather/stanza/pubsub_owner/purge.rb +34 -0
  47. data/lib/blather/stanza/pubsub_owner.rb +41 -0
  48. data/lib/blather/stanza.rb +35 -18
  49. data/lib/blather/stream/client.rb +1 -2
  50. data/lib/blather/stream/component.rb +9 -5
  51. data/lib/blather/stream/features/resource.rb +63 -0
  52. data/lib/blather/stream/{sasl.rb → features/sasl.rb} +53 -52
  53. data/lib/blather/stream/features/session.rb +44 -0
  54. data/lib/blather/stream/features/tls.rb +28 -0
  55. data/lib/blather/stream/features.rb +53 -0
  56. data/lib/blather/stream/parser.rb +70 -46
  57. data/lib/blather/stream.rb +76 -168
  58. data/lib/blather/xmpp_node.rb +113 -52
  59. data/lib/blather.rb +35 -12
  60. data/spec/blather/client/client_spec.rb +44 -58
  61. data/spec/blather/client/dsl/pubsub_spec.rb +465 -0
  62. data/spec/blather/client/dsl_spec.rb +19 -6
  63. data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
  64. data/spec/blather/errors/sasl_error_spec.rb +8 -8
  65. data/spec/blather/errors/stanza_error_spec.rb +25 -33
  66. data/spec/blather/errors/stream_error_spec.rb +21 -16
  67. data/spec/blather/errors_spec.rb +4 -11
  68. data/spec/blather/jid_spec.rb +31 -30
  69. data/spec/blather/roster_item_spec.rb +34 -23
  70. data/spec/blather/roster_spec.rb +27 -12
  71. data/spec/blather/stanza/discos/disco_info_spec.rb +61 -42
  72. data/spec/blather/stanza/discos/disco_items_spec.rb +47 -35
  73. data/spec/blather/stanza/iq/query_spec.rb +34 -11
  74. data/spec/blather/stanza/iq/roster_spec.rb +47 -30
  75. data/spec/blather/stanza/iq_spec.rb +19 -14
  76. data/spec/blather/stanza/message_spec.rb +30 -17
  77. data/spec/blather/stanza/presence/status_spec.rb +43 -20
  78. data/spec/blather/stanza/presence/subscription_spec.rb +41 -21
  79. data/spec/blather/stanza/presence_spec.rb +34 -21
  80. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  81. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  82. data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
  83. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  84. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  85. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  86. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  87. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  88. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  89. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
  90. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  91. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  92. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  93. data/spec/blather/stanza/pubsub_spec.rb +62 -0
  94. data/spec/blather/stanza_spec.rb +53 -38
  95. data/spec/blather/stream/client_spec.rb +231 -88
  96. data/spec/blather/stream/component_spec.rb +14 -5
  97. data/spec/blather/stream/parser_spec.rb +145 -0
  98. data/spec/blather/xmpp_node_spec.rb +192 -96
  99. data/spec/fixtures/pubsub.rb +311 -0
  100. data/spec/spec_helper.rb +5 -4
  101. metadata +53 -17
  102. data/Rakefile +0 -139
  103. data/ext/extconf.rb +0 -65
  104. data/ext/push_parser.c +0 -209
  105. data/lib/blather/core_ext/libxml.rb +0 -28
  106. data/lib/blather/stream/resource.rb +0 -48
  107. data/lib/blather/stream/session.rb +0 -36
  108. data/lib/blather/stream/stream_handler.rb +0 -39
  109. data/lib/blather/stream/tls.rb +0 -33
  110. 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 'Blather::XMPPNode' do
4
- it 'generates a new node' do
5
- n = XMPPNode.new 'foo'
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 'generates a node based on the current name' do
10
- class Foo < XMPPNode; end
11
- Foo.name = 'foo'
12
- Foo.new.element_name.must_equal 'foo'
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
- class Foo < XMPPNode; end
17
- Foo.ns = 'foo'
18
- Foo.new('foo').namespace.must_equal 'foo'
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 Foo < XMPPNode; register 'foo', 'foo:bar'; end
23
- Foo.name.must_equal 'foo'
24
- Foo.ns.must_equal 'foo:bar'
25
- XMPPNode.class_from_registration('foo', 'foo:bar').must_equal Foo
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 Foo < XMPPNode; register 'foo', 'foo:bar'; end
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 Foo
51
+ Blather::XMPPNode.import(n).must_be_kind_of ImportSubClass
33
52
  end
34
53
 
35
54
  it 'provides an attribute_reader' do
36
- class Foo < XMPPNode
37
- attribute_reader :foo
38
- end
39
- f = Foo.new
40
- f.must_respond_to :foo
41
- f.foo.must_be_nil
42
- f.attributes[:foo] = 'bar'
43
- f.foo.must_equal :bar
44
- end
45
-
46
- it 'provides an attribute_reader and not convert to syms' do
47
- class Foo < XMPPNode
48
- attribute_reader :foo, :to_sym => false
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
- class Foo < XMPPNode
59
- attribute_writer :foo
60
- end
61
- f = Foo.new
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
- class Foo < XMPPNode
69
- attribute_accessor :foo
70
- attribute_accessor :bar, :to_sym => false
71
- end
72
- f = Foo.new
73
- f.must_respond_to :foo
74
- f.foo.must_be_nil
75
- f.foo = 'bar'
76
- f.foo.must_equal :bar
77
-
78
- f.must_respond_to :bar
79
- f.bar.must_be_nil
80
- f.bar = 'baz'
81
- f.bar.must_equal 'baz'
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 Foo < XMPPNode; register 'foo'; end
86
- n = XMPPNode.new('foo')
87
- n.to_stanza.must_be_kind_of Foo
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.namespace.must_equal 'foo:bar'
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', 'bar'
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 'cuts line breaks out of #to_xml' do
164
- n = XMPPNode.new 'foo'
165
- n << XMPPNode.new('bar', 'baz')
166
- n.to_xml.scan(">\n<").size.must_equal 0
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 'overrides #find to find without xpath' do
170
- n = XMPPNode.new 'foo'
171
- n << XMPPNode.new('bar', 'baz')
172
- n.find(:bar).must_be_kind_of Array
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
- XML::Document.new.root = n
175
- n.find(:bar).must_be_kind_of XML::XPath::Object
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 'can find using a symbol' do
179
- n = XMPPNode.new 'foo'
180
- n << XMPPNode.new('bar', 'baz')
181
- n.find(:bar).first.to_s.must_equal "<bar>baz</bar>"
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