Chai assertions not executed inside JSDOM Env block - javascript

I've just started writing my front-end unit tests with mocha, chai and jsdom. When I try to follow the tutorials based on those - I'm getting passing tests even when I set them to fail. Everything else is setup and works as expected jQuery, setup.js, window etc. The only issue is that my Assertions are not getting executed at all inside the jsdom env block.
This is my test:
var chai = require('chai'),
expect = chai.expect,
jsdom = require('jsdom'),
fs = require('fs'),
jquery = fs.readFileSync('./js/vendor/jquery-3.0.0.min.js', 'utf-8');
describe('UI DOM tests', function () {
it('should fail', function () {
// simple html
var htmlFragment = fs.readFileSync('./test/runner.html');
jsdom.env({
html: htmlFragment,
src: [jquery, '../node_modules/chai/chai.js'],
done: function (err, window) {
var $ = window.$;
expect(true).eql(false); // nothing happens
done();
}
});
expect(true).eql(false); // assert fails as expected
});
});
Any help is greatly appreciated.

it seems you're missing the done argument in your it:
it('should fail', function (done) {
otherwise mocha will think your it is synchronous and finish before your jsdom env is created.

Related

How to use should.js as global variable:

I am trying to write some unit test that using mocha and should.js since I would like to keep format for each of my unit test the same and each unit test require should.js to verify proerpty of object. How can I make it as globally variable so I do not need to require should.js on each test file so far I have tried
global.should = require('should');
describe('try gloabl'), () => {
it('should work'), () => {
let user = { name: 'test'};
global.should(user).have.property('name', 'test');
});
});
#error, global.should is not a function
and if i use this. it works
const should = require('should');
should = require('should');
describe('try gloabl'), () => {
it('should work'), () => {
let user = { name: 'test'};
global.should(user).have.property('name', 'test');
});
});
First of all, I'm tired of writing "require" is the worst reason to use the GLOBAL variable. There is a reason that using require is the conventional way of doing things, and it is not different from any other language where you have to import or type using in each and every file. It just makes it easier to understand what the code is doing later on.
See this for further explanation.
Now, that said, when requiring should, the module actually attaches itself to the GLOBAL variable, and makes describe, it and should accessible methods.
index.js
require('should');
describe('try global', () => {
it('should work with global', () => {
let user = { name: 'test' };
global.should(user).have.property('name', 'test');
});
it('should work without global', () => {
let user = { name: 'test' };
should(user).have.property('name', 'test');
});
});
//////
mocha ./index.js
try global
√ should work with global
√ should work without global
2 passing (11ms)
I fixed the typos in your code (eg. Removing the extra ) from describe and it function), and this code works just fine when running with mocha ./index.js. Make sure you have install mocha with npm i -g mocha to make the module available in the CLI.

Sinon Spy and Stub function through actual http request

I have a function which is called from an API. I can stub it using sinon if I directly call it in my test for example foo.bar(); But if I call it through a test that makes an http request to that function it doesn't get stubbed. Any ideas?
You need to be able to start your application from the tests, and you should structure you application in a way that you can inject the dependencies that you want to control.
In the code below I have tried showing how you can use link seams (using proxyquire) to control the dependencies, but you could also use direct dependency injection to your app (say, pass it in to the start() method) as an alternative.
The code below is instructive, not necessarily working, so it skips setting up http listeners properly, etc. That is left as an exercise for the reader ;)
app.js
const myModule = require('./my-module');
if (require.main === module) {
/// starting from the cli
start({});
}
module.exports = {
start(){
app.get(`/`, (req, res) => {
myModule.foo(req.data).then(res.send).catch(res.send);
});
});
stop(){
app.stop(); // somehow kill the http listener and shutdown
}
}
test.js
const stub = sinon.stub();
const myApp = proxyquire('../app.js',{'./my-module': {foo: stub } });
before(()=> {
myApp.start();
});
it('should call a sinon stub', (done) => {
request('localhost:3000/')
.then( result = > expect(stub.called).to.equal(true) )
.then(done, done);
});

'window is not defined' when testing Paho MQTT Client with mocha and typescript

I googled for days but can't find anything about how to test the Paho MQTT Client. I tried it in a sort of naive way, like that:
import { suite, test, slow, timeout, skip, only } from 'mocha-typescript';
import chai = require('chai');
var jsdom = require('jsdom');
var Paho: any;
const expect: any = chai.expect;
const host: string = '127.0.0.1';
const port: number = 1384;
const clientId1: string = 'testid1';
const clientId2: string = 'testid2';
let client1;
let client2;
describe('test', function () {
it('should', function (done) {
// emulate browser window, which is required by Paho
jsdom.env("<html><body></body></html>", [],
function (err: any, window: any) {
// when window is ready, require Paho and
// initialize with built window
Paho = require('ng2-mqtt/mqttws31').jsdom(window);
// This does not work -> exception in mqttws31.js: window is not defined
client1 = new Paho.MQTT.Client(host, port, clientId1);
client1.connect({ onSuccess: () => { expect(true).to.be.true; done(); }, onFailure: () => { expect(false).to.be.true; } })
done();
});
});
});
However the Paho = require(...)-Part inside the callback function of jsdom.env(...) throws the exception in mqttws31.js: "window is not defined". Has anyone an idea how to solve that, in order to get the Paho Client running in a non-browser environment?
Thanks in advance!
https://www.npmjs.com/package/mochify You could be using similiar NPM module like this. Like you might expect Node.js environment dosen't have browser globals itself so use some library which can integrate these globals to your testing environment.
I am not very familiar with mocha but here's one more library I have played around in Karma as reference https://www.npmjs.com/package/karma-browserify
Or simply using some external service like BrowserStack https://www.npmjs.com/package/browserstack

Node.js Mocha Testing Restful API Endpoints and Code Coverage

I've been really enjoying Istanbul and experimenting with other Node.js coverage libraries as well, but I have an issue. Nearly all of my unit tests are HTTP calls to my API like so:
it('should update the customer', function (done) {
superagent.put('http://myapp:3000/api/customer')
.send(updatedData)
.end(function (res) {
var customer = res.body;
expect(res.statusCode).to.equal(200);
expect(customer.name).to.equal(updatedData.name);
done();
});
});
As opposed to actually requiring the customers.js file and calling updateCustomer directly. Testing the endpoint makes much more sense to me, as it not only tests updateCustomer, but also the routes, controllers, and everything else involved.
This works fine, but the problem is that I can't seem to see a way for any code coverage tool to recognize these tests. Is there any way for Istanbul or anything else to recognize these Mocha tests? If not, what is the convention? How do you test endpoints and still use code coverage tools?
The issue is that you're using superagent, whereas you should be using supertest to write unit tests. If you use supertest, istanbul will correctly track code coverage.
Some sample code to get you started:
'use strict';
var chai = require('chai').use(require('chai-as-promised'));
var expect = chai.expect;
var config = require('../../config/config');
var request = require('supertest');
var app = require('../../config/express')();
describe('Test API', function () {
describe('test()', function() {
it('should test', function(done) {
request(app)
.get('/test')
.query({test: 123})
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res){
expect(err).to.equal(null);
expect(res.body).to.equal('whatever');
done();
});
});
it('should return 400', function(done) {
request(app)
.get('/test/error')
.query({})
.expect('Content-Type', /json/)
.expect(400, done);
});
});
});

"undeclared variable" warning in Mocha tests in Cloud9

I'm new at node.js and the framework Mocha for unit testing, but I've created a couple of tests in cloud9 IDE just to see how it works. The code looks like this:
var assert = require("assert");
require("should");
describe('Array', function(){
describe('#indexOf()', function(){
it('should return -1 when the value is not present', function(){
assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));
});
});
});
describe('Array', function(){
describe('#indexOf()', function(){
it('should return the index when the value is present', function(){
assert.equal(1, [1,2,3].indexOf(2));
assert.equal(0, [1,2,3].indexOf(1));
assert.equal(2, [1,2,3].indexOf(3));
});
});
});
The tests work if I type mocha in the console, but the IDE shows warnings in the lines where "describe" and "it" are because it says that the variable has not been declared ("undeclared variable").
I wonder what should I do these tests to avoid the warnings.
Thanks.
In cloud9 you can add a hint for globals as a comment at the top of the file and it will remove the warnings.
e.g.
**/* global describe it before */**
var expect = require('chai').expect;
describe('Array', function(){
describe('#indexOf()', function(){
it('should return -1 when the value is not present', function(){
expect(true).to.equal(true);
})
})
})
That's because mocha "executable" wraps your test in requires needed to use mocha functions (describe, and it). Take a look at mocha and _mocha in your node_modules/mocha/bin directory.
On the other hand cloud9 tries to resolve all symbols using a pure node executable, so you have to require everything by hand.

Categories