OLD | NEW |
(Empty) | |
| 1 |
| 2 // Returns an IndexedDB database name likely to be unique to the test case. |
| 3 const databaseName = function(testCase) { |
| 4 return 'db' + self.location.pathname + '-' + testCase.name; |
| 5 }; |
| 6 |
| 7 // Creates an EventWatcher covering all the events that can be issued by |
| 8 // IndexedDB requests and transactions. |
| 9 const requestWatcher = function(testCase, request) { |
| 10 return new EventWatcher(testCase, request, |
| 11 ['error', 'success', 'upgradeneeded']); |
| 12 }; |
| 13 |
| 14 // Migrates an IndexedDB database whose name is unique for the test case. |
| 15 // |
| 16 // setupCallback will be called during a versionchange transaction, and will be |
| 17 // given the created database and the versionchange transaction. |
| 18 // |
| 19 // Returns a promise that resolves to an IndexedDB database. The caller must |
| 20 // close the database. |
| 21 const migrateDatabase = function(testCase, newVersion, setupCallback) { |
| 22 // We cannot use eventWatcher.wait_for('upgradeneeded') here, because |
| 23 // the versionchange transaction auto-commits before the Promise's then |
| 24 // callback gets called. |
| 25 return new Promise((resolve, reject) => { |
| 26 const request = indexedDB.open(databaseName(testCase), newVersion); |
| 27 request.onupgradeneeded = event => { |
| 28 const eventWatcher = requestWatcher(testCase, request); |
| 29 const database = event.target.result; |
| 30 const transaction = event.target.transaction; |
| 31 setupCallback(database, transaction); |
| 32 resolve(eventWatcher.wait_for('success')); |
| 33 }; |
| 34 request.onerror = event => reject(event.target.error); |
| 35 }).then(event => event.target.result); |
| 36 }; |
| 37 |
| 38 // Creates an IndexedDB database whose name is unique for the test case. |
| 39 // |
| 40 // setupCallback will be called during a versionchange transaction, and will be |
| 41 // given the created database and the versionchange transaction. |
| 42 // |
| 43 // Returns a promise that resolves to an IndexedDB database. The caller must |
| 44 // close the database. |
| 45 const createDatabase = function(testCase, setupCallback) { |
| 46 const request = indexedDB.deleteDatabase(databaseName(testCase)); |
| 47 const eventWatcher = requestWatcher(testCase, request); |
| 48 |
| 49 return eventWatcher.wait_for('success').then(event => |
| 50 migrateDatabase(testCase, 1, setupCallback)); |
| 51 }; |
| 52 |
| 53 // The data in the 'books' object store records in the first example of the |
| 54 // IndexedDB specification. |
| 55 const BOOKS_RECORD_DATA = [ |
| 56 { title: 'Quarry Memories', author: 'Fred', isbn: 123456 }, |
| 57 { title: 'Water Buffaloes', author: 'Fred', isbn: 234567 }, |
| 58 { title: 'Bedrock Nights', author: 'Barney', isbn: 345678 }, |
| 59 ]; |
| 60 |
| 61 // Creates a 'books' object store whose contents closely resembles the first |
| 62 // example in the IndexedDB specification. |
| 63 const createBooksStore = function(testCase, database) { |
| 64 const store = database.createObjectStore('books', |
| 65 { keyPath: 'isbn', autoIncrement: true }); |
| 66 store.createIndex('by_author', 'author'); |
| 67 store.createIndex('by_title', 'title', { unique: true }); |
| 68 for (let record of BOOKS_RECORD_DATA) |
| 69 store.put(record); |
| 70 return store; |
| 71 }; |
| 72 |
| 73 // Creates a 'not_books' object store used to test renaming into existing or |
| 74 // deleted store names. |
| 75 const createNotBooksStore = function(testCase, database) { |
| 76 return database.createObjectStore('not_books'); |
| 77 }; |
| 78 |
| 79 // Verifies that an object store's indexes match the indexes used to create the |
| 80 // books store in the test database's version 1. |
| 81 // |
| 82 // The errorMessage is used if the assertions fail. It can state that the |
| 83 // IndexedDB implementation being tested is incorrect, or that the testing code |
| 84 // is using it incorrectly. |
| 85 const checkStoreIndexes = function(testCase, store, errorMessage) { |
| 86 assert_array_equals( |
| 87 store.indexNames, ['by_author', 'by_title'], errorMessage); |
| 88 const authorIndex = store.index('by_author'); |
| 89 const titleIndex = store.index('by_title'); |
| 90 return Promise.all([ |
| 91 checkAuthorIndexContents(testCase, authorIndex, errorMessage), |
| 92 checkTitleIndexContents(testCase, titleIndex, errorMessage), |
| 93 ]); |
| 94 }; |
| 95 |
| 96 // Verifies that an object store's key generator is in the same state as the |
| 97 // key generator created for the books store in the test database's version 1. |
| 98 // |
| 99 // The errorMessage is used if the assertions fail. It can state that the |
| 100 // IndexedDB implementation being tested is incorrect, or that the testing code |
| 101 // is using it incorrectly. |
| 102 const checkStoreGenerator = function(testCase, |
| 103 store, |
| 104 expectedKey, |
| 105 errorMessage) { |
| 106 const request = store.put( |
| 107 { title: 'Bedrock Nights ' + expectedKey, author: 'Barney' }); |
| 108 const eventWatcher = requestWatcher(testCase, request); |
| 109 return eventWatcher.wait_for('success').then(() => { |
| 110 const result = request.result; |
| 111 assert_equals(result, expectedKey, errorMessage); |
| 112 }); |
| 113 }; |
| 114 |
| 115 // Verifies that an object store's contents matches the contents used to create |
| 116 // the books store in the test database's version 1. |
| 117 // |
| 118 // The errorMessage is used if the assertions fail. It can state that the |
| 119 // IndexedDB implementation being tested is incorrect, or that the testing code |
| 120 // is using it incorrectly. |
| 121 const checkStoreContents = function(testCase, store, errorMessage) { |
| 122 const request = store.get(123456); |
| 123 const eventWatcher = requestWatcher(testCase, request); |
| 124 return eventWatcher.wait_for('success').then(() => { |
| 125 const result = request.result; |
| 126 assert_equals(result.isbn, BOOKS_RECORD_DATA[0].isbn, errorMessage); |
| 127 assert_equals(result.author, BOOKS_RECORD_DATA[0].author, errorMessage); |
| 128 assert_equals(result.title, BOOKS_RECORD_DATA[0].title, errorMessage); |
| 129 }); |
| 130 }; |
| 131 |
| 132 // Verifies that index matches the 'by_author' index used to create the |
| 133 // by_author books store in the test database's version 1. |
| 134 // |
| 135 // The errorMessage is used if the assertions fail. It can state that the |
| 136 // IndexedDB implementation being tested is incorrect, or that the testing code |
| 137 // is using it incorrectly. |
| 138 const checkAuthorIndexContents = function(testCase, index, errorMessage) { |
| 139 const request = index.get(BOOKS_RECORD_DATA[2].author); |
| 140 const eventWatcher = requestWatcher(testCase, request); |
| 141 return eventWatcher.wait_for('success').then(() => { |
| 142 const result = request.result; |
| 143 assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage); |
| 144 assert_equals(result.title, BOOKS_RECORD_DATA[2].title, errorMessage); |
| 145 }); |
| 146 }; |
| 147 |
| 148 // Verifies that an index matches the 'by_title' index used to create the books |
| 149 // store in the test database's version 1. |
| 150 // |
| 151 // The errorMessage is used if the assertions fail. It can state that the |
| 152 // IndexedDB implementation being tested is incorrect, or that the testing code |
| 153 // is using it incorrectly. |
| 154 const checkTitleIndexContents = function(testCase, index, errorMessage) { |
| 155 const request = index.get(BOOKS_RECORD_DATA[2].title); |
| 156 const eventWatcher = requestWatcher(testCase, request); |
| 157 return eventWatcher.wait_for('success').then(() => { |
| 158 const result = request.result; |
| 159 assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage); |
| 160 assert_equals(result.author, BOOKS_RECORD_DATA[2].author, errorMessage); |
| 161 }); |
| 162 }; |
OLD | NEW |