7

I try to test my api with Jest. I want more abstraction, so i created this function:

const tokensConfig = config.get('test.tokens');

function testIt(method = 'get', url = '/', statuses = [], body = {}) {
      const testNames = ['unauthorized', 'user', 'admin'];
      const tokens = [null, tokensConfig.user, tokensConfig.admin];
    
      for (let i = 0; i < testNames.length; i++) {
        test(testNames[i], async () => {
          const response = await request(app)
            [method](url)
            .set('Accept', 'application/json')
            .set('Authorization', tokens[i])
            .send(body);
          expect(response.statusCode).toBe(statuses[i]);
        });
      }
    }

In test.js file i run:

const config  = require('config');
const request = require('supertest');
const testIt  = require('./testIt');
const app     = require('../app');

// It's work
describe('get user by email', () => {
    testIt('get', '/users/get-by-email/user@test', [401, 403, 200]);
  });
  
// It's not work  
describe('delete user', async () => {
    const userByEmail = await request(app)
      .get('/users/get-by-email/user@test')
      .set('Accept', 'application/json')
      .set('Authorization', config.get('test.tokens.admin'));

    testIt('delete', `/users/${userByEmail._id}`, [401, 403, 200]);
  });

Trouble in async/await - testIt running before request user.

If i move test (or it) to describe block from function testIt and create request user inside test, it will work. But i want more abstraction (test block very big for many tests)

How fix it?

4
  • What is test inside testIt? Commented May 2, 2018 at 12:18
  • 1
    I don't think describe support async functions. Commented May 2, 2018 at 12:18
  • @Bergi good catch, thats definitely it. describe describes a set of tests with it Commented May 2, 2018 at 12:24
  • I understand, that describe don't support async/await. If i move test (or it) to describe block from function testIt, it will work. But i want more abstraction (test block very big fro many tests). Commented May 2, 2018 at 12:32

2 Answers 2

5

Looks like you need to let jest know that the expect is an async method, with resolves.

Here is the sample code from Jest's documentation:

// async/await can be used.
it('works with async/await', async () => {
  expect.assertions(1);
  const data = await user.getUserName(4);
  expect(data).toEqual('Mark');
});

// async/await can also be used with `.resolves`.
it('works with async/await and resolves', async () => {
  expect.assertions(1);
  await expect(user.getUserName(5)).resolves.toEqual('Paul');
});

https://facebook.github.io/jest/docs/en/tutorial-async.html#async-await

Sign up to request clarification or add additional context in comments.

Comments

1

As a result, i had to move the test to test.js:

// test.js

it('delete user', async () => {
    const userByEmail = await request(app)
      .get('/users/get-by-email/user@test')
      .set('Accept', 'application/json')
      .set('Authorization', config.get('test.tokens.admin'));

    const result = await testIt('delete', `/users/${userByEmail.body._id}`);
    expect(result).toEqual([401, 403, 401, 200]);
  });

// testIt.js

const config  = require('config');
const request = require('supertest');
const app     = require('../app');

const tokensConfig = config.get('test.tokens');

async function testIt(method = 'get', url = '/', body = {}) {
  const testNames = ['unauthorized', 'user', 'adminTokenExpired', 'admin'];
  const tokens = [null, tokensConfig.userTokenInfinity, tokensConfig.adminTokenExpired, tokensConfig.adminTokenInfinity];
  let result = [];

  for (let i = 0; i < testNames.length; i++) {
    const response = await request(app)
      [method](url)
      .set('Accept', 'application/json')
      .set('Authorization', tokens[i])
      .send(body);

    result.push(response.statusCode);
  }

  return result;
}

module.exports = testIt;

But i had to confine myself to one answer to all roles instead individual answer to every role, because i want less code.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.