blather 0.4.13 → 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 CHANGED
@@ -169,6 +169,7 @@ than a change set made directly on master.
169
169
  * [Nolan Darilek](http://github.com/thewordnerd)
170
170
  * [Tim Carey-Smith](http://github.com/halorgium)
171
171
  * [Ben Langfeld](http://github.com/benlangfeld)
172
+ * [Anton Mironov](http://github.com/mironov)
172
173
 
173
174
  # Copyright
174
175
 
@@ -90,8 +90,8 @@ module Blather
90
90
  #
91
91
  # @return [Hash<group => Array<RosterItem>>]
92
92
  def grouped
93
- self.inject(Hash.new{|h,k|h[k]=[]}) do |hash, item|
94
- item[1].groups.each { |group| hash[group] << item[1] }
93
+ @items.values.sort.inject(Hash.new{|h,k|h[k]=[]}) do |hash, item|
94
+ item.groups.each { |group| hash[group] << item }
95
95
  hash
96
96
  end
97
97
  end
@@ -108,4 +108,4 @@ module Blather
108
108
  end
109
109
  end # Roster
110
110
 
111
- end # Blather
111
+ end # Blather
@@ -117,6 +117,17 @@ module Blather
117
117
  n.groups = groups
118
118
  r
119
119
  end
120
+
121
+ def <=>(o)
122
+ self.jid.to_s <=> o.jid.to_s
123
+ end
124
+
125
+ def eql?(o)
126
+ o.is_a?(RosterItem) &&
127
+ o.jid == self.jid &&
128
+ o.groups == self.groups
129
+ end
130
+ alias_method :==, :eql?
120
131
  end #RosterItem
121
132
 
122
- end
133
+ end
@@ -159,6 +159,9 @@ class Stanza
159
159
  class Message < Stanza
160
160
  VALID_TYPES = [:chat, :error, :groupchat, :headline, :normal].freeze
161
161
 
162
+ VALID_CHAT_STATES = [:active, :composing, :gone, :inactive, :paused].freeze
163
+ CHAT_STATE_NS = 'http://jabber.org/protocol/chatstates'.freeze
164
+
162
165
  HTML_NS = 'http://jabber.org/protocol/xhtml-im'.freeze
163
166
  HTML_BODY_NS = 'http://www.w3.org/1999/xhtml'.freeze
164
167
 
@@ -189,6 +192,7 @@ class Stanza
189
192
  node.to = to
190
193
  node.type = type
191
194
  node.body = body
195
+ node.chat_state = :active if [:chat, :groupchat].include?(type)
192
196
  node
193
197
  end
194
198
 
@@ -262,8 +266,9 @@ class Stanza
262
266
  end
263
267
 
264
268
  unless b = h.find_first('ns:body', :ns => HTML_BODY_NS)
265
- h << (b = XMPPNode.new('body', self.document))
269
+ b = XMPPNode.new('body', self.document)
266
270
  b.namespace = HTML_BODY_NS
271
+ h << b
267
272
  end
268
273
 
269
274
  b
@@ -273,7 +278,7 @@ class Stanza
273
278
  #
274
279
  # @return [String]
275
280
  def xhtml
276
- self.xhtml_node.content.strip
281
+ self.xhtml_node.inner_html.strip
277
282
  end
278
283
 
279
284
  # Set the message xhtml
@@ -281,7 +286,7 @@ class Stanza
281
286
  #
282
287
  # @param [#to_s] valid xhtml
283
288
  def xhtml=(xhtml_body)
284
- self.xhtml_node.content = Nokogiri::XML(xhtml_body).to_xhtml
289
+ self.xhtml_node.inner_html = Nokogiri::XML::DocumentFragment.parse(xhtml_body)
285
290
  end
286
291
 
287
292
  # Get the message subject
@@ -331,6 +336,32 @@ class Stanza
331
336
  def form
332
337
  X.find_or_create self
333
338
  end
339
+
340
+ # Get the message chat state
341
+ #
342
+ # @return [Symbol]
343
+ def chat_state
344
+ if (elem = find_first('ns:*', :ns => CHAT_STATE_NS)) && VALID_CHAT_STATES.include?(name = elem.name.to_sym)
345
+ name
346
+ end
347
+ end
348
+
349
+ # Set the message chat state
350
+ #
351
+ # @param [#to_s] chat_state the message chat state. Must be one of VALID_CHAT_STATES
352
+ def chat_state=(chat_state)
353
+ if chat_state && !VALID_CHAT_STATES.include?(chat_state.to_sym)
354
+ raise ArgumentError, "Invalid Chat State (#{chat_state}), use: #{VALID_CHAT_STATES*' '}"
355
+ end
356
+
357
+ xpath('ns:*', :ns => CHAT_STATE_NS).remove
358
+
359
+ if chat_state
360
+ state = XMPPNode.new(chat_state, self.document)
361
+ state.namespace = CHAT_STATE_NS
362
+ self << state
363
+ end
364
+ end
334
365
  end
335
366
 
336
367
  end
@@ -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
- Blather.logger.debug "SENDING: (#{caller[1]}) #{stanza}"
117
- send_data stanza.respond_to?(:to_xml) ? stanza.to_xml : stanza.to_s
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
@@ -37,11 +37,6 @@ class Stream # :nodoc:
37
37
  node[attr.localname] = attr.value
38
38
  end
39
39
 
40
- if !@receiver.stopped?
41
- @current << node if @current
42
- @current = node
43
- end
44
-
45
40
  ns_keys = namespaces.map { |pre, href| pre }
46
41
  namespaces.delete_if { |pre, href| NS_TO_IGNORE.include? href }
47
42
  @namespace_definitions.push []
@@ -53,6 +48,11 @@ class Stream # :nodoc:
53
48
  @namespaces[[prefix, uri]] ||= node.add_namespace(prefix, uri) if prefix && !ns_keys.include?(prefix)
54
49
  node.namespace = @namespaces[[prefix, uri]]
55
50
 
51
+ if !@receiver.stopped?
52
+ @current << node if @current
53
+ @current = node
54
+ end
55
+
56
56
  deliver(node) if elem == 'stream'
57
57
 
58
58
  # $stderr.puts "\n\n"
@@ -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]] || @@registrations[[name, nil]]
36
+ @@registrations[[name, ns]]
37
37
  end
38
38
 
39
39
  # Import an XML::Node to the appropriate class
@@ -93,4 +93,12 @@ describe Blather::RosterItem do
93
93
  i = Blather::RosterItem.new 'n@d'
94
94
  i.groups.must_equal [nil]
95
95
  end
96
+
97
+ it 'can determine equality' do
98
+ item1 = Blather::RosterItem.new 'n@d'
99
+ item2 = Blather::RosterItem.new 'n@d'
100
+ item1.groups = %w[group1 group2]
101
+ item2.groups = %w[group1 group2]
102
+ (item1 == item2).must_equal true
103
+ end
96
104
  end
@@ -109,8 +109,9 @@ describe Blather::Stanza::Message do
109
109
  msg = Blather::Stanza::Message.new
110
110
  msg << (h = Blather::XMPPNode.new('html', msg.document))
111
111
  h.namespace = Blather::Stanza::Message::HTML_NS
112
- h << (b = Blather::XMPPNode.new('body', msg.document))
112
+ b = Blather::XMPPNode.new('body', msg.document)
113
113
  b.namespace = Blather::Stanza::Message::HTML_BODY_NS
114
+ h << b
114
115
 
115
116
  msg.xhtml_node.must_equal(b)
116
117
  end
@@ -119,14 +120,21 @@ describe Blather::Stanza::Message do
119
120
  msg = Blather::Stanza::Message.new
120
121
  xhtml = "<some>xhtml</some>"
121
122
  msg.xhtml = xhtml
122
- msg.xhtml_node.content.strip.must_equal(xhtml)
123
+ msg.xhtml_node.inner_html.strip.must_equal(xhtml)
123
124
  end
124
125
 
125
126
  it 'sets valid xhtml even if the input is not valid' do
126
127
  msg = Blather::Stanza::Message.new
127
128
  xhtml = "<some>xhtml"
128
129
  msg.xhtml = xhtml
129
- msg.xhtml_node.content.strip.must_equal("<some>xhtml</some>")
130
+ msg.xhtml_node.inner_html.strip.must_equal("<some>xhtml</some>")
131
+ end
132
+
133
+ it 'sets xhtml with more than one root node' do
134
+ msg = Blather::Stanza::Message.new
135
+ xhtml = "<i>xhtml</i> more xhtml"
136
+ msg.xhtml = xhtml
137
+ msg.xhtml_node.inner_html.strip.must_equal("<i>xhtml</i> more xhtml")
130
138
  end
131
139
 
132
140
  it 'has an xhtml getter' do
@@ -136,6 +144,45 @@ describe Blather::Stanza::Message do
136
144
  msg.xhtml.must_equal(xhtml)
137
145
  end
138
146
 
147
+ it 'has a chat state setter' do
148
+ msg = Blather::Stanza::Message.new
149
+ msg.chat_state = :composing
150
+ msg.xpath('ns:composing', :ns => Blather::Stanza::Message::CHAT_STATE_NS).wont_be_empty
151
+ end
152
+
153
+ it 'will only add one chat state at a time' do
154
+ msg = Blather::Stanza::Message.new
155
+ msg.chat_state = :composing
156
+ msg.chat_state = :paused
157
+
158
+ msg.xpath('ns:*', :ns => Blather::Stanza::Message::CHAT_STATE_NS).size.must_equal(1)
159
+ end
160
+
161
+ it 'ensures chat state setter accepts strings' do
162
+ msg = Blather::Stanza::Message.new
163
+ msg.chat_state = "gone"
164
+ msg.xpath('ns:gone', :ns => Blather::Stanza::Message::CHAT_STATE_NS).wont_be_empty
165
+ end
166
+
167
+ it 'ensures chat state is one of Blather::Stanza::Message::VALID_CHAT_STATES' do
168
+ lambda do
169
+ msg = Blather::Stanza::Message.new
170
+ msg.chat_state = :invalid_chat_state
171
+ end.must_raise(Blather::ArgumentError)
172
+
173
+ Blather::Stanza::Message::VALID_CHAT_STATES.each do |valid_chat_state|
174
+ msg = Blather::Stanza::Message.new
175
+ msg.chat_state = valid_chat_state
176
+ msg.chat_state.must_equal valid_chat_state
177
+ end
178
+ end
179
+
180
+ it 'has a chat state getter' do
181
+ msg = Blather::Stanza::Message.new
182
+ msg.chat_state = :paused
183
+ msg.chat_state.must_equal(:paused)
184
+ end
185
+
139
186
  it 'makes a form child available' do
140
187
  n = Blather::XMPPNode.import(parse_stanza(message_xml).root)
141
188
  n.form.fields.size.must_equal 1
@@ -1008,4 +1008,17 @@ describe Blather::Stream::Client do
1008
1008
  comp.expects(:send_data).with { |s| s.wont_match(/^<message[^>]*from=/); true }
1009
1009
  comp.send msg
1010
1010
  end
1011
+
1012
+ it 'sends xml without formatting' do
1013
+ client = mock()
1014
+ client.stubs(:jid)
1015
+ client.stubs(:jid=)
1016
+
1017
+ msg = Blather::Stanza::Message.new 'to@jid.com', 'body'
1018
+ msg.xhtml = '<i>xhtml</i> body'
1019
+
1020
+ comp = Blather::Stream::Client.new nil, client, 'node@jid.com/resource', 'pass'
1021
+ comp.expects(:send_data).with { |s| s.wont_match(/\n/); true }
1022
+ comp.send msg
1023
+ end
1011
1024
  end
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), *%w[.. lib]))
3
3
 
4
4
  require 'blather'
5
5
  require 'rubygems'
6
+ gem 'minitest', '>=1.7.1'
6
7
  require 'minitest/spec'
7
8
  require 'mocha'
8
9
  require 'mocha/expectation_error'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blather
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
- - 13
10
- version: 0.4.13
9
+ - 14
10
+ version: 0.4.14
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jeff Smick
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-10 00:00:00 -07:00
18
+ date: 2010-09-02 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -50,6 +50,22 @@ dependencies:
50
50
  version: 1.4.0
51
51
  type: :runtime
52
52
  version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: minitest
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 9
62
+ segments:
63
+ - 1
64
+ - 7
65
+ - 1
66
+ version: 1.7.1
67
+ type: :development
68
+ version_requirements: *id003
53
69
  description: An XMPP DSL for Ruby written on top of EventMachine and Nokogiri
54
70
  email: sprsquish@gmail.com
55
71
  executables: []
@@ -122,49 +138,6 @@ files:
122
138
  - lib/blather/xmpp_node.rb
123
139
  - LICENSE
124
140
  - README.md
125
- - spec/blather/client/client_spec.rb
126
- - spec/blather/client/dsl/pubsub_spec.rb
127
- - spec/blather/client/dsl_spec.rb
128
- - spec/blather/core_ext/nokogiri_spec.rb
129
- - spec/blather/errors/sasl_error_spec.rb
130
- - spec/blather/errors/stanza_error_spec.rb
131
- - spec/blather/errors/stream_error_spec.rb
132
- - spec/blather/errors_spec.rb
133
- - spec/blather/jid_spec.rb
134
- - spec/blather/roster_item_spec.rb
135
- - spec/blather/roster_spec.rb
136
- - spec/blather/stanza/discos/disco_info_spec.rb
137
- - spec/blather/stanza/discos/disco_items_spec.rb
138
- - spec/blather/stanza/iq/command_spec.rb
139
- - spec/blather/stanza/iq/query_spec.rb
140
- - spec/blather/stanza/iq/roster_spec.rb
141
- - spec/blather/stanza/iq_spec.rb
142
- - spec/blather/stanza/message_spec.rb
143
- - spec/blather/stanza/presence/status_spec.rb
144
- - spec/blather/stanza/presence/subscription_spec.rb
145
- - spec/blather/stanza/presence_spec.rb
146
- - spec/blather/stanza/pubsub/affiliations_spec.rb
147
- - spec/blather/stanza/pubsub/create_spec.rb
148
- - spec/blather/stanza/pubsub/event_spec.rb
149
- - spec/blather/stanza/pubsub/items_spec.rb
150
- - spec/blather/stanza/pubsub/publish_spec.rb
151
- - spec/blather/stanza/pubsub/retract_spec.rb
152
- - spec/blather/stanza/pubsub/subscribe_spec.rb
153
- - spec/blather/stanza/pubsub/subscription_spec.rb
154
- - spec/blather/stanza/pubsub/subscriptions_spec.rb
155
- - spec/blather/stanza/pubsub/unsubscribe_spec.rb
156
- - spec/blather/stanza/pubsub_owner/delete_spec.rb
157
- - spec/blather/stanza/pubsub_owner/purge_spec.rb
158
- - spec/blather/stanza/pubsub_owner_spec.rb
159
- - spec/blather/stanza/pubsub_spec.rb
160
- - spec/blather/stanza/x_spec.rb
161
- - spec/blather/stanza_spec.rb
162
- - spec/blather/stream/client_spec.rb
163
- - spec/blather/stream/component_spec.rb
164
- - spec/blather/stream/parser_spec.rb
165
- - spec/blather/xmpp_node_spec.rb
166
- - spec/fixtures/pubsub.rb
167
- - spec/spec_helper.rb
168
141
  has_rdoc: true
169
142
  homepage: http://github.com/sprsquish/blather
170
143
  licenses: []
@@ -195,32 +168,41 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
168
  requirements: []
196
169
 
197
170
  rubyforge_project: squishtech
198
- rubygems_version: 1.3.7
171
+ rubygems_version: 1.3.6
199
172
  signing_key:
200
173
  specification_version: 3
201
174
  summary: Simpler XMPP built for speed
202
175
  test_files:
176
+ - spec/spec_helper.rb
177
+ - spec/blather/errors_spec.rb
178
+ - spec/blather/jid_spec.rb
179
+ - spec/blather/roster_item_spec.rb
180
+ - spec/blather/roster_spec.rb
181
+ - spec/blather/stanza_spec.rb
182
+ - spec/blather/xmpp_node_spec.rb
183
+ - spec/fixtures/pubsub.rb
203
184
  - spec/blather/client/client_spec.rb
204
- - spec/blather/client/dsl/pubsub_spec.rb
205
185
  - spec/blather/client/dsl_spec.rb
206
186
  - spec/blather/core_ext/nokogiri_spec.rb
207
187
  - spec/blather/errors/sasl_error_spec.rb
208
188
  - spec/blather/errors/stanza_error_spec.rb
209
189
  - spec/blather/errors/stream_error_spec.rb
210
- - spec/blather/errors_spec.rb
211
- - spec/blather/jid_spec.rb
212
- - spec/blather/roster_item_spec.rb
213
- - spec/blather/roster_spec.rb
190
+ - spec/blather/stanza/iq_spec.rb
191
+ - spec/blather/stanza/message_spec.rb
192
+ - spec/blather/stanza/presence_spec.rb
193
+ - spec/blather/stanza/pubsub_owner_spec.rb
194
+ - spec/blather/stanza/pubsub_spec.rb
195
+ - spec/blather/stanza/x_spec.rb
196
+ - spec/blather/stream/client_spec.rb
197
+ - spec/blather/stream/component_spec.rb
198
+ - spec/blather/stream/parser_spec.rb
214
199
  - spec/blather/stanza/discos/disco_info_spec.rb
215
200
  - spec/blather/stanza/discos/disco_items_spec.rb
216
201
  - spec/blather/stanza/iq/command_spec.rb
217
202
  - spec/blather/stanza/iq/query_spec.rb
218
203
  - spec/blather/stanza/iq/roster_spec.rb
219
- - spec/blather/stanza/iq_spec.rb
220
- - spec/blather/stanza/message_spec.rb
221
204
  - spec/blather/stanza/presence/status_spec.rb
222
205
  - spec/blather/stanza/presence/subscription_spec.rb
223
- - spec/blather/stanza/presence_spec.rb
224
206
  - spec/blather/stanza/pubsub/affiliations_spec.rb
225
207
  - spec/blather/stanza/pubsub/create_spec.rb
226
208
  - spec/blather/stanza/pubsub/event_spec.rb
@@ -233,13 +215,4 @@ test_files:
233
215
  - spec/blather/stanza/pubsub/unsubscribe_spec.rb
234
216
  - spec/blather/stanza/pubsub_owner/delete_spec.rb
235
217
  - spec/blather/stanza/pubsub_owner/purge_spec.rb
236
- - spec/blather/stanza/pubsub_owner_spec.rb
237
- - spec/blather/stanza/pubsub_spec.rb
238
- - spec/blather/stanza/x_spec.rb
239
- - spec/blather/stanza_spec.rb
240
- - spec/blather/stream/client_spec.rb
241
- - spec/blather/stream/component_spec.rb
242
- - spec/blather/stream/parser_spec.rb
243
- - spec/blather/xmpp_node_spec.rb
244
- - spec/fixtures/pubsub.rb
245
- - spec/spec_helper.rb
218
+ - spec/blather/client/dsl/pubsub_spec.rb