more WPTs
This commit is contained in:
parent
f9df95ded5
commit
c363458374
@ -1,5 +1,5 @@
|
||||
import test from "ava";
|
||||
import { createdb, idbFactory } from "./wptsupport";
|
||||
import { createdb, format_value, idbFactory } from "./wptsupport";
|
||||
|
||||
// IDBFactory.open() - request has no source
|
||||
test("WPT idbfactory-open.htm", async (t) => {
|
||||
@ -57,19 +57,411 @@ test("WPT idbfactory-open3.htm", async (t) => {
|
||||
t.pass();
|
||||
});
|
||||
|
||||
|
||||
// IDBFactory.open() - new database has default version
|
||||
test("WPT idbfactory-open4.htm", async (t) => {
|
||||
const indexedDB = idbFactory;
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
var open_rq = createdb(t, __filename + '-database_name');
|
||||
var open_rq = createdb(t, __filename + "-database_name");
|
||||
|
||||
open_rq.onupgradeneeded = function(e: any) {
|
||||
t.deepEqual(e.target.result.version, 1, "db.version");
|
||||
open_rq.onupgradeneeded = function (e: any) {
|
||||
t.deepEqual(e.target.result.version, 1, "db.version");
|
||||
};
|
||||
open_rq.onsuccess = function(e: any) {
|
||||
t.deepEqual(e.target.result.version, 1, "db.version");
|
||||
resolve();
|
||||
open_rq.onsuccess = function (e: any) {
|
||||
t.deepEqual(e.target.result.version, 1, "db.version");
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
t.pass();
|
||||
});
|
||||
|
||||
// IDBFactory.open() - new database is empty
|
||||
test("WPT idbfactory-open5.htm", async (t) => {
|
||||
const indexedDB = idbFactory;
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
var open_rq = createdb(t, __filename + "-database_name");
|
||||
|
||||
open_rq.onupgradeneeded = function () {};
|
||||
open_rq.onsuccess = function (e: any) {
|
||||
t.deepEqual(
|
||||
e.target.result.objectStoreNames.length,
|
||||
0,
|
||||
"objectStoreNames.length",
|
||||
);
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
t.pass();
|
||||
});
|
||||
|
||||
// IDBFactory.open() - open database with a lower version than current
|
||||
test("WPT idbfactory-open6.htm", async (t) => {
|
||||
const indexedDB = idbFactory;
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
var open_rq = createdb(t, undefined, 13);
|
||||
var did_upgrade = false;
|
||||
var open_rq2: any;
|
||||
|
||||
open_rq.onupgradeneeded = function () {};
|
||||
open_rq.onsuccess = function (e: any) {
|
||||
var db = e.target.result;
|
||||
db.close();
|
||||
|
||||
open_rq2 = indexedDB.open(db.name, 14);
|
||||
open_rq2.onupgradeneeded = function () {};
|
||||
open_rq2.onsuccess = open_previous_db;
|
||||
open_rq2.onerror = () => t.fail("Unexpected error");
|
||||
};
|
||||
|
||||
function open_previous_db(e: any) {
|
||||
var open_rq3 = indexedDB.open(e.target.result.name, 13);
|
||||
open_rq3.onerror = function (e: any) {
|
||||
t.deepEqual(e.target.error.name, "VersionError", "e.target.error.name");
|
||||
open_rq2.result.close();
|
||||
resolve();
|
||||
};
|
||||
open_rq3.onupgradeneeded = () => t.fail("Unexpected upgradeneeded");
|
||||
open_rq3.onsuccess = () => t.fail("Unexpected success");
|
||||
}
|
||||
});
|
||||
t.pass();
|
||||
});
|
||||
|
||||
// IDBFactory.open() - open database with a higher version than current
|
||||
test("WPT idbfactory-open7.htm", async (t) => {
|
||||
const indexedDB = idbFactory;
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
var open_rq = createdb(t, undefined, 13);
|
||||
var did_upgrade = false;
|
||||
var open_rq2: any;
|
||||
|
||||
open_rq.onupgradeneeded = function () {};
|
||||
open_rq.onsuccess = function (e: any) {
|
||||
var db = e.target.result;
|
||||
db.close();
|
||||
|
||||
open_rq2 = indexedDB.open(db.name, 14);
|
||||
open_rq2.onupgradeneeded = function () {
|
||||
did_upgrade = true;
|
||||
};
|
||||
open_rq2.onsuccess = open_current_db;
|
||||
open_rq2.onerror = () => t.fail("Unexpected error");
|
||||
};
|
||||
|
||||
function open_current_db(e: any) {
|
||||
var open_rq3 = indexedDB.open(e.target.result.name);
|
||||
open_rq3.onsuccess = function (e: any) {
|
||||
t.deepEqual(e.target.result.version, 14, "db.version");
|
||||
open_rq2.result.close();
|
||||
open_rq3.result.close();
|
||||
resolve();
|
||||
};
|
||||
open_rq3.onupgradeneeded = () => t.fail("Unexpected upgradeneeded");
|
||||
open_rq3.onerror = () => t.fail("Unexpected error");
|
||||
|
||||
t.true(did_upgrade, "did upgrade");
|
||||
}
|
||||
});
|
||||
t.pass();
|
||||
});
|
||||
|
||||
// IDBFactory.open() - error in version change transaction aborts open
|
||||
test("WPT idbfactory-open8.htm", async (t) => {
|
||||
const indexedDB = idbFactory;
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
var open_rq = createdb(t, undefined, 13);
|
||||
var did_upgrade = false;
|
||||
var did_db_abort = false;
|
||||
|
||||
open_rq.onupgradeneeded = function (e: any) {
|
||||
did_upgrade = true;
|
||||
e.target.result.onabort = function () {
|
||||
did_db_abort = true;
|
||||
};
|
||||
e.target.transaction.abort();
|
||||
};
|
||||
open_rq.onerror = function (e: any) {
|
||||
t.true(did_upgrade);
|
||||
t.deepEqual(e.target.error.name, "AbortError", "target.error");
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
t.pass();
|
||||
});
|
||||
|
||||
// IDBFactory.open() - errors in version argument
|
||||
test("WPT idbfactory-open9.htm", async (t) => {
|
||||
const indexedDB = idbFactory;
|
||||
function should_throw(val: any, name?: string) {
|
||||
if (!name) {
|
||||
name = typeof val == "object" && val ? "object" : format_value(val);
|
||||
}
|
||||
t.throws(
|
||||
() => {
|
||||
indexedDB.open("test", val);
|
||||
},
|
||||
{ instanceOf: TypeError },
|
||||
"Calling open() with version argument " +
|
||||
name +
|
||||
" should throw TypeError.",
|
||||
);
|
||||
}
|
||||
|
||||
should_throw(-1);
|
||||
should_throw(-0.5);
|
||||
should_throw(0);
|
||||
should_throw(0.5);
|
||||
should_throw(0.8);
|
||||
should_throw(0x20000000000000); // Number.MAX_SAFE_INTEGER + 1
|
||||
should_throw(NaN);
|
||||
should_throw(Infinity);
|
||||
should_throw(-Infinity);
|
||||
should_throw("foo");
|
||||
should_throw(null);
|
||||
should_throw(false);
|
||||
|
||||
should_throw({
|
||||
toString: function () {
|
||||
t.fail("toString should not be called for ToPrimitive [Number]");
|
||||
},
|
||||
valueOf: function () {
|
||||
return 0;
|
||||
},
|
||||
});
|
||||
should_throw(
|
||||
{
|
||||
toString: function () {
|
||||
return 0;
|
||||
},
|
||||
valueOf: function () {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
"object (second)",
|
||||
);
|
||||
should_throw(
|
||||
{
|
||||
toString: function () {
|
||||
return {};
|
||||
},
|
||||
valueOf: function () {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
"object (third)",
|
||||
);
|
||||
|
||||
/* Valid */
|
||||
|
||||
async function should_work(val: any, expected_version: number) {
|
||||
var name = format_value(val);
|
||||
var dbname = "test-db-does-not-exist";
|
||||
|
||||
await t.notThrowsAsync(async () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
indexedDB.deleteDatabase(dbname);
|
||||
var rq = indexedDB.open(dbname, val);
|
||||
rq.onupgradeneeded = function () {
|
||||
var db = rq.result;
|
||||
t.deepEqual(db.version, expected_version, "version");
|
||||
rq!.transaction!.abort();
|
||||
};
|
||||
rq.onsuccess = () => t.fail("open should fail");
|
||||
rq.onerror = () => resolve();
|
||||
});
|
||||
}, "Calling open() with version argument " + name + " should not throw.");
|
||||
}
|
||||
|
||||
await should_work(1.5, 1);
|
||||
await should_work(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER); // 0x20000000000000 - 1
|
||||
await should_work(undefined, 1);
|
||||
});
|
||||
|
||||
// IDBFactory.open() - error in version change transaction aborts open
|
||||
test("WPT idbfactory-open10.htm", async (t) => {
|
||||
const indexedDB = idbFactory;
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
var db: any, db2: any;
|
||||
var open_rq = createdb(t, undefined, 9);
|
||||
|
||||
open_rq.onupgradeneeded = function (e: any) {
|
||||
db = e.target.result;
|
||||
|
||||
var st = db.createObjectStore("store");
|
||||
st.createIndex("index", "i");
|
||||
|
||||
t.deepEqual(db.version, 9, "first db.version");
|
||||
t.true(
|
||||
db.objectStoreNames.contains("store"),
|
||||
"objectStoreNames contains store",
|
||||
);
|
||||
t.true(st.indexNames.contains("index"), "indexNames contains index");
|
||||
|
||||
st.add({ i: "Joshua" }, 1);
|
||||
st.add({ i: "Jonas" }, 2);
|
||||
};
|
||||
open_rq.onsuccess = function (e) {
|
||||
db.close();
|
||||
var open_rq2 = indexedDB.open(db.name, 10);
|
||||
open_rq2.onupgradeneeded = function (e: any) {
|
||||
db2 = e.target.result;
|
||||
|
||||
db2.createObjectStore("store2");
|
||||
|
||||
var store = open_rq2.transaction!.objectStore("store");
|
||||
store.createIndex("index2", "i");
|
||||
|
||||
t.deepEqual(db2.version, 10, "db2.version");
|
||||
|
||||
t.true(
|
||||
db2.objectStoreNames.contains("store"),
|
||||
"second objectStoreNames contains store",
|
||||
);
|
||||
t.true(
|
||||
db2.objectStoreNames.contains("store2"),
|
||||
"second objectStoreNames contains store2",
|
||||
);
|
||||
t.true(
|
||||
store.indexNames.contains("index"),
|
||||
"second indexNames contains index",
|
||||
);
|
||||
t.true(
|
||||
store.indexNames.contains("index2"),
|
||||
"second indexNames contains index2",
|
||||
);
|
||||
|
||||
store.add({ i: "Odin" }, 3);
|
||||
store.put({ i: "Sicking" }, 2);
|
||||
|
||||
open_rq2.transaction!.abort();
|
||||
};
|
||||
open_rq2.onerror = function () {
|
||||
t.deepEqual(db2.version, 9, "db2.version after error");
|
||||
t.true(
|
||||
db2.objectStoreNames.contains("store"),
|
||||
"objectStoreNames contains store after error",
|
||||
);
|
||||
t.false(
|
||||
db2.objectStoreNames.contains("store2"),
|
||||
"objectStoreNames not contains store2 after error",
|
||||
);
|
||||
|
||||
var open_rq3 = indexedDB.open(db.name);
|
||||
open_rq3.onsuccess = function (e: any) {
|
||||
var db3 = e.target.result;
|
||||
|
||||
t.true(
|
||||
db3.objectStoreNames.contains("store"),
|
||||
"third objectStoreNames contains store",
|
||||
);
|
||||
t.false(
|
||||
db3.objectStoreNames.contains("store2"),
|
||||
"third objectStoreNames contains store2",
|
||||
);
|
||||
|
||||
var st = db3.transaction("store").objectStore("store");
|
||||
|
||||
t.deepEqual(db3.version, 9, "db3.version");
|
||||
|
||||
t.true(
|
||||
st.indexNames.contains("index"),
|
||||
"third indexNames contains index",
|
||||
);
|
||||
t.false(
|
||||
st.indexNames.contains("index2"),
|
||||
"third indexNames contains index2",
|
||||
);
|
||||
|
||||
st.openCursor(null, "prev").onsuccess = function (e: any) {
|
||||
t.deepEqual(e.target.result.key, 2, "opencursor(prev) key");
|
||||
t.deepEqual(
|
||||
e.target.result.value.i,
|
||||
"Jonas",
|
||||
"opencursor(prev) value",
|
||||
);
|
||||
};
|
||||
st.get(3).onsuccess = function (e: any) {
|
||||
t.deepEqual(e.target.result, undefined, "get(3)");
|
||||
};
|
||||
|
||||
var idx = st.index("index");
|
||||
idx.getKey("Jonas").onsuccess = function (e: any) {
|
||||
t.deepEqual(e.target.result, 2, "getKey(Jonas)");
|
||||
};
|
||||
idx.getKey("Odin").onsuccess = function (e: any) {
|
||||
t.deepEqual(e.target.result, undefined, "getKey(Odin)");
|
||||
};
|
||||
idx.getKey("Sicking").onsuccess = function (e: any) {
|
||||
t.deepEqual(e.target.result, undefined, "getKey(Sicking)");
|
||||
db3.close();
|
||||
resolve();
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
t.pass();
|
||||
});
|
||||
|
||||
// IDBFactory.open() - second open's transaction is available to get objectStores
|
||||
test("WPT idbfactory-open11.htm", async (t) => {
|
||||
const indexedDB = idbFactory;
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
var db: any;
|
||||
var count_done = 0;
|
||||
var open_rq = createdb(t);
|
||||
|
||||
open_rq.onupgradeneeded = function (e: any) {
|
||||
db = e.target.result;
|
||||
|
||||
db.createObjectStore("store");
|
||||
assert_true(
|
||||
db.objectStoreNames.contains("store"),
|
||||
"objectStoreNames contains store",
|
||||
);
|
||||
|
||||
var store = e.target.transaction.objectStore("store");
|
||||
assert_equals(store.name, "store", "store.name");
|
||||
|
||||
store.add("data", 1);
|
||||
|
||||
store.count().onsuccess = this.step_func(function (e) {
|
||||
assert_equals(e.target.result, 1, "count()");
|
||||
count_done++;
|
||||
});
|
||||
|
||||
store.add("data2", 2);
|
||||
};
|
||||
open_rq.onsuccess = function (e) {
|
||||
var store = db.transaction("store").objectStore("store");
|
||||
assert_equals(store.name, "store", "store.name");
|
||||
store.count().onsuccess = this.step_func(function (e) {
|
||||
assert_equals(e.target.result, 2, "count()");
|
||||
count_done++;
|
||||
});
|
||||
db.close();
|
||||
|
||||
var open_rq2 = indexedDB.open(db.name, 10);
|
||||
open_rq2.onupgradeneeded = function (e: any) {
|
||||
var db2 = e.target.result;
|
||||
t.true(
|
||||
db2.objectStoreNames.contains("store"),
|
||||
"objectStoreNames contains store",
|
||||
);
|
||||
var store = open_rq2.transaction!.objectStore("store");
|
||||
t.deepEqual(store.name, "store", "store.name");
|
||||
|
||||
store.add("data3", 3);
|
||||
|
||||
store.count().onsuccess = function (e: any) {
|
||||
t.deepEqual(e.target.result, 3, "count()");
|
||||
count_done++;
|
||||
|
||||
t.deepEqual(count_done, 3, "count_done");
|
||||
|
||||
db2.close();
|
||||
resolve();
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
t.pass();
|
||||
|
@ -301,3 +301,124 @@ export function createNotBooksStore(
|
||||
store.createIndex("not_by_title", "title", { unique: true });
|
||||
return store;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string truncated to the given length, with ... added at the end
|
||||
* if it was longer.
|
||||
*/
|
||||
function truncate(s: string, len: number): string {
|
||||
if (s.length > len) {
|
||||
return s.substring(0, len - 3) + "...";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
var replacements = {
|
||||
"0": "0",
|
||||
"1": "x01",
|
||||
"2": "x02",
|
||||
"3": "x03",
|
||||
"4": "x04",
|
||||
"5": "x05",
|
||||
"6": "x06",
|
||||
"7": "x07",
|
||||
"8": "b",
|
||||
"9": "t",
|
||||
"10": "n",
|
||||
"11": "v",
|
||||
"12": "f",
|
||||
"13": "r",
|
||||
"14": "x0e",
|
||||
"15": "x0f",
|
||||
"16": "x10",
|
||||
"17": "x11",
|
||||
"18": "x12",
|
||||
"19": "x13",
|
||||
"20": "x14",
|
||||
"21": "x15",
|
||||
"22": "x16",
|
||||
"23": "x17",
|
||||
"24": "x18",
|
||||
"25": "x19",
|
||||
"26": "x1a",
|
||||
"27": "x1b",
|
||||
"28": "x1c",
|
||||
"29": "x1d",
|
||||
"30": "x1e",
|
||||
"31": "x1f",
|
||||
"0xfffd": "ufffd",
|
||||
"0xfffe": "ufffe",
|
||||
"0xffff": "uffff",
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert a value to a nice, human-readable string
|
||||
*/
|
||||
export function format_value(val: any, seen?: any): string {
|
||||
if (!seen) {
|
||||
seen = [];
|
||||
}
|
||||
if (typeof val === "object" && val !== null) {
|
||||
if (seen.indexOf(val) >= 0) {
|
||||
return "[...]";
|
||||
}
|
||||
seen.push(val);
|
||||
}
|
||||
if (Array.isArray(val)) {
|
||||
let output = "[";
|
||||
// @ts-ignore
|
||||
if (val.beginEllipsis !== undefined) {
|
||||
output += "…, ";
|
||||
}
|
||||
output += val
|
||||
.map(function (x) {
|
||||
return format_value(x, seen);
|
||||
})
|
||||
.join(", ");
|
||||
// @ts-ignore
|
||||
if (val.endEllipsis !== undefined) {
|
||||
output += ", …";
|
||||
}
|
||||
return output + "]";
|
||||
}
|
||||
|
||||
switch (typeof val) {
|
||||
case "string":
|
||||
val = val.replace(/\\/g, "\\\\");
|
||||
for (var p in replacements) {
|
||||
// @ts-ignore
|
||||
var replace = "\\" + replacements[p];
|
||||
// @ts-ignore
|
||||
val = val.replace(RegExp(String.fromCharCode(p), "g"), replace);
|
||||
}
|
||||
return '"' + val.replace(/"/g, '\\"') + '"';
|
||||
case "boolean":
|
||||
case "undefined":
|
||||
return String(val);
|
||||
case "number":
|
||||
// In JavaScript, -0 === 0 and String(-0) == "0", so we have to
|
||||
// special-case.
|
||||
if (val === -0 && 1 / val === -Infinity) {
|
||||
return "-0";
|
||||
}
|
||||
return String(val);
|
||||
case "object":
|
||||
if (val === null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
/* falls through */
|
||||
default:
|
||||
try {
|
||||
return typeof val + ' "' + truncate(String(val), 1000) + '"';
|
||||
} catch (e) {
|
||||
return (
|
||||
"[stringifying object threw " +
|
||||
String(e) +
|
||||
" with type " +
|
||||
String(typeof e) +
|
||||
"]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user