Use mocha programmatically via rest - node.js

currently I try to figure out, how I can run mocha tests on a GET request of localhost:3000/run/tests resource.
Most things seems to work fine, but mocha .on('end') is probably not fired correctly so my res.json(...) function is not called and node still hangs.
var Mocha = require('mocha');
...
app.get('/run/tests', (req, res) => {
var mocha = new Mocha({
reporter: 'json'
});
myTestFiles.forEach(testfile => mocha.addFile('./tests/' + testfile + '.js'));
mocha.run()
.on('end', function() {
console.log(this.testResults);
res.json(this.testResults);
});
});
I get expected output except the "0 passing" lines :
> ...
> CALL element.text()
> GET /session/:sessionID/element/9/text
> RESPONSE element.text() "Username"
√ App login finished: 37685ms
0 passing (0ms)
0 passing (16ms)
My testfile looks like this:
'use strict';
require('./helpers/setup');
var wd = require('wd');
var serverConfigs = require('./helpers/appium-servers');
describe('Carnet App', function () {
this.timeout(120000);
var driver;
var allPassed = true;
before(function () {
var serverConfig = serverConfigs.local;
driver = wd.promiseChainRemote(serverConfig);
require('./helpers/logging').configure(driver);
var desired = {
'appium-version': '1.4.16',
platformVersion: '6.0.1',
device: 'Android',
platformName: 'Android',
app: myapp.apk'
};
return driver
.init(desired)
.setImplicitWaitTimeout(120000);
});
after(function (done) {
return driver
.quit()
.done();
});
afterEach(function () {
allPassed = allPassed && this.currentTest.state === 'passed';
});
it('App login finished', function () {
return driver
.elementById('...')
.click()
.sendKeys('...')
.elementById('...')
.text().should.become('Username');
});
});
Do I make a mistake? Does anybody have expirence with wd + mocha programmatically? Thanks for help!

Ok I solved my problem by only modify the following:
mocha.run(function(failures){
res.json({ ... })
})
.on('test', function() {
// do some logging stuff (into a var retured by res.json above)
})
// ... all mocha events possible
// see https://github.com/mochajs/mocha/blob/master/lib/runner.js#L49
.on('test end', function() {
// do some advanced logging stuff
});

Related

How can I access PhantomJS WebPage module from inside Mocha tests in NodeJS?

I'm basing this off of the Page Loading section of http://phantomjs.org/quick-start.html
I want to do something like this:
tests.js
var should = require('chai').should();
var page = require('webpage').create();
describe('test website with phantomJS', function() {
it('should load html from page', function() {
page.open('myHomePageToTest.html', function(status) {
if (status === 'success') {
page.content.should.equal('<!DOCTYPE html>...etc...</html>');
}
});
});
});
If I try to run this with 'mocha-phantomjs test.js' I get the error 'Failed to start mocha: Init timeout'
If I try to run this with 'mocha test.js' I get the error 'Cannot find module "webpage"'
I'm sure those are the expected error messages given the code. It's my understanding that is failing. The code is my description of what I want to do. After several hours of treading water last night, I have no idea how to actually do it.
Thank you for any help or nudge in the right direction.
var assert = require('assert');
var phantom = require('phantom');
describe('Mocha and phantom', function () {
this.timeout(150000);
it('Tweeking with phantomjs', function (done) {
phantom.create(function (ph) {
ph.createPage(function (page) {
page.open('https://www.facebook.com/', function (status) {
page.evaluate(function () {
return document.all[0].outerHTML //can check different elements
}, function (result) {
console.log('----------->>>>result',result);
assert.equal(status,'success','Not appropriate status');
done();
})
})
})
})
})
})

SpookyJS has no Start Method while using it in Meteor

I have an weird error and can't find the cause of it for the last few hours...
I have a meteor app, that scrapes some webpages for information and everything works fine as long as I use reuqest and cheerio for static pages, but now I have a dynamic site and I wanted to use phantomjs, casperjs and spookyjs for this one, but here I get some bug...
My code is as follows, I import the npm modules at the start:
if (Meteor.isServer) {
var cheerio = Meteor.npmRequire('cheerio');
var request = Meteor.npmRequire('request');
var phantomJS = Meteor.npmRequire('phantomjs');
var spooky = Meteor.npmRequire('spooky');
And sometime later I want to use spooky to scrape some webpage:
spooky.start("https://www.coursera.org/");
spooky.then( function () {
this.fill("form", {email: user, password: pass}, true);
});`
But as soon as I call the method I get the following error message:
20150224-21:16:39.100(-5)? Exception while invoking method 'getLecturesCoursera' TypeError: Object function Spooky(options, callback) {
....
I20150224-21:16:39.281(-5)? } has no method 'start'
I20150224-21:16:39.281(-5)? at [object Object].Meteor.methods.getLecturesCoursera (app/moocis.js:72:14)
I am doing something completly wrong and I have no clue why it isn't working...
I tried to verify that spookyjs and phantomjs are installed correctly in my app, but that isn't as easy as it sounds for someone who uses them for the first time...
Like normally with spooky you have to create a new Spooky Object before you can start and run it...
if (Meteor.isServer) {
Meteor.startup( function () {
var Spooky = Meteor.npmRequire('spooky');
var spooky = new Spooky({
child: {
transport: 'http'
},
casper: {
logLevel: 'debug',
verbose: true,
ignoreSslErrors: true,
sslProtocol: 'tlsv1'
}
}, function (err) {
if (err) {
e = new Error('Failed to initialize SpookyJS');
e.details = err;
throw e;
}
spooky.start(
'https://www.google.com');
spooky.then(function () {
this.emit('hello', 'Hello, from ' + this.evaluate(function () {
return document.title;
}));
});
spooky.run();
});
spooky.on('error', function (e, stack) {
console.error(e);
if (stack) {
console.log(stack);
}
});
spooky.on('hello', function (greeting) {
console.log(greeting);
});
spooky.on('log', function (log) {
if (log.space === 'remote') {
console.log(log.message.replace(/ \- .*/, ''));
}
});
})
}

How to integratei sequelize in nodeunit test

I have an express-sequelize application, it uses nodeunit to test routes and for this I use the wonderfull nodeunit-express module.
All works fine, except sequelize creating the database. In my express app I do a sequelize.sync({force: true}) during the start.
My tests do work when I run
npm start (node server.js)
first, followed by
npm test (nodeunit test)
But when the database is not present and I run
npm test (nodeunit test)
Alone, the is not created errors.
Where in the nodeunit testing process should I place the sync sequelize to have it available for my tests?
var request = require('nodeunit-express');
var server = require('../server');
var models = require('../models');
var express = request(server.app);
exports["Rest interfaces"] = {
setUp: function (callback) {
//insert some stuff in the database?
callback();
},
tearDown: function (callback) {
callback();
//cleanup();
},
"/api/categories": function (test) {
express.get('/api/categories').expect(function (response) {
// response is the response from hitting '/'
var result = JSON.parse(response.body);
test.equal(response.statusCode, 200, '/api/categories is not available');
test.equal(result.length, 0, 'no categories should be returned');
test.done();
});
}
};
function cleanup() {
//wait a little
setTimeout(function () {
express.close();
}, 500);
}

Test Grunt Tasks

I am using Yeoman to generate some projects and also grunt-tasks.
Now I would also like to test the generated grunt tasks using Mocha, but I only find some information how to use Mocha tests in Grunt ;-)
Can anybody help?
Not an elegant solution but I took the approach of installing my dependencies (npm install) and consequently running the corresponding grunt task (for e.g. grunt less) and then writing test logic post that operation. I've used nested exec calls for this.
describe('less grunt tasks tests', function () {
var prompts = {
workFolder: 'temp',
fiddleDesc: 'mocha test'
};
var testGlobal = {};
beforeEach(function(done) {
testGlobal.app = helpers.run(path.join(__dirname, '../app'))
.inTmpDir(function(dir, err) {
if(err) { done(err); return; }
testGlobal.dir = dir;
// console.log(dir);
})
.withArguments(['skip-install'])
.withOptions({ less: true })
.withPrompts(prompts)
.on('end', function(){
done();
});
});
it('should modify app/styles/style.css', function(done){
this.timeout(60000 * 10); //10 minutes - my network is f**ked up
var opts = {
cwd : testGlobal.dir,
env: process.env,
detached: true
};
var gen = testGlobal.app.generator;
var devdeps = gen.devDependencies.join(' ');
var rootPath = testGlobal.dir;
var getPath = function(fpath) {
var s = path.join(rootPath, fpath);
// console.log(s); ;
return s;
};
exec('npm install ' + devdeps, opts, function(err, stdout, stderr) {
if(err) {
done(err);
return;
}
var h1 = fs.readFileSync(getPath('app/less/h1.less'), 'utf8');
var css = fs.readFileSync(getPath('app/styles/style.css'), 'utf8');
// expect(css).to.not.contain(h1);
expect(css).to.not.contain('h1');
exec('grunt less', opts, function(e, out, serr){
if(e) {
done(e);
return;
}
// console.log(out);
var h1 = fs.readFileSync(getPath('app/less/h1.less'), 'utf8');
var css = fs.readFileSync(getPath('app/styles/style.css'), 'utf8');
// expect(css).to.contain(h1); //this expect fails since for some reason \r are stripped out
expect(css).to.contain('h1');
done();
});
});
});
});
For more reference you can see more test code in the repo I contribute against.
Ps: I'd appreciate your comments on the approach I've taken.

Mocha Monitor Application Output

I'm building a logging module for my web app in nodejs. I'd like to be able to test using mocha that my module outputs the correct messages to the terminal. I have been looking around but haven't found any obvious solutions to check this. I have found
process.stdout.on('data', function (){})
but haven't been able to get this to work. does anybody have any advice?
process.stdout is never going to emit 'data' events because it's not a readable stream. You can read all about that in the node stream documentation, if you're curious.
As far as I know, the simplest way to hook or capture process.stdout or process.stderr is to replace process.stdout.write with a function that does what you want. Super hacky, I know, but in a testing scenario you can use before and after hooks to make sure it gets unhooked, so it's more or less harmless. Since it writes to the underlying stream anyway, it's not the end of the world if you don't unhook it anyway.
function captureStream(stream){
var oldWrite = stream.write;
var buf = '';
stream.write = function(chunk, encoding, callback){
buf += chunk.toString(); // chunk is a String or Buffer
oldWrite.apply(stream, arguments);
}
return {
unhook: function unhook(){
stream.write = oldWrite;
},
captured: function(){
return buf;
}
};
}
You can use it in mocha tests like this:
describe('console.log', function(){
var hook;
beforeEach(function(){
hook = captureStream(process.stdout);
});
afterEach(function(){
hook.unhook();
});
it('prints the argument', function(){
console.log('hi');
assert.equal(hook.captured(),'hi\n');
});
});
Here's a caveat: mocha reporters print to the standard output. They do not, as far as I know, do so while example (it('...',function(){})) functions are running, but you may run into trouble if your example functions are asynchronous. I'll see if I can find more out about this.
I've attempted jjm's answer and had problems which I suspect was due to my programs async behaviour.
I found a solution via a cli on github that uses the sinon library.
An example code to test:
/* jshint node:true */
module.exports = Test1;
function Test1(options) {
options = options || {};
}
Test1.prototype.executeSync = function() {
console.log("ABC");
console.log("123");
console.log("CBA");
console.log("321");
};
Test1.prototype.executeASync = function(time, callback) {
setTimeout(function() {
console.log("ABC");
console.log("123");
console.log("CBA");
console.log("321");
callback();
}, time);
};
And the mocha tests:
/* jshint node:true */
/* global describe:true, it:true, beforeEach:true, afterEach:true, expect:true */
var assert = require('chai').assert;
var expect = require('chai').expect;
var sinon = require("sinon");
var Test1 = require("../test");
var test1 = null;
describe("test1", function() {
beforeEach(function() {
sinon.stub(console, "log").returns(void 0);
sinon.stub(console, "error").returns(void 0);
test1 = new Test1();
});
afterEach(function() {
console.log.restore();
console.error.restore();
});
describe("executeSync", function() {
it("should output correctly", function() {
test1.executeSync();
assert.isTrue(console.log.called, "log should have been called.");
assert.equal(console.log.callCount, 4);
assert.isFalse(console.log.calledOnce);
expect(console.log.getCall(0).args[0]).to.equal("ABC");
expect(console.log.getCall(1).args[0]).to.equal("123");
expect(console.log.args[2][0]).to.equal("CBA");
expect(console.log.args[3][0]).to.equal("321");
});
});
describe("executeASync", function() {
it("should output correctly", function(done) {
test1.executeASync(100, function() {
assert.isTrue(console.log.called, "log should have been called.");
assert.equal(console.log.callCount, 4);
assert.isFalse(console.log.calledOnce);
expect(console.log.getCall(0).args[0]).to.equal("ABC");
expect(console.log.getCall(1).args[0]).to.equal("123");
expect(console.log.args[2][0]).to.equal("CBA");
expect(console.log.args[3][0]).to.equal("321");
done();
});
});
});
});
I'm providing the above as it demonstrates working with async calls, it deals with both console and error output and the method of inspection is of more use.
I should note that I've provided two methods of obtaining what was passed to the console, console.log.getCall(0).args[0] and console.log.args[0][0]. The first param is the line written to the console. Feel free to use what you think is appropriate.
Two other libraries that help with this are test-console and intercept-stdout I haven't used intercept-stdout, but here's how you can do it with test-console.
var myAsync = require('my-async');
var stdout = require('test-console').stdout;
describe('myAsync', function() {
it('outputs something', function(done) {
var inspect = stdout.inspect();
myAsync().then(function() {
inspect.restore();
assert.ok(inspect.output.length > 0);
done();
});
});
});
Note: You must use Mocha's async api. No calling done() will swallow mocha's test messaging.

Resources