I'm building some API tests for the product I'm building. One of the test looks like this:
GET FILTERS
✓ should be restricted (45ms)
it should get the filters
✓ should return 200
✓ should return an object
✓ should close db connections
GET USERS COUNT
✓ should be restricted
✓ should throw error when payload is not correct
it should get the user count
✓ should return 200
✓ should return an object
✓ should close db connections
GET USERS FILE
✓ should be restricted
✓ should throw error when no queryId is specified
it should retrieve the file
✓ should return 200
✓ should download an excel file
✓ should close db connections
UPLOAD PROMOTION IMAGE
✓ should throw error when no file is specified
it should save the file
✓ should return 200
✓ should have named the file with the title of the promotion
✓ should have uploaded the file to S3 (355ms)
✓ should close db connections
CREATE PROMOTION
it should save the promotion
✓ should return 200
✓ should return a correct response
✓ should close db connections
GET PROMOTIONS
✓ should be restricted
it should get the promotions
✓ should return 200
✓ should be an array of promotions
✓ should contain the previously created promotion
UPDATE PROMOTION
it should update the promotion
✓ should return 200
✓ should return a correct response
✓ should close db connections
PUT PROMOTION IN BIN
it should put the promotion in the bin
✓ should return 200
✓ should return a correct response
✓ should close db connections
GET ARCHIVED PROMOTIONS
✓ should be restricted
it should get the promotions
✓ should return 200
✓ should be an array of promotions
✓ should be an array of archived promotions
✓ should contain the previously archived promotion
DELETE PROMOTION
it should delete the promotion
✓ should return 200
✓ should return a correct response
✓ should have deleted the file from S3 (563ms)
✓ should close db connections
As you can see I've tried to put everything regarding promotions in a single test suite so that I can have a sort of workflow to test what the user will do exactly on the platform.
In this example I create a random generate promotion and then use the id of that promotion to read it, update it, archive it and then finally delete it. Every step is connected and I need to have return values for each suit (i.e: The ID of the inserted promotion, or the filters...)
At this moment my promotions.test.js file is 625 and, since I have not finished yet, I expect it to grow a lot in the next days.
Is there a way to split multiple test suits in different files but in a way that each test/file is able to return, as soon as it finishes, a value that I can pass to the next step ?
EDIT FOR BOUNTY
At the moment I only tried something like this:
describe.only("Gifts Workflow", function() {
var createdGift;
describe("CREATE", function() {
require("./GIFTS/CREATE.js")().then(function(data) {
createdGift = data;
});
});
describe("READ FROM WEB", function() {
require("./GIFTS/READ FROM WEB.js")(createdGift).then(function(data) {
});
});
});
Content of "./GIFTS/CREATE.js"
module.exports = function() {
return new Promise(function(resolve, reject) {
//DO SOME TESTS WITH IT AND DESCRIBE
after(function() {
resolve(createdGift);
});
});
};
The problem is that the test are immediately initialized by mocha and so in the second test suite "READ FROM WEB" the value passed as createdGift is given immediately to the test without waiting for the first test to complete and so undefined is passed.
Jankapunkt's Answer
This is how I tried in my code:
var create = require("./GIFTS/CREATE");
var read = require("./GIFTS/READ FROM WEB");
describe.only("Gifts Workflow", function() {
create(function(createdGift) {
read(createdGift);
});
});
CREATE
module.exports = function(callback) {
var createdGift;
//SOME TESTS
describe("it should insert a gift", function() {
var result;
before(function() {
return request
.post(url)
.then(function(res) {
createdGift = res.body;
});
});
//SOME OTHER TESTS
});
after(function() {
callback(createdGift);
});
};
READ FROM WEB
module.exports = function(createdGift) {
it("should be restricted", function(done) {
request
.get(url)
.query({})
.end(function(err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
describe("it should read all gifts", function() {
//SOME TESTS
});
};
And this is the output
Gifts Workflow
✓ should be restricted
✓ should not work when incomplete payload is specified
it should insert a gift
✓ should return 200
✓ should return an object
✓ should have uploaded the image to S3 (598ms)
✓ should close db connections
it should read all gifts
✓ should return 200
✓ should return an array
✓ should contain the previously added gift
✓ should close db connections
10 passing (3s)
It may seems it's working but as you can see from the tabulation it should read all gifts is not a children of Gifts Workflow but is a child of the root suite.
This is what happens:
- Mocha calls the root suite
- Mocha finds the Gifts Workflow suite and executes the create() function inside this suite
- Since the function is asynchronous Mocha thinks that the Gifts Workflow suite is ended and returns to the root suite
- read() is executed
- Mocha exit from the root suite and goes to the next tests because ,being asynchronous, it thinks that all the test are finished
- Test #3,4,5,... are never called
Can you confirm this is your case alse with more that two tests ?