Hello, I’m trying to make publication integration tests and faced with situation when inside one publications this instanceof === Object, I mean it is global object, not Publications. Why could this happens?
code of test:
it("should not let a regular user fetch userIds", function (done) {
const shopMembers = Meteor.server.publish_handlers["ShopMembers"];
spyOn(Meteor.server.publish_handlers, "ShopMembers").and.callFake(
function () {
this.userId = "notAdminUser";
return shopMembers.apply(this, arguments);
}
);
const cursor = Meteor.server.publish_handlers.ShopMembers();
expect(cursor).toEqual([]);
return done();
});
it("should not let a regular user fetch userIds", function () {
const publication = Meteor.server.publish_handlers["ShopMembers"];
const thisContext = {
userId: 'notAdminUser'
};
// spy on what you need to spy on here to make sure you get to the correct code path you want to test
const cursor = publication.apply(thisContext);
expect(cursor).toEqual([]);
});
@sam, thanks again, but my problem is not only in test, but why Meteor.publish this instanceof Object? How do you think, is this publication code correct?
Btw, I’m successfully running this test like so:
it("should not let a regular user fetch userIds", function (done) {
// setup
spyOn(Meteor.server.publish_handlers, "ShopMembers").and.callFake(
function () {
this.userId = "notAdminUserId";
// not so good, but this is the best I found to make this test works
this.ready = new Function("", "return 'test passed';");
return shopMembers.apply(this, arguments);
}
);
spyOn(ReactionCore, "getShopId").and.returnValue(shopId);
spyOn(Roles, "userIsInRole").and.returnValue(false);
// fixme: unexpected situation here. `this` inside this publication
// instance of global object, not `Publication`
const cursor = Meteor.server.publish_handlers.ShopMembers();
expect(cursor).toEqual("test passed");
done();
});
Ah I get what you mean. It’s because you are using apply, and passing in a new this context, which is an object. When Meteor calls it in the “real world” it gives it a Publication object.
This is a good thing, as it allows you to control the context of the publication. All you need to do now is this:
it("should not let a regular user fetch userIds", function () {
const publication = Meteor.server.publish_handlers["ShopMembers"];
const thisContext = {
userId: 'notAdminUser',
ready: function() { return true; }
};
spyOn(ReactionCore, "getShopId").and.returnValue(shopId);
spyOn(Roles, "userIsInRole").and.returnValue(false);
const cursor = publication.apply(thisContext);
expect(cursor).toEqual([]);
});
You don’t need the extra callFake if you do it the way I suggest here. Also, you don’t need a done since this test is not async