library IndexedDB1Test; import 'package:unittest/unittest.dart'; import 'package:unittest/html_individual_config.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) { var store = e.target.result.createObjectStore(storeName); expect(store, isNotNull); } var db; return html.window.indexedDB.deleteDatabase(dbName).then((_) { return html.window.indexedDB.open(dbName, version: version, onUpgradeNeeded: createObjectStore); }).then((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(() { if (db != null) { db.close(); } return html.window.indexedDB.deleteDatabase(dbName); }); }; testReadWriteTyped(key, value, matcher, [dbName, 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); } 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(() { if (db != null) { db.close(); } 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() { useHtmlIndividualConfiguration(); // 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('supportsDatabaseNames', () { test('supported', () { expect(html.window.indexedDB.supportsDatabaseNames, isTrue); }); }); 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); }); } }); }