name-scopes.any.js (5053B)
1 // META: title=IndexedDB: scoping for database / object store / index names, and index keys 2 // META: global=window,worker 3 // META: script=resources/support-promises.js 4 5 // Spec: https://w3c.github.io/IndexedDB/#constructs 6 7 'use strict'; 8 9 // Creates the structure inside a test database. 10 // 11 // The structure includes two stores with identical indexes and nearly-similar 12 // records. The records differ in the "path" attribute values, which are used to 13 // verify that IndexedDB returns the correct records when queried. 14 // 15 // databaseName appears redundant, but we don't want to rely on database.name. 16 const buildStores = (database, databaseName, useUniqueKeys) => { 17 for (let storeName of ['x', 'y']) { 18 const store = database.createObjectStore( 19 storeName, {keyPath: 'pKey', autoIncrement: true}); 20 for (let indexName of ['x', 'y']) { 21 store.createIndex(indexName, `${indexName}Key`, {unique: useUniqueKeys}); 22 } 23 24 for (let xKeyRoot of ['x', 'y']) { 25 for (let yKeyRoot of ['x', 'y']) { 26 let xKey, yKey; 27 if (useUniqueKeys) { 28 xKey = `${xKeyRoot}${yKeyRoot}`; 29 yKey = `${yKeyRoot}${xKeyRoot}`; 30 } else { 31 xKey = xKeyRoot; 32 yKey = yKeyRoot; 33 } 34 const path = `${databaseName}-${storeName}-${xKeyRoot}-${yKeyRoot}`; 35 store.put({xKey: xKey, yKey: yKey, path: path}); 36 } 37 } 38 } 39 }; 40 41 // Creates two databases with identical structures. 42 const buildDatabases = (testCase, useUniqueKeys) => { 43 return createNamedDatabase( 44 testCase, 'x', 45 database => buildStores(database, 'x', useUniqueKeys)) 46 .then(database => database.close()) 47 .then( 48 () => createNamedDatabase( 49 testCase, 'y', 50 database => buildStores(database, 'y', useUniqueKeys))) 51 .then(database => database.close()); 52 }; 53 54 // Reads all the store's values using an index. 55 // 56 // Returns a Promise that resolves with an array of values. 57 const readIndex = 58 (testCase, index) => { 59 return new Promise((resolve, reject) => { 60 const results = []; 61 const request = index.openCursor(IDBKeyRange.bound('a', 'z'), 'next'); 62 request.onsuccess = testCase.step_func(() => { 63 const cursor = request.result; 64 if (cursor) { 65 results.push(cursor.value); 66 cursor.continue(); 67 } else { 68 resolve(results); 69 } 70 }); 71 }); 72 } 73 74 // Verifies that a database contains the expected records. 75 const checkDatabaseContent = 76 (testCase, database, databaseName, usedUniqueKeys) => { 77 const promises = []; 78 const transaction = database.transaction(['x', 'y'], 'readonly'); 79 for (let storeName of ['x', 'y']) { 80 const store = transaction.objectStore(storeName); 81 for (let indexName of ['x', 'y']) { 82 const index = store.index(indexName); 83 84 const promise = readIndex(testCase, index).then((results) => { 85 assert_array_equals( 86 results.map(result => `${result.path}:${result.pKey}`).sort(), 87 [ 88 `${databaseName}-${storeName}-x-x:1`, 89 `${databaseName}-${storeName}-x-y:2`, 90 `${databaseName}-${storeName}-y-x:3`, 91 `${databaseName}-${storeName}-y-y:4` 92 ], 93 'The results should include all records put into the store'); 94 95 let expectedKeys = (usedUniqueKeys) ? 96 ['xx:xx', 'xy:yx', 'yx:xy', 'yy:yy'] : 97 ['x:x', 'x:y', 'y:x', 'y:y']; 98 assert_array_equals( 99 results.map(result => `${result.xKey}:${result.yKey}`).sort(), 100 expectedKeys, 101 'The results should include all the index keys put in the store'); 102 103 assert_array_equals( 104 results.map(result => result[`${indexName}Key`]), 105 results.map(result => result[`${indexName}Key`]).sort(), 106 'The results should be sorted by the index key'); 107 }); 108 promises.push(promise); 109 } 110 } 111 112 return Promise.all(promises).then(() => database); 113 } 114 115 promise_test(testCase => { 116 return buildDatabases(testCase, false) 117 .then(() => openNamedDatabase(testCase, 'x', 1)) 118 .then(database => checkDatabaseContent(testCase, database, 'x', false)) 119 .then(database => database.close()) 120 .then(() => openNamedDatabase(testCase, 'y', 1)) 121 .then(database => checkDatabaseContent(testCase, database, 'y', false)) 122 .then(database => database.close()); 123 }, 'Non-unique index keys'); 124 125 promise_test(testCase => { 126 return buildDatabases(testCase, true) 127 .then(() => openNamedDatabase(testCase, 'x', 1)) 128 .then(database => checkDatabaseContent(testCase, database, 'x', true)) 129 .then(database => database.close()) 130 .then(() => openNamedDatabase(testCase, 'y', 1)) 131 .then(database => checkDatabaseContent(testCase, database, 'y', true)) 132 .then(database => database.close()); 133 }, 'Unique index keys');