blather 0.7.1 → 0.8.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.
@@ -1,5 +1,11 @@
1
1
  # [develop](https://github.com/sprsquish/blather/compare/master...develop)
2
2
 
3
+ # [v0.8.0](https://github.com/sprsquish/blather/compare/v0.7.1...v0.8.0) - [2012-07-09](https://rubygems.org/gems/blather/versions/0.8.0)
4
+ * Feature(jmkeys): DSL methods for joining and sending messages to MUC rooms
5
+ * Feature(jackhong): Inband registration support
6
+ * Bugfix(benlangfeld): Ensure that presence nodes which are both status and subscription may be responded to
7
+ * Bugfix(benlangfeld): A whole bunch of JRuby fixes
8
+
3
9
  # [v0.7.1](https://github.com/sprsquish/blather/compare/v0.7.0...v0.7.1) - [2012-04-29](https://rubygems.org/gems/blather/versions/0.7.1)
4
10
  * Documentation updates
5
11
  * Bugfix(benlangfeld): Relax Nokogiri dependency to allow 1.5
data/README.md CHANGED
@@ -290,7 +290,7 @@ XEP-0100 | None |
290
290
  XEP-0106 | None |
291
291
  XEP-0107 | None |
292
292
  XEP-0108 | None |
293
- XEP-0114 | None |
293
+ XEP-0114 | Full |
294
294
  XEP-0115 | Partial |
295
295
  XEP-0118 | None |
296
296
  XEP-0122 | None |
@@ -34,9 +34,9 @@ Gem::Specification.new do |s|
34
34
  s.extra_rdoc_files = %w{LICENSE README.md}
35
35
 
36
36
  s.add_dependency "eventmachine", [">= 0.12.6"]
37
- s.add_dependency "nokogiri", ["~> 1.4"]
37
+ s.add_dependency "nokogiri", ["~> 1.5.5"]
38
38
  s.add_dependency "niceogiri", ["~> 1.0"]
39
- s.add_dependency "activesupport", [">= 3.0.7"]
39
+ s.add_dependency "activesupport", [">= 2.3.11"]
40
40
  s.add_dependency "girl_friday"
41
41
 
42
42
  s.add_development_dependency "bundler", ["~> 1.0"]
@@ -47,4 +47,5 @@ Gem::Specification.new do |s|
47
47
  s.add_development_dependency "yard", ["~> 0.6.1"]
48
48
  s.add_development_dependency "jruby-openssl", ["~> 0.7.4"] if jruby?
49
49
  s.add_development_dependency "bluecloth" unless jruby? || rbx?
50
+ s.add_development_dependency "countdownlatch"
50
51
  end
@@ -79,6 +79,7 @@
79
79
  blather/stream/features/sasl
80
80
  blather/stream/features/session
81
81
  blather/stream/features/tls
82
+ blather/stream/features/register
82
83
  ].each { |r| require r }
83
84
 
84
85
  module Blather
@@ -206,12 +206,32 @@ module Blather
206
206
  client.write stanza
207
207
  end
208
208
 
209
+ # Helper method to join a MUC room
210
+ #
211
+ # @overload join(room_jid, nickname)
212
+ # @param [Blather::JID, #to_s] room the JID of the room to join
213
+ # @param [#to_s] nickname the nickname to join the room as
214
+ # @overload join(room_jid, nickname)
215
+ # @param [#to_s] room the name of the room to join
216
+ # @param [Blather::JID, #to_s] service the service domain the room is hosted at
217
+ # @param [#to_s] nickname the nickname to join the room as
218
+ def join(room, service, nickname = nil)
219
+ join = Blather::Stanza::Presence::MUC.new
220
+ join.to = if nickname
221
+ "#{room}@#{service}/#{nickname}"
222
+ else
223
+ "#{room}/#{service}"
224
+ end
225
+ client.write join
226
+ end
227
+
209
228
  # Helper method to make sending basic messages easier
210
229
  #
211
230
  # @param [Blather::JID, #to_s] to the JID of the message recipient
212
231
  # @param [#to_s] msg the message to send
213
- def say(to, msg)
214
- client.write Blather::Stanza::Message.new(to, msg)
232
+ # @param [#to_sym] the stanza method to use
233
+ def say(to, msg, using = :chat)
234
+ client.write Blather::Stanza::Message.new(to, msg, using)
215
235
  end
216
236
 
217
237
  # The JID according to the server
@@ -121,9 +121,11 @@ module DSL
121
121
  #
122
122
  # @param [#to_s] node the node to create
123
123
  # @param [#to_s] host the PubSub host (defaults to the initialized host)
124
+ # @param [optional, Blather::Stanza::X] configuration the additional configuration to be set to created node
124
125
  # @yield [Blather::Stanza] stanza the reply stanza
125
- def create(node, host = nil)
126
+ def create(node, host = nil, configuration = nil)
126
127
  stanza = Stanza::PubSub::Create.new(:set, send_to(host), node)
128
+ stanza.configure_node << configuration if configuration
127
129
  request(stanza) { |n| yield n if block_given? }
128
130
  end
129
131
 
@@ -99,7 +99,7 @@ class Stanza
99
99
  decorators << Subscription
100
100
  end
101
101
 
102
- super
102
+ super node, *decorators
103
103
  end
104
104
 
105
105
  # Ensure element_name is "presence" for all subclasses
@@ -77,6 +77,7 @@ class Presence
77
77
  class Status < Presence
78
78
  # @private
79
79
  VALID_STATES = [:away, :chat, :dnd, :xa].freeze
80
+ VALID_TYPES = [:unavailable].freeze
80
81
 
81
82
  include Comparable
82
83
 
@@ -130,17 +131,6 @@ class Presence
130
131
  self.state == :xa
131
132
  end
132
133
 
133
- # Set the type attribute
134
- # Ensures type is nil or :unavailable
135
- #
136
- # @param [<:unavailable, nil>] type the type
137
- def type=(type)
138
- if type && type.to_sym != :unavailable
139
- raise ArgumentError, "Invalid type (#{type}). Must be nil or unavailable"
140
- end
141
- super
142
- end
143
-
144
134
  # Set the state
145
135
  # Ensure state is one of :available, :away, :chat, :dnd, :xa or nil
146
136
  #
@@ -203,8 +193,10 @@ class Presence
203
193
  # @param [Blather::Stanza::Presence::Status] o
204
194
  # @return [true,false]
205
195
  def <=>(o)
206
- unless self.from && o.from && self.from.stripped == o.from.stripped
207
- raise ArgumentError, "Cannot compare status from different JIDs: #{[self.from, o.from].inspect}"
196
+ if self.from || o.from
197
+ unless self.from.stripped == o.from.stripped
198
+ raise ArgumentError, "Cannot compare status from different JIDs: #{[self.from, o.from].inspect}"
199
+ end
208
200
  end
209
201
 
210
202
  if (self.type.nil? && o.type.nil?) || (!self.type.nil? && !o.type.nil?)
@@ -31,7 +31,19 @@ class Stream
31
31
  @idx = @idx ? @idx+1 : 0
32
32
  if stanza = @features.children[@idx]
33
33
  if stanza.namespaces['xmlns'] && (klass = self.class.from_namespace(stanza.namespaces['xmlns']))
34
- @feature = klass.new @stream, proc { next! }, @fail
34
+ @feature = klass.new(
35
+ @stream,
36
+ proc {
37
+ if (klass == Blather::Stream::Register && stanza = feature?(:mechanisms))
38
+ @idx = @features.children.index(stanza)
39
+ @feature = Blather::Stream::SASL.new @stream, proc { next! }, @fail
40
+ @feature.receive_data stanza
41
+ else
42
+ next!
43
+ end
44
+ },
45
+ (klass == Blather::Stream::SASL && feature?(:register)) ? proc { next! } : @fail
46
+ )
35
47
  @feature.receive_data stanza
36
48
  else
37
49
  next!
@@ -48,6 +60,10 @@ class Stream
48
60
  def fail!(msg)
49
61
  @fail.call msg
50
62
  end
63
+
64
+ def feature?(feature)
65
+ @features && @features.children.find { |v| v.element_name == feature.to_s }
66
+ end
51
67
  end
52
68
 
53
69
  end #Stream
@@ -0,0 +1,38 @@
1
+ module Blather
2
+ class Stream
3
+ class Register < Features
4
+ REGISTER_NS = "http://jabber.org/features/iq-register".freeze
5
+
6
+ register REGISTER_NS
7
+
8
+ def initialize(stream, succeed, fail)
9
+ super
10
+ @jid = @stream.jid
11
+ @pass = @stream.password
12
+ end
13
+
14
+ def receive_data(stanza)
15
+ error_node = stanza.xpath("//error").first
16
+
17
+ if error_node
18
+ fail!(BlatherError.new(stanza))
19
+ elsif stanza['type'] == 'result' && (stanza.content.empty? || stanza.children.find { |v| v.element_name == "query" })
20
+ succeed!
21
+ else
22
+ @stream.send register_query
23
+ end
24
+ end
25
+
26
+ def register_query
27
+ node = Blather::Stanza::Iq::Query.new(:set)
28
+ query_node = node.xpath('//query').first
29
+ query_node['xmlns'] = 'jabber:iq:register'
30
+ Nokogiri::XML::Builder.with(query_node) do |xml|
31
+ xml.username @jid.node
32
+ xml.password @pass
33
+ end
34
+ node
35
+ end
36
+ end
37
+ end
38
+ end
@@ -48,7 +48,7 @@ class Stream
48
48
  @namespaces[[prefix, uri]] ||= node.add_namespace(prefix, uri) if prefix && !ns_keys.include?(prefix)
49
49
  node.namespace = @namespaces[[prefix, uri]]
50
50
 
51
- if !@receiver.stopped?
51
+ unless @receiver.stopped?
52
52
  @current << node if @current
53
53
  @current = node
54
54
  end
@@ -1,3 +1,3 @@
1
1
  module Blather
2
- VERSION = '0.7.1'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -682,6 +682,6 @@ describe 'Blather::Client::Caps' do
682
682
  http://jabber.org/protocol/disco#items
683
683
  http://jabber.org/protocol/muc
684
684
  }
685
- @caps.c.inspect.should == "<presence>\n <c xmlns=\"http://jabber.org/protocol/caps\" hash=\"sha-1\" node=\"http://code.google.com/p/exodus\" ver=\"QgayPKawpkPSDYmwT/WM94uAlu0=\"/>\n</presence>"
685
+ Nokogiri::XML(@caps.c.to_xml).to_s.should == Nokogiri::XML("<presence><c xmlns=\"http://jabber.org/protocol/caps\" hash=\"sha-1\" node=\"http://code.google.com/p/exodus\" ver=\"QgayPKawpkPSDYmwT/WM94uAlu0=\"/></presence>").to_s
686
686
  end
687
687
  end
@@ -268,6 +268,26 @@ describe Blather::DSL::PubSub do
268
268
  @pubsub.create '/path/to/node'
269
269
  end
270
270
 
271
+ it 'can create a node with configuration' do
272
+ pubsub_configure = Blather::Stanza::X.new({
273
+ :type => :submit,
274
+ :fields => [
275
+ { :var => "FORM_TYPE", :type => 'hidden', :value => "http://jabber.org/protocol/pubsub#node_config" },
276
+ { :var => "pubsub#persist_items", :value => "0" },
277
+ { :var => "pubsub#max_items", :value => "0" },
278
+ { :var => "pubsub#notify_retract", :value => "0" },
279
+ { :var => "pubsub#publish_model", :value => "open" }]
280
+ })
281
+ @client.expects(:write_with_handler).with do |n|
282
+ n.should be_instance_of Blather::Stanza::PubSub::Create
283
+ n.find("/iq[@type='set']/ns:pubsub/ns:create[@node='/path/to/node']", :ns => Blather::Stanza::PubSub.registered_ns).should_not be_empty
284
+ n.to.should == Blather::JID.new(@host)
285
+ n.type.should == :set
286
+ n.configure_node.should == pubsub_configure
287
+ end
288
+ @pubsub.create '/path/to/node', nil, pubsub_configure
289
+ end
290
+
271
291
  it 'can delete a node' do
272
292
  @client.expects(:write_with_handler).with do |n|
273
293
  n.should be_instance_of Blather::Stanza::PubSubOwner::Delete
@@ -118,11 +118,31 @@ describe Blather::DSL do
118
118
  @dsl.write_to_stream stanza
119
119
  end
120
120
 
121
+ describe "#join" do
122
+ context "providing room and service as separate args" do
123
+ it "should join to a muc room with a specified nick" do
124
+ presence = Blather::Stanza::Presence::MUC.new
125
+ presence.to = "rabbit_hole@wonderland.lit/alice"
126
+ @client.expects(:write).with presence
127
+ @dsl.join 'rabbit_hole', 'wonderland.lit', 'alice'
128
+ end
129
+ end
130
+
131
+ context "providing a room JID" do
132
+ it "should join to a muc room with a specified nick" do
133
+ presence = Blather::Stanza::Presence::MUC.new
134
+ presence.to = "rabbit_hole@wonderland.lit/alice"
135
+ @client.expects(:write).with presence
136
+ @dsl.join 'rabbit_hole@wonderland.lit', 'alice'
137
+ end
138
+ end
139
+ end
140
+
121
141
  it 'provides a "say" helper' do
122
- to, msg = 'me@me.com', 'hello!'
142
+ to, msg, type = 'me@me.com', 'hello!', :groupchat
123
143
  Blather::Stanza::Message.stubs(:next_id).returns 0
124
- @client.expects(:write).with Blather::Stanza::Message.new(to, msg)
125
- @dsl.say to, msg
144
+ @client.expects(:write).with Blather::Stanza::Message.new(to, msg, type)
145
+ @dsl.say to, msg, type
126
146
  end
127
147
 
128
148
  it 'provides a JID accessor' do
@@ -27,11 +27,9 @@ describe Blather::Stanza::Presence::Subscription do
27
27
  end
28
28
 
29
29
  it 'generates an approval using #approve!' do
30
- jid = Blather::JID.new 'a@b'
31
- sub = Blather::Stanza::Presence::Subscription.new
32
- sub.from = jid
30
+ sub = Blather::Stanza.import Nokogiri::XML('<presence from="a@b" type="subscribe"><status/></presence>').root
33
31
  sub.approve!
34
- sub.to.should == jid
32
+ sub.to.should == 'a@b'
35
33
  sub.type.should == :subscribed
36
34
  end
37
35
 
@@ -1033,4 +1033,58 @@ describe Blather::Stream::Client do
1033
1033
  comp.expects(:send_data).with { |s| s.should_not match(/\n/); true }
1034
1034
  comp.send msg
1035
1035
  end
1036
+
1037
+ it 'tries to register if initial authentication failed but in-band registration enabled' do
1038
+ state = nil
1039
+ mocked_server(4) do |val, server|
1040
+ case state
1041
+ when nil
1042
+ state = :sasl_failed
1043
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
1044
+ server.send_data "<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism></mechanisms><register xmlns='http://jabber.org/features/iq-register'/></stream:features>"
1045
+ server.send_data "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized /></failure>"
1046
+ val.should match(/stream:stream/)
1047
+ when :sasl_failed
1048
+ state = :registered
1049
+ server.send_data "<iq type='result'/>"
1050
+ val.should match(/jabber:iq:register/)
1051
+ when :registered
1052
+ state = :authenticated
1053
+ server.send_data "<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />"
1054
+ val.should match(/mechanism="PLAIN"/)
1055
+ when :authenticated
1056
+ EM.stop
1057
+ val.should match(/stream:stream/)
1058
+ else
1059
+ EM.stop
1060
+ false
1061
+ end
1062
+ end
1063
+ end
1064
+
1065
+ it 'fails when in-band registration failed' do
1066
+ state = nil
1067
+ @client = mock()
1068
+ @client.expects(:receive_data).with { |n| n.should be_instance_of Blather::BlatherError }
1069
+ mocked_server(3) do |val, server|
1070
+ case state
1071
+ when nil
1072
+ state = :sasl_failed
1073
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
1074
+ server.send_data "<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism></mechanisms><register xmlns='http://jabber.org/features/iq-register'/></stream:features>"
1075
+ server.send_data "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized /></failure>"
1076
+ val.should match(/stream:stream/)
1077
+ when :sasl_failed
1078
+ state = :registration_failed
1079
+ server.send_data "<iq type='error'><query /><error code='409' type='cancel'><conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>"
1080
+ val.should match(/jabber:iq:register/)
1081
+ when :registration_failed
1082
+ EM.stop
1083
+ val.should match(/\/stream:stream/)
1084
+ else
1085
+ EM.stop
1086
+ false
1087
+ end
1088
+ end
1089
+ end
1036
1090
  end
@@ -1,32 +1,37 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Blather::Stream::Parser do
4
- before do
5
- @client = Class.new do
4
+ let :client do
5
+ Class.new do
6
6
  attr_reader :data
7
+ attr_accessor :latch
7
8
  def stopped?; false; end
8
- def receive(data)
9
+ def receive(node)
9
10
  @data ||= []
10
- @data << data
11
+ @data << node
12
+ latch.countdown!
11
13
  end
12
14
  end.new
13
- @parser = Blather::Stream::Parser.new @client
14
15
  end
15
16
 
16
- after { @client = @parser = nil}
17
+ subject { Blather::Stream::Parser.new client }
18
+
19
+ def process(*data)
20
+ client.latch = CountDownLatch.new 1
21
+ data.each { |d| subject.receive_data d }
22
+ client.latch.wait(2).should be_true
23
+ end
17
24
 
18
25
  def check_parse(data)
19
- @parser.receive_data data
20
- @client.data.size.should == 1
21
- @client.data[0].to_s.gsub(/\n\s*/,'').should == data
26
+ process data
27
+ client.data.size.should == 1
28
+ client.data[0].to_s.gsub(/\n\s*/,'').should == data
22
29
  end
23
30
 
24
31
  it 'handles fragmented parsing' do
25
- @parser.receive_data '<foo>'
26
- @parser.receive_data '<bar/>'
27
- @parser.receive_data '</foo>'
28
- @client.data.size.should == 1
29
- @client.data[0].to_s.gsub(/\n\s*/,'').should == '<foo><bar/></foo>'
32
+ process '<foo>', '<bar/>', '</foo>'
33
+ client.data.size.should == 1
34
+ client.data[0].to_s.gsub(/\n\s*/,'').should == '<foo><bar/></foo>'
30
35
  end
31
36
 
32
37
  it 'handles a basic example' do
@@ -85,71 +90,63 @@ describe Blather::Stream::Parser do
85
90
  '<text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">Some special application diagnostic information...</text>',
86
91
  '<special-application-condition xmlns="special:application-ns"/>',
87
92
  "</error>",
88
- "</message>",
93
+ "</message>"
89
94
  ]
90
- data.each { |d| @parser.receive_data d }
91
- @client.data.size.should == 1
92
- @client.data[0].to_s.split("\n").map{|n|n.strip}.should == data
93
- @client.data[0].xpath('//*[namespace-uri()="urn:ietf:params:xml:ns:xmpp-stanzas"]').size.should == 2
95
+ process *data
96
+ client.data.size.should == 1
97
+ Nokogiri::XML(client.data[0].to_s.gsub(/\n\s*/, '')).to_s.should == Nokogiri::XML(data.join).to_s
98
+ client.data[0].xpath('//*[namespace-uri()="urn:ietf:params:xml:ns:xmpp-stanzas"]').size.should == 2
94
99
  end
95
100
 
96
101
  it 'handles not absolute namespaces' do
97
102
  lambda do
98
- @parser.receive_data '<iq type="result" id="blather0007" to="n@d/r"><vCard xmlns="vcard-temp"/></iq>'
103
+ process '<iq type="result" id="blather0007" to="n@d/r"><vCard xmlns="vcard-temp"/></iq>'
99
104
  end.should_not raise_error
100
105
  end
101
106
 
102
107
  it 'responds with stream:stream as a separate response' do
103
- data = [
104
- '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" to="example.com" version="1.0">',
108
+ process '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" to="example.com" version="1.0">',
105
109
  '<foo/>'
106
- ]
107
- data.each { |d| @parser.receive_data d }
108
- @client.data.size.should == 2
109
- @client.data[0].document.xpath('/stream:stream[@to="example.com" and @version="1.0"]', 'xmlns' => 'jabber:client', 'stream' => 'http://etherx.jabber.org/streams').size.should == 1
110
- @client.data[1].to_s.should == '<foo/>'
110
+ client.data.size.should == 2
111
+ client.data[0].document.xpath('/stream:stream[@to="example.com" and @version="1.0"]', 'xmlns' => 'jabber:client', 'stream' => 'http://etherx.jabber.org/streams').size.should == 1
112
+ client.data[1].to_s.should == '<foo/>'
111
113
  end
112
114
 
113
115
  it 'response with stream:end when receiving </stream:stream>' do
114
- @parser.receive_data '<stream:stream xmlns:stream="http://etherx.jabber.org/streams"/>'
115
- @client.data.size.should == 2
116
- @client.data[1].to_s.should == '<stream:end xmlns:stream="http://etherx.jabber.org/streams"/>'
116
+ process '<stream:stream xmlns:stream="http://etherx.jabber.org/streams"/>'
117
+ client.data.size.should == 2
118
+ client.data[1].to_s.should == '<stream:end xmlns:stream="http://etherx.jabber.org/streams"/>'
117
119
  end
118
120
 
119
121
  it 'raises ParseError when an error is sent' do
120
- lambda { @parser.receive_data "<stream:stream>" }.should raise_error(Blather::ParseError)
122
+ lambda { process "<stream:stream>" }.should raise_error(Blather::ParseError)
121
123
  end
122
124
 
123
125
  it 'handles stream stanzas without an issue' do
124
- data = [
125
- '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" to="example.com" version="1.0">',
126
+ process '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" to="example.com" version="1.0">',
126
127
  '<stream:features/>'
127
- ]
128
- data.each { |d| @parser.receive_data d }
129
- @client.data.size.should == 2
130
- @client.data[0].document.xpath('/stream:stream[@to="example.com" and @version="1.0"]', 'xmlns' => 'jabber:client', 'stream' => 'http://etherx.jabber.org/streams').size.should == 1
131
- @client.data[1].to_s.should == '<stream:features xmlns:stream="http://etherx.jabber.org/streams"/>'
128
+ client.data.size.should == 2
129
+ client.data[0].document.xpath('/stream:stream[@to="example.com" and @version="1.0"]', 'xmlns' => 'jabber:client', 'stream' => 'http://etherx.jabber.org/streams').size.should == 1
130
+ client.data[1].to_s.should == '<stream:features xmlns:stream="http://etherx.jabber.org/streams"/>'
132
131
  end
133
132
 
134
133
  it 'ignores the client namespace on stanzas' do
135
- [ "<message type='chat' to='n@d' from='n@d/r' id='id1' xmlns='jabber:client'>",
134
+ process "<message type='chat' to='n@d' from='n@d/r' id='id1' xmlns='jabber:client'>",
136
135
  "<body>exit</body>",
137
136
  "<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>exit</body></html>",
138
137
  "</message>"
139
- ].each { |d| @parser.receive_data d }
140
- @client.data.size.should == 1
141
- @client.data[0].document.xpath('/message/body[.="exit"]').should_not be_empty
142
- @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').should_not be_empty
138
+ client.data.size.should == 1
139
+ client.data[0].document.xpath('/message/body[.="exit"]').should_not be_empty
140
+ 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').should_not be_empty
143
141
  end
144
142
 
145
143
  it 'ignores the component namespace on stanzas' do
146
- [ "<message type='chat' to='n@d' from='n@d/r' id='id1' xmlns='jabber:component:accept'>",
144
+ process "<message type='chat' to='n@d' from='n@d/r' id='id1' xmlns='jabber:component:accept'>",
147
145
  "<body>exit</body>",
148
146
  "<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>exit</body></html>",
149
147
  "</message>"
150
- ].each { |d| @parser.receive_data d }
151
- @client.data.size.should == 1
152
- @client.data[0].document.xpath('/message/body[.="exit"]').should_not be_empty
153
- @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').should_not be_empty
148
+ client.data.size.should == 1
149
+ client.data[0].document.xpath('/message/body[.="exit"]').should_not be_empty
150
+ 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').should_not be_empty
154
151
  end
155
152
  end
@@ -1,5 +1,6 @@
1
1
  require 'blather'
2
2
  require 'mocha'
3
+ require 'countdownlatch'
3
4
 
4
5
  Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
5
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blather
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-29 00:00:00.000000000 Z
12
+ date: 2012-07-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: '1.4'
37
+ version: 1.5.5
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: '1.4'
45
+ version: 1.5.5
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: niceogiri
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ! '>='
68
68
  - !ruby/object:Gem::Version
69
- version: 3.0.7
69
+ version: 2.3.11
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,7 +74,7 @@ dependencies:
74
74
  requirements:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
- version: 3.0.7
77
+ version: 2.3.11
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: girl_friday
80
80
  requirement: !ruby/object:Gem::Requirement
@@ -203,6 +203,22 @@ dependencies:
203
203
  - - ! '>='
204
204
  - !ruby/object:Gem::Version
205
205
  version: '0'
206
+ - !ruby/object:Gem::Dependency
207
+ name: countdownlatch
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
206
222
  description: An XMPP DSL for Ruby written on top of EventMachine and Nokogiri
207
223
  email: sprsquish@gmail.com
208
224
  executables: []
@@ -295,6 +311,7 @@ files:
295
311
  - lib/blather/stream/client.rb
296
312
  - lib/blather/stream/component.rb
297
313
  - lib/blather/stream/features.rb
314
+ - lib/blather/stream/features/register.rb
298
315
  - lib/blather/stream/features/resource.rb
299
316
  - lib/blather/stream/features/sasl.rb
300
317
  - lib/blather/stream/features/session.rb
@@ -374,7 +391,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
374
391
  version: '0'
375
392
  segments:
376
393
  - 0
377
- hash: 4196042577194384774
394
+ hash: -4548531025459259087
378
395
  required_rubygems_version: !ruby/object:Gem::Requirement
379
396
  none: false
380
397
  requirements:
@@ -383,10 +400,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
383
400
  version: '0'
384
401
  segments:
385
402
  - 0
386
- hash: 4196042577194384774
403
+ hash: -4548531025459259087
387
404
  requirements: []
388
405
  rubyforge_project:
389
- rubygems_version: 1.8.21
406
+ rubygems_version: 1.8.24
390
407
  signing_key:
391
408
  specification_version: 3
392
409
  summary: Simpler XMPP built for speed