blather 0.8.1 → 0.8.2

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/.gitignore CHANGED
@@ -17,3 +17,4 @@ notes
17
17
  vendor
18
18
  .rvmrc
19
19
  .rbx
20
+ tmp
@@ -1,8 +1,9 @@
1
+ language: ruby
1
2
  rvm:
2
3
  - 1.9.2
3
4
  - 1.9.3
4
- - jruby-18mode
5
5
  - jruby-19mode
6
- - rbx-18mode
7
6
  - rbx-19mode
8
7
  - ruby-head
8
+ notifications:
9
+ irc: "irc.freenode.org#adhearsion"
@@ -1,5 +1,11 @@
1
1
  # [develop](https://github.com/adhearsion/blather/compare/master...develop)
2
2
 
3
+ # [v0.8.2](https://github.com/adhearsion/blather/compare/v0.8.1...v0.8.2) - [2013-01-02](https://rubygems.org/gems/blather/versions/0.8.2)
4
+ * Bugfix: General spec fixes
5
+ * Bugfix: Fixes for JRuby and Rubinius
6
+ * Bugfix: Ensure parsers are shut down correctly
7
+ * Update: Bump Nokogiri (1.5.6) and EventMachine (1.0.0) minimum versions
8
+
3
9
  # [v0.8.1](https://github.com/adhearsion/blather/compare/v0.8.0...v0.8.1) - [2012-09-17](https://rubygems.org/gems/blather/versions/0.8.1)
4
10
  * Project moved to the Adhearsion Foundation
5
11
  * Fixes for EventMachine 1.0.x
data/Guardfile CHANGED
@@ -1,4 +1,4 @@
1
- guard 'rspec', :version => 2, :cli => '--format documentation' do
1
+ guard 'rspec', :cli => '--format documentation' do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
3
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
4
  watch('spec/spec_helper.rb') { "spec/" }
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Blather [ ![Build status](http://travis-ci.org/adhearsion/blather.png) ](http://travis-ci.org/adhearsion/blather)
1
+ # Blather [![Build Status](https://travis-ci.org/adhearsion/blather.png?branch=develop)](https://travis-ci.org/adhearsion/blather)
2
2
 
3
3
  XMPP DSL (and more) for Ruby written on [EventMachine](http://rubyeventmachine.com/) and [Nokogiri](http://nokogiri.org/).
4
4
 
@@ -11,7 +11,7 @@ XMPP DSL (and more) for Ruby written on [EventMachine](http://rubyeventmachine.c
11
11
  ## Project Pages
12
12
 
13
13
  * [GitHub](https://github.com/adhearsion/blather)
14
- * [Gemcutter](http://gemcutter.org/gems/blather)
14
+ * [Rubygems](http://rubygems.org/gems/blather)
15
15
  * [API Documentation](http://rdoc.info/gems/blather/file/README.md)
16
16
  * [Google Group](http://groups.google.com/group/xmpp-blather)
17
17
 
@@ -33,8 +33,8 @@ Gem::Specification.new do |s|
33
33
  s.rdoc_options = %w{--charset=UTF-8}
34
34
  s.extra_rdoc_files = %w{LICENSE README.md}
35
35
 
36
- s.add_dependency "eventmachine", [">= 0.12.6"]
37
- s.add_dependency "nokogiri", ["~> 1.5.5"]
36
+ s.add_dependency "eventmachine", [">= 1.0.0"]
37
+ s.add_dependency "nokogiri", ["~> 1.5", ">= 1.5.6"]
38
38
  s.add_dependency "niceogiri", ["~> 1.0"]
39
39
  s.add_dependency "activesupport", [">= 2.3.11"]
40
40
  s.add_dependency "girl_friday"
@@ -42,10 +42,11 @@ Gem::Specification.new do |s|
42
42
  s.add_development_dependency "bundler", ["~> 1.0"]
43
43
  s.add_development_dependency "rake"
44
44
  s.add_development_dependency "rspec", ["~> 2.7"]
45
- s.add_development_dependency "mocha", ["~> 0.9.12"]
45
+ s.add_development_dependency "mocha", ["~> 0.9"]
46
46
  s.add_development_dependency "guard-rspec"
47
- s.add_development_dependency "yard", ["~> 0.6.1"]
48
- s.add_development_dependency "jruby-openssl", ["~> 0.7.4"] if jruby?
47
+ s.add_development_dependency "yard", ["~> 0.6"]
48
+ s.add_development_dependency "jruby-openssl", ["~> 0.7"] if jruby?
49
49
  s.add_development_dependency "bluecloth" unless jruby? || rbx?
50
50
  s.add_development_dependency "countdownlatch"
51
+ s.add_development_dependency 'rb-fsevent', ['~> 0.9']
51
52
  end
@@ -6,9 +6,6 @@ module Blather
6
6
  # This uses the #{cert_directory}/*.crt files as the list of trusted root
7
7
  # CA certificates.
8
8
  class CertStore
9
- @@certs = nil
10
- @cert_directory = nil
11
-
12
9
  def initialize(cert_directory)
13
10
  @cert_directory = cert_directory
14
11
  @store = OpenSSL::X509::Store.new
@@ -19,19 +16,24 @@ module Blather
19
16
  # store. If the certificate can be trusted, it's added to the store so
20
17
  # it can be used to trust other certs.
21
18
  def trusted?(pem)
22
- if cert = OpenSSL::X509::Certificate.new(pem) rescue nil
19
+ if cert = OpenSSL::X509::Certificate.new(pem)
23
20
  @store.verify(cert).tap do |trusted|
24
- @store.add_cert(cert) if trusted rescue nil
21
+ begin
22
+ @store.add_cert(cert) if trusted
23
+ rescue OpenSSL::X509::StoreError
24
+ end
25
25
  end
26
26
  end
27
+ rescue OpenSSL::X509::CertificateError
28
+ nil
27
29
  end
28
30
 
29
31
  # Return true if the domain name matches one of the names in the
30
32
  # certificate. In other words, is the certificate provided to us really
31
33
  # for the domain to which we think we're connected?
32
34
  def domain?(pem, domain)
33
- if cert = OpenSSL::X509::Certificate.new(pem) rescue nil
34
- OpenSSL::SSL.verify_certificate_identity(cert, domain) rescue false
35
+ if cert = OpenSSL::X509::Certificate.new(pem)
36
+ OpenSSL::SSL.verify_certificate_identity(cert, domain)
35
37
  end
36
38
  end
37
39
 
@@ -39,15 +41,15 @@ module Blather
39
41
  # certificates are used to start the trust chain needed to validate certs
40
42
  # we receive from clients and servers.
41
43
  def certs
42
- unless @@certs
44
+ @certs ||= begin
43
45
  pattern = /-{5}BEGIN CERTIFICATE-{5}\n.*?-{5}END CERTIFICATE-{5}\n/m
44
- dir = @cert_directory
45
- certs = Dir[File.join(dir, '*.crt')].map {|f| File.read(f) }
46
- certs = certs.map {|c| c.scan(pattern) }.flatten
47
- certs.map! {|c| OpenSSL::X509::Certificate.new(c) }
48
- @@certs = certs.reject {|c| c.not_after < Time.now }
46
+ Dir[File.join(@cert_directory, '*.crt')]
47
+ .map {|f| File.read(f) }
48
+ .map {|c| c.scan(pattern) }
49
+ .flatten
50
+ .map {|c| OpenSSL::X509::Certificate.new(c) }
51
+ .reject {|c| c.not_after < Time.now }
49
52
  end
50
- @@certs
51
53
  end
52
54
  end
53
- end
55
+ end
@@ -30,7 +30,7 @@ optparse = OptionParser.new do |opts|
30
30
  end
31
31
  options[:log] = log
32
32
  end
33
-
33
+
34
34
  opts.on('--certs=[CERTS DIRECTORY]', 'The directory path where the trusted certificates are stored') do |certs|
35
35
  if !File.directory?(certs)
36
36
  $stderr.puts "The certs directory path (#{certs}) is no good."
@@ -38,7 +38,7 @@ optparse = OptionParser.new do |opts|
38
38
  end
39
39
  options[:certs] = certs
40
40
  end
41
-
41
+
42
42
  opts.on_tail('-h', '--help', 'Show this message') do
43
43
  puts opts
44
44
  exit
@@ -11,7 +11,7 @@ module Blather
11
11
 
12
12
  # Set this to true if you want SOCKS5 Bytestreams to attempt to use private network addresses
13
13
  attr_accessor :allow_private_ips
14
-
14
+
15
15
  # Create a new FileTransfer
16
16
  #
17
17
  # @param [Blather::Stream] stream the stream the file transfer should use
@@ -65,4 +65,4 @@ module Blather
65
65
  end
66
66
  end
67
67
  end
68
- end
68
+ end
@@ -97,7 +97,7 @@ module Blather
97
97
 
98
98
  def post_init
99
99
  self.succeed
100
-
100
+
101
101
  class << self
102
102
  include @@handler
103
103
  end
@@ -142,7 +142,7 @@ class Stanza
142
142
  # The Identity's xml_lang
143
143
  # @return [String]
144
144
  def xml_lang
145
- read_attr "lang"
145
+ read_attr "xml:lang"
146
146
  end
147
147
 
148
148
  # Set the Identity's name
@@ -50,4 +50,4 @@ class Iq
50
50
 
51
51
  end #Iq
52
52
  end #Stanza
53
- end
53
+ end
@@ -182,4 +182,4 @@ class Iq
182
182
 
183
183
  end #Iq
184
184
  end #Stanza
185
- end
185
+ end
@@ -57,7 +57,6 @@ module Blather
57
57
  STREAM_NS = 'http://etherx.jabber.org/streams'
58
58
  attr_accessor :password
59
59
  attr_reader :jid
60
- @@store = nil
61
60
 
62
61
  # Start the stream between client and server
63
62
  #
@@ -76,7 +75,7 @@ module Blather
76
75
  jid = JID.new jid
77
76
  port ||= 5222
78
77
  if certs_directory
79
- @@store = CertStore.new(certs_directory)
78
+ @store = CertStore.new(certs_directory)
80
79
  end
81
80
  if host
82
81
  connect host, port, self, client, jid, pass, connect_timeout
@@ -142,6 +141,8 @@ module Blather
142
141
  @to = self.jid.domain
143
142
  @password = pass
144
143
  @connect_timeout = connect_timeout || 180
144
+
145
+ @parser = Parser.new self
145
146
  end
146
147
 
147
148
  # Called when EM completes the connection to the server
@@ -154,7 +155,6 @@ module Blather
154
155
  end
155
156
  end
156
157
  @connected = true
157
- # @keepalive = EM::PeriodicTimer.new(60) { send_data ' ' }
158
158
  start
159
159
  end
160
160
 
@@ -162,11 +162,9 @@ module Blather
162
162
  # @private
163
163
  def receive_data(data)
164
164
  @parser << data
165
-
166
165
  rescue ParseError => e
167
166
  @error = e
168
- send "<stream:error><xml-not-well-formed xmlns='#{StreamError::STREAM_ERR_NS}'/></stream:error>"
169
- stop
167
+ stop "<stream:error><xml-not-well-formed xmlns='#{StreamError::STREAM_ERR_NS}'/></stream:error>"
170
168
  end
171
169
 
172
170
  # Called by EM to verify the peer certificate. If a certificate store directory
@@ -178,8 +176,8 @@ module Blather
178
176
  # but it only does that for inbound connections, not when we
179
177
  # make a connection to another server.
180
178
  Blather.log "Checking SSL cert: #{pem}"
181
- return true if !@@store
182
- @@store.trusted?(pem).tap do |trusted|
179
+ return true unless @store
180
+ @store.trusted?(pem).tap do |trusted|
183
181
  close_connection unless trusted
184
182
  end
185
183
  end
@@ -193,29 +191,33 @@ module Blather
193
191
  # Called by EM when the connection is closed
194
192
  # @private
195
193
  def unbind
194
+ cleanup
195
+
196
196
  raise NoConnection unless @inited
197
197
  raise ConnectionFailed unless @connected
198
198
 
199
- @connect_timer.cancel if @connect_timer
200
- # @keepalive.cancel
201
199
  @state = :stopped
202
200
  @client.receive_data @error if @error
203
201
  @client.unbind
204
202
  end
205
203
 
204
+ def cleanup
205
+ @parser.finish
206
+ @connect_timer.cancel if @connect_timer
207
+ end
208
+
206
209
  # Called by the parser with parsed nodes
207
210
  # @private
208
211
  def receive(node)
209
212
  Blather.log "RECEIVING (#{node.element_name}) #{node}"
210
- @node = node
211
213
 
212
- if @node.namespace && @node.namespace.prefix == 'stream'
213
- case @node.element_name
214
+ if node.namespace && node.namespace.prefix == 'stream'
215
+ case node.element_name
214
216
  when 'stream'
215
217
  @state = :ready if @state == :stopped
216
218
  return
217
219
  when 'error'
218
- handle_stream_error
220
+ handle_stream_error node
219
221
  return
220
222
  when 'end'
221
223
  stop
@@ -229,7 +231,7 @@ module Blather
229
231
  )
230
232
  end
231
233
  end
232
- @receiver.receive_data @node.to_stanza
234
+ @receiver.receive_data node.to_stanza
233
235
  end
234
236
 
235
237
  # Ensure the JID gets attached to the client
@@ -242,16 +244,16 @@ module Blather
242
244
  protected
243
245
  # Stop the stream
244
246
  # @private
245
- def stop
247
+ def stop(error = nil)
246
248
  unless @state == :stopped
247
249
  @state = :stopped
248
- send '</stream:stream>'
250
+ send "#{error}</stream:stream>"
249
251
  end
250
252
  end
251
253
 
252
254
  # @private
253
- def handle_stream_error
254
- @error = StreamError.import(@node)
255
+ def handle_stream_error(node)
256
+ @error = StreamError.import(node)
255
257
  stop
256
258
  end
257
259
 
@@ -8,17 +8,7 @@ class Stream
8
8
  NAMESPACE = 'jabber:client'
9
9
 
10
10
  def start
11
- @parser = Parser.new self
12
- start_stream = <<-STREAM
13
- <stream:stream
14
- to='#{@to}'
15
- xmlns='#{NAMESPACE}'
16
- xmlns:stream='#{STREAM_NS}'
17
- version='#{VERSION}'
18
- xml:lang='#{LANG}'
19
- >
20
- STREAM
21
- send start_stream.gsub(/\s+/, ' ')
11
+ send "<stream:stream to='#{@to}' xmlns='#{NAMESPACE}' xmlns:stream='#{STREAM_NS}' version='#{VERSION}' xml:lang='#{LANG}'>"
22
12
  end
23
13
 
24
14
  def send(stanza)
@@ -13,7 +13,7 @@ class Stream
13
13
  end
14
14
 
15
15
  if node.document.find_first('/stream:stream[not(stream:error)]', :xmlns => NAMESPACE, :stream => STREAM_NS)
16
- send("<handshake>#{Digest::SHA1.hexdigest(@node['id']+@password)}</handshake>")
16
+ send "<handshake>#{Digest::SHA1.hexdigest(node['id']+@password)}</handshake>"
17
17
  end
18
18
  end
19
19
 
@@ -23,15 +23,7 @@ class Stream
23
23
  end
24
24
 
25
25
  def start
26
- @parser = Parser.new self
27
- start_stream = <<-STREAM
28
- <stream:stream
29
- to='#{@jid}'
30
- xmlns='#{NAMESPACE}'
31
- xmlns:stream='#{STREAM_NS}'
32
- >
33
- STREAM
34
- send start_stream.gsub(/\s+/, ' ')
26
+ send "<stream:stream to='#{@jid}' xmlns='#{NAMESPACE}' xmlns:stream='#{STREAM_NS}'>"
35
27
  end
36
28
  end #Client
37
29
 
@@ -13,9 +13,7 @@ class Stream
13
13
  end
14
14
 
15
15
  def initialize(stream, succeed, fail)
16
- @stream = stream
17
- @succeed = succeed
18
- @fail = fail
16
+ @stream, @succeed, @fail = stream, succeed, fail
19
17
  end
20
18
 
21
19
  def receive_data(stanza)
@@ -15,13 +15,15 @@ class Stream
15
15
  @namespaces = {}
16
16
  @namespace_definitions = []
17
17
  @parser = Nokogiri::XML::SAX::PushParser.new self
18
- @parser.options = Nokogiri::XML::ParseOptions::DEFAULT_XML | Nokogiri::XML::ParseOptions::NOENT
18
+ @parser.options = Nokogiri::XML::ParseOptions::NOENT
19
19
  end
20
20
 
21
21
  def receive_data(string)
22
22
  Blather.log "PARSING: (#{string})" if @@debug
23
23
  @parser << string
24
24
  self
25
+ rescue Nokogiri::XML::SyntaxError => e
26
+ error e.message
25
27
  end
26
28
  alias_method :<<, :receive_data
27
29
 
@@ -54,13 +56,6 @@ class Stream
54
56
  end
55
57
 
56
58
  deliver(node) if elem == 'stream'
57
-
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*/,'')
64
59
  end
65
60
 
66
61
  def end_element_namespace(elem, prefix, uri)
@@ -91,6 +86,11 @@ class Stream
91
86
  raise ParseError.new(msg)
92
87
  end
93
88
 
89
+ def finish
90
+ @parser.finish
91
+ rescue ParseError, RuntimeError
92
+ end
93
+
94
94
  private
95
95
  def deliver(node)
96
96
  @current, @namespaces, @namespace_definitions = nil, {}, []
@@ -1,3 +1,3 @@
1
1
  module Blather
2
- VERSION = '0.8.1'
2
+ VERSION = '0.8.2'
3
3
  end
@@ -2,204 +2,202 @@ require 'spec_helper'
2
2
  require 'blather/client/client'
3
3
 
4
4
  describe Blather::Client do
5
+ let(:jid) { Blather::JID.new 'n@d/r' }
6
+ let(:stream) { mock 'Stream' }
7
+
5
8
  before do
6
- @client = Blather::Client.new
7
- @stream = mock
8
- @stream.stubs(:send)
9
- @jid = Blather::JID.new('n@d/r')
9
+ stream.stubs :send
10
10
  end
11
11
 
12
12
  it 'provides a Blather::JID reader' do
13
- @client.post_init @stream, @jid
14
- @client.should respond_to :jid
15
- @client.jid.should == @jid
13
+ subject.post_init stream, jid
14
+ subject.should respond_to :jid
15
+ subject.jid.should == jid
16
16
  end
17
17
 
18
18
  it 'provides a reader for the roster' do
19
- @client.should respond_to :roster
20
- @client.roster.should be_kind_of Blather::Roster
19
+ subject.should respond_to :roster
20
+ subject.roster.should be_kind_of Blather::Roster
21
21
  end
22
22
 
23
23
  it 'provides a status reader' do
24
- @client.post_init @stream, @jid
25
- @client.should respond_to :status
26
- @client.status = :away
27
- @client.status.should == :away
24
+ subject.post_init stream, jid
25
+ subject.should respond_to :status
26
+ subject.status = :away
27
+ subject.status.should == :away
28
28
  end
29
29
 
30
30
  it 'should have a caps handler' do
31
- @client.should respond_to :caps
32
- @client.caps.should be_kind_of Blather::Stanza::Capabilities
31
+ subject.should respond_to :caps
32
+ subject.caps.should be_kind_of Blather::Stanza::Capabilities
33
33
  end
34
34
 
35
35
  it 'can be setup' do
36
- @client.should respond_to :setup
37
- @client.setup('me@me.com', 'pass').should == @client
36
+ subject.should respond_to :setup
37
+ subject.setup('me@me.com', 'pass').should == subject
38
38
  end
39
39
 
40
40
  it 'knows if it has been setup' do
41
- @client.should respond_to :setup?
42
- @client.setup?.should == false
43
- @client.setup 'me@me.com', 'pass'
44
- @client.setup?.should == true
41
+ subject.should respond_to :setup?
42
+ subject.should_not be_setup
43
+ subject.setup 'me@me.com', 'pass'
44
+ subject.should be_setup
45
45
  end
46
46
 
47
47
  it 'cannot be run before being setup' do
48
- lambda { @client.run }.should raise_error RuntimeError
48
+ lambda { subject.run }.should raise_error RuntimeError
49
49
  end
50
50
 
51
51
  it 'starts up a Component connection when setup without a node' do
52
52
  setup = 'pubsub.jabber.local', 'secret'
53
- @client.setup *setup
54
- Blather::Stream::Component.expects(:start).with @client, *setup + [nil, nil, nil, nil]
55
- @client.run
53
+ subject.setup *setup
54
+ Blather::Stream::Component.expects(:start).with subject, *setup + [nil, nil, nil, nil]
55
+ subject.run
56
56
  end
57
57
 
58
58
  it 'starts up a Client connection when setup with a node' do
59
59
  setup = 'test@jabber.local', 'secret'
60
- @client.setup *setup
61
- Blather::Stream::Client.expects(:start).with @client, *setup + [nil, nil, nil, nil]
62
- @client.run
60
+ subject.setup *setup
61
+ Blather::Stream::Client.expects(:start).with subject, *setup + [nil, nil, nil, nil]
62
+ subject.run
63
63
  end
64
64
 
65
65
  it 'knows if it is disconnected' do
66
- @client.should respond_to :connected?
67
- @client.connected?.should == false
66
+ subject.should respond_to :connected?
67
+ subject.should_not be_connected
68
68
  end
69
69
 
70
70
  it 'knows if it is connected' do
71
- stream = mock
72
71
  stream.expects(:stopped?).returns false
73
- @client.setup('me.com', 'secret')
74
- @client.post_init stream, Blather::JID.new('me.com')
75
- @client.connected?.should == true
72
+ subject.setup 'me.com', 'secret'
73
+ subject.post_init stream, Blather::JID.new('me.com')
74
+ subject.should be_connected
76
75
  end
77
76
 
78
77
  describe 'if it has been setup but not connected yet' do
79
78
  it 'should consider itself disconnected' do
80
- @client.setup('me.com', 'secret')
81
- @client.connected?.should == false
79
+ subject.setup 'me.com', 'secret'
80
+ subject.should_not be_connected
82
81
  end
83
82
  end
84
83
 
85
84
  it 'writes to the connection the closes when #close is called' do
86
- stream = mock()
87
85
  stream.expects(:close_connection_after_writing)
88
- @client.setup('me.com', 'secret')
89
- @client.post_init stream, Blather::JID.new('me.com')
90
- @client.close
86
+ subject.setup 'me.com', 'secret'
87
+ subject.post_init stream, Blather::JID.new('me.com')
88
+ subject.close
91
89
  end
92
90
 
93
91
  it 'shuts down EM when #unbind is called if it is running' do
94
92
  EM.expects(:reactor_running?).returns true
95
93
  EM.expects(:stop)
96
- @client.unbind
94
+ subject.unbind
97
95
  end
98
96
 
99
97
  it 'does nothing when #unbind is called and EM is not running' do
100
98
  EM.expects(:reactor_running?).returns false
101
99
  EM.expects(:stop).never
102
- @client.unbind
100
+ subject.unbind
103
101
  end
104
102
 
105
103
  it 'calls the :disconnected handler with #unbind is called' do
106
104
  EM.expects(:reactor_running?).returns false
107
- disconnected = mock()
105
+ disconnected = mock
108
106
  disconnected.expects(:call)
109
- @client.register_handler(:disconnected) { disconnected.call }
110
- @client.unbind
107
+ subject.register_handler(:disconnected) { disconnected.call }
108
+ subject.unbind
111
109
  end
112
110
 
113
111
  it 'does not call EM.stop on #unbind if a handler returns positive' do
114
112
  EM.expects(:reactor_running?).never
115
113
  EM.expects(:stop).never
116
- disconnected = mock()
114
+ disconnected = mock
117
115
  disconnected.expects(:call).returns true
118
- @client.register_handler(:disconnected) { disconnected.call }
119
- @client.unbind
116
+ subject.register_handler(:disconnected) { disconnected.call }
117
+ subject.unbind
120
118
  end
121
119
 
122
120
  it 'calls EM.stop on #unbind if a handler returns negative' do
123
121
  EM.expects(:reactor_running?).returns true
124
122
  EM.expects(:stop)
125
- disconnected = mock()
123
+ disconnected = mock
126
124
  disconnected.expects(:call).returns false
127
- @client.register_handler(:disconnected) { disconnected.call }
128
- @client.unbind
125
+ subject.register_handler(:disconnected) { disconnected.call }
126
+ subject.unbind
129
127
  end
130
128
 
131
129
  it 'can register a temporary handler based on stanza ID' do
132
130
  stanza = Blather::Stanza::Iq.new
133
- response = mock()
131
+ response = mock
134
132
  response.expects(:call)
135
- @client.register_tmp_handler(stanza.id) { |_| response.call }
136
- @client.receive_data stanza
133
+ subject.register_tmp_handler(stanza.id) { |_| response.call }
134
+ subject.receive_data stanza
137
135
  end
138
136
 
139
137
  it 'removes a tmp handler as soon as it is used' do
140
138
  stanza = Blather::Stanza::Iq.new
141
- response = mock()
139
+ response = mock
142
140
  response.expects(:call)
143
- @client.register_tmp_handler(stanza.id) { |_| response.call }
144
- @client.receive_data stanza
145
- @client.receive_data stanza
141
+ subject.register_tmp_handler(stanza.id) { |_| response.call }
142
+ subject.receive_data stanza
143
+ subject.receive_data stanza
146
144
  end
147
145
 
148
146
  it 'will create a handler then write the stanza' do
149
147
  stanza = Blather::Stanza::Iq.new
150
- response = mock()
148
+ response = mock
151
149
  response.expects(:call)
152
- @client.expects(:write).with do |s|
153
- @client.receive_data stanza
150
+ subject.expects(:write).with do |s|
151
+ subject.receive_data stanza
154
152
  s.should == stanza
155
153
  end
156
- @client.write_with_handler(stanza) { |_| response.call }
154
+ subject.write_with_handler(stanza) { |_| response.call }
157
155
  end
158
156
 
159
157
  it 'can register a handler' do
160
158
  stanza = Blather::Stanza::Iq.new
161
- response = mock()
159
+ response = mock
162
160
  response.expects(:call).times(2)
163
- @client.register_handler(:iq) { |_| response.call }
164
- @client.receive_data stanza
165
- @client.receive_data stanza
161
+ subject.register_handler(:iq) { |_| response.call }
162
+ subject.receive_data stanza
163
+ subject.receive_data stanza
166
164
  end
167
165
 
168
166
  it 'allows for breaking out of handlers' do
169
167
  stanza = Blather::Stanza::Iq.new
170
168
  response = mock(:iq => nil)
171
- @client.register_handler(:iq) do |_|
169
+ subject.register_handler(:iq) do |_|
172
170
  response.iq
173
171
  throw :halt
174
172
  response.fail
175
173
  end
176
- @client.receive_data stanza
174
+ subject.receive_data stanza
177
175
  end
178
176
 
179
177
  it 'allows for passing to the next handler of the same type' do
180
178
  stanza = Blather::Stanza::Iq.new
181
179
  response = mock(:iq1 => nil, :iq2 => nil)
182
- @client.register_handler(:iq) do |_|
180
+ subject.register_handler(:iq) do |_|
183
181
  response.iq1
184
182
  throw :pass
185
183
  response.fail
186
184
  end
187
- @client.register_handler(:iq) do |_|
185
+ subject.register_handler(:iq) do |_|
188
186
  response.iq2
189
187
  end
190
- @client.receive_data stanza
188
+ subject.receive_data stanza
191
189
  end
192
190
 
193
191
  it 'allows for passing to the next handler in the hierarchy' do
194
192
  stanza = Blather::Stanza::Iq::Query.new
195
193
  response = mock(:query => nil, :iq => nil)
196
- @client.register_handler(:query) do |_|
194
+ subject.register_handler(:query) do |_|
197
195
  response.query
198
196
  throw :pass
199
197
  response.fail
200
198
  end
201
- @client.register_handler(:iq) { |_| response.iq }
202
- @client.receive_data stanza
199
+ subject.register_handler(:iq) { |_| response.iq }
200
+ subject.receive_data stanza
203
201
  end
204
202
 
205
203
  it 'can clear handlers' do
@@ -209,479 +207,447 @@ describe Blather::Client do
209
207
  response = mock
210
208
  response.expects(:call).once
211
209
 
212
- @client.register_handler(:message, :chat?) { |_| response.call }
213
- @client.receive_data stanza
210
+ subject.register_handler(:message, :chat?) { |_| response.call }
211
+ subject.receive_data stanza
214
212
 
215
- @client.clear_handlers(:message, :chat?)
216
- @client.receive_data stanza
213
+ subject.clear_handlers :message, :chat?
214
+ subject.receive_data stanza
217
215
  end
218
- end
219
216
 
220
- describe 'Blather::Client#write' do
221
- before do
222
- @client = Blather::Client.new
217
+ describe '#write' do
218
+ it 'writes to the stream' do
219
+ stanza = Blather::Stanza::Iq.new
220
+ stream.expects(:send).with stanza
221
+ subject.setup 'me@me.com', 'me'
222
+ subject.post_init stream, Blather::JID.new('me.com')
223
+ subject.write stanza
224
+ end
223
225
  end
224
226
 
225
- it 'writes to the stream' do
226
- stanza = Blather::Stanza::Iq.new
227
- stream = mock()
228
- stream.expects(:send).with stanza
229
- @client.setup('me@me.com', 'me')
230
- @client.post_init stream, Blather::JID.new('me.com')
231
- @client.write stanza
232
- end
233
- end
227
+ describe '#status=' do
228
+ before do
229
+ subject.post_init stream, Blather::JID.new('n@d/r')
230
+ end
234
231
 
235
- describe 'Blather::Client#status=' do
236
- before do
237
- @client = Blather::Client.new
238
- @stream = mock()
239
- @stream.stubs(:send)
240
- @client.post_init @stream, Blather::JID.new('n@d/r')
241
- end
232
+ it 'updates the state when not sending to a Blather::JID' do
233
+ stream.stubs(:write)
234
+ subject.status.should_not equal :away
235
+ subject.status = :away, 'message'
236
+ subject.status.should == :away
237
+ end
242
238
 
243
- it 'updates the state when not sending to a Blather::JID' do
244
- @stream.stubs(:write)
245
- @client.status.should_not equal :away
246
- @client.status = :away, 'message'
247
- @client.status.should == :away
248
- end
239
+ it 'does not update the state when sending to a Blather::JID' do
240
+ stream.stubs(:write)
241
+ subject.status.should_not equal :away
242
+ subject.status = :away, 'message', 'me@me.com'
243
+ subject.status.should_not equal :away
244
+ end
249
245
 
250
- it 'does not update the state when sending to a Blather::JID' do
251
- @stream.stubs(:write)
252
- @client.status.should_not equal :away
253
- @client.status = :away, 'message', 'me@me.com'
254
- @client.status.should_not equal :away
246
+ it 'writes the new status to the stream' do
247
+ Blather::Stanza::Presence::Status.stubs(:next_id).returns 0
248
+ status = [:away, 'message']
249
+ stream.expects(:send).with do |s|
250
+ s.should be_kind_of Blather::Stanza::Presence::Status
251
+ s.to_s.should == Blather::Stanza::Presence::Status.new(*status).to_s
252
+ end
253
+ subject.status = status
254
+ end
255
255
  end
256
256
 
257
- it 'writes the new status to the stream' do
258
- Blather::Stanza::Presence::Status.stubs(:next_id).returns 0
259
- status = [:away, 'message']
260
- @stream.expects(:send).with do |s|
261
- s.should be_kind_of Blather::Stanza::Presence::Status
262
- s.to_s.should == Blather::Stanza::Presence::Status.new(*status).to_s
257
+ describe 'default handlers' do
258
+ it 're-raises errors' do
259
+ err = Blather::BlatherError.new
260
+ lambda { subject.receive_data err }.should raise_error Blather::BlatherError
263
261
  end
264
- @client.status = status
265
- end
266
- end
267
262
 
268
- describe 'Blather::Client default handlers' do
269
- before do
270
- @client = Blather::Client.new
271
- @stream = mock()
272
- @stream.stubs(:send)
273
- @client.post_init @stream, Blather::JID.new('n@d/r')
274
- end
275
-
276
- it 're-raises errors' do
277
- err = Blather::BlatherError.new
278
- lambda { @client.receive_data err }.should raise_error Blather::BlatherError
279
- end
280
-
281
- # it 'responds to iq:get with a "service-unavailable" error' do
282
- # get = Blather::Stanza::Iq.new :get
283
- # err = Blather::StanzaError.new(get, 'service-unavailable', :cancel).to_node
284
- # @client.expects(:write).with err
285
- # @client.receive_data get
286
- # end
287
-
288
- # it 'responds to iq:get with a "service-unavailable" error' do
289
- # get = Blather::Stanza::Iq.new :get
290
- # err = Blather::StanzaError.new(get, 'service-unavailable', :cancel).to_node
291
- # @client.expects(:write).with { |n| n.to_s.should == err.to_s }
292
- # @client.receive_data get
293
- # end
294
-
295
- # it 'responds to iq:set with a "service-unavailable" error' do
296
- # get = Blather::Stanza::Iq.new :set
297
- # err = Blather::StanzaError.new(get, 'service-unavailable', :cancel).to_node
298
- # @client.expects(:write).with { |n| n.to_s.should == err.to_s }
299
- # @client.receive_data get
300
- # end
301
-
302
- it 'responds to s2c pings with a pong' do
303
- ping = Blather::Stanza::Iq::Ping.new :get
304
- pong = ping.reply
305
- @client.expects(:write).with { |n| n.to_s.should == pong.to_s }
306
- @client.receive_data ping
307
- end
308
-
309
- it 'handles status changes by updating the roster if the status is from a Blather::JID in the roster' do
310
- jid = 'friend@jabber.local'
311
- status = Blather::Stanza::Presence::Status.new :away
312
- status.stubs(:from).returns jid
313
- roster_item = mock()
314
- roster_item.expects(:status=).with status
315
- @client.stubs(:roster).returns({status.from => roster_item})
316
- @client.receive_data status
317
- end
318
-
319
- it 'lets status stanzas fall through to other handlers' do
320
- jid = 'friend@jabber.local'
321
- status = Blather::Stanza::Presence::Status.new :away
322
- status.stubs(:from).returns jid
323
- roster_item = mock()
324
- roster_item.expects(:status=).with status
325
- @client.stubs(:roster).returns({status.from => roster_item})
326
-
327
- response = mock()
328
- response.expects(:call).with jid
329
- @client.register_handler(:status) { |s| response.call s.from.to_s }
330
- @client.receive_data status
331
- end
332
-
333
- it 'handles an incoming roster node by processing it through the roster' do
334
- roster = Blather::Stanza::Iq::Roster.new
335
- client_roster = mock()
336
- client_roster.expects(:process).with roster
337
- @client.stubs(:roster).returns client_roster
338
- @client.receive_data roster
339
- end
340
-
341
- it 'handles an incoming roster node by processing it through the roster' do
342
- roster = Blather::Stanza::Iq::Roster.new
343
- client_roster = mock()
344
- client_roster.expects(:process).with roster
345
- @client.stubs(:roster).returns client_roster
346
-
347
- response = mock()
348
- response.expects(:call)
349
- @client.register_handler(:roster) { |_| response.call }
350
- @client.receive_data roster
351
- end
352
- end
263
+ # it 'responds to iq:get with a "service-unavailable" error' do
264
+ # get = Blather::Stanza::Iq.new :get
265
+ # err = Blather::StanzaError.new(get, 'service-unavailable', :cancel).to_node
266
+ # subject.expects(:write).with err
267
+ # subject.receive_data get
268
+ # end
269
+
270
+ # it 'responds to iq:get with a "service-unavailable" error' do
271
+ # get = Blather::Stanza::Iq.new :get
272
+ # err = Blather::StanzaError.new(get, 'service-unavailable', :cancel).to_node
273
+ # subject.expects(:write).with { |n| n.to_s.should == err.to_s }
274
+ # subject.receive_data get
275
+ # end
276
+
277
+ # it 'responds to iq:set with a "service-unavailable" error' do
278
+ # get = Blather::Stanza::Iq.new :set
279
+ # err = Blather::StanzaError.new(get, 'service-unavailable', :cancel).to_node
280
+ # subject.expects(:write).with { |n| n.to_s.should == err.to_s }
281
+ # subject.receive_data get
282
+ # end
283
+
284
+ it 'responds to s2c pings with a pong' do
285
+ ping = Blather::Stanza::Iq::Ping.new :get
286
+ pong = ping.reply
287
+ subject.expects(:write).with { |n| n.to_s.should == pong.to_s }
288
+ subject.receive_data ping
289
+ end
353
290
 
354
- describe 'Blather::Client with a Component stream' do
355
- before do
356
- class MockComponent < Blather::Stream::Component; def initialize(); end; end
357
- @stream = MockComponent.new('')
358
- @stream.stubs(:send_data)
359
- @client = Blather::Client.new
360
- @client.setup('me.com', 'secret')
361
- end
291
+ it 'handles status changes by updating the roster if the status is from a Blather::JID in the roster' do
292
+ jid = 'friend@jabber.local'
293
+ status = Blather::Stanza::Presence::Status.new :away
294
+ status.stubs(:from).returns jid
295
+ roster_item = mock
296
+ roster_item.expects(:status=).with status
297
+ subject.stubs(:roster).returns({status.from => roster_item})
298
+ subject.receive_data status
299
+ end
362
300
 
363
- it 'calls the ready handler when sent post_init' do
364
- ready = mock()
365
- ready.expects(:call)
366
- @client.register_handler(:ready) { ready.call }
367
- @client.post_init @stream
368
- end
369
- end
301
+ it 'lets status stanzas fall through to other handlers' do
302
+ jid = 'friend@jabber.local'
303
+ status = Blather::Stanza::Presence::Status.new :away
304
+ status.stubs(:from).returns jid
305
+ roster_item = mock
306
+ roster_item.expects(:status=).with status
307
+ subject.stubs(:roster).returns({status.from => roster_item})
308
+
309
+ response = mock
310
+ response.expects(:call).with jid
311
+ subject.register_handler(:status) { |s| response.call s.from.to_s }
312
+ subject.receive_data status
313
+ end
370
314
 
371
- describe 'Blather::Client with a Client stream' do
372
- before do
373
- class MockClientStream < Blather::Stream::Client; def initialize(); end; end
374
- @stream = MockClientStream.new('')
375
- @client = Blather::Client.new
376
- Blather::Stream::Client.stubs(:start).returns @stream
377
- @client.setup('me@me.com', 'secret').run
378
- end
315
+ it 'handles an incoming roster node by processing it through the roster' do
316
+ roster = Blather::Stanza::Iq::Roster.new
317
+ client_roster = mock
318
+ client_roster.expects(:process).with roster
319
+ subject.stubs(:roster).returns client_roster
320
+ subject.receive_data roster
321
+ end
322
+
323
+ it 'handles an incoming roster node by processing it through the roster' do
324
+ roster = Blather::Stanza::Iq::Roster.new
325
+ client_roster = mock
326
+ client_roster.expects(:process).with roster
327
+ subject.stubs(:roster).returns client_roster
379
328
 
380
- it 'sends a request for the roster when post_init is called' do
381
- @stream.expects(:send).with { |stanza| stanza.should be_kind_of Blather::Stanza::Iq::Roster }
382
- @client.post_init @stream, Blather::JID.new('n@d/r')
329
+ response = mock
330
+ response.expects(:call)
331
+ subject.register_handler(:roster) { |_| response.call }
332
+ subject.receive_data roster
333
+ end
383
334
  end
384
335
 
385
- it 'calls the ready handler after post_init and roster is received' do
386
- result_roster = Blather::Stanza::Iq::Roster.new :result
387
- @stream.stubs(:send).with { |s| result_roster.id = s.id; @client.receive_data result_roster; true }
336
+ describe 'with a Component stream' do
337
+ before do
338
+ class MockComponent < Blather::Stream::Component; def initialize(); end; end
339
+ stream = MockComponent.new('')
340
+ stream.stubs(:send_data)
341
+ subject.setup 'me.com', 'secret'
342
+ end
388
343
 
389
- ready = mock()
390
- ready.expects(:call)
391
- @client.register_handler(:ready) { ready.call }
392
- @client.post_init @stream, Blather::JID.new('n@d/r')
344
+ it 'calls the ready handler when sent post_init' do
345
+ ready = mock
346
+ ready.expects(:call)
347
+ subject.register_handler(:ready) { ready.call }
348
+ subject.post_init stream
349
+ end
393
350
  end
394
- end
395
351
 
396
- describe 'Blather::Client filters' do
397
- before do
398
- @client = Blather::Client.new
399
- @stream = mock()
400
- @stream.stubs(:send)
401
- @client.post_init @stream, Blather::JID.new('n@d/r')
402
- end
352
+ describe 'with a Client stream' do
353
+ before do
354
+ class MockClientStream < Blather::Stream::Client; def initialize(); end; end
355
+ stream = MockClientStream.new('')
356
+ Blather::Stream::Client.stubs(:start).returns stream
357
+ subject.setup('me@me.com', 'secret').run
358
+ end
403
359
 
404
- it 'raises an error when an invalid filter type is registered' do
405
- lambda { @client.register_filter(:invalid) {} }.should raise_error RuntimeError
406
- end
360
+ it 'sends a request for the roster when post_init is called' do
361
+ stream.expects(:send).with { |stanza| stanza.should be_kind_of Blather::Stanza::Iq::Roster }
362
+ subject.post_init stream, Blather::JID.new('n@d/r')
363
+ end
407
364
 
408
- it 'can be guarded' do
409
- stanza = Blather::Stanza::Iq.new
410
- ready = mock()
411
- ready.expects(:call).once
412
- @client.register_filter(:before, :iq, :id => stanza.id) { |_| ready.call }
413
- @client.register_filter(:before, :iq, :id => 'not-id') { |_| ready.call }
414
- @client.receive_data stanza
365
+ it 'calls the ready handler after post_init and roster is received' do
366
+ result_roster = Blather::Stanza::Iq::Roster.new :result
367
+ stream.stubs(:send).with do |s|
368
+ result_roster.id = s.id
369
+ subject.receive_data result_roster
370
+ true
371
+ end
372
+
373
+ ready = mock
374
+ ready.expects(:call)
375
+ subject.register_handler(:ready) { ready.call }
376
+ subject.post_init stream, Blather::JID.new('n@d/r')
377
+ end
415
378
  end
416
379
 
417
- it 'can pass to the next handler' do
418
- stanza = Blather::Stanza::Iq.new
419
- ready = mock()
420
- ready.expects(:call).once
421
- @client.register_filter(:before) { |_| throw :pass; ready.call }
422
- @client.register_filter(:before) { |_| ready.call }
423
- @client.receive_data stanza
424
- end
380
+ describe 'filters' do
381
+ it 'raises an error when an invalid filter type is registered' do
382
+ lambda { subject.register_filter(:invalid) {} }.should raise_error RuntimeError
383
+ end
425
384
 
426
- it 'runs them in order' do
427
- stanza = Blather::Stanza::Iq.new
428
- count = 0
429
- @client.register_filter(:before) { |_| count.should == 0; count = 1 }
430
- @client.register_filter(:before) { |_| count.should == 1; count = 2 }
431
- @client.register_handler(:iq) { |_| count.should == 2; count = 3 }
432
- @client.register_filter(:after) { |_| count.should == 3; count = 4 }
433
- @client.register_filter(:after) { |_| count.should == 4 }
434
- @client.receive_data stanza
435
- end
385
+ it 'can be guarded' do
386
+ stanza = Blather::Stanza::Iq.new
387
+ ready = mock
388
+ ready.expects(:call).once
389
+ subject.register_filter(:before, :iq, :id => stanza.id) { |_| ready.call }
390
+ subject.register_filter(:before, :iq, :id => 'not-id') { |_| ready.call }
391
+ subject.receive_data stanza
392
+ end
436
393
 
437
- it 'can modify the stanza' do
438
- stanza = Blather::Stanza::Iq.new
439
- stanza.from = 'from@test.local'
440
- new_jid = 'before@filter.local'
441
- ready = mock()
442
- ready.expects(:call).with new_jid
443
- @client.register_filter(:before) { |s| s.from = new_jid }
444
- @client.register_handler(:iq) { |s| ready.call s.from.to_s }
445
- @client.receive_data stanza
446
- end
394
+ it 'can pass to the next handler' do
395
+ stanza = Blather::Stanza::Iq.new
396
+ ready = mock
397
+ ready.expects(:call).once
398
+ subject.register_filter(:before) { |_| throw :pass; ready.call }
399
+ subject.register_filter(:before) { |_| ready.call }
400
+ subject.receive_data stanza
401
+ end
447
402
 
448
- it 'can halt the handler chain' do
449
- stanza = Blather::Stanza::Iq.new
450
- ready = mock()
451
- ready.expects(:call).never
452
- @client.register_filter(:before) { |_| throw :halt }
453
- @client.register_handler(:iq) { |_| ready.call }
454
- @client.receive_data stanza
455
- end
403
+ it 'runs them in order' do
404
+ stanza = Blather::Stanza::Iq.new
405
+ count = 0
406
+ subject.register_filter(:before) { |_| count.should == 0; count = 1 }
407
+ subject.register_filter(:before) { |_| count.should == 1; count = 2 }
408
+ subject.register_handler(:iq) { |_| count.should == 2; count = 3 }
409
+ subject.register_filter(:after) { |_| count.should == 3; count = 4 }
410
+ subject.register_filter(:after) { |_| count.should == 4 }
411
+ subject.receive_data stanza
412
+ end
456
413
 
457
- it 'can be specific to a handler' do
458
- stanza = Blather::Stanza::Iq.new
459
- ready = mock()
460
- ready.expects(:call).once
461
- @client.register_filter(:before, :iq) { |_| ready.call }
462
- @client.register_filter(:before, :message) { |_| ready.call }
463
- @client.receive_data stanza
464
- end
465
- end
414
+ it 'can modify the stanza' do
415
+ stanza = Blather::Stanza::Iq.new
416
+ stanza.from = 'from@test.local'
417
+ new_jid = 'before@filter.local'
418
+ ready = mock
419
+ ready.expects(:call).with new_jid
420
+ subject.register_filter(:before) { |s| s.from = new_jid }
421
+ subject.register_handler(:iq) { |s| ready.call s.from.to_s }
422
+ subject.receive_data stanza
423
+ end
466
424
 
467
- describe 'Blather::Client guards' do
468
- before do
469
- stream = mock()
470
- stream.stubs(:send)
471
- @client = Blather::Client.new
472
- @client.post_init stream, Blather::JID.new('n@d/r')
473
- @stanza = Blather::Stanza::Iq.new
474
- @response = mock()
425
+ it 'can halt the handler chain' do
426
+ stanza = Blather::Stanza::Iq.new
427
+ ready = mock
428
+ ready.expects(:call).never
429
+ subject.register_filter(:before) { |_| throw :halt }
430
+ subject.register_handler(:iq) { |_| ready.call }
431
+ subject.receive_data stanza
432
+ end
433
+
434
+ it 'can be specific to a handler' do
435
+ stanza = Blather::Stanza::Iq.new
436
+ ready = mock
437
+ ready.expects(:call).once
438
+ subject.register_filter(:before, :iq) { |_| ready.call }
439
+ subject.register_filter(:before, :message) { |_| ready.call }
440
+ subject.receive_data stanza
441
+ end
475
442
  end
476
443
 
477
- it 'can be a symbol' do
478
- @response.expects :call
479
- @client.register_handler(:iq, :chat?) { |_| @response.call }
444
+ describe 'guards' do
445
+ let(:stanza) { Blather::Stanza::Iq.new }
446
+ let(:response) { mock }
480
447
 
481
- @stanza.expects(:chat?).returns true
482
- @client.receive_data @stanza
448
+ it 'can be a symbol' do
449
+ response.expects :call
450
+ subject.register_handler(:iq, :chat?) { |_| response.call }
483
451
 
484
- @stanza.expects(:chat?).returns false
485
- @client.receive_data @stanza
486
- end
452
+ stanza.expects(:chat?).returns true
453
+ subject.receive_data stanza
487
454
 
488
- it 'can be a hash with string match' do
489
- @response.expects :call
490
- @client.register_handler(:iq, :body => 'exit') { |_| @response.call }
455
+ stanza.expects(:chat?).returns false
456
+ subject.receive_data stanza
457
+ end
491
458
 
492
- @stanza.expects(:body).returns 'exit'
493
- @client.receive_data @stanza
459
+ it 'can be a hash with string match' do
460
+ response.expects :call
461
+ subject.register_handler(:iq, :body => 'exit') { |_| response.call }
494
462
 
495
- @stanza.expects(:body).returns 'not-exit'
496
- @client.receive_data @stanza
497
- end
463
+ stanza.expects(:body).returns 'exit'
464
+ subject.receive_data stanza
498
465
 
499
- it 'can be a hash with a value' do
500
- @response.expects :call
501
- @client.register_handler(:iq, :number => 0) { |_| @response.call }
466
+ stanza.expects(:body).returns 'not-exit'
467
+ subject.receive_data stanza
468
+ end
502
469
 
503
- @stanza.expects(:number).returns 0
504
- @client.receive_data @stanza
470
+ it 'can be a hash with a value' do
471
+ response.expects :call
472
+ subject.register_handler(:iq, :number => 0) { |_| response.call }
505
473
 
506
- @stanza.expects(:number).returns 1
507
- @client.receive_data @stanza
508
- end
474
+ stanza.expects(:number).returns 0
475
+ subject.receive_data stanza
509
476
 
510
- it 'can be a hash with a regexp' do
511
- @response.expects :call
512
- @client.register_handler(:iq, :body => /exit/) { |_| @response.call }
477
+ stanza.expects(:number).returns 1
478
+ subject.receive_data stanza
479
+ end
513
480
 
514
- @stanza.expects(:body).returns 'more than just exit, but exit still'
515
- @client.receive_data @stanza
481
+ it 'can be a hash with a regexp' do
482
+ response.expects :call
483
+ subject.register_handler(:iq, :body => /exit/) { |_| response.call }
516
484
 
517
- @stanza.expects(:body).returns 'keyword not found'
518
- @client.receive_data @stanza
485
+ stanza.expects(:body).returns 'more than just exit, but exit still'
486
+ subject.receive_data stanza
519
487
 
520
- @stanza.expects(:body).returns nil
521
- @client.receive_data @stanza
522
- end
488
+ stanza.expects(:body).returns 'keyword not found'
489
+ subject.receive_data stanza
523
490
 
524
- it 'can be a hash with an array' do
525
- @response.expects(:call).times(2)
526
- @client.register_handler(:iq, :type => [:result, :error]) { |_| @response.call }
491
+ stanza.expects(:body).returns nil
492
+ subject.receive_data stanza
493
+ end
527
494
 
528
- stanza = Blather::Stanza::Iq.new
529
- stanza.expects(:type).at_least_once.returns :result
530
- @client.receive_data stanza
495
+ it 'can be a hash with an array' do
496
+ response.expects(:call).times(2)
497
+ subject.register_handler(:iq, :type => [:result, :error]) { |_| response.call }
531
498
 
532
- stanza = Blather::Stanza::Iq.new
533
- stanza.expects(:type).at_least_once.returns :error
534
- @client.receive_data stanza
499
+ stanza = Blather::Stanza::Iq.new
500
+ stanza.expects(:type).at_least_once.returns :result
501
+ subject.receive_data stanza
535
502
 
536
- stanza = Blather::Stanza::Iq.new
537
- stanza.expects(:type).at_least_once.returns :get
538
- @client.receive_data stanza
539
- end
503
+ stanza = Blather::Stanza::Iq.new
504
+ stanza.expects(:type).at_least_once.returns :error
505
+ subject.receive_data stanza
540
506
 
541
- it 'chained are treated like andand (short circuited)' do
542
- @response.expects :call
543
- @client.register_handler(:iq, :type => :get, :body => 'test') { |_| @response.call }
507
+ stanza = Blather::Stanza::Iq.new
508
+ stanza.expects(:type).at_least_once.returns :get
509
+ subject.receive_data stanza
510
+ end
544
511
 
545
- stanza = Blather::Stanza::Iq.new
546
- stanza.expects(:type).at_least_once.returns :get
547
- stanza.expects(:body).returns 'test'
548
- @client.receive_data stanza
512
+ it 'chained are treated like andand (short circuited)' do
513
+ response.expects :call
514
+ subject.register_handler(:iq, :type => :get, :body => 'test') { |_| response.call }
549
515
 
550
- stanza = Blather::Stanza::Iq.new
551
- stanza.expects(:type).at_least_once.returns :set
552
- stanza.expects(:body).never
553
- @client.receive_data stanza
554
- end
516
+ stanza = Blather::Stanza::Iq.new
517
+ stanza.expects(:type).at_least_once.returns :get
518
+ stanza.expects(:body).returns 'test'
519
+ subject.receive_data stanza
555
520
 
556
- it 'within an Array are treated as oror (short circuited)' do
557
- @response.expects(:call).times 2
558
- @client.register_handler(:iq, [{:type => :get}, {:body => 'test'}]) { |_| @response.call }
521
+ stanza = Blather::Stanza::Iq.new
522
+ stanza.expects(:type).at_least_once.returns :set
523
+ stanza.expects(:body).never
524
+ subject.receive_data stanza
525
+ end
559
526
 
560
- stanza = Blather::Stanza::Iq.new
561
- stanza.expects(:type).at_least_once.returns :set
562
- stanza.expects(:body).returns 'test'
563
- @client.receive_data stanza
527
+ it 'within an Array are treated as oror (short circuited)' do
528
+ response.expects(:call).times 2
529
+ subject.register_handler(:iq, [{:type => :get}, {:body => 'test'}]) { |_| response.call }
564
530
 
565
- stanza = Blather::Stanza::Iq.new
566
- stanza.stubs(:type).at_least_once.returns :get
567
- stanza.expects(:body).never
568
- @client.receive_data stanza
569
- end
531
+ stanza = Blather::Stanza::Iq.new
532
+ stanza.expects(:type).at_least_once.returns :set
533
+ stanza.expects(:body).returns 'test'
534
+ subject.receive_data stanza
570
535
 
571
- it 'can be a lambda' do
572
- @response.expects :call
573
- @client.register_handler(:iq, lambda { |s| s.number % 3 == 0 }) { |_| @response.call }
536
+ stanza = Blather::Stanza::Iq.new
537
+ stanza.stubs(:type).at_least_once.returns :get
538
+ stanza.expects(:body).never
539
+ subject.receive_data stanza
540
+ end
574
541
 
575
- @stanza.expects(:number).at_least_once.returns 3
576
- @client.receive_data @stanza
542
+ it 'can be a lambda' do
543
+ response.expects :call
544
+ subject.register_handler(:iq, lambda { |s| s.number % 3 == 0 }) { |_| response.call }
577
545
 
578
- @stanza.expects(:number).at_least_once.returns 2
579
- @client.receive_data @stanza
580
- end
546
+ stanza.expects(:number).at_least_once.returns 3
547
+ subject.receive_data stanza
581
548
 
582
- it 'can be an xpath and will send the result to the handler' do
583
- @response.expects(:call).with do |stanza, xpath|
584
- xpath.should be_instance_of Nokogiri::XML::NodeSet
585
- xpath.should_not be_empty
586
- stanza.should == @stanza
549
+ stanza.expects(:number).at_least_once.returns 2
550
+ subject.receive_data stanza
587
551
  end
588
- @client.register_handler(:iq, "/iq[@id='#{@stanza.id}']") { |stanza, xpath| @response.call stanza, xpath }
589
- @client.receive_data @stanza
590
- end
591
552
 
592
- it 'can be an xpath with namespaces and will send the result to the handler' do
593
- @stanza = Blather::Stanza.parse('<message><foo xmlns="http://bar.com"></message>')
594
- @response.expects(:call).with do |stanza, xpath|
595
- xpath.should be_instance_of Nokogiri::XML::NodeSet
596
- xpath.should_not be_empty
597
- stanza.should == @stanza
553
+ it 'can be an xpath and will send the result to the handler' do
554
+ response.expects(:call).with do |stanza, xpath|
555
+ xpath.should be_instance_of Nokogiri::XML::NodeSet
556
+ xpath.should_not be_empty
557
+ stanza.should == stanza
558
+ end
559
+ subject.register_handler(:iq, "/iq[@id='#{stanza.id}']") { |stanza, xpath| response.call stanza, xpath }
560
+ subject.receive_data stanza
561
+ end
562
+
563
+ it 'can be an xpath with namespaces and will send the result to the handler' do
564
+ stanza = Blather::Stanza.parse('<message><foo xmlns="http://bar.com"></message>')
565
+ response.expects(:call).with do |stanza, xpath|
566
+ xpath.should be_instance_of Nokogiri::XML::NodeSet
567
+ xpath.should_not be_empty
568
+ stanza.should == stanza
569
+ end
570
+ subject.register_handler(:message, "/message/bar:foo", :bar => 'http://bar.com') { |stanza, xpath| response.call stanza, xpath }
571
+ subject.receive_data stanza
598
572
  end
599
- @client.register_handler(:message, "/message/bar:foo", :bar => 'http://bar.com') { |stanza, xpath| @response.call stanza, xpath }
600
- @client.receive_data @stanza
601
- end
602
573
 
603
- it 'raises an error when a bad guard is tried' do
604
- lambda { @client.register_handler(:iq, 0) {} }.should raise_error RuntimeError
574
+ it 'raises an error when a bad guard is tried' do
575
+ lambda { subject.register_handler(:iq, 0) {} }.should raise_error RuntimeError
576
+ end
605
577
  end
606
- end
607
578
 
608
- describe 'Blather::Client::Caps' do
609
- before do
610
- @client = Blather::Client.new
611
- @stream = mock()
612
- @stream.stubs(:send)
613
- @client.post_init @stream, Blather::JID.new('n@d/r')
614
- @caps = @client.caps
615
- end
616
-
617
- it 'must be of type result' do
618
- @caps.should respond_to :type
619
- @caps.type.should == :result
620
- end
621
-
622
- it 'can have a client node set' do
623
- @caps.should respond_to :node=
624
- @caps.node = "somenode"
625
- end
626
-
627
- it 'provides a client node reader' do
628
- @caps.should respond_to :node
629
- @caps.node = "somenode"
630
- @caps.node.should == "somenode##{@caps.ver}"
631
- end
632
-
633
- it 'can have identities set' do
634
- @caps.should respond_to :identities=
635
- @caps.identities = [{:name => "name", :type => "type", :category => "cat"}]
636
- end
637
-
638
- it 'provides an identities reader' do
639
- @caps.should respond_to :identities
640
- @caps.identities = [{:name => "name", :type => "type", :category => "cat"}]
641
- @caps.identities.should == [Blather::Stanza::Iq::DiscoInfo::Identity.new({:name => "name", :type => "type", :category => "cat"})]
642
- end
643
-
644
- it 'can have features set' do
645
- @caps.should respond_to :features=
646
- @caps.features.size.should == 0
647
- @caps.features = ["feature1"]
648
- @caps.features.size.should == 1
649
- @caps.features += [Blather::Stanza::Iq::DiscoInfo::Feature.new("feature2")]
650
- @caps.features.size.should == 2
651
- @caps.features = nil
652
- @caps.features.size.should == 0
653
- end
654
-
655
- it 'provides a features reader' do
656
- @caps.should respond_to :features
657
- @caps.features = %w{feature1 feature2}
658
- @caps.features.should == [Blather::Stanza::Iq::DiscoInfo::Feature.new("feature1"), Blather::Stanza::Iq::DiscoInfo::Feature.new("feature2")]
659
- end
660
-
661
- it 'provides a client ver reader' do
662
- @caps.should respond_to :ver
663
- @caps.node = 'http://code.google.com/p/exodus'
664
- @caps.identities = [Blather::Stanza::Iq::DiscoInfo::Identity.new({:name => 'Exodus 0.9.1', :type => 'pc', :category => 'client'})]
665
- @caps.features = %w{
666
- http://jabber.org/protocol/caps
667
- http://jabber.org/protocol/disco#info
668
- http://jabber.org/protocol/disco#items
669
- http://jabber.org/protocol/muc
670
- }
671
- @caps.ver.should == 'QgayPKawpkPSDYmwT/WM94uAlu0='
672
- @caps.node.should == "http://code.google.com/p/exodus#QgayPKawpkPSDYmwT/WM94uAlu0="
673
- end
674
-
675
- it 'can construct caps presence correctly' do
676
- @caps.should respond_to :c
677
- @caps.node = 'http://code.google.com/p/exodus'
678
- @caps.identities = [Blather::Stanza::Iq::DiscoInfo::Identity.new({:name => 'Exodus 0.9.1', :type => 'pc', :category => 'client'})]
679
- @caps.features = %w{
680
- http://jabber.org/protocol/caps
681
- http://jabber.org/protocol/disco#info
682
- http://jabber.org/protocol/disco#items
683
- http://jabber.org/protocol/muc
684
- }
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
579
+ describe '#caps' do
580
+ let(:caps) { subject.caps }
581
+
582
+ it 'must be of type result' do
583
+ caps.should respond_to :type
584
+ caps.type.should == :result
585
+ end
586
+
587
+ it 'can have a client node set' do
588
+ caps.should respond_to :node=
589
+ caps.node = "somenode"
590
+ end
591
+
592
+ it 'provides a client node reader' do
593
+ caps.should respond_to :node
594
+ caps.node = "somenode"
595
+ caps.node.should == "somenode##{caps.ver}"
596
+ end
597
+
598
+ it 'can have identities set' do
599
+ caps.should respond_to :identities=
600
+ caps.identities = [{:name => "name", :type => "type", :category => "cat"}]
601
+ end
602
+
603
+ it 'provides an identities reader' do
604
+ caps.should respond_to :identities
605
+ caps.identities = [{:name => "name", :type => "type", :category => "cat"}]
606
+ caps.identities.should == [Blather::Stanza::Iq::DiscoInfo::Identity.new({:name => "name", :type => "type", :category => "cat"})]
607
+ end
608
+
609
+ it 'can have features set' do
610
+ caps.should respond_to :features=
611
+ caps.features.size.should == 0
612
+ caps.features = ["feature1"]
613
+ caps.features.size.should == 1
614
+ caps.features += [Blather::Stanza::Iq::DiscoInfo::Feature.new("feature2")]
615
+ caps.features.size.should == 2
616
+ caps.features = nil
617
+ caps.features.size.should == 0
618
+ end
619
+
620
+ it 'provides a features reader' do
621
+ caps.should respond_to :features
622
+ caps.features = %w{feature1 feature2}
623
+ caps.features.should == [Blather::Stanza::Iq::DiscoInfo::Feature.new("feature1"), Blather::Stanza::Iq::DiscoInfo::Feature.new("feature2")]
624
+ end
625
+
626
+ it 'provides a client ver reader' do
627
+ caps.should respond_to :ver
628
+ caps.node = 'http://code.google.com/p/exodus'
629
+ caps.identities = [Blather::Stanza::Iq::DiscoInfo::Identity.new({:name => 'Exodus 0.9.1', :type => 'pc', :category => 'client'})]
630
+ caps.features = %w{
631
+ http://jabber.org/protocol/caps
632
+ http://jabber.org/protocol/disco#info
633
+ http://jabber.org/protocol/disco#items
634
+ http://jabber.org/protocol/muc
635
+ }
636
+ caps.ver.should == 'QgayPKawpkPSDYmwT/WM94uAlu0='
637
+ caps.node.should == "http://code.google.com/p/exodus#QgayPKawpkPSDYmwT/WM94uAlu0="
638
+ end
639
+
640
+ it 'can construct caps presence correctly' do
641
+ caps.should respond_to :c
642
+ caps.node = 'http://code.google.com/p/exodus'
643
+ caps.identities = [Blather::Stanza::Iq::DiscoInfo::Identity.new({:name => 'Exodus 0.9.1', :type => 'pc', :category => 'client'})]
644
+ caps.features = %w{
645
+ http://jabber.org/protocol/caps
646
+ http://jabber.org/protocol/disco#info
647
+ http://jabber.org/protocol/disco#items
648
+ http://jabber.org/protocol/muc
649
+ }
650
+ 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
651
+ end
686
652
  end
687
653
  end