sprsquish-blather 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +17 -2
- data/Rakefile +1 -1
- data/examples/ping_pong.rb +37 -0
- data/lib/blather.rb +1 -4
- data/lib/blather/client.rb +75 -3
- data/lib/blather/client/client.rb +67 -53
- data/lib/blather/client/dsl.rb +13 -18
- data/lib/blather/stanza/disco/disco_info.rb +0 -12
- data/lib/blather/stanza/disco/disco_items.rb +0 -7
- data/lib/blather/stream.rb +4 -4
- data/lib/blather/stream/component.rb +1 -1
- data/spec/blather/client/client_spec.rb +389 -0
- data/spec/blather/client/dsl_spec.rb +105 -0
- data/spec/blather/stream/client_spec.rb +18 -18
- data/spec/blather/stream/component_spec.rb +3 -3
- data/spec/spec_helper.rb +4 -1
- metadata +6 -3
data/README.rdoc
CHANGED
@@ -60,7 +60,7 @@ Guards act like AND statements. Each condition must be met if the handler is to
|
|
60
60
|
# Equivalent to saying (stanza.chat? && stanza.body)
|
61
61
|
message :chat?, :body
|
62
62
|
|
63
|
-
|
63
|
+
The different types of guards are:
|
64
64
|
|
65
65
|
# Symbol
|
66
66
|
# Checks for a non-false reply to calling the symbol on the stanza
|
@@ -93,9 +93,24 @@ There are 5 different types of guards:
|
|
93
93
|
# Equivalent to stanza.body == 'foo' || stanza.body == 'baz'
|
94
94
|
message [{:body => 'foo'}, {:body => 'baz'}]
|
95
95
|
|
96
|
+
== On the Command Line:
|
97
|
+
|
98
|
+
Default usage is:
|
99
|
+
|
100
|
+
[blather_script] [options] node@domain.com/resource password [host] [port]
|
101
|
+
|
102
|
+
Command line options:
|
103
|
+
|
104
|
+
-D, --debug Run in debug mode (you will see all XMPP communication)
|
105
|
+
-d, --daemonize Daemonize the process
|
106
|
+
--pid=[PID] Write the PID to this file
|
107
|
+
--log=[LOG] Write to the [LOG] file instead of stdout/stderr
|
108
|
+
-h, --help Show this message
|
109
|
+
-v, --version Show version
|
110
|
+
|
111
|
+
|
96
112
|
= TODO
|
97
113
|
|
98
|
-
* Better Documentation
|
99
114
|
* Add XPath guard that passes the result to the handler
|
100
115
|
* Add Disco the the DSL
|
101
116
|
* PubSub (XEP-0060: http://xmpp.org/extensions/xep-0060.html)
|
data/Rakefile
CHANGED
@@ -16,7 +16,7 @@ begin
|
|
16
16
|
gem.extensions = ['Rakefile']
|
17
17
|
|
18
18
|
gem.add_dependency 'eventmachine', '>= 0.12.6'
|
19
|
-
gem.add_dependency 'libxml-ruby', '>= 1.1.
|
19
|
+
gem.add_dependency 'libxml-ruby', '>= 1.1.2'
|
20
20
|
|
21
21
|
gem.files = FileList['examples/**/*', 'lib/**/*', 'ext/*.{rb,c}'].to_a
|
22
22
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'blather/client/dsl'
|
2
|
+
$stdout.sync = true
|
3
|
+
|
4
|
+
module Ping
|
5
|
+
extend Blather::DSL
|
6
|
+
def self.run; client.run; end
|
7
|
+
|
8
|
+
setup 'echo@jabber.local/ping', 'echo'
|
9
|
+
|
10
|
+
status :from => Blather::JID.new('echo@jabber.local/pong') do |s|
|
11
|
+
puts "serve!"
|
12
|
+
say s.from, 'ping'
|
13
|
+
end
|
14
|
+
|
15
|
+
message :chat?, :body => 'pong' do |m|
|
16
|
+
puts "ping!"
|
17
|
+
say m.from, 'ping'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Pong
|
22
|
+
extend Blather::DSL
|
23
|
+
def self.run; client.run; end
|
24
|
+
|
25
|
+
setup 'echo@jabber.local/pong', 'echo'
|
26
|
+
message :chat?, :body => 'ping' do |m|
|
27
|
+
puts "pong!"
|
28
|
+
say m.from, 'pong'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
trap(:INT) { EM.stop }
|
33
|
+
trap(:TERM) { EM.stop }
|
34
|
+
EM.run do
|
35
|
+
Ping.run
|
36
|
+
Pong.run
|
37
|
+
end
|
data/lib/blather.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__)
|
2
|
-
$:.unshift File.join(File.dirname(__FILE__), '..')
|
3
|
-
|
4
1
|
# Require the necessary files
|
5
2
|
%w[
|
6
3
|
rubygems
|
@@ -48,6 +45,6 @@ $:.unshift File.join(File.dirname(__FILE__), '..')
|
|
48
45
|
XML.indent_tree_output = false
|
49
46
|
|
50
47
|
module Blather
|
51
|
-
LOG = Logger.new(
|
48
|
+
LOG = Logger.new($stdout) unless const_defined?(:LOG)
|
52
49
|
LOG.level = Logger::INFO
|
53
50
|
end
|
data/lib/blather/client.rb
CHANGED
@@ -1,13 +1,85 @@
|
|
1
|
+
require 'optparse'
|
1
2
|
require File.join(File.dirname(__FILE__), *%w[client dsl])
|
2
3
|
|
3
4
|
include Blather::DSL
|
4
5
|
|
6
|
+
options = {}
|
7
|
+
optparse = OptionParser.new do |opts|
|
8
|
+
opts.banner = "Run with #{$0} [options] user@server/resource password [host] [port]"
|
9
|
+
|
10
|
+
opts.on('-D', '--debug', 'Run in debug mode (you will see all XMPP communication)') do |debug|
|
11
|
+
options[:debug] = debug
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on('-d', '--daemonize', 'Daemonize the process') do |daemonize|
|
15
|
+
options[:daemonize] = daemonize
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.on('--pid=[PID]', 'Write the PID to this file') do |pid|
|
19
|
+
if !File.writable?(File.dirname(pid))
|
20
|
+
$stderr.puts "Unable to write log file to #{pid}"
|
21
|
+
exit 1
|
22
|
+
end
|
23
|
+
options[:pid] = pid
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on('--log=[LOG]', 'Write to the [LOG] file instead of stdout/stderr') do |log|
|
27
|
+
if !File.writable?(File.dirname(log))
|
28
|
+
$stderr.puts "Unable to write log file to #{log}"
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
options[:log] = log
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
35
|
+
puts opts
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on_tail('-v', '--version', 'Show version') do
|
40
|
+
require 'yaml'
|
41
|
+
version = YAML.load_file File.join(File.dirname(__FILE__), %w[.. .. VERSION.yml])
|
42
|
+
puts "Blather v#{version[:major]}.#{version[:minor]}.#{version[:patch]}"
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
end
|
46
|
+
optparse.parse!
|
47
|
+
|
5
48
|
at_exit do
|
6
49
|
unless client.setup?
|
7
50
|
if ARGV.length < 2
|
8
|
-
puts
|
9
|
-
|
10
|
-
|
51
|
+
puts optparse
|
52
|
+
exit 1
|
53
|
+
end
|
54
|
+
client.setup(*ARGV)
|
55
|
+
end
|
56
|
+
|
57
|
+
def run(options)
|
58
|
+
$stdin.reopen "/dev/null"
|
59
|
+
|
60
|
+
if options[:log]
|
61
|
+
log = File.new(options[:log], 'a')
|
62
|
+
log.sync = options[:debug]
|
63
|
+
Blather::LOG.level = Logger::DEBUG if options[:debug]
|
64
|
+
$stdout.reopen log
|
65
|
+
$stderr.reopen $stdout
|
66
|
+
end
|
67
|
+
trap(:INT) { EM.stop }
|
68
|
+
trap(:TERM) { EM.stop }
|
69
|
+
EM.run { client.run }
|
70
|
+
end
|
71
|
+
|
72
|
+
if options[:daemonize]
|
73
|
+
pid = fork do
|
74
|
+
Process.setsid
|
75
|
+
exit if fork
|
76
|
+
File.open(options[:pid], 'w') { |f| f << Process.pid } if options[:pid]
|
77
|
+
run options
|
78
|
+
FileUtils.rm(options[:pid]) if options[:pid]
|
11
79
|
end
|
80
|
+
::Process.detach pid
|
81
|
+
exit
|
82
|
+
else
|
83
|
+
run options
|
12
84
|
end
|
13
85
|
end
|
@@ -3,8 +3,8 @@ require File.join(File.dirname(__FILE__), *%w[.. .. blather])
|
|
3
3
|
module Blather #:nodoc:
|
4
4
|
|
5
5
|
class Client #:nodoc:
|
6
|
-
|
7
|
-
|
6
|
+
attr_reader :jid,
|
7
|
+
:roster
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
@state = :initializing
|
@@ -17,6 +17,24 @@ module Blather #:nodoc:
|
|
17
17
|
setup_initial_handlers
|
18
18
|
end
|
19
19
|
|
20
|
+
def jid=(new_jid)
|
21
|
+
@jid = JID.new new_jid
|
22
|
+
end
|
23
|
+
|
24
|
+
def status
|
25
|
+
@status.state
|
26
|
+
end
|
27
|
+
|
28
|
+
def status=(state)
|
29
|
+
state, msg, to = state
|
30
|
+
|
31
|
+
status = Stanza::Presence::Status.new state, msg
|
32
|
+
status.to = to
|
33
|
+
@status = status unless to
|
34
|
+
|
35
|
+
write status
|
36
|
+
end
|
37
|
+
|
20
38
|
def setup?
|
21
39
|
@setup.is_a? Array
|
22
40
|
end
|
@@ -30,11 +48,8 @@ module Blather #:nodoc:
|
|
30
48
|
|
31
49
|
def run
|
32
50
|
raise 'not setup!' unless setup?
|
33
|
-
|
34
|
-
|
35
|
-
klass = @setup[0].node ? Blather::Stream::Client : Blather::Stream::Component
|
36
|
-
klass.start self, *@setup
|
37
|
-
}
|
51
|
+
klass = @setup[0].node ? Blather::Stream::Client : Blather::Stream::Component
|
52
|
+
@stream = klass.start self, *@setup
|
38
53
|
end
|
39
54
|
|
40
55
|
def register_tmp_handler(id, &handler)
|
@@ -42,62 +57,38 @@ module Blather #:nodoc:
|
|
42
57
|
end
|
43
58
|
|
44
59
|
def register_handler(type, *guards, &handler)
|
60
|
+
check_guards guards
|
45
61
|
@handlers[type] ||= []
|
46
62
|
@handlers[type] << [guards, handler]
|
47
63
|
end
|
48
64
|
|
49
|
-
def status
|
50
|
-
@status.state
|
51
|
-
end
|
52
|
-
|
53
|
-
def status=(state)
|
54
|
-
state, msg, to = state
|
55
|
-
|
56
|
-
status = Stanza::Presence::Status.new state, msg
|
57
|
-
status.to = to
|
58
|
-
@status = status unless to
|
59
|
-
|
60
|
-
write status
|
61
|
-
end
|
62
|
-
|
63
65
|
def write(stanza)
|
64
66
|
stanza.from ||= jid if stanza.respond_to?(:from)
|
65
67
|
@stream.send(stanza) if @stream
|
66
68
|
end
|
67
69
|
|
68
|
-
def write_with_handler(stanza, &
|
70
|
+
def write_with_handler(stanza, &handler)
|
69
71
|
register_tmp_handler stanza.id, &handler
|
70
72
|
write stanza
|
71
73
|
end
|
72
74
|
|
73
|
-
def
|
74
|
-
@stream
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
@state = :ready
|
79
|
-
call_handler_for :ready, nil
|
80
|
-
else
|
81
|
-
r = Stanza::Iq::Roster.new
|
82
|
-
register_tmp_handler r.id do |node|
|
83
|
-
roster.process node
|
84
|
-
@state = :ready
|
85
|
-
write @status
|
86
|
-
call_handler_for :ready, nil
|
87
|
-
end
|
88
|
-
write r
|
75
|
+
def post_init
|
76
|
+
case @stream
|
77
|
+
when Stream::Component then ready!
|
78
|
+
when Stream::Client then client_post_init
|
79
|
+
else raise "Don't know #{@stream.class} stream type. How the hell did this happen!?"
|
89
80
|
end
|
90
81
|
end
|
91
82
|
|
92
|
-
def
|
83
|
+
def close
|
93
84
|
@stream.close_connection_after_writing
|
94
85
|
end
|
95
86
|
|
96
|
-
def
|
97
|
-
EM.stop
|
87
|
+
def unbind
|
88
|
+
EM.stop if EM.reactor_running?
|
98
89
|
end
|
99
90
|
|
100
|
-
def
|
91
|
+
def receive_data(stanza)
|
101
92
|
if handler = @tmp_handlers.delete(stanza.id)
|
102
93
|
handler.call stanza
|
103
94
|
else
|
@@ -107,21 +98,14 @@ module Blather #:nodoc:
|
|
107
98
|
end
|
108
99
|
end
|
109
100
|
|
110
|
-
def call_handler_for(type, stanza)
|
111
|
-
if @handlers[type]
|
112
|
-
@handlers[type].find { |guards, handler| handler.call(stanza) unless guarded?(guards, stanza) }
|
113
|
-
true
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
101
|
protected
|
118
102
|
def setup_initial_handlers
|
119
103
|
register_handler :error do |err|
|
120
104
|
raise err
|
121
105
|
end
|
122
106
|
|
123
|
-
register_handler :iq do |iq|
|
124
|
-
write(StanzaError.new(iq, 'service-unavailable', :cancel).to_node)
|
107
|
+
register_handler :iq, :type => [:get, :set] do |iq|
|
108
|
+
write(StanzaError.new(iq, 'service-unavailable', :cancel).to_node)
|
125
109
|
end
|
126
110
|
|
127
111
|
register_handler :status do |status|
|
@@ -133,8 +117,30 @@ module Blather #:nodoc:
|
|
133
117
|
end
|
134
118
|
end
|
135
119
|
|
120
|
+
def ready!
|
121
|
+
@state = :ready
|
122
|
+
call_handler_for :ready, nil
|
123
|
+
end
|
124
|
+
|
125
|
+
def client_post_init
|
126
|
+
write_with_handler Stanza::Iq::Roster.new do |node|
|
127
|
+
roster.process node
|
128
|
+
write @status
|
129
|
+
ready!
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def call_handler_for(type, stanza)
|
134
|
+
if @handlers[type]
|
135
|
+
@handlers[type].find { |guards, handler| handler.call(stanza) unless guarded?(guards, stanza) }
|
136
|
+
true
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
136
140
|
##
|
137
141
|
# If any of the guards returns FALSE this returns true
|
142
|
+
# the logic is reversed to allow short circuiting
|
143
|
+
# (why would anyone want to loop over more values than necessary?)
|
138
144
|
def guarded?(guards, stanza)
|
139
145
|
guards.find do |guard|
|
140
146
|
case guard
|
@@ -158,8 +164,16 @@ module Blather #:nodoc:
|
|
158
164
|
end
|
159
165
|
when Proc
|
160
166
|
!guard.call(stanza)
|
161
|
-
|
162
|
-
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def check_guards(guards)
|
172
|
+
guards.each do |guard|
|
173
|
+
case guard
|
174
|
+
when Array then guard.each { |g| check_guards([g]) }
|
175
|
+
when Symbol, Proc, Hash then nil
|
176
|
+
else raise "Bad guard: #{guard.inspect}"
|
163
177
|
end
|
164
178
|
end
|
165
179
|
end
|
data/lib/blather/client/dsl.rb
CHANGED
@@ -13,14 +13,13 @@ module Blather
|
|
13
13
|
# host and port are optional defaulting to the domain in the JID and 5222 respectively
|
14
14
|
def setup(jid, password, host = nil, port = nil)
|
15
15
|
client.setup(jid, password, host, port)
|
16
|
-
at_exit { client.run }
|
17
16
|
end
|
18
17
|
|
19
18
|
##
|
20
19
|
# Shutdown the connection.
|
21
20
|
# Flushes the write buffer then stops EventMachine
|
22
21
|
def shutdown
|
23
|
-
client.
|
22
|
+
client.close
|
24
23
|
end
|
25
24
|
|
26
25
|
##
|
@@ -37,13 +36,13 @@ module Blather
|
|
37
36
|
|
38
37
|
##
|
39
38
|
# Set current status
|
40
|
-
def
|
39
|
+
def set_status(state = nil, msg = nil)
|
41
40
|
client.status = state, msg
|
42
41
|
end
|
43
42
|
|
44
43
|
##
|
45
44
|
# Direct access to the roster
|
46
|
-
def
|
45
|
+
def my_roster
|
47
46
|
client.roster
|
48
47
|
end
|
49
48
|
|
@@ -51,7 +50,7 @@ module Blather
|
|
51
50
|
# Write data to the stream
|
52
51
|
# Anything that resonds to #to_s can be paseed to the stream
|
53
52
|
def write(stanza)
|
54
|
-
client.write
|
53
|
+
client.write stanza
|
55
54
|
end
|
56
55
|
|
57
56
|
##
|
@@ -68,7 +67,9 @@ module Blather
|
|
68
67
|
end
|
69
68
|
|
70
69
|
##
|
71
|
-
#
|
70
|
+
# Request items or info from an entity
|
71
|
+
# discover (items|info), [jid], [node] do |response|
|
72
|
+
# end
|
72
73
|
def discover(what, who, where, &callback)
|
73
74
|
stanza = Blather::Stanza.class_from_registration(:query, "http://jabber.org/protocol/disco##{what}").new
|
74
75
|
stanza.to = who
|
@@ -78,22 +79,16 @@ module Blather
|
|
78
79
|
write stanza
|
79
80
|
end
|
80
81
|
|
81
|
-
##
|
82
|
-
# PubSub proxy
|
83
|
-
def pubsub
|
84
|
-
client.pubsub
|
85
|
-
end
|
86
|
-
|
87
82
|
##
|
88
83
|
# Checks to see if the method is part of the handlers list.
|
89
84
|
# If so it creates a handler, otherwise it'll pass it back
|
90
85
|
# to Ruby's method_missing handler
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
86
|
+
Blather::Stanza.handler_list.each do |handler_name|
|
87
|
+
module_eval <<-METHOD, __FILE__, __LINE__
|
88
|
+
def #{handler_name}(*args, &callback)
|
89
|
+
handle :#{handler_name}, *args, &callback
|
90
|
+
end
|
91
|
+
METHOD
|
97
92
|
end
|
98
93
|
end #DSL
|
99
94
|
end #Blather
|
@@ -52,13 +52,6 @@ class Stanza
|
|
52
52
|
self.category = category
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
56
|
-
def eql?(other)
|
57
|
-
other.kind_of?(self.class) &&
|
58
|
-
other.name == self.name &&
|
59
|
-
other.type == self.type &&
|
60
|
-
other.category == self.category
|
61
|
-
end
|
62
55
|
end
|
63
56
|
|
64
57
|
class Feature < XMPPNode
|
@@ -72,11 +65,6 @@ class Stanza
|
|
72
65
|
self.var = var
|
73
66
|
end
|
74
67
|
end
|
75
|
-
|
76
|
-
def eql?(other)
|
77
|
-
other.kind_of?(self.class) &&
|
78
|
-
other.var == self.var
|
79
|
-
end
|
80
68
|
end
|
81
69
|
end
|
82
70
|
|
data/lib/blather/stream.rb
CHANGED
@@ -87,8 +87,8 @@ module Blather
|
|
87
87
|
def unbind # :nodoc:
|
88
88
|
# @keepalive.cancel
|
89
89
|
@state = :stopped
|
90
|
-
@client.
|
91
|
-
@client.
|
90
|
+
@client.receive_data @error if @error
|
91
|
+
@client.unbind
|
92
92
|
end
|
93
93
|
|
94
94
|
##
|
@@ -162,7 +162,7 @@ module Blather
|
|
162
162
|
# Called when @state == :ready
|
163
163
|
# Simply passes the stanza to the client
|
164
164
|
def ready
|
165
|
-
@client.
|
165
|
+
@client.receive_data @node.to_stanza
|
166
166
|
end
|
167
167
|
|
168
168
|
def handle_stream_error
|
@@ -242,7 +242,7 @@ module Blather
|
|
242
242
|
@session = Session.new self, @to
|
243
243
|
# on success destroy the session object, let the client know the stream has been started
|
244
244
|
# then continue the features dispatch process
|
245
|
-
@session.on_success { LOG.debug "SESSION: SUCCESS"; @session = nil; @client.
|
245
|
+
@session.on_success { LOG.debug "SESSION: SUCCESS"; @session = nil; @client.post_init; @state = :features; dispatch }
|
246
246
|
# on failure end the stream
|
247
247
|
@session.on_failure { |err| LOG.debug "SESSION: FAILURE"; @error = err; stop }
|
248
248
|
|
@@ -0,0 +1,389 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
|
2
|
+
require 'blather/client/client'
|
3
|
+
|
4
|
+
describe 'Blather::Client' do
|
5
|
+
before do
|
6
|
+
@client = Blather::Client.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'provides a JID accessor' do
|
10
|
+
@client.must_respond_to :jid
|
11
|
+
@client.jid.must_be_nil
|
12
|
+
|
13
|
+
jid = 'me@me.com/test'
|
14
|
+
@client.must_respond_to :jid=
|
15
|
+
@client.jid = jid
|
16
|
+
@client.jid.must_be_kind_of JID
|
17
|
+
@client.jid.must_equal JID.new(jid)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'provides a reader for the roster' do
|
21
|
+
@client.must_respond_to :roster
|
22
|
+
@client.roster.must_be_kind_of Roster
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'provides a status reader' do
|
26
|
+
@client.must_respond_to :status
|
27
|
+
@client.status = :away
|
28
|
+
@client.status.must_equal :away
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'can be setup' do
|
32
|
+
@client.must_respond_to :setup
|
33
|
+
@client.setup('me@me.com', 'pass').must_equal @client
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'knows if it has been setup' do
|
37
|
+
@client.must_respond_to :setup?
|
38
|
+
@client.setup?.must_equal false
|
39
|
+
@client.setup 'me@me.com', 'pass'
|
40
|
+
@client.setup?.must_equal true
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'cannot be run before being setup' do
|
44
|
+
lambda { @client.run }.must_raise RuntimeError
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'starts up a Component connection when setup without a node' do
|
48
|
+
setup = 'pubsub.jabber.local', 'secret'
|
49
|
+
@client.setup *setup
|
50
|
+
Blather::Stream::Component.expects(:start).with @client, *setup
|
51
|
+
@client.run
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'starts up a Client connection when setup with a node' do
|
55
|
+
setup = 'test@jabber.local', 'secret'
|
56
|
+
@client.setup *setup
|
57
|
+
Blather::Stream::Client.expects(:start).with @client, *setup
|
58
|
+
@client.run
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'writes to the connection the closes when #close is called' do
|
62
|
+
stream = mock()
|
63
|
+
stream.expects(:close_connection_after_writing)
|
64
|
+
Blather::Stream::Component.stubs(:start).returns stream
|
65
|
+
@client.setup('me.com', 'secret').run
|
66
|
+
@client.close
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'shuts down EM when #unbind is called if it is running' do
|
70
|
+
EM.expects(:reactor_running?).returns true
|
71
|
+
EM.expects(:stop)
|
72
|
+
@client.unbind
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'does nothing when #unbind is called and EM is not running' do
|
76
|
+
EM.expects(:reactor_running?).returns false
|
77
|
+
EM.expects(:stop).never
|
78
|
+
@client.unbind
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'raises an error if the stream type somehow is not supported' do
|
82
|
+
Blather::Stream::Component.stubs(:start).returns nil
|
83
|
+
@client.setup('me.com', 'secret').run
|
84
|
+
lambda { @client.post_init }.must_raise RuntimeError
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'can register a temporary handler based on stanza ID' do
|
88
|
+
stanza = Stanza::Iq.new
|
89
|
+
response = mock()
|
90
|
+
response.expects(:call)
|
91
|
+
@client.register_tmp_handler(stanza.id) { |_| response.call }
|
92
|
+
@client.receive_data stanza
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'removes a tmp handler as soon as it is used' do
|
96
|
+
stanza = Stanza::Iq.new
|
97
|
+
response = mock()
|
98
|
+
response.expects(:call)
|
99
|
+
@client.register_tmp_handler(stanza.id) { |_| response.call }
|
100
|
+
@client.receive_data stanza
|
101
|
+
@client.receive_data stanza
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'will create a handler then write the stanza' do
|
105
|
+
stanza = Stanza::Iq.new
|
106
|
+
response = mock()
|
107
|
+
response.expects(:call)
|
108
|
+
@client.expects(:write).with do |s|
|
109
|
+
@client.receive_data stanza
|
110
|
+
s.must_equal stanza
|
111
|
+
end
|
112
|
+
@client.write_with_handler(stanza) { |_| response.call }
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'can register a handler' do
|
116
|
+
stanza = Stanza::Iq.new
|
117
|
+
response = mock()
|
118
|
+
response.expects(:call).times(2)
|
119
|
+
@client.register_handler(:iq) { |_| response.call }
|
120
|
+
@client.receive_data stanza
|
121
|
+
@client.receive_data stanza
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe 'Blather::Client#write' do
|
126
|
+
before do
|
127
|
+
@client = Blather::Client.new
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'sets the from attr on a stanza' do
|
131
|
+
jid = 'me@me.com'
|
132
|
+
stanza = mock(:from => nil)
|
133
|
+
stanza.expects(:from=).with jid
|
134
|
+
@client.jid = jid
|
135
|
+
@client.write stanza
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'does not set the from attr if it already exists' do
|
139
|
+
jid = 'me@me.com'
|
140
|
+
stanza = Stanza::Iq.new
|
141
|
+
stanza.from = jid
|
142
|
+
stanza.expects(:from).returns jid
|
143
|
+
stanza.expects(:from=).never
|
144
|
+
@client.jid = jid
|
145
|
+
@client.write stanza
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'writes to the stream' do
|
149
|
+
stanza = Stanza::Iq.new
|
150
|
+
stream = mock()
|
151
|
+
stream.expects(:send).with stanza
|
152
|
+
Blather::Stream::Client.expects(:start).returns stream
|
153
|
+
@client.setup('me@me.com', 'me').run
|
154
|
+
@client.write stanza
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe 'Blather::Client#status=' do
|
159
|
+
before do
|
160
|
+
@client = Blather::Client.new
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'updates the state when not sending to a JID' do
|
164
|
+
@client.status.wont_equal :away
|
165
|
+
@client.status = :away, 'message'
|
166
|
+
@client.status.must_equal :away
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'does not update the state when sending to a JID' do
|
170
|
+
@client.status.wont_equal :away
|
171
|
+
@client.status = :away, 'message', 'me@me.com'
|
172
|
+
@client.status.wont_equal :away
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'writes the new status to the stream' do
|
176
|
+
Stanza::Presence::Status.stubs(:next_id).returns 0
|
177
|
+
status = [:away, 'message']
|
178
|
+
@client.expects(:write).with do |s|
|
179
|
+
s.must_be_kind_of Stanza::Presence::Status
|
180
|
+
s.to_s.must_equal Stanza::Presence::Status.new(*status).to_s
|
181
|
+
end
|
182
|
+
@client.status = status
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe 'Blather::Client default handlers' do
|
187
|
+
before do
|
188
|
+
@client = Blather::Client.new
|
189
|
+
end
|
190
|
+
|
191
|
+
it 're-raises errors' do
|
192
|
+
err = BlatherError.new
|
193
|
+
lambda { @client.receive_data err }.must_raise BlatherError
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'responds to iq:get with a "service-unavailable" error' do
|
197
|
+
get = Stanza::Iq.new :get
|
198
|
+
err = StanzaError.new(get, 'service-unavailable', :cancel).to_node
|
199
|
+
@client.expects(:write).with err
|
200
|
+
@client.receive_data get
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'responds to iq:get with a "service-unavailable" error' do
|
204
|
+
get = Stanza::Iq.new :get
|
205
|
+
err = StanzaError.new(get, 'service-unavailable', :cancel).to_node
|
206
|
+
@client.expects(:write).with err
|
207
|
+
@client.receive_data get
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'responds to iq:set with a "service-unavailable" error' do
|
211
|
+
get = Stanza::Iq.new :set
|
212
|
+
err = StanzaError.new(get, 'service-unavailable', :cancel).to_node
|
213
|
+
@client.expects(:write).with err
|
214
|
+
@client.receive_data get
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'handles status changes by updating the roster if the status is from a JID in the roster' do
|
218
|
+
jid = 'friend@jabber.local'
|
219
|
+
status = Stanza::Presence::Status.new :away
|
220
|
+
status.stubs(:from).returns jid
|
221
|
+
roster_item = mock()
|
222
|
+
roster_item.expects(:status=).with status
|
223
|
+
@client.stubs(:roster).returns({status.from => roster_item})
|
224
|
+
@client.receive_data status
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'handles an incoming roster node by processing it through the roster' do
|
228
|
+
roster = Stanza::Iq::Roster.new
|
229
|
+
client_roster = mock()
|
230
|
+
client_roster.expects(:process).with roster
|
231
|
+
@client.stubs(:roster).returns client_roster
|
232
|
+
@client.receive_data roster
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe 'Blather::Client with a Component stream' do
|
237
|
+
before do
|
238
|
+
class MockComponent < Blather::Stream::Component; def initialize(); end; end
|
239
|
+
@client = Blather::Client.new
|
240
|
+
Blather::Stream::Component.stubs(:start).returns MockComponent.new('')
|
241
|
+
@client.setup('me.com', 'secret').run
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'calls the ready handler when sent post_init' do
|
245
|
+
ready = mock()
|
246
|
+
ready.expects(:call)
|
247
|
+
@client.register_handler(:ready) { ready.call }
|
248
|
+
@client.post_init
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
describe 'Blather::Client with a Client stream' do
|
253
|
+
before do
|
254
|
+
class MockClientStream < Blather::Stream::Client; def initialize(); end; end
|
255
|
+
@stream = MockClientStream.new('')
|
256
|
+
@client = Blather::Client.new
|
257
|
+
Blather::Stream::Client.stubs(:start).returns @stream
|
258
|
+
@client.setup('me@me.com', 'secret').run
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'sends a request for the roster when post_init is called' do
|
262
|
+
@stream.expects(:send).with { |stanza| stanza.must_be_kind_of Stanza::Iq::Roster }
|
263
|
+
@client.post_init
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'calls the ready handler after post_init and roster is received' do
|
267
|
+
result_roster = Stanza::Iq::Roster.new :result
|
268
|
+
@stream.stubs(:send).with { |s| result_roster.id = s.id; @client.receive_data result_roster; true }
|
269
|
+
|
270
|
+
ready = mock()
|
271
|
+
ready.expects(:call)
|
272
|
+
@client.register_handler(:ready) { ready.call }
|
273
|
+
@client.post_init
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
describe 'Blather::Client guards' do
|
278
|
+
before do
|
279
|
+
@client = Blather::Client.new
|
280
|
+
@stanza = Stanza::Iq.new
|
281
|
+
@response = mock()
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'can be a symbol' do
|
285
|
+
@response.expects :call
|
286
|
+
@client.register_handler(:iq, :chat?) { |_| @response.call }
|
287
|
+
|
288
|
+
@stanza.expects(:chat?).returns true
|
289
|
+
@client.receive_data @stanza
|
290
|
+
|
291
|
+
@stanza.expects(:chat?).returns false
|
292
|
+
@client.receive_data @stanza
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'can be a hash with string match' do
|
296
|
+
@response.expects :call
|
297
|
+
@client.register_handler(:iq, :body => 'exit') { |_| @response.call }
|
298
|
+
|
299
|
+
@stanza.expects(:body).returns 'exit'
|
300
|
+
@client.receive_data @stanza
|
301
|
+
|
302
|
+
@stanza.expects(:body).returns 'not-exit'
|
303
|
+
@client.receive_data @stanza
|
304
|
+
end
|
305
|
+
|
306
|
+
it 'can be a hash with a value' do
|
307
|
+
@response.expects :call
|
308
|
+
@client.register_handler(:iq, :number => 0) { |_| @response.call }
|
309
|
+
|
310
|
+
@stanza.expects(:number).returns 0
|
311
|
+
@client.receive_data @stanza
|
312
|
+
|
313
|
+
@stanza.expects(:number).returns 1
|
314
|
+
@client.receive_data @stanza
|
315
|
+
end
|
316
|
+
|
317
|
+
it 'can be a hash with a regexp' do
|
318
|
+
@response.expects :call
|
319
|
+
@client.register_handler(:iq, :body => /exit/) { |_| @response.call }
|
320
|
+
|
321
|
+
@stanza.expects(:body).returns 'more than just exit, but exit still'
|
322
|
+
@client.receive_data @stanza
|
323
|
+
|
324
|
+
@stanza.expects(:body).returns 'keyword not found'
|
325
|
+
@client.receive_data @stanza
|
326
|
+
end
|
327
|
+
|
328
|
+
it 'can be a hash with an array' do
|
329
|
+
@response.expects(:call).times(2)
|
330
|
+
@client.register_handler(:iq, :type => [:result, :error]) { |_| @response.call }
|
331
|
+
|
332
|
+
stanza = Stanza::Iq.new
|
333
|
+
stanza.expects(:type).at_least_once.returns :result
|
334
|
+
@client.receive_data stanza
|
335
|
+
|
336
|
+
stanza = Stanza::Iq.new
|
337
|
+
stanza.expects(:type).at_least_once.returns :error
|
338
|
+
@client.receive_data stanza
|
339
|
+
|
340
|
+
stanza = Stanza::Iq.new
|
341
|
+
stanza.expects(:type).at_least_once.returns :get
|
342
|
+
@client.receive_data stanza
|
343
|
+
end
|
344
|
+
|
345
|
+
it 'chained are treated like andand (short circuited)' do
|
346
|
+
@response.expects :call
|
347
|
+
@client.register_handler(:iq, :type => :get, :body => 'test') { |_| @response.call }
|
348
|
+
|
349
|
+
stanza = Stanza::Iq.new
|
350
|
+
stanza.expects(:type).at_least_once.returns :get
|
351
|
+
stanza.expects(:body).returns 'test'
|
352
|
+
@client.receive_data stanza
|
353
|
+
|
354
|
+
stanza = Stanza::Iq.new
|
355
|
+
stanza.expects(:type).at_least_once.returns :set
|
356
|
+
stanza.expects(:body).never
|
357
|
+
@client.receive_data stanza
|
358
|
+
end
|
359
|
+
|
360
|
+
it 'within an Array are treated as oror (short circuited)' do
|
361
|
+
@response.expects(:call).times 2
|
362
|
+
@client.register_handler(:iq, [{:type => :get}, {:body => 'test'}]) { |_| @response.call }
|
363
|
+
|
364
|
+
stanza = Stanza::Iq.new
|
365
|
+
stanza.expects(:type).at_least_once.returns :set
|
366
|
+
stanza.expects(:body).returns 'test'
|
367
|
+
@client.receive_data stanza
|
368
|
+
|
369
|
+
stanza = Stanza::Iq.new
|
370
|
+
stanza.stubs(:type).at_least_once.returns :get
|
371
|
+
stanza.expects(:body).never
|
372
|
+
@client.receive_data stanza
|
373
|
+
end
|
374
|
+
|
375
|
+
it 'can be a lambda' do
|
376
|
+
@response.expects :call
|
377
|
+
@client.register_handler(:iq, lambda { |s| s.number % 3 == 0 }) { |_| @response.call }
|
378
|
+
|
379
|
+
@stanza.expects(:number).at_least_once.returns 3
|
380
|
+
@client.receive_data @stanza
|
381
|
+
|
382
|
+
@stanza.expects(:number).at_least_once.returns 2
|
383
|
+
@client.receive_data @stanza
|
384
|
+
end
|
385
|
+
|
386
|
+
it 'raises an error when a bad guard is tried' do
|
387
|
+
lambda { @client.register_handler(:iq, 0) {} }.must_raise RuntimeError
|
388
|
+
end
|
389
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
|
2
|
+
require 'blather/client/dsl'
|
3
|
+
|
4
|
+
describe 'Blather::DSL' do
|
5
|
+
before do
|
6
|
+
@client = mock()
|
7
|
+
@dsl = class MockDSL; include Blather::DSL; end.new
|
8
|
+
Client.stubs(:new).returns(@client)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'wraps the setup' do
|
12
|
+
args = ['jid', 'pass', 'host', 0000]
|
13
|
+
@client.expects(:setup).with *args
|
14
|
+
@dsl.setup *args
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'allows host to be nil in setup' do
|
18
|
+
args = ['jid', 'pass']
|
19
|
+
@client.expects(:setup).with *(args + [nil, nil])
|
20
|
+
@dsl.setup *args
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'allows port to be nil in setup' do
|
24
|
+
args = ['jid', 'pass', 'host']
|
25
|
+
@client.expects(:setup).with *(args + [nil])
|
26
|
+
@dsl.setup *args
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'stops when shutdown is called' do
|
30
|
+
@client.expects(:close)
|
31
|
+
@dsl.shutdown
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'sets up handlers' do
|
35
|
+
type = :message
|
36
|
+
guards = [:chat?, {:body => 'exit'}]
|
37
|
+
@client.expects(:register_handler).with type, *guards
|
38
|
+
@dsl.handle type, *guards
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'provides a helper for ready state' do
|
42
|
+
@client.expects(:register_handler).with :ready
|
43
|
+
@dsl.when_ready
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'sets the initial status' do
|
47
|
+
state = :away
|
48
|
+
msg = 'do not disturb'
|
49
|
+
@client.expects(:status=).with [state, msg]
|
50
|
+
@dsl.set_status state, msg
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'provides a roster accessor' do
|
54
|
+
@client.expects :roster
|
55
|
+
@dsl.my_roster
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'provides a writer' do
|
59
|
+
stanza = Blather::Stanza::Iq.new
|
60
|
+
@client.expects(:write).with stanza
|
61
|
+
@dsl.write stanza
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'provides a "say" helper' do
|
65
|
+
to, msg = 'me@me.com', 'hello!'
|
66
|
+
Blather::Stanza::Message.stubs(:next_id).returns 0
|
67
|
+
@client.expects(:write).with Blather::Stanza::Message.new(to, msg)
|
68
|
+
@dsl.say to, msg
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'provides a JID accessor' do
|
72
|
+
@client.expects :jid
|
73
|
+
@dsl.jid
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'provides a disco helper for items' do
|
77
|
+
what, who, where = :items, 'me@me.com', 'my/node'
|
78
|
+
Blather::Stanza::Disco::DiscoItems.stubs(:next_id).returns 0
|
79
|
+
@client.expects(:temporary_handler).with '0'
|
80
|
+
expected_stanza = Blather::Stanza::Disco::DiscoItems.new
|
81
|
+
expected_stanza.to = who
|
82
|
+
expected_stanza.node = where
|
83
|
+
@client.expects(:write).with expected_stanza
|
84
|
+
@dsl.discover what, who, where
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'provides a disco helper for info' do
|
88
|
+
what, who, where = :info, 'me@me.com', 'my/node'
|
89
|
+
Blather::Stanza::Disco::DiscoInfo.stubs(:next_id).returns 0
|
90
|
+
@client.expects(:temporary_handler).with '0'
|
91
|
+
expected_stanza = Blather::Stanza::Disco::DiscoInfo.new
|
92
|
+
expected_stanza.to = who
|
93
|
+
expected_stanza.node = where
|
94
|
+
@client.expects(:write).with expected_stanza
|
95
|
+
@dsl.discover what, who, where
|
96
|
+
end
|
97
|
+
|
98
|
+
Blather::Stanza.handler_list.each do |handler_method|
|
99
|
+
it "provides a helper method for #{handler_method}" do
|
100
|
+
guards = [:chat?, {:body => 'exit'}]
|
101
|
+
@client.expects(:register_handler).with handler_method, *guards
|
102
|
+
@dsl.__send__(handler_method, *guards)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -11,7 +11,7 @@ describe 'Blather::Stream::Client' do
|
|
11
11
|
|
12
12
|
def mocked_server(times = nil, &block)
|
13
13
|
@client ||= mock()
|
14
|
-
@client.stubs(:
|
14
|
+
@client.stubs(:unbind) unless @client.respond_to?(:unbind)
|
15
15
|
@client.stubs(:jid=) unless @client.respond_to?(:jid=)
|
16
16
|
|
17
17
|
MockServer.any_instance.expects(:receive_data).send(*(times ? [:times, times] : [:at_least, 1])).with &block
|
@@ -58,7 +58,7 @@ describe 'Blather::Stream::Client' do
|
|
58
58
|
|
59
59
|
it 'sends stanzas to the client when the stream is ready' do
|
60
60
|
@client = mock()
|
61
|
-
@client.expects(:
|
61
|
+
@client.expects(:receive_data).with do |n|
|
62
62
|
EM.stop
|
63
63
|
n.kind_of?(Stanza::Message) && @stream.ready?.must_equal(true)
|
64
64
|
end
|
@@ -72,7 +72,7 @@ describe 'Blather::Stream::Client' do
|
|
72
72
|
|
73
73
|
it 'puts itself in the stopped state and calls @client.stopped when stopped' do
|
74
74
|
@client = mock()
|
75
|
-
@client.expects(:
|
75
|
+
@client.expects(:unbind).at_least_once
|
76
76
|
|
77
77
|
started = false
|
78
78
|
mocked_server(2) do |val, server|
|
@@ -95,8 +95,8 @@ describe 'Blather::Stream::Client' do
|
|
95
95
|
it 'will be in the negotiating state during feature negotiations' do
|
96
96
|
state = nil
|
97
97
|
@client = mock()
|
98
|
-
@client.stubs(:
|
99
|
-
@client.expects(:
|
98
|
+
@client.stubs(:post_init)
|
99
|
+
@client.expects(:receive_data).with do |n|
|
100
100
|
EM.stop
|
101
101
|
state.must_equal(:negotiated) && @stream.negotiating?.must_equal(false)
|
102
102
|
end
|
@@ -154,7 +154,7 @@ describe 'Blather::Stream::Client' do
|
|
154
154
|
|
155
155
|
it 'sends client an error on stream:error' do
|
156
156
|
@client = mock()
|
157
|
-
@client.expects(:
|
157
|
+
@client.expects(:receive_data).with do |v|
|
158
158
|
v.name.must_equal :conflict
|
159
159
|
v.text.must_equal 'Already signed in'
|
160
160
|
v.to_s.must_equal "Stream Error (conflict): #{v.text}"
|
@@ -216,7 +216,7 @@ describe 'Blather::Stream::Client' do
|
|
216
216
|
it 'will fail if TLS negotiation fails' do
|
217
217
|
state = nil
|
218
218
|
@client = mock()
|
219
|
-
@client.expects(:
|
219
|
+
@client.expects(:receive_data).with { |v| v.must_be_kind_of TLSFailure }
|
220
220
|
mocked_server(3) do |val, server|
|
221
221
|
case state
|
222
222
|
when nil
|
@@ -245,7 +245,7 @@ describe 'Blather::Stream::Client' do
|
|
245
245
|
it 'will fail if a bad node comes through TLS negotiations' do
|
246
246
|
state = nil
|
247
247
|
@client = mock()
|
248
|
-
@client.expects(:
|
248
|
+
@client.expects(:receive_data).with do |v|
|
249
249
|
v.must_be_kind_of UnknownResponse
|
250
250
|
v.node.element_name.must_equal 'foo-bar'
|
251
251
|
end
|
@@ -400,7 +400,7 @@ describe 'Blather::Stream::Client' do
|
|
400
400
|
it 'tries each possible mechanism until it fails completely' do
|
401
401
|
state = nil
|
402
402
|
@client = mock()
|
403
|
-
@client.expects(:
|
403
|
+
@client.expects(:receive_data).with do |n|
|
404
404
|
n.must_be_kind_of(SASLError)
|
405
405
|
n.name.must_equal :not_authorized
|
406
406
|
end
|
@@ -473,7 +473,7 @@ describe 'Blather::Stream::Client' do
|
|
473
473
|
|
474
474
|
it 'sends client an error when an unknown mechanism is sent' do
|
475
475
|
@client = mock()
|
476
|
-
@client.expects(:
|
476
|
+
@client.expects(:receive_data).with { |v| v.must_be_kind_of(Stream::SASL::UnknownMechanism) }
|
477
477
|
started = false
|
478
478
|
mocked_server(2) do |val, server|
|
479
479
|
if !started
|
@@ -500,7 +500,7 @@ describe 'Blather::Stream::Client' do
|
|
500
500
|
].each do |error_type|
|
501
501
|
it "fails on #{error_type}" do
|
502
502
|
@client = mock()
|
503
|
-
@client.expects(:
|
503
|
+
@client.expects(:receive_data).with do |n|
|
504
504
|
n.name.must_equal error_type.gsub('-','_').to_sym
|
505
505
|
end
|
506
506
|
state = nil
|
@@ -532,7 +532,7 @@ describe 'Blather::Stream::Client' do
|
|
532
532
|
|
533
533
|
it 'fails when an unkown node comes through during SASL negotiation' do
|
534
534
|
@client = mock()
|
535
|
-
@client.expects(:
|
535
|
+
@client.expects(:receive_data).with do |n|
|
536
536
|
n.must_be_instance_of UnknownResponse
|
537
537
|
n.node.element_name.must_equal 'foo-bar'
|
538
538
|
end
|
@@ -629,7 +629,7 @@ describe 'Blather::Stream::Client' do
|
|
629
629
|
it 'will return an error if resource binding errors out' do
|
630
630
|
state = nil
|
631
631
|
@client = mock()
|
632
|
-
@client.expects(:
|
632
|
+
@client.expects(:receive_data).with do |n|
|
633
633
|
n.name.must_equal :bad_request
|
634
634
|
end
|
635
635
|
mocked_server(3) do |val, server|
|
@@ -660,7 +660,7 @@ describe 'Blather::Stream::Client' do
|
|
660
660
|
it 'will return an error if an unkown node comes through during resouce binding' do
|
661
661
|
state = nil
|
662
662
|
@client = mock()
|
663
|
-
@client.expects(:
|
663
|
+
@client.expects(:receive_data).with do |n|
|
664
664
|
n.must_be_instance_of UnknownResponse
|
665
665
|
n.node.element_name.must_equal 'foo-bar'
|
666
666
|
end
|
@@ -692,7 +692,7 @@ describe 'Blather::Stream::Client' do
|
|
692
692
|
it 'will establish a session if requested' do
|
693
693
|
state = nil
|
694
694
|
@client = mock()
|
695
|
-
@client.expects(:
|
695
|
+
@client.expects(:post_init)
|
696
696
|
|
697
697
|
mocked_server(3) do |val, server|
|
698
698
|
case state
|
@@ -723,7 +723,7 @@ describe 'Blather::Stream::Client' do
|
|
723
723
|
it 'will return an error if session establishment errors out' do
|
724
724
|
state = nil
|
725
725
|
@client = mock()
|
726
|
-
@client.expects(:
|
726
|
+
@client.expects(:receive_data).with do |n|
|
727
727
|
n.name.must_equal :internal_server_error
|
728
728
|
end
|
729
729
|
mocked_server(3) do |val, server|
|
@@ -754,7 +754,7 @@ describe 'Blather::Stream::Client' do
|
|
754
754
|
it 'will return an error if an unknown node come through during session establishment' do
|
755
755
|
state = nil
|
756
756
|
@client = mock()
|
757
|
-
@client.expects(:
|
757
|
+
@client.expects(:receive_data).with do |n|
|
758
758
|
n.must_be_instance_of UnknownResponse
|
759
759
|
n.node.element_name.must_equal 'foo-bar'
|
760
760
|
end
|
@@ -785,7 +785,7 @@ describe 'Blather::Stream::Client' do
|
|
785
785
|
|
786
786
|
it 'sends client an error on parse error' do
|
787
787
|
@client = mock()
|
788
|
-
@client.expects(:
|
788
|
+
@client.expects(:receive_data).with do |v|
|
789
789
|
v.must_be_kind_of ParseError
|
790
790
|
v.message.must_match(/generate\-parse\-error/)
|
791
791
|
end
|
@@ -11,7 +11,7 @@ describe 'Blather::Stream::Component' do
|
|
11
11
|
|
12
12
|
def mocked_server(times = nil, &block)
|
13
13
|
@client ||= mock()
|
14
|
-
@client.stubs(:
|
14
|
+
@client.stubs(:unbind) unless @client.respond_to?(:unbind)
|
15
15
|
@client.stubs(:jid=) unless @client.respond_to?(:jid=)
|
16
16
|
|
17
17
|
MockServer.any_instance.expects(:receive_data).send(*(times ? [:times, times] : [:at_least, 1])).with &block
|
@@ -60,8 +60,8 @@ describe 'Blather::Stream::Component' do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'sends stanzas to the client when the stream is ready' do
|
63
|
-
@client = mock(:
|
64
|
-
@client.expects(:
|
63
|
+
@client = mock(:post_init)
|
64
|
+
@client.expects(:receive_data).with do |n|
|
65
65
|
EM.stop
|
66
66
|
n.kind_of?(Stanza::Message) && @stream.ready?.must_equal(true)
|
67
67
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
2
|
+
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), *%w[.. lib]))
|
3
|
+
|
4
|
+
require 'blather'
|
2
5
|
require 'rubygems'
|
3
6
|
require 'minitest/spec'
|
4
7
|
require 'mocha'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sprsquish-blather
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Smick
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-14 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.1.
|
33
|
+
version: 1.1.2
|
34
34
|
version:
|
35
35
|
description:
|
36
36
|
email: sprsquish@gmail.com
|
@@ -44,6 +44,7 @@ extra_rdoc_files:
|
|
44
44
|
files:
|
45
45
|
- examples/drb_client.rb
|
46
46
|
- examples/echo.rb
|
47
|
+
- examples/ping_pong.rb
|
47
48
|
- examples/print_heirarchy.rb
|
48
49
|
- ext/extconf.rb
|
49
50
|
- ext/push_parser.c
|
@@ -110,6 +111,8 @@ signing_key:
|
|
110
111
|
specification_version: 3
|
111
112
|
summary: An evented XMPP library written on EventMachine and libxml-ruby
|
112
113
|
test_files:
|
114
|
+
- spec/blather/client/client_spec.rb
|
115
|
+
- spec/blather/client/dsl_spec.rb
|
113
116
|
- spec/blather/core_ext/libxml_spec.rb
|
114
117
|
- spec/blather/errors/sasl_error_spec.rb
|
115
118
|
- spec/blather/errors/stanza_error_spec.rb
|