Execute npm script within mocha test - node.js

I currently have a script 'npm run make-file' which will create a boiler plate file. Nothing fancy at all, but I am trying to create a test for that in my test suite. I am using Mocha/Chai for testing.
Is it even possible to run a script in the terminal from a mocha test?
describe('Make File', function () {
it('Runs npm run make file', function (done) {
// What would belong here?
});
});

Related

How to knowif all tests have passed with mocha

I would like to know if it is possible to execute something if all my test files have passed with mocha.
Below: is my index.js file which is run by mocha (in order to get the order I want)
require('dotenv').config();
const logger = require('../toolkits/logger');
//silent mode for testing
logger.transports.forEach((t) => (t.silent = true));
require("./broker.test");
require("./mongo.test");
require("./auth.test");
require("./meal.test");
require("./bowl.test");
I want to process.exit(0) if the tests passed (to integrate it into gitlab CI).
I succeded in check if a test hasn't passed by doing this :
afterEach(function(){
if (this.currentTest.state === "failed")
process.exit(1);
})
But I can't detect if all the tests passed.
I can't just process.exit(0) after requiring all the tests because some of them are asynchronous.
Do you have an idea how I can do that?
! Update !
I found out that I could pass the --exit argument when running mocha from npm :
mocha file --exit

why is jest not required?

I have a react app and I don't know why I don't need to require the jest module.
import Task from './Task';
describe('class Task', () => {
it('inProgress()', () => {
var t = new Task("prova");
expect(t.isInProgress()).not.toBeTruthy();
});
});
The test command for create-react-app runs react-scripts test --env=jsdom.
The script for react-scripts test requires jest on this line and after configuring everything it runs jest on this line.
jest then finds your test files, loads them, and runs them.
In other words, your tests don't load and run jest, it's jest that loads and runs your tests.
Since your tests run within jest they can take advantage of the globals, expect, environment, etc. provided by jest without having to "require or import anything to use them".

mocha tests not found: "0 passing"

I dont know why the test runner wont detect my tests.
npm test
myproject#1.0.0 test C:\Users\sjsui\Desktop\git_workshop\myproject
mocha ./built/source
0 passing (4ms)
PS C:\Users\sjsui\Desktop\git_workshop\myproject>
I know that test is the default folder that mocha searches for so that is how I structured my project.
built
\--source
\--test
\--test.js
here is my test.js file
describe("consumer tests", function()
{
it("runs bad request tests", (done) => {
let tests = new badrequesttests()
iteratebadtests(tests, done)
})
it("normal consumer tests", (done) => {
let tests = new normaltests()
iteratenormaltests(tests, done)
})
it("abnormal consumer tests", (done) => {
let tests = new unauthorizedtests()
iterateunauthorizedtests(tests, done)
})
})
npm scripts section in package.json
"scripts": {
"test": "mocha ./built/source"
},
as a side note, break points wont hit inside the test (visual studio code debug task -> mocha)
I think your test scripts are not detected y mocha because by default mocha does not scan sub-directories and your tests are inside a subdirectory of path you are passing at the time of invking mocha. There are two ways to resolve this.
Provide the path of test folder to mocha as below
mocha ./built/source/test
Trigger mocha tests with recursive flag. Using this flag mocha will scan the subdirectories of the path you provide
mocha ./built/source --recursive
I think this should solve your problem
You can pass the directory to search for your test files like below:
mocha -- ./built/source/**/*.test.js
This will check for all test files ending with .test.js in their file name in any directory within the source directory.
mocha -- ./built/source/*.test.js
That will check for test files within the source directory.

Why can't get the global variable which was set in globalSetup in test code?

I use Jest to do unit test in node.
And I use the new feature globalSetup which come in Jest v22.
I have defined a global variable in globalSetup.
But I can't get it in the test code. Console log is undefined.
Anyone in this question?
Thanks.
Jest version: 22.0.0
node version: 8.9.0
yarn version: 1.3.2
OS: mac High Sierra 10.13.2
The code as follow:
// package.json
{
"jest": {
"globalSetup": "<rootDir>/src/globalSetupTest.js"
}
}
// globalSetupTest.js
module.exports = async function() {
global.foo = 'foo';
console.log(`global setup: ${global.foo}`);
};
// App.test.js
describe('APP test', () => {
it('renders without crashing', () => {
console.log({ foo: global.foo });
});
});
// test result
yarn run v1.3.2
$ node scripts/test.js --env=node --colors
global setup: foo
PASS src/App.test.js
APP test
✓ renders without crashing (5ms)
console.log src/App.test.js:3
{ foo: undefined }
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.354s, estimated 1s
Ran all test suites.
There's a solution offered from Jest people themselves: https://jestjs.io/docs/en/puppeteer.html. Note that if you're using CRA, this won't work out of the box (solution below), cause it currently doesn't support testEnvironment option for Jest.
Anyways:
In Jest config file you setup paths to global setup, teardown and test environment scripts
In global setup script, you create a browser and write it's WSEndpoint to a file
In global teardown script, you simply close the browser
In testEnvironment script, you read WSEndpoint from the file you saved before and then use it to connect to the running browser - after this, browser is available in your tests by using a global variable
If you're using CRA, you can use a custom setup for these tests and run them completely separately. And if you're using Puppeteer for e2e tests, this is probably what you want to do anyway.
You just add another script to your package.json: "test:e2e": "jest -c ./jest-e2e.config.js" and set it up as you want. Now you will have npm run test for unit tests and npm run test:e2e for end to end tests.
For what I understood is a design decision of Jest because is considered a bad practice to share state across different tests. Tests run in parallel and they should keep their own state.
See:
https://github.com/facebook/jest/issues/6007#issuecomment-381743011
https://github.com/facebook/jest/issues/4118
Can you try..
global.foo = 'foo';
console.log(`global setup: ${global.foo}`);
(remove the exports)
You can try changing globalSetup to setupFiles. That one, won't expect a function.
https://facebook.github.io/jest/docs/en/configuration.html#setupfiles-array

How to run mocha tests and node in a single npm test command ? (CI)

I want to use Circle CI to integrate a git project.
I'm using mocha for my tests .
What i want to do?
When running npm test I want:
my node server to start
my test file to run
How can I run a single npm test command to run both node and my mocha tests which are already wrapped in a single index.js file.
I have tried this in my package.json:
"scripts": {
"test": "node server/app.js & mocha server/tests/index.js",
"start": "node server/app.js",
"postinstall": "bower install"
}
The problems with the above
My server takes some time to start and the tests fail since they run before the server starts
Is there a standard way to run a server and the tests with a single command but I'm missing something?
If it is possible at all in your case I'd suggest using something like supertest to do the testing. This way, you can avoid having to start a server before starting the test.
I understand that there are scenarios where using supertest is not possible. In such case, you could poll your server in a before hook before all tests to wait until it is ready:
before(function (done) {
// Set a reasonable timeout for this hook.
this.timeout(5000);
function check() {
if (serverIsReady()) {
done();
return;
}
// The server is no ready, check again in 1/10th of a second.
setTimeout(check, 100);
}
check(); // Start checking.
});
I'm not sure what serverIsReady should be precisely in your case. It could be an attempt at getting a trivial path from your server like issuing a GET on the path /.
I think the key is to run your node server in your test, rather than trying to initialise it in another process.
Your mocha test should start with a require to your app, then each
of your tests can interact with it.
For example:
var http = require('http');
var server = http.createServer(function(req, res){
res.end('Hello World\n');
})
server.listen(8888);
describe('http', function(){
it('should provide an example', function(done){
http.get({ path: '/', port: 8888 }, function(res){
expect(res).to.have.property('statusCode', 200);
done();
})
})
})
What I do when running a test that needs certain pre-requisites is use mochas beforeEach() functionality.
From the documentation
You may also pick any file and add “root”-level hooks. For example, add beforeEach() outside of all describe() blocks. This will cause the callback to beforeEach() to run before any test case, regardless of the file it lives in (this is because Mocha has an implied describe() block, called the “root suite”).
beforeEach(function() {
console.log('before every test in every file');
});
In the before each code block you can run your command to start the server
using for example the exec library from npm
https://www.npmjs.com/package/exec
This will ensure your server is running before your tests are run allowing you to simply run npm test.

Resources