radamanthus-skates 0.3.5

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.
@@ -0,0 +1,233 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require File.dirname(__FILE__) + '/../../em_mock'
3
+
4
+ describe Skates::Runner do
5
+ before(:all) do
6
+ FileUtils.chdir("#{FileUtils.pwd}/templates/skates") unless ("#{FileUtils.pwd}" =~ /\/templates\/skates/ )
7
+ end
8
+
9
+ describe ".prepare" do
10
+ before(:each) do
11
+ @config = {"production"=>{"port"=>5278, "auto-reconnect"=>true, "jid"=>"component.server.com", "host"=>"localhost", "password"=>"password"}, "development"=>{"auto-reconnect"=>true, "jid"=>"user@server.com", "application_type"=>"client", "password"=>"password"}, "test"=>{"port"=>5278, "auto-reconnect"=>true, "jid"=>"component.server.com", "host"=>"localhost", "password"=>"password"}}
12
+ Skates.config_file = "config/config.yaml"
13
+ YAML.stub(:load_file).and_return(@config)
14
+ Skates::Runner.stub!(:require_directory).and_return(true)
15
+ end
16
+
17
+ it "should add the environment log file as an outputter to skates's default log" do
18
+ Skates.should_receive(:reopen_logs)
19
+ Skates::Runner.prepare("test")
20
+ end
21
+
22
+ it "should require all models" do
23
+ Skates::Runner.should_receive(:require_directory).with('app/models/*.rb').and_return(true)
24
+ Skates::Runner.prepare("test")
25
+ end
26
+
27
+ it "should require all stanzas" do
28
+ Skates::Runner.should_receive(:require_directory).with('app/stanzas/*.rb').and_return(true)
29
+ Skates::Runner.prepare("test")
30
+ end
31
+
32
+ it "should require all controllers" do
33
+ Skates::Runner.should_receive(:require_directory).with('app/controllers/*_controller.rb').and_return(true)
34
+ Skates::Runner.prepare("test")
35
+ end
36
+
37
+ it "should create a router" do
38
+ router = Skates::StanzaRouter.new
39
+ Skates::StanzaRouter.should_receive(:new).and_return(router)
40
+ Skates.should_receive(:router=).with(router)
41
+ Skates::Runner.prepare("test")
42
+ end
43
+
44
+ it "should load the routes" do
45
+ Skates::Runner.should_receive(:require).with('config/routes.rb')
46
+ Skates::Runner.prepare("test")
47
+ end
48
+
49
+ it "should load the configuration file" do
50
+ YAML.should_receive(:load_file).with('config/config.yaml').and_return(@config)
51
+ Skates::Runner.prepare("test")
52
+ end
53
+
54
+ it "should assign the configuration" do
55
+ Skates::Runner.prepare("test")
56
+ Skates.config.should == {"port"=>5278, "jid"=>"component.server.com", "auto-reconnect"=>true, "host"=>"localhost", "password"=>"password"}
57
+ end
58
+
59
+ it "should cache the views" do
60
+ Skates.should_receive(:cache_views)
61
+ Skates::Runner.prepare("test")
62
+ end
63
+ end
64
+
65
+ describe "require_directory" do
66
+ before(:each) do
67
+ @dir = "/my/dir"
68
+ @files = ["hello.rb", "byebye.rb"]
69
+ Dir.stub!(:glob).with(@dir).and_return(@files)
70
+ @files.each do |f|
71
+ Skates::Runner.stub!(:require).with(f).and_return(true)
72
+ end
73
+ end
74
+ it "should list all files in the directory" do
75
+ Dir.should_receive(:glob).with(@dir).and_return(@files)
76
+ Skates::Runner.require_directory(@dir)
77
+ end
78
+ it "should require each of the files" do
79
+ @files.each do |f|
80
+ Skates::Runner.should_receive(:require).with(f).and_return(true)
81
+ end
82
+ Skates::Runner.require_directory(@dir)
83
+ end
84
+ end
85
+
86
+ describe ".run" do
87
+ before(:each) do
88
+ Skates::ClientConnection.stub!(:connect).and_return(true)
89
+ Skates::ComponentConnection.stub!(:connect).and_return(true)
90
+ EventMachine.stub!(:run).and_yield
91
+ end
92
+
93
+ it "should set the environment" do
94
+ Skates::Runner.run("test")
95
+ Skates.environment.should == "test"
96
+ end
97
+
98
+ it "should epoll the EventMachine" do
99
+ EventMachine.should_receive(:epoll)
100
+ Skates::Runner.run("test")
101
+ end
102
+
103
+ it "should run the EventMachine" do
104
+ EventMachine.should_receive(:run)
105
+ Skates::Runner.run("test")
106
+ end
107
+
108
+ it "should call prepare" do
109
+ Skates::Runner.should_receive(:prepare).with("test")
110
+ Skates::Runner.run("test")
111
+ end
112
+
113
+ it "should connect the client connection if specified by the config" do
114
+ Skates.stub!(:config).and_return({"application_type" => "client"})
115
+ Skates::ClientConnection.should_receive(:connect).with(Skates.config, Skates::Runner)
116
+ Skates::Runner.run("test")
117
+ end
118
+
119
+ it "should connect the component connection if no application_type specified by the config" do
120
+ Skates.stub!(:config).and_return({})
121
+ Skates::ComponentConnection.should_receive(:connect).with(Skates.config, Skates::Runner)
122
+ Skates::Runner.run("test")
123
+ end
124
+
125
+ end
126
+
127
+ describe ".connection_observers" do
128
+ it "should return an array" do
129
+ Skates::Runner.connection_observers.should be_an_instance_of(Array)
130
+ end
131
+ end
132
+
133
+ describe ".add_connection_observer" do
134
+ before(:each) do
135
+ class MyController < Skates::Base::Controller; end
136
+ end
137
+
138
+ it "should not accept non-Skates::Base::Controller subclasses" do
139
+ Skates::Runner.add_connection_observer(Object).should be_false
140
+ end
141
+
142
+ it "should accept" do
143
+ Skates::Runner.add_connection_observer(MyController).should be_true
144
+ end
145
+
146
+ it "should add it to the list of observers" do
147
+ observers = Skates::Runner.connection_observers
148
+ Skates::Runner.add_connection_observer(MyController)
149
+ observers.include?(MyController).should be_true
150
+ end
151
+
152
+ it "should not add it twice" do
153
+ observers = Skates::Runner.connection_observers
154
+ Skates::Runner.add_connection_observer(MyController)
155
+ Skates::Runner.add_connection_observer(MyController)
156
+ observers.should == [MyController]
157
+ end
158
+
159
+ end
160
+
161
+ describe ".on_connected" do
162
+ before(:each) do
163
+ @connection = mock(Object)
164
+ Skates.router = Skates::StanzaRouter.new
165
+ Skates.router.stub!(:connected).with(@connection)
166
+ Skates.router.stub!(:execute_route).with(MyController, "on_connected")
167
+ end
168
+
169
+ it "should call connected on StanzaRouter" do
170
+ Skates.router.should_receive(:connected).with(@connection)
171
+ Skates::Runner.on_connected(@connection)
172
+ end
173
+
174
+ it "should call on_connected on the various observers and send the corresponding response" do
175
+ Skates::Runner.add_connection_observer(MyController)
176
+ Skates.router.should_receive(:execute_route).with(MyController, "on_connected")
177
+ Skates::Runner.on_connected(@connection)
178
+ end
179
+ end
180
+
181
+ describe ".on_disconnected" do
182
+ it "should call on_disconnected on the various observers" do
183
+ class MyObserver < Skates::Base::Controller; def on_disconnected; end; end
184
+ my_observer = MyObserver.new
185
+ Skates::Runner.add_connection_observer(MyObserver)
186
+ MyObserver.should_receive(:new).and_return(my_observer)
187
+ my_observer.should_receive(:on_disconnected)
188
+ Skates::Runner.on_disconnected
189
+ end
190
+
191
+ context "when the application should auto-reconnect" do
192
+ before(:each) do
193
+ Skates.config["auto-reconnect"] = true
194
+ EventMachine.stub!(:reactor_running?).and_return(false)
195
+ EventMachine.stub!(:add_timer).and_yield()
196
+ @delay = 15
197
+ Skates::Runner.stub!(:fib).and_return(@delay)
198
+ end
199
+
200
+ it "should determine when is the best time to reconnect with fibonacci" do
201
+ Skates::Runner.should_receive(:fib).and_return(@delay)
202
+ Skates::Runner.on_disconnected()
203
+ end
204
+
205
+ it "should try to reconnect at the determined time" do
206
+ EventMachine.stub!(:reactor_running?).and_return(true)
207
+ Skates::Runner.should_receive(:reconnect)
208
+ EventMachine.should_receive(:add_timer).with(@delay).and_yield()
209
+ Skates::Runner.on_disconnected()
210
+ end
211
+ end
212
+
213
+ context "when the application should not auto-reconnect" do
214
+ before(:each) do
215
+ Skates.config["auto-reconnect"] = false
216
+ end
217
+
218
+ it "should stop the event loop" do
219
+ connection = mock(Object)
220
+ EventMachine.should_receive(:stop_event_loop)
221
+ Skates::Runner.on_disconnected()
222
+ end
223
+ end
224
+ end
225
+
226
+ describe ".on_stanza" do
227
+ it "should call route on StanzaRouter" do
228
+ stanza = mock(Object)
229
+ Skates.router.should_receive(:route).with(stanza)
230
+ Skates::Runner.on_stanza(stanza)
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,222 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require File.dirname(__FILE__) + '/../../em_mock'
3
+
4
+ describe Skates::XmppConnection do
5
+
6
+ include SkatesSpecHelper
7
+
8
+ before(:each) do
9
+ @params = {"jid" => "jid@server", "password" => "password", "port" => 1234, "host" => "myhost.com"}
10
+ @connection = Skates::XmppConnection._connect(@params, handler_mock)
11
+ end
12
+
13
+ describe "_connect" do
14
+ it "should connect EventMachine and return it" do
15
+ EventMachine.should_receive(:connect).with(@params["host"], @params["port"], Skates::XmppConnection, hash_including("handler" => handler_mock)).and_return(@connection)
16
+ Skates::XmppConnection._connect(@params, handler_mock).should == @connection
17
+ end
18
+
19
+ it "should rescue Connection Errors" do
20
+ EventMachine.stub!(:connect).with(@params["host"], @params["port"], Skates::XmppConnection, hash_including("handler" => handler_mock)).and_raise(RuntimeError)
21
+ lambda {
22
+ Skates::XmppConnection._connect(@params, handler_mock)
23
+ }.should raise_error(Skates::NotConnected)
24
+ end
25
+
26
+ end
27
+
28
+ describe "connect" do
29
+ describe "connect" do
30
+ it "should not try to resolve the dns if a host IP has been provided" do
31
+ @params["host"] = "123.123.123.123"
32
+ Skates::XmppConnection.should_not_receive(:resolve)
33
+ Skates::XmppConnection.connect(@params, handler_mock)
34
+ end
35
+
36
+ describe "when a host is provided, which is not an IP" do
37
+ it "should resolve it" do
38
+ @params["host"] = "domain.tld"
39
+ Skates::XmppConnection.should_receive(:resolve)
40
+ Skates::XmppConnection.connect(@params, handler_mock)
41
+ end
42
+ end
43
+
44
+ describe "when no host is provided, and no port either" do
45
+ it "should resolve the host to an IP" do
46
+ Skates::XmppConnection.should_receive(:resolve)
47
+ Skates::XmppConnection.connect(@params, handler_mock)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "initialize" do
54
+ it "should assign @connected to false" do
55
+ @connection.instance_variable_get("@connected").should be_false
56
+ end
57
+
58
+ it "should assign @jid to params['jid']" do
59
+ @connection.instance_variable_get("@jid").should == @params["jid"]
60
+ end
61
+
62
+ it "should assign @password to params['password']" do
63
+ @connection.instance_variable_get("@password").should == @params["password"]
64
+ end
65
+
66
+ it "should assign @host to params['host']" do
67
+ @connection.instance_variable_get("@host").should == @params["host"]
68
+ end
69
+
70
+ it "should assign @port to params['port']" do
71
+ @connection.instance_variable_get("@port").should == @params["port"]
72
+ end
73
+
74
+ it "should assign @handler to params['handler']" do
75
+ @connection.instance_variable_get("@handler").should == handler_mock
76
+ end
77
+
78
+ it "should assign @buffer to ''" do
79
+ @connection.instance_variable_get("@buffer").should == ""
80
+ end
81
+ end
82
+
83
+ describe "post_init" do
84
+ it "assigne a new parser" do
85
+ parser = Skates::XmppParser.new(@connection.method(:receive_stanza))
86
+ Skates::XmppParser.should_receive(:new).and_return(parser)
87
+ @connection.post_init
88
+ @connection.instance_variable_get("@parser").should == parser
89
+ end
90
+ end
91
+
92
+ describe "connection_completed" do
93
+ it "should set @connected to true" do
94
+ @connection.connection_completed
95
+ @connection.instance_variable_get("@connected").should be_true
96
+ end
97
+ end
98
+
99
+ describe "unbind" do
100
+ it "should set @connected to false" do
101
+ @connection.connection_completed
102
+ @connection.unbind
103
+ @connection.instance_variable_get("@connected").should be_false
104
+ end
105
+ end
106
+
107
+ describe "receive_stanza" do
108
+
109
+ before(:each) do
110
+ @doc = Nokogiri::XML::Document.new
111
+ end
112
+
113
+ describe "with an stanza that starts with stream:error" do
114
+
115
+ before(:each) do
116
+ @error_stanza = Nokogiri::XML::Node.new("stream:error", @doc)
117
+ end
118
+
119
+ it "should close the connection" do
120
+ @connection.should_receive(:close_connection)
121
+ @connection.receive_stanza(@error_stanza)
122
+ end
123
+
124
+ describe "with a malformed stanza error" do
125
+ before(:each) do
126
+ @xml_not_well_formed_stanza = Nokogiri::XML::Node.new("xml-not-well-formed", @doc)
127
+ @xml_not_well_formed_stanza.add_namespace("xmlns", "urn:ietf:params:xml:ns:xmpp-streams")
128
+ @error_stanza.add_child(@xml_not_well_formed_stanza)
129
+ end
130
+
131
+ end
132
+ end
133
+
134
+ describe "with a stanza that is not an error" do
135
+ it "should call the on_stanza block" do
136
+ stanza = Nokogiri::XML::Node.new("message", @doc)
137
+ handler_mock.should_receive(:on_stanza)
138
+ @connection.receive_stanza(stanza)
139
+ end
140
+ end
141
+
142
+ end
143
+
144
+ describe "send_chunk" do
145
+ it "should raise an error if not connected" do
146
+ @connection.instance_variable_set("@connected", false)
147
+ lambda {
148
+ @connection.__send__(:send_chunk, "hello world")
149
+ }.should raise_error(Skates::NotConnected)
150
+ end
151
+
152
+ it "should raise an error if the stanza size is above the limit" do
153
+ @connection.instance_variable_set("@connected", true)
154
+ string = "a" * (Skates::XmppConnection.max_stanza_size + 1)
155
+ lambda {
156
+ @connection.__send__(:send_chunk, string)
157
+ }.should raise_error(Skates::StanzaTooBig)
158
+ end
159
+
160
+ it "should return if the string is blank" do
161
+ @connection.instance_variable_set("@connected", true)
162
+ @connection.should_not_receive(:send_data)
163
+ @connection.__send__(:send_chunk, "")
164
+ end
165
+
166
+ it "should cann send_data with the string" do
167
+ @connection.instance_variable_set("@connected", true)
168
+ string = "hello world"
169
+ @connection.should_receive(:send_data).with(string)
170
+ @connection.__send__(:send_chunk, string)
171
+ end
172
+
173
+ end
174
+
175
+ describe "send_xml" do
176
+
177
+ before(:each) do
178
+ @connection.instance_variable_set("@connected", true)
179
+ @connection.stub!(:send_chunk).and_return(true)
180
+ @doc = Nokogiri::XML::Document.new
181
+ end
182
+
183
+ describe "with a nodeset as argument" do
184
+ before(:each) do
185
+ iq = Nokogiri::XML::Node.new("iq", @doc)
186
+ message = Nokogiri::XML::Node.new("message", @doc)
187
+ presence = Nokogiri::XML::Node.new("presence", @doc)
188
+ @node_set = Nokogiri::XML::NodeSet.new(@doc, [message, presence, iq])
189
+ end
190
+
191
+ it "should call send_chunk for each of the nodes in the set" do
192
+ @node_set.each do |node|
193
+ @connection.should_receive(:send_chunk).with(node.to_s)
194
+ end
195
+ @connection.send_xml(@node_set)
196
+ end
197
+ end
198
+
199
+ describe "with an argument with is not a NodeSet" do
200
+ before(:each) do
201
+ @message = Nokogiri::XML::Node.new("message", @doc)
202
+ end
203
+ it "should call send_chunk for the node" do
204
+ @connection.should_receive(:send_chunk).with(@message.to_s)
205
+ @connection.send_xml(@message)
206
+ end
207
+ end
208
+ end
209
+
210
+ describe "receive_data" do
211
+ before(:each) do
212
+ @connection.instance_variable_get("@parser").stub!(:push).and_return(true)
213
+ end
214
+
215
+ it "should push the received data to the parser" do
216
+ data = "<hello>hello world!</hello>"
217
+ @connection.instance_variable_get("@parser").should_receive(:push).with(data).and_return(true)
218
+ @connection.__send__(:receive_data, data)
219
+ end
220
+ end
221
+
222
+ end