Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /**
2 * Any copyright is dedicated to the Public Domain.
3 * http://creativecommons.org/publicdomain/zero/1.0/
4 */
6 var testGenerator = testSteps();
8 var abortFired = false;
10 function abortListener(evt)
11 {
12 abortFired = true;
13 is(evt.target.error, null, "Expect a null error for an aborted transaction");
14 }
16 function testSteps()
17 {
18 const Ci = Components.interfaces;
20 const name = this.window ? window.location.pathname : "Splendid Test";
22 let request = indexedDB.open(name, 1);
23 request.onerror = errorHandler;
24 request.onupgradeneeded = grabEventAndContinueHandler;
25 request.onsuccess = grabEventAndContinueHandler;
26 let event = yield undefined;
28 let db = event.target.result;
29 db.onabort = abortListener;
31 let transaction;
32 let objectStore;
33 let index;
35 transaction = event.target.transaction;
37 try {
38 let error = transaction.error;
39 ok(false, "Expect an exception");
40 } catch(e) {
41 ok(true, "Got an exception.");
42 is(e.name, "InvalidStateError", "Got the right exception");
43 }
45 objectStore = db.createObjectStore("foo", { autoIncrement: true });
46 index = objectStore.createIndex("fooindex", "indexKey", { unique: true });
48 is(transaction.db, db, "Correct database");
49 is(transaction.mode, "versionchange", "Correct mode");
50 is(transaction.objectStoreNames.length, 1, "Correct names length");
51 is(transaction.objectStoreNames.item(0), "foo", "Correct name");
52 is(transaction.objectStore("foo"), objectStore, "Can get stores");
53 is(transaction.oncomplete, null, "No complete listener");
54 is(transaction.onabort, null, "No abort listener");
56 is(objectStore.name, "foo", "Correct name");
57 is(objectStore.keyPath, null, "Correct keyPath");
59 is(objectStore.indexNames.length, 1, "Correct indexNames length");
60 is(objectStore.indexNames[0], "fooindex", "Correct indexNames name");
61 is(objectStore.index("fooindex"), index, "Can get index");
63 // Wait until it's complete!
64 transaction.oncomplete = grabEventAndContinueHandler;
65 event = yield undefined;
67 is(transaction.db, db, "Correct database");
68 is(transaction.mode, "versionchange", "Correct mode");
69 is(transaction.objectStoreNames.length, 1, "Correct names length");
70 is(transaction.objectStoreNames.item(0), "foo", "Correct name");
71 is(transaction.onabort, null, "No abort listener");
73 try {
74 is(transaction.objectStore("foo").name, "foo", "Can't get stores");
75 ok(false, "Should have thrown");
76 }
77 catch (e) {
78 ok(true, "Out of scope transaction can't make stores");
79 }
81 is(objectStore.name, "foo", "Correct name");
82 is(objectStore.keyPath, null, "Correct keyPath");
84 is(objectStore.indexNames.length, 1, "Correct indexNames length");
85 is(objectStore.indexNames[0], "fooindex", "Correct indexNames name");
87 try {
88 objectStore.add({});
89 ok(false, "Should have thrown");
90 }
91 catch (e) {
92 ok(true, "Add threw");
93 }
95 try {
96 objectStore.put({}, 1);
97 ok(false, "Should have thrown");
98 }
99 catch (e) {
100 ok(true, "Put threw");
101 }
103 try {
104 objectStore.put({}, 1);
105 ok(false, "Should have thrown");
106 }
107 catch (e) {
108 ok(true, "Put threw");
109 }
111 try {
112 objectStore.delete(1);
113 ok(false, "Should have thrown");
114 }
115 catch (e) {
116 ok(true, "Remove threw");
117 }
119 try {
120 objectStore.get(1);
121 ok(false, "Should have thrown");
122 }
123 catch (e) {
124 ok(true, "Get threw");
125 }
127 try {
128 objectStore.getAll(null);
129 ok(false, "Should have thrown");
130 }
131 catch (e) {
132 ok(true, "GetAll threw");
133 }
135 try {
136 objectStore.openCursor();
137 ok(false, "Should have thrown");
138 }
139 catch (e) {
140 ok(true, "OpenCursor threw");
141 }
143 try {
144 objectStore.createIndex("bar", "id");
145 ok(false, "Should have thrown");
146 }
147 catch (e) {
148 ok(true, "CreateIndex threw");
149 }
151 try {
152 objectStore.index("bar");
153 ok(false, "Should have thrown");
154 }
155 catch (e) {
156 ok(true, "Index threw");
157 }
159 try {
160 objectStore.deleteIndex("bar");
161 ok(false, "Should have thrown");
162 }
163 catch (e) {
164 ok(true, "RemoveIndex threw");
165 }
167 yield undefined;
169 request = db.transaction("foo", "readwrite").objectStore("foo").add({});
170 request.onerror = errorHandler;
171 request.onsuccess = grabEventAndContinueHandler;
172 event = yield undefined;
174 event.target.transaction.onabort = function(event) {
175 ok(false, "Shouldn't see an abort event!");
176 };
177 event.target.transaction.oncomplete = grabEventAndContinueHandler;
178 event = yield undefined;
180 is(event.type, "complete", "Right kind of event");
182 let key;
184 request = db.transaction("foo", "readwrite").objectStore("foo").add({});
185 request.onerror = errorHandler;
186 request.onsuccess = grabEventAndContinueHandler;
187 event = yield undefined;
189 key = event.target.result;
191 event.target.transaction.onabort = grabEventAndContinueHandler;
192 event.target.transaction.oncomplete = function(event) {
193 ok(false, "Shouldn't see a complete event here!");
194 };
196 event.target.transaction.abort();
198 event = yield undefined;
200 is(event.type, "abort", "Right kind of event");
202 request = db.transaction("foo").objectStore("foo").get(key);
203 request.onerror = errorHandler;
204 request.onsuccess = grabEventAndContinueHandler;
205 event = yield undefined;
207 is(event.target.result, undefined, "Object was removed");
209 executeSoon(function() { testGenerator.next(); });
210 yield undefined;
212 let keys = [];
213 let abortEventCount = 0;
214 function abortErrorHandler(event) {
215 is(event.target.error.name, "AbortError",
216 "Good error");
217 abortEventCount++;
218 event.preventDefault();
219 };
220 objectStore = db.transaction("foo", "readwrite").objectStore("foo");
222 for (let i = 0; i < 10; i++) {
223 request = objectStore.add({});
224 request.onerror = abortErrorHandler;
225 request.onsuccess = function(event) {
226 keys.push(event.target.result);
227 if (keys.length == 5) {
228 event.target.transaction.onabort = grabEventAndContinueHandler;
229 event.target.transaction.abort();
230 }
231 };
232 }
233 event = yield undefined;
235 is(event.type, "abort", "Got abort event");
236 is(keys.length, 5, "Added 5 items in this transaction");
237 is(abortEventCount, 5, "Got 5 abort error events");
239 for (let i in keys) {
240 request = db.transaction("foo").objectStore("foo").get(keys[i]);
241 request.onerror = errorHandler;
242 request.onsuccess = grabEventAndContinueHandler;
243 event = yield undefined;
245 is(event.target.result, undefined, "Object was removed by abort");
246 }
248 // Set up some predictible data
249 transaction = db.transaction("foo", "readwrite");
250 objectStore = transaction.objectStore("foo");
251 objectStore.clear();
252 objectStore.add({}, 1);
253 objectStore.add({}, 2);
254 request = objectStore.add({}, 1);
255 request.onsuccess = function() {
256 ok(false, "inserting duplicate key should fail");
257 }
258 request.onerror = function(event) {
259 ok(true, "inserting duplicate key should fail");
260 event.preventDefault();
261 }
262 transaction.oncomplete = grabEventAndContinueHandler;
263 yield undefined;
265 // Check when aborting is allowed
266 abortEventCount = 0;
267 let expectedAbortEventCount = 0;
269 // During INITIAL
270 transaction = db.transaction("foo");
271 transaction.abort();
272 try {
273 transaction.abort();
274 ok(false, "second abort should throw an error");
275 }
276 catch (ex) {
277 ok(true, "second abort should throw an error");
278 }
280 // During LOADING
281 transaction = db.transaction("foo");
282 transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
283 expectedAbortEventCount++;
284 transaction.abort();
285 try {
286 transaction.abort();
287 ok(false, "second abort should throw an error");
288 }
289 catch (ex) {
290 ok(true, "second abort should throw an error");
291 }
293 // During LOADING from callback
294 transaction = db.transaction("foo");
295 transaction.objectStore("foo").get(1).onsuccess = grabEventAndContinueHandler;
296 event = yield undefined;
297 transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
298 expectedAbortEventCount++
299 transaction.abort();
300 try {
301 transaction.abort();
302 ok(false, "second abort should throw an error");
303 }
304 catch (ex) {
305 ok(true, "second abort should throw an error");
306 }
308 // During LOADING from error callback
309 transaction = db.transaction("foo", "readwrite");
310 transaction.objectStore("foo").add({}, 1).onerror = function(event) {
311 event.preventDefault();
313 transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
314 expectedAbortEventCount++
316 transaction.abort();
317 continueToNextStep();
318 }
319 yield undefined;
321 // In between callbacks
322 transaction = db.transaction("foo");
323 function makeNewRequest() {
324 let r = transaction.objectStore("foo").get(1);
325 r.onsuccess = makeNewRequest;
326 r.onerror = abortErrorHandler;
327 }
328 makeNewRequest();
329 transaction.objectStore("foo").get(1).onsuccess = function(event) {
330 executeSoon(function() {
331 transaction.abort();
332 expectedAbortEventCount++;
333 continueToNextStep();
334 });
335 };
336 yield undefined;
338 // During COMMITTING
339 transaction = db.transaction("foo", "readwrite");
340 transaction.objectStore("foo").put({hello: "world"}, 1).onsuccess = function(event) {
341 continueToNextStep();
342 };
343 yield undefined;
344 try {
345 transaction.abort();
346 ok(false, "second abort should throw an error");
347 }
348 catch (ex) {
349 ok(true, "second abort should throw an error");
350 }
351 transaction.oncomplete = grabEventAndContinueHandler;
352 event = yield undefined;
354 // Since the previous transaction shouldn't have caused any error events,
355 // we know that all events should have fired by now.
356 is(abortEventCount, expectedAbortEventCount,
357 "All abort errors fired");
359 // Abort both failing and succeeding requests
360 transaction = db.transaction("foo", "readwrite");
361 transaction.onabort = transaction.oncomplete = grabEventAndContinueHandler;
362 transaction.objectStore("foo").add({indexKey: "key"}).onsuccess = function(event) {
363 transaction.abort();
364 };
365 let request1 = transaction.objectStore("foo").add({indexKey: "key"});
366 request1.onsuccess = grabEventAndContinueHandler;
367 request1.onerror = grabEventAndContinueHandler;
368 let request2 = transaction.objectStore("foo").get(1);
369 request2.onsuccess = grabEventAndContinueHandler;
370 request2.onerror = grabEventAndContinueHandler;
372 event = yield undefined;
373 is(event.type, "error", "abort() should make all requests fail");
374 is(event.target, request1, "abort() should make all requests fail");
375 is(event.target.error.name, "AbortError", "abort() should make all requests fail");
376 event.preventDefault();
378 event = yield undefined;
379 is(event.type, "error", "abort() should make all requests fail");
380 is(event.target, request2, "abort() should make all requests fail");
381 is(event.target.error.name, "AbortError", "abort() should make all requests fail");
382 event.preventDefault();
384 event = yield undefined;
385 is(event.type, "abort", "transaction should fail");
386 is(event.target, transaction, "transaction should fail");
388 ok(abortFired, "Abort should have fired!");
390 finishTest();
391 yield undefined;
392 }