How to launch a chai test in node? - node.js

I have a node/typescript application. I'm trying to test routes with chai and chai-http. I can launch a file when I write an explicit name: yarn test myroute.test.ts, but yarn test at the root does nothing.
Also, the test is never performed. I only receive a Done in 0.06s. in my terminal. No "passed" or "failed".
Here is the test:
import chai from "chai";
import chaiHttp from "chai-http";
import { server } from "../index";
chai.use(chaiHttp);
const chaiApi = chai.request(server);
describe("GET /user/:id", () => {
it("return user information", async () => {
const res = await chaiApi
.get("/user/123")
.set("Cookie", "_id=567;locale=en");
chai.assert.equal(res.status, 200);
});
});
the package.json script is: "test": "test". I assume it's completely wrong, but chai doc says nothing about what to write here.

chai is an assertion library, similar to Node's built-in assert. It does NOT contain a test runner. You need to use mocha to collect and run your declared test suites and test cases.
After adding the mocha test framework, you can declare npm test script like this:
"test": "mocha --require ts-node/register --timeout 5000",
In order to run the TS test file, we need to specify ts-node/register. Use it like this:
yarn test myroute.test.ts

Related

"Cannot use import statement outside a module" got message when I try to mocha

I was using jest now on vue/nuxt.
And I am trying to change TDD by mocha and chai.
Installed mocha though npm i mocha --save-dev
package.json
"scripts": {
"test": "mocha"
},
test/list.spec.json
import { expect } from 'chai';
describe('test', function () {
it('should be rendered', function () {
const comp = [1, 2, 3];
expect(Math.max(...comp)).to.above(1);
});
});
Error message when I typed npm test
import { expect } from 'chai';
^^^^^^
SyntaxError: Cannot use import statement outside a module
What is problem with that ?
You cannot use the import syntax in a Node app (import { expect } from 'chai';) if your project isn't properly configured to use this newer syntax. The original Node syntax pre JS modules is const variable = require('./folder/file')
You have to set up Jest or the project you work on to work with ES6 Modules. In package.json, add "type": "module". Here's an explanation: https://www.geeksforgeeks.org/how-to-use-an-es6-import-in-node-js/

How do you write object literal line coverage in Typescript Mocha unit-test?

Lead:
New to working with typescript and writing unit tests using Mocha and Chai.
Question
Any tips on how I can go about getting 100% line coverage in unit tests with an object literal that isn’t in a class? Trying to avoid going static if at all possible, but unit testing still has to hit 100% to pass.
// constants.ts
export default {
path: “./example”,
name: “Example Name”
}
// constants.spec.ts
// How do I unit test ‘export default’ for 100% line coverage?
// I have tried
import chai from "chai";
import * as constants from “./constants.ts”;
describe(“constants”, () => {
it(“Constants literals should have a length of 2“, () => {
chai.expect(constants.default.length).equal(2);
});
});
// The mocha test succeeds, but the line still says it hasn’t been tested.
I think I found the answer, but I am sure there is an easier way to use and test literals in Typescript.
describe("Constants", async () => {
it("can be created", async () => {
const obj = constants.default;
chai.should().exist(obj);
});
});
Typescript Mocha Chai unit-test 100% line coverage

Mocha (Spectron) suddenly times out on async test scenarios

I wanted to run some Spectron e2e tests I wrote some weeks ago, but to my surprise, suddenly they all stopped working for one and the same reason.
According to the error message, I'm dealing with rejected Promises, but I can't figure out where the problem is coming from. Calling done at the end of my testcase raises the exact same error.
I'm running the following command to launch my test suit: mocha test/e2e
Mocha then executes this index.js before running my tests in ordner to support ES6+ features
'use strict'
//index.js
// Set BABEL_ENV to use proper env config
process.env.BABEL_ENV = 'test'
// Enable use of ES6+ on required files
require('babel-register')({
ignore: /node_modules/
})
// Attach Chai APIs to global scope
const { expect, should, assert } = require('chai')
global.expect = expect
global.should = should
global.assert = assert
// Require all JS files in `./specs` for Mocha to consume
require('require-dir')('./specs')
After that its trying to run this small Login.spec.js which returns the error mentioned above
import utils from '../utils'
import {Application} from "spectron";
import electron from "electron";
describe('🔑 Login', function () {
this.timeout(11000);
it('login form exists', async function (done) {
this.app = new Application({
path: electron,
env: {"SPECTRON_RUNNING":true},
args: ['dist/electron/main.js'],
startTimeout: 10000,
waitTimeout: 10000
})
await this.app.start()
await this.app.client.windowByIndex(1);
done();
})
})

Mock dependencies with Mocha and Typescript

I have a typescript project which uses mocha. Let's say we have two modules as follows.
// http.ts
export class Http {
}
// app.ts
import Http from './http';
export class App {
}
How could I mock the Http module when I'm testing the App?
The test is executed through the npm script as below.
"test": "cross-env NODE_ENV=test ./node_modules/mocha/bin/mocha",
And the mocha options (mocha.opts) looks like below.
test/setup.ts
--compilers ts:ts-node/register
--compilers tsx:ts-node/register
./src/**/*.spec.ts
ts-mock-imports gives you run time control over your imports and maintains type safety.
in app.spec.ts
import * as httpModule from 'http';
import { App } from '../src/app';
import { ImportMock } from 'ts-mock-imports';
const httpMock = ImportMock.mockClass(httpModule, 'Http');
const app = new App(); // App now uses a fake version of the Http class
Now you can control how the Http module behaves in your tests.
Mock the response to a get:
httpMock.mock('get', { data: true });
const response = app.makeGetRequest(); // returns { data: true }
The import statement in typescript is compiled to require. You can use proxyquire to mock any dependencies in your tests

Bootstrapping a Mocha test suite

I have numerous tests spread across multiple files in a Node JS application. I'd like to run bootstrap code prior to Mocha's execution of any of the test files. This is so that I can, for example, set globals to be used in each of the actual tests.
Sample bootstrap code
global.chai = require('chai');
global.expect = chai.expect;
global.sinon = require('sinon');
It seems Mocha loads all files under /test alphabetically, so if I name this bootstrap code "bootstrap.js" and everything else with a starting letter after "B" it "works".
Obviously this is fragile and sucky, but I don't want to put this boilerplate requiring of my supporting libraries at the top of every test file.
How do I tell Mocha to load a bootstrap script first, or create something functionally equivalent?
have you tried mocha --require mymodule.js TESTS_DIR
from the documentation
-r, --require
The --require option is useful for libraries such as should.js, so you
may simply --require should instead of manually invoking
require('should') within each test file. Note that this works well for
should as it augments Object.prototype, however if you wish to access
a module's exports you will have to require them, for example var
should = require('should').
you could also write at the top of each test to load the require("./bootstrap.js") and run tests.
I use mocha's flag --delay
If you need to perform asynchronous operations before any of your
suites are run, you may delay the root suite. Simply run Mocha with
the --delay flag. This will provide a special function, run(), in the
global context.
setTimeout(function() {
// do some setup
describe('my suite', function() {
// ...
});
run();
}, 5000);
If prior to running Mocha you want to first run some bootstrap code in a file that uses ECMAScript 2015 Module syntax (i.e. import instead of require)
Create the following files:
./setupBabel.js (to bootstrap Babel transpiler)
require('babel-polyfill');
require('babel-register');
./setupDependencies.js (to bootstrap Chai and Sinon using ES2015 syntax)
import chai from 'chai';
import sinon from 'sinon';
global.expect = chai.expect;
global.sinon = sinon;
./test/codeSpec.js (example Unit Test using Chai, Sinon Stubs, Spies, and ES2015 syntax such as arrow functions, let, and const)
describe('test suite', () => {
it('does not modify immutable constant value', () => {
const myStub = sinon.stub();
const mySpy = sinon.spy(myStub);
myStub.returns({});
let val = 1;
expect(val).to.not.equal(2);
sinon.assert.notCalled(mySpy);
});
});
Run the following in terminal to install relevant NPM packages:
npm install babel-polyfill babel-register chai sinon mocha
Run the test suite with the following terminal command and flags:
mocha --require ./setupBabel.js --require ./setupDependencies.js ./test/codeSpec.js
describe('异步钩子测试', function () {
const lover = {
bodyname: 'yueyue',
girlname: 'fangfang'
}
const test = 'lihang'
beforeEach('每一个测试之前的钩子', function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('通过')
})
})
})
it('方方爱张越', function () {
// 是否等于yueuyue
expect(lover.bodyname).to.equal('yueyue')
// 是否是一个字符串
lover.girlname.should.equal('fangfang')
})
})

Resources