blob: 378a48a0cdd59805d8c793dad822af9f251013a4 [file] [log] [blame]
// 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:expect/legacy/async_minitest.dart'; // ignore: deprecated_member_use
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);
});
}
});
}