blather 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
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