I am trying to make simple chat app using socket.io. Manually it's working fine (via browser localhost:3000/) but I want to write unit tests to verify logic of the server. I don't know which tools/libraries to use for testing.
Here is my node server code:
index.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var socketCount = 0;
http.listen(3000, function(){
console.log('listening on *:3000');
});
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket) {
socketCount++;
console.log('new user connected');
// Let all sockets know how many are connected
io.emit('users connected', socketCount);
socket.on('disconnect', function(){
// Decrease the socket count on a disconnect, emit
socketCount--;
io.emit('users connected', socketCount);
});
socket.on('chat message', function(msg){
// New message added, broadcast it to all sockets
io.emit('chat message', msg);
});
});
And here is my html page:
file: index.html
<html>
...
<body>
<ul id="messages"></ul>
<div class='footer'>
<div id="usersConnected"></div>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</div>
</body>
...
<script>
$(document).ready(function(){
$('#messages').val('');
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
// New message emitted, add it to our list of current messages
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
// New socket connected, display new count on page
socket.on('users connected', function(count){
$('#usersConnected').html('Users connected: ' + count);
});
});
</script>
</html>
Thanks.
I had this problem: How to do unit test with a "socket.io-client" if you don't know how long the server take to respond?.
I've solved so using mocha and chai:
var os = require('os');
var should = require("chai").should();
var socketio_client = require('socket.io-client');
var end_point = 'http://' + os.hostname() + ':8081';
var opts = {forceNew: true};
describe("async test with socket.io", function () {
this.timeout(10000);
it('Response should be an object', function (done) {
setTimeout(function () {
var socket_client = socketio_client(end_point, opts);
socket_client.emit('event', 'ABCDEF');
socket_client.on('event response', function (data) {
data.should.be.an('object');
socket_client.disconnect();
done();
});
socket_client.on('event response error', function (data) {
console.error(data);
socket_client.disconnect();
done();
});
}, 4000);
});
});
Related
I am creating a chat where there will be a div that displays the users that have connected to the server. The user's name is being taken from a prompt. I have managed to push each connected user to the array but can't figure out how to display that array. At the moment it only appends the div with the name of the individual user but I want them all to be displayed.
<body>
<div id="chatlog" class="col-sm-9">
<ul id="messages"></ul>
</div>
<div id="online" class="col-sm-3">
<div id="username"></div>
</div>
<form class="col-sm-12" action="">
<input id="type" type="text" />
<input type="submit" id="submit" />
</form>
<script>
var socket = io();
var user = prompt("What's your name?");
$('form').submit(function() {
socket.emit('chat message', $('#type').val());
$('#type').val('');
return false;
});
socket.on('chat message', function(msg) {
$('#messages').append($('<li>').text(msg));
});
socket.emit("join", user);
socket.on("join", function(user) {
$("#username").append($("<p>").text(user));
})
</script>
</body>
server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var express = require("express");
var port = 3000;
var onlineUsers = [];
console.log(onlineUsers);
app.use(express.static(__dirname + '/'));
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket) {
console.log('a user connected');
socket.on("join", function(user) {
socket.emit("join", user);
onlineUsers.push(user);
console.log(onlineUsers);
});
socket.on('chat message', function(msg) {
console.log('message: ' + msg);
io.emit('chat message', msg);
});
socket.on('disconnect', function() {
console.log('user disconnected');
});
});
http.listen(port, function() {
console.log('listening on *:' + port);
});
I am also open to suggestions how to do this another way but node.js is very new to me and think this might be the easiest way.
Send the array of users back to the clients when a user joins. This way all clients will have a updated user list every time a user joins. Below is a suggestion on how you could implement this
server:
socket.on("join", function(user) {
onlineUsers.push(user);
io.emit("user list", onlineUsers);
});
client:
socket.emit("join", user);
socket.on('user list', function(onlineUsers) {
$("#username").empty();
for(var i=0;i<onlineUsers.length;i++){
$("#username").append($("<p>").text(onlineUsers[i]));
}
});
This is my first time working with node.js/socket.io and I'm having a little trouble with the 'connect' event firing for all sockets. I followed the chat application example and then tried to add a feature where instead of displaying in the console when a user connects or disconnects, I would display it on-screen.
The disconnect event is firing for all tabs (if I have multiple tabs open to the chat application), but the connect event only seems to fire for the current tab.
Server (index.js)
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.on('connect', function(){
io.emit('connect', "A user connected");
});
socket.on('disconnect', function(){
io.emit('disconnect', "A user disconnected");
});
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
Client (index.html)
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
socket.on('disconnect', function(msg){
$('#users').text(msg);
});
socket.on('connect', function(msg){
$('#users').text(msg);
});
</script>
Ensure that your socket.io client and server are same major version of socket.io. E.g use socket.io#2.3.0 on both server and client or socket.io-client#3.. on both server and client.
There are two problems I can see with your code.
One is you don't need a socket "on connect" function. You can just put your code in the io "on connection", and it will fire when the user connects.
io.on("connection", function (socket) {
// Do connect stuff here
})
The other is that in your socket disconnect function, you emit disconnect which is could cause problems because it shares the name with other functions. Do something like this instead:
//Server:
io.on('connection', function(socket){
io.emit('set users', "A user connected");
socket.on('disconnect', function(){
io.emit('set users', "A user disconnected");
});
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
//Client:
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
//You only need one function to set "#users"
socket.on('set users', function(msg){
$('#users').text(msg); //this will set the text in #users
});
You can try this, it may work:
server:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
io.emit('new user', "A user connected");
socket.on('disconnect', function(){
io.emit('disconnect', "A user disconnected");
});
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
client:
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('connect', function() {
$('#users').text('I am connected!');
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
socket.on('disconnect', function(msg){
$('#users').text(msg);
});
socket.on('new user', function(msg){
$('#users').text(msg);
});
</script>
I try to learn socket.io on my web server. I have installed node.js and socket.io on my server. I have prepared web site my socket javascript code is work properly -listening port 3000 on console- but when i try to run example chat application, i got "socket.io/?EIO=3&transport=polling&t=1423949334574-31 404 (Not Found)" error. Where is mistake?
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
There is my index.html script:
<script>
var socket = io("http://localhost:3000");
$('form').submit(function(){
socket.emit('chat message', $('#messagebox').val());
var mesaj = $('#messagebox').val();
$('.messageBoard').prepend('<p style="display: none">'+mesaj+'</p>');
$('#messagebox').val('');
$('.messageBoard').find('p:first-child').show('slideDown');
e.preventDefault();
return false;
});
socket.on('chat message', function(msg){
$('.messageBoard').prepend('<p style="display: none">'+mesaj+'</p>');
});
</script>
My chat application is working properly on local server, but when I am pushing it to the openshift server, the chat functionality is not working.
I am following this example : http://socket.io/get-started/chat/
The following is my HTML code
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function () {
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function (msg) {
$('#messages').append($('<li>').text(msg));
});
</script>
</body>
Below is my server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var ipaddress = process.env.OPENSHIFT_NODEJS_IP || "127.0.0.1";
var port = process.env.OPENSHIFT_NODEJS_PORT || 3000;
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
socket.on('chat message', function (msg) {
io.emit('chat message', msg);
});
});
http.listen(port, function () {
console.log('listening');
});
The same code is working fine on my local server. For now I am simply broadcasting the message including the sender too.
Where am I wrong?
$( document ).ready(function() {});
this code saved me. i forgot to enclose my scripting in jquery document ready. so the final code looks like this.
$( document ).ready(function() {
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
});
Your chat client needs to connect to the websocket chat server on port 8000 for ws (or 8443 for wss). Make sure you are specifying that port number when you have it connect.
I know it´s a bit late, but the document isn´t ready and that caused the error.
Try this code:
$( document ).ready(function() {
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
});
Server:
var
io=require('socket.io'),
express=require('express'),
UUID=require('node-uuid'),
path=require('path'),
app = express();
app.configure(function(){
app.use(express.static(path.join(__dirname,'')));
});
var server = require('http').createServer(app).listen(8080);
sio = io.listen(server);
app.get('/', function(req, res){
res.sendfile('/index.html', {root:__dirname});
});
sio.sockets.on('connection', function(socket){
socket.userid = UUID();
socket.on('message', function(){
console.log('client just sent something');
socket.emit('news', { hello: 'world' });
});
});
Client connects index.html at first, then click a href to gameroom.html. This is gameroom.html:
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src="game.room.js"></script>
<script type="text/javascript" src="client.js"></script>
</head>
</html>
client.js:
window.onload = function(){
var game = new game_room();
}
game.room.js:
var game_room = function(){
this.socket = io.connect();
this.socket.on('connect', function(){
this.socket.emit('message', 'Hello server');
});
}
When the client connects, it should emit the message and the server writes the log, but I didn't get any log. I tried the code without this.socket.on('connect') in game.room.js, and the client can emit the message and I got the log. Also, if I transfer the code from game.room.js to client.js, i.e. in window.onload I created var socket = io.connect() and socket.on('connect', function() {socket.emit('messsage', 'Hello server')}); it works fine.
Can someone help me out or explain what is happening? Thanks.
You are loosing context you could try bind:
var game_room = function(){
this.socket = io.connect();
this.socket.on('connect', function(){
this.socket.emit('message', 'Hello server');
}.bind(this));
}
or you could just set this.socket to some local var:
var game_room = function(){
var socket = this.socket = io.connect();
this.socket.on('connect', function(){
socket.emit('message', 'Hello server');
});
}