| // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library IndexedDB1Test; |
| |
| import 'package:async_helper/async_minitest.dart'; |
| import 'dart:async'; |
| import 'dart:html' as html; |
| import 'dart:math' as math; |
| import 'dart:indexed_db' as idb; |
| |
| const String STORE_NAME = 'TEST'; |
| const int VERSION = 1; |
| |
| var databaseNameIndex = 0; |
| String nextDatabaseName() { |
| return 'Test1_${databaseNameIndex++}'; |
| } |
| |
| Future testUpgrade() { |
| var dbName = nextDatabaseName(); |
| var upgraded = false; |
| |
| // Delete any existing DBs. |
| return html.window.indexedDB!.deleteDatabase(dbName).then((_) { |
| return html.window.indexedDB! |
| .open(dbName, version: 1, onUpgradeNeeded: (e) {}); |
| }).then((db) { |
| db.close(); |
| }).then((_) { |
| return html.window.indexedDB!.open(dbName, version: 2, |
| onUpgradeNeeded: (e) { |
| expect(e.oldVersion, 1); |
| expect(e.newVersion, 2); |
| upgraded = true; |
| }); |
| }).then((_) { |
| expect(upgraded, isTrue); |
| }); |
| } |
| |
| testReadWrite(key, value, matcher, |
| [dbName, |
| storeName = STORE_NAME, |
| version = VERSION, |
| stringifyResult = false]) => |
| () { |
| if (dbName == null) { |
| dbName = nextDatabaseName(); |
| } |
| createObjectStore(e) { |
| idb.ObjectStore store = e.target.result.createObjectStore(storeName); |
| expect(store, isNotNull); |
| } |
| |
| late idb.Database db; |
| return html.window.indexedDB!.deleteDatabase(dbName).then((_) { |
| return html.window.indexedDB! |
| .open(dbName, version: version, onUpgradeNeeded: createObjectStore); |
| }).then((idb.Database result) { |
| db = result; |
| var transaction = db.transactionList([storeName], 'readwrite'); |
| transaction.objectStore(storeName).put(value, key); |
| return transaction.completed; |
| }).then((_) { |
| var transaction = db.transaction(storeName, 'readonly'); |
| return transaction.objectStore(storeName).getObject(key); |
| }).then((object) { |
| db.close(); |
| if (stringifyResult) { |
| // Stringify the numbers to verify that we're correctly returning ints |
| // as ints vs doubles. |
| expect(object.toString(), matcher); |
| } else { |
| expect(object, matcher); |
| } |
| }).whenComplete(() { |
| return html.window.indexedDB!.deleteDatabase(dbName); |
| }); |
| }; |
| |
| testReadWriteTyped(key, value, matcher, |
| [dbName, |
| String storeName = STORE_NAME, |
| version = VERSION, |
| stringifyResult = false]) => |
| () { |
| if (dbName == null) { |
| dbName = nextDatabaseName(); |
| } |
| void createObjectStore(e) { |
| var store = e.target.result.createObjectStore(storeName); |
| expect(store, isNotNull); |
| } |
| |
| late idb.Database db; |
| // Delete any existing DBs. |
| return html.window.indexedDB!.deleteDatabase(dbName).then((_) { |
| return html.window.indexedDB! |
| .open(dbName, version: version, onUpgradeNeeded: createObjectStore); |
| }).then((idb.Database result) { |
| db = result; |
| idb.Transaction transaction = |
| db.transactionList([storeName], 'readwrite'); |
| transaction.objectStore(storeName).put(value, key); |
| |
| return transaction.completed; |
| }).then((idb.Database result) { |
| idb.Transaction transaction = db.transaction(storeName, 'readonly'); |
| return transaction.objectStore(storeName).getObject(key); |
| }).then((object) { |
| db.close(); |
| if (stringifyResult) { |
| // Stringify the numbers to verify that we're correctly returning ints |
| // as ints vs doubles. |
| expect(object.toString(), matcher); |
| } else { |
| expect(object, matcher); |
| } |
| }).whenComplete(() { |
| return html.window.indexedDB!.deleteDatabase(dbName); |
| }); |
| }; |
| |
| void testTypes(testFunction) { |
| test('String', testFunction(123, 'Hoot!', equals('Hoot!'))); |
| test('int', testFunction(123, 12345, equals(12345))); |
| test('List', testFunction(123, [1, 2, 3], equals([1, 2, 3]))); |
| test('List 2', testFunction(123, [2, 3, 4], equals([2, 3, 4]))); |
| test('bool', testFunction(123, [true, false], equals([true, false]))); |
| test( |
| 'largeInt', |
| testFunction(123, 1371854424211, equals("1371854424211"), null, |
| STORE_NAME, VERSION, true)); |
| test( |
| 'largeDoubleConvertedToInt', |
| testFunction(123, 1371854424211.0, equals("1371854424211"), null, |
| STORE_NAME, VERSION, true)); |
| test( |
| 'largeIntInMap', |
| testFunction(123, {'time': 4503599627370492}, |
| equals("{time: 4503599627370492}"), null, STORE_NAME, VERSION, true)); |
| var now = new DateTime.now(); |
| test( |
| 'DateTime', |
| testFunction( |
| 123, |
| now, |
| predicate((date) => |
| date.millisecondsSinceEpoch == now.millisecondsSinceEpoch))); |
| } |
| |
| main() { |
| // Test that indexed_db is properly flagged as supported or not. |
| // Note that the rest of the indexed_db tests assume that this has been |
| // checked. |
| group('supported', () { |
| test('supported', () { |
| expect(idb.IdbFactory.supported, true); |
| }); |
| }); |
| |
| group('functional', () { |
| test('throws when unsupported', () { |
| var expectation = idb.IdbFactory.supported ? returnsNormally : throws; |
| |
| expect(() { |
| var db = html.window.indexedDB!; |
| db.open('random_db'); |
| }, expectation); |
| }); |
| |
| // Don't bother with these tests if it's unsupported. |
| if (idb.IdbFactory.supported) { |
| test('upgrade', testUpgrade); |
| group('dynamic', () { |
| testTypes(testReadWrite); |
| }); |
| group('typed', () { |
| testTypes(testReadWriteTyped); |
| }); |
| } |
| }); |
| } |