1
- // Returns an IndexedDB database name likely to be unique to the test case.
2
- const databaseName = ( testCase ) => {
1
+ 'use strict' ;
2
+
3
+ // Returns an IndexedDB database name that is unique to the test case.
4
+ function databaseName ( testCase ) {
3
5
return 'db' + self . location . pathname + '-' + testCase . name ;
4
- } ;
6
+ }
5
7
6
8
// Creates an EventWatcher covering all the events that can be issued by
7
9
// IndexedDB requests and transactions.
8
- const requestWatcher = ( testCase , request ) => {
10
+ function requestWatcher ( testCase , request ) {
9
11
return new EventWatcher ( testCase , request ,
10
- [ 'error' , 'success' , 'upgradeneeded' ] ) ;
11
- } ;
12
+ [ 'abort' , 'blocked' , 'complete' , ' error', 'success' , 'upgradeneeded' ] ) ;
13
+ }
12
14
13
15
// Migrates an IndexedDB database whose name is unique for the test case.
14
16
//
15
17
// newVersion must be greater than the database's current version.
16
18
//
17
19
// migrationCallback will be called during a versionchange transaction and will
18
- // be given the created database and the versionchange transaction.
20
+ // given the created database, the versionchange transaction, and the database
21
+ // open request.
19
22
//
20
23
// Returns a promise. If the versionchange transaction goes through, the promise
21
24
// resolves to an IndexedDB database that must be closed by the caller. If the
22
25
// versionchange transaction is aborted, the promise resolves to an error.
23
- const migrateDatabase = ( testCase , newVersion , migrationCallback ) => {
26
+ function migrateDatabase ( testCase , newVersion , migrationCallback ) {
24
27
return migrateNamedDatabase (
25
28
testCase , databaseName ( testCase ) , newVersion , migrationCallback ) ;
26
- } ;
29
+ }
27
30
28
31
// Migrates an IndexedDB database.
29
32
//
30
33
// newVersion must be greater than the database's current version.
31
34
//
32
35
// migrationCallback will be called during a versionchange transaction and will
33
- // be given the created database and the versionchange transaction.
36
+ // given the created database, the versionchange transaction, and the database
37
+ // open request.
34
38
//
35
39
// Returns a promise. If the versionchange transaction goes through, the promise
36
40
// resolves to an IndexedDB database that must be closed by the caller. If the
37
41
// versionchange transaction is aborted, the promise resolves to an error.
38
- const migrateNamedDatabase =
39
- ( testCase , databaseName , newVersion , migrationCallback ) => {
42
+ function migrateNamedDatabase (
43
+ testCase , databaseName , newVersion , migrationCallback ) {
40
44
// We cannot use eventWatcher.wait_for('upgradeneeded') here, because
41
45
// the versionchange transaction auto-commits before the Promise's then
42
46
// callback gets called.
@@ -45,70 +49,86 @@ const migrateNamedDatabase =
45
49
request . onupgradeneeded = testCase . step_func ( event => {
46
50
const database = event . target . result ;
47
51
const transaction = event . target . transaction ;
48
- let abortCalled = false ;
52
+ let shouldBeAborted = false ;
53
+ let requestEventPromise = null ;
49
54
50
55
// We wrap IDBTransaction.abort so we can set up the correct event
51
56
// listeners and expectations if the test chooses to abort the
52
57
// versionchange transaction.
53
58
const transactionAbort = transaction . abort . bind ( transaction ) ;
54
59
transaction . abort = ( ) => {
55
- request . onerror = event => {
56
- event . preventDefault ( ) ;
57
- resolve ( event ) ;
58
- } ;
59
- request . onsuccess = ( ) => reject ( new Error (
60
- 'indexedDB.open should not succeed after the versionchange ' +
61
- 'transaction is aborted' ) ) ;
60
+ transaction . _willBeAborted ( ) ;
62
61
transactionAbort ( ) ;
63
- abortCalled = true ;
62
+ }
63
+ transaction . _willBeAborted = ( ) => {
64
+ requestEventPromise = new Promise ( ( resolve , reject ) => {
65
+ request . onerror = event => {
66
+ event . preventDefault ( ) ;
67
+ resolve ( event ) ;
68
+ } ;
69
+ request . onsuccess = ( ) => reject ( new Error (
70
+ 'indexedDB.open should not succeed for an aborted ' +
71
+ 'versionchange transaction' ) ) ;
72
+ } ) ;
73
+ shouldBeAborted = true ;
64
74
}
65
75
66
- migrationCallback ( database , transaction ) ;
67
- if ( ! abortCalled ) {
76
+ // If migration callback returns a promise, we'll wait for it to resolve.
77
+ // This simplifies some tests.
78
+ const callbackResult = migrationCallback ( database , transaction , request ) ;
79
+ if ( ! shouldBeAborted ) {
80
+ request . onerror = null ;
68
81
request . onsuccess = null ;
69
- resolve ( requestWatcher ( testCase , request ) . wait_for ( 'success' ) ) ;
82
+ requestEventPromise =
83
+ requestWatcher ( testCase , request ) . wait_for ( 'success' ) ;
70
84
}
85
+
86
+ // requestEventPromise needs to be the last promise in the chain, because
87
+ // we want the event that it resolves to.
88
+ resolve ( Promise . resolve ( callbackResult ) . then ( ( ) => requestEventPromise ) ) ;
71
89
} ) ;
72
90
request . onerror = event => reject ( event . target . error ) ;
73
91
request . onsuccess = ( ) => reject ( new Error (
74
92
'indexedDB.open should not succeed without creating a ' +
75
93
'versionchange transaction' ) ) ;
76
94
} ) . then ( event => event . target . result || event . target . error ) ;
77
- } ;
95
+ }
78
96
79
97
// Creates an IndexedDB database whose name is unique for the test case.
80
98
//
81
99
// setupCallback will be called during a versionchange transaction, and will be
82
- // given the created database and the versionchange transaction.
100
+ // given the created database, the versionchange transaction, and the database
101
+ // open request.
83
102
//
84
103
// Returns a promise that resolves to an IndexedDB database. The caller must
85
104
// close the database.
86
- const createDatabase = ( testCase , setupCallback ) => {
105
+ function createDatabase ( testCase , setupCallback ) {
87
106
return createNamedDatabase ( testCase , databaseName ( testCase ) , setupCallback ) ;
88
- } ;
107
+ }
89
108
90
109
// Creates an IndexedDB database.
91
110
//
92
111
// setupCallback will be called during a versionchange transaction, and will be
93
- // given the created database and the versionchange transaction.
112
+ // given the created database, the versionchange transaction, and the database
113
+ // open request.
94
114
//
95
115
// Returns a promise that resolves to an IndexedDB database. The caller must
96
116
// close the database.
97
- const createNamedDatabase = ( testCase , databaseName , setupCallback ) => {
117
+ function createNamedDatabase ( testCase , databaseName , setupCallback ) {
98
118
const request = indexedDB . deleteDatabase ( databaseName ) ;
99
119
const eventWatcher = requestWatcher ( testCase , request ) ;
100
120
101
121
return eventWatcher . wait_for ( 'success' ) . then ( event =>
102
122
migrateNamedDatabase ( testCase , databaseName , 1 , setupCallback ) ) ;
103
- } ;
123
+ }
104
124
105
125
// Opens an IndexedDB database without performing schema changes.
106
126
//
107
127
// The given version number must match the database's current version.
108
128
//
109
129
// Returns a promise that resolves to an IndexedDB database. The caller must
110
130
// close the database.
111
- const openDatabase = ( testCase , version ) => {
131
+ function openDatabase ( testCase , version ) {
112
132
return openNamedDatabase ( testCase , databaseName ( testCase ) , version ) ;
113
133
}
114
134
@@ -118,7 +138,7 @@ const openDatabase = (testCase, version) => {
118
138
//
119
139
// Returns a promise that resolves to an IndexedDB database. The caller must
120
140
// close the database.
121
- const openNamedDatabase = ( testCase , databaseName , version ) => {
141
+ function openNamedDatabase ( testCase , databaseName , version ) {
122
142
const request = indexedDB . open ( databaseName , version ) ;
123
143
const eventWatcher = requestWatcher ( testCase , request ) ;
124
144
return eventWatcher . wait_for ( 'success' ) . then ( event => event . target . result ) ;
@@ -142,24 +162,24 @@ const createBooksStore = (testCase, database) => {
142
162
for ( let record of BOOKS_RECORD_DATA )
143
163
store . put ( record ) ;
144
164
return store ;
145
- } ;
165
+ }
146
166
147
167
// Creates a 'not_books' object store used to test renaming into existing or
148
168
// deleted store names.
149
- const createNotBooksStore = ( testCase , database ) => {
150
- const store = database . createObjectStore ( 'not_books' ) ;
151
- store . createIndex ( 'not_by_author' , 'author' ) ;
152
- store . createIndex ( 'not_by_title' , 'title' , { unique : true } ) ;
153
- return store ;
154
- } ;
169
+ function createNotBooksStore ( testCase , database ) {
170
+ const store = database . createObjectStore ( 'not_books' ) ;
171
+ store . createIndex ( 'not_by_author' , 'author' ) ;
172
+ store . createIndex ( 'not_by_title' , 'title' , { unique : true } ) ;
173
+ return store ;
174
+ }
155
175
156
176
// Verifies that an object store's indexes match the indexes used to create the
157
177
// books store in the test database's version 1.
158
178
//
159
179
// The errorMessage is used if the assertions fail. It can state that the
160
180
// IndexedDB implementation being tested is incorrect, or that the testing code
161
181
// is using it incorrectly.
162
- const checkStoreIndexes = ( testCase , store , errorMessage ) => {
182
+ function checkStoreIndexes ( testCase , store , errorMessage ) {
163
183
assert_array_equals (
164
184
store . indexNames , [ 'by_author' , 'by_title' ] , errorMessage ) ;
165
185
const authorIndex = store . index ( 'by_author' ) ;
@@ -168,31 +188,31 @@ const checkStoreIndexes = (testCase, store, errorMessage) => {
168
188
checkAuthorIndexContents ( testCase , authorIndex , errorMessage ) ,
169
189
checkTitleIndexContents ( testCase , titleIndex , errorMessage ) ,
170
190
] ) ;
171
- } ;
191
+ }
172
192
173
193
// Verifies that an object store's key generator is in the same state as the
174
194
// key generator created for the books store in the test database's version 1.
175
195
//
176
196
// The errorMessage is used if the assertions fail. It can state that the
177
197
// IndexedDB implementation being tested is incorrect, or that the testing code
178
198
// is using it incorrectly.
179
- const checkStoreGenerator = ( testCase , store , expectedKey , errorMessage ) => {
199
+ function checkStoreGenerator ( testCase , store , expectedKey , errorMessage ) {
180
200
const request = store . put (
181
201
{ title : 'Bedrock Nights ' + expectedKey , author : 'Barney' } ) ;
182
202
const eventWatcher = requestWatcher ( testCase , request ) ;
183
203
return eventWatcher . wait_for ( 'success' ) . then ( ( ) => {
184
204
const result = request . result ;
185
205
assert_equals ( result , expectedKey , errorMessage ) ;
186
206
} ) ;
187
- } ;
207
+ }
188
208
189
209
// Verifies that an object store's contents matches the contents used to create
190
210
// the books store in the test database's version 1.
191
211
//
192
212
// The errorMessage is used if the assertions fail. It can state that the
193
213
// IndexedDB implementation being tested is incorrect, or that the testing code
194
214
// is using it incorrectly.
195
- const checkStoreContents = ( testCase , store , errorMessage ) => {
215
+ function checkStoreContents ( testCase , store , errorMessage ) {
196
216
const request = store . get ( 123456 ) ;
197
217
const eventWatcher = requestWatcher ( testCase , request ) ;
198
218
return eventWatcher . wait_for ( 'success' ) . then ( ( ) => {
@@ -201,36 +221,36 @@ const checkStoreContents = (testCase, store, errorMessage) => {
201
221
assert_equals ( result . author , BOOKS_RECORD_DATA [ 0 ] . author , errorMessage ) ;
202
222
assert_equals ( result . title , BOOKS_RECORD_DATA [ 0 ] . title , errorMessage ) ;
203
223
} ) ;
204
- } ;
224
+ }
205
225
206
226
// Verifies that index matches the 'by_author' index used to create the
207
227
// by_author books store in the test database's version 1.
208
228
//
209
229
// The errorMessage is used if the assertions fail. It can state that the
210
230
// IndexedDB implementation being tested is incorrect, or that the testing code
211
231
// is using it incorrectly.
212
- const checkAuthorIndexContents = ( testCase , index , errorMessage ) => {
232
+ function checkAuthorIndexContents ( testCase , index , errorMessage ) {
213
233
const request = index . get ( BOOKS_RECORD_DATA [ 2 ] . author ) ;
214
234
const eventWatcher = requestWatcher ( testCase , request ) ;
215
235
return eventWatcher . wait_for ( 'success' ) . then ( ( ) => {
216
236
const result = request . result ;
217
237
assert_equals ( result . isbn , BOOKS_RECORD_DATA [ 2 ] . isbn , errorMessage ) ;
218
238
assert_equals ( result . title , BOOKS_RECORD_DATA [ 2 ] . title , errorMessage ) ;
219
239
} ) ;
220
- } ;
240
+ }
221
241
222
242
// Verifies that an index matches the 'by_title' index used to create the books
223
243
// store in the test database's version 1.
224
244
//
225
245
// The errorMessage is used if the assertions fail. It can state that the
226
246
// IndexedDB implementation being tested is incorrect, or that the testing code
227
247
// is using it incorrectly.
228
- const checkTitleIndexContents = ( testCase , index , errorMessage ) => {
248
+ function checkTitleIndexContents ( testCase , index , errorMessage ) {
229
249
const request = index . get ( BOOKS_RECORD_DATA [ 2 ] . title ) ;
230
250
const eventWatcher = requestWatcher ( testCase , request ) ;
231
251
return eventWatcher . wait_for ( 'success' ) . then ( ( ) => {
232
252
const result = request . result ;
233
253
assert_equals ( result . isbn , BOOKS_RECORD_DATA [ 2 ] . isbn , errorMessage ) ;
234
254
assert_equals ( result . author , BOOKS_RECORD_DATA [ 2 ] . author , errorMessage ) ;
235
255
} ) ;
236
- } ;
256
+ }
0 commit comments