julien51-babylon 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,222 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require File.dirname(__FILE__) + '/../../em_mock'
3
+
4
+ describe Babylon::XmppConnection do
5
+
6
+ include BabylonSpecHelper
7
+
8
+ before(:each) do
9
+ @params = {"jid" => "jid@server", "password" => "password", "port" => 1234, "host" => "myhost.com"}
10
+ @connection = Babylon::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"], Babylon::XmppConnection, hash_including("handler" => handler_mock)).and_return(@connection)
16
+ Babylon::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"], Babylon::XmppConnection, hash_including("handler" => handler_mock)).and_raise(RuntimeError)
21
+ lambda {
22
+ Babylon::XmppConnection.connect(@params, handler_mock)
23
+ }.should raise_error(Babylon::NotConnected)
24
+ end
25
+
26
+ end
27
+
28
+ describe "initialize" do
29
+ it "should assign @connected to false" do
30
+ @connection.instance_variable_get("@connected").should be_false
31
+ end
32
+
33
+ it "should assign @jid to params['jid']" do
34
+ @connection.instance_variable_get("@jid").should == @params["jid"]
35
+ end
36
+
37
+ it "should assign @password to params['password']" do
38
+ @connection.instance_variable_get("@password").should == @params["password"]
39
+ end
40
+
41
+ it "should assign @host to params['host']" do
42
+ @connection.instance_variable_get("@host").should == @params["host"]
43
+ end
44
+
45
+ it "should assign @port to params['port']" do
46
+ @connection.instance_variable_get("@port").should == @params["port"]
47
+ end
48
+
49
+ it "should assign @handler to params['handler']" do
50
+ @connection.instance_variable_get("@handler").should == handler_mock
51
+ end
52
+
53
+ it "should assign @buffer to ''" do
54
+ @connection.instance_variable_get("@buffer").should == ""
55
+ end
56
+ end
57
+
58
+ describe "post_init" do
59
+ it "assigne a new parser" do
60
+ parser = Babylon::XmppParser.new(@connection.method(:receive_stanza))
61
+ Babylon::XmppParser.should_receive(:new).and_return(parser)
62
+ @connection.post_init
63
+ @connection.instance_variable_get("@parser").should == parser
64
+ end
65
+
66
+ end
67
+
68
+ describe "connection_completed" do
69
+ it "should write a log message" do
70
+ Babylon.logger.should_receive(:debug).with("CONNECTED")
71
+ @connection.connection_completed
72
+ end
73
+ it "should set @connected to true" do
74
+ @connection.connection_completed
75
+ @connection.instance_variable_get("@connected").should be_true
76
+ end
77
+ end
78
+
79
+ describe "unbind" do
80
+ it "should write a log message, and call on_disconnected" do
81
+ Babylon.logger.should_receive(:debug).with("DISCONNECTED")
82
+ handler_mock.should_receive(:on_disconnected)
83
+ @connection.unbind
84
+ end
85
+ it "should set @connected to false" do
86
+ @connection.connection_completed
87
+ @connection.unbind
88
+ @connection.instance_variable_get("@connected").should be_false
89
+ end
90
+ end
91
+
92
+ describe "receive_stanza" do
93
+
94
+ before(:each) do
95
+ @doc = Nokogiri::XML::Document.new
96
+ end
97
+
98
+ it "should write a log message for debug" do
99
+ Babylon.logger.should_receive(:debug).with(/PARSED/)
100
+ @connection.receive_stanza(Nokogiri::XML::Node.new("node", @doc))
101
+ end
102
+
103
+ describe "with an stanza that starts with stream:error" do
104
+
105
+ before(:each) do
106
+ @error_stanza = Nokogiri::XML::Node.new("stream:error", @doc)
107
+ end
108
+
109
+ it "should close the connection" do
110
+ @connection.should_receive(:close_connection)
111
+ @connection.receive_stanza(@error_stanza)
112
+ end
113
+
114
+ describe "with a malformed stanza error" do
115
+ before(:each) do
116
+ @xml_not_well_formed_stanza = Nokogiri::XML::Node.new("xml-not-well-formed", @doc)
117
+ @xml_not_well_formed_stanza.add_namespace("xmlns", "urn:ietf:params:xml:ns:xmpp-streams")
118
+ @error_stanza.add_child(@xml_not_well_formed_stanza)
119
+ end
120
+
121
+ it "should write an error to the log and raise an error" do
122
+ Babylon.logger.should_receive(:error).with(/DISCONNECTED DUE TO MALFORMED STANZA/)
123
+ lambda {@connection.receive_stanza(@error_stanza)}.should raise_error(Babylon::XmlNotWellFormed)
124
+ end
125
+ end
126
+ end
127
+
128
+ describe "with a stanza that is not an error" do
129
+ it "should call the on_stanza block" do
130
+ stanza = Nokogiri::XML::Node.new("message", @doc)
131
+ handler_mock.should_receive(:on_stanza)
132
+ @connection.receive_stanza(stanza)
133
+ end
134
+ end
135
+
136
+ end
137
+
138
+ describe "send_chunk" do
139
+ it "should raise an error if not connected" do
140
+ @connection.instance_variable_set("@connected", false)
141
+ lambda {
142
+ @connection.__send__(:send_chunk, "hello world")
143
+ }.should raise_error(Babylon::NotConnected)
144
+ end
145
+
146
+ it "should raise an error if the stanza size is above the limit" do
147
+ @connection.instance_variable_set("@connected", true)
148
+ string = "a" * (Babylon::XmppConnection.max_stanza_size + 1)
149
+ lambda {
150
+ @connection.__send__(:send_chunk, string)
151
+ }.should raise_error(Babylon::StanzaTooBig)
152
+ end
153
+
154
+ it "should return if the string is blank" do
155
+ @connection.instance_variable_set("@connected", true)
156
+ @connection.should_not_receive(:send_data)
157
+ @connection.__send__(:send_chunk, "")
158
+ end
159
+
160
+ it "should cann send_data with the string" do
161
+ @connection.instance_variable_set("@connected", true)
162
+ string = "hello world"
163
+ @connection.should_receive(:send_data).with(string)
164
+ @connection.__send__(:send_chunk, string)
165
+ end
166
+
167
+ end
168
+
169
+ describe "send_xml" do
170
+
171
+ before(:each) do
172
+ @connection.instance_variable_set("@connected", true)
173
+ @connection.stub!(:send_chunk).and_return(true)
174
+ @doc = Nokogiri::XML::Document.new
175
+ end
176
+
177
+ describe "with a nodeset as argument" do
178
+ before(:each) do
179
+ iq = Nokogiri::XML::Node.new("iq", @doc)
180
+ message = Nokogiri::XML::Node.new("message", @doc)
181
+ presence = Nokogiri::XML::Node.new("presence", @doc)
182
+ @node_set = Nokogiri::XML::NodeSet.new(@doc, [message, presence, iq])
183
+ end
184
+
185
+ it "should call send_chunk for each of the nodes in the set" do
186
+ @node_set.each do |node|
187
+ @connection.should_receive(:send_chunk).with(node.to_s)
188
+ end
189
+ @connection.send_xml(@node_set)
190
+ end
191
+ end
192
+
193
+ describe "with an argument with is not a NodeSet" do
194
+ before(:each) do
195
+ @message = Nokogiri::XML::Node.new("message", @doc)
196
+ end
197
+ it "should call send_chunk for the node" do
198
+ @connection.should_receive(:send_chunk).with(@message.to_s)
199
+ @connection.send_xml(@message)
200
+ end
201
+ end
202
+ end
203
+
204
+ describe "receive_data" do
205
+ before(:each) do
206
+ @connection.instance_variable_get("@parser").stub!(:push).and_return(true)
207
+ end
208
+
209
+ it "should show a message on the log" do
210
+ data = "<hello>hello world!</hello>"
211
+ Babylon.logger.should_receive(:debug).with("RECEIVED : #{data}")
212
+ @connection.__send__(:receive_data, data)
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
@@ -0,0 +1,268 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Babylon::XmppParser do
4
+
5
+ before(:each) do
6
+ @last_stanza = ""
7
+ @proc = mock(Proc, :call => true)
8
+ @parser = Babylon::XmppParser.new(@proc)
9
+ end
10
+
11
+ describe ".reset" do
12
+ it "should reset the document to nil" do
13
+ @parser.reset
14
+ @parser.elem.should be_nil
15
+ end
16
+
17
+ it "should reset the element to nil (no element is being parsed)" do
18
+ @parser.reset
19
+ @parser.elem.should be_nil
20
+ end
21
+
22
+ it "should reset the parser to a parser" do
23
+ new_parser = Nokogiri::XML::SAX::PushParser.new(@parser, "UTF-8")
24
+ Nokogiri::XML::SAX::PushParser.should_receive(:new).with(@parser, "UTF-8").and_return(new_parser)
25
+ @parser.reset
26
+ @parser.parser.should == new_parser
27
+ end
28
+ end
29
+
30
+ describe ".push" do
31
+ it "should send the data to the parser" do
32
+ data = "<name>me</name>"
33
+ @parser.parser.should_receive(:<<).with(data)
34
+ @parser.push(data)
35
+ end
36
+ end
37
+
38
+ describe ".characters" do
39
+ before(:each) do
40
+ @parser.doc = Nokogiri::XML::Document.new
41
+ @parser.elem = Nokogiri::XML::Element.new("element", @parser.doc)
42
+ end
43
+
44
+ it "should add the characters to the buffer" do
45
+ chars = "hello my name is julien"
46
+ @parser.characters(chars)
47
+ @parser.instance_variable_get("@buffer").should == chars
48
+ end
49
+
50
+ it "should concatenate the text if we receive in both pieces" do
51
+ chars = "hello my name is julien"
52
+ @parser.characters(chars)
53
+ @parser.instance_variable_get("@buffer").should == chars
54
+ chars2 = "and I'm french!"
55
+ @parser.characters(chars2)
56
+ @parser.instance_variable_get("@buffer").should == chars + chars2
57
+ end
58
+ end
59
+
60
+ describe ".start_element" do
61
+
62
+ before(:each) do
63
+ @new_elem_name = "new"
64
+ @new_elem_attributes = ["to", "you@yourserver.com/home", "xmlns", "http://ns.com"]
65
+ end
66
+
67
+ it "should create a new doc if we don't have one" do
68
+ new_doc = Nokogiri::XML::Document.new
69
+ @parser.doc = nil
70
+ Nokogiri::XML::Document.should_receive(:new).and_return(new_doc)
71
+ @parser.start_element(@new_elem_name, @new_elem_attributes)
72
+ @parser.doc.should == new_doc
73
+ end
74
+
75
+ it "should not create a new doc we already have one" do
76
+ @parser.doc = Nokogiri::XML::Document.new
77
+ Nokogiri::XML::Document.should_not_receive(:new)
78
+ @parser.start_element(@new_elem_name, @new_elem_attributes)
79
+ end
80
+
81
+ it "should create a new element" do
82
+ @doc = Nokogiri::XML::Document.new
83
+ @parser.doc = @doc
84
+ @new_elem = Nokogiri::XML::Element.new(@new_elem_name, @parser.doc)
85
+ Nokogiri::XML::Element.should_receive(:new).and_return(@new_elem)
86
+ @parser.start_element(@new_elem_name, @new_elem_attributes)
87
+ end
88
+
89
+ it "should add the new element as a child to the current element if there is one" do
90
+ @doc = Nokogiri::XML::Document.new
91
+ @parser.doc = @doc
92
+ @current = Nokogiri::XML::Element.new("element", @parser.doc)
93
+ @parser.elem = @current
94
+ @new_elem = Nokogiri::XML::Element.new(@new_elem_name, @parser.doc)
95
+ Nokogiri::XML::Element.stub!(:new).and_return(@new_elem)
96
+ @parser.start_element(@new_elem_name, @new_elem_attributes)
97
+ @new_elem.parent.should == @current
98
+ end
99
+
100
+ it "should add the new element as the child of the doc if there is none" do
101
+ @doc = Nokogiri::XML::Document.new
102
+ @parser.doc = @doc
103
+ @new_elem = Nokogiri::XML::Element.new(@new_elem_name, @parser.doc)
104
+ Nokogiri::XML::Element.stub!(:new).and_return(@new_elem)
105
+ @parser.start_element(@new_elem_name, @new_elem_attributes)
106
+ @new_elem.parent.should == @doc
107
+ end
108
+
109
+ it "should add the right attributes and namespaces to the newly created element" do
110
+ @parser.start_element(@new_elem_name, @new_elem_attributes)
111
+ @parser.elem["to"].should == "you@yourserver.com/home"
112
+ # TODO : FIX NAMESPACES : @parser.elem.namespaces.should == {"xmlns"=>"http://ns.com"}
113
+ @parser.elem.namespaces.should == {}
114
+ end
115
+
116
+ describe "when the new element is of name stream:stream" do
117
+ it "should callback" do
118
+ @proc.should_receive(:call)
119
+ @parser.start_element("stream:stream", [])
120
+ end
121
+
122
+ it "should reinit to nil the doc and the elem" do
123
+ @parser.start_element("stream:stream", [])
124
+ @parser.doc.should == nil
125
+ @parser.elem.should == nil
126
+ end
127
+ end
128
+ end
129
+
130
+ describe ".end_element" do
131
+ before(:each) do
132
+ @doc = Nokogiri::XML::Document.new
133
+ @parser.doc = @doc
134
+ @current = Nokogiri::XML::Element.new("element", @parser.doc)
135
+ @parser.elem = @current
136
+ end
137
+
138
+ it "should add the content of the buffer to the @elem" do
139
+ @elem = Nokogiri::XML::Element.new("element", @parser.doc)
140
+ chars = "hello world"
141
+ @parser.instance_variable_set("@buffer", chars)
142
+ @parser.elem = @elem
143
+ @parser.end_element("element")
144
+ @elem.content.should == chars
145
+ end
146
+
147
+ describe "when we're finishing the doc's root" do
148
+ before(:each) do
149
+ @parser.doc.root = @current
150
+ end
151
+
152
+ it "should callback" do
153
+ @proc.should_receive(:call)
154
+ @parser.end_element("element")
155
+ end
156
+
157
+ it "should reinit to nil the doc and the elem" do
158
+ @parser.end_element("element")
159
+ @parser.doc.should == nil
160
+ @parser.elem.should == nil
161
+ end
162
+ end
163
+
164
+ describe "when we're finishing another element" do
165
+ before(:each) do
166
+ @parser.doc.root = Nokogiri::XML::Element.new("root", @parser.doc)
167
+ @current.parent = @parser.doc.root
168
+ end
169
+
170
+ it "should go back up one level" do
171
+ @parser.end_element("element")
172
+ @parser.elem = @current.parent
173
+ end
174
+ end
175
+ end
176
+
177
+ describe ".add_namespaces_and_attributes_to_node" do
178
+ before(:each) do
179
+ @doc = Nokogiri::XML::Document.new
180
+ @parser.doc = @doc
181
+ @element = Nokogiri::XML::Element.new("element", @parser.doc)
182
+ @attrs = ["from", "me", "xmlns:atom", "http://www.w3.org/2005/Atom" ,"to", "you", "xmlns", "http://namespace.com"]
183
+ @parser.elem = @element
184
+ end
185
+
186
+ it "should assign even elements to attributes value or namespaces urls" do
187
+ @parser.__send__(:add_namespaces_and_attributes_to_current_node, @attrs)
188
+ even = []
189
+ @attrs.size.times do |i|
190
+ even << @attrs[i*2]
191
+ end
192
+ even.compact!
193
+ @element.attributes.keys.each do |k|
194
+ even.should include(k)
195
+ end
196
+ end
197
+
198
+ it "should assign odd elements to attributes names of namespaces prefixes" do
199
+ @parser.__send__(:add_namespaces_and_attributes_to_current_node, @attrs)
200
+ even = []
201
+ @attrs.size.times do |i|
202
+ even << @attrs[i*2+1]
203
+ end
204
+ even.compact!
205
+ @element.attributes.values.each do |v|
206
+ even.should include("#{v}")
207
+ end
208
+ end
209
+
210
+ it "should add namespace for each attribute name that starts with xmlns" do
211
+ @parser.__send__(:add_namespaces_and_attributes_to_current_node, @attrs)
212
+ # TODO: FIX NAMESPACES @element.namespaces.values.should == ["http://www.w3.org/2005/Atom", "http://namespace.com"]
213
+ @element.namespaces.values.should == []
214
+ end
215
+ end
216
+
217
+ describe "a communication with an XMPP Client" do
218
+
219
+ before(:each) do
220
+ @stanzas = []
221
+ @proc = Proc.new { |stanza|
222
+ @stanzas << stanza
223
+ }
224
+ @parser = Babylon::XmppParser.new(@proc)
225
+ end
226
+
227
+ it "should parse the right information" do
228
+ string = "<stream:stream
229
+ xmlns:stream='http://etherx.jabber.org/streams'
230
+ xmlns='jabber:component:accept'
231
+ from='plays.shakespeare.lit'
232
+ id='3BF96D32'>
233
+ <handshake/>
234
+ <message from='juliet@example.com'
235
+ to='romeo@example.net'
236
+ xml:lang='en'>
237
+ <body>Art thou not Romeo, and a Montague?</body>
238
+ <link href='http://sfbay.craigslist.org/search/sss?query=%2522mac+mini%2522+Intel+Core+Duo&amp;minAsk=min&amp;maxAsk=max&amp;format=rss&amp;format=rss' />
239
+ </message>"
240
+ pieces = rand(string.size/30)
241
+ # So we have to pick 'pieces' number between 0 and string.size
242
+ indices = []
243
+ pieces.times do |i|
244
+ indices[i] = rand(string.size)
245
+ end
246
+ # Now let's sort indices
247
+ indices.sort!
248
+ substrings = []
249
+ prev_index = 0
250
+ indices.each do |index|
251
+ substrings << string[prev_index, (index-prev_index)]
252
+ prev_index = index
253
+ end
254
+ substrings << string[prev_index, string.size]
255
+ #Just to make sure we split the string the right way!
256
+ substrings.join("").should == string
257
+
258
+ substrings.each do |s|
259
+ @parser.push(s)
260
+ end
261
+
262
+ @stanzas.join("").should == "<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:component:accept\" from=\"plays.shakespeare.lit\" id=\"3BF96D32\"/><handshake/><message from=\"juliet@example.com\" to=\"romeo@example.net\" xml:lang=\"en\">\n <body>Art thou not Romeo, and a Montague?</body>\n <link href=\"http://sfbay.craigslist.org/search/sss?query=%2522mac+mini%2522+Intel+Core+Duo&amp;minAsk=min&amp;maxAsk=max&amp;format=rss&amp;format=rss\"/>\n</message>"
263
+ @stanzas.last.at("link")["href"].should == "http://sfbay.craigslist.org/search/sss?query=%2522mac+mini%2522+Intel+Core+Duo&minAsk=min&maxAsk=max&format=rss&format=rss"
264
+ end
265
+
266
+ end
267
+
268
+ end