has anyone integrated QUnit tests with ZombieJS? I have a script so i want to pass a "tests.html" file and poll until the tests complete, then read the results. Similar to what i'm doing with PhantomJS and it works perfectly fine. I'd mostly like to compare Phantom and Zombie with respect to performance. Also we have a lot of Qunit tests already created so i don't want to just dump them and rewrite everything from scratch in the Zombie environment (if i decide to go for it in the first place :)
the issue i am facing is that my tests never complete, so Qunit is always in running state. Haven't debugged anything in detail yet, but just wanted to make sure i am not missing something obvious.
var Browser = require("zombie");
var assert = require("assert");
// Load the page from localhost
browser = new Browser();
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 100000, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
process.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 100); //< repeat check every 250ms
};
browser.visit("tests.html", function () {
waitFor(function(){
return browser.evaluate(function(){
var el = browser.document.getElementById('qunit-testresult');
if (el && el.textContent.match('completed')) {
return true;
}
return false;
});
}, function(){
var failedNum = browser.evaluate(function(){
var el = browser.document.getElementById('qunit-testresult');
console.log(el.textContent);
try {
return el.getElementsByClassName('failed')[0].innerHTML;
} catch (e) { }
return 10000;
});
process.exit((parseInt(failedNum, 10) > 0) ? 1 : 0);
});
});
Related
Im using is-port-reachable package that returns promise. I would like to find first free (not reachable) port. So I should perform IsPortReachable in loop. Im trying to use yield, but have an error SyntaxError: Unexpected strict mode reserved word (yield couldBeBinded). If I move yield outside promise an error will disappear.
findPort () {
function * checkPort() {
let couldBeBinded = false;
let port = this.port;
do {
IsPortReachable(this.port, {host: 'localhost'})
.then(function (reachable) {
"use strict";
if (!reachable) { // not binded
couldBeBinded = true;
} else {
port++;
}
if (port > 65534) {
return couldBeBinded;
}
yield couldBeBinded;
});
} while(!couldBeBinded && (port < 65534));
}
var generator = checkPort();
let couldBeBinded = { value: false, done: false };
while((couldBeBinded.value !== true) && (couldBeBinded.done !== false)) {
couldBeBinded = generator.next();
console.log(couldBeBinded);
}
}
May be my code is totally wrong, so please advice me how to loop promises on node. Thanks
Here's my solution to this problem:
const IsPortReachable = require('is-port-reachable');
var options = {
start_port : 2994,
end_port : 3003,
findFirstFree : true
}
function CheckPort(port, firstFree, callback) {
IsPortReachable(port, {host: 'localhost'})
.then((reachable) => {
if (reachable) {
console.log(port, "reachable");
if (firstFree) callback(port);
}
else {
console.log(port, "free")
if (!firstFree) callback(port);
}
})
}
function CheckPortHandler(port, firstFree) {
if (port >= options.end_port) return;
CheckPort(port + 1, firstFree, CheckPortHandler)
}
CheckPort(options.start_port, options.findFirstFree, CheckPortHandler);
You can change the start and end port in the options. If you want to find the first reachable port (as opposed to first free port) change findFirstFree to false.
In the code I'm creating a function CheckPort that wraps around IsPortReachable but also receives a callback. The callback is called if the reachable status does not agree with the firstFree parameter. The callback is another function that calls CheckPort again with an incremented port, so the process continues. It continues until the reachable status agrees with the firstFree param, so the callback is no longer called.
It might be a bit confusing but it works ok for me.
Here is the output with findFirstFree : true
2994 'free'
And the output with findFirstFree : false
2994 'free'
2995 'free'
2996 'free'
2997 'free'
2998 'free'
2999 'free'
3000 'reachable'
I have created a little maze with a robot and I use Blockly to generate code to try to solve it. I can move the robot using Javascript commands which are Blockly blocks. So far so good.
I am currently breaking my head over arguments of if-statements and while loops. Mainly, I have tried two things:
Blockly maze
create a variable, 'not_goal_reached' which says whether or not the robot has reached the goal position (cross). Code:
function not_done() {
var goal_location = get_goal_position()
var goal_x = goal_location[0];
var goal_y = goal_location[1];
console.log('in not done');
//console.log(player.x!= goal_x || player.y != goal_y)
return (player.x!= goal_x || player.y != goal_y);
};
Blockly.Blocks['not_goal_reached'] = {
init: function() {
this.appendDummyInput()
.appendField("not at goal")
this.setOutput(true, "Boolean");
this.setColour(230);
this.setTooltip('');
this.setHelpUrl('');
}
};
Blockly.JavaScript['not_goal_reached'] = function(block) {
var code = 'not_done()';
// TODO: Change ORDER_NONE to the correct strength.
//console.log(code)
return [code, Blockly.JavaScript.ORDER_ATOMIC];
};
However, when using this block in an If or While statement. I always get a Javascript error that does not help me to find the solution:
TypeError: Cannot read property 'toBoolean' of undefined
at Interpreter.stepConditionalExpression (acorn_interpreter.js:148)
at Interpreter.step (acorn_interpreter.js:45)
at nextStep (index.html:79)
I use the Acorn js interpreter:
window.LoopTrap = 2000;
//Blockly.JavaScript.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = Blockly.JavaScript.workspaceToCode(workspace);
console.log(code);
var myInterpreter = new Interpreter(code, initInterpreter);
//Blockly.JavaScript.INFINITE_LOOP_TRAP = null
var counter = 0;
function nextStep() {
try {
if (myInterpreter.step()) {
counter+=1;
console.log(counter);
if (counter < window.LoopTrap) {
window.setTimeout(nextStep, 30);
}
else {
throw "Infinite Loop!"
}
}
}
catch (e) {
//alert(e);
console.log(e)
}
}
nextStep();
Problem: javascript error I can not solve :(
I created my own While block that does not require input. This While block checks internally whether or not the robot has reached the goal and then processes the DO statements:
Blockly.Blocks['repeat_forever'] = {
init: function() {
this.appendDummyInput()
.appendField("While not at goal");
this.appendStatementInput("DO")
.appendField("Do");
this.setPreviousStatement(true);
this.setColour(230);
this.setTooltip('');
this.setHelpUrl('');
}
};
Blockly.JavaScript['repeat_forever'] = function(block) {
var branch = Blockly.JavaScript.statementToCode(block, 'DO');
// TODO: Assemble JavaScript into code variable.
//if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {
// branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,
// '\'block_id_' + block.id + '\'') + branch;
// console.log(branch);
//}
var code = 'while (' + not_done() + ') {' + branch + '}';
console.log(code)
return [code, Blockly.JavaScript.ORDER_ATOMIC];
};
This works, BUT, here I have the problem that my internal function 'not_done' is only evaluated once (at code generation) to while(true) (since the first time the robot is of course not at the goal location yet). This block correctly applies the DO codes but does not halt (since while (true)). If I add quotes around 'not_done()' the function is evaluated once apparently, but then I receive the same Javascript error as above (Cannot read property 'toBoolean' of undefined)
Am I missing something here? Thanks a lot for your time!
Greetings
K
It seems that you setTimeout which cannot be reached while the while loop runs.
I'm building my first node.js application on my Raspberry Pi which I am using to control an air conditioner via LIRC. The following code is called when you want to increase the temperature of the AC unit. It sends a LIRC command every 250 milliseconds depending on how many degrees you want to increase it by. This code works as expected.
var iDegrees = 5;
var i = 0;
var delay = 250 // The delay in milliseconds
function increaseTemperatureLoop(){
i++;
//lirc_node.irsend.send_once("ac", "INCREASE", function() {});
console.log(i);
// Call the fucntion/loop again after the delay if we still need to increase the temperature
if (i <= iDegrees){
timer = setTimeout(increaseTemperatureLoop, delay);
}
else {
res.json({"message": "Success"});
}
}
// Start the timer to call the recursive function for the first time
var timer = setTimeout(increaseTemperatureLoop, delay);
I'm having a hard time working with the asynchronous nature of node.js. Once my recursive function is done, I return my json to the browser as shown in the code above. By habit, I feel like I should return the json in a line of code after my initial function call like below but obviously that wouldn't wait for all of the LIRC calls to be successful - it seems silly to have it inside of the function:
var timer = setTimeout(increaseTemperatureLoop, delay);
res.json({"message": "Success"});
What if I have a bunch of other stuff to do after my LIRC sends are done but before I want to send my json back to the browser? Or what if that block of code throws an error...
My second question is, how do I properly wrap the LIRC call in a try/catch and then if there is an error, stop the recursive calls, pass the error back up, and then pass this back to the browser along with the actual error message:
res.json({"message": "Failed"});
For track end of the cycle execution task, you can use a callback.
In order to know whether completed all routine tasks, you can use the task queue.
Monitor and report bugs to the top - it is possible with the help of
three of the same callback.
In general, it is desirable to wrap everything into a single object.
Some example for reflection:
var lircTasks = function __self (){
if (typeof __self.tasks === "undefined") __self.tasks = 0;
__self.func = {
increaseTemperature: function() {
// lirc_node.irsend.send_once("ac", "INCREASE_TEMPERATURE", function() {});
},
increaseFanPower: function() {
// lirc_node.irsend.send_once("ac", "INCREASE_FANPOWER", function() {});
}
}
var fab = function () {
__self.tasks++;
this.i = 0;
this.args = arguments[0];
this.callback = arguments[1];
this.run = function __ref(taskName) {
if (taskName) this.taskName = taskName;
if (this.i<this.args.deg) {
try {
__self.func[this.taskName]();
} catch(e) {
__self.tasks--;
this.callback( {message: "error", error: e, taskName: this.taskName, task: this.args, tasks: __self.tasks} );
}
this.i++;
setTimeout( __ref.bind(this), this.args.delay );
} else {
__self.tasks--;
this.callback({message:"complete", taskName: this.taskName, task: this.args, tasks: __self.tasks});
}
}
}
if ((arguments.length === 2) && (typeof arguments[1] === "function") && arguments[0].deg>0 && arguments[0].delay>=0) {
return new fab(arguments[0], arguments[1]);
}
}
function complete(e) {
console.log(e);
if (e.tasks === 0) console.log({message: "Success"});
}
lircTasks( {deg: 10, delay:100, device: "d1" }, complete ).run("increaseTemperature");
lircTasks( {deg: 20, delay:150, device: "d2" }, complete ).run("increaseTemperature");
lircTasks( {deg: 5, delay:100, device: "d3" }, complete ).run("increaseFanPower");
How can I prevent someone from simply doing
while(true){client.emit('i am spammer', true)};
This sure proves to be a problem when someone has the urge to crash my node server!
Like tsrurzl said you need to implement a rate limiter (throttling sockets).
Following code example only works reliably if your socket returns a Buffer (instead of a string). The code example assumes that you will first call addRatingEntry(), and then call evalRating() immediately afterwards. Otherwise you risk a memory leak in the case where evalRating() doesn't get called at all or too late.
var rating, limit, interval;
rating = []; // rating: [*{'timestamp', 'size'}]
limit = 1048576; // limit: maximum number of bytes/characters.
interval = 1000; // interval: interval in milliseconds.
// Describes a rate limit of 1mb/s
function addRatingEntry (size) {
// Returns entry object.
return rating[(rating.push({
'timestamp': Date.now(),
'size': size
}) - 1);
}
function evalRating () {
// Removes outdated entries, computes combined size, and compares with limit variable.
// Returns true if you're connection is NOT flooding, returns false if you need to disconnect.
var i, newRating, totalSize;
// totalSize in bytes in case of underlying Buffer value, in number of characters for strings. Actual byte size in case of strings might be variable => not reliable.
newRating = [];
for (i = rating.length - 1; i >= 0; i -= 1) {
if ((Date.now() - rating[i].timestamp) < interval) {
newRating.push(rating[i]);
}
}
rating = newRating;
totalSize = 0;
for (i = newRating.length - 1; i >= 0; i -= 1) {
totalSize += newRating[i].timestamp;
}
return (totalSize > limit ? false : true);
}
// Assume connection variable already exists and has a readable stream interface
connection.on('data', function (chunk) {
addRatingEntry(chunk.length);
if (evalRating()) {
// Continue processing chunk.
} else {
// Disconnect due to flooding.
}
});
You can add extra checks, like checking whether or not the size parameter really is a number etc.
Addendum: Make sure the rating, limit and interval variables are enclosed (in a closure) per connection, and that they don't define a global rate (where each connection manipulates the same rating).
I implemented a little flood function, not perfect (see improvements below) but it will disconnect a user when he does to much request.
// Not more then 100 request in 10 seconds
let FLOOD_TIME = 10000;
let FLOOD_MAX = 100;
let flood = {
floods: {},
lastFloodClear: new Date(),
protect: (io, socket) => {
// Reset flood protection
if( Math.abs( new Date() - flood.lastFloodClear) > FLOOD_TIME ){
flood.floods = {};
flood.lastFloodClear = new Date();
}
flood.floods[socket.id] == undefined ? flood.floods[socket.id] = {} : flood.floods[socket.id];
flood.floods[socket.id].count == undefined ? flood.floods[socket.id].count = 0 : flood.floods[socket.id].count;
flood.floods[socket.id].count++;
//Disconnect the socket if he went over FLOOD_MAX in FLOOD_TIME
if( flood.floods[socket.id].count > FLOOD_MAX){
console.log('FLOODPROTECTION ', socket.id)
io.sockets.connected[socket.id].disconnect();
return false;
}
return true;
}
}
exports = module.exports = flood;
And then use it like this:
let flood = require('../modules/flood')
// ... init socket io...
socket.on('message', function () {
if(flood.protect(io, socket)){
//do stuff
}
});
Improvements would be, to add another value next to the count, how often he got disconneted and then create a banlist and dont let him connect anymore. Also when a user refreshes the page he gets a new socket.id so maybe use here a unique cookie value instead of the socket.id
Here is simple rate-limiter-flexible package example.
const app = require('http').createServer();
const io = require('socket.io')(app);
const { RateLimiterMemory } = require('rate-limiter-flexible');
app.listen(3000);
const rateLimiter = new RateLimiterMemory(
{
points: 5, // 5 points
duration: 1, // per second
});
io.on('connection', (socket) => {
socket.on('bcast', async (data) => {
try {
await rateLimiter.consume(socket.handshake.address); // consume 1 point per event from IP
socket.emit('news', { 'data': data });
socket.broadcast.emit('news', { 'data': data });
} catch(rejRes) {
// no available points to consume
// emit error or warning message
socket.emit('blocked', { 'retry-ms': rejRes.msBeforeNext });
}
});
});
Read more in official docs
Here is my situation, I need to speed up the function running time, so setInterval is not a wise choose, right? Since it will cost at least 4ms for each time.
So, may I change setInterval function to requestAnimationFrame, but I don't quite understand how the requestAnimationFrame works.
For example
// some code here
var interval = setInterval(doSomething, 10)
var progress = 0
function doSomething(){
if (progress != 100){
// do some thing here
}else{
clearInterval(interval)
}
}
and how can I apply requestAnimationFrame?
I think the key to understand requestAnimationFrame lies in paul Irish's explanation:
Any rAFs queued in a rAF will be executed in the next frame
from requestAnimationFrame Scheduling For Nerds
var rafReference;
var progress = 0;
function doSomething(){
// only run 100 times
if (progress < 100){
/* do what you wanna do here */
progress++;
//recursively calls it self as requestAnimationFrame's callback
rafReference = requestAnimationFrame(doSomething) // passed as reference
}else{
cancelAnimationFrame(rafReference)
}
}
//starting the recursion
requestAnimationFrame(doSomething)
Looks better in a fiddle-->just the code,no animation
Every thing is commented inside the code for simplification.No need of using setInterval.
Just use cancelAnimationFrame when we are suppose to clear interval.
// This makes sure that there is a method to request a callback to update the graphics for next frame
var requestAnimationFrame =
window.requestAnimationFrame || // According to the standard
window.mozRequestAnimationFrame || // For mozilla
window.webkitRequestAnimationFrame || // For webkit
window.msRequestAnimationFrame || // For ie
function (f) { window.setTimeout(function () { f(Date.now()); }, 1000/60); }; // If everthing else fails
var cancelAnimationFrame =
window.cancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.msCancelAnimationFrame;
// your code here
var progress = 0;
function doSomething() {
if (progress != 100) {
// do something here
var myAnimation = requestAnimationFrame(doSomething);
} else {
// don't use clearInterval(interval) instead when you know that animation is completed use cancelAnimationFrame()
cancelAnimationFrame(myAnimation);
}
}
Some Links worth a read-->
CreativeJs---the best explanation any one could give,Every begineer must read
CancelAnimationFrame
link 3-->in context of your question
I found this fiddle on google,quite the same that you want.
Other things that you should know:
RAF is still in the development stage.
Why doesn't jQuery use requestAnimationFrame?