-1

Context: I am trying to set up testing using jest and supertest for a MongoDB application I am writing

The aim: Assign a value returned from the postArticleByAPI function to a constant id.

Issue: It's returning Promise { <pending> }

What I have tried:

  1. Promise.resolve(postArticleByAPI) results in the same issue.
  2. Chaining a .then((res) => {console.log(res}) results in undefined.

I think I fundamentally don't understand promises, or namely how to assign values they return outside of the promise. Is this possible? Anyone have any tips?

const articleData = {title: 'Hello123', doi: '123', journal: 'Facebook'};

/**
 * Posts an article through the API
 * @param {Object} article - the article objection containing dummy data
 * @return {string} request - the article id stored in the database
**/
async function postArticleByAPI(article) {
  await request(app)
      .post('/api/articles')
      .send(article)
      .expect(200)
      .then((response) => {
        expect(response.body.title).toBe(article.title);
        expect(response.body.doi).toBe(article.doi);
        expect(response.body.journal).toBe(article.journal);
        expect(response.body.id).toBeTruthy();
        return response.body.id;
      });
}


describe('Test POST through API', () => {
  test('It should response the POST method /api/articles', () => {
    const id = postArticleByAPI(articleData);
    console.log(id);
  });
});
user5067291
  • 440
  • 1
  • 6
  • 16
  • You're not returning anything in the function – Phix May 15 '21 at 17:31
  • ALL `async` functions return a promise. That's how they work. You have to use `.then()` or `await` on that returned promise to know when it has finished its work and/or get the resolved value out of it (if you decide to return a value from your `async` function. – jfriend00 May 15 '21 at 17:45
  • @Phix is correct, you forgot to `return`. However `return await...` is an anti-pattern and you can simply write `return ...` because all `async` functions automatically return promises. For this function particular, since there is no `await` you can remove the `async` keyword as well, `function postArticleByAPI(article) { return request(...) }` works exactly the same. – Mulan May 15 '21 at 17:46

1 Answers1

0

Indeed postArticleByAPI returns a Promise and it's not resolved at the time you log it. You should write this instead:

describe('Test POST through API', () => {
  test('It should response the POST method /api/articles', async () => {
    const id = await postArticleByAPI(articleData);
    console.log(id);
  });
});

Also don't forget to return the Promise from postArticleByAPI:

function postArticleByAPI(article) {
  return request(app)
      .post('/api/articles')
      .send(article)
      .expect(200)
      .then((response) => {
        expect(response.body.title).toBe(article.title);
        expect(response.body.doi).toBe(article.doi);
        expect(response.body.journal).toBe(article.journal);
        expect(response.body.id).toBeTruthy();
        return response.body.id;
      });
}

If you want to use async and await, you should not use .then -

async function postArticleByAPI(article) {
  const response =
    await request(app)
      .post('/api/articles')
      .send(article)
      .expect(200)

  expect(response.body.title).toBe(article.title);
  expect(response.body.doi).toBe(article.doi);
  expect(response.body.journal).toBe(article.journal);
  expect(response.body.id).toBeTruthy();
  return response.body.id;
}
Guerric P
  • 30,447
  • 6
  • 48
  • 86