javascriptunit-testingmeteormocha.jsmeteor-methods

Passing Meteor.userId to validated method when testing


I have a validated method that I am writing a test for. The method checks that a user is an administrator and throws an error if they aren't.

I'm using dburles:factory to create a new user with 'administrator' role in the Meteor.users collection.

I'm then invoking the validated method using the userId of the 'admin' user, but it is throwing an error.

Although I invoke the method using the context of the administrator user as per the documentation, it doesn't seem to be passing it to the method. When I console.log(this.userId); in the method it returns undefined.

Can anyone check my code out and tell me why this is happening? Thanks!

Method code:

import { Meteor } from 'meteor/meteor';
import { Clients } from '../../clients';
import SimpleSchema from 'simpl-schema';
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { Roles } from 'meteor/alanning:roles';

export const createClient = new ValidatedMethod({
    name: 'Clients.methods.create',
    validate: new SimpleSchema({
        name: { type: String },
        description: { type: String },
    }).validator(),
    run(client) {

        console.log(this.userId); //this is undefined for some reason

        if(!Roles.userIsInRole(this.userId, 'administrator')) {
            throw new Meteor.Error('unauthorised', 'You cannot do this.');
        }
        Clients.insert(client);
    },
});

Test code:

import { Meteor } from 'meteor/meteor';
import { expect, be } from 'meteor/practicalmeteor:chai';
import { describe, it, before, after } from 'meteor/practicalmeteor:mocha';
import { resetDatabase } from 'meteor/xolvio:cleaner';
import { sinon } from 'meteor/practicalmeteor:sinon';
import { Factory } from 'meteor/dburles:factory';

import { createClient } from './create-client';
import { Clients } from '/imports/api/clients/clients';

describe('Client API Methods', function() {
  afterEach(function() {
    resetDatabase();
  });

  it('Admin user can create a new client', function() {
    let clientName = "Test",
        description = "This is a description of the client!",
        data = {
          name: clientName,
          description: description
        };

    Factory.define('adminUser', Meteor.users, {
      email: 'admin@admin.com',
      profile: { name: 'admin' },
      roles: [ 'administrator' ]
    });

    const admin = Factory.create('adminUser');

    console.log(Roles.userIsInRole(admin._id, 'administrator'));// this returns true

    //invoking the validated method with the context of the admin user as per the documentation
    createClient._execute(admin._id, data);

    let client = Clients.findOne();


    expect(Clients.find().count()).to.equal(1);
    expect(client.name).to.equal(clientName);
    expect(client.description).to.equal(description);
  });

Solution

  • I have worked out the solution to my issue.

    When you execute a validated method, you need to pass the userId as an object like { userId: j8H12k9l98UjL }

    I was passing it as a string so the method wasn't being invoked with the context of the user that was being created by Factory.

    This test now works perfectly

    Hope this helps someone else