1185 lines
34 KiB
JavaScript
1185 lines
34 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
var PouchDB = require('./pouchdb');
|
||
|
var should = require('chai').should();
|
||
|
var testUtils = require('./test.utils.js');
|
||
|
var adapters = ['local'];
|
||
|
|
||
|
adapters.forEach(function (adapter) {
|
||
|
|
||
|
describe('test.basics.js-' + adapter, function () {
|
||
|
|
||
|
var dbs = {};
|
||
|
|
||
|
beforeEach(function (done) {
|
||
|
dbs.name = testUtils.adapterUrl(adapter, 'testdb');
|
||
|
testUtils.cleanup([dbs.name], done);
|
||
|
});
|
||
|
|
||
|
after(function (done) {
|
||
|
testUtils.cleanup([dbs.name], done);
|
||
|
});
|
||
|
|
||
|
|
||
|
it('Create a pouch', function (done) {
|
||
|
new PouchDB(dbs.name, function (err, db) {
|
||
|
should.not.exist(err);
|
||
|
db.should.be.an.instanceof(PouchDB);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Create a pouch without new keyword', function () {
|
||
|
/* jshint newcap:false */
|
||
|
var db = PouchDB(dbs.name);
|
||
|
db.should.be.an.instanceof(PouchDB);
|
||
|
});
|
||
|
|
||
|
it('Create a pouch with a promise', function () {
|
||
|
return new PouchDB(dbs.name);
|
||
|
});
|
||
|
|
||
|
it('4314 Create a pouch with + in name', function () {
|
||
|
var db = new PouchDB(dbs.name + '+suffix');
|
||
|
return db.info().then(function () {
|
||
|
return db.destroy();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('4314 Create a pouch with urlencoded name', function () {
|
||
|
var db = new PouchDB(dbs.name + 'some%2Ftest');
|
||
|
return db.info().then(function () {
|
||
|
return db.destroy();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Catch an error when creating a pouch with a promise', function (done) {
|
||
|
new PouchDB().catch(function (err) {
|
||
|
should.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('destroy a pouch', function (done) {
|
||
|
new PouchDB(dbs.name, function (err, db) {
|
||
|
should.exist(db);
|
||
|
db.destroy(function (err, info) {
|
||
|
should.not.exist(err);
|
||
|
should.exist(info);
|
||
|
info.ok.should.equal(true);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('4219 destroy a pouch', function () {
|
||
|
return new PouchDB(dbs.name).destroy({});
|
||
|
});
|
||
|
|
||
|
it('4339 throw useful error if method called on stale instance', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
|
||
|
return db.put({
|
||
|
_id: 'cleanTest'
|
||
|
}).then(function () {
|
||
|
return db.destroy();
|
||
|
}).then(function () {
|
||
|
return db.get('cleanTest');
|
||
|
}).then(function () {
|
||
|
throw new Error('.get should return an error');
|
||
|
}, function (err) {
|
||
|
should.equal(err instanceof Error, true, 'should be an error');
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('destroy a pouch, with a promise', function (done) {
|
||
|
new PouchDB(dbs.name, function (err, db) {
|
||
|
should.exist(db);
|
||
|
db.destroy().then(function (info) {
|
||
|
should.exist(info);
|
||
|
info.ok.should.equal(true);
|
||
|
done();
|
||
|
}, done);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it.skip('[4595] should reject xhr errors', function(done){
|
||
|
var invalidUrl = 'http:///';
|
||
|
new PouchDB(dbs.name).replicate.to(invalidUrl, {}).catch(function() {
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
});
|
||
|
it.skip('[4595] should emit error event on xhr error', function(done){
|
||
|
var invalidUrl = 'http:///';
|
||
|
new PouchDB(dbs.name).replicate.to(invalidUrl,{})
|
||
|
.on('error', function () { done(); });
|
||
|
});
|
||
|
|
||
|
it('Add a doc', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({test: 'somestuff'}, function (err) {
|
||
|
should.not.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Get invalid id', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
return db.get(1234).then(function() {
|
||
|
throw 'show not be here';
|
||
|
}).catch(function(err) {
|
||
|
should.exist(err);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Add a doc with a promise', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({test: 'somestuff'}).then(function () {
|
||
|
done();
|
||
|
}, done);
|
||
|
});
|
||
|
|
||
|
it('Add a doc with opts object', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({test: 'somestuff'}, {}, function (err) {
|
||
|
should.not.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Modify a doc', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({test: 'somestuff'}, function (err, info) {
|
||
|
db.put({
|
||
|
_id: info.id,
|
||
|
_rev: info.rev,
|
||
|
another: 'test'
|
||
|
}, function (err, info2) {
|
||
|
should.not.exist(err);
|
||
|
info.rev.should.not.equal(info2.rev);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Modify a doc with sugar syntax', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({test: 'somestuff'}, function (err, info) {
|
||
|
db.put({another: 'test'}, info.id, info.rev, function (err, info2) {
|
||
|
info.rev.should.not.equal(info2.rev);
|
||
|
db.put({yet_another: 'test'}, 'yet_another', function (err, info3) {
|
||
|
info3.id.should.equal('yet_another');
|
||
|
info.rev.should.not.equal(info2.rev);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Modify a doc with sugar syntax and omit the _id', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({test: 'somestuff'}, function (err, info) {
|
||
|
db.put({another: 'test', _id: info.id}, info.rev,
|
||
|
function (err, info2) {
|
||
|
info.rev.should.not.equal(info2.rev);
|
||
|
db.put({yet_another: 'test'}, 'yet_another', function (err, info3) {
|
||
|
info3.id.should.equal('yet_another');
|
||
|
info.rev.should.not.equal(info2.rev);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Modify a doc with a promise', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({test: 'promisestuff'}).then(function (info) {
|
||
|
return db.put({
|
||
|
_id: info.id,
|
||
|
_rev: info.rev,
|
||
|
another: 'test'
|
||
|
}).then(function (info2) {
|
||
|
info.rev.should.not.equal(info2.rev);
|
||
|
});
|
||
|
}).catch(done).then(function () {
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Read db id', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.id(function (err, id) {
|
||
|
id.should.be.a('string');
|
||
|
done(err);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Read db id with promise', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.id().then(function (id) {
|
||
|
id.should.be.a('string');
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Close db', function (done) {
|
||
|
new PouchDB(dbs.name, function (err, db) {
|
||
|
db.close(done);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Close db with a promise', function (done) {
|
||
|
new PouchDB(dbs.name, function (err, db) {
|
||
|
db.close().then(done, done);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Read db id after closing Close', function (done) {
|
||
|
new PouchDB(dbs.name, function (err, db) {
|
||
|
db.close(function () {
|
||
|
db = new PouchDB(dbs.name);
|
||
|
db.id(function (err, id) {
|
||
|
id.should.be.a('string');
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Modify a doc with incorrect rev', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({ test: 'somestuff' }, function (err, info) {
|
||
|
var nDoc = {
|
||
|
_id: info.id,
|
||
|
_rev: info.rev + 'broken',
|
||
|
another: 'test'
|
||
|
};
|
||
|
db.put(nDoc, function (err) {
|
||
|
should.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Remove doc', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({ test: 'somestuff' }, function (err, info) {
|
||
|
db.remove({
|
||
|
test: 'somestuff',
|
||
|
_id: info.id,
|
||
|
_rev: info.rev
|
||
|
}, function () {
|
||
|
db.get(info.id, function (err) {
|
||
|
should.exist(err.error);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Remove doc with a promise', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({test: 'someotherstuff'}).then(function (info) {
|
||
|
return db.remove({
|
||
|
test: 'someotherstuff',
|
||
|
_id: info.id,
|
||
|
_rev: info.rev
|
||
|
}).then(function () {
|
||
|
return db.get(info.id).then(function () {
|
||
|
done(true);
|
||
|
}, function (err) {
|
||
|
should.exist(err.error);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Remove doc with new syntax', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({ test: 'somestuff' }, function (err, info) {
|
||
|
db.remove(info.id, info.rev, function (err) {
|
||
|
should.not.exist(err);
|
||
|
db.get(info.id, function (err) {
|
||
|
should.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Remove doc with new syntax and a promise', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var id;
|
||
|
db.post({test: 'someotherstuff'}).then(function (info) {
|
||
|
id = info.id;
|
||
|
return db.remove(info.id, info.rev);
|
||
|
}).then(function () {
|
||
|
return db.get(id);
|
||
|
}).then(function () {
|
||
|
done(true);
|
||
|
}, function (err) {
|
||
|
should.exist(err.error);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Doc removal leaves only stub', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.put({_id: 'foo', value: 'test'}, function () {
|
||
|
db.get('foo', function (err, doc) {
|
||
|
db.remove(doc, function (err, res) {
|
||
|
db.get('foo', { rev: res.rev }, function (err, doc) {
|
||
|
doc.should.deep.equal({
|
||
|
_id: res.id,
|
||
|
_rev: res.rev,
|
||
|
_deleted: true
|
||
|
});
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Remove doc twice with specified id', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
return db.put({_id: 'specifiedId', test: 'somestuff'}).then(function () {
|
||
|
return db.get('specifiedId');
|
||
|
}).then(function (doc) {
|
||
|
return db.remove(doc);
|
||
|
}).then(function () {
|
||
|
return db.put({
|
||
|
_id: 'specifiedId',
|
||
|
test: 'somestuff2'
|
||
|
});
|
||
|
}).then(function () {
|
||
|
return db.get('specifiedId');
|
||
|
}).then(function (doc) {
|
||
|
return db.remove(doc);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Remove doc, no callback', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var changes = db.changes({
|
||
|
live: true,
|
||
|
include_docs: true
|
||
|
}).on('change', function (change) {
|
||
|
if (change.doc._deleted) {
|
||
|
changes.cancel();
|
||
|
}
|
||
|
}).on('complete', function (result) {
|
||
|
result.status.should.equal('cancelled');
|
||
|
done();
|
||
|
}).on('error', done);
|
||
|
db.post({ _id: 'somestuff' }, function (err, res) {
|
||
|
db.remove({
|
||
|
_id: res.id,
|
||
|
_rev: res.rev
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Delete document without id', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.remove({test: 'ing'}, function (err) {
|
||
|
should.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Delete document with many args', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc = {_id: 'foo'};
|
||
|
return db.put(doc).then(function (info) {
|
||
|
return db.remove(doc._id, info.rev, {});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Delete document with many args, callback style', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc = {_id: 'foo'};
|
||
|
db.put(doc, function (err, info) {
|
||
|
should.not.exist(err);
|
||
|
db.remove(doc._id, info.rev, {}, function (err) {
|
||
|
should.not.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Delete doc with id + rev + no opts', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc = {_id: 'foo'};
|
||
|
return db.put(doc).then(function (info) {
|
||
|
return db.remove(doc._id, info.rev);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Delete doc with id + rev + no opts, callback style', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc = {_id: 'foo'};
|
||
|
db.put(doc, function (err, info) {
|
||
|
should.not.exist(err);
|
||
|
db.remove(doc._id, info.rev, function (err) {
|
||
|
should.not.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Delete doc with doc + opts', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc = {_id: 'foo'};
|
||
|
return db.put(doc).then(function (info) {
|
||
|
doc._rev = info.rev;
|
||
|
return db.remove(doc, {});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Delete doc with doc + opts, callback style', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc = {_id: 'foo'};
|
||
|
db.put(doc, function (err, info) {
|
||
|
should.not.exist(err);
|
||
|
doc._rev = info.rev;
|
||
|
db.remove(doc, {}, function (err) {
|
||
|
should.not.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Delete doc with rev in opts', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc = {_id: 'foo'};
|
||
|
return db.put(doc).then(function (info) {
|
||
|
return db.remove(doc, {rev: info.rev});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Bulk docs', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.bulkDocs({
|
||
|
docs: [
|
||
|
{ test: 'somestuff' },
|
||
|
{ test: 'another' }
|
||
|
]
|
||
|
}, function (err, infos) {
|
||
|
infos.length.should.equal(2);
|
||
|
infos[0].ok.should.equal(true);
|
||
|
infos[1].ok.should.equal(true);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Bulk docs with a promise', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.bulkDocs({
|
||
|
docs: [
|
||
|
{ test: 'somestuff' },
|
||
|
{ test: 'another' }
|
||
|
]
|
||
|
}).then(function (infos) {
|
||
|
infos.length.should.equal(2);
|
||
|
infos[0].ok.should.equal(true);
|
||
|
infos[1].ok.should.equal(true);
|
||
|
done();
|
||
|
}).catch(done);
|
||
|
});
|
||
|
|
||
|
it('Basic checks', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.info(function (err, info) {
|
||
|
var updateSeq = info.update_seq;
|
||
|
var doc = {_id: '0', a: 1, b: 1};
|
||
|
info.doc_count.should.equal(0);
|
||
|
db.put(doc, function (err, res) {
|
||
|
res.ok.should.equal(true);
|
||
|
res.should.have.property('id');
|
||
|
res.should.have.property('rev');
|
||
|
db.info(function (err, info) {
|
||
|
info.doc_count.should.equal(1);
|
||
|
info.update_seq.should.not.equal(updateSeq);
|
||
|
db.get(doc._id, function (err, doc) {
|
||
|
doc._id.should.equal(res.id);
|
||
|
doc._rev.should.equal(res.rev);
|
||
|
db.get(doc._id, { revs_info: true }, function (err, doc) {
|
||
|
doc._revs_info[0].status.should.equal('available');
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('update with invalid rev', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({test: 'somestuff'}, function (err, info) {
|
||
|
should.not.exist(err);
|
||
|
db.put({
|
||
|
_id: info.id,
|
||
|
_rev: 'undefined',
|
||
|
another: 'test'
|
||
|
}, function (err) {
|
||
|
should.exist(err);
|
||
|
err.status.should.equal(PouchDB.Errors.INVALID_REV.status);
|
||
|
err.message.should.equal(PouchDB.Errors.INVALID_REV.message,
|
||
|
'correct error message returned');
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Doc validation', function (done) {
|
||
|
var bad_docs = [
|
||
|
{'_zing': 4},
|
||
|
{'_zoom': 'hello'},
|
||
|
{'zane': 'goldfish',
|
||
|
'_fan': 'something smells delicious'},
|
||
|
{'_bing': {'wha?': 'soda can'}}
|
||
|
];
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.bulkDocs({ docs: bad_docs }, function (err) {
|
||
|
err.status.should.equal(PouchDB.Errors.DOC_VALIDATION.status);
|
||
|
err.message.should.equal(PouchDB.Errors.DOC_VALIDATION.message +
|
||
|
': _zing',
|
||
|
'correct error message returned');
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Replication fields (#2442)', function (done) {
|
||
|
var doc = {
|
||
|
'_replication_id': 'test',
|
||
|
'_replication_state': 'triggered',
|
||
|
'_replication_state_time': 1,
|
||
|
'_replication_stats': {}
|
||
|
};
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post(doc, function (err, resp) {
|
||
|
should.not.exist(err);
|
||
|
|
||
|
db.get(resp.id, function (err, doc2) {
|
||
|
should.not.exist(err);
|
||
|
|
||
|
doc2._replication_id.should.equal('test');
|
||
|
doc2._replication_state.should.equal('triggered');
|
||
|
doc2._replication_state_time.should.equal(1);
|
||
|
doc2._replication_stats.should.eql({});
|
||
|
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Testing issue #48', function (done) {
|
||
|
var docs = [
|
||
|
{'_id': '0'}, {'_id': '1'}, {'_id': '2'},
|
||
|
{'_id': '3'}, {'_id': '4'}, {'_id': '5'}
|
||
|
];
|
||
|
var TO_SEND = 5;
|
||
|
var sent = 0;
|
||
|
var complete = 0;
|
||
|
var timer;
|
||
|
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
|
||
|
var bulkCallback = function (err) {
|
||
|
should.not.exist(err);
|
||
|
if (++complete === TO_SEND) {
|
||
|
done();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var save = function () {
|
||
|
if (++sent === TO_SEND) {
|
||
|
clearInterval(timer);
|
||
|
}
|
||
|
db.bulkDocs({docs: docs}, bulkCallback);
|
||
|
};
|
||
|
|
||
|
timer = setInterval(save, 10);
|
||
|
});
|
||
|
|
||
|
it('Testing valid id', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({
|
||
|
'_id': 123,
|
||
|
test: 'somestuff'
|
||
|
}, function (err) {
|
||
|
should.exist(err);
|
||
|
err.error.should.equal(PouchDB.Errors.INVALID_ID.error);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Put doc without _id should fail', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.put({test: 'somestuff' }, function (err) {
|
||
|
should.exist(err);
|
||
|
err.message.should.equal(PouchDB.Errors.MISSING_ID.message,
|
||
|
'correct error message returned');
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Put doc with bad reserved id should fail', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.put({
|
||
|
_id: '_i_test',
|
||
|
test: 'somestuff'
|
||
|
}, function (err) {
|
||
|
should.exist(err);
|
||
|
err.status.should.equal(PouchDB.Errors.RESERVED_ID.status);
|
||
|
err.message.should.equal(PouchDB.Errors.RESERVED_ID.message,
|
||
|
'correct error message returned');
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('update_seq persists', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.post({ test: 'somestuff' }, function () {
|
||
|
new PouchDB(dbs.name, function (err, db) {
|
||
|
db.info(function (err, info) {
|
||
|
info.update_seq.should.not.equal(0);
|
||
|
info.doc_count.should.equal(1);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('deletions persists', function (done) {
|
||
|
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc = {_id: 'staticId', contents: 'stuff'};
|
||
|
|
||
|
function writeAndDelete(cb) {
|
||
|
db.put(doc, function (err, info) {
|
||
|
db.remove({
|
||
|
_id: info.id,
|
||
|
_rev: info.rev
|
||
|
}, function () {
|
||
|
cb();
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
writeAndDelete(function () {
|
||
|
writeAndDelete(function () {
|
||
|
db.put(doc, function () {
|
||
|
db.get(doc._id, { conflicts: true }, function (err, details) {
|
||
|
details.should.not.have.property('_conflicts');
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('#4126 should not store raw Dates', function () {
|
||
|
var date = new Date();
|
||
|
var date2 = new Date();
|
||
|
var date3 = new Date();
|
||
|
var origDocs = [
|
||
|
{ _id: '1', mydate: date },
|
||
|
{ _id: '2', array: [date2] },
|
||
|
{ _id: '3', deep: { deeper: { deeperstill: date3 } }
|
||
|
}
|
||
|
];
|
||
|
return new PouchDB(dbs.name).then(function (db) {
|
||
|
return db.bulkDocs(origDocs).then(function () {
|
||
|
return db.allDocs({include_docs: true});
|
||
|
}).then(function (res) {
|
||
|
var docs = res.rows.map(function (row) {
|
||
|
delete row.doc._rev;
|
||
|
return row.doc;
|
||
|
});
|
||
|
docs.should.deep.equal([
|
||
|
{ _id: '1', mydate: date.toJSON() },
|
||
|
{ _id: '2', array: [date2.toJSON()] },
|
||
|
{ _id: '3', deep: { deeper: { deeperstill: date3.toJSON() } }
|
||
|
}
|
||
|
]);
|
||
|
origDocs[0].mydate.should.be.instanceof(Date, 'date not modified');
|
||
|
origDocs[1].array[0].should.be.instanceof(Date, 'date not modified');
|
||
|
origDocs[2].deep.deeper.deeperstill.should.be.instanceof(Date,
|
||
|
'date not modified');
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Create a db with a reserved name', function () {
|
||
|
var db = new PouchDB('__proto__');
|
||
|
return db.info().then(function () {
|
||
|
return db.destroy();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Error when document is not an object', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc1 = [{ _id: 'foo' }, { _id: 'bar' }];
|
||
|
var doc2 = 'this is not an object';
|
||
|
var count = 5;
|
||
|
var callback = function (err) {
|
||
|
should.exist(err);
|
||
|
count--;
|
||
|
if (count === 0) {
|
||
|
done();
|
||
|
}
|
||
|
};
|
||
|
db.post(doc1, callback);
|
||
|
db.post(doc2, callback);
|
||
|
db.put(doc1, callback);
|
||
|
db.put(doc2, callback);
|
||
|
db.bulkDocs({docs: [doc1, doc2]}, callback);
|
||
|
});
|
||
|
|
||
|
it('Test instance update_seq updates correctly', function (done) {
|
||
|
new PouchDB(dbs.name, function (err, db1) {
|
||
|
var db2 = new PouchDB(dbs.name);
|
||
|
db1.post({ a: 'doc' }, function () {
|
||
|
db1.info(function (err, db1Info) {
|
||
|
db2.info(function (err, db2Info) {
|
||
|
db1Info.update_seq.should.not.equal(0);
|
||
|
db2Info.update_seq.should.not.equal(0);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Error works', function () {
|
||
|
var newError = PouchDB.utils
|
||
|
.createError(PouchDB.Errors.BAD_REQUEST, 'love needs no message');
|
||
|
newError.status.should.equal(PouchDB.Errors.BAD_REQUEST.status);
|
||
|
newError.name.should.equal(PouchDB.Errors.BAD_REQUEST.name);
|
||
|
newError.message.should.equal(PouchDB.Errors.BAD_REQUEST.message,
|
||
|
'correct error message returned');
|
||
|
newError.reason.should.equal('love needs no message');
|
||
|
});
|
||
|
|
||
|
it('Fail to fetch a doc after db was deleted', function (done) {
|
||
|
new PouchDB(dbs.name, function (err, db) {
|
||
|
var db2 = new PouchDB(dbs.name);
|
||
|
var doc = { _id: 'foodoc' };
|
||
|
var doc2 = { _id: 'foodoc2' };
|
||
|
db.put(doc, function () {
|
||
|
db2.put(doc2, function () {
|
||
|
db.allDocs(function (err, docs) {
|
||
|
docs.total_rows.should.equal(2);
|
||
|
db.destroy(function (err) {
|
||
|
should.not.exist(err);
|
||
|
db2 = new PouchDB(dbs.name);
|
||
|
db2.get(doc._id, function (err) {
|
||
|
err.status.should.equal(404);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Fail to fetch a doc after db was deleted', function (done) {
|
||
|
new PouchDB(dbs.name, function (err, db) {
|
||
|
var db2 = new PouchDB(dbs.name);
|
||
|
var doc = { _id: 'foodoc' };
|
||
|
var doc2 = { _id: 'foodoc2' };
|
||
|
db.put(doc, function () {
|
||
|
db2.put(doc2, function () {
|
||
|
db.allDocs(function (err, docs) {
|
||
|
docs.total_rows.should.equal(2);
|
||
|
db.destroy().then(function () {
|
||
|
db2 = new PouchDB(dbs.name);
|
||
|
db2.get(doc._id, function (err, doc) {
|
||
|
should.not.exist(doc);
|
||
|
err.status.should.equal(404);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Cant add docs with empty ids', function (done) {
|
||
|
var docs = [
|
||
|
{},
|
||
|
{ _id: null },
|
||
|
{ _id: undefined },
|
||
|
{ _id: '' },
|
||
|
{ _id: {} },
|
||
|
{ _id: '_underscored_id' }
|
||
|
];
|
||
|
var num = docs.length;
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
docs.forEach(function (doc) {
|
||
|
db.put(doc, function (err) {
|
||
|
should.exist(err);
|
||
|
if (!--num) {
|
||
|
done();
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('Test doc with percent in ID', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var doc = {
|
||
|
foo: 'bar',
|
||
|
_id: 'foo%bar'
|
||
|
};
|
||
|
return db.put(doc).then(function (res) {
|
||
|
res.id.should.equal('foo%bar');
|
||
|
doc.foo.should.equal('bar');
|
||
|
return db.get('foo%bar');
|
||
|
}).then(function (doc) {
|
||
|
doc._id.should.equal('foo%bar');
|
||
|
return db.allDocs({include_docs: true});
|
||
|
}).then(function (res) {
|
||
|
var x = res.rows[0];
|
||
|
x.id.should.equal('foo%bar');
|
||
|
x.doc._id.should.equal('foo%bar');
|
||
|
x.key.should.equal('foo%bar');
|
||
|
should.exist(x.doc._rev);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('db.info should give correct name', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.info().then(function (info) {
|
||
|
info.db_name.should.equal('testdb');
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('db.info should give auto_compaction = false (#2744)', function () {
|
||
|
var db = new PouchDB(dbs.name, { auto_compaction: false});
|
||
|
return db.info().then(function (info) {
|
||
|
info.auto_compaction.should.equal(false);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('db.info should give auto_compaction = true (#2744)', function () {
|
||
|
var db = new PouchDB(dbs.name, { auto_compaction: true});
|
||
|
return db.info().then(function (info) {
|
||
|
// http doesn't support auto compaction
|
||
|
info.auto_compaction.should.equal(db.type() !== 'http');
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('db.info should give adapter name (#3567)', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
return db.info().then(function (info) {
|
||
|
info.adapter.should.equal(db.type());
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('db.info should give correct doc_count', function (done) {
|
||
|
new PouchDB(dbs.name).then(function (db) {
|
||
|
db.info().then(function (info) {
|
||
|
info.doc_count.should.equal(0);
|
||
|
return db.bulkDocs({docs : [{_id : '1'}, {_id : '2'}, {_id : '3'}]});
|
||
|
}).then(function () {
|
||
|
return db.info();
|
||
|
}).then(function (info) {
|
||
|
info.doc_count.should.equal(3);
|
||
|
return db.get('1');
|
||
|
}).then(function (doc) {
|
||
|
return db.remove(doc);
|
||
|
}).then(function () {
|
||
|
return db.info();
|
||
|
}).then(function (info) {
|
||
|
info.doc_count.should.equal(2);
|
||
|
done();
|
||
|
}, done);
|
||
|
}, done);
|
||
|
});
|
||
|
|
||
|
it('putting returns {ok: true}', function () {
|
||
|
// in couch, it's {ok: true} and in cloudant it's {},
|
||
|
// but the http adapter smooths this out
|
||
|
return new PouchDB(dbs.name).then(function (db) {
|
||
|
return db.put({_id: '_local/foo'}).then(function (info) {
|
||
|
true.should.equal(info.ok, 'putting local returns ok=true');
|
||
|
return db.put({_id: 'quux'});
|
||
|
}).then(function (info) {
|
||
|
true.should.equal(info.ok, 'putting returns ok=true');
|
||
|
return db.bulkDocs([ {_id: '_local/bar'}, {_id: 'baz'} ]);
|
||
|
}).then(function (info) {
|
||
|
info.should.have.length(2, 'correct num bulk docs');
|
||
|
true.should.equal(info[0].ok, 'bulk docs says ok=true #1');
|
||
|
true.should.equal(info[1].ok, 'bulk docs says ok=true #2');
|
||
|
return db.post({});
|
||
|
}).then(function (info) {
|
||
|
true.should.equal(info.ok, 'posting returns ok=true');
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
it('putting is override-able', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var called = 0;
|
||
|
var plugin = {
|
||
|
initPull: function () {
|
||
|
this.oldPut = this.put;
|
||
|
this.put = function () {
|
||
|
if (typeof arguments[arguments.length - 1] === 'function') {
|
||
|
called++;
|
||
|
}
|
||
|
return this.oldPut.apply(this, arguments);
|
||
|
};
|
||
|
},
|
||
|
cleanupPut: function () {
|
||
|
this.put = this.oldPut;
|
||
|
}
|
||
|
};
|
||
|
PouchDB.plugin(plugin);
|
||
|
db.initPull();
|
||
|
return db.put({foo: 'bar'}, 'anid').then(function () {
|
||
|
called.should.be.above(0, 'put was called');
|
||
|
return db.get('anid');
|
||
|
}).then(function (doc) {
|
||
|
doc.foo.should.equal('bar', 'correct doc');
|
||
|
}).then(function () {
|
||
|
done();
|
||
|
}, done);
|
||
|
});
|
||
|
|
||
|
it('issue 2779, deleted docs, old revs COUCHDB-292', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var rev;
|
||
|
|
||
|
db.put({_id: 'foo'}).then(function (resp) {
|
||
|
rev = resp.rev;
|
||
|
return db.remove('foo', rev);
|
||
|
}).then(function () {
|
||
|
return db.get('foo');
|
||
|
}).catch(function () {
|
||
|
return db.put({_id: 'foo', _rev: rev});
|
||
|
}).then(function () {
|
||
|
done(new Error('should never have got here'));
|
||
|
}, function (err) {
|
||
|
should.exist(err);
|
||
|
done();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('issue 2779, correct behavior for undeleting', function () {
|
||
|
|
||
|
if (testUtils.isCouchMaster()) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var rev;
|
||
|
|
||
|
function checkNumRevisions(num) {
|
||
|
return db.get('foo', {
|
||
|
open_revs: 'all',
|
||
|
revs: true
|
||
|
}).then(function (fullDocs) {
|
||
|
fullDocs[0].ok._revisions.ids.should.have.length(num);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return db.put({_id: 'foo'}).then(function (resp) {
|
||
|
rev = resp.rev;
|
||
|
return checkNumRevisions(1);
|
||
|
}).then(function () {
|
||
|
return db.remove('foo', rev);
|
||
|
}).then(function () {
|
||
|
return checkNumRevisions(2);
|
||
|
}).then(function () {
|
||
|
return db.allDocs({keys: ['foo']});
|
||
|
}).then(function (res) {
|
||
|
rev = res.rows[0].value.rev;
|
||
|
return db.put({_id: 'foo', _rev: rev});
|
||
|
}).then(function () {
|
||
|
return checkNumRevisions(3);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('issue 2888, successive deletes and writes', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var rev;
|
||
|
|
||
|
function checkNumRevisions(num) {
|
||
|
return db.get('foo', {
|
||
|
open_revs: 'all',
|
||
|
revs: true
|
||
|
}).then(function (fullDocs) {
|
||
|
fullDocs[0].ok._revisions.ids.should.have.length(num);
|
||
|
});
|
||
|
}
|
||
|
return db.put({ _id: 'foo' }).then(function (resp) {
|
||
|
rev = resp.rev;
|
||
|
return checkNumRevisions(1);
|
||
|
}).then(function () {
|
||
|
return db.remove('foo', rev);
|
||
|
}).then(function () {
|
||
|
return checkNumRevisions(2);
|
||
|
}).then(function () {
|
||
|
return db.put({ _id: 'foo' });
|
||
|
}).then(function (res) {
|
||
|
rev = res.rev;
|
||
|
return checkNumRevisions(3);
|
||
|
}).then(function () {
|
||
|
return db.remove('foo', rev);
|
||
|
}).then(function () {
|
||
|
return checkNumRevisions(4);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('2 invalid puts', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var called = 0;
|
||
|
var cb = function() {
|
||
|
if (++called === 2) {
|
||
|
done();
|
||
|
}
|
||
|
};
|
||
|
db.put({_id: 'foo', _zing: 'zing'}, cb);
|
||
|
db.put({_id: 'bar', _zing: 'zing'}, cb);
|
||
|
});
|
||
|
|
||
|
it('Docs save "null" value', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
return db.put({_id: 'doc', foo: null}).then(function () {
|
||
|
return db.get('doc');
|
||
|
}).then(function (doc) {
|
||
|
(typeof doc.foo).should.equal('object');
|
||
|
should.not.exist(doc.foo);
|
||
|
Object.keys(doc).sort().should.deep.equal(['_id', '_rev', 'foo']);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('db.type() returns a type', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
db.type().should.be.a('string');
|
||
|
});
|
||
|
|
||
|
it('#4788 db.type() is synchronous', function () {
|
||
|
new PouchDB(dbs.name).type.should.be.a('function');
|
||
|
new PouchDB(dbs.name).type.should.be.a('function');
|
||
|
});
|
||
|
|
||
|
it('replace PouchDB.destroy() (express-pouchdb#203)', function (done) {
|
||
|
var old = PouchDB.destroy;
|
||
|
PouchDB.destroy = function (name, callback) {
|
||
|
var db = new PouchDB(name);
|
||
|
return db.destroy(callback);
|
||
|
};
|
||
|
// delete a non-existing db, should be fine.
|
||
|
PouchDB.destroy(dbs.name, function (err, resp) {
|
||
|
PouchDB.destroy = old;
|
||
|
|
||
|
done(err, resp);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('3968, keeps all object fields', function () {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
/* jshint -W001 */
|
||
|
var doc = {
|
||
|
_id: "x",
|
||
|
type: "testdoc",
|
||
|
watch: 1,
|
||
|
unwatch: 1,
|
||
|
constructor: 1,
|
||
|
toString: 1,
|
||
|
toSource: 1,
|
||
|
toLocaleString: 1,
|
||
|
propertyIsEnumerable: 1,
|
||
|
isPrototypeOf: 1,
|
||
|
hasOwnProperty: 1
|
||
|
};
|
||
|
return db.put(doc).then(function () {
|
||
|
return db.get(doc._id);
|
||
|
}).then(function (savedDoc) {
|
||
|
// We shouldnt need to delete from doc here (#4273)
|
||
|
should.not.exist(doc._rev);
|
||
|
should.not.exist(doc._rev_tree);
|
||
|
|
||
|
delete savedDoc._rev;
|
||
|
savedDoc.should.deep.equal(doc);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('4712 invalid rev for new doc generates conflict', function () {
|
||
|
// CouchDB 1.X has a bug which allows this insertion via bulk_docs
|
||
|
// (which PouchDB uses for all document insertions)
|
||
|
if (adapter === 'http' && !testUtils.isCouchMaster()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var newdoc = {
|
||
|
'_id': 'foobar',
|
||
|
'_rev': '1-123'
|
||
|
};
|
||
|
|
||
|
return db.put(newdoc).then(function () {
|
||
|
throw new Error('expected an error');
|
||
|
}, function (err) {
|
||
|
err.should.have.property('status', 409);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
if (adapter === 'local') {
|
||
|
// TODO: this test fails in the http adapter in Chrome
|
||
|
it('should allow unicode doc ids', function (done) {
|
||
|
var db = new PouchDB(dbs.name);
|
||
|
var ids = [
|
||
|
// "PouchDB is awesome" in Japanese, contains 1-3 byte chars
|
||
|
'\u30d1\u30a6\u30c1\u30e5DB\u306f\u6700\u9ad8\u3060',
|
||
|
'\u03B2', // 2-byte utf-8 char: 3b2
|
||
|
'\uD843\uDF2D', // exotic 4-byte utf-8 char: 20f2d
|
||
|
'\u0000foo\u0000bar\u0001baz\u0002quux', // like mapreduce
|
||
|
'\u0000',
|
||
|
'\u30d1'
|
||
|
];
|
||
|
var numDone = 0;
|
||
|
ids.forEach(function (id) {
|
||
|
var doc = {_id : id, foo : 'bar'};
|
||
|
db.put(doc).then(function (info) {
|
||
|
doc._rev = info.rev;
|
||
|
return db.put(doc);
|
||
|
}).then(function () {
|
||
|
return db.get(id);
|
||
|
}).then(function (resp) {
|
||
|
resp._id.should.equal(id);
|
||
|
if (++numDone === ids.length) {
|
||
|
done();
|
||
|
}
|
||
|
}, done);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// this test only really makes sense for IDB
|
||
|
it('should have same blob support for 2 dbs', function () {
|
||
|
var db1 = new PouchDB(dbs.name);
|
||
|
return db1.info().then(function () {
|
||
|
var db2 = new PouchDB(dbs.name);
|
||
|
return db2.info().then(function () {
|
||
|
if (typeof db1._blobSupport !== 'undefined') {
|
||
|
db1._blobSupport.should.equal(db2._blobSupport,
|
||
|
'same blob support');
|
||
|
} else {
|
||
|
true.should.equal(true);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
});
|