2010-06-23 12:46:08 -07:00
|
|
|
<!--
|
|
|
|
Any copyright is dedicated to the Public Domain.
|
|
|
|
http://creativecommons.org/publicdomain/zero/1.0/
|
|
|
|
-->
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>Indexed Database Property Test</title>
|
|
|
|
|
|
|
|
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
|
|
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
|
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
|
|
|
|
|
|
|
<script type="text/javascript;version=1.7">
|
|
|
|
function testSteps()
|
|
|
|
{
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
|
2011-01-27 13:47:35 -08:00
|
|
|
const INITIAL = Ci.nsIIDBTransaction.INITIAL;
|
2010-06-23 12:46:08 -07:00
|
|
|
const LOADING = Ci.nsIIDBTransaction.LOADING;
|
2011-01-27 13:47:35 -08:00
|
|
|
const COMMITTING = Ci.nsIIDBTransaction.COMMITTING;
|
2010-06-23 12:46:08 -07:00
|
|
|
const DONE = Ci.nsIIDBTransaction.DONE;
|
|
|
|
const READ_ONLY = Ci.nsIIDBTransaction.READ_ONLY;
|
|
|
|
const READ_WRITE = Ci.nsIIDBTransaction.READ_WRITE;
|
2010-10-19 10:58:52 -07:00
|
|
|
const VERSION_CHANGE = Ci.nsIIDBTransaction.VERSION_CHANGE;
|
2010-06-23 12:46:08 -07:00
|
|
|
|
|
|
|
const name = window.location.pathname;
|
|
|
|
const description = "My Test Database";
|
|
|
|
|
|
|
|
|
2011-01-03 12:03:06 -08:00
|
|
|
let request = mozIndexedDB.open(name, description);
|
2010-06-23 12:46:08 -07:00
|
|
|
request.onerror = errorHandler;
|
|
|
|
request.onsuccess = grabEventAndContinueHandler;
|
|
|
|
let event = yield;
|
|
|
|
|
2011-01-06 22:21:36 -08:00
|
|
|
let db = event.target.result;
|
2010-06-23 12:46:08 -07:00
|
|
|
|
|
|
|
let transaction;
|
|
|
|
let objectStore;
|
|
|
|
|
2010-10-19 10:58:52 -07:00
|
|
|
request = db.setVersion("1");
|
2010-06-23 12:46:08 -07:00
|
|
|
request.onerror = errorHandler;
|
|
|
|
request.onsuccess = grabEventAndContinueHandler;
|
|
|
|
event = yield;
|
|
|
|
|
2011-01-06 22:21:36 -08:00
|
|
|
transaction = event.target.transaction;
|
2010-12-21 08:02:01 -08:00
|
|
|
objectStore = db.createObjectStore("foo", { autoIncrement: true });
|
2010-06-23 12:46:08 -07:00
|
|
|
|
|
|
|
is(transaction.db, db, "Correct database");
|
|
|
|
is(transaction.readyState, LOADING, "Correct readyState");
|
2010-10-19 10:58:52 -07:00
|
|
|
is(transaction.mode, VERSION_CHANGE, "Correct mode");
|
2010-06-23 12:46:08 -07:00
|
|
|
is(transaction.objectStoreNames.length, 1, "Correct names length");
|
|
|
|
is(transaction.objectStoreNames.item(0), "foo", "Correct name");
|
2011-01-27 13:47:35 -08:00
|
|
|
is(transaction.objectStore("foo"), objectStore, "Can get stores");
|
2010-06-23 12:46:08 -07:00
|
|
|
is(transaction.oncomplete, null, "No complete listener");
|
|
|
|
is(transaction.onabort, null, "No abort listener");
|
|
|
|
is(transaction.ontimeout, null, "No timeout listener");
|
|
|
|
|
|
|
|
is(objectStore.name, "foo", "Correct name");
|
|
|
|
is(objectStore.keyPath, "", "Correct keyPath");
|
|
|
|
is(objectStore.indexNames.length, 0, "Correct indexNames");
|
|
|
|
|
2010-10-19 18:32:05 -07:00
|
|
|
// Wait until it's complete!
|
2010-10-19 17:46:37 -07:00
|
|
|
transaction.oncomplete = grabEventAndContinueHandler;
|
|
|
|
event = yield;
|
2010-06-23 12:46:08 -07:00
|
|
|
|
|
|
|
is(transaction.db, db, "Correct database");
|
|
|
|
is(transaction.readyState, DONE, "Correct readyState");
|
2010-10-19 10:58:52 -07:00
|
|
|
is(transaction.mode, VERSION_CHANGE, "Correct mode");
|
2010-06-23 12:46:08 -07:00
|
|
|
is(transaction.objectStoreNames.length, 1, "Correct names length");
|
|
|
|
is(transaction.objectStoreNames.item(0), "foo", "Correct name");
|
|
|
|
is(transaction.onabort, null, "No abort listener");
|
|
|
|
is(transaction.ontimeout, null, "No timeout listener");
|
|
|
|
|
|
|
|
try {
|
|
|
|
is(transaction.objectStore("foo").name, "foo", "Can't get stores");
|
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
ok(true, "Out of scope transaction can't make stores");
|
|
|
|
}
|
|
|
|
|
|
|
|
is(objectStore.name, "foo", "Correct name");
|
|
|
|
is(objectStore.keyPath, "", "Correct keyPath");
|
|
|
|
is(objectStore.indexNames.length, 0, "Correct indexNames");
|
|
|
|
|
|
|
|
try {
|
|
|
|
objectStore.add({});
|
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
ok(true, "Add threw");
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2010-08-26 13:57:28 -07:00
|
|
|
objectStore.put({}, 1);
|
2010-06-23 12:46:08 -07:00
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
2010-08-26 13:57:28 -07:00
|
|
|
ok(true, "Put threw");
|
2010-06-23 12:46:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2010-08-26 13:57:28 -07:00
|
|
|
objectStore.put({}, 1);
|
2010-06-23 12:46:08 -07:00
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
2010-08-26 13:57:28 -07:00
|
|
|
ok(true, "Put threw");
|
2010-06-23 12:46:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2010-11-10 15:25:57 -08:00
|
|
|
objectStore.delete(1);
|
2010-06-23 12:46:08 -07:00
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
ok(true, "Remove threw");
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
objectStore.get(1);
|
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
ok(true, "Get threw");
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
objectStore.getAll(null);
|
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
ok(true, "GetAll threw");
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
objectStore.openCursor();
|
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
ok(true, "OpenCursor threw");
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
objectStore.createIndex("bar", "id");
|
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
ok(true, "CreateIndex threw");
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
objectStore.index("bar");
|
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
ok(true, "Index threw");
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2010-11-10 15:25:57 -08:00
|
|
|
objectStore.deleteIndex("bar");
|
2010-06-23 12:46:08 -07:00
|
|
|
ok(false, "Should have thrown");
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
ok(true, "RemoveIndex threw");
|
|
|
|
}
|
|
|
|
|
2010-10-19 10:58:49 -07:00
|
|
|
request = db.transaction("foo", READ_WRITE).objectStore("foo").add({});
|
2010-06-23 12:46:08 -07:00
|
|
|
request.onerror = errorHandler;
|
|
|
|
request.onsuccess = grabEventAndContinueHandler;
|
|
|
|
event = yield;
|
|
|
|
|
2011-01-06 22:21:36 -08:00
|
|
|
event.target.transaction.onabort = function(event) {
|
2010-06-23 12:46:08 -07:00
|
|
|
ok(false, "Shouldn't see an abort event!");
|
|
|
|
};
|
2011-01-06 22:21:36 -08:00
|
|
|
event.target.transaction.oncomplete = grabEventAndContinueHandler;
|
2010-06-23 12:46:08 -07:00
|
|
|
event = yield;
|
|
|
|
|
|
|
|
is(event.type, "complete", "Right kind of event");
|
|
|
|
|
|
|
|
let key;
|
|
|
|
|
2010-10-19 10:58:49 -07:00
|
|
|
request = db.transaction("foo", READ_WRITE).objectStore("foo").add({});
|
2010-06-23 12:46:08 -07:00
|
|
|
request.onerror = errorHandler;
|
|
|
|
request.onsuccess = grabEventAndContinueHandler;
|
|
|
|
event = yield;
|
|
|
|
|
2011-01-06 22:21:36 -08:00
|
|
|
key = event.target.result;
|
2010-06-23 12:46:08 -07:00
|
|
|
|
2011-01-06 22:21:36 -08:00
|
|
|
event.target.transaction.onabort = grabEventAndContinueHandler;
|
|
|
|
event.target.transaction.oncomplete = function(event) {
|
2010-06-23 12:46:08 -07:00
|
|
|
ok(false, "Shouldn't see a complete event here!");
|
|
|
|
};
|
|
|
|
|
2011-01-06 22:21:36 -08:00
|
|
|
is(event.target.transaction.readyState, LOADING, "Correct readyState");
|
|
|
|
event.target.transaction.abort();
|
|
|
|
is(event.target.transaction.readyState, DONE, "Correct readyState");
|
2010-06-23 12:46:08 -07:00
|
|
|
|
|
|
|
event = yield;
|
|
|
|
|
|
|
|
is(event.type, "abort", "Right kind of event");
|
|
|
|
|
2010-10-19 10:58:49 -07:00
|
|
|
request = db.transaction("foo").objectStore("foo").get(key);
|
2010-12-15 13:21:09 -08:00
|
|
|
request.onerror = errorHandler;
|
|
|
|
request.onsuccess = grabEventAndContinueHandler;
|
2010-06-23 12:46:08 -07:00
|
|
|
event = yield;
|
|
|
|
|
2011-01-06 22:21:36 -08:00
|
|
|
is(event.target.result, undefined, "Object was removed");
|
2010-12-15 13:21:09 -08:00
|
|
|
|
2010-06-23 12:46:08 -07:00
|
|
|
SimpleTest.executeSoon(function() { testGenerator.next(); });
|
|
|
|
yield;
|
|
|
|
|
|
|
|
let keys = [];
|
2010-12-15 13:21:17 -08:00
|
|
|
let abortEventCount = 0;
|
2011-01-27 13:47:35 -08:00
|
|
|
function abortErrorHandler(event) {
|
2011-01-06 22:21:36 -08:00
|
|
|
is(event.target.errorCode, IDBDatabaseException.ABORT_ERR,
|
|
|
|
"Good code");
|
2010-12-15 13:21:17 -08:00
|
|
|
abortEventCount++;
|
|
|
|
event.preventDefault();
|
2011-01-27 13:47:35 -08:00
|
|
|
};
|
|
|
|
objectStore = db.transaction("foo", READ_WRITE).objectStore("foo");
|
|
|
|
|
|
|
|
for (let i = 0; i < 10; i++) {
|
|
|
|
request = objectStore.add({});
|
|
|
|
request.onerror = abortErrorHandler;
|
2010-06-23 12:46:08 -07:00
|
|
|
request.onsuccess = function(event) {
|
2011-01-06 22:21:36 -08:00
|
|
|
keys.push(event.target.result);
|
2010-06-23 12:46:08 -07:00
|
|
|
if (keys.length == 5) {
|
2011-01-06 22:21:36 -08:00
|
|
|
event.target.transaction.onabort = grabEventAndContinueHandler;
|
|
|
|
event.target.transaction.abort();
|
2010-06-23 12:46:08 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
event = yield;
|
|
|
|
|
2010-12-15 13:21:17 -08:00
|
|
|
is(event.type, "abort", "Got abort event");
|
|
|
|
is(keys.length, 5, "Added 5 items in this transaction");
|
|
|
|
is(abortEventCount, 5, "Got 5 abort error events");
|
2010-06-23 12:46:08 -07:00
|
|
|
|
2010-12-15 13:21:17 -08:00
|
|
|
for (let i in keys) {
|
2010-10-19 10:58:49 -07:00
|
|
|
request = db.transaction("foo").objectStore("foo").get(keys[i]);
|
2010-12-15 13:21:09 -08:00
|
|
|
request.onerror = errorHandler;
|
|
|
|
request.onsuccess = grabEventAndContinueHandler;
|
2010-06-23 12:46:08 -07:00
|
|
|
event = yield;
|
2010-12-15 13:21:09 -08:00
|
|
|
|
2011-01-06 22:21:36 -08:00
|
|
|
is(event.target.result, undefined, "Object was removed by abort");
|
2010-06-23 12:46:08 -07:00
|
|
|
}
|
|
|
|
|
2011-01-27 13:47:35 -08:00
|
|
|
// Set up some predictible data
|
|
|
|
transaction = db.transaction("foo", READ_WRITE);
|
|
|
|
objectStore = transaction.objectStore("foo");
|
|
|
|
objectStore.clear();
|
|
|
|
objectStore.add({}, 1);
|
|
|
|
objectStore.add({}, 2);
|
|
|
|
request = objectStore.add({}, 1);
|
|
|
|
request.onsuccess = function() {
|
|
|
|
ok(false, "inserting duplicate key should fail");
|
|
|
|
}
|
|
|
|
request.onerror = function(event) {
|
|
|
|
ok(true, "inserting duplicate key should fail");
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
transaction.oncomplete = grabEventAndContinueHandler;
|
|
|
|
yield;
|
|
|
|
|
|
|
|
// Check when aborting is allowed
|
|
|
|
abortEventCount = 0;
|
|
|
|
let expectedAbortEventCount = 0;
|
|
|
|
|
|
|
|
// During INITIAL
|
|
|
|
transaction = db.transaction("foo");
|
|
|
|
is(transaction.readyState, INITIAL, "in INITIAL state");
|
|
|
|
transaction.abort();
|
|
|
|
is(transaction.readyState, DONE, "in DONE state after abort()");
|
|
|
|
try {
|
|
|
|
transaction.abort();
|
|
|
|
ok(false, "second abort should throw an error");
|
|
|
|
}
|
|
|
|
catch (ex) {
|
|
|
|
ok(true, "second abort should throw an error");
|
|
|
|
}
|
|
|
|
|
|
|
|
// During LOADING
|
|
|
|
transaction = db.transaction("foo");
|
|
|
|
transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
|
|
|
|
expectedAbortEventCount++;
|
|
|
|
is(transaction.readyState, LOADING, "in LOADING state");
|
|
|
|
transaction.abort();
|
|
|
|
is(transaction.readyState, DONE, "in DONE state after abort()");
|
|
|
|
try {
|
|
|
|
transaction.abort();
|
|
|
|
ok(false, "second abort should throw an error");
|
|
|
|
}
|
|
|
|
catch (ex) {
|
|
|
|
ok(true, "second abort should throw an error");
|
|
|
|
}
|
|
|
|
|
|
|
|
// During LOADING from callback
|
|
|
|
transaction = db.transaction("foo");
|
|
|
|
transaction.objectStore("foo").get(1).onsuccess = grabEventAndContinueHandler;
|
|
|
|
event = yield;
|
|
|
|
transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
|
|
|
|
expectedAbortEventCount++
|
|
|
|
is(transaction.readyState, LOADING, "in LOADING state");
|
|
|
|
transaction.abort();
|
|
|
|
is(transaction.readyState, DONE, "in DONE state after abort()");
|
|
|
|
try {
|
|
|
|
transaction.abort();
|
|
|
|
ok(false, "second abort should throw an error");
|
|
|
|
}
|
|
|
|
catch (ex) {
|
|
|
|
ok(true, "second abort should throw an error");
|
|
|
|
}
|
|
|
|
|
|
|
|
// During LOADING from error callback
|
|
|
|
transaction = db.transaction("foo", READ_WRITE);
|
|
|
|
transaction.objectStore("foo").add({}, 1).onerror = function(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
|
|
|
|
expectedAbortEventCount++
|
|
|
|
|
|
|
|
is(transaction.readyState, LOADING, "in LOADING state");
|
|
|
|
transaction.abort();
|
|
|
|
is(transaction.readyState, DONE, "in DONE state after abort()");
|
|
|
|
continueToNextStep();
|
|
|
|
}
|
|
|
|
yield;
|
|
|
|
|
|
|
|
// In between callbacks
|
|
|
|
transaction = db.transaction("foo");
|
|
|
|
function makeNewRequest() {
|
|
|
|
let r = transaction.objectStore("foo").get(1);
|
|
|
|
r.onsuccess = makeNewRequest;
|
|
|
|
r.onerror = abortErrorHandler;
|
|
|
|
}
|
|
|
|
makeNewRequest();
|
|
|
|
transaction.objectStore("foo").get(1).onsuccess = function(event) {
|
|
|
|
SimpleTest.executeSoon(function() {
|
|
|
|
is(transaction.readyState, LOADING, "in LOADING state");
|
|
|
|
transaction.abort();
|
|
|
|
expectedAbortEventCount++;
|
|
|
|
is(transaction.readyState, DONE, "in DONE state after abort()");
|
|
|
|
continueToNextStep();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
yield;
|
|
|
|
|
|
|
|
// During COMMITTING
|
|
|
|
transaction = db.transaction("foo", READ_WRITE);
|
|
|
|
transaction.objectStore("foo").put({hello: "world"}, 1).onsuccess = function(event) {
|
|
|
|
continueToNextStep();
|
|
|
|
};
|
|
|
|
yield;
|
|
|
|
is(transaction.readyState, COMMITTING, "in COMMITTING state");
|
|
|
|
try {
|
|
|
|
transaction.abort();
|
|
|
|
ok(false, "second abort should throw an error");
|
|
|
|
}
|
|
|
|
catch (ex) {
|
|
|
|
ok(true, "second abort should throw an error");
|
|
|
|
}
|
|
|
|
transaction.oncomplete = grabEventAndContinueHandler;
|
|
|
|
event = yield;
|
|
|
|
is(transaction.readyState, DONE, "in DONE state");
|
|
|
|
|
|
|
|
// Since the previous transaction shouldn't have caused any error events,
|
|
|
|
// we know that all events should have fired by now.
|
|
|
|
is(abortEventCount, expectedAbortEventCount,
|
|
|
|
"All abort errors fired");
|
|
|
|
|
2010-06-23 12:46:08 -07:00
|
|
|
finishTest();
|
|
|
|
yield;
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
<body onload="runTest();"></body>
|
|
|
|
|
|
|
|
</html>
|