WebSQL Storage Provider with tests (4 tests failing still)

This commit is contained in:
David Humphrey (:humph) david.humphrey@senecacollege.ca 2013-11-27 16:52:52 -05:00
parent 3d171b867d
commit 58392efd10
6 changed files with 378 additions and 3 deletions

View File

@ -15,6 +15,10 @@ define(function(require) {
IDB_RO: 'readonly', IDB_RO: 'readonly',
IDB_RW: 'readwrite', IDB_RW: 'readwrite',
WSQL_VERSION: "1",
WSQL_SIZE: 5 * 1024 * 1024,
WSQL_DESC: "FileSystem Storage",
MODE_FILE: 'FILE', MODE_FILE: 'FILE',
MODE_DIRECTORY: 'DIRECTORY', MODE_DIRECTORY: 'DIRECTORY',
MODE_SYMBOLIC_LINK: 'SYMLINK', MODE_SYMBOLIC_LINK: 'SYMLINK',

View File

@ -1,7 +1,31 @@
define(function(require) { define(function(require) {
var IndexedDB = require('src/providers/indexeddb');
var WebSQL = require('src/providers/websql');
var Memory = require('src/providers/memory');
return { return {
IndexedDB: require('src/providers/indexeddb'), IndexedDB: IndexedDB,
Memory: require('src/providers/memory'), WebSQL: WebSQL,
Default: require('src/providers/indexeddb') Memory: Memory,
Default: IndexedDB,
// The Legacy provider does automatic fallback checks
Legacy: (function() {
if(IndexedDB.isSupported()) {
return IndexedDB;
}
if(WebSQL.isSupported()) {
return WebSQL;
}
function NotSupported() {
throw "[IDBFS Error] Your browser doesn't support IndexedDB or WebSQL.";
}
NotSupported.isSupported = function() {
return false;
};
return NotSupported;
}())
}; };
}); });

130
src/providers/websql.js Normal file
View File

@ -0,0 +1,130 @@
define(function(require) {
var FILE_SYSTEM_NAME = require('src/constants').FILE_SYSTEM_NAME;
var FILE_STORE_NAME = require('src/constants').FILE_STORE_NAME;
var WSQL_VERSION = require('src/constants').WSQL_VERSION;
var WSQL_SIZE = require('src/constants').WSQL_SIZE;
var WSQL_DESC = require('src/constants').WSQL_DESC;
function WebSQLContext(db, isReadOnly) {
var that = this;
this.getTransaction = function(callback) {
if(that.transaction) {
callback(that.transaction);
return;
}
// Either do readTransaction() (read-only) or transaction() (read/write)
db[isReadOnly ? 'transaction' : 'readTransaction'](function(transaction) {
that.transaction = transaction;
callback(transaction);
});
};
}
WebSQLContext.prototype.clear = function(callback) {
function onSuccess(transaction, result) {
callback(null);
}
function onError(transaction, error) {
callback(error);
}
this.getTransaction(function(transaction) {
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME,
[], onSuccess, onError);
});
};
WebSQLContext.prototype.get = function(key, callback) {
function onSuccess(transaction, result) {
if(result.rows.length !== 1) {
callback("[WebSQLContext] Error: expected 1 row for get operation.");
return;
}
callback(null, result.rows.item(0).data);
}
function onError(transaction, error) {
callback(error);
}
this.getTransaction(function(transaction) {
transaction.executeSql("SELECT * FROM " + FILE_STORE_NAME + " WHERE id = ?",
[key], onSuccess, onError);
});
};
WebSQLContext.prototype.put = function(key, value, callback) {
function onSuccess(transaction, result) {
callback(null);
}
function onError(transaction, error) {
callback(error);
}
this.getTransaction(function(transaction) {
transaction.executeSql("INSERT OR REPLACE INTO " + FILE_STORE_NAME + " (id, data)",
[key, value], onSuccess, onError);
});
};
WebSQLContext.prototype.delete = function(key, callback) {
function onSuccess(transaction, result) {
callback(null);
}
function onError(transaction, error) {
callback(error);
}
this.getTransaction(function(transaction) {
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME + " WHERE id = ?",
[key], onSuccess, onError);
});
};
function WebSQL(name) {
this.name = name || FILE_SYSTEM_NAME;
this.db = null;
}
WebSQL.isSupported = function() {
return !!window.openDatabase;
};
WebSQL.prototype.open = function(callback) {
var that = this;
// Bail if we already have a db open
if(that.db) {
callback(null, false);
return;
}
var db = window.openDatabase(that.name, WSQL_VERSION, WSQL_DESC, WSQL_SIZE);
if(!db) {
callback("[WebSQL] Unable to open database.");
return;
}
that.db = db;
function onError(transaction, error) {
callback(error);
}
function onSuccess(transaction, result) {
function gotCount(transaction, result) {
var firstAccess = result.rows.item(0).count > 0;
callback(null, firstAccess);
}
function onError(transaction, error) {
callback(error);
}
// Keep track of whether we're accessing this db for the first time
// and therefore needs to get formatted.
transaction.executeSql("SELECT COUNT(id) AS count FROM " + FILE_STORE_NAME,
[], gotCount, onError);
}
db.transaction(function(transaction) {
transaction.executeSql("CREATE TABLE IF NOT EXISTS " + FILE_STORE_NAME + " (id unique, data)",
[], onSuccess, onError);
});
};
WebSQL.prototype.getReadOnlyContext = function() {
return new WebSQLContext(this.db, true);
};
WebSQL.prototype.getReadWriteContext = function() {
return new WebSQLContext(this.db, false);
};
return WebSQL;
});

View File

@ -8,6 +8,10 @@ define(["IDBFS"], function(IDBFS) {
expect(typeof IDBFS.FileSystem.providers.IndexedDB).toEqual('function'); expect(typeof IDBFS.FileSystem.providers.IndexedDB).toEqual('function');
}); });
it("has WebSQL constructor", function() {
expect(typeof IDBFS.FileSystem.providers.WebSQL).toEqual('function');
});
it("has Memory constructor", function() { it("has Memory constructor", function() {
expect(typeof IDBFS.FileSystem.providers.Memory).toEqual('function'); expect(typeof IDBFS.FileSystem.providers.Memory).toEqual('function');
}); });
@ -15,5 +19,9 @@ define(["IDBFS"], function(IDBFS) {
it("has a Default constructor", function() { it("has a Default constructor", function() {
expect(typeof IDBFS.FileSystem.providers.Default).toEqual('function'); expect(typeof IDBFS.FileSystem.providers.Default).toEqual('function');
}); });
it("has Legacy constructor", function() {
expect(typeof IDBFS.FileSystem.providers.Legacy).toEqual('function');
});
}); });
}); });

View File

@ -0,0 +1,208 @@
define(["IDBFS"], function(IDBFS) {
var WEBSQL_NAME = "websql-test-db";
function wipeDB() {
var provider = new IDBFS.FileSystem.providers.WebSQL(WEBSQL_NAME);
provider.open(function(err, firstAccess) {
if(err) {
console.error("Problem clearing WebSQL db: " + err);
return;
}
var context = provider.getReadWriteContext();
context.clear(function(err) {
console.error("Problem clearing WebSQL db: " + err);
});
});
}
describe("IDBFS.FileSystem.providers.WebSQL", function() {
it("is supported -- if it isn't, none of these tests can run.", function() {
expect(IDBFS.FileSystem.providers.WebSQL.isSupported()).toEqual(true);
});
it("has open, getReadOnlyContext, and getReadWriteContext instance methods", function() {
var webSQLProvider = new IDBFS.FileSystem.providers.WebSQL();
expect(typeof webSQLProvider.open).toEqual('function');
expect(typeof webSQLProvider.getReadOnlyContext).toEqual('function');
expect(typeof webSQLProvider.getReadWriteContext).toEqual('function');
});
describe("open an WebSQL provider", function() {
beforeEach(function() {
wipeDB();
});
afterEach(function() {
wipeDB();
});
it("should open a new WebSQL database", function() {
var complete = false;
var _error, _result;
var provider = new IDBFS.FileSystem.providers.WebSQL(WEBSQL_NAME);
provider.open(function(err, firstAccess) {
_error = err;
_result = firstAccess;
complete = true;
});
waitsFor(function() {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function() {
expect(_error).toEqual(null);
expect(_result).toEqual(true);
});
});
});
describe("Read/Write operations on an WebSQL provider", function() {
beforeEach(function() {
wipeDB();
});
afterEach(function() {
wipeDB();
});
it("should allow put() and get()", function() {
var complete = false;
var _error, _result;
var provider = new IDBFS.FileSystem.providers.WebSQL(WEBSQL_NAME);
provider.open(function(err, firstAccess) {
_error = err;
var context = provider.getReadWriteContext();
context.put("key", "value", function(err, result) {
_error = _error || err;
context.get("key", function(err, result) {
_error = _error || err;
_result = result;
complete = true;
});
});
});
waitsFor(function() {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function() {
expect(_error).toEqual(null);
expect(_result).toEqual("value");
});
});
it("should allow delete()", function() {
var complete = false;
var _error, _result;
var provider = new IDBFS.FileSystem.providers.WebSQL(WEBSQL_NAME);
provider.open(function(err, firstAccess) {
_error = err;
var context = provider.getReadWriteContext();
context.put("key", "value", function(err, result) {
_error = _error || err;
context.delete("key", function(err, result) {
_error = _error || err;
context.get("key", function(err, result) {
_error = _error || err;
_result = result;
complete = true;
});
});
});
});
waitsFor(function() {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function() {
expect(_error).toEqual(null);
expect(_result).toEqual(null);
});
});
it("should allow clear()", function() {
var complete = false;
var _error, _result1, _result2;
var provider = new IDBFS.FileSystem.providers.WebSQL(WEBSQL_NAME);
provider.open(function(err, firstAccess) {
_error = err;
var context = provider.getReadWriteContext();
context.put("key1", "value1", function(err, result) {
_error = _error || err;
context.put("key2", "value2", function(err, result) {
_error = _error || err;
context.clear(function(err) {
_error = _error || err;
context.get("key1", function(err, result) {
_error = _error || err;
_result1 = result;
context.get("key2", function(err, result) {
_error = _error || err;
_result2 = result;
complete = true;
});
});
});
});
});
});
waitsFor(function() {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function() {
expect(_error).toEqual(null);
expect(_result1).toEqual(null);
expect(_result2).toEqual(null);
});
});
it("should fail when trying to write on ReadOnlyContext", function() {
var complete = false;
var _error, _result;
var provider = new IDBFS.FileSystem.providers.WebSQL(WEBSQL_NAME);
provider.open(function(err, firstAccess) {
_error = err;
var context = provider.getReadOnlyContext();
context.put("key1", "value1", function(err, result) {
_error = _error || err;
_result = result;
complete = true;
});
});
waitsFor(function() {
return complete;
}, 'test to complete', DEFAULT_TIMEOUT);
runs(function() {
expect(_error).toBeDefined();
expect(_result).toEqual(null);
});
});
});
});
});

View File

@ -32,6 +32,7 @@ define([
"spec/providers/providers.spec", "spec/providers/providers.spec",
"spec/providers/providers.memory.spec", "spec/providers/providers.memory.spec",
"spec/providers/providers.indexeddb.spec", "spec/providers/providers.indexeddb.spec",
"spec/providers/providers.websql.spec",
// Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test) // Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test)
"spec/node-js/simple/test-fs-mkdir", "spec/node-js/simple/test-fs-mkdir",