1239 lines
40 KiB
JavaScript
1239 lines
40 KiB
JavaScript
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
goog.provide('goog.oldDbTest');
|
|
goog.setTestOnly('goog.oldDbTest');
|
|
|
|
goog.require('goog.async.Deferred');
|
|
goog.require('goog.db');
|
|
goog.require('goog.db.Cursor');
|
|
goog.require('goog.db.Error');
|
|
goog.require('goog.db.IndexedDb');
|
|
goog.require('goog.db.KeyRange');
|
|
goog.require('goog.db.Transaction');
|
|
goog.require('goog.events');
|
|
goog.require('goog.testing.AsyncTestCase');
|
|
goog.require('goog.testing.asserts');
|
|
goog.require('goog.testing.jsunit');
|
|
goog.require('goog.userAgent.product');
|
|
goog.require('goog.userAgent.product.isVersion');
|
|
|
|
// These tests test the old setVersion API, which is only supported on Chrome
|
|
// through version 24. Once Chrome 24 is no longer supported, they (and
|
|
// goog.db.IndexedDb.setVersion) can be removed.
|
|
var idbSupported = goog.userAgent.product.CHROME &&
|
|
goog.userAgent.product.isVersion('22') &&
|
|
!goog.userAgent.product.isVersion('25');
|
|
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
|
|
asyncTestCase.stepTimeout = 5000;
|
|
var dbName;
|
|
var dbBaseName = 'testDb';
|
|
var globalDb = null;
|
|
|
|
// On Chrome 24+, the database reports its default version as 1 as opposed to
|
|
// the empty string (as per the new spec).
|
|
var baseVersion = goog.userAgent.product.isVersion('24') ? 1 : '';
|
|
|
|
function restartDatabase(opt_db) {
|
|
if (opt_db && opt_db.isOpen()) {
|
|
opt_db.close();
|
|
}
|
|
return goog.db.openDatabase(dbName);
|
|
}
|
|
|
|
function addStore(db) {
|
|
return db.setVersion('test').addCallback(function(tx) {
|
|
db.createObjectStore('store');
|
|
return restartDatabase(db);
|
|
});
|
|
}
|
|
|
|
function addStoreWithIndex(db) {
|
|
return db.setVersion('test').addCallback(function(tx) {
|
|
var store = db.createObjectStore('store', {keyPath: 'key'});
|
|
store.createIndex('index', 'value');
|
|
return restartDatabase(db);
|
|
});
|
|
}
|
|
|
|
function populateStore(values, keys, db) {
|
|
var d = new goog.async.Deferred();
|
|
var putTx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
|
|
var store = putTx.objectStore('store');
|
|
for (var i = 0; i < values.length; ++i) {
|
|
store.put(values[i], keys[i]);
|
|
}
|
|
|
|
goog.events.listen(
|
|
putTx,
|
|
goog.db.Transaction.EventTypes.ERROR,
|
|
failOnErrorEvent);
|
|
|
|
goog.events.listen(
|
|
putTx,
|
|
goog.db.Transaction.EventTypes.COMPLETE,
|
|
function() {
|
|
d.callback(db);
|
|
});
|
|
|
|
return d;
|
|
}
|
|
|
|
function assertStoreValues(values, db) {
|
|
var assertStoreTx = db.createTransaction(['store']);
|
|
assertStoreTx.objectStore('store').getAll().addCallback(function(results) {
|
|
assertSameElements(values, results);
|
|
closeAndContinue(db);
|
|
});
|
|
}
|
|
|
|
function assertStoreDoesntExist(db) {
|
|
try {
|
|
db.createTransaction(['store']);
|
|
fail('Create transaction with a non-existent store should have failed.');
|
|
} catch (e) {
|
|
// expected
|
|
assertEquals(e.code, goog.db.Error.ErrorCode.NOT_FOUND_ERR);
|
|
closeAndContinue(db);
|
|
}
|
|
}
|
|
|
|
function failOnError(err) {
|
|
fail(err.message);
|
|
}
|
|
|
|
function failOnErrorEvent(ev) {
|
|
fail(ev.target.message);
|
|
}
|
|
|
|
function closeAndContinue(db) {
|
|
db.close();
|
|
asyncTestCase.continueTesting();
|
|
}
|
|
|
|
function setUp() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
// Always use a clean database by generating a new database name.
|
|
dbName = dbBaseName + Date.now().toString();
|
|
globalDb = restartDatabase();
|
|
}
|
|
|
|
function testDatabaseOpened() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('check database is open');
|
|
assertNotNull(globalDb);
|
|
globalDb.branch().addCallback(function(db) {
|
|
assertTrue(db.isOpen());
|
|
closeAndContinue(db);
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testSetVersion() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('set version request');
|
|
globalDb.branch().addCallback(function(db) {
|
|
assertEquals(baseVersion, db.getVersion());
|
|
return db.setVersion('version').addCallback(function(tx) {
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
assertEquals('version', db.getVersion());
|
|
closeAndContinue(db);
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testManipulateObjectStores() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('set version and manipulate object stores');
|
|
globalDb.branch().addCallback(function(db) {
|
|
assertEquals(baseVersion, db.getVersion());
|
|
return db.setVersion('objstores').addCallback(function(tx) {
|
|
db.createObjectStore('basicStore');
|
|
db.createObjectStore('keyPathStore', {keyPath: 'keyGoesHere'});
|
|
db.createObjectStore(
|
|
'autoIncrementStore',
|
|
{autoIncrement: true});
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
var storeNames = db.getObjectStoreNames();
|
|
assertEquals(3, storeNames.length);
|
|
assertTrue(storeNames.contains('basicStore'));
|
|
assertTrue(storeNames.contains('keyPathStore'));
|
|
assertTrue(storeNames.contains('autoIncrementStore'));
|
|
assertEquals('objstores', db.getVersion());
|
|
return db.setVersion('delstores').addCallback(function(tx) {
|
|
db.deleteObjectStore('basicStore');
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
var storeNames = db.getObjectStoreNames();
|
|
assertEquals(2, storeNames.length);
|
|
assertFalse(storeNames.contains('basicStore'));
|
|
assertTrue(storeNames.contains('keyPathStore'));
|
|
assertTrue(storeNames.contains('autoIncrementStore'));
|
|
closeAndContinue(db);
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testBadObjectStoreManipulation() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('bad object store manipulation');
|
|
var expectedCode = goog.db.Error.ErrorCode.INVALID_STATE_ERR;
|
|
globalDb.branch().addCallback(function(db) {
|
|
try {
|
|
db.createObjectStore('diediedie');
|
|
fail('Create object store outside transaction should have failed.');
|
|
} catch (err) {
|
|
// expected
|
|
assertEquals(expectedCode, err.code);
|
|
}
|
|
}).addCallback(addStore).addCallback(function(db) {
|
|
try {
|
|
db.deleteObjectStore('store');
|
|
fail('Delete object store outside transaction should have failed.');
|
|
} catch (err) {
|
|
// expected
|
|
assertEquals(expectedCode, err.code);
|
|
}
|
|
}).addCallback(function(db) {
|
|
return db.setVersion('delstore').addCallback(function(tx) {
|
|
try {
|
|
db.deleteObjectStore('diediedie');
|
|
fail('Delete non-existent store should have failed.');
|
|
} catch (err) {
|
|
// expected
|
|
assertEquals(goog.db.Error.ErrorCode.NOT_FOUND_ERR, err.code);
|
|
}
|
|
closeAndContinue(db);
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testGetNonExistentObjectStore() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('get non-existent object store');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
var tx = db.createTransaction(['store']);
|
|
try {
|
|
tx.objectStore('diediedie');
|
|
fail('getting non-existent object store should have failed');
|
|
} catch (err) {
|
|
assertEquals(goog.db.Error.ErrorCode.NOT_FOUND_ERR, err.code);
|
|
}
|
|
closeAndContinue(db);
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testCreateTransaction() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('create transactions');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
var tx = db.createTransaction(['store']);
|
|
assertEquals(
|
|
'mode not READ_ONLY',
|
|
goog.db.Transaction.TransactionMode.READ_ONLY,
|
|
tx.getMode());
|
|
tx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
assertEquals(
|
|
'mode not READ_WRITE',
|
|
goog.db.Transaction.TransactionMode.READ_WRITE,
|
|
tx.getMode());
|
|
closeAndContinue(db);
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testPutRecord() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('putting record');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
var rw = goog.db.Transaction.TransactionMode.READ_WRITE;
|
|
var COMPLETE = goog.db.Transaction.EventTypes.COMPLETE;
|
|
var ERROR = goog.db.Transaction.EventTypes.ERROR;
|
|
|
|
function checkForOverwrittenValue() {
|
|
var checkOverwriteTx = db.createTransaction(['store']);
|
|
checkOverwriteTx.objectStore('store').get('putKey').addCallback(
|
|
function(result) {
|
|
// this is guaranteed to run before the COMPLETE event fires on
|
|
// the transaction
|
|
assertEquals('overwritten', result.key);
|
|
assertEquals('value2', result.value);
|
|
});
|
|
|
|
goog.events.listen(checkOverwriteTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(checkOverwriteTx, COMPLETE, function() {
|
|
closeAndContinue(db);
|
|
});
|
|
}
|
|
|
|
function overwriteValue() {
|
|
var overwriteTx = db.createTransaction(['store'], rw);
|
|
overwriteTx.objectStore('store').put(
|
|
{key: 'overwritten', value: 'value2'},
|
|
'putKey');
|
|
|
|
goog.events.listen(overwriteTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(overwriteTx, COMPLETE, checkForOverwrittenValue);
|
|
}
|
|
|
|
function checkForInitialValue() {
|
|
var checkResultsTx = db.createTransaction(['store']);
|
|
checkResultsTx.objectStore('store').get('putKey').addCallback(
|
|
function(result) {
|
|
assertEquals('initial', result.key);
|
|
assertEquals('value1', result.value);
|
|
});
|
|
goog.events.listen(checkResultsTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(checkResultsTx, COMPLETE, overwriteValue);
|
|
}
|
|
|
|
var initialPutTx = db.createTransaction(['store'], rw);
|
|
initialPutTx.objectStore('store').put(
|
|
{key: 'initial', value: 'value1'},
|
|
'putKey');
|
|
|
|
goog.events.listen(initialPutTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(initialPutTx, COMPLETE, checkForInitialValue);
|
|
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testAddRecord() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('adding record');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
var rw = goog.db.Transaction.TransactionMode.READ_WRITE;
|
|
var COMPLETE = goog.db.Transaction.EventTypes.COMPLETE;
|
|
var ERROR = goog.db.Transaction.EventTypes.ERROR;
|
|
|
|
var initialAddTx = db.createTransaction(['store'], rw);
|
|
initialAddTx.objectStore('store').add(
|
|
{key: 'hi', value: 'something'},
|
|
'stuff');
|
|
|
|
goog.events.listen(initialAddTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(initialAddTx, COMPLETE, function() {
|
|
var successfulAddTx = db.createTransaction(['store']);
|
|
successfulAddTx.objectStore('store').get('stuff').addCallback(
|
|
function(result) {
|
|
assertEquals('hi', result.key);
|
|
assertEquals('something', result.value);
|
|
});
|
|
|
|
goog.events.listen(successfulAddTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(successfulAddTx, COMPLETE, function() {
|
|
var addOverwriteTx = db.createTransaction(['store'], rw);
|
|
addOverwriteTx.objectStore('store').add(
|
|
{key: 'bye', value: 'nothing'},
|
|
'stuff').addErrback(
|
|
function(err) {
|
|
// expected
|
|
assertEquals(
|
|
goog.db.Error.ErrorCode.CONSTRAINT_ERR,
|
|
err.code);
|
|
});
|
|
|
|
goog.events.listen(addOverwriteTx, COMPLETE, function() {
|
|
fail('adding existing record should not have succeeded');
|
|
});
|
|
goog.events.listen(addOverwriteTx, ERROR, function(ev) {
|
|
assertEquals(
|
|
goog.db.Error.ErrorCode.CONSTRAINT_ERR,
|
|
ev.target.code);
|
|
closeAndContinue(db);
|
|
});
|
|
});
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testPutRecordKeyPathStore() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('adding record, key path store');
|
|
globalDb.branch().addCallback(function(db) {
|
|
return db.setVersion('test').addCallback(function(tx) {
|
|
db.createObjectStore('keyStore', {keyPath: 'key'});
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
var COMPLETE = goog.db.Transaction.EventTypes.COMPLETE;
|
|
var ERROR = goog.db.Transaction.EventTypes.ERROR;
|
|
|
|
var putTx = db.createTransaction(
|
|
['keyStore'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
putTx.objectStore('keyStore').put({key: 'hi', value: 'something'});
|
|
|
|
goog.events.listen(putTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(putTx, COMPLETE, function() {
|
|
var checkResultsTx = db.createTransaction(['keyStore']);
|
|
checkResultsTx.objectStore('keyStore').get('hi').addCallback(
|
|
function(result) {
|
|
assertNotUndefined(result);
|
|
assertEquals('hi', result.key);
|
|
assertEquals('something', result.value);
|
|
});
|
|
|
|
goog.events.listen(checkResultsTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(checkResultsTx, COMPLETE, function() {
|
|
closeAndContinue(db);
|
|
});
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testPutBadRecordKeyPathStore() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('adding bad record, key path store');
|
|
globalDb.branch().addCallback(function(db) {
|
|
return db.setVersion('test').addCallback(function(tx) {
|
|
db.createObjectStore('keyStore', {keyPath: 'key'});
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
var badTx = db.createTransaction(
|
|
['keyStore'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
badTx.objectStore('keyStore').put(
|
|
{key: 'diedie', value: 'anything'},
|
|
'badKey').addCallback(function() {
|
|
fail('inserting with explicit key should have failed');
|
|
}).addErrback(function(err) {
|
|
// expected
|
|
assertEquals(goog.db.Error.ErrorCode.DATA_ERR, err.code);
|
|
closeAndContinue(db);
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testPutRecordAutoIncrementStore() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('adding record, auto increment store');
|
|
globalDb.branch().addCallback(function(db) {
|
|
return db.setVersion('test').addCallback(function(tx) {
|
|
db.createObjectStore('aiStore', {autoIncrement: true});
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
var tx = db.createTransaction(
|
|
['aiStore'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
tx.objectStore('aiStore').put('1');
|
|
tx.objectStore('aiStore').put('2');
|
|
tx.objectStore('aiStore').put('3');
|
|
goog.events.listen(
|
|
tx,
|
|
goog.db.Transaction.EventTypes.ERROR,
|
|
failOnErrorEvent);
|
|
|
|
goog.events.listen(tx, goog.db.Transaction.EventTypes.COMPLETE, function() {
|
|
var tx = db.createTransaction(['aiStore']);
|
|
tx.objectStore('aiStore').getAll().addCallback(function(results) {
|
|
assertEquals(3, results.length);
|
|
// only checking to see if the results are included because the keys
|
|
// are not specified
|
|
assertNotEquals(-1, results.indexOf('1'));
|
|
assertNotEquals(-1, results.indexOf('2'));
|
|
assertNotEquals(-1, results.indexOf('3'));
|
|
closeAndContinue(db);
|
|
});
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testPutRecordKeyPathAndAutoIncrementStore() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('adding record, key path + auto increment store');
|
|
globalDb.branch().addCallback(function(db) {
|
|
return db.setVersion('test').addCallback(function(tx) {
|
|
db.createObjectStore('hybridStore', {
|
|
keyPath: 'key',
|
|
autoIncrement: true
|
|
});
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
var tx = db.createTransaction(
|
|
['hybridStore'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
tx.objectStore('hybridStore').put({value: 'whatever'});
|
|
goog.events.listen(
|
|
tx,
|
|
goog.db.Transaction.EventTypes.ERROR,
|
|
failOnErrorEvent);
|
|
|
|
goog.events.listen(tx, goog.db.Transaction.EventTypes.COMPLETE, function() {
|
|
var tx = db.createTransaction(['hybridStore']);
|
|
tx.objectStore('hybridStore').getAll().addCallback(function(results) {
|
|
assertEquals(1, results.length);
|
|
assertEquals('whatever', results[0].value);
|
|
assertNotUndefined(results[0].key);
|
|
closeAndContinue(db);
|
|
});
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testPutIllegalRecords() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('adding illegal records');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
var tx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
|
|
tx.objectStore('store').put('death', null).addCallback(function() {
|
|
fail('putting with null key should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(goog.db.Error.ErrorCode.DATA_ERR, err.code);
|
|
});
|
|
|
|
tx.objectStore('store').put('death', NaN).addCallback(function() {
|
|
fail('putting with NaN key should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(goog.db.Error.ErrorCode.DATA_ERR, err.code);
|
|
});
|
|
|
|
tx.objectStore('store').put('death', undefined).addCallback(function() {
|
|
fail('putting with undefined key should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(goog.db.Error.ErrorCode.DATA_ERR, err.code);
|
|
});
|
|
|
|
closeAndContinue(db);
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testPutIllegalRecordsWithIndex() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('adding illegal records');
|
|
globalDb.branch().addCallback(addStoreWithIndex).addCallback(function(db) {
|
|
var tx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
|
|
tx.objectStore('store').put({key: 'diediedie', value: null}).
|
|
addErrback(function(err) {
|
|
assertEquals(goog.db.Error.ErrorCode.DATA_ERR, err.code);
|
|
});
|
|
|
|
tx.objectStore('store').put({key: 'dietodeath', value: NaN}).
|
|
addErrback(function(err) {
|
|
assertEquals(goog.db.Error.ErrorCode.DATA_ERR, err.code);
|
|
});
|
|
|
|
tx.objectStore('store').put({key: 'dietodeath', value: undefined}).
|
|
addErrback(function(err) {
|
|
assertEquals(goog.db.Error.ErrorCode.DATA_ERR, err.code);
|
|
});
|
|
|
|
closeAndContinue(db);
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testDeleteRecord() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('deleting record');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
var rw = goog.db.Transaction.TransactionMode.READ_WRITE;
|
|
var COMPLETE = goog.db.Transaction.EventTypes.COMPLETE;
|
|
var ERROR = goog.db.Transaction.EventTypes.ERROR;
|
|
var putTx = db.createTransaction(['store'], rw);
|
|
putTx.objectStore('store').put({key: 'hi', value: 'something'}, 'stuff');
|
|
|
|
goog.events.listen(putTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(putTx, COMPLETE, function() {
|
|
var deleteTx = db.createTransaction(['store'], rw);
|
|
deleteTx.objectStore('store').remove('stuff');
|
|
|
|
goog.events.listen(deleteTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(deleteTx, COMPLETE, function() {
|
|
var checkResultsTx = db.createTransaction(['store']);
|
|
checkResultsTx.objectStore('store').get('stuff').addCallback(
|
|
function(result) {
|
|
assertUndefined(result);
|
|
});
|
|
|
|
goog.events.listen(checkResultsTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(checkResultsTx, COMPLETE, function() {
|
|
closeAndContinue(db);
|
|
});
|
|
});
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testGetAll() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
var values = ['1', '2', '3'];
|
|
var keys = ['a', 'b', 'c'];
|
|
|
|
var addData = goog.partial(populateStore, values, keys);
|
|
var checkStore = goog.partial(assertStoreValues, values);
|
|
|
|
asyncTestCase.waitForAsync('getting all');
|
|
globalDb.branch()
|
|
.addCallbacks(addStore, failOnError)
|
|
.addCallback(addData)
|
|
.addCallback(checkStore);
|
|
}
|
|
|
|
function testCursorGet() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
var values = ['1', '2', '3', '4'];
|
|
var keys = ['a', 'b', 'c', 'd'];
|
|
|
|
var addData = goog.partial(populateStore, values, keys);
|
|
|
|
// Open the cursor over range ['b', 'c'], move in backwards direction.
|
|
var openCursorAndCheck = function(db) {
|
|
var cursorTx = db.createTransaction(['store']);
|
|
var store = cursorTx.objectStore('store');
|
|
var d = new goog.async.Deferred();
|
|
var values = [];
|
|
var keys = [];
|
|
var cursor = store.openCursor(
|
|
goog.db.KeyRange.bound('b', 'c'),
|
|
goog.db.Cursor.Direction.PREV);
|
|
|
|
var key = goog.events.listen(
|
|
cursor, goog.db.Cursor.EventType.NEW_DATA, function() {
|
|
values.push(cursor.getValue());
|
|
keys.push(cursor.getKey());
|
|
cursor.next();
|
|
});
|
|
|
|
goog.events.listenOnce(cursor, [
|
|
goog.db.Cursor.EventType.COMPLETE,
|
|
goog.db.Cursor.EventType.ERROR
|
|
], function(evt) {
|
|
goog.events.unlistenByKey(key);
|
|
if (evt.type == goog.db.Cursor.EventType.COMPLETE) {
|
|
d.callback(db);
|
|
} else {
|
|
d.errback();
|
|
}
|
|
});
|
|
|
|
d.addCallback(function(db) {
|
|
assertArrayEquals(['3', '2'], values);
|
|
assertArrayEquals(['c', 'b'], keys);
|
|
closeAndContinue(db);
|
|
});
|
|
};
|
|
|
|
asyncTestCase.waitForAsync('getting range');
|
|
globalDb.branch()
|
|
.addCallbacks(addStore, failOnError)
|
|
.addCallback(addData)
|
|
.addCallback(openCursorAndCheck);
|
|
}
|
|
|
|
function testCursorReplace() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
var values = ['1', '2', '3', '4'];
|
|
var keys = ['a', 'b', 'c', 'd'];
|
|
|
|
var addData = goog.partial(populateStore, values, keys);
|
|
|
|
// Store should contain ['1', '2', '5', '4'] after replacement.
|
|
var checkStore = goog.partial(assertStoreValues, ['1', '2', '5', '4']);
|
|
|
|
// Use a bounded cursor for ('b', 'c'] to update value '3' -> '5'.
|
|
var openCursorAndReplace = function(db) {
|
|
var d = new goog.async.Deferred();
|
|
var cursorTx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
var store = cursorTx.objectStore('store');
|
|
var cursor = store.openCursor(goog.db.KeyRange.bound('b', 'c', true));
|
|
|
|
var key = goog.events.listen(
|
|
cursor, goog.db.Cursor.EventType.NEW_DATA, function() {
|
|
assertEquals('3', cursor.getValue());
|
|
cursor.update('5').addCallback(function() {
|
|
cursor.next();
|
|
}).addErrback(failOnError);
|
|
});
|
|
|
|
goog.events.listenOnce(cursor, [
|
|
goog.db.Cursor.EventType.COMPLETE,
|
|
goog.db.Cursor.EventType.ERROR
|
|
], function(evt) {
|
|
goog.events.unlistenByKey(key);
|
|
if (evt.type == goog.db.Cursor.EventType.COMPLETE) {
|
|
d.callback(db);
|
|
} else {
|
|
d.errback();
|
|
}
|
|
});
|
|
return d;
|
|
};
|
|
|
|
// Setup and execute test case.
|
|
asyncTestCase.waitForAsync('replacing value by cursor');
|
|
globalDb.branch()
|
|
.addCallbacks(addStore, failOnError)
|
|
.addCallback(addData)
|
|
.addCallback(openCursorAndReplace)
|
|
.addCallback(checkStore);
|
|
}
|
|
|
|
function testCursorRemove() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
var values = ['1', '2', '3', '4'];
|
|
var keys = ['a', 'b', 'c', 'd'];
|
|
|
|
var addData = goog.partial(populateStore, values, keys);
|
|
|
|
// Store should contain ['1', '2'] after removing elements.
|
|
var checkStore = goog.partial(assertStoreValues, ['1', '2']);
|
|
|
|
// Use a bounded cursor for ('b', ...) to remove '3', '4'.
|
|
var openCursorAndRemove = function(db) {
|
|
var d = new goog.async.Deferred();
|
|
var cursorTx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
var store = cursorTx.objectStore('store');
|
|
var cursor = store.openCursor(goog.db.KeyRange.lowerBound('b', true));
|
|
|
|
var key = goog.events.listen(
|
|
cursor, goog.db.Cursor.EventType.NEW_DATA, function() {
|
|
cursor.remove('5').addCallback(function() {
|
|
cursor.next();
|
|
}).addErrback(failOnError);
|
|
});
|
|
|
|
goog.events.listenOnce(cursor, [
|
|
goog.db.Cursor.EventType.COMPLETE,
|
|
goog.db.Cursor.EventType.ERROR
|
|
], function(evt) {
|
|
goog.events.unlistenByKey(key);
|
|
if (evt.type == goog.db.Cursor.EventType.COMPLETE) {
|
|
d.callback(db);
|
|
} else {
|
|
d.errback();
|
|
}
|
|
});
|
|
return d;
|
|
};
|
|
|
|
// Setup and execute test case.
|
|
asyncTestCase.waitForAsync('removing value by cursor');
|
|
globalDb.branch()
|
|
.addCallbacks(addStore, failOnError)
|
|
.addCallback(addData)
|
|
.addCallback(openCursorAndRemove)
|
|
.addCallback(checkStore);
|
|
}
|
|
|
|
function testClear() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('clearing');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
var rw = goog.db.Transaction.TransactionMode.READ_WRITE;
|
|
var COMPLETE = goog.db.Transaction.EventTypes.COMPLETE;
|
|
var ERROR = goog.db.Transaction.EventTypes.ERROR;
|
|
|
|
var putTx = db.createTransaction(['store'], rw);
|
|
putTx.objectStore('store').put('1', 'a');
|
|
putTx.objectStore('store').put('2', 'b');
|
|
putTx.objectStore('store').put('3', 'c');
|
|
|
|
goog.events.listen(putTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(putTx, COMPLETE, function() {
|
|
var clearTx = db.createTransaction(['store'], rw);
|
|
clearTx.objectStore('store').clear();
|
|
|
|
goog.events.listen(clearTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(clearTx, COMPLETE, function() {
|
|
var checkResultsTx = db.createTransaction(['store']);
|
|
checkResultsTx.objectStore('store').getAll().addCallback(
|
|
function(results) {
|
|
assertEquals(0, results.length);
|
|
}).addErrback(failOnError);
|
|
|
|
goog.events.listen(checkResultsTx, ERROR, failOnErrorEvent);
|
|
goog.events.listen(checkResultsTx, COMPLETE, function() {
|
|
closeAndContinue(db);
|
|
});
|
|
});
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testAbortTransaction() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('abort transaction');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
var abortTx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
abortTx.objectStore('store').put('data', 'stuff').addCallback(function() {
|
|
abortTx.abort();
|
|
});
|
|
goog.events.listen(
|
|
abortTx,
|
|
goog.db.Transaction.EventTypes.ERROR,
|
|
failOnErrorEvent);
|
|
|
|
goog.events.listen(
|
|
abortTx,
|
|
goog.db.Transaction.EventTypes.COMPLETE,
|
|
function() {
|
|
fail('transaction shouldn\'t have completed after being aborted');
|
|
});
|
|
|
|
goog.events.listen(
|
|
abortTx,
|
|
goog.db.Transaction.EventTypes.ABORT,
|
|
function() {
|
|
var checkResultsTx = db.createTransaction(['store']);
|
|
checkResultsTx.objectStore('store').get('stuff').addCallback(
|
|
function(result) {
|
|
assertUndefined(result);
|
|
});
|
|
goog.events.listen(
|
|
checkResultsTx,
|
|
goog.db.Transaction.EventTypes.COMPLETE,
|
|
function() {
|
|
closeAndContinue(db);
|
|
});
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testInactiveTransaction() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('inactive transaction');
|
|
globalDb.branch().addCallback(addStoreWithIndex).addCallback(function(db) {
|
|
var tx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
var store = tx.objectStore('store');
|
|
var index = store.getIndex('index');
|
|
store.put({key: 'something', value: 'anything'});
|
|
goog.events.listen(tx, goog.db.Transaction.EventTypes.COMPLETE, function() {
|
|
var expectedCode = goog.db.Error.ErrorCode.TRANSACTION_INACTIVE_ERR;
|
|
store.put({
|
|
key: 'another',
|
|
value: 'thing'
|
|
}).addCallback(function() {
|
|
fail('putting with inactive transaction should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
store.add({
|
|
key: 'another',
|
|
value: 'thing'
|
|
}).addCallback(function() {
|
|
fail('adding with inactive transaction should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
store.remove('something').addCallback(function() {
|
|
fail('deleting with inactive transaction should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
store.get('something').addCallback(function() {
|
|
fail('getting with inactive transaction should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
store.getAll().addCallback(function() {
|
|
fail('getting all with inactive transaction should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
store.clear().addCallback(function() {
|
|
fail('clearing all with inactive transaction should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
|
|
index.get('anything').
|
|
addCallback(function() {
|
|
fail('getting from index with inactive transaction should have ' +
|
|
'failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
index.getKey('anything').
|
|
addCallback(function() {
|
|
fail('getting key from index with inactive transaction ' +
|
|
'should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
index.getAll('anything').
|
|
addCallback(function() {
|
|
fail('getting all from index with inactive transaction ' +
|
|
'should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
index.getAllKeys('anything').
|
|
addCallback(function() {
|
|
fail('getting all keys from index with inactive transaction ' +
|
|
'should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(expectedCode, err.code);
|
|
});
|
|
closeAndContinue(db);
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testWrongTransactionMode() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('wrong transaction mode');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
var tx = db.createTransaction(['store']);
|
|
assertEquals(goog.db.Transaction.TransactionMode.READ_ONLY, tx.getMode());
|
|
tx.objectStore('store').put('KABOOM!', 'anything').addCallback(function() {
|
|
fail('putting should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(goog.db.Error.ErrorCode.READ_ONLY_ERR, err.code);
|
|
});
|
|
tx.objectStore('store').add('EXPLODE!', 'die').addCallback(function() {
|
|
fail('adding should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(goog.db.Error.ErrorCode.READ_ONLY_ERR, err.code);
|
|
});
|
|
tx.objectStore('store').remove('no key', 'nothing').addCallback(function() {
|
|
fail('deleting should have failed');
|
|
}).addErrback(function(err) {
|
|
assertEquals(goog.db.Error.ErrorCode.READ_ONLY_ERR, err.code);
|
|
});
|
|
closeAndContinue(db);
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testManipulateIndexes() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('index manipulation');
|
|
globalDb.branch().addCallback(function(db) {
|
|
return db.setVersion('testIndex').addCallback(function(tx) {
|
|
var store = db.createObjectStore('store');
|
|
store.createIndex('index', 'attr1');
|
|
store.createIndex('uniqueIndex', 'attr2', {unique: true});
|
|
store.createIndex('multirowIndex', 'attr3', {multirow: true});
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
return db.setVersion('testDelIndex').addCallback(function(tx) {
|
|
var store = tx.objectStore('store');
|
|
var index = store.getIndex('index');
|
|
var uniqueIndex = store.getIndex('uniqueIndex');
|
|
var multirowIndex = store.getIndex('multirowIndex');
|
|
try {
|
|
var dies = store.getIndex('diediedie');
|
|
fail('getting non-existent index should have failed');
|
|
} catch (err) {
|
|
assertEquals(goog.db.Error.ErrorCode.NOT_FOUND_ERR, err.code);
|
|
}
|
|
store.deleteIndex('index');
|
|
try {
|
|
store.deleteIndex('diediedie');
|
|
fail('deleting non-existent index should have failed');
|
|
} catch (err) {
|
|
assertEquals(goog.db.Error.ErrorCode.NOT_FOUND_ERR, err.code);
|
|
}
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
var tx = db.createTransaction(['store']);
|
|
var store = tx.objectStore('store');
|
|
try {
|
|
var index = store.getIndex('index');
|
|
fail('getting deleted index should have failed');
|
|
} catch (err) {
|
|
assertEquals(goog.db.Error.ErrorCode.NOT_FOUND_ERR, err.code);
|
|
}
|
|
var uniqueIndex = store.getIndex('uniqueIndex');
|
|
var multirowIndex = store.getIndex('multirowIndex');
|
|
}).addCallback(closeAndContinue).addErrback(failOnError);
|
|
}
|
|
|
|
function testAddRecordWithIndex() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('add record with index');
|
|
globalDb.branch().addCallback(addStoreWithIndex).addCallback(function(db) {
|
|
var COMPLETE = goog.db.Transaction.EventTypes.COMPLETE;
|
|
var addTx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
var store = addTx.objectStore('store');
|
|
assertFalse(store.getIndex('index').isUnique());
|
|
assertEquals('value', store.getIndex('index').getKeyPath());
|
|
store.add({key: 'someKey', value: 'lookUpThis'});
|
|
|
|
goog.events.listen(addTx, COMPLETE, function() {
|
|
var checkResultsTx = db.createTransaction(['store']);
|
|
var index = checkResultsTx.objectStore('store').getIndex('index');
|
|
index.get('lookUpThis').addCallback(function(result) {
|
|
assertNotUndefined(result);
|
|
assertEquals('someKey', result.key);
|
|
assertEquals('lookUpThis', result.value);
|
|
});
|
|
index.getKey('lookUpThis').addCallback(function(result) {
|
|
assertNotUndefined(result);
|
|
assertEquals('someKey', result);
|
|
});
|
|
goog.events.listen(
|
|
checkResultsTx,
|
|
goog.db.Transaction.EventTypes.ERROR,
|
|
failOnErrorEvent);
|
|
goog.events.listen(checkResultsTx, COMPLETE, function() {
|
|
closeAndContinue(db);
|
|
});
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testGetMultipleRecordsFromIndex() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('get multiple records from index');
|
|
globalDb.branch().addCallback(addStoreWithIndex).addCallback(function(db) {
|
|
var COMPLETE = goog.db.Transaction.EventTypes.COMPLETE;
|
|
var addTx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
addTx.objectStore('store').add({key: '1', value: 'a'});
|
|
addTx.objectStore('store').add({key: '2', value: 'a'});
|
|
addTx.objectStore('store').add({key: '3', value: 'b'});
|
|
// The following line breaks Chrome 14, but not Chrome 15:
|
|
// addTx.objectStore('store').add({key: '4'});
|
|
goog.events.listen(
|
|
addTx,
|
|
goog.db.Transaction.EventTypes.ERROR,
|
|
failOnErrorEvent);
|
|
|
|
goog.events.listen(addTx, COMPLETE, function() {
|
|
var checkResultsTx = db.createTransaction(['store']);
|
|
var index = checkResultsTx.objectStore('store').getIndex('index');
|
|
index.getAll().addCallback(function(results) {
|
|
assertNotUndefined(results);
|
|
assertEquals(3, results.length);
|
|
});
|
|
index.getAll('a').addCallback(function(results) {
|
|
assertNotUndefined(results);
|
|
assertEquals(2, results.length);
|
|
});
|
|
index.getAllKeys().addCallback(function(results) {
|
|
assertNotUndefined(results);
|
|
assertEquals(3, results.length);
|
|
});
|
|
index.getAllKeys('b').addCallback(function(results) {
|
|
assertNotUndefined(results);
|
|
assertEquals(1, results.length);
|
|
});
|
|
|
|
goog.events.listen(
|
|
checkResultsTx,
|
|
goog.db.Transaction.EventTypes.ERROR,
|
|
failOnErrorEvent);
|
|
goog.events.listen(checkResultsTx, COMPLETE, function() {
|
|
closeAndContinue(db);
|
|
});
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testUniqueIndex() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('adding to unique index');
|
|
globalDb.branch().addCallback(function(db) {
|
|
return db.setVersion('test').addCallback(function(tx) {
|
|
var store = db.createObjectStore('store', {keyPath: 'key'});
|
|
store.createIndex('index', 'value', {unique: true});
|
|
return restartDatabase(db);
|
|
});
|
|
}).addCallback(function(db) {
|
|
var tx = db.createTransaction(
|
|
['store'],
|
|
goog.db.Transaction.TransactionMode.READ_WRITE);
|
|
assertTrue(tx.objectStore('store').getIndex('index').isUnique());
|
|
tx.objectStore('store').add({key: '1', value: 'a'});
|
|
tx.objectStore('store').add({key: '2', value: 'a'});
|
|
goog.events.listen(tx, goog.db.Transaction.EventTypes.ERROR, function(ev) {
|
|
// expected
|
|
assertTrue(
|
|
'Expected DATA_ERR, CONSTRAINT_ERR or UNKNOWN_ERR, was ' +
|
|
ev.target.code,
|
|
// Chrome 15-21, 23+
|
|
ev.target.code == goog.db.Error.ErrorCode.CONSTRAINT_ERR ||
|
|
// Chrome 22
|
|
ev.target.code == goog.db.Error.ErrorCode.DATA_ERR ||
|
|
// Chrome 14
|
|
ev.target.code == goog.db.Error.ErrorCode.UNKNOWN_ERR);
|
|
closeAndContinue(db);
|
|
});
|
|
}).addErrback(failOnError);
|
|
}
|
|
|
|
function testDeleteDatabase() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
asyncTestCase.waitForAsync('deleting database');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
db.close();
|
|
return goog.db.deleteDatabase(dbName, function() {
|
|
fail('didn\'t expect deleteDatabase to be blocked');
|
|
});
|
|
}).addCallback(function() {
|
|
return restartDatabase();
|
|
}).addCallback(assertStoreDoesntExist).addErrback(failOnError);
|
|
}
|
|
|
|
function testDeleteDatabaseIsBlocked() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
var wasBlocked = false;
|
|
asyncTestCase.waitForAsync('deleting database (blocked)');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
db.close();
|
|
// Get a fresh connection, without any events registered on globalDb.
|
|
return goog.db.openDatabase(dbName);
|
|
}).addCallback(function(db) {
|
|
return goog.db.deleteDatabase(dbName, function(ev) {
|
|
wasBlocked = true;
|
|
db.close();
|
|
});
|
|
}).addCallback(function() {
|
|
assertTrue(wasBlocked);
|
|
return restartDatabase();
|
|
}).addCallback(assertStoreDoesntExist).addErrback(failOnError);
|
|
}
|
|
|
|
function testBlockedDeleteDatabaseWithVersionChangeEvent() {
|
|
if (!idbSupported) {
|
|
return;
|
|
}
|
|
|
|
var gotVersionChange = false;
|
|
asyncTestCase.waitForAsync('deleting database (blocked)');
|
|
globalDb.branch().addCallback(addStore).addCallback(function(db) {
|
|
db.close();
|
|
// Get a fresh connection, without any events registered on globalDb.
|
|
return goog.db.openDatabase(dbName);
|
|
}).addCallback(function(db) {
|
|
goog.events.listen(
|
|
db, goog.db.IndexedDb.EventType.VERSION_CHANGE, function(ev) {
|
|
gotVersionChange = true;
|
|
db.close();
|
|
});
|
|
return goog.db.deleteDatabase(dbName);
|
|
}).addCallback(function() {
|
|
assertTrue(gotVersionChange);
|
|
return restartDatabase();
|
|
}).addCallback(assertStoreDoesntExist);
|
|
}
|