Reputation: 603
I found that I have many repeated tests cases in multiple integration tests in a Node.js REST API. So for example, I test invalid requests for every endpoint where I expect an error to always have the same properties.
import { app } from 'server';
import * as request from 'supertest';
describe('Authentication tests', () => {
describe('POST /login', () => {
// other test cases
// describe('valid request should ...', () => {...})
describe('invalid requests with missing fields', () => {
let response = null;
beforeAll(async () => {
await request(app)
.post('/login')
.expect('Content-Type', 'application/json; charset=utf-8')
.field('email', '[email protected]')
.then(res => {
response = res;
});
});
it('should return an invalid status code', () => {
expect(response.status).toBe(400);
});
it('should return a valid error schema', () => {
expect(typeof response.body).toBe('object');
expect(response.body).toHaveProperty('error');
expect(response.body.error).toHaveProperty('code');
expect(response.body.error).toHaveProperty('message');
});
it('should return an error with explicit message', () => {
expect(response.body.error).toHaveProperty('message');
});
});
});
});
Does Jest provide any way to create some share tests so I can encapsulate this error validation and declare it in other suite cases avoiding so much repetition?
Upvotes: 2
Views: 2944
Reputation: 102467
You can encapsulate these tests into a function. The docs says:
Tests must be defined synchronously for Jest to be able to collect your tests.
For example:
function createInvalidRequestTests() {
describe('invalid request', () => {
let response;
beforeAll(async () => {
// simulate request of supertest
response = await Promise.resolve({ status: 400, body: { error: { code: 1, message: 'network error' } } });
});
it('should return an invalid status code', () => {
expect(response.status).toBe(400);
});
it('should return a valid error schema', () => {
expect(typeof response.body).toBe('object');
expect(response.body).toHaveProperty('error');
expect(response.body.error).toHaveProperty('code');
expect(response.body.error).toHaveProperty('message');
});
it('should return an error with explicit message', () => {
expect(response.body.error).toHaveProperty('message');
});
});
}
Then, you can use this function to define your tests. Jest test runner will collect and run these tests as usual
describe('Authentication tests', () => {
describe('POST /login', () => {
describe('valid request', () => {
it('should login correctly', () => {
expect(1).toBe(1);
});
});
createInvalidRequestTests();
});
describe('POST /register', () => {
describe('valid request', () => {
it('should register correctly', () => {
expect(2).toBe(2);
});
});
createInvalidRequestTests();
});
});
Unit test result:
PASS src/stackoverflow/58081822/index.spec.ts (9.622s)
Authentication tests
POST /login
valid request
✓ should login correctly (5ms)
invalid request
✓ should return an invalid status code
✓ should return a valid error schema (2ms)
✓ should return an error with explicit message
POST /register
valid request
✓ should register correctly (1ms)
invalid request
✓ should return an invalid status code (1ms)
✓ should return a valid error schema (2ms)
✓ should return an error with explicit message (1ms)
Test Suites: 1 passed, 1 total
Tests: 8 passed, 8 total
Snapshots: 0 total
Time: 12.053s, estimated 14s
Upvotes: 2