How run different describe blocks from different files using Jest - jestjs

I need to run differents describe blocks from different files in determinate order. Also, I need pass 1 argument between this blocks, but the argument needs to keep the state with which it left the previous describes. For example, i have this:
file1.test.js
export const Test1= () => {
describe("Describe 1", () => {
test("test1", async () => {//my test1
})
test("test2", async () => {//my test2
})
describe("Describe 2", () => {
test("test3", async () => {//my test3
})
test("test4", async () => {//my test4
})
}
file2.test.js
export const Test2= () => {
describe("Describe 3", () => {
test("test5", async () => {//my test5
})
test("test6", async () => {//my test6
})
describe("Describe 4", () => {
test("test7", async () => {//my test7
})
test("test8", async () => {//my test8
})
}
I want to run the tests in the following order with this argument:
let myArgument;
Test1
Describe 1(myArgument)
Test2
Describe 3
Test1
Describe 2(myArgument)
Test2
Describe 4
I am using to run the tests: jest --runInBand

It is generally a good idea to keep tests isolated from each other, so that failures of one test do not cascade to other tests. Playwright recommends using different browser contexts for tests – browser contexts are concurrent, isolated execution environments. They are cheap/fast to create, and can reuse a single browser instance.
Having said that, it is possible to achieve your use-case with Jest, with some work:
Define myArgument as a global object. Global objects are shared across tests, and can be defined through globals in your Jest config (docs)
Define a custom sequencer in your Jest config to define the sequence in which tests are executed. Use the testSequencer property in Jest config (docs)

Related

How to use jest.each asynchronously

I am having problems loading filenames into jest.each asynchronously.
My code:
let files: string[][]
function getFilesWorking() {
files = [["test1"], ["test2"]]
}
async function getFilesAsync() {
files = await Promise.resolve([["test1"], ["test2"]])
}
beforeAll(() => {
console.log("before")
})
describe.only("Name of the group", () => {
getFilesAsync()
test.each(files)("runs", f => {})
})
beforeAll is executed before each test but NOT before initialization of test.each, so I end up with undefined.
How can I load files before using test.each?
You can pass an async callback to beforeAll and await getFilesAsync within it
beforeAll(async () => {
await getFilesAsync();
})
As of Jest 28.1.3 and prior, this is not possible. There is an open issue documenting this behavior.
The best thing you can do for now is put your tests in a regular it() test and do a deep value comparison:
it('tests an array of cases', async () => {
const data = await getSomeAsyncData()
const expectedData = [ ... ]
expect(data).toEqual(expectedData)
})
You can use beforeEach to set up code that will run prior to tests for any given scope, https://jestjs.io/docs/setup-teardown:
beforeEach(() => {
console.log('before every test');
});
describe.only(('Name of the group') => {
beforeEach(() => {
console.log('before tests in this describe block');
})
})
Jest is only going to run the tests in your describe.only block. If you want to use beforeEach in other blocks and run those tests as well, change describe.only to describe.
(Edit: I know this is a year late, I'm just trying to look for a similar problem/solution set and thought I could answer this.)

Nodejs Jest mocking is not working in multiple describe block in a single file, it works in first describe block only

I am using jest for unit testing in my node express application,please excuse , because i am new to all this
in my abc.test.js
const s3Helper = require('../../../../../lib/s3_helper');
beforeEach(async () => {
s3Helper.uploadBufferToS3 = jest.fn(() => true);
});
describe('test1', () => {
it('test1', async () => {
expect(s3Helper.uploadBufferToS3)
.toHaveBeenCalled();
});
});
describe('test2', () => {
it('test2', async () => {
expect(s3Helper.uploadBufferToS3)
.toHaveBeenCalled();
});
});
so when i run this test file in test1 it returns that test is passed, however in test2 it returns expected >=1 returned 0.
since i am mocking it beforeEach i expect it should return 1 for each describe block

How to use resetMocks:true with module factory mocks

I would like to mock imported modules while keeping my unit tests independent of each other.
Setting resetMocks:true in my Jest config file means that behaviour set up using module factory mocking is lost (issue). Setting up module mocks in any other way doesn't work (issue).
Changing to resetMocks:false couples the unit tests and makes the order they are executed matter, which goes against unit testing best practices.
I have tried calling jest.mock('./a', () => {/* implementation */}) inside beforeEach() and at the top of test(). I have also tried to use a reference to a jest.fn() inside the module factory mock and then call .mockImplementation() on that reference.
Minimum demonstration:
// greeter.ts
export class Greeter {
sayHello(): string {
return 'hello world!';
}
}
// module-mocking.spec.ts
import { Greeter } from "./greeter";
jest.mock('./greeter', () => ({
Greeter: jest.fn(() => ({ sayHello: () => 'goodbye world!' }))
}));
test('mocked module behaviour should exist', () => {
const result = new Greeter().sayHello();
expect(result).toEqual('goodbye world!');
});
This test fails with the error:
TypeError: (intermediate value).sayHello is not a function
Moving the jest.mock() inside beforeEach() or into test() results in:
Expected: "goodbye world!" Received: "hello world!"
Edit
I managed to work around this by using require instead of import. The question still remains for ES6 imports.
// module-mocking.spec.ts
const greeter = require("./greeter");
let mockGreeter: any;
beforeEach(() => {
mockGreeter = { sayHello: () => 'goodbye world!' };
greeter.Greeter = jest.fn(() => mockGreeter);
});
test('mocked module behaviour should exist', () => {
const result = new Greeter().sayHello();
expect(result).toEqual('goodbye world!');
});

Jest limit concurrency of integration tests

How can I limit the concurrency of test execution in jest? Let's say I only want to run 4 test cases in parallel at the same time.
My current problem is that I have a lot of integration tests using a real database connection. Jest executes too much test cases in parallel, thus often connections timeout or the performance of my test database instance drops significantly because there are too many queries at the same time.
All of my integration test suits have the following structure:
describe('<functionality x>', () => {
test('case 1', async () => {...})
test('case 2', async () => {...})
test('case 3', async () => {...})
})
describe('<functionality y>', () => {
test('case 1', async () => {...})
test('case 2', async () => {...})
test('case 3', async () => {...})
})
I already tried running jest with --maxWorkers=1, but I guess this is the same as --runInBand, which works, but really slows down the overall execution time.
Rather than --maxWorkers=1, you could provide a larger value like --maxWorkers=2 or --maxWorkers=50%.
However, if you are trying to limit the number of tests running in parallel, it seems like you want to use:
jest --maxConcurrency=N
Jest's documentation says:
Prevents Jest from executing more than the specified amount of tests at the same time. Only affects tests that use test.concurrent.
so, note you have to modify your tests by adding the .concurrent:
describe('<functionality x>', () => {
test.concurrent('case 1', async () => {...})
test.concurrent('case 2', async () => {...})
test.concurrent('case 3', async () => {...})
})
describe('<functionality y>', () => {
test.concurrent('case 1', async () => {...})
test.concurrent('case 2', async () => {...})
test.concurrent('case 3', async () => {...})
})

beforeAll and beforeEach suite instead of spec

I am writing some e2e tests using protractor 5. What I am trying to achieve is to execute whole tests which shared setup, and specific setup (for groups of tests).
I got following code:
Base.ts:
beforeAll(() => {
console.log("before all base");
});
beforeEach(()=> {
console.log("before each base");
});
afterEach(() => {
console.log("after each base")
});
afterAll(() => {
console.log("after all base");
});
TestSuite1.ts:
require('./Base');
describe("test suite 1", () => {
beforeAll(() => {
console.log("before all 1");
});
beforeEach(()=> {
console.log("before each 1");
});
afterEach(() => {
console.log("after each 1")
});
afterAll(() => {
console.log("after all 1");
});
it("test 1", () => {
console.log("test 1 1");
});
it("test 2", () => {
console.log("test 1 2");
});
});
TestSuite2.ts:
require('./Base');
describe("test suite 2", () => {
it("test 1", () => {
console.log("test 2 1");
});
it("test 2", () => {
console.log("test 2 2");
});
});
and conf.ts:
var testsTimeout = 3600000;
export let config: Config = {
framework: 'jasmine',
capabilities: {
browserName: 'chrome'
},
specs: ['test/TestSuite1.js', 'test/TestSuite2.js'],
seleniumAddress: 'http://localhost:4444/wd/hub',
noGlobals: true,
allScriptsTimeout: testsTimeout
};
I would like to get following output:
before all base
before each base
before all 1
before each 1
test 1 1
after each 1
before each 1
test 1 2
after each 1
after all 1
after each base
before each base
test 2 1
test 2 2
after each base
after all base
Unfornatelly my before/after all and before/after each are grouped together and prints as follows:
before all base
before all 1
before each base
before each 1
test 1 1
after each 1
after each base
.before each base
before each 1
test 1 2
after each 1
after each base
.after all 1
before each base
test 2 1
after each base
.before each base
test 2 2
after each base
.after all base
Is it possible to get execution flow which I expect?
This is possible, your function will be executed before/after everything in your suite.
Idea is to put beforeAll() afterAll() or beforeEach() afterEach() into protractor's configuration file - into onPrepare() section.
This might look like this:
module.exports.config = {
//somewhere in your config
onPrepare: function () {
beforeEach(function () {
//This will be executed before EVERY 'it' in each specfile
})
beforeAll(function () {
//This will be executed before EVERY 'describe' in each specfile (even before nested describes)
})
}
}
Also check other options in protractor config: onComplete() afterLaunch() - they might better work for you instead jasmine functions
You might want to look on jasmine reporters, in case you need to somehow work with test name, test result, suite result, and might be good alternative to before/after functions . They are pretty easy to create and use, check this:
https://jasmine.github.io/edge/custom_reporter.html
I guess this is how Protractor is designed to work. There was an issue which was raised to track the scenario where a beforeAll() runs before any beforeEach() in parent describe block
Check the complete discussion here.
With the current implementation (if I understand correctly), it only
really makes sense to have a single beforeAll, and this should either
be outside of any describe block, or at the top of the outermost
describe block. i.e. It would make no sense for my 2nd beforeAll to be
located where it is.

Resources