"Meteor.userId can only be called by calling a method" in the Meteor Method test

I am learning Meteor after the main "Todo tutorial" from the official site. I have a problem with the Testing step. I have a basic test of one method, it looks like this:

if (Meteor.isServer) {
    describe('Tasks', () => {
        describe('methods', () => {
            const userId = Random.id();
            let taskId;

            beforeEach(() => {
                Tasks.remove({});
                taskId = Tasks.insert({
                    text: 'test task',
                    createdAt: new Date(),
                    owner: userId,
                    username: 'tmeasday',
                });
            });

            it('can delete owned task', () => {
                const deleteTask = Meteor.server.method_handlers['tasks.remove'];

                const invocation = { userId };
                deleteTask.apply(invocation, [taskId]);
                assert.equal(Tasks.find().count(), 0);
            });
        });
    });
}

      

This test failed with an error:

Error: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.
    at AccountsServer.userId (packages/accounts-base/accounts_server.js:82:13)
    at Object.Meteor.userId (packages/accounts-base/accounts_common.js:257:19)
    at Object.Meteor.methods.tasks.remove (imports/api/tasks.js:37:35)
    at Test.<anonymous> (imports/api/tasks.tests.js:27:28)
    at run (packages/practicalmeteor:mocha-core/server.js:34:29)
    at Context.wrappedFunction (packages/practicalmeteor:mocha-core/server.js:63:33)

      

IMO, this error message is contradictory because it speaks of an error that I didn't, because as you can see from line 4 in the error message, the stacktrace points to the body of the method declaration, it is:

'tasks.remove' (taskId) {
        check(taskId, String);

        const task = Tasks.findOne(taskId);
        if (task.owner !== Meteor.userId()) { // <- ERROR MESSAGE POINTS TO THIS LINE
            // If the task is private, make sure only the owner can delete it
            throw new Meteor.Error('not-authorized');
        }

        Tasks.remove(taskId);
    },

      

There is one difference between the tutorial code and mine: I removed the condition !todo.private

from my statements if

, so in the original tutorial they look like this: if (!task.private && task.owner !== Meteor.userId()) {...

IMO, this change makes the test reach the expression where it fails, because with the original code the test passes.

I also mentioned that changing Meteor.userId()

to this.userId

makes the test pass and the app also looks like it did before.

So my question is basically this: why is the error message showing me conflicting (IMO) information and what is the difference between use this.userId

and Meteor.userId()

in methods?

My complete code for the "Todo tutorial" project can be found at: https://github.com/kemsbe/simple-todo

+3


source to share


1 answer


Basically this.userId uses the context of the this

function and Meteor.userId () uses the current fiber to get the userId.



If you want your code to work with Meteor.userId (), you need to run your function on a fiber. Another thing you can do is dummy meteor.userId as described in How to unit test a meteor method with a practical meteorite: mocha

+2


source







All Articles