How do you test your Meteor Publications?

I’m just wondering and curious if, and if so, how do you test your publications? What frameworks, patterns do you use?

I’m going to bump this because I think it’s an important topic. Pub/sub in most meteor apps constitutes most of the who-can-see-what security.

I have some tests which use this style of testing publications:

#coffeescript
publicationName = 'foo'
publicationHandler = Meteor.server.publish_handlers[publicationName]
thisContext = {userId: 'bob'}
publishParams = ['some', 'params']
publishedCursor = thePublicationFunction.apply(thisContext, publishParams)
#followed by some test code inspecting the records in the cursor.

This allows me to test the contents of the cursor returned from the publish function as a user would see it. The problem is this only works with “simple” publish functions that returns a cursor, like this:

Meteor.publish({
  foo: function() {
    if (!this.userId) return;
    return FooCollection.find({userId: this.userId})
  }
});

If foo is more complicated (ex. calls observeChanges, this.added, this.changed, this.removed), I don’t know a good way to test the publication. Anyone else?

1 Like

Am very interested in seeing what other people come up w/ on this as well. One package that I’ve been using which might help is practicalmeteor:munit.

Given @mark’s publication, you could probably use a sinon.stub() on Meteor.server.publish_handlers. Perhaps something like:

describe('test the publication', function() {
	var context;

    beforeAll(function() {
    	sinon.stub(FooCollection, 'find').returns('cursor');
    });
    afterAll(function() {
    	FooCollection.find.restore();
    });

    beforeEach(function() {
    	context = { userId: "bob" };
    	FooCollection.find.reset();
    });

    it('should call .find() on collection with correct params and return the cursor', function() {
    	var params = ['some', 'params'];
    	var result = Meteor.server.publish_handlers.foo.apply(context, params);
    	assert.isTrue(FooCollection.find.calledWithExactly({ userId: "bob" }), 'FooCollection.find() was not called with correct params');
    	assert.equal(result, 'cursor', 'The publication function did not return the cursor');
    });

});

For more complex publication logic, you could fake a return object with .added(), .changed() and .removed() stubbed out as well.

Meteor publication collector package takes care of stubbing added, changed, removed methods.