diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..a72b21c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Test", + "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "args": [ + "-u", + "tdd", + "--timeout", + "999999", + "--colors", + "${workspaceFolder}/tests/*" + ], + "internalConsoleOptions": "openOnSessionStart", + "env": { + }, + "outputCapture": "std" + }, + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 59f49fc..1196f00 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,9 @@ Promise fulfilled with object having properties: * `total` {Number} - Total number of documents in collection that match a query * `limit` {Number} - Limit that was used * `[page]` {Number} - Only if specified or default `page`/`offset` values were used -* `[pages]` {Number} - Only if `page` specified or default `page`/`offset` values were used +* `[pages]` {Number} - Only if `page` specified or default `page`/`offset` values were used +* `[prev]` {Number} - Only if there is a previous page to go to. +* `[next]` {Number} - Only if there is a next page to go to. * `[offset]` {Number} - Only if specified or default `page`/`offset` values were used ### Examples diff --git a/index.js b/index.js index 8af68dd..50137b1 100644 --- a/index.js +++ b/index.js @@ -6,6 +6,7 @@ * @param {Object} [options={}] * @param {Object|String} [options.select] * @param {Object|String} [options.sort] + * @param {Object} [options.collation] * @param {Array|Object|String} [options.populate] * @param {Boolean} [options.lean=false] * @param {Boolean} [options.leanWithId=true] @@ -22,14 +23,15 @@ function paginate(query, options, callback) { let select = options.select; let sort = options.sort; let populate = options.populate; + let collation = options.collation || {}; let lean = options.lean || false; - let leanWithId = options.leanWithId ? options.leanWithId : true; - let limit = options.limit ? options.limit : 10; - let page, offset, skip, promises; - if (options.offset) { + let leanWithId = options.hasOwnProperty('leanWithId') ? options.leanWithId : true; + let limit = options.hasOwnProperty('limit') ? options.limit : 10; + let page, offset, skip, promises = []; + if (options.hasOwnProperty('offset')) { offset = options.offset; skip = offset; - } else if (options.page) { + } else if (options.hasOwnProperty('page')) { page = options.page; skip = (page - 1) * limit; } else { @@ -37,36 +39,41 @@ function paginate(query, options, callback) { offset = 0; skip = offset; } - if (limit) { + + promises.push(this.count(query).exec()); + + if (limit > 0) { let docsQuery = this.find(query) .select(select) .sort(sort) .skip(skip) .limit(limit) - .lean(lean); + .lean(lean) + .collation(collation); if (populate) { [].concat(populate).forEach((item) => { docsQuery.populate(item); }); } - promises = { - docs: docsQuery.exec(), - count: this.count(query).exec() - }; + + let docPromise = docsQuery.exec(); + if (lean && leanWithId) { - promises.docs = promises.docs.then((docs) => { + docPromise = docPromise.then((docs) => { docs.forEach((doc) => { doc.id = String(doc._id); }); return docs; }); } + + promises.push(docPromise); } - promises = Object.keys(promises).map((x) => promises[x]); + return Promise.all(promises).then((data) => { let result = { - docs: data.docs, - total: data.count, + total: data[0], + docs: data[1] || [], limit: limit }; if (offset !== undefined) { @@ -74,14 +81,22 @@ function paginate(query, options, callback) { } if (page !== undefined) { result.page = page; - result.pages = Math.ceil(data.count / limit) || 1; + result.pages = Math.ceil(result.total / limit) || 1; + let prev = page - 1; + let next = page + 1; + + if (prev > 0) { + result.prev = prev; + } + + if (next <= result.pages) { + result.next = next; + } } if (typeof callback === 'function') { return callback(null, result); } - let promise = new Promise(); - promise.resolve(result); - return promise; + return result; }); } @@ -89,7 +104,7 @@ function paginate(query, options, callback) { * @param {Schema} schema */ -module.exports = function(schema) { +module.exports = function (schema) { schema.statics.paginate = paginate; }; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0caafb1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,339 @@ +{ + "name": "mongoose-paginate", + "version": "5.1.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "assertion-error": { + "version": "1.1.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "async": { + "version": "2.6.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "4.17.10" + } + }, + "bluebird": { + "version": "3.5.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" + }, + "bson": { + "version": "1.0.9", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/bson/-/bson-1.0.9.tgz", + "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==" + }, + "chai": { + "version": "3.4.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/chai/-/chai-3.4.1.tgz", + "integrity": "sha1-Mwri+BkSTCYYIDb6XkOojqThvYU=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + } + }, + "commander": { + "version": "2.3.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "diff": { + "version": "1.4.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "glob": { + "version": "3.2.3", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "dev": true, + "requires": { + "graceful-fs": "2.0.3", + "inherits": "2.0.3", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + }, + "growl": { + "version": "1.8.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/growl/-/growl-1.8.1.tgz", + "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "kareem": { + "version": "2.2.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/kareem/-/kareem-2.2.1.tgz", + "integrity": "sha512-xpDFy8OxkFM+vK6pXy6JmH92ibeEFUuDWzas5M9L7MzVmHW3jzwAHxodCPV/BYkf4A31bVDLyonrMfp9RXb/oA==" + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "2.3.4", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/mocha/-/mocha-2.3.4.tgz", + "integrity": "sha1-himm+wRPLSJapLgaKuLQAWmesmY=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.3", + "growl": "1.8.1", + "jade": "0.26.3", + "mkdirp": "0.5.0", + "supports-color": "1.2.0" + } + }, + "mongodb": { + "version": "3.0.10", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/mongodb/-/mongodb-3.0.10.tgz", + "integrity": "sha512-jy9s4FgcM4rl8sHNETYHGeWcuRh9AlwQCUuMiTj041t/HD02HwyFgmm2VZdd9/mA9YNHaUJLqj0tzBx2QFivtg==", + "requires": { + "mongodb-core": "3.0.9" + } + }, + "mongodb-core": { + "version": "3.0.9", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/mongodb-core/-/mongodb-core-3.0.9.tgz", + "integrity": "sha512-buOWjdLLBlEqjHDeHYSXqXx173wHMVp7bafhdHxSjxWdB9V6Ri4myTqxjYZwL/eGFZxvd8oRQSuhwuIDbaaB+g==", + "requires": { + "bson": "1.0.9", + "require_optional": "1.0.1" + } + }, + "mongoose": { + "version": "5.1.6", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/mongoose/-/mongoose-5.1.6.tgz", + "integrity": "sha512-p8p/3Z2kfXViqawN1TV+cZ8XbHz6SsllkytKTog+CDWfCNObyGraHQlUuRv/9aYPNKiZfq6WWITgLpJLZW/o/A==", + "requires": { + "async": "2.6.1", + "bson": "1.0.9", + "kareem": "2.2.1", + "lodash.get": "4.4.2", + "mongodb": "3.0.10", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.4.1", + "mquery": "3.0.0", + "ms": "2.0.0", + "regexp-clone": "0.0.1", + "sliced": "1.0.1" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + }, + "mpath": { + "version": "0.4.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/mpath/-/mpath-0.4.1.tgz", + "integrity": "sha512-NNY/MpBkALb9jJmjpBlIi6GRoLveLUM0pJzgbp9vY9F7IQEb/HREC/nxrixechcQwd1NevOhJnWWV8QQQRE+OA==" + }, + "mquery": { + "version": "3.0.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/mquery/-/mquery-3.0.0.tgz", + "integrity": "sha512-WL1Lk8v4l8VFSSwN3yCzY9TXw+fKVYKn6f+w86TRzOLSE8k1yTgGaLBPUByJQi8VcLbOdnUneFV/y3Kv874pnQ==", + "requires": { + "bluebird": "3.5.0", + "debug": "2.6.9", + "regexp-clone": "0.0.1", + "sliced": "0.0.5" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "sliced": { + "version": "0.0.5", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/sliced/-/sliced-0.0.5.tgz", + "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" + } + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "regexp-clone": { + "version": "0.0.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/regexp-clone/-/regexp-clone-0.0.1.tgz", + "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "2.0.0", + "semver": "5.5.0" + } + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + }, + "supports-color": { + "version": "1.2.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", + "dev": true + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://hq-nexus.rhoneapp.com/repository/npm/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 1a4b394..f5a3b09 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose-paginate", "description": "Pagination plugin for Mongoose", - "version": "5.0.2", + "version": "5.1.1", "author": { "name": "Edward Hotchkiss", "email": "edward@edwardhotchkiss.com" @@ -35,11 +35,12 @@ "engines": { "node": ">=4.2.4" }, - "dependencies": {}, + "dependencies": { + "mongoose": "^5.1.6" + }, "devDependencies": { - "mongoose": "4.3.4", - "mocha": "2.3.4", - "chai": "3.4.1" + "chai": "3.4.1", + "mocha": "2.3.4" }, "scripts": { "test": "./node_modules/.bin/mocha tests/*.js -R spec --ui bdd --timeout 5000" diff --git a/tests/index.js b/tests/index.js index 7a1a8d2..c052768 100644 --- a/tests/index.js +++ b/tests/index.js @@ -4,9 +4,16 @@ let mongoose = require('mongoose'); let expect = require('chai').expect; let mongoosePaginate = require('../index'); -let MONGO_URI = 'mongodb://127.0.0.1/mongoose_paginate_test'; +let MONGO_URI = 'mongodb://localhost:27017/mongoose_paginate_test'; + +const AUTHOR_1 = { name: 'bbb' }; +const AUTHOR_2 = { name: 'CCCC' }; +const AUTHOR_3 = { name: 'dddd' }; +const AUTHOR_4 = { name: 'Arthur Conan Doyle' }; let AuthorSchema = new mongoose.Schema({ name: String }); + +AuthorSchema.plugin(mongoosePaginate); let Author = mongoose.model('Author', AuthorSchema); let BookSchema = new mongoose.Schema({ @@ -19,23 +26,23 @@ let BookSchema = new mongoose.Schema({ }); BookSchema.plugin(mongoosePaginate); - let Book = mongoose.model('Book', BookSchema); -describe('mongoose-paginate', function() { +describe('mongoose-paginate', function () { - before(function(done) { + before(function (done) { mongoose.connect(MONGO_URI, done); }); - before(function(done) { + before(function (done) { mongoose.connection.db.dropDatabase(done); }); - before(function() { + before(function () { let book, books = []; let date = new Date(); - return Author.create({ name: 'Arthur Conan Doyle' }).then(function(author) { + Author.create([AUTHOR_1, AUTHOR_2, AUTHOR_3]); + return Author.create(AUTHOR_4).then(function (author) { for (let i = 1; i <= 100; i++) { book = new Book({ title: 'Book #' + i, @@ -48,34 +55,32 @@ describe('mongoose-paginate', function() { }); }); - afterEach(function() { + afterEach(function () { delete mongoosePaginate.paginate.options; }); - it('returns promise', function() { + it('returns promise', function () { let promise = Book.paginate(); expect(promise.then).to.be.an.instanceof(Function); }); - it('calls callback', function(done) { - Book.paginate({}, {}, function(err, result) { + it('calls callback', function (done) { + Book.paginate({}, {}, function (err, result) { expect(err).to.be.null; expect(result).to.be.an.instanceOf(Object); done(); }); }); - describe('paginates', function() { - it('with criteria', function() { + describe('paginates', function () { + it('with criteria', function () { return Book.paginate({ title: 'Book #10' }).then((result) => { - console.log('with criteria logging =================='); - console.log('result:', result); expect(result.docs).to.have.length(1); expect(result.docs[0].title).to.equal('Book #10'); }); }); - it('with default options (page=1, limit=10, lean=false)', function() { - return Book.paginate().then(function(result) { + it('with default options (page=1, limit=10, lean=false)', function () { + return Book.paginate().then(function (result) { expect(result.docs).to.have.length(10); expect(result.docs[0]).to.be.an.instanceof(mongoose.Document); expect(result.total).to.equal(100); @@ -85,19 +90,19 @@ describe('mongoose-paginate', function() { expect(result.offset).to.equal(0); }); }); - it('with custom default options', function() { + it('with custom default options', function () { mongoosePaginate.paginate.options = { limit: 20, lean: true }; - return Book.paginate().then(function(result) { + return Book.paginate().then(function (result) { expect(result.docs).to.have.length(20); expect(result.limit).to.equal(20); expect(result.docs[0]).to.not.be.an.instanceof(mongoose.Document); }); }); - it('with offset and limit', function() { - return Book.paginate({}, { offset: 30, limit: 20 }).then(function(result) { + it('with offset and limit', function () { + return Book.paginate({}, { offset: 30, limit: 20 }).then(function (result) { expect(result.docs).to.have.length(20); expect(result.total).to.equal(100); expect(result.limit).to.equal(20); @@ -106,18 +111,44 @@ describe('mongoose-paginate', function() { expect(result).to.not.have.property('pages'); }); }); - it('with page and limit', function() { - return Book.paginate({}, { page: 1, limit: 20 }).then(function(result) { + it('with page and limit', function () { + return Book.paginate({}, { page: 1, limit: 20 }).then(function (result) { expect(result.docs).to.have.length(20); expect(result.total).to.equal(100); expect(result.limit).to.equal(20); expect(result.page).to.equal(1); expect(result.pages).to.equal(5); + expect(result.next).to.equal(2); + expect(result.prev).to.be.undefined; expect(result).to.not.have.property('offset'); }); }); - it('with zero limit', function() { - return Book.paginate({}, { page: 1, limit: 0 }).then(function(result) { + it('on the first page', function () { + return Book.paginate({}, { page: 1, limit: 20 }).then(function (result) { + expect(result.next).to.equal(2); + expect(result).to.not.have.property('prev'); + }); + }); + it('on the last page', function () { + return Book.paginate({}, { page: 5, limit: 20 }).then(function (result) { + expect(result.prev).to.equal(4); + expect(result).to.not.have.property('next'); + }); + }); + it('on the middle page', function () { + return Book.paginate({}, { page: 3, limit: 20 }).then(function (result) { + expect(result.prev).to.equal(2); + expect(result.next).to.equal(4); + }); + }); + it('with page 1 and limit', function () { + return Book.paginate({}, { page: 1, limit: 20 }).then(function (result) { + expect(result.next).to.equal(2); + expect(result).to.not.have.property('prev'); + }); + }); + it('with zero limit', function () { + return Book.paginate({}, { page: 1, limit: 0 }).then(function (result) { expect(result.docs).to.have.length(0); expect(result.total).to.equal(100); expect(result.limit).to.equal(0); @@ -125,31 +156,39 @@ describe('mongoose-paginate', function() { expect(result.pages).to.equal(Infinity); }); }); - it('with select', function() { - return Book.paginate({}, { select: 'title' }).then(function(result) { + it('with select', function () { + return Book.paginate({}, { select: 'title' }).then(function (result) { expect(result.docs[0].title).to.exist; expect(result.docs[0].date).to.not.exist; }); }); - it('with sort', function() { - return Book.paginate({}, { sort: { date: -1 } }).then(function(result) { + it('with sort', function () { + return Book.paginate({}, { sort: { date: -1 } }).then(function (result) { expect(result.docs[0].title).to.equal('Book #100'); }); }); - it('with populate', function() { - return Book.paginate({}, { populate: 'author' }).then(function(result) { + it('with populate', function () { + return Book.paginate({}, { populate: 'author' }).then(function (result) { expect(result.docs[0].author.name).to.equal('Arthur Conan Doyle'); }); }); - describe('with lean', function() { - it('with default leanWithId=true', function() { - return Book.paginate({}, { lean: true }).then(function(result) { + it('with sorting & collation', function () { + return Author.paginate({}, { sort: { name: 1 }, collation: { locale: 'en', strength: 1 } }).then(function (result) { + expect(result.docs[0].name).to.equal(AUTHOR_4.name); + expect(result.docs[1].name).to.equal(AUTHOR_1.name); + expect(result.docs[2].name).to.equal(AUTHOR_2.name); + expect(result.docs[3].name).to.equal(AUTHOR_3.name); + }); + }); + describe('with lean', function () { + it('with default leanWithId=true', function () { + return Book.paginate({}, { lean: true }).then(function (result) { expect(result.docs[0]).to.not.be.an.instanceof(mongoose.Document); expect(result.docs[0].id).to.equal(String(result.docs[0]._id)); }); }); - it('with leanWithId=false', function() { - return Book.paginate({}, { lean: true, leanWithId: false }).then(function(result) { + it('with leanWithId=false', function () { + return Book.paginate({}, { lean: true, leanWithId: false }).then(function (result) { expect(result.docs[0]).to.not.be.an.instanceof(mongoose.Document); expect(result.docs[0]).to.not.have.property('id'); }); @@ -157,11 +196,11 @@ describe('mongoose-paginate', function() { }); }); - after(function(done) { + after(function (done) { mongoose.connection.db.dropDatabase(done); }); - after(function(done) { + after(function (done) { mongoose.disconnect(done); });