johanbrook / meteor-publication-collector Goto Github PK
View Code? Open in Web Editor NEWTest a Meteor publication by collecting its output.
Home Page: https://atmospherejs.com/johanbrook/publication-collector
License: MIT License
Test a Meteor publication by collecting its output.
Home Page: https://atmospherejs.com/johanbrook/publication-collector
License: MIT License
Hi,
We've just updated Publication Collector to 1.1.0 and it's broken a few of our tests. Given that you've added support for Promises, I'd say this is probably something you'd consider "expected behaviour", but I was thinking you might want to update the changelog/history to note that it's a potentially breaking change.
Example of the problem:
// FooBarQux is a publication that has a check(argument, String) call for type-checking arguments
describe('FooBarQux subscription', () => {
it('Takes a String argument', () => {
const collector = new PublicationCollector();
expect(() => collector.collect('OrganisationDetail'))
.to.throw(/Match error/);
expect(() => collector.collect('FooBarQux', {
foo: 'bar',
}))
.to.throw(/Match error/);
});
});
This test has regressed because collector.collect()
no longer re-throws errors that are thrown by the publication; instead it returns a promise and rejects it.
This is obviously expected behaviour and we've updated our test suite accordingly, but I can only assume that anybody else testing for publication errors has been doing something similar, so I'd argue that this is potentially a breaking change?
When a collection is published using the low-level publication API, calling this.ready()
does not seem to have any effect. My tests are reporting: Error: timeout of 2000ms exceeded.
. I can't replicate this error when running the app and subscribing to the same publication. I noticed this package's tests are testing publications that all use return
, so it may be worth checking this use case.
Thanks for the package, though. It makes testing so much easier in the majority of use cases.
Hi,
I have a publication that returns a cursor. If the collection exists but the cursor has no documents, I would expect publication-collector have an empty array for that collection. Instead it is undefined.
Error: Cannot read property 'length' of undefined
If I add one document its fine.
Is this behavior expected?
Here's my publication:
Meteor.publish("pairsAsParticipant", function (participantId) {
authorizeOwner.call(this, participantId);
return Pairs.find( { $and: [ {"inviteeId":{$ne:null}}, { $or: [ { inviterId: participantId }, { inviteeId: participantId } ] } ] } );
});
and my test:
describe('No Pairs', () => {
beforeEach(function (){
resetDatabase()
// make 5 pairs
const fiveRandomPairs = [...Array(5)].map( () => {
return Factory.create('pair', { inviterId: Random.id(), inviteeId: Random.id() })
})
})
it('should find zero pairs if currentUser is not a participant', function() {
const collector = new PublicationCollector({userId: currentUserId})
collector.collect('pairsAsParticipant', currentUserId, (collections) => {
expect(collections.pairs).to.have.lengthOf(0)
})
})
})
Hello and thank you for this package!
I get an error on line 37:
this.observeHandles.forEach(handle => handle.stop());
โฃ
Error: Cannot read property 'stop' of undefined
at packages/johanbrook:publication-collector/publication-collector.js:37:47
at Array.forEach (native)
at PublicationCollector.<anonymous> (packages/johanbrook:publication-collector/publication-collector.js:37:29)
at PublicationCollector.ready (packages/johanbrook:publication-collector/publication-collector.js:99:10)
at PublicationCollector.collect (packages/johanbrook:publication-collector/publication-collector.js:53:10)
at Test.<anonymous> (imports/projects/api/projects.tests.js:26:19)
at run (packages/practicalmeteor:mocha-core/server.js:34:29)
The issue is caused by publishing a counter obtained using the meteor-publish-performant-counts package. This is my publication code:
Meteor.publish('PubName', function() {
const cursor = collection.find({})
const counter = new Counter('PubNameListCount', cursor)
return [
cursor, counter
];
})
I am not sure if this is because that package is not confirming to the subscription API, or because the publication-collector is relying on features that are not present in all publications. I did a little bit of investigation and I feel like it is the latter, but I am not that intimately familiar with the Meteor pub / sub mechanism yet so I could be missing something! Would there be interest in accepting a PR if it is warranted?
I have a publication that publishes a selection of users and fields depending on the user, but it doesn't work. I get the output below when i try to run it.
TypeError: Cannot read property 'call' of undefined
at PublicationCollector.collect (packages/johanbrook:publication-collector/publication-collector.js:67:28)
My publication looks like this:
Meteor.publish('users', function () {
const user = Meteor.users.findOne(this.userId);
if (!user) {
return this.ready();
}
if (Roles.userIsInRole(user._id, ['admin'])) {
return Meteor.users.find({}, {
fields: {
createdAt: 1,
emails: 1,
roles: 1,
},
});
}
return this.ready();
});
I have emptied and populated both the user and role collection and trying just to get the test working like this:
it('should publish users', function(done) {
const collector = new PublicationCollector({ userId: 'D9E6CRGLX4Me3p6x9' });
collector.collect('users', (collections) => {
done();
});
});
this.userId
is undefined
when using arrow function as argument of the publication.
// pub.js
Meteor.publish('posts', function({ _id }) {
const user = this.userId; // working correctly
return Posts.find({ _id, user });
});
// pub.js
Meteor.publish('posts', ({ _id }) => {
const user = this.userId; // userId is undefined
return Posts.find({ _id, user });
});
// test.js
const collector = new PublicationCollector({ userId });
collector.collect('posts', (collections) => {
assert.equal(collections.posts.length, 5);
done();
});
I have run into a problem with peerlibrary:reactive-publish where "publish._isDeactivated" is not a function.
TypeError: publish._isDeactivated is not a function
at Computation.<anonymous> (packages/peerlibrary_reactive-publish.js:354:24)
at runWithEnvironment (packages/meteor.js:1176:24)
at packages/meteor.js:1189:14
at packages/peerlibrary_server-autorun.js:474:23
at packages/peerlibrary_server-autorun.js:452:18
at Function.FiberUtils.synchronize (packages/peerlibrary_fiber-utils.js:188:12)
at Computation.Tracker.Computation.Computation._runInside (packages/peerlibrary_server-autorun.js:441:23)
at packages/peerlibrary_server-autorun.js:466:22
at Function.FiberUtils.synchronize (packages/peerlibrary_fiber-utils.js:188:12)
at Computation.Tracker.Computation.Computation._compute (packages/peerlibrary_server-autorun.js:463:23)
at new Computation (packages/peerlibrary_server-autorun.js:335:12)
at Object.Tracker.autorun (packages/peerlibrary_server-autorun.js:253:7)
at PublicationCollector.publish.autorun (packages/peerlibrary_reactive-publish.js:340:24)
at imports/api/users/server/publications.js:52:22
at PublicationCollector.<anonymous> (imports/api/users/server/publications.js:29:22)
at PublicationCollector.<anonymous> (packages/peerlibrary_subscription-data.js:234:30)
at PublicationCollector.<anonymous> (packages/peerlibrary_reactive-publish.js:371:30)
at PublicationCollector.collect (packages/johanbrook:publication-collector/publication-collector.js:44:20)
at Test.<anonymous> (imports/api/users/server/publicatons.test.js:35:19)
I wonder if this is along the same lines as the last issue that related to peerlibrary:reactive-publish?
Could you please add a license so that others can use this package? Publishing software without a license means that anyone attempting to use it would be in violation of copyright. If you could please add an MIT or another distribution-friendly license, that would be appreciated!
Thanks in advance!
I want to test (server side) a package, that auto-publishes data to the user. The publication scheme it uses therefore is
Metepr.publish(null, function(){...})
which adds the publication to the universal_publish_handlers
instead of publish_handlers
, as taken from the code.
When calling the collector.collect(null, ...);
then of course I get an error, because it uses publish_handlers[name]
and not universal_publish_handlers
when no name is provided.
Does it make sense to add this feature? I could try to provide a PR with an implementation and some tests, if desired.
I can't use publication-collector
while using peerlibrary:reactive-publish
at the same time.
server/example.test.js
import { PublicationCollector } from 'meteor/johanbrook:publication-collector'
import '/imports/api/server/publications.js'
describe('example', () => {
it('should return empty array', function(done) {
const collector = new PublicationCollector()
collector.collect('publication', (collections) => {
expect(collections.publication).to.be.deep.equal([])
done()
})
})
})
server/publications.js
Meteor.publish('publication', function() {
this.autorun(function() {
return Collection.find({ any: 'thing' })
})
})
I have to remove this.autorun()
to get the test working. Otherwise I'll get this error:
Error: publish._isDeactivated is not a function
at Computation.<anonymous> (packages/peerlibrary_reactive-publish.js:349:24)
at runWithEnvironment (packages/meteor.js:1176:24)
at packages/meteor.js:1189:14
at packages/peerlibrary_server-autorun.js:469:23
at packages/peerlibrary_server-autorun.js:447:18
at Function.FiberUtils.synchronize (packages/peerlibrary_fiber-utils.js:183:12)
at Computation.Tracker.Computation.Computation._runInside (packages/peerlibrary_server-autorun.js:436:23)
at packages/peerlibrary_server-autorun.js:461:22
at Function.FiberUtils.synchronize (packages/peerlibrary_fiber-utils.js:183:12)
at Computation.Tracker.Computation.Computation._compute (packages/peerlibrary_server-autorun.js:458:23)
Using:
It gives the error:
Exception in queued task: Error: Match error: Expected string, got object
It's caused by check(id, String);
. How can this be avoided? Thanks.
Hey Johan,
I recently came across a very missleading error from this package
Error: Cannot read property 'call' of undefined
at PublicationCollector.collect (packages/johanbrook:publication-collector/publication-collector.js:67:28)
....
which refers to those 2 lines:
collect(name, ...args) {
...
const handler = Meteor.server.publish_handlers[name];
const result = handler.call(this, ...args);
...
}
It turns out I "just" misspelled my publication which apperantly caused the read error.
Due to the thrown error, it took me a little while to figure out what caused the error (also because I'm not familiar with publish_handlers
or meteor internals in generall). Therefor I would love to get a more specific error message suggesting that I eventually misspelled the publication.
Unfortunately, I'm busy right now and therefor not able to provide a pull request. Sorry!
Since 1.0.4 the behaviour of collect(...) regarding this.stop() seems to be changed,
the callback will not be called if the publication is stopped before it is "ready".
Is this intended?
Thanks
?
This is what we get in our terminal as the error:
Exception in queued task: TypeError: Cannot call method 'idStringify' of undefined
at PublicationCollector.publish.added (packages/peerlibrary_reactive-publish/packages/peerlibrary_reactive-publish.js:283:1)
at added (packages/mongo/collection.js:346:11)
at packages/mongo/observe_multiplex.js:183:30
at Function..each..forEach (packages/underscore/underscore.js:108:1)
at Object.task (packages/mongo/observe_multiplex.js:177:9)
at [object Object]._.extend._run (packages/meteor/fiber_helpers.js:147:1)
at packages/meteor/fiber_helpers.js:125:1
Hi,
I'm trying to use the hwillson:stub-collections package for publication tests. I would like to use stubbed collections to have the tests run quicker.
The stacktrace of the error I get is:
Can't publish a cursor from a collection without a name. at [object Object].LocalCollection.Cursor._publishCursor (packages/minimongo.js:265:11) at packages/johanbrook:publication-collector/publication-collector.js:49:20 at Array.map (native) at PublicationCollector.collect (packages/johanbrook:publication-collector/publication-collector.js:44:47)
The error occurs because the hwillson:stub-collections package creates an in-memory (minimongo) collection to replace the real collection and that is achieved by creating a new Meteor collection without a name (null).
I realise this problem isn't because of your package, but I am hoping you have some insight to share?
Thanks!
When using a findOne()
query like so:
Meteor.publish('event', (id) => {
return Events.findOne({_id: id})
})
I get an error when I try to call collect()
on a publication collector:
Error: Object [object Object] has no method '_publishCursor'
at packages/johanbrook:publication-collector/publication-collector.js:33:44
I realize findOne()
doesn't return a cursor, but a document. For now I can use a regular find()
query in the publication as a temporary workaround. Any suggestions on how to fix this issue?
Hi,
First thanks for your package, it's really useful for testing Meteor publications.
With latest version I am getting following errors while testing my publications:
Error: done() called multiple times
Here the "done" function is the Mocha callback used for asynchronous code like the one you use in your usage example.
The publications I am testing are using the low-level added/changed/removed interface which means I am also calling the "ready" method once the initial record set is complete.
The problem in that case is that you're also calling "this.ready()" at the end of "collect" method and thus the callback passed to the "collect" method is called twice since it's part of the "ready" listener you're defining before calling the publication function.
That behavior was introduced in v1.0.5 since you're now adding the "ready" listener before calling the publication function.
I could be wrong but my recommendation would be to define an empty "ready" method on PublicationCollector
class (like the stop()
one) and use a different name for your custom ready event.
Let me know if that's not clear enough.
Thanks for your help.
-Nicolas
When testing the published data for this collection, userId = null
, I get Publish function can only return a Cursor or an array of Cursors
Meteor.publish('kibanaDashboards', function () {
//make sure that the user is logged in
if (this.userId) {
return KibanaDashboards.find({});
} else {
this.stop();
return [];
}
});
I think the collector should expect empty arrays and null
values.
I did npm i
, is there anything else I need to do to set up eslint? My editor (atom) is giving me Error: Cannot find module 'eslint-config-lookback/meteor'
Hi guys. I spent a couple of days on this and finally narrowed down the problem. I have this publication:
Meteor.publish("game_requests", function() {
const user = Meteor.user();
if (!user || !user.loggedOn) return [];
if (Game.isPlayingGame(user)) return GameRequestCollection.find({ _id: "0" }); //return [];
const id = user._id;
if (!id) return [];
return GameRequestCollection.find(
{
$or: [
{ challenger_id: id },
{ receiver_id: id },
{ owner: id },
{ matchingusers: id },
{ type: "seek" }
]
},
{ fields: { matchingusers: 0 } }
);
});
When I return find({_id: "0"})
, collector.collect returns correctly.
When I return []
, collector.collect does not resolve or call the callback.
According to the Meteor documentation, return []
is the accepted practice when returning an empty publication, right? Am I missing something, or is this an actual issue?
Thank you,
David Logan
In the latest version of Meteor (1.7.x) the following error is thrown when collecting data from a publication published with limit and/or skip:
Error: Must use an ordered observe with skip or limit (i.e. 'addedBefore' for observeChanges or 'addedAt' for observe, instead of 'added').
This seems to originate within the package because the same publication works correctly outside of the test.
My collection that is being returned sometimes has only two items in the array, but more than often it has three. Here is my code
import { PublicationCollector } from 'meteor/johanbrook:publication-collector';
import { chai, assert } from 'meteor/practicalmeteor:chai';
import { Communities } from '/imports/collections/communities.jsx'
import { Random } from 'meteor/random';
import { resetDatabase } from 'meteor/xolvio:cleaner';
import { _ } from 'meteor/stevezhu:lodash';
if (Meteor.isServer) {
describe('communities', function () {
before( () => {
resetDatabase()
_.times(3, () => {
Factory.create("community");
});
})
after( () => {
resetDatabase()
})
it('publishes all communities', function (done) {
const collector = new PublicationCollector();
collector.collect('communities', (collections) => {
console.log("\n\nCOMMUNITIES BEFORE\n\n")
console.log(Communities.find().fetch() )
console.log("\n\nCOMMUNITIES AFTER\n\n")
console.log(collections)
chai.assert.typeOf(collections.communities, 'array');
chai.assert.equal(collections.communities.length, 3);
done();
});
});
});
};
Usually this passing fine, but about 1/5 times it returns with an error saying expected 3 items in array, got 2.
Refreshing once or twice, I then get the correct results
Here is my console logs of the incorrect results
And here is the console log of the correct results
So it seems like sometimes, collections.communities is just returning only two, since a straight database calls shows all three are actually in there. Any Idea?
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.