Meteor-Community-Packages/meteor-publication-collector

Support multiple `collector.collect`-calls within 1 test

Opened this issue ยท 4 comments

Hi Johan,

first of all: thanks for this cool package!! ๐Ÿ‘

I have a useCase where I am creating shitloads of fixtures (they take about 10 seconds to be created) and I'd love to write ONE integrational-test, testing different subscriptions - all within ONE test.

The problem is that collecter.collect can only be run ONCE within the testcase.

It would be so cool if we could use the syntax in synchronous style, so that we can call collecter.collect multiple times, like so:

  it('should allow to call collect multiple times', function() {
    const collector = new PublicationCollector({userId: Random.id()});

    collector.collect('publicationName', 'arg1', (collections) => {
      console.log('arg1')
      assert.equal(collections.myCollection.length, 10);
    });
    collector.collect('publicationName', 'arg2', (collections) => {
      // NOT called right now
      console.log('arg2')
      assert.equal(collections.myCollection.length, 10);
    });
  });

or

  it('should allow to call collect multiple times', function(done) {
    const collector = new PublicationCollector({userId: Random.id()});

    const differentArgumentValues = [
      'argValue1',
      'argValue2',
      'argValue3',
    ]
    _.each(differentArgumentValues, (currentArgument) => {
      collector.collect('publicationName', currentArgument, (collections) => {
        console.log(`testing currentArgument "${currentArgument}"`)  // only gets called for the first value "argValue1"
        assert.equal(collections.myCollection.length, 10);
      });
    })
    done();
  });

Any chance or trick of supporting this?

I would like something similar so that I can test my peerlibrary:reactive-publish based publications that change if the underlying query changes.

a quick workaround is to simply instanciate more collectors, like so:

  it('should allow to call collect multiple times', function() {
    const collector = new PublicationCollector({userId: Random.id()});
    const collector2 = new PublicationCollector({userId: Random.id()});

    collector.collect('publicationName', 'arg1', (collections) => {
      console.log('arg1')
      assert.equal(collections.myCollection.length, 10);
    });
    collector2.collect('publicationName', 'arg2', (collections) => {
      console.log('arg2')  // will be called
      assert.equal(collections.myCollection.length, 10);
    });
  })

of course that does NOT make the code look clean and simple

Hi, sorry for the slow turn around on this.

Exactly how isn't it working to call collect() several times? I'd guess it's because stop() is called on the subscription within the code: https://github.com/johanbrook/meteor-publication-collector/blob/master/publication-collector.js#L36-L42

@thebarty I personally do not see a reason to run the two publications sequentially. This would be as putting it into two tests. But I see a reason to run them in parallel (as the other publication is still running).

Since the PublicationCollector stops the subscription after the collect() method has run and it's callback is executed, I decided to move my second collect() call into the callback.

Here's a sample:

it('should allow to call collect multiple times', function(done) {
    const collector = new PublicationCollector({userId: Random.id()});
    const collector2 = new PublicationCollector({userId: Random.id()});

    collector.collect('publicationName', 'arg1', (collections1) => {
        collector2.collect('publicationName', 'arg2', (collections2) => {
            // Do your comparison here ...
            done();
        });
    });
});

Hope it helps in your case as well. If you want, you can also use this to collect to the same collector. This would then be the same as to subscribe to two publications on one client.

EDIT: You only need to call the done-method yourself when using delayInMs to catch documents added after the collect method has finished. This also changes the description above. You might also archive your goal by using delayInMs but I think you can easily run into a race-condition if you do not think it through properly.