mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
add unit test for backup database
This commit is contained in:
parent
372ad1f513
commit
d0a32b18c5
@ -16,41 +16,29 @@
|
||||
* The BackupDatabase handles all the database interactions related
|
||||
* to piskel snapshots continuously saved while during the usage of
|
||||
* Piskel.
|
||||
*
|
||||
* @param {Object} options
|
||||
* - onUpgrade {Function} optional callback called when a DB
|
||||
* upgrade is performed.
|
||||
*/
|
||||
ns.BackupDatabase = function (options) {
|
||||
options = options || {};
|
||||
|
||||
ns.BackupDatabase = function () {
|
||||
this.db = null;
|
||||
this.onUpgrade = options.onUpgrade;
|
||||
};
|
||||
|
||||
ns.BackupDatabase.drop = function () {
|
||||
return _requestPromise(window.indexedDB.deleteDatabase(DB_NAME));
|
||||
};
|
||||
|
||||
/**
|
||||
* Open and initialize the database.
|
||||
* Returns a promise that resolves when the databse is opened.
|
||||
*/
|
||||
ns.BackupDatabase.prototype.init = function () {
|
||||
this.initDeferred_ = Q.defer();
|
||||
|
||||
var request = window.indexedDB.open(DB_NAME, DB_VERSION);
|
||||
|
||||
request.onerror = this.onRequestError_.bind(this);
|
||||
request.onsuccess = this.onRequestSuccess_.bind(this);
|
||||
request.onupgradeneeded = this.onUpgradeNeeded_.bind(this);
|
||||
|
||||
return this.initDeferred_.promise;
|
||||
};
|
||||
|
||||
ns.BackupDatabase.prototype.onRequestError_ = function (event) {
|
||||
console.log('Could not initialize the piskel backup database');
|
||||
this.initDeferred_.reject();
|
||||
};
|
||||
|
||||
ns.BackupDatabase.prototype.onRequestSuccess_ = function (event) {
|
||||
this.db = event.target.result;
|
||||
this.initDeferred_.resolve(this.db);
|
||||
return _requestPromise(request).then(function (event) {
|
||||
this.db = event.target.result;
|
||||
return this.db;
|
||||
}.bind(this)).catch(function (e) {
|
||||
console.log('Could not initialize the piskel backup database');
|
||||
});
|
||||
};
|
||||
|
||||
ns.BackupDatabase.prototype.onUpgradeNeeded_ = function (event) {
|
||||
@ -65,9 +53,7 @@
|
||||
objectStore.createIndex('session_id, date', ['session_id', 'date'], { unique: false });
|
||||
|
||||
objectStore.transaction.oncomplete = function(event) {
|
||||
if (typeof this.onUpgrade == 'function') {
|
||||
this.onUpgrade(this.db);
|
||||
}
|
||||
// Nothing to do at the moment!
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
@ -187,18 +173,18 @@
|
||||
var sessions = {};
|
||||
|
||||
var _createSession = function (snapshot) {
|
||||
sessions[snapshot.sessionId] = {
|
||||
sessions[snapshot.session_id] = {
|
||||
startDate: snapshot.date,
|
||||
endDate: snapshot.date,
|
||||
name: snapshot.name,
|
||||
id: snapshot.sessionId
|
||||
id: snapshot.session_id
|
||||
};
|
||||
};
|
||||
|
||||
var _updateSessions = function (snapshot) {
|
||||
var s = sessions[snapshot.sessionId];
|
||||
s.startDate = Math.min(s.startDate, snapshot.startDate);
|
||||
s.endDate = Math.max(s.endDate, snapshot.endDate);
|
||||
var _updateSession = function (snapshot) {
|
||||
var s = sessions[snapshot.session_id];
|
||||
s.startDate = Math.min(s.startDate, snapshot.date);
|
||||
s.endDate = Math.max(s.endDate, snapshot.date);
|
||||
if (s.endDate === snapshot.endDate) {
|
||||
s.name = snapshot.name;
|
||||
}
|
||||
@ -212,10 +198,10 @@
|
||||
if (!snapshot) {
|
||||
deferred.resolve(sessions);
|
||||
} else {
|
||||
if (sessions[snapshot.sessionId]) {
|
||||
_createSession(snapshot);
|
||||
if (sessions[snapshot.session_id]) {
|
||||
_updateSession(snapshot);
|
||||
} else {
|
||||
_updateSessions(snapshot);
|
||||
_createSession(snapshot);
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
@ -234,7 +220,7 @@
|
||||
var deferred = Q.defer();
|
||||
|
||||
// Open a transaction to the snapshots object store.
|
||||
var objectStore = this.db.transaction(['snapshots']).objectStore('snapshots');
|
||||
var objectStore = this.openObjectStore_();
|
||||
|
||||
// Loop on all the saved snapshots for the provided piskel id
|
||||
var index = objectStore.index('session_id');
|
||||
|
@ -15,16 +15,9 @@
|
||||
/**
|
||||
* The PiskelDatabase handles all the database interactions related
|
||||
* to the local piskel saved that can be performed in-browser.
|
||||
*
|
||||
* @param {Object} options
|
||||
* - onUpgrade {Function} optional callback called when a DB
|
||||
* upgrade is performed.
|
||||
*/
|
||||
ns.PiskelDatabase = function (options) {
|
||||
options = options || {};
|
||||
|
||||
this.db = null;
|
||||
this.onUpgrade = options.onUpgrade;
|
||||
};
|
||||
|
||||
ns.PiskelDatabase.prototype.init = function () {
|
||||
@ -57,9 +50,7 @@
|
||||
// Create an object store "piskels" with the autoIncrement flag set as true.
|
||||
var objectStore = this.db.createObjectStore('piskels', { keyPath : 'name' });
|
||||
objectStore.transaction.oncomplete = function(event) {
|
||||
if (typeof this.onUpgrade == 'function') {
|
||||
this.onUpgrade(this.db);
|
||||
}
|
||||
pskl.service.storage.migrate.MigrateLocalStorageToIndexed.migrate(this.db);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.service.storage');
|
||||
var DB_NAME = 'PiskelDatabase';
|
||||
var DB_VERSION = 1;
|
||||
|
||||
ns.IndexedDbStorageService = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
|
@ -4,11 +4,10 @@
|
||||
// Simple migration helper to move local storage saves to indexed db.
|
||||
ns.MigrateLocalStorageToIndexedDb = {};
|
||||
|
||||
ns.MigrateLocalStorageToIndexedDb.migrate = function () {
|
||||
ns.MigrateLocalStorageToIndexedDb.migrate = function (piskelDatabase) {
|
||||
var deferred = Q.defer();
|
||||
|
||||
var localStorageService = pskl.app.localStorageService;
|
||||
var indexedDbStorageService = pskl.app.indexedDbStorageService;
|
||||
|
||||
var localStorageKeys = localStorageService.getKeys();
|
||||
var migrationData = localStorageKeys.map(function (key) {
|
||||
@ -28,24 +27,22 @@
|
||||
if (!data) {
|
||||
console.log('Data migration from local storage to indexed db finished.');
|
||||
if (success) {
|
||||
console.log('Local storage piskels successfully migrated. Old copies will be deleted.');
|
||||
ns.MigrateLocalStorageToIndexedDb.deleteLocalStoragePiskels();
|
||||
}
|
||||
|
||||
deferred.resolve();
|
||||
return;
|
||||
} else {
|
||||
ns.MigrateLocalStorageToIndexedDb.save_(piskelDatabase, data)
|
||||
.then(function () {
|
||||
migrateSprite(index + 1);
|
||||
})
|
||||
.catch(function (e) {
|
||||
var success = false;
|
||||
console.error('Failed to migrate local storage sprite for name: ' + data.name);
|
||||
migrateSprite(index + 1);
|
||||
});
|
||||
}
|
||||
indexedDbStorageService.save_(
|
||||
data.name,
|
||||
data.description,
|
||||
data.date,
|
||||
data.serialized
|
||||
).then(function () {
|
||||
migrateSprite(index + 1);
|
||||
}).catch(function (e) {
|
||||
var success = false;
|
||||
console.error('Failed to migrate local storage sprite for name: ' + data.name);
|
||||
migrateSprite(index + 1);
|
||||
});
|
||||
};
|
||||
|
||||
// Start the migration.
|
||||
@ -54,6 +51,17 @@
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
ns.MigrateLocalStorageToIndexedDb.save_ = function (piskelDatabase, piskelData) {
|
||||
return piskelDatabase.get(piskelData.name).then(function (event) {
|
||||
var data = event.target.result;
|
||||
if (typeof data !== 'undefined') {
|
||||
return piskelDatabase.update(piskelData.name, piskelData.description, piskelData.date, piskelData.serialized);
|
||||
} else {
|
||||
return piskelDatabase.create(piskelData.name, piskelData.description, piskelData.date, piskelData.serialized);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ns.MigrateLocalStorageToIndexedDb.deleteLocalStoragePiskels = function () {
|
||||
var localStorageKeys = pskl.app.localStorageService.getKeys();
|
||||
|
||||
|
235
test/js/database/BackupDatabaseTest.js
Normal file
235
test/js/database/BackupDatabaseTest.js
Normal file
@ -0,0 +1,235 @@
|
||||
describe('BackupDatabase test', function () {
|
||||
|
||||
// Test object.
|
||||
var backupDatabase;
|
||||
|
||||
var _toSnapshot = function (session_id, name, description, date, serialized) {
|
||||
return {
|
||||
session_id: session_id,
|
||||
name: name,
|
||||
description: description,
|
||||
date: date,
|
||||
serialized: serialized
|
||||
};
|
||||
};
|
||||
|
||||
var _checkSnapshot = function (actual, expected) {
|
||||
expect(actual.session_id).toBe(actual.session_id);
|
||||
expect(actual.name).toBe(actual.name);
|
||||
expect(actual.description).toBe(actual.description);
|
||||
expect(actual.date).toBe(actual.date);
|
||||
expect(actual.serialized).toBe(actual.serialized);
|
||||
};
|
||||
|
||||
var _addSnapshots = function (snapshots) {
|
||||
var _add = function (index) {
|
||||
return backupDatabase.createSnapshot(snapshots[index]).then(function () {
|
||||
if (snapshots[index + 1]) {
|
||||
return _add(index + 1);
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
return _add(0);
|
||||
};
|
||||
|
||||
beforeEach(function (done) {
|
||||
// Drop the database before each test.
|
||||
pskl.database.BackupDatabase.drop().then(done);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
// Close the database if it was still open.
|
||||
if (backupDatabase && backupDatabase.db) {
|
||||
backupDatabase.db.close();
|
||||
}
|
||||
});
|
||||
|
||||
it('initializes the DB and returns a promise', function (done) {
|
||||
backupDatabase = new pskl.database.BackupDatabase();
|
||||
backupDatabase.init().then(done);
|
||||
});
|
||||
|
||||
it('can add snapshots and retrieve them', function (done) {
|
||||
var snapshot = _toSnapshot('session_1', 'name', 'desc', 0, 'serialized');
|
||||
|
||||
backupDatabase = new pskl.database.BackupDatabase();
|
||||
backupDatabase.init()
|
||||
.then(function (db) {
|
||||
// Create snapshot in backup database
|
||||
return backupDatabase.createSnapshot(snapshot);
|
||||
}).then(function () {
|
||||
// Get snapshots for session_1 in backup database
|
||||
return backupDatabase.getSnapshotsBySessionId('session_1');
|
||||
}).then(function (snapshots) {
|
||||
expect(snapshots.length).toBe(1);
|
||||
_checkSnapshot(snapshots[0], snapshot);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can update snapshots and retrieve them', function (done) {
|
||||
var snapshot = _toSnapshot('session_1', 'name', 'desc', 0, 'serialized');
|
||||
var updated = _toSnapshot('session_1', 'name_updated', 'desc_updated', 10, 'serialized_updated');
|
||||
|
||||
backupDatabase = new pskl.database.BackupDatabase();
|
||||
backupDatabase.init()
|
||||
.then(function () {
|
||||
// Create snapshot in backup database
|
||||
return backupDatabase.createSnapshot(snapshot);
|
||||
}).then(function () {
|
||||
// Retrieve snapshots to get the inserted snapshot id
|
||||
return backupDatabase.getSnapshotsBySessionId('session_1');
|
||||
}).then(function (snapshots) {
|
||||
// Update snapshot in backup database
|
||||
updated.id = snapshots[0].id;
|
||||
return backupDatabase.updateSnapshot(updated);
|
||||
}).then(function () {
|
||||
// Get snapshots for session_1 in backup database
|
||||
return backupDatabase.getSnapshotsBySessionId('session_1');
|
||||
}).then(function (snapshots) {
|
||||
expect(snapshots.length).toBe(1);
|
||||
_checkSnapshot(snapshots[0], updated);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can delete snapshots', function (done) {
|
||||
var testSnapshots = [
|
||||
_toSnapshot('session_1', 'name1', 'desc1', 0, 'serialized1'),
|
||||
_toSnapshot('session_1', 'name2', 'desc2', 0, 'serialized2'),
|
||||
_toSnapshot('session_2', 'name3', 'desc3', 0, 'serialized3')
|
||||
];
|
||||
|
||||
backupDatabase = new pskl.database.BackupDatabase();
|
||||
backupDatabase.init()
|
||||
.then(function () {
|
||||
return _addSnapshots(testSnapshots);
|
||||
}).then(function () {
|
||||
// Retrieve snapshots to get the inserted snapshot id
|
||||
return backupDatabase.getSnapshotsBySessionId('session_1');
|
||||
}).then(function (snapshots) {
|
||||
expect(snapshots.length).toBe(2);
|
||||
// Delete snapshot with 'name1' from backup database
|
||||
var snapshot = snapshots.filter(function (s) { return s.name === 'name1' })[0];
|
||||
return backupDatabase.deleteSnapshot(snapshot);
|
||||
}).then(function () {
|
||||
// Get snapshots for session_1 in backup database
|
||||
return backupDatabase.getSnapshotsBySessionId('session_1');
|
||||
}).then(function (snapshots) {
|
||||
expect(snapshots.length).toBe(1);
|
||||
_checkSnapshot(snapshots[0], testSnapshots[1]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an empty array when calling getSnapshots for an empty session', function (done) {
|
||||
var testSnapshots = [
|
||||
_toSnapshot('session_1', 'name1', 'desc1', 0, 'serialized1'),
|
||||
_toSnapshot('session_1', 'name2', 'desc2', 0, 'serialized2'),
|
||||
_toSnapshot('session_2', 'name3', 'desc3', 0, 'serialized3')
|
||||
];
|
||||
|
||||
backupDatabase = new pskl.database.BackupDatabase();
|
||||
backupDatabase.init()
|
||||
.then(function () {
|
||||
return _addSnapshots(testSnapshots);
|
||||
}).then(function () {
|
||||
// Retrieve snapshots for a session that doesn't exist
|
||||
return backupDatabase.getSnapshotsBySessionId('session_3');
|
||||
}).then(function (snapshots) {
|
||||
expect(snapshots.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can delete all snapshots for a session', function (done) {
|
||||
var testSnapshots = [
|
||||
_toSnapshot('session_1', 'name1', 'desc1', 0, 'serialized1'),
|
||||
_toSnapshot('session_1', 'name2', 'desc2', 0, 'serialized2'),
|
||||
_toSnapshot('session_2', 'name3', 'desc3', 0, 'serialized3')
|
||||
];
|
||||
|
||||
backupDatabase = new pskl.database.BackupDatabase();
|
||||
backupDatabase.init()
|
||||
.then(function () {
|
||||
return _addSnapshots(testSnapshots);
|
||||
}).then(function () {
|
||||
// Retrieve snapshots to get the inserted snapshot id
|
||||
return backupDatabase.getSnapshotsBySessionId('session_1');
|
||||
}).then(function (snapshots) {
|
||||
// Check that we have 2 snapshots for session_1
|
||||
expect(snapshots.length).toBe(2);
|
||||
// Delete snapshots for session_1
|
||||
return backupDatabase.deleteSnapshotsForSession('session_1');
|
||||
}).then(function () {
|
||||
// Get snapshots for session_1 in backup database
|
||||
return backupDatabase.getSnapshotsBySessionId('session_1');
|
||||
}).then(function (snapshots) {
|
||||
// All snapshots should have been deleted
|
||||
expect(snapshots.length).toBe(0);
|
||||
// Get snapshots for session_2 in backup database
|
||||
return backupDatabase.getSnapshotsBySessionId('session_2');
|
||||
}).then(function (snapshots) {
|
||||
// There should still be the snapshot for session_2
|
||||
expect(snapshots.length).toBe(1);
|
||||
_checkSnapshot(snapshots[0], testSnapshots[2]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('does a noop when calling deleteAllSnapshotsForSession for a missing session', function (done) {
|
||||
backupDatabase = new pskl.database.BackupDatabase();
|
||||
backupDatabase.init()
|
||||
.then(function () {
|
||||
// Delete snapshot with 'name1' from backup database
|
||||
return backupDatabase.deleteSnapshotsForSession('session_1');
|
||||
}).then(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns sessions array when calling getSessions', function (done) {
|
||||
var testSnapshots = [
|
||||
_toSnapshot('session_1', 'name1', 'desc1', 5, 'serialized1'),
|
||||
_toSnapshot('session_1', 'name2', 'desc2', 10, 'serialized2'),
|
||||
_toSnapshot('session_2', 'name3', 'desc3', 15, 'serialized3')
|
||||
];
|
||||
|
||||
backupDatabase = new pskl.database.BackupDatabase();
|
||||
backupDatabase.init()
|
||||
.then(function () {
|
||||
return _addSnapshots(testSnapshots);
|
||||
}).then(function () {
|
||||
return backupDatabase.getSessions();
|
||||
}).then(function (sessions) {
|
||||
// Check that we have 2 sessions
|
||||
expect(sessions.length).toBe(2);
|
||||
|
||||
// Get the actual sessions
|
||||
var session1 = sessions.filter(function (s) { return s.id === 'session_1'; })[0];
|
||||
var session2 = sessions.filter(function (s) { return s.id === 'session_2'; })[0];
|
||||
|
||||
// Check the start/end date were computed properly
|
||||
expect(session1.startDate).toBe(5);
|
||||
expect(session1.endDate).toBe(10);
|
||||
expect(session2.startDate).toBe(15);
|
||||
expect(session2.endDate).toBe(15);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an empty array when calling getSessions on an empty DB', function (done) {
|
||||
backupDatabase = new pskl.database.BackupDatabase();
|
||||
backupDatabase.init()
|
||||
.then(function () {
|
||||
return backupDatabase.getSessions();
|
||||
}).then(function (sessions) {
|
||||
expect(sessions.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user