RNA
RNA

Reputation: 1071

Mocha test for async Meteor.call

I am new to both Meteor and Mocha. It looks like I am not writing the test properly, I would like some help here.

Basically this is what I am trying to do:

  1. get status of an app
  2. toggle status
  3. get current status again
  4. check if it's toggled

.

if(Meteor.isServer) {
  describe('should be able to toggle the status', function() {        

    // check if toggle working
    it('should be able to toggle the status', function(done) {

      // if app is in DB
      if (Apps.findOne({ url: sampleUrl })) {

        // get the current status
        let status = Apps.findOne({ url: sampleUrl }).status;

        // run toggle method
        Meteor.call('toggle', Apps.findOne({ url: sampleUrl }), function(error) {

          if (error) {
            // handle error
            console.log(error);
          } else {

            // get the current status again
            const newStatus = Apps.findOne({ url: sampleUrl }).status;

            // compare
            expect(status).to.equal(!newStatus);
            done();
          }
        });
      }
    });
  });
 }

The questions are:

  1. Test finishes before Meteor.call('toggle') is done, How do I make it wait til Meteor.call is finished then proceed the test?
  2. if (Apps.findOne({ url: sampleUrl })) sometimes is false, I think this if statement is called when the app is not yet added to DB, How do I make sure app is added? I am adding the app as:

    // add app to DB before test
    before(function(done) {
      Meteor.call('addApp', app);
      done();
    });
    
  3. Is there a way to // handle error properly other than console.log(error)? I would like Mocha to throw an error and say what was wrong and stop proceeding.

Upvotes: 0

Views: 401

Answers (1)

Jankapunkt
Jankapunkt

Reputation: 8413

Try the following code, comment if it is not working. We can make this work.

if (Meteor.isServer) {

    // For Question 2: first call to your addApp
    // addApp should return true, once the app is running
    const isRunning = Meteor.call('addApp', app); 
    assert.isTrue(isRunning);

    describe('should be able to toggle the status', function() {        

        // check if toggle working
        it('should be able to toggle the status', function(done) {

            // ensure that app is defined
            // so no if required
            const currentApp = Apps.findOne({ url: sampleUrl });
            expect(currentApp ).to.notEqual(null);
            expect(currentApp ).to.notEqual(undefined);

            // get the current status from app
            let status = currentApp.status;

            // run toggle method
            Meteor.call('toggle', Apps.findOne({ url: sampleUrl }), function(error) {

                if (error) {
                    // Regarding question 3:
                    done(error);
                } else {

                    // get the current status again
                    const newStatus = Apps.findOne({ url: sampleUrl }).status;

                    // compare
                    expect(status).to.equal(!newStatus);
                    done();
                }
            }); // close call
        }); // close it
  }); // close describe
}

Regarding Question 1 I can just say, that using done in callbacks usually works quite fine to make mocha wait until your Meteor.call has been completed. Maybe it resolves your overall problem, if you add the done(error) callback as described regarding question 3.

Regarding you meteor methods

Usually you would mock the addApp method's result e.g. with sinon or manually to ensure, that issues in this function do not interfere your tests of toggleApp. I really suggest you to read more into mocking and spying to have more clean and more seperate units of tests.

Upvotes: 1

Related Questions