How do you test your Meteor Publications?


#1

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


#2

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?


How to get a list of available publishes
#3

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.


#4

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