Skip to content

Commit c25c519

Browse files
authored
test(countDocuments): full test coverage for countDocuments
Add tests that were node-specific or missing from spec tests. Fixes NODE-1559
1 parent 25ca557 commit c25c519

File tree

3 files changed

+168
-6
lines changed

3 files changed

+168
-6
lines changed

lib/operations/collection_ops.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,9 @@ function countDocuments(coll, query, options, callback) {
230230
delete options.limit;
231231
delete options.skip;
232232

233-
coll.aggregate(pipeline, options, (err, result) => {
233+
coll.aggregate(pipeline, options).toArray((err, docs) => {
234234
if (err) return handleCallback(callback, err);
235-
result.toArray((err, docs) => {
236-
if (err) return handleCallback(err);
237-
handleCallback(callback, null, docs.length ? docs[0].n : 0);
238-
});
235+
handleCallback(callback, null, docs.length ? docs[0].n : 0);
239236
});
240237
}
241238

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"prettier": "~1.12.0",
3535
"semver": "5.4.1",
3636
"sinon": "^4.3.0",
37+
"sinon-chai": "^3.2.0",
3738
"worker-farm": "^1.5.0"
3839
},
3940
"author": "Christian Kvalheim",

test/functional/collection_tests.js

+165-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
'use strict';
22
const test = require('./shared').assert;
33
const setupDatabase = require('./shared').setupDatabase;
4-
const expect = require('chai').expect;
4+
const chai = require('chai');
5+
const expect = chai.expect;
56
const MongoClient = require('../..').MongoClient;
7+
const sinonChai = require('sinon-chai');
8+
const mock = require('mongodb-mock-server');
9+
chai.use(sinonChai);
610

711
describe('Collection', function() {
812
before(function() {
@@ -1616,6 +1620,166 @@ describe('Collection', function() {
16161620
});
16171621
});
16181622

1623+
it('countDocuments should return Promise that resolves when no callback passed', function(done) {
1624+
const configuration = this.configuration;
1625+
const client = new MongoClient(configuration.url(), { w: 1 });
1626+
1627+
client.connect(function(err, client) {
1628+
const db = client.db(configuration.db);
1629+
const collection = db.collection('countDoc_return_promise');
1630+
const docsPromise = collection.countDocuments();
1631+
const close = e => client.close(() => done(e));
1632+
1633+
expect(docsPromise).to.exist.and.to.be.an.instanceof(collection.s.promiseLibrary);
1634+
1635+
docsPromise
1636+
.then(result => expect(result).to.equal(0))
1637+
.then(() => close())
1638+
.catch(e => close(e));
1639+
});
1640+
});
1641+
1642+
it('countDocuments should not return a promise if callback given', function(done) {
1643+
const configuration = this.configuration;
1644+
const client = new MongoClient(configuration.url(), { w: 1 });
1645+
1646+
client.connect(function(err, client) {
1647+
const db = client.db(configuration.db);
1648+
const collection = db.collection('countDoc_no_promise');
1649+
const close = e => client.close(() => done(e));
1650+
1651+
const notPromise = collection.countDocuments({ a: 1 }, function() {
1652+
expect(notPromise).to.be.undefined;
1653+
close();
1654+
});
1655+
});
1656+
});
1657+
1658+
it('countDocuments should correctly call the given callback', function(done) {
1659+
const configuration = this.configuration;
1660+
const client = new MongoClient(configuration.url(), { w: 1 });
1661+
1662+
client.connect(function(err, client) {
1663+
const db = client.db(configuration.db);
1664+
const collection = db.collection('countDoc_callback');
1665+
const docs = [{ a: 1 }, { a: 2 }];
1666+
const close = e => client.close(() => done(e));
1667+
1668+
collection.insertMany(docs).then(() =>
1669+
collection.countDocuments({ a: 1 }, (err, data) => {
1670+
expect(data).to.equal(1);
1671+
close(err);
1672+
})
1673+
);
1674+
});
1675+
});
1676+
1677+
describe('countDocuments with mock server', function() {
1678+
let server;
1679+
1680+
beforeEach(() => {
1681+
return mock.createServer().then(s => {
1682+
server = s;
1683+
});
1684+
});
1685+
1686+
afterEach(() => mock.cleanup());
1687+
1688+
function testCountDocMock(config, done) {
1689+
const client = new MongoClient(`mongodb://${server.uri()}/test`);
1690+
const close = e => client.close(() => done(e));
1691+
1692+
server.setMessageHandler(request => {
1693+
const doc = request.document;
1694+
if (doc.aggregate) {
1695+
try {
1696+
config.replyHandler(doc);
1697+
request.reply(config.reply);
1698+
} catch (e) {
1699+
close(e);
1700+
}
1701+
}
1702+
1703+
if (doc.ismaster) {
1704+
request.reply(Object.assign({}, mock.DEFAULT_ISMASTER));
1705+
} else if (doc.endSessions) {
1706+
request.reply({ ok: 1 });
1707+
}
1708+
});
1709+
1710+
client.connect(function(err, client) {
1711+
const db = client.db('test');
1712+
const collection = db.collection('countDoc_mock');
1713+
1714+
config.executeCountDocuments(collection, close);
1715+
});
1716+
}
1717+
1718+
it('countDocuments should return appropriate error if aggregation fails with callback given', function(done) {
1719+
const replyHandler = () => {};
1720+
const executeCountDocuments = (collection, close) => {
1721+
collection.countDocuments(err => {
1722+
expect(err).to.exist;
1723+
expect(err.errmsg).to.equal('aggregation error - callback');
1724+
close();
1725+
});
1726+
};
1727+
1728+
testCountDocMock(
1729+
{
1730+
replyHandler,
1731+
executeCountDocuments,
1732+
reply: { ok: 0, errmsg: 'aggregation error - callback' }
1733+
},
1734+
done
1735+
);
1736+
});
1737+
1738+
it('countDocuments should error if aggregation fails using Promises', function(done) {
1739+
const replyHandler = () => {};
1740+
const executeCountDocuments = (collection, close) => {
1741+
collection
1742+
.countDocuments()
1743+
.then(() => expect(false).to.equal(true)) // should never get here; error should be caught
1744+
.catch(e => {
1745+
expect(e.errmsg).to.equal('aggregation error - promise');
1746+
close();
1747+
});
1748+
};
1749+
1750+
testCountDocMock(
1751+
{
1752+
replyHandler,
1753+
executeCountDocuments,
1754+
reply: { ok: 0, errmsg: 'aggregation error - promise' }
1755+
},
1756+
done
1757+
);
1758+
});
1759+
1760+
it('countDocuments pipeline should be correct with skip and limit applied', function(done) {
1761+
const replyHandler = doc => {
1762+
expect(doc.pipeline).to.deep.include({ $skip: 1 });
1763+
expect(doc.pipeline).to.deep.include({ $limit: 1 });
1764+
};
1765+
const executeCountDocuments = (collection, close) => {
1766+
collection.countDocuments({}, { limit: 1, skip: 1 }, err => {
1767+
expect(err).to.not.exist;
1768+
close();
1769+
});
1770+
};
1771+
1772+
testCountDocMock(
1773+
{
1774+
replyHandler,
1775+
executeCountDocuments,
1776+
reply: { ok: 1 }
1777+
},
1778+
done
1779+
);
1780+
});
1781+
});
1782+
16191783
describe('Retryable Writes on bulk ops', function() {
16201784
const MongoClient = require('../../lib/mongo_client');
16211785

0 commit comments

Comments
 (0)