Permalink
Browse files

Added a mock server instead of mock stream

Made tests nastier, but when I have time I'll make the server respond appropriately,
so tests will only need to send stuff.
  • Loading branch information...
1 parent 4261d9f commit ba12de5ba79ad25033cb7ea7f318406f94bc3633 Jonas Westerlund committed Apr 5, 2012
Showing with 469 additions and 293 deletions.
  1. +6 −20 lib/irc.js
  2. +1 −1 lib/objects.js
  3. +17 −5 lib/observers.js
  4. +20 −13 spec/helpers.js
  5. +1 −1 spec/lib/config.json
  6. +173 −108 spec/lib/irc.spec.js
  7. +195 −78 spec/lib/objects.spec.js
  8. +0 −67 spec/mockstream.js
  9. +56 −0 spec/server.js
View
26 lib/irc.js
@@ -5,22 +5,16 @@
* http://irchelp.org/irchelp/rfc/ :D
*/
- // Exported in Makefile
-const TEST = process.env["IRCJS_TEST"] ? true : false
- , stream = TEST ? [ __dirname, "..", "spec", "mockstream" ]
- : [ "net" ]
-
// Standard imports
const events = require( "events" )
, fs = require( "fs" )
+ , net = require( "net" )
, path = require( "path" )
, tls = require( "tls" )
// Relative imports
, constants = require( "./constants" )
, map = require( "./map" )
, log = require( "./logger" )
- // THE OLD SWITCHEROO HAHAHAHA
- , net = require( path.join.apply( path, stream ) )
, notify = require( "./notifications" )
, objects = require( "./objects" )
, observers = require( "./observers" )
@@ -66,7 +60,6 @@ const getConfig = function( conf ) {
const MAXLEN = 510
/** IRC!
- * The star of the show.
*
* @constructor
* @param {string=} conf Path to config file. Defaults to "config.json" in current directory.
@@ -97,9 +90,6 @@ const IRC = function( conf ) {
this.connect = connect.bind( this, internal )
this.disconnect = disconnect.bind( this, internal )
this.send = send.bind( this, internal )
-
- // Add all default observers
- observers.register( this )
}
/** @private
@@ -130,10 +120,10 @@ const onConnect = function( internal ) {
*/
const disconnect = function( internal ) {
const since = internal.connectedSince
- internal.connectedSince = null
internal.queue.splice( 0 )
- internal.connected = false
internal.socket.end()
+ internal.connected = false
+ internal.connectedSince = null
internal.socket = null
this.observers.notify( EVENT.DISCONNECT )
this.observers.clear()
@@ -206,12 +196,8 @@ const connect = function( internal, callback ) {
internal.socket.addListener( SOCKET.DATA, onData.bind( this, internal ) )
internal.socket.addListener( SOCKET.TIMEOUT, this.disconnect )
- this.observe( REPLY.MYINFO, function( msg ) {
- const name = msg.params[1]
- logger.log( LEVEL.DEBUG, "[DEBUG] Updating server name from %s to %s", this.server.name, name )
- this.server.name = name
- return STATUS.SUCCESS | STATUS.REMOVE
- }.bind( this ) )
+ // Add all default observers
+ observers.register( this )
if ( 2 === arguments.length ) // Do all servers send a 001 ?
this.observe( REPLY.WELCOME
@@ -250,7 +236,7 @@ const write = function( sock, data ) {
logger.log( LEVEL.ERROR, "[ERROR] Socket is not open, but tried to send: %s", data )
return this
}
- const crlf = /\r\n$/.test( data ) ? "" : "\r\n"
+ const crlf = data.lastIndexOf( "\r\n" ) === data.length - 2 ? "" : "\r\n"
sock.write( data + crlf )
logger.log( LEVEL.INFO, "[SENT] %s", data )
return this
View
2 lib/objects.js
@@ -492,8 +492,8 @@ const handleJoinReply = function( callback, msg ) {
break
case REPLY.NAMREPLY:
status |= STATUS.SUCCESS | STATUS.REMOVE
- callback( this )
logger.log( LEVEL.DEBUG, "[DEBUG] Got name reply for %s, JOIN callback time", this.name )
+ callback( this )
break
default:
logger.log( LEVEL.DEBUG, "[DEBUG] Fell through the giant join switch. Message: %s", msg )
View
22 lib/observers.js
@@ -163,6 +163,13 @@ const onQuitCommand = function( msg ) {
}
// Numeric replies
+const onMyInfoReply = function( msg ) {
+ const name = msg.params[1]
+ logger.log( LEVEL.DEBUG, "[DEBUG] Updating server name from %s to %s", this.server.name, name )
+ this.server.name = name
+ return STATUS.SUCCESS | STATUS.REMOVE
+}
+
const onNameReply = function( msg ) {
const chan = this.channels.get( msg.params[2] )
, nicks = parser.nick( msg.params[3], this.config.die )
@@ -217,13 +224,16 @@ const onAnyError = function( msg ) {
const onForwardError = function( msg ) {
const from = msg.params[1]
, to = msg.params[2]
- if ( this.channels.contains( to ) )
+ if ( this.channels.contains( to ) ) {
logger.log( LEVEL.DEBUG, "[DEBUG] Forwarded from %s to %s, which already existed", from, to )
- else
- this.channels.add( to )
+ return
+ }
+ const chan = channel( to )
+ chan.people.add( this.user )
+ this.channels.add( chan.for( this ) )
+ this.channels.add( to )
+ logger.log( LEVEL.INFO, "[INFO] Got forwarded from %s to %s, adding %s", from, to, to )
- this.channels.remove( from )
- logger.log( LEVEL.DEBUG, "[DEBUG] Renamed channel %s to %s", from, to )
return STATUS.ERROR
}
@@ -247,6 +257,8 @@ const register = function( irc ) {
, onQuitCommand.bind( irc ) )
// Numeric replies
+ irc.observe( REPLY.MYINFO
+ , onMyInfoReply.bind( irc ) )
irc.observe( REPLY.NAMREPLY
, onNameReply.bind( irc ) )
irc.observe( REPLY.TOPIC
View
33 spec/helpers.js
@@ -1,25 +1,32 @@
const path = require( "path" )
, fs = require( "fs" )
, irc = require( path.join( __dirname, "..", "lib", "irc" ) )
- , conf = path.join( __dirname, "lib", "config.json" )
, fxtp = path.join( __dirname, "fixtures" )
- , strm = require( "./mockstream" )
+ , srv = require( "./server" )
-// Convenience wrapper around `it`, with added bottage
+const readFixture = function( fileName, fp ) {
+ return JSON.parse( fs.readFileSync( path.join( fp || fxtp, fileName ), "utf8" ) )
+}
+
+const conf = path.join( __dirname, "lib", "config.json" )
+ , jonf = JSON.parse( fs.readFileSync( conf, "utf8" ) )
+
+const server = srv.server
+
+server.listen( jonf.server.port, jonf.server.address, function() {
+ console.info( "LISTENING" )
+})
+
+const bot = new irc.IRC( conf ).connect()
+
+// Convenience wrapper around `it`, with added bottage/servage
const bit = function( desc, f ) {
- const bot = new irc.IRC( conf ).connect()
- // Expose stuff for convenience
+ server.removeAllListeners( "message" )
if ( ! f )
return it( desc )
- bot._stream = strm.MockStream.current
- fbot = f.bind( bot )
- return it( desc, fbot )
-}
-
-const readFixture = function( fileName ) {
- return JSON.parse( fs.readFileSync( path.join( fxtp, fileName ), "utf8" ) )
+ it( desc, f.bind( bot ) )
}
exports.bit = bit
-exports.conf = JSON.parse( fs.readFileSync( conf, "utf8" ) )
+exports.conf = jonf
exports.readFixture = readFixture
View
2 spec/lib/config.json
@@ -21,7 +21,7 @@
, "server" :
{ "//" : "IRC server address"
- , "address" : "chat.freenode.net"
+ , "address" : "localhost"
, "//" : "IRC server port"
, "port" : 6667
View
281 spec/lib/irc.spec.js
@@ -6,13 +6,16 @@ const f = require( "util" ).format
, help = require( path.join( __dirname, "..", "helpers" ) )
, o = require( path.join( lib, "objects" ) )
, cs = require( path.join( lib, "constants" ) )
- , IRC = require( path.join( lib, "irc" ) ).IRC
+ , irc = require( path.join( lib, "irc" ) )
+ , IRC = irc.IRC
+ , server = require( path.join( "..", "server" ) ).server
, bit = help.bit
, conf = help.conf
, COMMAND = cs.COMMAND
, EVENT = cs.EVENT
- , REPLY = cs.REPLY
, MODE = cs.MODE
+ , REPLY = cs.REPLY
+ , STATUS = irc.STATUS
// Make sure config files are up to date
const defaultConf = JSON.parse( fs.readFileSync( path.join( lib, "config.json" ) ) )
@@ -23,41 +26,66 @@ const defaultConf = JSON.parse( fs.readFileSync( path.join( lib, "config.json" )
describe( "irc", function() {
describe( "IRC", function() {
describe( "send", function() {
- bit( "should append \"\\r\\n\" if not present", function() {
- this.send( o.message( COMMAND.PRIVMSG, [ "#nou", "NO U" ] ) )
- this._stream.output[0].should.equal( "PRIVMSG #nou NO U\r\n" )
+ bit( "should append \"\\r\\n\" if not present", function( done ) {
+ server.on( "message", function ok( d ) {
+ if ( /PRIVMSG #nou/.test( d ) ) {
+ server.removeListener( "message", ok )
+ d.should.equal( "PRIVMSG #nou :NO U\r\n" )
+ done()
+ }
+ })
+ this.send( o.message( COMMAND.PRIVMSG, [ "#nou", ":NO U" ] ) )
})
- bit( "should truncate messages to 512 chars (including \"\\r\\n\")", function() {
- const longAssString = f( ":%s", Array( 567 ).join( "*" ) )
+ bit( "should truncate messages to 512 chars (including \"\\r\\n\")", function( done ) {
+ const longAssString = ":" + Array( 567 ).join( "*" )
+ server.on( "message", function ok( d ) {
+ if ( /PRIVMSG #longassstrings/.test( d ) ) {
+ server.removeListener( "message", ok )
+ d.length.should.equal( 512 )
+ done()
+ }
+ })
this.send( o.message( COMMAND.PRIVMSG, [ "#longassstrings", longAssString ] ) )
- this._stream.output[0].length.should.equal( 512 )
})
})
describe( "connect", function() {
// Pass is set in spec/lib/config.json
bit( "should send the server password, if provided, on connect", function() {
- this._stream.output[2].should.equal( f( "PASS %s\r\n", conf.user.password ) )
+ server.received[server.received.length - 1].should.equal( f( "PASS %s\r\n", conf.user.password ) )
})
// Modes set in config
bit( "should send user information with correct modes", function() {
- this._stream.output[0]
+ server.received[server.received.length - 3]
.should.equal( f( "USER %s 12 * :%s\r\n", conf.user.username, conf.user.realname ) )
})
- bit( "should connect after having been disconnected", function( done ) {
- this.disconnect()
- this.connect( function( b ) {
+ bit( "should reconnect after having been disconnected", function( done ) {
+ const bot = this
+ bot.disconnect()
+ bot.connect( function( b ) {
b.should.be.an.instanceof( IRC )
done()
+ return STATUS.REMOVE
+ })
+ server.on( "connection", function( s ) {
+ server.recite( f( ":crichton.freenode.net 001 %s :Welcome to the freenode IRC Network js-irc\r\n"
+ , bot.user.nick ) )
})
- this._stream.emit( "data", f( ":crichton.freenode.net 001 %s :Welcome to the freenode IRC Network js-irc\r\n", this.user.nick ) )
})
- bit( "should update server name on 004", function() {
- this._stream.emit( "data", f( ":holmes.freenode.net 004 %s holmes.freenode.net ircd-seven-1.1.3 DOQRSZaghilopswz CFILMPQbcefgijklmnopqrstvz bkloveqjfI\r\n", this.user.nick ) )
- this.server.name.should.equal( "holmes.freenode.net" )
+ bit( "should update server name on 004", function( done ) {
+ const bot = this
+ bot.observe( REPLY.MYINFO, function() {
+ bot.server.name.should.equal( "holmes.freenode.net" )
+ done()
+ // Better set it back now :)
+ bot.server.name = conf.server.address
+ return STATUS.REMOVE
+ })
+ server.recite( f( ":holmes.freenode.net 004 %s holmes.freenode.net ircd-seven-1.1.3 DOQRSZaghilopswz CFILMPQbcefgijklmnopqrstvz bkloveqjfI\r\n"
+ , this.user.nick ) )
})
})
@@ -66,53 +94,73 @@ describe( "irc", function() {
})
describe( "quit", function() {
- bit( "should quit without a message", function() {
- const sock = this._stream
+ bit( "should quit without a message", function( done ) {
+ const bot = this
+ server.on( "message", function ok( m ) {
+ if ( ! /QUIT/.test( m ) )
+ return
+ m.should.equal( "QUIT\r\n" )
+ bot.connect( function() { done() } )
+ server.removeListener( "message", ok )
+ })
this.quit()
- sock.output[0].should.equal( "QUIT\r\n" )
- sock.mockEnded.should.be.ok
})
- bit( "should quit with a message", function() {
- const sock = this._stream
- this.quit( "LOL BAI" )
- sock.output[0].should.equal( "QUIT :LOL BAI\r\n" )
- sock.mockEnded.should.be.ok
+ bit( "should quit with a message", function( done ) {
+ const msg = "QUIT :LOL BAI\r\n", bot = this
+ server.on( "message", function ok( m ) {
+ if ( ! /QUIT/.test( m ) )
+ return
+ m.should.equal( msg )
+ bot.connect( function() { done() } )
+ server.removeListener( "message", ok )
+ })
+ this.quit( msg.slice( 6, -2 ) )
})
- bit( "should disconnect and end the socket", function() {
- const sock = this._stream
+ bit( "should disconnect and end the socket", function( done ) {
+ const bot = this
+ server.on( "end", function ok() {
+ server.removeListener( "message", ok )
+ bot.connect( function() { done() } )
+ })
this.quit()
- sock.mockEnded.should.be.ok
})
})
describe( "setMode", function() {
- bit( "should set various modes on the current user", function() {
- this.user.nick = "pewpew"
+ bit( "should set various modes on the current user", function( done ) {
+ const bot = this
this.setMode( "-o" )
- this._stream.output[0].should.equal( f( "MODE %s -o\r\n", this.user.nick ) )
+ server.on( "message", function ok( m ) {
+ if ( ! /MODE/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "MODE %s -o\r\n", bot.user.nick ) )
+ done()
+ })
})
})
describe( "list", function() {
- it( "should get the information for a given channel", function() {
- })
-
- it( "should get the information for all channels on a server", function() {
- })
+ it( "should get the information for a given channel" )
+ it( "should get the information for all channels on a server" )
})
describe( "send", function() {
- bit( "should send Message objects", function() {
- this.channels.add( "#asl" ).say( "hey sup everyone?" )
- this._stream.output[0].should.equal( "PRIVMSG #asl :hey sup everyone?\r\n" )
-
+ bit( "should send Message objects", function( done ) {
+ const bot = this
+ server.on( "message", function ok( m ) {
+ if ( ! /PRIVMSG/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( "PRIVMSG #asl :Sending stuff\r\n" )
+ done()
+ })
this.send( o.message( COMMAND.PRIVMSG, [ "#asl", ":Sending stuff" ] ) )
- this._stream.output[0].should.equal( "PRIVMSG #asl :Sending stuff\r\n" )
})
- // TODO reimplement
+ /** @todo reimplement */
bit( "should split long messages into multiple messages" )
})
@@ -125,9 +173,9 @@ describe( "irc", function() {
ch.should.equal( chan )
done()
})
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, chan, this.user.nick ) )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n"
+ , this.user.nick, chan, this.user.nick ) )
})
bit( "should let you add Channel objects", function( done ) {
@@ -138,45 +186,60 @@ describe( "irc", function() {
bot.channels.get( ch ).should.equal( chan )
done()
})
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, chan, this.user.nick ) )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, chan, this.user.nick ) )
})
bit( "should let you remove channels by name", function( done ) {
const chan = "#removechanname", bot = this
this.channels.add( chan, function( ch ) {
bot.channels.contains( chan ).should.equal( true )
+ server.on( "message", function ok( m ) {
+ if ( ! /PART/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "PART %s\r\n", chan ) )
+ server.recite( f( ":%s!~a@b.c PART %s\r\n", bot.user.nick, chan ) )
+ done()
+ })
bot.channels.remove( chan )
- bot._stream.output[0].should.equal( f( "PART %s\r\n", chan ) )
- bot._stream.emit( "data", f( ":%s!~a@b.c PART %s\r\n", bot.user.nick, chan ) )
- bot.channels.contains( chan ).should.equal( false )
- done()
})
- this._stream.output[0].should.equal( f( "JOIN %s\r\n", chan ) )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s\r\n", this.user.nick, chan, this.user.nick ) )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s\r\n", this.user.nick, chan, this.user.nick ) )
})
bit( "should let you remove Channel objects", function( done ) {
const chan = new o.Channel( "#removechanobj" ), bot = this
this.channels.add( chan, function( ch ) {
bot.channels.contains( chan ).should.equal( true )
+ server.on( "message", function ok( m ) {
+ if ( ! /PART/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "PART %s\r\n", chan ) )
+ })
bot.channels.remove( chan )
- bot._stream.output[0].should.equal( f( "PART %s\r\n", chan ) )
- bot._stream.emit( "data", f( ":%s!~a@b.c PART %s\r\n", bot.user.nick, chan ) )
- bot.channels.contains( chan ).should.equal( false )
+ bot.observe( COMMAND.PART, function() {
+ bot.channels.contains( chan ).should.equal( false )
+ return STATUS.REMOVE
+ })
+ server.recite( f( ":%s!~a@b.c PART %s\r\n", bot.user.nick, chan ) )
done()
})
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s\r\n", this.user.nick, chan, this.user.nick ) )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s\r\n", this.user.nick, chan, this.user.nick ) )
})
bit( "should add people to its list of users, for various relevant messages", function( done ) {
const bot = this
- , chan = this.channels.add( "#addpeople", function( ch ) {
+ , chan = this.channels.add( "#addpeople" )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ // A name reply for a channel
+ server.recite( f( ":niven.freenode.net 353 %s @ %s :some +different @nicks\r\n", conf.nick, chan ) )
+ // A specific user joins
+ server.recite( f( ":protobot!~protobot@lol.com JOIN %s\r\n", chan ) )
+
+ setTimeout( function() {
should.exist( chan.people.get( "protobot" ) )
chan.people.get( "protobot" ).should.be.an.instanceof( o.Person )
should.exist( chan.people.get( "some" ) )
@@ -186,41 +249,44 @@ describe( "irc", function() {
chan.people.get( "different" ).should.be.an.instanceof( o.Person )
chan.people.get( "nicks" ).should.be.an.instanceof( o.Person )
done()
- })
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- // A specific user JOINs
- bot._stream.emit( "data", f( ":protobot!~protobot@lol.com JOIN %s\r\n", chan ) )
- // A name reply for a channel
- bot._stream.emit( "data", f( ":niven.freenode.net 353 %s @ %s :some +different @nicks\r\n", conf.nick, chan ) )
+ }, 10 )
})
- bit( "should remove people from its list of users", function() {
- const chan = this.channels.add( "#removepeople" )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ bit( "should remove people from its list of users", function( done ) {
+ const chan = this.channels.add( "#removepeople" ), bot = this
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", bot.user.nick, chan ) )
// Hit and run lol
- this._stream.emit( "data", ":protobot!~protobot@rogers.com JOIN #removepeople\r\n" )
- this._stream.emit( "data", ":protobot!~protobot@rogers.com PART #removepeople\r\n" )
- should.not.exist( this.channels.get( "#removepeople" ).people.get( "protobot" ) )
+ server.recite( ":protobot1!~protobot@rogers.com JOIN #removepeople\r\n" )
+ server.recite( ":protobot1!~protobot@rogers.com PART #removepeople\r\n" )
// getting kicked should also remove the person
- this._stream.emit( "data", ":protobot!~protobot@rogers.com JOIN #removepeople\r\n" )
- this._stream.emit( "data", ":nemesis!~nemesis@rogers.com KICK #removepeople protobot\r\n" )
- should.not.exist( this.channels.get( "#removepeople" ).people.get( "protobot" ) )
+ server.recite( ":protobot2!~protobot@rogers.com JOIN #removepeople\r\n" )
+ server.recite( ":evilbot!~nemesis@rogers.com KICK #removepeople protobot2\r\n" )
// also quitting
- this.channels.add( "#quitters" )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, "#quitters" ) )
- this._stream.emit( "data", ":protobot!~protobot@rogers.com JOIN #removepeople\r\n" )
- this._stream.emit( "data", ":protobot!~protobot@rogers.com JOIN #quitters\r\n" )
- this._stream.emit( "data", ":protobot!~protobot@rogers.com QUIT :Oh no!\r\n" )
- should.not.exist( this.channels.get( "#removepeople" ).people.get( "protobot" ) )
- should.not.exist( this.channels.get( "#quitters" ).people.get( "protobot" ) )
+ bot.channels.add( "#quitters" )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", bot.user.nick, "#quitters" ) )
+ server.recite( ":protobot3!~protobot@rogers.com JOIN #removepeople\r\n" )
+ server.recite( ":protobot3!~protobot@rogers.com JOIN #quitters\r\n" )
+ server.recite( ":protobot3!~protobot@rogers.com QUIT :Laterz\r\n" )
+ setTimeout( function() {
+ should.not.exist( bot.channels.get( "#removepeople" ).people.get( "protobot1" ) )
+ should.not.exist( bot.channels.get( "#removepeople" ).people.get( "protobot2" ) )
+ should.not.exist( bot.channels.get( "#removepeople" ).people.get( "protobot3" ) )
+ should.not.exist( bot.channels.get( "#quitters" ).people.get( "protobot3" ) )
+ done()
+ }, 10 )
})
- bit( "should remove a channel if kicked from it", function() {
- const chan = this.channels.add( "#kickedfrom" )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this.channels.contains( chan ).should.equal( true )
- this._stream.emit( "data", f( ":kicky@kick.com KICK #lol,%s @other,%s,+another\r\n", chan, this.user.nick ) )
- this.channels.contains( chan ).should.equal( false )
+ bit( "should remove a channel if kicked from it", function( done ) {
+ const chan = this.channels.add( "#kickedfrom" ), bot = this
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", bot.user.nick, chan ) )
+ setTimeout( function() {
+ bot.channels.contains( chan ).should.equal( true )
+ server.recite( f( ":kicky@kick.com KICK #lol,%s @other,%s,+another\r\n", chan, bot.user.nick ) )
+ setTimeout( function() {
+ bot.channels.contains( chan ).should.equal( false )
+ done()
+ }, 10 )
+ }, 10 )
})
bit( "should create only one Person instance per user", function( done ) {
@@ -232,12 +298,10 @@ describe( "irc", function() {
c1.people.get( nick ).should.equal( c2.people.get( nick ) )
done()
})
- this._stream.emit( "data", f( ":%s@wee JOIN %s\r\n", this.user.nick, c1 ) )
- this._stream.emit( "data", f( ":%s@wee JOIN %s\r\n", this.user.nick, c2 ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, c1, nick ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, c2, nick ) )
+ server.recite( f( ":%s@wee JOIN %s\r\n", this.user.nick, c1 ) )
+ server.recite( f( ":%s@wee JOIN %s\r\n", this.user.nick, c2 ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, c1, nick ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, c2, nick ) )
})
bit( "should know that lol{}|^ is the same as LOL[]\\~", function( done ) {
@@ -246,36 +310,37 @@ describe( "irc", function() {
bot.channels.contains( "#LOL[]\\~" ).should.equal( true )
done()
})
- this._stream.emit( "data", f( ":%s@wee JOIN %s\r\n", this.user.nick, lol ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, lol, this.user.nick ) )
+ server.recite( f( ":%s@wee JOIN %s\r\n", this.user.nick, lol ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n"
+ , this.user.nick, lol, this.user.nick ) )
})
bit( "should rename the channel if forwarded", function( done ) {
const c1 = o.channel( "#fwdfrom" )
, c2 = o.channel( "#fwdto" )
+ , bot = this
this.channels.add( c1, function( ch, err ) {
err.should.be.an.instanceof( Error )
err.message.should.equal( "Forwarding to another channel" )
ch.name.should.equal( c2.name )
+ bot.channels.contains( c2 ).should.equal( true )
+ bot.channels.contains( "#fwdfrom" ).should.equal( false )
done()
})
- this._stream.emit( "data"
- , f( ":holmes.freenode.net 470 %s %s %s :Forwarding to another channel\r\n", this.user.nick, c1, c2 ) )
- this._stream.emit( "data", f( ":%s@wee JOIN %s\r\n", this.user.nick, c2 ) )
- this.channels.contains( c2 ).should.equal( true )
- this.channels.contains( "#fwdfrom" ).should.equal( false )
- c1.name.should.equal( c2.name )
+ server.recite( f( ":holmes.freenode.net 470 %s %s %s :Forwarding to another channel\r\n"
+ , this.user.nick, c1, c2 ) )
+ server.recite( f( ":%s@wee JOIN %s\r\n", this.user.nick, c2 ) )
})
})
bit( f( "should emit all events as a `%s` event with message as first parameter", EVENT.ANY ), function( done ) {
this.observe( EVENT.ANY, function( msg ) {
msg.type.should.equal( COMMAND.PRIVMSG )
done()
+ return STATUS.REMOVE
})
- this._stream.emit( "data", ":gf3!n=gianni@pdpc/supporter/active/gf3 PRIVMSG #runlevel6 :NO U LOL\r\n")
+ server.recite( ":gf3!n=gianni@pdpc/supporter/active/gf3 PRIVMSG #runlevel6 :ANY LOL\r\n")
})
})
View
273 spec/lib/objects.spec.js
@@ -7,6 +7,7 @@ const f = require( "util" ).format
, IRC = require( path.join( lib, "irc" ) )
, cs = require( path.join( lib, "constants" ) )
, o = require( path.join( lib, "objects" ) )
+ , server = require( path.join( "..", "server" ) ).server
, bit = help.bit
, COMMAND = cs.COMMAND
, ERROR = cs.ERROR
@@ -19,27 +20,45 @@ const msgs = help.readFixture( "messages.json" )
describe( "objects", function() {
describe( "Message", function() {
describe( "send", function() {
- bit( "should send itself", function() {
+ bit( "should send itself", function( done ) {
const txt = o.trailing( "Message, send thyself" )
, msg = o.message( COMMAND.PRIVMSG, [ "#nlogax", txt ] ).for( this )
+ server.on( "message", function ok( m ) {
+ if ( ! /PRIVMSG #nlogax/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( "PRIVMSG #nlogax :Message, send thyself\r\n" )
+ done()
+ })
msg.send()
- this._stream.output[0].should.equal( f( "PRIVMSG #nlogax %s\r\n", txt ) )
})
})
describe( "reply", function() {
- bit( "should reply to channel messages", function() {
+ bit( "should reply to channel messages", function( done ) {
const msg = o.message( o.person( "gf3" ), COMMAND.PRIVMSG
, [ "#jquery-ot", ":wat" ] ).for( this )
+ server.on( "message", function ok( m ) {
+ if ( ! /PRIVMSG #jquery-ot/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( "PRIVMSG #jquery-ot :Is these a bug?\r\n" )
+ done()
+ })
msg.reply( "Is these a bug?" )
- this._stream.output[0].should.equal( "PRIVMSG #jquery-ot :Is these a bug?\r\n" )
})
- bit( "should reply to direct messages", function() {
+ bit( "should reply to direct messages", function( done ) {
const msg = o.message( o.person( "gf3" ), COMMAND.PRIVMSG
, [ this.user.nick, ":wat" ] ).for( this )
+ server.on( "message", function ok( m ) {
+ if ( ! /PRIVMSG gf3/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( "PRIVMSG gf3 :Is these a bug?\r\n" )
+ done()
+ })
msg.reply( "Is these a bug?" )
- this._stream.output[0].should.equal( "PRIVMSG gf3 :Is these a bug?\r\n" )
})
})
@@ -86,114 +105,176 @@ describe( "objects", function() {
})
describe( "topic", function() {
- bit( "should set its own topic", function() {
+ bit( "should set its own topic", function( done ) {
const chan = o.channel( "#setowntopic" ).for( this )
, topic = "My own topic should be set to this"
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.on( "message", function ok( m ) {
+ if ( ! /TOPIC #setowntopic/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ server.recite( f( ":topic@setter.com TOPIC %s :%s\r\n", chan, topic ) )
+ setTimeout( function() {
+ chan.topic.should.equal( topic )
+ done()
+ }, 10 )
+ })
chan.setTopic( topic )
- this._stream.output[0].should.equal( f( "TOPIC %s :%s\r\n", chan, topic ) )
})
- bit( "should keep its topic updated", function() {
+ bit( "should keep its topic updated", function( done ) {
const chan = this.channels.add( "#updatetopic" ).for( this )
, topic = "This topic is so up to date"
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data", f( ":topic@setter.com TOPIC %s :%s\r\n", chan, topic ) )
- chan.topic.should.equal( topic )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":topic@setter.com TOPIC %s :%s\r\n", chan, topic ) )
+ setTimeout( function() {
+ chan.topic.should.equal( topic )
+ done()
+ }, 10 )
})
})
describe( "mode", function() {
- bit( "should record the channel mode", function() {
+ bit( "should record the channel mode", function( done ) {
const chan = o.channel( "#gotmodez" )
this.channels.add( chan )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data", ":the.server.com MODE #gotmodez +am-i\r\n" )
- chan.mode.should.equal( MODE.CHANNEL.ANONYMOUS | MODE.CHANNEL.MODERATED )
- this._stream.emit( "data", ":the.server.com MODE #gotmodez +i\r\n" )
- chan.mode.should.equal( MODE.CHANNEL.ANONYMOUS | MODE.CHANNEL.MODERATED | MODE.CHANNEL.INVITE )
- this._stream.emit( "data", ":the.server.com MODE #gotmodez -a\r\n" )
- chan.mode.should.equal( MODE.CHANNEL.MODERATED | MODE.CHANNEL.INVITE )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( ":the.server.com MODE #gotmodez +am-i\r\n" )
+ setTimeout( function() {
+ chan.mode.should.equal( MODE.CHANNEL.ANONYMOUS | MODE.CHANNEL.MODERATED )
+ done()
+ }, 10 )
})
- bit( "should set the channel mode from a mask", function() {
+ bit( "should set the channel mode from a mask", function( done ) {
// This is silly, but when turning the mask into a string, every mode *not* set is _un_set
// @todo {jonas} Make unsilly
const mode = "-a+i-mnpqrs+t-bOeIklov"
, chan = o.channel( "#modezmask" )
+ , bot = this
this.channels.add( chan )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.on( "message", function ok( m ) {
+ if ( ! /MODE #modezmask/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "MODE %s %s\r\n", chan, mode ) )
+ bot.observe( COMMAND.MODE, function( msg ) {
+ if ( msg.params[0] !== chan.name )
+ return
+ chan.mode.should.equal( MODE.CHANNEL.INVITE | MODE.CHANNEL.TOPIC )
+ chan.mode.should.equal( MODE.CHANNEL.INVITE | MODE.CHANNEL.TOPIC )
+ done()
+ })
+ server.recite( f( ":lol@omg.com MODE %s %s\r\n", chan, mode ) )
+ })
chan.setMode( MODE.CHANNEL.INVITE | MODE.CHANNEL.TOPIC )
- this._stream.output[0].should.equal( f( "MODE %s %s\r\n", chan, mode ) )
- this._stream.emit( "data", f( ":lol@omg.com MODE %s %s\r\n", chan, mode ) )
- chan.mode.should.equal( MODE.CHANNEL.INVITE | MODE.CHANNEL.TOPIC )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
})
- bit( "should set the channel mode from a string", function() {
+ bit( "should set the channel mode from a string", function( done ) {
const chan = this.channels.add( "#modez" )
, mode = "+it"
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- chan.setMode( "+it" )
- this._stream.output[0].should.equal( f( "MODE %s %s\r\n", chan, mode ) )
- this._stream.emit( "data", f( ":lol@omg.com MODE %s %s\r\n", chan, mode ) )
- chan.mode.should.equal( MODE.CHANNEL.INVITE | MODE.CHANNEL.TOPIC )
+ server.on( "message", function ok( m ) {
+ if ( ! /MODE #modez/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "MODE %s %s\r\n", chan, mode ) )
+ server.recite( f( ":lol@omg.com MODE %s %s\r\n", chan, mode ) )
+ })
+ this.observe( COMMAND.MODE, function() {
+ chan.mode.should.equal( MODE.CHANNEL.INVITE | MODE.CHANNEL.TOPIC )
+ done()
+ })
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ chan.setMode( mode )
})
})
describe( "invite", function() {
- bit( "should invite people by name", function() {
+ bit( "should invite people by name", function( done ) {
const chan = o.channel( "#peoplewithnames" ).for( this )
, user = "namedperson"
+ server.on( "message", function ok( m ) {
+ if ( ! /INVITE/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "INVITE %s %s\r\n", user, chan ) )
+ done()
+ })
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n"
+ , this.user.nick, chan, this.user.nick ) )
chan.invite( user )
- this._stream.output[0].should.equal( f( "INVITE %s %s\r\n", user, chan ) )
})
- bit( "should invite Person objects", function() {
+ bit( "should invite Person objects", function( done ) {
const chan = o.channel( "#objectified" ).for( this )
, user = o.person( "obj", "lol", "omg" )
+ server.on( "message", function ok( m ) {
+ if ( ! /INVITE/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "INVITE %s %s\r\n", user.nick, chan ) )
+ done()
+ })
chan.invite( user )
- this._stream.output[0].should.equal( f( "INVITE %s %s\r\n", user.nick, chan ) )
})
})
describe( "join", function() {
- bit( "should join a Channel object", function() {
+ bit( "should join a Channel object", function( done ) {
const chan = o.channel( "#joiners" ).for( this )
+ server.on( "message", function ok( m ) {
+ if ( ! /JOIN/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "JOIN %s\r\n", chan.name ) )
+ done()
+ })
chan.join()
- this._stream.output[0].should.equal( f( "JOIN %s\r\n", chan.name ) )
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n"
+ , this.user.nick, chan, this.user.nick ) )
})
bit( "should join a Channel object with a key", function( done ) {
const chan = o.channel( "#keyjoin" ).for( this )
, key = "keymaster"
, bot = this
- this.observe( REPLY.NAMREPLY, function( ch ) {
+ chan.join( key, function( ch ) {
bot.channels.contains( chan ).should.equal( true )
done()
})
- chan.join( key )
this.channels.contains( chan ).should.equal( false )
- this._stream.output[0].should.equal( f( "JOIN %s %s\r\n", chan.name, key ) )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, chan, this.user.nick ) )
+ server.on( "message", function ok( m ) {
+ if ( ! /JOIN/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "JOIN %s %s\r\n", chan.name, key ) )
+ })
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n"
+ , this.user.nick, chan, this.user.nick ) )
})
bit( "should join a Channel object with a callback", function( done ) {
const chan = o.channel( "#callbackz" ).for( this )
, bot = this
chan.join( function( ch ) {
chan.should.equal( ch )
- // Since we give the callback after a 353, people should be available
ch.people.contains( bot.user ).should.equal( true )
ch.people.contains( "nlogax" ).should.equal( true )
done()
})
- this._stream.output[0].should.equal( f( "JOIN %s\r\n", chan.name ) )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, chan, this.user.nick ) )
- this.channels.contains( chan ).should.equal( true )
+ server.on( "message", function ok( m ) {
+ if ( ! /JOIN/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "JOIN %s\r\n", chan.name ) )
+ })
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n"
+ , this.user.nick, chan, this.user.nick ) )
})
bit( "should join a Channel object with a key and a callback", function( done ) {
@@ -203,11 +284,14 @@ describe( "objects", function() {
chan.should.equal( ch )
done()
})
- this._stream.output[0].should.equal( f( "JOIN %s %s\r\n", chan.name, key ) )
- this._stream.emit( "data", f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
- this._stream.emit( "data"
- , f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, chan, this.user.nick ) )
- this.channels.contains( chan ).should.equal( true )
+ server.on( "message", function ok( m ) {
+ if ( ! /JOIN/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "JOIN %s %s\r\n", chan.name, key ) )
+ })
+ server.recite( f( ":%s!~a@b.c JOIN %s\r\n", this.user.nick, chan ) )
+ server.recite( f( ":card.freenode.net 353 %s @ %s :%s nlogax\r\n", this.user.nick, chan, this.user.nick ) )
})
// All error responses to joining a channel except ERR_NEEDMOREPARAMS
@@ -236,35 +320,51 @@ describe( "objects", function() {
if ( ++i === l )
done()
})
- bot._stream.output[0].should.equal( f( "JOIN %s\r\n", chan.name ) )
- bot._stream.emit( "data"
- , f( ":n.o.u %s %s :%s\r\n", e, chan, f( "Cannot join channel (%s)", e ) ) )
+ server.recite( f( ":n.o.u %s %s :%s\r\n", e, chan, f( "Cannot join channel (%s)", e ) ) )
})
})
})
describe( "kick", function() {
- bit( "should kick people by name", function() {
- const chan = o.channel( "#meanies" ).for( this )
+ bit( "should kick people by name", function( done ) {
+ const chan = o.channel( "#meanies" ).for( this ).join()
, user = "victim"
+ server.on( "message", function ok( m ) {
+ if ( ! /KICK/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "KICK %s %s\r\n", chan, user ) )
+ done()
+ })
chan.kick( user )
- this._stream.output[0].should.equal( f( "KICK %s %s\r\n", chan, user ) )
})
- bit( "should kick Person objects", function() {
- const chan = o.channel( "#meanies" ).for( this )
+ bit( "should kick Person objects", function( done ) {
+ const chan = o.channel( "#meanies" ).for( this ).join()
, user = o.person( "victim" )
+ server.on( "message", function ok( m ) {
+ if ( ! /KICK/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "KICK %s %s\r\n", chan, user.nick ) )
+ done()
+ })
chan.kick( user )
- this._stream.output[0].should.equal( f( "KICK %s %s\r\n", chan, user.nick ) )
})
})
describe( "notify", function() {
- bit( "should get notified", function() {
+ bit( "should get notified", function( done ) {
const chan = o.channel( "#notifications" ).for( this )
, notice = "Important announcement"
+ server.on( "message", function ok( m ) {
+ if ( ! /NOTICE/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "NOTICE %s :%s\r\n", chan, notice ) )
+ done()
+ })
chan.notify( notice )
- this._stream.output[0].should.equal( f( "NOTICE %s :%s\r\n", chan, notice ) )
})
})
@@ -292,39 +392,56 @@ describe( "objects", function() {
})
describe( "kickFrom", function() {
- bit( "should get kicked from a channel by name", function() {
+ bit( "should get kicked from a channel by name", function( done ) {
const prsn = o.person( "kicked1", "ki", "ck" ).for( this )
, chan = "#namekick"
+ server.on( "message", function ok( m ) {
+ if ( ! /KICK/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "KICK %s %s\r\n", chan, prsn.nick ) )
+ done()
+ })
prsn.kickFrom( chan )
- this._stream.output[0].should.equal( f( "KICK %s %s\r\n", chan, prsn.nick ) )
})
- bit( "should get kicked from a Channel object", function() {
+ bit( "should get kicked from a Channel object", function( done ) {
const prsn = o.person( "kicked2", "bo", "om" ).for( this )
- , chan = o.channel( "#objkick" )
+ , chan = o.channel( "#objkick" ).for( this ).join()
+ server.on( "message", function ok( m ) {
+ if ( ! /KICK/.test( m ) )
+ return
+ server.removeListener( "message", ok )
+ m.should.equal( f( "KICK %s %s\r\n", chan.name, prsn.nick ) )
+ done()
+ })
prsn.kickFrom( chan )
- this._stream.output[0].should.equal( f( "KICK %s %s\r\n", chan.name, prsn.nick ) )
})
})
describe( "inviteTo", function() {
- bit( "should get invited to a channel, by name or Channel object", function() {
+ bit( "should get invited to a channel, by name or Channel object", function( done ) {
const prsn = o.person( "gf3", "eh", "canada" ).for( this )
, chan = o.channel( "#america" )
+ server.on( "message", function ok( m ) {
+ server.removeListener( "message", ok )
+ m.should.equal( f( "INVITE %s %s\r\n", prsn.nick, chan ) )
+ done()
+ })
prsn.inviteTo( chan )
- this._stream.output[0].should.equal( f( "INVITE %s %s\r\n", prsn.nick, chan ) )
-
- prsn.inviteTo( "#america" )
- this._stream.output[0].should.equal( f( "INVITE %s %s\r\n", prsn.nick, chan ) )
})
})
describe( "notify", function() {
- bit( "should get notified", function() {
+ bit( "should get notified", function( done ) {
const person = o.person( "gf3" ).for( this )
, notice = "Important announcement"
+ server.on( "message", function ok( m ) {
+ server.removeListener( "message", ok )
+ m.should.equal( f( "NOTICE %s :%s\r\n", person, notice ) )
+ done()
+ })
person.notify( notice )
- this._stream.output[0].should.equal( f( "NOTICE %s :%s\r\n", person, notice ) )
})
})
View
67 spec/mockstream.js
@@ -1,67 +0,0 @@
-const util = require( "util" )
- , events = require( "events" )
-
-var uid = 0
- , last = null
-
-const MockStream = function() {
- this.readyState = "closed"
- this.mockConnected = false
- this.mockEnded = false
- this.output = []
- this.uid = uid
- last = this
-}
-
-util.inherits( MockStream, events.EventEmitter )
-
-MockStream.prototype.connect = function( port, host, connectListener ) {
- this.readyState = "open"
- this.mockConnected = true
- this.mockEnded = false
- // Give IRC a chance to add connect listeners
- process.nextTick( this.emit.bind( this, "connect" ) )
- return this
-}
-
-MockStream.prototype.end = function( port, host, connectListener ) {
- this.readyState = "closed"
- this.mockConnected = false
- this.mockEnded = true
- this.emit( "end" )
- return this
-}
-
-Object.defineProperty( MockStream, "current", {
- get: function() {
- return last
- }
-})
-
-MockStream.prototype.write = function( data ) {
- this.output.unshift( data )
- return this
-}
-
-MockStream.prototype.setEncoding = function( e ) {
- this.encoding = e
- return this
-}
-
-MockStream.prototype.setTimeout = function( t ) {
- this.timeout = t
- return this
-}
-
-MockStream.prototype.reset = function() {
- this.removeAllListeners()
- this.output.length = 0
-}
-
-const connect = function( port, host, connectListener ) {
- const ms = new MockStream()
- return ms.connect.apply( ms, arguments )
-}
-
-exports.MockStream = MockStream
-exports.connect = connect
View
56 spec/server.js
@@ -0,0 +1,56 @@
+const net = require( "net" )
+
+const MSG = /(.+)(\r\n)?/g
+ , SEP = "\r\n"
+
+const log =
+ { received: []
+ , sent: []
+ }
+
+const mockServer = new net.Server( function( s ) {
+ const buf = []
+
+ s.setEncoding( "ascii" )
+ mockServer.received = []
+ mockServer.sent = []
+
+ mockServer.on( "recite", function( data ) {
+ if ( s.readyState !== "open" )
+ return "GTFO"
+
+ mockServer.sent.unshift( data )
+ s.write( data )
+ })
+
+ mockServer.recite = function( stuff ) {
+ mockServer.emit( "recite", stuff )
+ }
+
+ s.on( "data", function( data ) {
+ const parts = data.match( MSG )
+ , out = []
+ var i = 0
+ , l = 0
+ , msg = null
+ if ( buf.length )
+ parts.unshift.apply( parts, buf.splice( 0 ) )
+ for ( var i = 0, l = parts.length ; i < l; ++i ) {
+ out.push( parts[i] )
+ if ( parts[i].lastIndexOf( SEP ) === parts[i].length - SEP.length ) {
+ msg = out.splice( 0 ).join( "" )
+ mockServer.received.unshift( msg )
+ mockServer.emit( "message", msg )
+ }
+ }
+ if ( out.length )
+ buf.push.apply( buf, out )
+ })
+
+ s.on( "end", function() {
+ mockServer.emit( "end" )
+ })
+})
+
+exports.server = mockServer
+exports.log = log

0 comments on commit ba12de5

Please sign in to comment.