Why won't these chai tests fail? - node.js

We have some simple "is this really working" chai tests of an electron app using spectron and WebdriverIO. The example code we started with is from
https://github.com/jwood803/ElectronSpectronDemo as reported in https://github.com/jwood803/ElectronSpectronDemo/issues/2, the chai-as-promised tests are not catching mismatches, so I thought I would add some additional tests to find out why Chai is not failing tests where the electron app has text that doesn't match the expected unit test text.
Let's start with something really simple, the rest of the code is at https://github.com/drjasonharrison/ElectronSpectronDemo
describe('Test Example', function () {
beforeEach(function (done) {
app.start().then(function() { done(); } );
});
afterEach(function (done) {
app.stop().then(function() { done(); });
});
it('yes == no should fail', function () {
chai.expect("yes").to.equal("no");
});
it('yes == yes should succeed', function () {
chai.expect("yes").to.equal("yes");
});
The first unit test fails, the second succeeds.
And when we put the assertion into a function this still detects the failure:
it('should fail, but succeeds!?', function () {
function fn() {
var yes = 'yes';
yes.should.equal('no');
};
fn();
});
So now into the world of electron, webdriverio, and spectron, the application title is supposed to be "Hello World!", so this should fail, but it passes:
it('tests the page title', function () {
page.getApplicationTitle().should.eventually.equal("NO WAY");
});
Hmm, let's try a more familiar test:
it('should fail, waitUntilWindowLoaded, yes != no', function () {
app.client.waitUntilWindowLoaded().getTitle().then(
function (txt) {
console.log('txt = ' + txt);
var yes = 'yes';
yes.should.equal('no');
}
);
});
Output:
✓ should fail, waitUntilWindowLoaded, yes != no
txt = Hello World!
It succeeds? What? Why? How?

Found it! If you look at https://github.com/webdriverio/webdriverio/blob/master/examples/standalone/webdriverio.with.mocha.and.chai.js
you will see that you need to return the promise from each of the tests. This is typical for async chai/mocha tests:
it('tests the page title', function () {
return page.getApplicationTitle().should.eventually.equal("NO WAY");
});
If you do that, then the chai test is actually correctly evaluated.

Related

Order of Operations in `before` and `describe` blocks in Mocha/Chai Node Tests

To try and understand the execution order of one of my Mocha tests (where I was seeing functions execute out of order), I created the following simple test case:
describe("methods", function () {
before(async function () {
console.log('---------- BEFORE ------------');
let sum = 1 + 2;
console.log('sum: ', sum);
});
describe("test case", async function () {
console.log('---------- AFTER ------------');
});
});
Again, all I wanted to check here was the order of operations. And sure enough, in this case, all that prints to the console is ------------ AFTER ------------. The logging from the before block doesn't show up in the console at all.
Why is this? What am I missing here?
In my actual test case I use the before block to create and save a document. And then in the next describe block I look it up in the db. When I ran into issues where the document was being looked up before creation had happened I decided to do some simpler tests. Hence what you see above.
it's because of the "before" block is executed just before an IT block
try to execute this:
describe("methods", function () {
before(async function () {
console.log('---------- BEFORE ------------');
let sum = 1 + 2;
console.log('sum: ', sum);
});
it('should be a test', function(){
console.log('test');
});
describe("test case", async function () {
console.log('---------- AFTER ------------');
});
});
see this post for more:
https://gist.github.com/samwize/8877226

Context in mocha test is undefined

So I'm using mocha and node to test some apis. I have a test that goes
import { describe, before, it, xit } from 'mocha';
describe('test my scenarios dude', () => {
before('do all my pre-test stuff', () => {
const blah = blah;
});
it('tests my really useful test', () => {
const testName = this.test.ctx.currentTest.fullTitle();
});
});
The 'this' is undefined though. How can I get the test name?
https://mochajs.org/#arrow-functions
as docs says Passing arrow functions (“lambdas”) to Mocha is discouraged
use function instead
describe('test my scenarios dude', function() {
before('do all my pre-test stuff', function() {
const blah = blah;
});
it('tests my really useful test', function() {
const testName = this.test.ctx.currentTest.fullTitle();
});
});
also you can read more about arrow functions here. they don't have this

How to unit test promise with sinon in my case?

I am trying to start a stub in unit test for my app.
I have something like this in my file.
var sinon = require('sinon'),
should = require('should');
require('sinon-stub-promise');
describe('test unit Tests', function(){
describe('My first test', function(){
it('should test a promise', function(){
sinon.stub().resolves('foo')().then(function (value) {
console.log('test');
assert.equal(value, 'not foooo')
})
})
});
My problem is I can't seem to trigger the assert.equal error. I can see the 'test' in the output when run the test. However, the test should fail because the value should be foo and not 'not foooo'. For some reason it passed. I am not sure the reason. Can someone help me about it? Thanks a lot!
you need to return the promise so mocha waits:
describe('test unit Tests', function(){
describe('My first test', function(){
it('should test a promise', function(){
return sinon.stub().resolves('foo')().then(function (value) {
console.log('test');
assert.equal(value, 'not foooo')
})
})
})
});

Node.js sinon stubbing a function in parallel executions causes failed tests

I have 2 test cases which test the same function just taking 2 different executions paths, so to illustrate:
MyClass.prototype.functionBeingTested = function() {
if (this.check1()) {
this.isCheck1Called = true;
} else if (this.check2()) {
this.isCheck1Called = false;
} else {
...
}
};
My 2 test cases are as follow:
it('should take check1() execution path', function() {
var myClass= new MyClass({}, {}, {});
var check1Stub sinon.stub(MyClass.prototype, 'check1');
check1Stub.returns(true);
myClass.functionBeingTested();
myClass.isCheck1Called.should.equal(true);
});
it('should take check2() execution path', function() {
var myClass= new MyClass({}, {}, {});
var check2Stub sinon.stub(MyClass.prototype, 'check2');
check2Stub.returns(true);
myClass.functionBeingTested();
myClass.isCheck1Called.should.equal(false);
});
Now by default, check1() returns false so I don't stub it in the second test case, but by the time the second case is running, the check1() function stub is still active and causes the second case to enter the execution path of the first case as-well, making the second case test fail.
I understand it's a problem of test running in parallel and the first sinon stub still being used by the first test case, is there anyway I can solve this problem?
At the end of the first test, you should restore the original method (which is always a good thing, to prevent tests from being influenced by previous tests):
check1Stub.restore()
Or, alternatively, you can use a Sinon sandbox to run each test in:
describe('MyClass', function() {
beforeEach(function() {
this.sinon = sinon.sandbox.create();
});
afterEach(function() {
this.sinon.restore();
});
it('should take check1() execution path', function() {
var myClass = new MyClass({}, {}, {});
// `this.sinon` is the sandbox
var check1Stub = this.sinon.stub(MyClass.prototype, 'check1');
check1Stub.returns(true);
myClass.functionBeingTested();
myClass.isCheck1Called.should.equal(true);
});
it('should take check2() execution path', function() {
var myClass = new MyClass({}, {}, {});
var check2Stub = this.sinon.stub(MyClass.prototype, 'check2');
check2Stub.returns(true);
myClass.functionBeingTested();
myClass.isCheck1Called.should.equal(false);
});
});
(See mocha-sinon, which does exactly the same)

waitForCondition method never returning?

I'm trying to use Intern to author a first functional test, and I can't get around the following problem: when running the following test script
define(["intern!object",
"intern/chai!assert"
], function(registerSuite, assert){
registerSuite({
name: "suite",
"test": function(){
var browser = this.remote;
console.log("HELLO !");
browser.get("http://www.google.com", function() {
console.log("PAGE LOADED !");
browser.waitForCondition("!!window.document.gbqf", 1000, function(err, value){
console.log("LET'S BEGIN... ");
browser.eval("window.document.gbqf", function(err, value){
console.log("BYE BYE !");
browser.quit();
});
});
});
}
});
});
in chrome, using selenium server standalone 2.32.0 and chromedriver 26.0.1383.0 for windows, my test never end and the last message displayed in the console is "PAGE LOADED !".
Does anyone has an idea of how I'm suppose to write this test, or have a link to some proper (real life) functional tests examples ?
Thanks for your help,
Sebastien
The functional interface does not use callback arguments, it uses promises instead. Your code should look like this:
define([
"intern!object",
"intern/chai!assert"
], function (registerSuite, assert) {
registerSuite({
name: "suite",
"test": function () {
var browser = this.remote;
console.log("HELLO !");
return browser
.get("http://www.google.com")
.then(function () {
console.log("PAGE LOADED !");
})
.waitForCondition("!!window.document.gbqf", 1000)
.then(function () {
console.log("LET'S BEGIN... ");
})
.eval("window.document.gbqf")
.then(function (value) {
console.log("BYE BYE !");
});
});
}
});
});
Note in particular:
The last promise chain from this.remote is returned by the test function to indicate to Intern that the test is asynchronous
waitForCondition does not return a value
You should never call quit yourself; this is handled by Intern once the test is complete

Resources