Hooking a custom mocha reporter - javascript

I am new to javascript and mocha. I have been looking at how to create a third party reporter. I saw some samples at https://github.com/mochajs/mocha/wiki/Third-party-reporters
I created one that meets my needs and was able to install it and use it. But, the requirement is to not install the reporter. It can either be a different file or be part of the same js file.
Can anyone please tell me how to hook the reporter with the js file?
Here is my test js file
const mochasteps = require('mocha-steps')
var Mocha = require('mocha');
var report = require('./report')
var mochainstance = new Mocha({reporter: report});
console.log(mochainstance._reporter)
before(() => console.log('before'))
after(() => console.log('after'))
describe('Array', () => {
step('should start empty', done => {
var arr = [];
if (arr.length == 1) return done()
done(new Error('array length not 0'))
});
});
describe('Test', () => {
step('some Test', done => {
done();
});
});
Here is my test report.js file that does the reporting.
var mocha = require('mocha');
module.exports = report;
function report(runner) {
mocha.reporters.Base.call(this, runner);
runner.on('pass', function(test){
console.log('[pass]%s', test.title);
});
runner.on('fail', function(test, err){
console.log('[fail]%s(%s)', test.title, err.message);
});
runner.on('end', function(){
process.exit(0);
});
}
Thanks,
r1j1m1n1

You need to pass the path to the custom reporter when running the tests. In your example, assuming test.js and report.js are in the same folder, it would be as follows:
mocha test.js -R 'report.js'
This will run the test.js tests with report.js as the reporter without having to install the reporter.

Related

Bypass some of the require() statements in the testing file

I want to write unit tests for myFunction() in the server.js file:
Main file: server.js
const config = require('./configuration'); // <==== local js file that breaks when unit testing
const other = require('some-module'); // <==== some module that is needed and it does not break when testing.
module.exports { myFunction };
function myFunction() {
// ...
}
function someOtherFunctions() { /*...*/ }
Test file: server.test.js:
const server = require('../server'); // <=== one level up in the folder hierarchy
it('should work', () => {
});
Problem:
jest breaks at const config = require('./configuration') and I don't actually need this to test myFunction.
However, I need the second: require('some-module').
I need to mock or bypass the first const config = require('./configuration').
Question:
How can I only import the myFunction() from server.js and somehow mock the first require(...) statements in the server.js ?

Import a file after the Jest environment has been torn down

I'm making a simple API with Express and I'm trying to add tests with Jest but when I try to run the tests it displays the next error:
ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.
at BufferList.Readable (node_modules/readable-stream/lib/_stream_readable.js:179:22)
at BufferList.Duplex (node_modules/readable-stream/lib/_stream_duplex.js:67:12)
at new BufferList (node_modules/bl/bl.js:33:16)
at new MessageStream (node_modules/mongodb/lib/cmap/message_stream.js:35:21)
at new Connection (node_modules/mongodb/lib/cmap/connection.js:52:28)
/home/jonathangomz/Documents/Node/Express/Devotionals/node_modules/readable-stream/lib/_stream_readable.js:111
var isDuplex = stream instanceof Duplex;
^
TypeError: Right-hand side of 'instanceof' is not callable
I'm not sure to trust the result if right after jest break (or something like that):
My test is:
const app = require("../app");
const request = require("supertest");
describe("Testing root router", () => {
test("Should test that true === true", async () => {
jest.useFakeTimers();
const response = await request(app).get("/");
expect(response.status).toBe(200);
});
});
My jest configuration on package.json:
"jest": {
"testEnvironment": "node",
"coveragePathIgnorePatterns": [
"/node_modules/"
]
}
Notes:
I read about jest.useFakeTimers() but It's not working and I'm not sure if I'm using in the wrong way. I also tried adding it to the beforeEach method but nothing.
In my case, I had to add the package to transformIgnorePatterns in the jest config.
Add jest.useFakeTimers('modern') before the asynchronous call. Add jest.runAllTimers() after the asynchronous call. This will fast-forward timers for you.
const app = require("../app")
const request = require("supertest")
describe("Testing root router", () => {
test("Should test that true === true", async () => {
//Before asynchronous call
jest.useFakeTimers("modern")
const response = await request(app).get("/")
//After asynchronous call
jest.runAllTimers()
expect(response.status).toBe(200)
})
})
Try adding --testTimeout=10000 flag when calling jest, it works for me.
Information based on Testing NodeJs/Express API with Jest and Supertest
--testTimeout flag - This increases the default timeout of Jest which is 5000ms. This is important since the test runner needs to refresh the database before running the test
By adding jest.useFakeTimers() just after all your import.
What about making your test async ?
const app = require("../app");
const request = require("supertest");
describe("Testing root router",async () => {
test("Should test that true === true", async () => {
jest.useFakeTimers();
const response = await request(app).get("/");
expect(response.status).toBe(200);
});
});

Load nodejs module dynamically with mocked filesystem in jest unit tests?

Well I'm trying to unit test a module loading script. Part of it is of course creating mocks for the scripts. For this mock-fs library is used.
import mock = require("mock-fs");
describe("getFileConfig", function () {
beforeEach(() => {
jest.resetModules();
});
afterEach(() => {
mock.restore();
});
it("should read and parse .js from ./config", async () => {
const expected = {
abc: 1,
fun: function() {return true;}
};
mock({config: {"myCfg.js": "module.exports = {abc: 1, fun: function(){return true;}}"}});
const test = require("./config/myCfg.js");
expect(test.abc).toEqual(1);
});
});
I "think" this should work? - mock creates a local copy of the file systems right?
However when I test above test the following error occurs:
Error: Cannot find module './config/myCfg.js' from 'test/loader.test.ts'
So this means the module loader is not using the mocked filesystem? How can make it use the mocked filesystem?

How to manipulate results of Mocha test in Node.js?

I have a simple Mocha file:
const assert = require('assert');
describe('Array', function () {
describe('#indexOf()', function () {
it('should return -1 when the value is not present', function () {
assert.equal([1, 2, 3].indexOf(4), -1);
});
});
});
I'm looking to run the test above inside Node.js and get access to the test results for further manipulation.
I know it's possible to import Mocha and run tests, like this:
const Mocha = require('mocha');
const test = new Mocha();
test.addFile('./assert.js');
test.run();
But, I'd like a way of getting the result of assert.equal and the corresponding descriptions, perhaps via the then() method. Any ideas? Could Sinon.JS help?
The end goal is to display these tests in the browser, using an API endpoint.
You can use the instance of test and look for events for each test execution.
for example:
const Mocha = require('mocha');
const test = new Mocha();
test.addFile('./assert.js');
let runner = test.run();
runner.on('pass', (e) => {
passed.push({
title: e.title,
speed: e.speed,
duration: e.duration,
file: e.file
});
});
runner.on('fail', (e) => {
failed.push({
title: e.title,
err: error,
file: e.file
});
});

How to clear a module mock between tests in same test suite in Jest?

I've mocked some nodejs modules (one of them, for example, is fs). I have them in a __mocks__ folder (same level als node_modules) folder and the module mocking works. However, whichever "between test clearing" option I use, the next test is not "sandboxed". What is going wrong here?
A very simplified example of the mocked fs module is:
// __mocks__/fs.js
module.exports = {
existsSync: jest.fn()
.mockReturnValueOnce(1)
.mockReturnValueOnce(2)
.mockReturnValueOnce(3)
}
I'm simply expecting that in every test, whenever init() is called (see below), existsSync starts again at value 1: the first value of jest.fn().mockReturnValue(). In the testfile I have the following structure:
// init.test.js
const init = require("../init");
const { existsSync } = require("fs");
jest.mock("fs");
describe("initializes script", () => {
afterEach(() => {
// see below!
});
test("it checks for a package.json in current directory", () => {
init();
});
test("it stops script if there's a package.json in dir", () => {
init(); // should be run in clean environment!
});
}
And once again very simplified, the init.js file
const { existsSync } = require("fs");
console.log("value of mocked response : ", existsSync())
I'm getting the following results for existsSync() after the first and second run ofinit() respectively when I run in afterEach():
jest.resetModules() : 1, 2
existsSync.mockReset(): 1, undefined
existsSync.mockClear(): 1, 2
existsSync.mockRestore(): 1, undefined
Somebody know what I'am doing wrong? How do I clear module mock between tests in the same suite? I'll glady clarify if necessary. Thanks!
Reset the modules and require them again for each test:
describe("initializes script", () => {
afterEach(() => {
jest.resetModules()
});
beforeEach(() => {
jest.mock("fs");
})
test("it checks for a package.json in current directory", () => {
const init = require("../init");
init();
});
test("it stops script if there's a package.json in dir", () => {
const init = require("../init");
init();
});
}
I had problems with the solution above. I managed to solve the issue with the next snippet.
afterEach(() => {
Object.keys(mockedModule).forEach(method => mockedModule[method].mockReset())
})
I would prefer to have a native method doing this though. Something like mockedModule.mockReset().
For local variables, the scope of declaration is important.
const mockFunc1 = jest.fn() // possibly bad mock reset/clear between tests
describe('useGetMetaData', () => {
const mockFunc2 = jest.fn() // good mock reset/clear between tests
afterEach(() => {/* reset/clear mocks */})
test.todo('implement tests here')
})

Categories

Resources