summaryrefslogtreecommitdiffstats
path: root/dom/indexedDB/test/unit/test_transaction_abort.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/indexedDB/test/unit/test_transaction_abort.js')
-rw-r--r--dom/indexedDB/test/unit/test_transaction_abort.js384
1 files changed, 384 insertions, 0 deletions
diff --git a/dom/indexedDB/test/unit/test_transaction_abort.js b/dom/indexedDB/test/unit/test_transaction_abort.js
new file mode 100644
index 000000000..0f051f968
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_transaction_abort.js
@@ -0,0 +1,384 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var testGenerator = testSteps();
+
+var abortFired = false;
+
+function abortListener(evt)
+{
+ abortFired = true;
+ is(evt.target.error, null, "Expect a null error for an aborted transaction");
+}
+
+function testSteps()
+{
+ const name = this.window ? window.location.pathname : "Splendid Test";
+
+ let request = indexedDB.open(name, 1);
+ request.onerror = errorHandler;
+ request.onupgradeneeded = grabEventAndContinueHandler;
+ request.onsuccess = grabEventAndContinueHandler;
+ let event = yield undefined;
+
+ let db = event.target.result;
+ db.onabort = abortListener;
+
+ let transaction;
+ let objectStore;
+ let index;
+
+ transaction = event.target.transaction;
+
+ is(transaction.error, null, "Expect a null error");
+
+ objectStore = db.createObjectStore("foo", { autoIncrement: true });
+ index = objectStore.createIndex("fooindex", "indexKey", { unique: true });
+
+ is(transaction.db, db, "Correct database");
+ is(transaction.mode, "versionchange", "Correct mode");
+ is(transaction.objectStoreNames.length, 1, "Correct names length");
+ is(transaction.objectStoreNames.item(0), "foo", "Correct name");
+ is(transaction.objectStore("foo"), objectStore, "Can get stores");
+ is(transaction.oncomplete, null, "No complete listener");
+ is(transaction.onabort, null, "No abort listener");
+
+ is(objectStore.name, "foo", "Correct name");
+ is(objectStore.keyPath, null, "Correct keyPath");
+
+ is(objectStore.indexNames.length, 1, "Correct indexNames length");
+ is(objectStore.indexNames[0], "fooindex", "Correct indexNames name");
+ is(objectStore.index("fooindex"), index, "Can get index");
+
+ // Wait until it's complete!
+ transaction.oncomplete = grabEventAndContinueHandler;
+ event = yield undefined;
+
+ is(transaction.db, db, "Correct database");
+ is(transaction.mode, "versionchange", "Correct mode");
+ is(transaction.objectStoreNames.length, 1, "Correct names length");
+ is(transaction.objectStoreNames.item(0), "foo", "Correct name");
+ is(transaction.onabort, null, "No abort 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, null, "Correct keyPath");
+
+ is(objectStore.indexNames.length, 1, "Correct indexNames length");
+ is(objectStore.indexNames[0], "fooindex", "Correct indexNames name");
+
+ try {
+ objectStore.add({});
+ ok(false, "Should have thrown");
+ }
+ catch (e) {
+ ok(true, "Add threw");
+ }
+
+ try {
+ objectStore.put({}, 1);
+ ok(false, "Should have thrown");
+ }
+ catch (e) {
+ ok(true, "Put threw");
+ }
+
+ try {
+ objectStore.put({}, 1);
+ ok(false, "Should have thrown");
+ }
+ catch (e) {
+ ok(true, "Put threw");
+ }
+
+ try {
+ objectStore.delete(1);
+ 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 {
+ objectStore.deleteIndex("bar");
+ ok(false, "Should have thrown");
+ }
+ catch (e) {
+ ok(true, "RemoveIndex threw");
+ }
+
+ yield undefined;
+
+ request = db.transaction("foo", "readwrite").objectStore("foo").add({});
+ request.onerror = errorHandler;
+ request.onsuccess = grabEventAndContinueHandler;
+ event = yield undefined;
+
+ event.target.transaction.onabort = function(event) {
+ ok(false, "Shouldn't see an abort event!");
+ };
+ event.target.transaction.oncomplete = grabEventAndContinueHandler;
+ event = yield undefined;
+
+ is(event.type, "complete", "Right kind of event");
+
+ let key;
+
+ request = db.transaction("foo", "readwrite").objectStore("foo").add({});
+ request.onerror = errorHandler;
+ request.onsuccess = grabEventAndContinueHandler;
+ event = yield undefined;
+
+ key = event.target.result;
+
+ event.target.transaction.onabort = grabEventAndContinueHandler;
+ event.target.transaction.oncomplete = function(event) {
+ ok(false, "Shouldn't see a complete event here!");
+ };
+
+ event.target.transaction.abort();
+
+ event = yield undefined;
+
+ is(event.type, "abort", "Right kind of event");
+
+ request = db.transaction("foo").objectStore("foo").get(key);
+ request.onerror = errorHandler;
+ request.onsuccess = grabEventAndContinueHandler;
+ event = yield undefined;
+
+ is(event.target.result, undefined, "Object was removed");
+
+ executeSoon(function() { testGenerator.next(); });
+ yield undefined;
+
+ let keys = [];
+ let abortEventCount = 0;
+ function abortErrorHandler(event) {
+ is(event.target.error.name, "AbortError",
+ "Good error");
+ abortEventCount++;
+ event.preventDefault();
+ };
+ objectStore = db.transaction("foo", "readwrite").objectStore("foo");
+
+ for (let i = 0; i < 10; i++) {
+ request = objectStore.add({});
+ request.onerror = abortErrorHandler;
+ request.onsuccess = function(event) {
+ keys.push(event.target.result);
+ if (keys.length == 5) {
+ event.target.transaction.onabort = grabEventAndContinueHandler;
+ event.target.transaction.abort();
+ }
+ };
+ }
+ event = yield undefined;
+
+ 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");
+
+ for (let i in keys) {
+ request = db.transaction("foo").objectStore("foo").get(keys[i]);
+ request.onerror = errorHandler;
+ request.onsuccess = grabEventAndContinueHandler;
+ event = yield undefined;
+
+ is(event.target.result, undefined, "Object was removed by abort");
+ }
+
+ // Set up some predictible data
+ transaction = db.transaction("foo", "readwrite");
+ 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 undefined;
+
+ // Check when aborting is allowed
+ abortEventCount = 0;
+ let expectedAbortEventCount = 0;
+
+ // During INITIAL
+ transaction = db.transaction("foo");
+ transaction.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++;
+ transaction.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 undefined;
+ transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
+ expectedAbortEventCount++
+ transaction.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", "readwrite");
+ transaction.objectStore("foo").add({}, 1).onerror = function(event) {
+ event.preventDefault();
+
+ transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
+ expectedAbortEventCount++
+
+ transaction.abort();
+ continueToNextStep();
+ }
+ yield undefined;
+
+ // 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) {
+ executeSoon(function() {
+ transaction.abort();
+ expectedAbortEventCount++;
+ continueToNextStep();
+ });
+ };
+ yield undefined;
+
+ // During COMMITTING
+ transaction = db.transaction("foo", "readwrite");
+ transaction.objectStore("foo").put({hello: "world"}, 1).onsuccess = function(event) {
+ continueToNextStep();
+ };
+ yield undefined;
+ 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 undefined;
+
+ // 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");
+
+ // Abort both failing and succeeding requests
+ transaction = db.transaction("foo", "readwrite");
+ transaction.onabort = transaction.oncomplete = grabEventAndContinueHandler;
+ transaction.objectStore("foo").add({indexKey: "key"}).onsuccess = function(event) {
+ transaction.abort();
+ };
+ let request1 = transaction.objectStore("foo").add({indexKey: "key"});
+ request1.onsuccess = grabEventAndContinueHandler;
+ request1.onerror = grabEventAndContinueHandler;
+ let request2 = transaction.objectStore("foo").get(1);
+ request2.onsuccess = grabEventAndContinueHandler;
+ request2.onerror = grabEventAndContinueHandler;
+
+ event = yield undefined;
+ is(event.type, "error", "abort() should make all requests fail");
+ is(event.target, request1, "abort() should make all requests fail");
+ is(event.target.error.name, "AbortError", "abort() should make all requests fail");
+ event.preventDefault();
+
+ event = yield undefined;
+ is(event.type, "error", "abort() should make all requests fail");
+ is(event.target, request2, "abort() should make all requests fail");
+ is(event.target.error.name, "AbortError", "abort() should make all requests fail");
+ event.preventDefault();
+
+ event = yield undefined;
+ is(event.type, "abort", "transaction should fail");
+ is(event.target, transaction, "transaction should fail");
+
+ ok(abortFired, "Abort should have fired!");
+
+ finishTest();
+ yield undefined;
+}