How do you create multiple test files in jest - node.js

Having this node.js app which is going to be quite huge.
First I created a file named
user.account.test.js
In that I begun putting all the possible tests (positive and negative tests) for the usuale flow: signup, singin, activation, restore password etc.
At the end I have this file that is over 600 rows. Now, Im going to create a lot of more tests. And having everything in the same file sounds silly to me.
I could not really find resources that explain how to split the test in severals test files.
Im having a nightmare when I created a new test file where to put other tests. I mostly got timeout issues.
And a lot of things look strange. For example:
In the user.account.test.js I had this line:
beforeAll(async () => {
await mongoose.connect(process.env.MONGODB_TEST_URI);
});
In the second test file, named user.step2.test.js, I was unsure if I had to also put the same function.
At the end I did it, and incredibly that file did not know anything about "process.env.MONGODB_TEST_URI".
What is the best practice when you want to split tests into multiple files?

Ok, solution seems to be adding the flag --runInBand. Then they will run sequentially.

For me each routes I write one test file.
For example:
Each test file have sth like this:
import request from 'supertest'
import {app} from '../../app'
it('create new user', async() => {
return request(app).post('/api/users')
.send({account: "123", password:"123"})
.expect(201)
})
and I create a test setup file:
beforeAll(async () => {
// init your database connection here
})
beforeEach(() => {
// delete all data in your database
})
afterAll(async() => {
//close your db connection
})
and in package.json:
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
"setupFilesAfterEnv": [
"./src/test/setup.ts"
]
},

Related

Mock file in Jest and prevent getting loaded

I have a file that uses a webworker that I want to unit test. But because Jest is flaky on ESModules, it doesn't like import.meta.url.
I don't want to test this part, I need to test the functionality around it. But because it's still included in the build, js-test keeps tripping over having this included in the build.
I abstracted it into a separate JS file worker-loader.js:
const spawnWorker = () => {
return new Worker(new URL('./worker.ts', import.meta.url));
};
module.exports = { spawnSqlJsWorker};
Which is use with a require in the main source code.
I tried adding a mocks directory with an empty mock:
const spawnWorker = () => {
return null;
};
module.exports = { spawnSqlJsWorker};
And ignore this file from jest in jest.config.js:
transformIgnorePatterns: ['worker-loader.js'],
But the loader keeps wanting to include this file. Is there a way in jest to completely ignore a file and mock the complete contents of it?

NestJS conditional module import

Is there a way to import a module conditionally?
I want to check if the .env file exists, so I configure the env variables using the ConfigModule.
imports: [
UsersModule,
ConfigModule.forRoot({ load: [configuration] }), //I want to use this just if the .env file exists
MongooseModule.forRoot(
`mongodb+srv://${process.env.DATABASE_USER}:${process.env.DATABASE_PASSWORD}#${process.env.DATABASE_URL}`,
),
],
Why: I deployed an api and configured the environment variables using heroku, and in production it works, but I dont have this variables to run the code in development, and I can't expose the .env in my public repository because this contains my database credentials. Because of this, I thinked to create a .env file and put it on .gitignore to don't publish with this file
You can do this pretty easily with a spread and a ternary check on whatever condition you want. Just return an empty array in the case that the check evaluates to false and the module will not be included.
#Module({
imports: [
...(isEnvPresent ? [ConfigModule.forRoot({ load: [configuration] })] : []),
UsersModule,
],
})
here's a small snippet that does importing within a code construct (dynamic importing, like how require's would allow):
const events = files.filter(file => file.endsWith('.mjs'));
for (const file of events) {
import(`${eventDir}${file}`)
.then(function({ default: event }) {
const eventName = file.split('.')[0];
dBot.on(eventName, event.bind(null, dBot));
console.log(`${success} Loaded event ${eventName}`);
})
.catch(function(err) {
console.error(`${error}: Error loading event: ${err}`);
return;
});
I think this gets you what you want, just put the conditions around it as needed, instead of my for loop, use an if statement, or whatever.

Jasmine - Load nested describes from external files?

I'm writing e2e tests using Jasmine and Protractor with AngularJS. I have a parent describe which describes the page, and some setup call in beforeAll that goes to the correct page for the following tests. I've broken these tests up into multiple describes per feature. Here is an example:
describe('Page Detail', () => {
beforeAll(() => {
utils.doSomething();
})
describe('Location Section'), () => ...
describe('Information Section', () => ...
The problem I'm having is that there are a lot of features within this module, and the tests are starting to push 300-400 lines of code. I would ideally like to put the nested describes in seperate files and import them. I've done something like this:
const describeLocation = require('./folder/location'),
describeInformation = require('./folder/information');
describe('Page Detail', () => {
beforeAll(() => {
utils.doSomething();
})
describeLocation();
describeInformation();
In the other files I'm simply exporting an anonymous function and including the nested describe's code. This works, but unfortunately the tests don't have the jasmine context (can't access anything in beforeAll).
I'm curious if there is a standard or better way to accomplish this?
//export.js
describe(...
)
//Import or your main specs file
describe('',()=>{
require('./export');
})
Don't export in a form of a method just write your spec and import it using require in the main describe.

Nestjs: How to generate "spec.ts" files if --no-spec used to disable spec files generation

Nestjs: How to generate "spec.ts" files if --no-spec used to disable spec files generation. I need to test the complete module but i do not have spec.ts files. Is there any mechanism to generate these files for existing modules.
There is no way to re-run the spec file generation for a file that already exists. You can create the spec file manually, or you can tell Nest to create a new file of some sort, ensure that it creates a new spec file, and delete the other file it creates with it. If you are needing the boilerplate for the spec file, it's usually something like this:
import { Test, TestingModule } from '#nestjs/testing';
import { MyService } from './my.service';
describe('MyService', () => {
let service: MyService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MyService],
}).compile();
service = module.get<MyService>(MyService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
if you use vs-code plugin nestjs snippets
use prefix : n-test or n-test-service will quickly generate template code for test

Jest beforeAll() share between multiple test files

I have a Node.js project that I'm testing using Jest. I have several test files that have the same setup requirement. Previously, all these tests were in one file, so I just had a beforeAll(...) that performed the common setup. Now, with the tests split into multiple files, it seems like I have to copy/paste that beforeAll(...) code into each of the files. That seems inelegant - is there a better way to do this, ideally where I can just write my beforeAll(...)/setup logic once, and "require" it from multiple test files? Note that there are other tests in my test suite that don't require this setup functionality, so I don't want to make all my tests run this setup (just a particular subset of test files).
If you're using Jest >=20, you might want to look into creating a custom jest-environment for the tests that require this common setup. This would be a module that extends either jest-environment-node or jest-environment-jsdom, and implements async setup(), async teardown(), and async runScript() to do this setup work.
You can then add a #jest-environment my-custom-env directive to those files that require this setup.
See the Jest config docs for testEnvironment for details on how to set this up; there's a simple example there.
I am using a simple "test hooks" pattern for this:
// This function wraps beforeAll and afterAll into a single RAII-like call.
// That makes the describe code further down easier to read and makes
// sure you don't forget the afterAll part. Can easily be shared between tests.
function useFakeServer() {
let server;
beforeAll(() => server = sinon.fakeServer.create());
afterAll(() => server.restore());
return () => server;
}
describe('Some scenario', () => {
const getServer = useFakeServer();
it('accesses the server', () => {
const server = getServer();
// Test as you normally would..
expect(server.requests[0]. /* ... */);
});
});
If you need a script to run before all your test files, you can use globalSetup
This option allows the use of a custom global setup module which exports an async function that is triggered once before all test suites.
in your jest.config.js
//jest.config.js
module.exports = {
...
testTimeout: 20000,
globalSetup: "./setup.js"
};
then create a file named setup.js
// setup.js
module.exports = async () => {
console.log("I'll be called first before any test cases run");
//add in what you need to do here
};
Docs
You can move your beforeAll logic into one file and reference it in jest.config.js setupFilesAfterEnv section:
module.exports = {
...
setupFilesAfterEnv: ['<rootDir>/testHelper.ts'],
...
}
https://jestjs.io/docs/en/configuration#setupfilesafterenv-array
Create a function somewhere like so:
export function setupBeforeAndAfter(putParamsHereIfYouHaveAny) {
beforeAll(() => shared-before-all-code);
afterAll(() => shared-after-all-code);
beforeEach(() => shared-before-each-code);
afterEach(() => shared-after-each-code);
}
Then just call it wherever you would otherwise have manually written these functions:
describe('My test', () => {
setupBeforeAndAfter(putParamsHereIfYouHaveAny)
it('is amazing', () => {
// Stuff in setupBeforeAndAfter() will run before/after this test as appropriate
})
})

Resources