mocha, node.js, ReferenceError: Board is not defined - node.js

I'm new with node.js and I'm trying to collaborate in a project adding a mocha test suite for it. The issue that I have at the moment is the following
ReferenceError: Board is not defined
at new Game (/Users/.../dr_mojo/public/javascripts/game.js:8:20)
at Context.<anonymous> (/Users/.../dr_mojo/test/test.game.js:13:17)
at Test.Runnable.run (/usr/local/lib/node_modules/mocha/lib/runnable.js:213:32)
at Runner.runTest (/usr/local/lib/node_modules/mocha/lib/runner.js:343:10)
at Runner.runTests.next (/usr/local/lib/node_modules/mocha/lib/runner.js:389:12)
. . .
when run my test with
$> mocha -u tdd test/test.game.js --reporter spec
public/javascripts/board.js
function Board(width, height) {
this.board = new Array(width);
this.width = width;
this.height = height;
for( var i = 0; i < width ; ++i) {
this.board[i] = new Array(height);
}
}
...
if(typeof module != 'undefined') {
module.exports.Board = Board;
}
public/javascripts/game.js
function Game(lvl, speed, music) {
this.initial = { ... };
this.board = new Board(board_size[0], board_size[1]);
...
}
...
if(typeof module != 'undefined') {
module.exports.Game = Game;
}
test/test.game.js
var assert = require("assert");
var Board = require(__dirname + "/../public/javascripts/board.js").Board;
var Pill = require(__dirname + "/../public/javascripts/pill.js").Pill;
var Game = require(__dirname + "/../public/javascripts/game.js").Game;
describe('Game', function(){
it('Clears a row', function(){
var game = new Game();
var pill1 = new Pill(game.board, game.detector, [ {x : 0 , y : 0 }, {x : 1, y : 0 } ],["red", "red"]);
var pill2 = new Pill(game.board, game.detector, [ {x : 2 , y : 0 }, {x : 3, y : 0 } ],["red", "red"]);
assert.equal(game.board.matches().length, 1);
game.findMatches(function(){});
assert.equal(game.board.matches().length, 0);
})
})
server.js
var express = require('express'),
port = 8888;
var app = express.createServer();
app.use(express.static(__dirname + '/public'));
app.set("view engine", "jade");
app.set('view options', { layout: false });
app.get('/play', function(req, res){
res.render('play_game');
});
app.listen(port);
As you can see the error is in game.js:8 the thing is that I don't know how to configure it properly given that when the game is playing it works ok, this means that new Game() works ok and the problem is that I'm not configuring it properly from the test suite. I'll appreciate any help. Thanks in advance.

From the code you provided my guess is that you'll need to require board.js from game.js like so:
var Board = require(__dirname + "/../public/javascripts/board.js").Board;
It looks like this is a browser game that you're also testing from node.js. Is that correct?

Related

Javascript node js browser refresh upon POST

I am using node canvas in a project; essentially the project is about displaying an image on the browser screen, and being able to control the position of tge image by way of REST API POSTs. This works fine, but upon a POST i want to refresh the browser automatically.
I have looked at:
npm packages (browser-refresh, etc) ; but they require to put some code in the client page, but i dont have any html client page.
calling res.redirect ; this doesnt seem to do anything.
calling my draw() method in the POST method: i m getting an error about 'write after end' .
any help ? Again, the ask is to refresh the browser (or part thereof) upon new coordinates, in the POST method.
Code below.
Cheers,
Matt
Node server.js:
//Lets require/import the HTTP module
var http = require('http');
var express = require('express');
var app = express();
var bodyParser = require('body-parser')
var fs = require('fs')
var path = require('path')
var draw = require('./draw_badge');
var robot1;
var robot1_xcoord = 30;
var robot1_ycoord = 100;
var robot2;
var robot2_xcoord = 50;
var robot2_ycoord = 30;
/** bodyParser.urlencoded(options)
* Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST)
* and exposes the resulting object (containing the keys and values) on req.body
*/
app.use(bodyParser.urlencoded({
extended: true
}));
/**bodyParser.json(options)
* Parses the text as JSON and exposes the resulting object on req.body.
*/
app.use(bodyParser.json());
/** -------- Start -----
*
*/
{
app.get('/', function (req, res) {
console.log("Xcoord: " + robot1_xcoord);
res.setHeader('Content-Type', 'image/png');
// redraw everything
draw(robot1_xcoord,robot1_ycoord, robot2_xcoord,robot2_ycoord).pngStream().pipe(res);
});
// Getting a POST
app.post('/', function (req, res) {
console.log(req.body.id);
if (req.body.id=="1")
{
console.log("robot1 change");
robot1_xcoord = req.body.xcoordinate;
robot1_ycoord = req.body.ycoordinate;
}
else
if (req.body.id=="2")
{
console.log("robot2 change");
robot2_xcoord = req.body.xcoordinate;
robot2_ycoord = req.body.ycoordinate;
}
// draw(robot1_xcoord,robot1_ycoord, robot2_xcoord,robot2_ycoord).pngStream().pipe(res);
//res.redirect('localhost:5000');
res.send('Got a POST request' );
// try
//res.redirect(req.get('referer'));
/*
return http.get({
host: 'localhost',
path: '/'
}, function(response) {
// Continuously update stream with data
var body = '';
response.on('data', function(d) {
body += d;
});
response.on('end', function() {
// Data reception is done, do whatever with it!
var parsed = JSON.parse(body);
});
});
*/
});
// Main app - Listen
app.listen(process.env.PORT || 5000, function () {
console.log('Example app listening !');
});
and
draw_badge.js:
var Canvas = require('canvas')
var fs = require('fs')
function draw_badge(x,y) {
var x, y, i
ctx.clearRect(0, 0, 120, 120)
ctx.save()
ctx.translate(160, 160)
ctx.beginPath()
ctx.lineWidth = 14
ctx.strokeStyle = '#325FA2'
ctx.fillStyle = '#eeeeee'
ctx.arc(x, y, 42, 0, Math.PI * 2, true)
ctx.stroke()
ctx.fill()
return canvas;
}
function draw_robot(x,y) {
var Image = Canvas.Image
var canvas = new Canvas(600, 600)
var ctx = canvas.getContext('2d')
var img = new Image()
img.src = canvas.toBuffer()
ctx.drawImage(img, 0, 0, 50, 50)
ctx.drawImage(img, 50, 0, 50, 50)
ctx.drawImage(img, 100, 0, 50, 50)
img.src = fs.readFileSync('./kuka.png')
ctx.drawImage(img, 100, 0, img.width , img.height )
//img = new Image()
img.src = fs.readFileSync('./robot.jpeg')
ctx.drawImage(img, x, y, img.width / 2, img.height / 2)
// new
canvas.createPNGStream().pipe(fs.createWriteStream('./image-robot.png'))
return canvas
}
function draw(x1,y1,x2,y2)
{
Image = Canvas.Image,
canvas = new Canvas(600, 600),
ctx = canvas.getContext('2d');
canvas = draw_robot(x1,y1);
canvas = draw_badge(x2,y2);
return canvas;
}
module.exports = draw;
They way you are trying cannot work
The image that has been delivered to the browser cannot be refreshed dynamically, simply because it is an image. Once the server has delivered and the client loaded their work is done.
Attempting to write to the request (which may be one of hundreds) will of course result in a "write after end", because the end of the request was when the image first loaded in your browser.
the express res.redirect function cannot be called post facto (after the request) either, also it would immediately redirect, which you are not looking for.
Simple solution: Refresh via HTTP-Header (correctly)
app.get('/', function (req, res) {
console.log("Xcoord: " + robot1_xcoord);
res.setHeader('Content-Type', 'image/png');
// refresh every second
res.setHeader('Refresh','1');
// redraw everything
draw(robot1_xcoord,robot1_ycoord,robot2_xcoord,robot2_ycoord).pngStream().pipe(res);
});
Real solution: streaming image
You could supply an actual image-stream. The idea being that your request to the picture would never be closed, and when you alter the picture via your REST-API, the next picture of the stream would be delivered. In theory, your browser would display the last complete frame it got, thus kind of "update" your image in the browser window. This would be the real solution here, but might be expensive in terms of time wasted on the implementation. This would take some re-arrangements in your code.
caveat: firefox only, chrome support has been dropped as I just learned :/
server.js
//Lets require/import the HTTP module
var http = require('http');
var express = require('express');
var app = express();
var bodyParser = require('body-parser')
var fs = require('fs')
var path = require('path')
var draw = require('./draw_badge');
var robot1;
var robot1_xcoord = 30;
var robot1_ycoord = 100;
var robot2;
var robot2_xcoord = 50;
var robot2_ycoord = 30;
// An array to hold a list of active clients
var clients = [];
// draw an initial version of your buffer
var imageData = draw(robot1_xcoord, robot1_ycoord, robot2_xcoord, robot2_ycoord).toBuffer(undefined, 3, canvas.PNG_FILTER_NONE);
// get the size in bytes as well, we'll need it
var length = imageData.byteLength;
/** bodyParser.urlencoded(options)
* Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST)
* and exposes the resulting object (containing the keys and values) on req.body
*/
app.use(bodyParser.urlencoded({
extended: true
}));
/**bodyParser.json(options)
* Parses the text as JSON and exposes the resulting object on req.body.
*/
app.use(bodyParser.json());
/** -------- Start -----
*
*/
app.get('/', function(req, res) {
// prepare header so that the browser will wait for arbitray updates
res.writeHead(200, {
'Content-Type': 'multipart/x-mixed-replace; boundary=--NEW_IMAGE_HERE',
'Cache-Control': 'no-cache',
'Connection': 'close',
'Pragma': 'no-cache'
});
var on_update = function(imageData, length) {
try {
console.log("Updating client.. bytes:", length)
res.write("--NEW_IMAGE_HERE\r\n");
res.write("Content-Type: image/png\r\n");
res.write("Content-Length: " + length + "\r\n\r\n");
res.write(imageData);
} catch (e) { // in case of an error remove from the clients array
console.log("Error: ", e);
clients.splice(clients.indexOf(on_update), 1);
}
}
// remove on disconnect
res.on('close', function() {
console.log("Disconnected");
clients.splice(clients.indexOf(on_update), 1);
});
// send the client our last cached version of the image
on_update(imageData, length);
// add our update function to the array of clients
clients.push(on_update);
});
// Getting a POST
app.post('/', function(req, res) {
console.log(req.body.id);
if (req.body.id == "1") {
console.log("robot1 change");
robot1_xcoord = req.body.xcoordinate;
robot1_ycoord = req.body.ycoordinate;
} else
if (req.body.id == "2") {
console.log("robot2 change");
robot2_xcoord = req.body.xcoordinate;
robot2_ycoord = req.body.ycoordinate;
}
res.send('Got a POST request');
// redraw everything into the buffer
imageData = draw(robot1_xcoord, robot1_ycoord, robot2_xcoord, robot2_ycoord).toBuffer(undefined, 3, canvas.PNG_FILTER_NONE);
length = imageData.byteLength;
// notify active clients
for (on_update of clients) {
on_update(imageData, length);
}
});
// Main app - Listen
app.listen(process.env.PORT || 5000, function() {
console.log('Example app listening !');
});

-FIXED- cannot get / express and node js

hey guys im working on a project with some friends and we want our server on openshift it runs without errors but it always gives cannot get /
i tried to look for solutions and tried many but it just doesent fix it.
any ideas ?
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io').listen(server);
//
app.use(express.static(__dirname + '/public'));
app.use('/static', express.static(__dirname + '/public'));
server.listen(process.env.OPENSHIFT_NODEJS_PORT, process.env.OPENSHIFT_NODEJS_IP);
io.on('connection', onSocketConnection);
var players = [];
var npc1 = new Player(1049, 980);
npc1.id = "Johan Kruijs";
npc1.color = "gold";
npc1.name = "[NPC] Johan Kruijs";
players.push(npc1);
function onSocketConnection(client) {
console.log("Player has connected: ");
client.on("disconnect", onClientDisconnect);
client.on("new player", onNewPlayer);
client.on("move player", onMovePlayer);
};
function onClientDisconnect() {
var removePlayer = playerById(this.id);
if (!removePlayer) {
console.log("Player not found: " + this.id);
return;
}
console.log(removePlayer.name + " has disconnected.");
players.splice(players.indexOf(removePlayer), 1);
this.broadcast.emit("remove player", {
id: this.id
});
};
function onNewPlayer(data) {
var newPlayer = new Player(data.x, data.y);
newPlayer.id = this.id;
newPlayer.name = data.name;
newPlayer.color = data.color;
this.broadcast.emit("new player", {
id: newPlayer.id,
x: newPlayer.x,
y: newPlayer.y,
name: newPlayer.name,
color: newPlayer.color
});
var i, existingPlayer;
for (i = 0; i < players.length; i++) {
existingPlayer = players[i];
this.emit("new player", {
id: existingPlayer.id,
x: existingPlayer.x,
y: existingPlayer.y,
name: existingPlayer.name,
color: existingPlayer.color
});
};
players.push(newPlayer);
console.log(" - name: [" + newPlayer.name + "]")
console.log(" - id: [" + newPlayer.id + "]");
};
function onMovePlayer(data) {
var player = playerById(data.id);
player.x = data.x;
player.y = data.y;
player.id = data.id;
io.emit("move player", {
id: data.id,
x: data.x,
y: data.y
})
};
function playerById(id) {
var i;
for (i = 0; i < players.length; i++) {
if (players[i].id == id)
return players[i];
};
return false;
};
function Player(xpos, ypos) {
var result = {
x: xpos,
y: ypos,
id: 0
}
return result;
}
path --
In the screenshot you shared, the folder name is Public and not public, in osX (I assume that is what you are using from the screenshot), Public and public are different.
If you write this,
app.use(express.static(__dirname + '/Public'));
Things should start working.
Plus if you wanna set a default page, i.e. when user visits / and you want your /index.html to be served, you can do it like
app.use('/', express.static(__dirname + '/Public', {index: "index.html"}));
I hope this resolves your issue!!

mocha test sends `test` as variable to node app

When writing the tests for my entry file, index.js I run into the problem that the command mocha test passes test as an argument to index.js as it uses process.argv to receive parameters to run on a development environment. I had thought that by using something like minimist to name the parameters would fix this, however this problem still remains when running the tests. In this way my tests do not use the object provided in my test suits, as shown in the following code.
How do I get around this, so that when running my tests, it uses the event object I provide in my test set-up and not the command mocha test?
index.js
'use strict';
var _ = require("underscore");
var async = require('async');
var argv = require("minimist")(process.argv.slice(2));
var getprotocol = require("./getProtocol");
var _getprotocol = getprotocol.getProtocol;
var S3rs = require("./S3resizer");
var s3resizer = S3rs.rs;
var objCr = require("./objectCreator");
var createObj = objCr.creator;
var fileRs = require("./fileResizer");
var fileResizer = fileRs.rs;
var configs = require("./configs.json");
var mkDir = require("./makeDir");
var makeDir = mkDir.handler;
exports.imageRs = function (event, context) {
var _path = argv.x || event.path; //argv.x used to be process.argv[2]
console.log("Path, %s", _path);
var _dir = argv.y; // used to be process.argv[3]
console.log(_dir);
var parts = _getprotocol(_path);
var imgName = parts.pathname.split("/").pop();
console.log("imgName: %s", imgName);
var s3Bucket = parts.hostname;
var s3Key = imgName;
var _protocol = parts.protocol;
console.log(_protocol);
// RegExp to check for image type
var imageTypeRegExp = /(?:(jpg)|(png)|(jpeg))$/;
var sizesConfigs = configs.sizes;
var obj = createObj(_path);
// Check if file has a supported image extension
var imgExt = imageTypeRegExp.exec(s3Key);
if (imgExt === null) {
console.error('unable to infer the image type for key %s', s3Key);
context.done(new Error('unable to infer the image type for key %s' + s3Key));
return;
}
var imageType = imgExt[1] || imgExt[2];
// Do more stuff here
};
if (!process.env.LAMBDA_TASK_ROOT) {
exports.imageRs();
}
test.js
describe("imgeRs", function () {
var getprotocol = require("../getProtocol");
var S3rs = require("../S3resizer");
var objCr = require("../objectCreator");
var mkDir = require("../makeDir");
var fileResizer = require("../fileResizer");
describe("Calling S3", function () {
describe("Success call", function () {
var testedModule, eventObj, contextDoneSpy, S3resizerStub, objCreatorStub, getProtocolStub, fakeResults, mkDirStub, fileResizerStub;
before(function (done) {
contextDoneSpy = sinon.spy();
S3resizerStub = sinon.stub(S3rs, "rs");
objCreatorStub = sinon.stub(objCr, 'creator');
getProtocolStub = sinon.stub(getprotocol, "getProtocol");
mkDirStub = sinon.stub(mkDir, "handler");
fileResizerStub = sinon.stub(fileResizer, "rs");
eventObj = {"path": "s3://theBucket/image.jpeg"};
fakeResults = ["resized"];
testedModule = proxyquire("../index", {
'./getProtocol': {
'getProtocol': getProtocolStub
},
'./S3resizer': {
'rs': S3resizerStub
},
'./objectCreator': {
'creator': objCreatorStub
},
'./makeDir': {
'handler': mkDirStub
},
'./fileResizer': {
'rs': fileResizerStub
}
});
S3resizerStub.callsArgWith(5, null, fakeResults);
testedModule.imageRs(eventObj, {done: function (error) {
contextDoneSpy.apply(null, arguments);
done();
}});
});
after(function () {
S3rs.rs.restore();
objCr.creator.restore();
getprotocol.getProtocol.restore();
mkDir.handler.restore();
fileResizer.rs.restore();
});
it("calls context.done with no error", function () {
expect(contextDoneSpy).has.been.called;
});
});
});
});

req.param inside res.render causes strange console log

I am using using EJS templates with Node.js and Express. I am trying to pass a request parameter to my EJS template. It is working, however, for some reason my console log is reporting something strange.
Versions:
Node 0.10.26
Express 4.6.1
EJS 0.8.5
Here is the route that handles the ejs template:
var express = require('express');
var router = express.Router();
var data = require('../data.json');
var pkg = require('../../package.json');
router.get('/', function(req, res) {
res.render('index',
{
'acs' : data.acs,
'products' : data.products,
'pkg' : pkg,
'debug' : req.param('debug')
});
});
module.exports = router;
This is the console log (I replaced anything long with "..." to save space)
var __stack = {
lineno: 1,
input: "<!DOCTYPE html>\n<html lang=\"en\"> ... </html>\n",
filename: "/web/app/views/index.ejs" };
function rethrow(err, str, filename, lineno){
var lines = str.split('\n')
, start = Math.max(lineno - 3, 0)
, end = Math.min(lines.length, lineno + 3);
// Error context
var context = lines.slice(start, end).map(function(line, i){
var curr = i + start + 1;
return (curr == lineno ? ' >> ' : ' ')
+ curr
+ '| '
+ line;
}).join('\n');
// Alter exception message
err.path = filename;
err.message = (filename || 'ejs') + ':'
+ lineno + '\n'
+ context + '\n\n'
+ err.message;
throw err;
}
try {
var buf = [];
with (locals || {}) { (function(){
buf.push('<!DOCTYPE html>\n<html lang="en">...</html>\n'); })();
}
return buf.join('');
} catch (err) {
rethrow(err, __stack.input, __stack.filename, __stack.lineno);
}
Like I said, it is working, however I can't tell why this is being logged in the console. Thanks for the help!
The problem is that the second argument passed to res.render() is passed to both the rendering engine AND your template. Because of this behavior, ejs (at least through 1.0 as of this writing), looks for a debug property in that object to determine if debug information will be printed.

regarding foodme project in github

hello i have a question regarding the foodme express example over github:
code:
var express = require('express');
var fs = require('fs');
var open = require('open');
var RestaurantRecord = require('./model').Restaurant;
var MemoryStorage = require('./storage').Memory;
var API_URL = '/api/restaurant';
var API_URL_ID = API_URL + '/:id';
var API_URL_ORDER = '/api/order';
var removeMenuItems = function(restaurant) {
var clone = {};
Object.getOwnPropertyNames(restaurant).forEach(function(key) {
if (key !== 'menuItems') {
clone[key] = restaurant[key];
}
});
return clone;
};
exports.start = function(PORT, STATIC_DIR, DATA_FILE, TEST_DIR) {
var app = express();
var storage = new MemoryStorage();
// log requests
app.use(express.logger('dev'));
// serve static files for demo client
app.use(express.static(STATIC_DIR));
// parse body into req.body
app.use(express.bodyParser());
// API
app.get(API_URL, function(req, res, next) {
res.send(200, storage.getAll().map(removeMenuItems));
});
i don't understand where is the api folder. it doesn't exist and i don't understand how information is going in and out from there. i can't find it.
can someone please explain this to me?
another question:
there is a resource for the restaurant
foodMeApp.factory('Restaurant', function($resource) {
return $resource('/api/restaurant/:id', {id: '#id'});
});
and in the restaurant controller there is a query:
var allRestaurants = Restaurant.query(filterAndSortRestaurants);
and the following lines:
$scope.$watch('filter', filterAndSortRestaurants, true);
function filterAndSortRestaurants() {
$scope.restaurants = [];
// filter
angular.forEach(allRestaurants, function(item, key) {
if (filter.price && filter.price !== item.price) {
return;
}
if (filter.rating && filter.rating !== item.rating) {
return;
}
if (filter.cuisine.length && filter.cuisine.indexOf(item.cuisine) === -1) {
return;
}
$scope.restaurants.push(item);
});
// sort
$scope.restaurants.sort(function(a, b) {
if (a[filter.sortBy] > b[filter.sortBy]) {
return filter.sortAsc ? 1 : -1;
}
if (a[filter.sortBy] < b[filter.sortBy]) {
return filter.sortAsc ? -1 : 1;
}
return 0;
});
};
the things that isn't clear to me is:
how is that we are giving the query just a function without even activating it.
as i understand we should have passed the query somthing like:
{id: $routeParams.restaurantId}
but we only passed a reference to a function. that doesn't make any sense.
could someone elaborate on this?
thanks again.
var API_URL = '/api/restaurant';
var API_URL_ID = API_URL + '/:id';
var API_URL_ORDER = '/api/order';
These lines are just defining string constants that are plugged into Express further down. They're not a folder.
app.get(API_URL, function(req, res, next) {
res.send(200, storage.getAll().map(removeMenuItems));
});
So this function call to app.get(API_URL... is telling Express "Look out for GET requests that are pointed at the URL (your app's domain)/api/restaurant, and execute this function to handle such a request."
"api" is not a folder.
Every requests will pass through the app.get method.
This method will respond to the routes /api/restaurant as defined in the API_URL variable.

Resources