0

I just added a route in one of my node router files and would like to add the appropriate unit test for it. The route is the following:

router.post('/addtradables', checkIsAdmin, async function(req, res, next) {
  const SteamApp = require('../models/steamapp.model');
  const Tradable = require('../models/tradable.model');
  const User = require('../models/user.model');
  const postedTradables = req.body.tradables;

  if(postedTradables) {
    res.json({ success: true, result: constants.PROCESS_STARTED, textResult: 'The tradables are being added' });
    const adminUser = await User.findOne({ steamId: ADMIN_ID }).exec();

    for(let currentKey in postedTradables) {
      if(postedTradables.hasOwnProperty(currentKey)) {
        const currentTradable = postedTradables[currentKey];
        const appFound = currentTradable.sku ? await SteamApp.findOne({ appid: currentTradable.sku }).exec() : null;
        
        await new Tradable( { /* object data here */ } ).save();
      }
    }
  } else {
    return res.json({ success: false, result: constants.INVALID_FORMAT, textResult: 'No tradable found, check the format' });
  }
} );

As you can see, it returns an object with a code and text message so that the front end can know if the process was started or not. This is because the insertion process can take a while, depending on the input data.

Here is my Jasmine spec file:

const app = require('../../app');
const request = require('supertest');
const MongoDbTest = require('../../lib/mongodb-tests.lib');
const jwt = require('jsonwebtoken');
const SteamApp = require('../../models/steamapp.model');
const Tradable = require('../../models/tradable.model');
const User = require('../../models/user.model');
const JWT_TOKEN = process.env.JTW_KEY;
const ADMIN_ID = process.env.MASTER_STEAMID;

const constants = require('../../config/constants');

const adminUser = {
  role: 'admin',
  steamId: ADMIN_ID
};

const testTradable = {
  sku: 1234,
  barterId: 83838,
  extra: 2,
  type: 'gift',
  title: 'Les patates volent!'
};

describe("route /addtradables", () => {
  const mongod = new MongoDbTest();
  let testOwner;

  beforeAll(async () => {
    await mongod.connect();
    await new SteamApp({ appid: 1234, name: 'patate' }).save();
    testOwner = await new User(adminUser).save();
  } );

  afterAll(async () => {
    await SteamApp.deleteMany({});
    await User.deleteMany({});
    await mongod.close();
  } );

  it("devrait retourner un message indiquant que le format est incorrect lorsque c'est le cas", async () => {
    const userToken = jwt.sign(adminUser, JWT_TOKEN, { algorithm: 'HS256' });
    const response = await request(app).post(`/api/addtradables`).send({ patate: 'pouelle' }).set('Authorization', `Bearer ${userToken}`).expect('Content-Type', /json/);
    expect(response.statusCode).toBe(200);
    expect(response.body.success).toBe(false);
    expect(response.body.result).toBe(constants.INVALID_FORMAT);
  } );

  it("devrait retourner un message indiquant que le processus a débuté lorsque le format est correct", async () => {
    const userToken = jwt.sign(adminUser, JWT_TOKEN, { algorithm: 'HS256' });
    const response = await request(app).post(`/api/addtradables`).send({ tradables: { 9837489374: testTradable } }).set('Authorization', `Bearer ${userToken}`).expect('Content-Type', /json/);
    expect(response.statusCode).toBe(200);
    expect(response.body.success).toBe(true);
    /*
     I WANT TO WAIT HERE! If I don't wait for the router.post call to finish the data will not be available in the database
    */
    const insertedTradable = await Tradable.findOne({ appid: 1234 }).exec();
    expect(insertedTradable.barterId).toBe(testTradable.barterId);
    expect(insertedTradable.isGift).toBe(true);
    expect(insertedTradable.copies).toBe(testTradable.extra);
    expect(insertedTradable.name).toBe(testTradable.title);
  } );
} );

Is there a way to spy on the router.post call and check when everything is completed so that I can extract data from the database and check that the data was inserted properly? Short of that, what would be the best way to sleep / stop execution in the jasmine test routine while the the router.post call wraps up? I've looked at using a done function but since the code is inside the router I don't see how I could use done in this scenario.

Technoh
  • 1,606
  • 15
  • 34
  • https://stackoverflow.com/questions/51156856/can-you-make-supertest-wait-for-an-express-handler-to-finish-executing I think you're facing that situation, try to see if the answer can help you out even if it is hacky. – AliF50 Nov 19 '20 at 00:28
  • Well I was able to build a similar function that simply waits a fixed amount of time and that works but I was wondering if there was an official Jasmine way to do this. – Technoh Nov 19 '20 at 15:23
  • I think it would be more a `supertest` responsibility compared to Jasmine but I don't think `supertest` allows it. – AliF50 Nov 19 '20 at 16:15

0 Answers0