| /* global PouchDBVersion110,PouchDBVersion200,PouchDBVersion220,PouchDB */ |
| 'use strict'; |
| |
| var scenarios = [ |
| 'PouchDB v1.1.0', |
| 'PouchDB v2.0.0', |
| 'PouchDB v2.2.0', |
| 'websql' |
| ]; |
| |
| describe('migration', function () { |
| |
| function usingDefaultPreferredAdapters() { |
| var defaults = ['idb', 'websql']; |
| return !(PouchDB.preferredAdapters < defaults || |
| PouchDB.preferredAdapters > defaults); |
| } |
| |
| scenarios.forEach(function (scenario) { |
| |
| describe('migrate from ' + scenario, function () { |
| |
| var dbs = {}; |
| var constructors = {}; |
| var skip = false; |
| |
| beforeEach(function (done) { |
| |
| if (!usingDefaultPreferredAdapters() || window.msIndexedDB) { |
| skip = true; |
| done(); |
| return; |
| } |
| |
| constructors = { |
| 'PouchDB v1.1.0': PouchDBVersion110, |
| 'PouchDB v2.0.0': PouchDBVersion200, |
| 'PouchDB v2.2.0': PouchDBVersion220, |
| PouchDB: PouchDB |
| }; |
| |
| // need actual unique db names for these tests |
| var localName = testUtils.adapterUrl('local', 'test_migration_local'); |
| var remoteName = testUtils.adapterUrl('http', 'test_migration_remote'); |
| |
| dbs.first = { |
| pouch : constructors[scenario] || PouchDB, |
| local : localName, |
| remote : remoteName, |
| localOpts : {} |
| }; |
| |
| dbs.second = { |
| pouch : PouchDB, |
| local : localName, |
| remote : remoteName |
| }; |
| |
| if (scenario in PouchDB.adapters) { |
| dbs.first.localOpts.adapter = scenario; |
| } |
| // else scenario might not make sense for this browser, so just use |
| // same adapter for both |
| |
| testUtils.cleanup([dbs.first.local, dbs.second.local], done); |
| |
| }); |
| |
| afterEach(function (done) { |
| if (skip) { |
| done(); |
| return; |
| } |
| testUtils.cleanup([dbs.first.local, dbs.second.local], done); |
| }); |
| |
| var origDocs = [ |
| {_id: '0', a: 1, b: 1}, |
| {_id: '3', a: 4, b: 16}, |
| {_id: '1', a: 2, b: 4}, |
| {_id: '2', a: 3, b: 9} |
| ]; |
| |
| it('Testing basic migration integrity', function (done) { |
| if (skip) { return done(); } |
| var oldPouch = |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| }); |
| oldPouch.bulkDocs({docs: origDocs}, function (err, res) { |
| var removedDoc = {_deleted: true, _rev: res[0].rev, _id: res[0].id}; |
| oldPouch.remove(removedDoc, function (err, res) { |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.then(function (newPouch) { |
| return newPouch.allDocs({key: '2'}); |
| }).then(function (res) { |
| res.total_rows.should.equal(3); |
| res.rows.should.have.length(1); |
| return newPouch.allDocs({key: '0'}); |
| }).then(function (res) { |
| res.total_rows.should.equal(3); |
| res.rows.should.have.length(0); |
| done(); |
| }).catch(function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |
| it("Test basic replication with migration", function (done) { |
| if (skip) { return done(); } |
| var docs = [ |
| {_id: "0", integer: 0, string: '0'}, |
| {_id: "1", integer: 1, string: '1'}, |
| {_id: "2", integer: 2, string: '2'}, |
| {_id: "3", integer: 3, string: '3', _deleted : true}, |
| {_id: "4", integer: 4, string: '4', _deleted : true} |
| ]; |
| |
| new dbs.first.pouch(dbs.first.remote, function (err, oldPouch) { |
| should.not.exist(err, 'got error in constructor: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| oldPouch.bulkDocs({docs: docs}, {}, function (err, res) { |
| should.not.exist(err, 'got error in bulkDocs: ' + |
| JSON.stringify(err)); |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err, oldLocalPouch) { |
| oldPouch.replicate.to(oldLocalPouch, function (err, result) { |
| should.not.exist(err, 'got error in replicate: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| should.exist(result.ok, 'replication was ok'); |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'got error in close: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| oldLocalPouch.close(function (err) { |
| should.not.exist(err, 'got error in close: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| new dbs.second.pouch(dbs.second.local, |
| function (err, newPouch) { |
| should.not.exist(err, 'got error in 2nd constructor: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| newPouch.allDocs({}, function (err, res) { |
| should.not.exist(err, 'got error in allDocs: ' + |
| JSON.stringify(err)); |
| res.rows.should.have.length(3, 'unexpected rows: ' + |
| JSON.stringify(res.rows)); |
| res.total_rows.should.equal(3); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |
| if (scenario === 'PouchDB v2.2.0' && !skip) { |
| it("Test persistent views don't require update", function (done) { |
| if (scenario !== 'PouchDB v2.2.0' || skip) { return done(); } |
| var oldPouch = |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| }); |
| var docs = origDocs.slice().concat([{ |
| _id: '_design/myview', |
| views: { |
| myview: { |
| map: function (doc) { |
| emit(doc.a); |
| }.toString() |
| } |
| } |
| }]); |
| var expectedRows = [ |
| { key: 1, id: '0', value: null }, |
| { key: 2, id: '1', value: null }, |
| { key: 3, id: '2', value: null }, |
| { key: 4, id: '3', value: null } |
| ]; |
| oldPouch.bulkDocs({docs: docs}, function (err, res) { |
| should.not.exist(err, 'bulkDocs'); |
| oldPouch.query('myview', function (err, res) { |
| should.not.exist(err, 'query'); |
| res.rows.should.deep.equal(expectedRows); |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'close'); |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.then(function (newPouch) { |
| return newPouch.query('myview', {stale: 'ok'}); |
| }).then(function (res) { |
| res.rows.should.deep.equal(expectedRows); |
| done(); |
| }).catch(function (err) { |
| should.not.exist(err, 'catch'); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |
| it("Test persistent views don't require update, with a value", |
| function (done) { |
| if (scenario !== 'PouchDB v2.2.0' || skip) { return done(); } |
| var oldPouch = |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| }); |
| var docs = origDocs.slice().concat([{ |
| _id: '_design/myview', |
| views: { |
| myview: { |
| map: function (doc) { |
| emit(doc.a, doc.b); |
| }.toString() |
| } |
| } |
| }]); |
| var expectedRows = [ |
| { key: 1, id: '0', value: 1 }, |
| { key: 2, id: '1', value: 4 }, |
| { key: 3, id: '2', value: 9 }, |
| { key: 4, id: '3', value: 16 } |
| ]; |
| oldPouch.bulkDocs({docs: docs}, function (err, res) { |
| should.not.exist(err, 'bulkDocs'); |
| oldPouch.query('myview', function (err, res) { |
| should.not.exist(err, 'query'); |
| res.rows.should.deep.equal(expectedRows); |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'close'); |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.then(function (newPouch) { |
| return newPouch.query('myview', {stale: 'ok'}); |
| }).then(function (res) { |
| res.rows.should.deep.equal(expectedRows); |
| done(); |
| }).catch(function (err) { |
| should.not.exist(err, 'catch'); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |
| it('Returns ok for viewCleanup after modifying view', function (done) { |
| if (skip) { return done(); } |
| var oldPouch = |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| }); |
| var ddoc = { |
| _id: '_design/myview', |
| views: { |
| myview: { |
| map: function (doc) { |
| emit(doc.firstName); |
| }.toString() |
| } |
| } |
| }; |
| var doc = { |
| _id: 'foo', |
| firstName: 'Foobar', |
| lastName: 'Bazman' |
| }; |
| oldPouch.bulkDocs({docs: [ddoc, doc]}).then(function (info) { |
| ddoc._rev = info[0].rev; |
| return oldPouch.query('myview'); |
| }).then(function (res) { |
| res.rows.should.deep.equal([ |
| {id: 'foo', key: 'Foobar', value: null} |
| ]); |
| ddoc.views.myview.map = function (doc) { |
| emit(doc.lastName); |
| }.toString(); |
| return oldPouch.put(ddoc); |
| }).then(function () { |
| return oldPouch.query('myview'); |
| }).then(function (res) { |
| res.rows.should.deep.equal([ |
| {id: 'foo', key: 'Bazman', value: null} |
| ]); |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.viewCleanup().then(function () { |
| done(); |
| }, done); |
| }, done); |
| }); |
| it('Remembers local docs', function (done) { |
| if (skip) { return done(); } |
| var oldPouch = |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| }); |
| var docs = [ |
| { _id: '_local/foo' }, |
| { _id: '_local/bar' } |
| ]; |
| oldPouch.bulkDocs({docs: docs}).then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.get('_local/foo').then(function () { |
| return newPouch.get('_local/bar'); |
| }).then(function () { |
| done(); |
| }, done); |
| }, done); |
| }); |
| |
| it('Testing migration with weird doc ids', function (done) { |
| if (skip) { return done(); } |
| |
| var origDocs = [ |
| {_id: 'foo::bar::baz'}, |
| {_id: '\u0000foo\u0000'} |
| ]; |
| |
| var oldPouch = |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| }); |
| oldPouch.bulkDocs({docs: origDocs}, function (err, res) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.then(function (newPouch) { |
| return newPouch.allDocs(); |
| }).then(function (res) { |
| res.total_rows.should.equal(2); |
| res.rows.should.have.length(2); |
| res.rows[1].id.should.equal(origDocs[0]._id); |
| res.rows[0].id.should.equal(origDocs[1]._id); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| } |
| }); |
| }); |
| }); |