diff --git a/spec/unit/stores/indexeddb.spec.ts b/spec/unit/stores/indexeddb.spec.ts index 4a1c9edd8..899b26833 100644 --- a/spec/unit/stores/indexeddb.spec.ts +++ b/spec/unit/stores/indexeddb.spec.ts @@ -79,6 +79,41 @@ describe("IndexedDBStore", () => { expect(await store.getOutOfBandMembers(roomId)).toHaveLength(2); }); + it("should handle failed queries", async () => { + const store = new IndexedDBStore({ + indexedDB: indexedDB, + dbName: "database", + localStorage, + }); + await store.startup(); + + // Simulate a failed query + let txn: IDBRequest; + (store.backend as LocalIndexedDBStoreBackend)["db"]!.transaction = (): IDBTransaction => { + return { + objectStore: (name: string) => + ({ + name, + openCursor: (query: unknown) => { + return (txn = { + error: new DOMException("Expected error"), + } as IDBRequest); + }, + }) as IDBObjectStore, + } as IDBTransaction; + }; + + // Call backend directly as otherwise the error is masked. + const promise = store.backend.getClientOptions(); + // The function uses a Promise.then(() => trick to delay execution + // so we need to wait before we can call the txn onerror handler. + process.nextTick(() => { + txn!.onerror!(new Event("we-ignore-this")); + }); + + await expect(() => promise).rejects.toThrow("selectQuery failed for client_options"); + }); + it("Should load presence events on startup", async () => { // 1. Create idb database const indexedDB = new IDBFactory(); diff --git a/src/store/indexeddb-local-backend.ts b/src/store/indexeddb-local-backend.ts index c1c8b85c6..25b18611e 100644 --- a/src/store/indexeddb-local-backend.ts +++ b/src/store/indexeddb-local-backend.ts @@ -61,6 +61,7 @@ const VERSION = DB_MIGRATIONS.length; * Return the data you want to keep. * @returns Promise which resolves to an array of whatever you returned from * resultMapper. + * @throws If there was an error completing the query. */ function selectQuery( store: IDBObjectStore, @@ -71,7 +72,7 @@ function selectQuery( return new Promise((resolve, reject) => { const results: T[] = []; query.onerror = (): void => { - reject(new Error("Query failed: " + query.error?.name)); + reject(new Error(`selectQuery failed for ${store.name}`, { cause: query.error })); }; // collect results query.onsuccess = (): void => {