| // META: global=window,worker |
| // META: title=IDBCursor.continuePrimaryKey() - Exception Orders |
| // META: script=resources/support.js |
| // META: timeout=long |
| |
| // Spec: http://w3c.github.io/IndexedDB/#dom-idbcursor-continueprimarykey |
| |
| 'use strict'; |
| |
| function setup_test_store(db) { |
| const records = [ |
| {iKey: 'A', pKey: 1}, {iKey: 'A', pKey: 2}, {iKey: 'A', pKey: 3}, |
| {iKey: 'A', pKey: 4}, {iKey: 'B', pKey: 5}, {iKey: 'B', pKey: 6}, |
| {iKey: 'B', pKey: 7}, {iKey: 'C', pKey: 8}, {iKey: 'C', pKey: 9}, |
| {iKey: 'D', pKey: 10} |
| ]; |
| |
| const store = db.createObjectStore('test', {keyPath: 'pKey'}); |
| store.createIndex('idx', 'iKey'); |
| |
| for (let i = 0; i < records.length; i++) { |
| store.add(records[i]); |
| } |
| |
| return store; |
| } |
| |
| indexeddb_test(function(t, db, txn) { |
| const store = setup_test_store(db); |
| const cursor_rq = store.index('idx').openCursor(); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| store.deleteIndex('idx'); |
| }); |
| txn.oncomplete = t.step_func(() => { |
| assert_throws_dom('TransactionInactiveError', () => { |
| cursor.continuePrimaryKey('A', 4); |
| }, 'transaction-state check should precede deletion check'); |
| t.done(); |
| }); |
| }, null, 'TransactionInactiveError v.s. InvalidStateError(deleted index)'); |
| |
| indexeddb_test( |
| function(t, db, txn) { |
| const store = setup_test_store(db); |
| const cursor_rq = store.openCursor(); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| db.deleteObjectStore('test'); |
| |
| assert_throws_dom('InvalidStateError', () => { |
| cursor.continuePrimaryKey('A', 4); |
| }, 'deletion check should precede index source check'); |
| t.done(); |
| }); |
| }, |
| null, |
| 'InvalidStateError(deleted source) v.s. InvalidAccessError(incorrect source)'); |
| |
| indexeddb_test( |
| function(t, db, txn) { |
| const store = setup_test_store(db); |
| const cursor_rq = store.index('idx').openCursor(null, 'nextunique'); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| store.deleteIndex('idx'); |
| |
| assert_throws_dom('InvalidStateError', () => { |
| cursor.continuePrimaryKey('A', 4); |
| }, 'deletion check should precede cursor direction check'); |
| t.done(); |
| }); |
| }, |
| null, |
| 'InvalidStateError(deleted source) v.s. InvalidAccessError(incorrect direction)'); |
| |
| indexeddb_test( |
| function(t, db, txn) { |
| const store = db.createObjectStore('test', {keyPath: 'pKey'}); |
| |
| store.add({iKey: 'A', pKey: 1}); |
| |
| const cursor_rq = |
| store.createIndex('idx', 'iKey').openCursor(null, 'nextunique'); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| if (e.target.result) { |
| cursor = e.target.result; |
| cursor.continue(); |
| return; |
| } |
| |
| assert_throws_dom('InvalidAccessError', () => { |
| cursor.continuePrimaryKey('A', 4); |
| }, 'direction check should precede got_value_flag check'); |
| t.done(); |
| }); |
| }, |
| null, |
| 'InvalidAccessError(incorrect direction) v.s. InvalidStateError(iteration complete)'); |
| |
| indexeddb_test( |
| function(t, db, txn) { |
| const store = db.createObjectStore('test', {keyPath: 'pKey'}); |
| |
| store.add({iKey: 'A', pKey: 1}); |
| |
| const cursor_rq = |
| store.createIndex('idx', 'iKey').openCursor(null, 'nextunique'); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| if (!cursor) { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| cursor.continue(); |
| |
| assert_throws_dom('InvalidAccessError', () => { |
| cursor.continuePrimaryKey('A', 4); |
| }, 'direction check should precede iteration ongoing check'); |
| t.done(); |
| } |
| }); |
| }, |
| null, |
| 'InvalidAccessError(incorrect direction) v.s. InvalidStateError(iteration ongoing)'); |
| |
| indexeddb_test( |
| function(t, db, txn) { |
| const store = setup_test_store(db); |
| const cursor_rq = store.openCursor(); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| if (!cursor) { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| cursor.continue(); |
| |
| assert_throws_dom('InvalidAccessError', () => { |
| cursor.continuePrimaryKey('A', 4); |
| }, 'index source check should precede iteration ongoing check'); |
| t.done(); |
| } |
| }); |
| }, |
| null, |
| 'InvalidAccessError(incorrect source) v.s. InvalidStateError(iteration ongoing)'); |
| |
| indexeddb_test( |
| function(t, db, txn) { |
| const store = db.createObjectStore('test', {keyPath: 'pKey'}); |
| |
| store.add({iKey: 'A', pKey: 1}); |
| |
| const cursor_rq = store.openCursor(); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| if (e.target.result) { |
| cursor = e.target.result; |
| cursor.continue(); |
| return; |
| } |
| |
| assert_throws_dom('InvalidAccessError', () => { |
| cursor.continuePrimaryKey('A', 4); |
| }, 'index source check should precede got_value_flag check'); |
| t.done(); |
| }); |
| }, |
| null, |
| 'InvalidAccessError(incorrect source) v.s. InvalidStateError(iteration complete)'); |
| |
| indexeddb_test(function(t, db, txn) { |
| const store = setup_test_store(db); |
| const cursor_rq = store.index('idx').openCursor(); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| if (!cursor) { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| cursor.continue(); |
| |
| assert_throws_dom('InvalidStateError', () => { |
| cursor.continuePrimaryKey(null, 4); |
| }, 'iteration ongoing check should precede unset key check'); |
| t.done(); |
| } |
| }); |
| }, null, 'InvalidStateError(iteration ongoing) v.s. DataError(unset key)'); |
| |
| indexeddb_test(function(t, db, txn) { |
| const store = db.createObjectStore('test', {keyPath: 'pKey'}); |
| |
| store.add({iKey: 'A', pKey: 1}); |
| |
| const cursor_rq = store.createIndex('idx', 'iKey').openCursor(); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| if (e.target.result) { |
| cursor = e.target.result; |
| cursor.continue(); |
| return; |
| } |
| |
| assert_throws_dom('InvalidStateError', () => { |
| cursor.continuePrimaryKey(null, 4); |
| }, 'got_value_flag check should precede unset key check'); |
| t.done(); |
| }); |
| }, null, 'InvalidStateError(iteration complete) v.s. DataError(unset key)'); |
| |
| indexeddb_test(function(t, db, txn) { |
| const store = setup_test_store(db); |
| const cursor_rq = store.index('idx').openCursor(); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| assert_throws_dom('DataError', () => { |
| cursor.continuePrimaryKey(null, 4); |
| }, 'DataError is expected if key is unset.'); |
| t.done(); |
| }); |
| }, null, 'DataError(unset key)'); |
| |
| indexeddb_test(function(t, db, txn) { |
| const store = setup_test_store(db); |
| const cursor_rq = store.index('idx').openCursor(); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| assert_throws_dom('DataError', () => { |
| cursor.continuePrimaryKey('A', null); |
| }, 'DataError is expected if primary key is unset.'); |
| t.done(); |
| }); |
| }, null, 'DataError(unset primary key)'); |
| |
| indexeddb_test(function(t, db, txn) { |
| const store = setup_test_store(db); |
| const cursor_rq = store.index('idx').openCursor(IDBKeyRange.lowerBound('B')); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func((e) => { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| assert_equals(cursor.key, 'B', 'expected key'); |
| assert_equals(cursor.primaryKey, 5, 'expected primary key'); |
| |
| assert_throws_dom('DataError', () => { |
| cursor.continuePrimaryKey('A', 6); |
| }, 'DataError is expected if key is lower then current one.'); |
| |
| assert_throws_dom('DataError', () => { |
| cursor.continuePrimaryKey('B', 5); |
| }, 'DataError is expected if primary key is equal to current one.'); |
| |
| assert_throws_dom('DataError', () => { |
| cursor.continuePrimaryKey('B', 4); |
| }, 'DataError is expected if primary key is lower than current one.'); |
| |
| t.done(); |
| }); |
| }, null, 'DataError(keys are lower then current one) in \'next\' direction'); |
| |
| indexeddb_test(function(t, db, txn) { |
| const store = setup_test_store(db); |
| const cursor_rq = |
| store.index('idx').openCursor(IDBKeyRange.upperBound('B'), 'prev'); |
| let cursor; |
| |
| cursor_rq.onerror = t.unreached_func('openCursor should succeed'); |
| cursor_rq.onsuccess = t.step_func(function(e) { |
| cursor = e.target.result; |
| assert_true(!!cursor, 'acquire cursor'); |
| |
| assert_equals(cursor.key, 'B', 'expected key'); |
| assert_equals(cursor.primaryKey, 7, 'expected primary key'); |
| |
| assert_throws_dom('DataError', () => { |
| cursor.continuePrimaryKey('C', 6); |
| }, 'DataError is expected if key is larger then current one.'); |
| |
| assert_throws_dom('DataError', () => { |
| cursor.continuePrimaryKey('B', 7); |
| }, 'DataError is expected if primary key is equal to current one.'); |
| |
| assert_throws_dom('DataError', () => { |
| cursor.continuePrimaryKey('B', 8); |
| }, 'DataError is expected if primary key is larger than current one.'); |
| |
| t.done(); |
| }); |
| }, null, 'DataError(keys are larger then current one) in \'prev\' direction'); |