blather 0.4.7 → 0.4.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +162 -0
- data/examples/{print_heirarchy.rb → print_hierarchy.rb} +5 -5
- data/examples/stream_only.rb +27 -0
- data/lib/blather.rb +4 -0
- data/lib/blather/client/client.rb +91 -73
- data/lib/blather/client/dsl.rb +156 -32
- data/lib/blather/client/dsl/pubsub.rb +86 -54
- data/lib/blather/core_ext/active_support.rb +9 -9
- data/lib/blather/core_ext/active_support/inheritable_attributes.rb +2 -2
- data/lib/blather/core_ext/nokogiri.rb +12 -7
- data/lib/blather/errors.rb +25 -14
- data/lib/blather/errors/sasl_error.rb +21 -3
- data/lib/blather/errors/stanza_error.rb +37 -21
- data/lib/blather/errors/stream_error.rb +27 -17
- data/lib/blather/jid.rb +79 -24
- data/lib/blather/roster.rb +39 -21
- data/lib/blather/roster_item.rb +43 -21
- data/lib/blather/stanza.rb +88 -40
- data/lib/blather/stanza/disco.rb +12 -2
- data/lib/blather/stanza/disco/disco_info.rb +112 -20
- data/lib/blather/stanza/disco/disco_items.rb +81 -12
- data/lib/blather/stanza/iq.rb +94 -38
- data/lib/blather/stanza/iq/query.rb +16 -22
- data/lib/blather/stanza/iq/roster.rb +98 -20
- data/lib/blather/stanza/message.rb +266 -111
- data/lib/blather/stanza/presence.rb +118 -42
- data/lib/blather/stanza/presence/status.rb +140 -60
- data/lib/blather/stanza/presence/subscription.rb +44 -10
- data/lib/blather/stanza/pubsub.rb +70 -15
- data/lib/blather/stanza/pubsub/affiliations.rb +36 -7
- data/lib/blather/stanza/pubsub/create.rb +26 -4
- data/lib/blather/stanza/pubsub/errors.rb +13 -4
- data/lib/blather/stanza/pubsub/event.rb +56 -10
- data/lib/blather/stanza/pubsub/items.rb +46 -6
- data/lib/blather/stanza/pubsub/publish.rb +52 -7
- data/lib/blather/stanza/pubsub/retract.rb +45 -6
- data/lib/blather/stanza/pubsub/subscribe.rb +30 -4
- data/lib/blather/stanza/pubsub/subscription.rb +74 -6
- data/lib/blather/stanza/pubsub/subscriptions.rb +35 -9
- data/lib/blather/stanza/pubsub/unsubscribe.rb +30 -4
- data/lib/blather/stanza/pubsub_owner.rb +17 -7
- data/lib/blather/stanza/pubsub_owner/delete.rb +23 -5
- data/lib/blather/stanza/pubsub_owner/purge.rb +23 -5
- data/lib/blather/stream.rb +96 -29
- data/lib/blather/stream/parser.rb +6 -9
- data/lib/blather/xmpp_node.rb +101 -153
- data/spec/blather/client/client_spec.rb +1 -1
- data/spec/blather/errors_spec.rb +5 -5
- data/spec/blather/stanza/message_spec.rb +56 -0
- data/spec/blather/stanza/presence/status_spec.rb +1 -1
- data/spec/blather/stanza_spec.rb +3 -3
- data/spec/blather/xmpp_node_spec.rb +19 -74
- metadata +6 -10
- data/README.rdoc +0 -185
- data/examples/drb_client.rb +0 -5
- data/examples/ping.rb +0 -11
- data/examples/pong.rb +0 -6
- data/examples/pubsub/cli.rb +0 -64
- data/examples/pubsub/ping_pong.rb +0 -18
@@ -42,7 +42,6 @@ class Stream # :nodoc:
|
|
42
42
|
@current = node
|
43
43
|
end
|
44
44
|
|
45
|
-
|
46
45
|
ns_keys = namespaces.map { |pre, href| pre }
|
47
46
|
namespaces.delete_if { |pre, href| NS_TO_IGNORE.include? href }
|
48
47
|
@namespace_definitions.push []
|
@@ -56,14 +55,12 @@ class Stream # :nodoc:
|
|
56
55
|
|
57
56
|
deliver(node) if elem == 'stream'
|
58
57
|
|
59
|
-
|
60
|
-
$stderr.puts
|
61
|
-
$stderr.puts
|
62
|
-
$stderr.puts @namespaces.inspect
|
63
|
-
$stderr.puts
|
64
|
-
$stderr.puts node.
|
65
|
-
$stderr.puts node.document.to_s.gsub(/\n\s*/,'')
|
66
|
-
=end
|
58
|
+
# $stderr.puts "\n\n"
|
59
|
+
# $stderr.puts [elem, attrs, prefix, uri, namespaces].inspect
|
60
|
+
# $stderr.puts @namespaces.inspect
|
61
|
+
# $stderr.puts [@namespaces[[prefix, uri]].prefix, @namespaces[[prefix, uri]].href].inspect if @namespaces[[prefix, uri]]
|
62
|
+
# $stderr.puts node.inspect
|
63
|
+
# $stderr.puts node.document.to_s.gsub(/\n\s*/,'')
|
67
64
|
end
|
68
65
|
|
69
66
|
def end_element_namespace(elem, prefix, uri)
|
data/lib/blather/xmpp_node.rb
CHANGED
@@ -1,42 +1,50 @@
|
|
1
1
|
module Blather
|
2
2
|
|
3
|
-
##
|
4
3
|
# Base XML Node
|
5
|
-
# All XML classes subclass XMPPNode
|
6
|
-
# it allows the addition of helpers
|
4
|
+
# All XML classes subclass XMPPNode it allows the addition of helpers
|
7
5
|
class XMPPNode < Nokogiri::XML::Node
|
6
|
+
# @private
|
8
7
|
BASE_NAMES = %w[presence message iq].freeze
|
9
8
|
|
9
|
+
# @private
|
10
10
|
@@registrations = {}
|
11
11
|
|
12
12
|
class_inheritable_accessor :registered_ns,
|
13
13
|
:registered_name
|
14
14
|
|
15
|
-
|
16
|
-
# Lets a subclass register itself
|
15
|
+
# Register a new stanza class to a name and/or namespace
|
17
16
|
#
|
18
17
|
# This registers a namespace that is used when looking
|
19
18
|
# up the class name of the object to instantiate when a new
|
20
19
|
# stanza is received
|
20
|
+
#
|
21
|
+
# @param [#to_s] name the name of the node
|
22
|
+
# @param [String, nil] ns the namespace the node belongs to
|
21
23
|
def self.register(name, ns = nil)
|
22
24
|
self.registered_name = name.to_s
|
23
25
|
self.registered_ns = ns
|
24
26
|
@@registrations[[self.registered_name, self.registered_ns]] = self
|
25
27
|
end
|
26
28
|
|
27
|
-
##
|
28
29
|
# Find the class to use given the name and namespace of a stanza
|
29
|
-
|
30
|
+
#
|
31
|
+
# @param [#to_s] name the name to lookup
|
32
|
+
# @param [String, nil] xmlns the namespace the node belongs to
|
33
|
+
# @return [Class, nil] the class appropriate for the name/ns combination
|
34
|
+
def self.class_from_registration(name, ns = nil)
|
30
35
|
name = name.to_s
|
31
|
-
@@registrations[[name,
|
36
|
+
@@registrations[[name, ns]] || @@registrations[[name, nil]]
|
32
37
|
end
|
33
38
|
|
34
|
-
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
39
|
+
# Import an XML::Node to the appropriate class
|
40
|
+
#
|
41
|
+
# Looks up the class the node should be then creates it based on the
|
42
|
+
# elements of the XML::Node
|
43
|
+
# @param [XML::Node] node the node to import
|
44
|
+
# @return the appropriate object based on the node name and namespace
|
38
45
|
def self.import(node)
|
39
|
-
|
46
|
+
ns = (node.namespace.href if node.namespace)
|
47
|
+
klass = class_from_registration(node.element_name, ns)
|
40
48
|
if klass && klass != self
|
41
49
|
klass.import(node)
|
42
50
|
else
|
@@ -44,151 +52,71 @@ module Blather
|
|
44
52
|
end
|
45
53
|
end
|
46
54
|
|
47
|
-
|
48
|
-
# Provides an attribute reader helper. Default behavior is to
|
49
|
-
# conver the values of the attribute into a symbol. This can
|
50
|
-
# be turned off by passing <tt>:to_sym => false</tt>
|
55
|
+
# Create a new Node object
|
51
56
|
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
|
57
|
-
|
58
|
-
# n[:type] = 'foo'
|
59
|
-
# n.type == :foo
|
60
|
-
# n[:name] = 'bar'
|
61
|
-
# n.name == 'bar'
|
62
|
-
def self.attribute_reader(*syms)
|
63
|
-
opts = syms.last.is_a?(Hash) ? syms.pop : {}
|
64
|
-
convert_str = "val.#{opts[:call]} if val" if opts[:call]
|
65
|
-
syms.flatten.each do |sym|
|
66
|
-
class_eval(<<-END, __FILE__, __LINE__)
|
67
|
-
def #{sym}
|
68
|
-
val = self[:#{sym}]
|
69
|
-
#{convert_str}
|
70
|
-
end
|
71
|
-
END
|
72
|
-
end
|
73
|
-
end
|
57
|
+
# @param [String, nil] name the element name
|
58
|
+
# @param [XML::Document, nil] doc the document to attach the node to. If
|
59
|
+
# not provided one will be created
|
60
|
+
# @return a new object with the registered name and namespace
|
61
|
+
def self.new(name = nil, doc = nil)
|
62
|
+
name ||= self.registered_name
|
74
63
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
# attribute_writer :type
|
80
|
-
# end
|
81
|
-
#
|
82
|
-
# n = Node.new
|
83
|
-
# n.type = 'foo'
|
84
|
-
# n[:type] == 'foo'
|
85
|
-
def self.attribute_writer(*syms)
|
86
|
-
syms.flatten.each do |sym|
|
87
|
-
next if sym.is_a?(Hash)
|
88
|
-
class_eval(<<-END, __FILE__, __LINE__)
|
89
|
-
def #{sym}=(value)
|
90
|
-
self[:#{sym}] = value
|
91
|
-
end
|
92
|
-
END
|
93
|
-
end
|
64
|
+
node = super name.to_s, (doc || Nokogiri::XML::Document.new)
|
65
|
+
node.document.root = node unless doc
|
66
|
+
node.namespace = self.registered_ns unless BASE_NAMES.include?(name.to_s)
|
67
|
+
node
|
94
68
|
end
|
95
69
|
|
96
|
-
|
97
|
-
# Provides an attribute accessor helper combining
|
98
|
-
# <tt>attribute_reader</tt> and <tt>attribute_writer</tt>
|
99
|
-
#
|
100
|
-
# class Node
|
101
|
-
# attribute_accessor :type
|
102
|
-
# attribute_accessor :name, :to_sym => false
|
103
|
-
# end
|
70
|
+
# Helper method to read an attribute
|
104
71
|
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
attribute_writer *syms
|
72
|
+
# @param [#to_sym] attr_name the name of the attribute
|
73
|
+
# @param [String, Symbol, nil] to_call the name of the method to call on
|
74
|
+
# the returned value
|
75
|
+
# @return nil or the value
|
76
|
+
def read_attr(attr_name, to_call = nil)
|
77
|
+
val = self[attr_name.to_sym]
|
78
|
+
val && to_call ? val.__send__(to_call) : val
|
113
79
|
end
|
114
80
|
|
115
|
-
|
116
|
-
# Provides a content reader helper that returns the content of a node
|
117
|
-
# +method+ is the method to create
|
118
|
-
# +conversion+ is a method to call on the content before sending it back
|
119
|
-
# +node+ is the name of the content node (this defaults to the method name)
|
81
|
+
# Helper method to write a value to an attribute
|
120
82
|
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
|
124
|
-
|
125
|
-
# end
|
126
|
-
#
|
127
|
-
# n = Node.new 'foo'
|
128
|
-
# n.to_s == "<foo><body>foobarbaz</body><type>error</type><identity>1000</identity></foo>"
|
129
|
-
# n.body == 'foobarbaz'
|
130
|
-
# n.type == :error
|
131
|
-
# n.id == 1000
|
132
|
-
def self.content_attr_reader(method, conversion = nil, node = nil)
|
133
|
-
node ||= method
|
134
|
-
conversion = "val.#{conversion} if val.respond_to?(:#{conversion})" if conversion
|
135
|
-
class_eval(<<-END, __FILE__, __LINE__)
|
136
|
-
def #{method}
|
137
|
-
val = content_from :#{node}
|
138
|
-
#{conversion}
|
139
|
-
end
|
140
|
-
END
|
83
|
+
# @param [#to_sym] attr_name the name of the attribute
|
84
|
+
# @param [#to_s] value the value to set the attribute to
|
85
|
+
def write_attr(attr_name, value)
|
86
|
+
self[attr_name.to_sym] = value
|
141
87
|
end
|
142
88
|
|
143
|
-
|
144
|
-
# Provides a content writer helper that creates or updates the content of a node
|
145
|
-
# +method+ is the method to create
|
146
|
-
# +node+ is the name of the node to create (defaults to the method name)
|
147
|
-
#
|
148
|
-
# class Node
|
149
|
-
# content_attr_writer :body
|
150
|
-
# content_attr_writer :id, :identity
|
151
|
-
# end
|
89
|
+
# Helper method to read the content of a node
|
152
90
|
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
def
|
158
|
-
|
159
|
-
|
160
|
-
def #{method}=(val)
|
161
|
-
set_content_for :#{node}, val
|
162
|
-
end
|
163
|
-
END
|
164
|
-
end
|
165
|
-
|
166
|
-
##
|
167
|
-
# Provides a quick way of building +content_attr_reader+ and +content_attr_writer+
|
168
|
-
# for the same method and node
|
169
|
-
def self.content_attr_accessor(method, conversion = nil, node = nil)
|
170
|
-
content_attr_reader method, conversion, node
|
171
|
-
content_attr_writer method, node
|
91
|
+
# @param [#to_sym] node the name of the node
|
92
|
+
# @param [String, Symbol, nil] to_call the name of the method to call on
|
93
|
+
# the returned value
|
94
|
+
# @return nil or the value
|
95
|
+
def read_content(node, to_call = nil)
|
96
|
+
val = content_from node.to_sym
|
97
|
+
val && to_call ? val.__send__(to_call) : val
|
172
98
|
end
|
173
99
|
|
174
|
-
|
175
|
-
#
|
176
|
-
|
177
|
-
name ||= self.registered_name
|
178
|
-
|
179
|
-
node = super name.to_s, (doc || Nokogiri::XML::Document.new)
|
180
|
-
node.document.root = node unless doc
|
181
|
-
node.namespace = self.registered_ns unless BASE_NAMES.include?(name.to_s)
|
182
|
-
node
|
183
|
-
end
|
184
|
-
|
185
|
-
##
|
186
|
-
# Quickway of turning itself into a proper object
|
100
|
+
# Turn the object into a proper stanza
|
101
|
+
#
|
102
|
+
# @return a stanza object
|
187
103
|
def to_stanza
|
188
104
|
self.class.import self
|
189
105
|
end
|
190
106
|
|
107
|
+
# @private
|
191
108
|
alias_method :nokogiri_namespace=, :namespace=
|
109
|
+
# Attach a namespace to the node
|
110
|
+
#
|
111
|
+
# @overload namespace=(ns)
|
112
|
+
# Attach an already created XML::Namespace
|
113
|
+
# @param [XML::Namespace] ns the namespace object
|
114
|
+
# @overload namespace=(ns)
|
115
|
+
# Create a new namespace and attach it
|
116
|
+
# @param [String] ns the namespace uri
|
117
|
+
# @overload namespace=(namespaces)
|
118
|
+
# Createa and add new namespaces from a hash
|
119
|
+
# @param [Hash] namespaces a hash of prefix => uri pairs
|
192
120
|
def namespace=(namespaces)
|
193
121
|
case namespaces
|
194
122
|
when Nokogiri::XML::Namespace
|
@@ -206,34 +134,46 @@ module Blather
|
|
206
134
|
end
|
207
135
|
end
|
208
136
|
|
137
|
+
# Helper method to get the node's namespace
|
138
|
+
#
|
139
|
+
# @return [XML::Namespace, nil] The node's namespace object if it exists
|
209
140
|
def namespace_href
|
210
141
|
namespace.href if namespace
|
211
142
|
end
|
212
143
|
|
213
|
-
##
|
214
144
|
# Remove a child with the name and (optionally) namespace given
|
145
|
+
#
|
146
|
+
# @param [String] name the name or xpath of the node to remove
|
147
|
+
# @param [String, nil] ns the namespace the node is in
|
215
148
|
def remove_child(name, ns = nil)
|
216
149
|
child = xpath(name, ns).first
|
217
150
|
child.remove if child
|
218
151
|
end
|
219
152
|
|
220
|
-
|
221
|
-
#
|
153
|
+
# Remove all children with a given name regardless of namespace
|
154
|
+
#
|
155
|
+
# @param [String] name the name of the nodes to remove
|
222
156
|
def remove_children(name)
|
223
157
|
xpath("./*[local-name()='#{name}']").remove
|
224
158
|
end
|
225
159
|
|
226
|
-
|
227
|
-
#
|
160
|
+
# The content of the named node
|
161
|
+
#
|
162
|
+
# @param [String] name the name or xpath of the node
|
163
|
+
# @param [String, nil] ns the namespace the node is in
|
164
|
+
# @return [String, nil] the content of the node
|
228
165
|
def content_from(name, ns = nil)
|
229
166
|
child = xpath(name, ns).first
|
230
167
|
child.content if child
|
231
168
|
end
|
232
169
|
|
233
|
-
##
|
234
170
|
# Sets the content for the specified node.
|
235
171
|
# If the node exists it is updated. If not a new node is created
|
236
|
-
# If the node exists and the content is nil, the node will be removed
|
172
|
+
# If the node exists and the content is nil, the node will be removed
|
173
|
+
# entirely
|
174
|
+
#
|
175
|
+
# @param [String] node the name of the node to update/create
|
176
|
+
# @param [String, nil] content the content to set within the node
|
237
177
|
def set_content_for(node, content = nil)
|
238
178
|
if content
|
239
179
|
child = xpath(node).first
|
@@ -246,8 +186,10 @@ module Blather
|
|
246
186
|
|
247
187
|
alias_method :copy, :dup
|
248
188
|
|
249
|
-
|
250
|
-
#
|
189
|
+
# Inherit the attributes and children of an XML::Node
|
190
|
+
#
|
191
|
+
# @param [XML::Node] stanza the node to inherit
|
192
|
+
# @return [self]
|
251
193
|
def inherit(stanza)
|
252
194
|
set_namespace stanza.namespace if stanza.namespace
|
253
195
|
inherit_attrs stanza.attributes
|
@@ -259,12 +201,18 @@ module Blather
|
|
259
201
|
self
|
260
202
|
end
|
261
203
|
|
262
|
-
|
263
|
-
#
|
204
|
+
# Inherit a set of attributes
|
205
|
+
#
|
206
|
+
# @param [Hash] attrs a hash of attributes to set on the node
|
207
|
+
# @return [self]
|
264
208
|
def inherit_attrs(attrs)
|
265
209
|
attrs.each { |name, value| self[name] = value }
|
266
210
|
self
|
267
211
|
end
|
268
|
-
end #XMPPNode
|
269
212
|
|
270
|
-
|
213
|
+
def inspect
|
214
|
+
self.to_xml
|
215
|
+
end
|
216
|
+
end # XMPPNode
|
217
|
+
|
218
|
+
end # Blather
|
@@ -164,7 +164,7 @@ describe Blather::Client do
|
|
164
164
|
@client.receive_data stanza
|
165
165
|
end
|
166
166
|
|
167
|
-
it 'allows for passing to the next handler in the
|
167
|
+
it 'allows for passing to the next handler in the hierarchy' do
|
168
168
|
stanza = Blather::Stanza::Iq::Query.new
|
169
169
|
response = mock(:query => nil, :iq => nil)
|
170
170
|
@client.register_handler(:query) do |_|
|
data/spec/blather/errors_spec.rb
CHANGED
@@ -2,15 +2,15 @@ require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
|
|
2
2
|
|
3
3
|
describe Blather::BlatherError do
|
4
4
|
it 'is handled by :error' do
|
5
|
-
Blather::BlatherError.new.
|
5
|
+
Blather::BlatherError.new.handler_hierarchy.must_equal [:error]
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
describe 'Blather::ParseError' do
|
10
10
|
before { @error = Blather::ParseError.new('</generate-parse-error>"') }
|
11
11
|
|
12
|
-
it 'is registers with the handler
|
13
|
-
@error.
|
12
|
+
it 'is registers with the handler hierarchy' do
|
13
|
+
@error.handler_hierarchy.must_equal [:parse_error, :error]
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'contains the error message' do
|
@@ -22,8 +22,8 @@ end
|
|
22
22
|
describe 'Blather::UnknownResponse' do
|
23
23
|
before { @error = Blather::UnknownResponse.new(Blather::XMPPNode.new('foo-bar')) }
|
24
24
|
|
25
|
-
it 'is registers with the handler
|
26
|
-
@error.
|
25
|
+
it 'is registers with the handler hierarchy' do
|
26
|
+
@error.handler_hierarchy.must_equal [:unknown_response_error, :error]
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'holds on to a copy of the failure node' do
|
@@ -73,4 +73,60 @@ describe Blather::Stanza::Message do
|
|
73
73
|
Blather::Stanza::Message.new.must_respond_to :"#{valid_type}?"
|
74
74
|
end
|
75
75
|
end
|
76
|
+
|
77
|
+
it 'ensures an html node exists when asked for xhtml_node' do
|
78
|
+
search_args = [
|
79
|
+
'/message/html_ns:html',
|
80
|
+
{:html_ns => Blather::Stanza::Message::HTML_NS}
|
81
|
+
]
|
82
|
+
msg = Blather::Stanza::Message.new
|
83
|
+
msg.find_first(*search_args).must_be_nil
|
84
|
+
|
85
|
+
msg.xhtml_node
|
86
|
+
msg.find_first(*search_args).wont_be_nil
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'ensures a body node exists when asked for xhtml_node' do
|
90
|
+
search_args = [
|
91
|
+
'/message/html_ns:html/body_ns:body',
|
92
|
+
{:html_ns => Blather::Stanza::Message::HTML_NS,
|
93
|
+
:body_ns => Blather::Stanza::Message::HTML_BODY_NS}
|
94
|
+
]
|
95
|
+
msg = Blather::Stanza::Message.new
|
96
|
+
msg.find_first(*search_args).must_be_nil
|
97
|
+
|
98
|
+
msg.xhtml_node
|
99
|
+
msg.find_first(*search_args).wont_be_nil
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns an existing node when asked for xhtml_node' do
|
103
|
+
msg = Blather::Stanza::Message.new
|
104
|
+
msg << (h = Blather::XMPPNode.new('html', msg.document))
|
105
|
+
h.namespace = Blather::Stanza::Message::HTML_NS
|
106
|
+
h << (b = Blather::XMPPNode.new('body', msg.document))
|
107
|
+
b.namespace = Blather::Stanza::Message::HTML_BODY_NS
|
108
|
+
|
109
|
+
msg.xhtml_node.must_equal(b)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'has an xhtml setter' do
|
113
|
+
msg = Blather::Stanza::Message.new
|
114
|
+
xhtml = "<some>xhtml</some>"
|
115
|
+
msg.xhtml = xhtml
|
116
|
+
msg.xhtml_node.content.strip.must_equal(xhtml)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'sets valid xhtml even if the input is not valid' do
|
120
|
+
msg = Blather::Stanza::Message.new
|
121
|
+
xhtml = "<some>xhtml"
|
122
|
+
msg.xhtml = xhtml
|
123
|
+
msg.xhtml_node.content.strip.must_equal("<some>xhtml</some>")
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'has an xhtml getter' do
|
127
|
+
msg = Blather::Stanza::Message.new
|
128
|
+
xhtml = "<some>xhtml</some>"
|
129
|
+
msg.xhtml = xhtml
|
130
|
+
msg.xhtml.must_equal(xhtml)
|
131
|
+
end
|
76
132
|
end
|