mrkeyoor.com_
Tue 22 Sept 22:37 UTC
npmTestingupdated 22 Sept 2026

fake-indexeddb review

fake-indexeddb 6.2.5 is an in-memory JavaScript implementation of the browser IndexedDB API for tests that run under Node. Importing `fake-indexeddb/auto` installs IndexedDB globals, while named exports let a test inject its own factory and key-range object. The current release adds `handleEvent` and capture support to its event layer and fixes transaction-timing edge cases. It never writes a database to disk. Its README reports 1,369 of 1,653 relevant IndexedDB Web Platform Tests passing, or 82.8%, so browser coverage still matters for behavior outside the common path.

Verdict

fake-indexeddb 6.2.5 installed in 0.7 seconds, used 1 MB, and produced 0 audit findings in our sandbox, making it a cheap Node test dependency for ordinary IndexedDB flows. Keep real-browser coverage because the project reports 82.8% of its relevant Web Platform Tests passing and does not persist data to disk.

We installed it

Lab card: what happened when we installed fake-indexeddbScreenshot of fake-indexeddb documentation
Install✓ · 0.7s3 packages on disk · 1 MB
ImportESM import works · require() works · ESM package with exports map
Browser14.8 KBgzipped (55.7 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does fake-indexeddb install cleanly?

Yes. In a fresh container with an empty cache, npm install fake-indexeddb finished in 0.7s, leaving 3 packages and 1 MB on disk. npm audit reported no known vulnerabilities.

How much does fake-indexeddb add to a browser bundle?

14.8 KB gzipped (55.7 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does fake-indexeddb work with both ESM and CommonJS?

Yes. Both import 'fake-indexeddb' and require('fake-indexeddb') worked in Node 22 in our run. The package is published as ESM with an exports map.

Does fake-indexeddb include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

fake-indexeddb or indexeddbshim: which should you use?

indexeddbshim: Use it when an older environment needs IndexedDB behavior backed by WebSQL rather than an in-memory Node test double. fake-indexeddb 6.2.5 installed in 0.7 seconds, used 1 MB, and produced 0 audit findings in our sandbox, making it a cheap Node test dependency for ordinary IndexedDB flows.

When should you not use fake-indexeddb?

Your test must prove persistence across processes or restarts. The README states that this implementation keeps data in memory and does not persist it to disk.

API stability4/5Version 6.2.5 follows the standard IndexedDB names and event model, so application code can usually swap between the fake factory and a browser implementation. The package has explicit root, auto, and individual-class exports for both ESM and CommonJS. Compatibility is not exact: `forceCloseDatabase()` is project-specific, the declarations reuse TypeScript's DOM types, and the project's own test table records 1,369 passes out of 1,653 relevant cases.
Docs4/5The README shows global and explicit imports, Dexie injection, Jest setup, jsdom `structuredClone` workarounds, factory resets, forced close events, and a full request-and-cursor example. It also publishes the exact Web Platform Test comparison and explains excluded browser cases. Guidance is concentrated in one long page, and there is no separate API reference for the nonstandard helpers or a compatibility matrix by IndexedDB feature.
Maintenance4/5GitHub shows an unarchived repository pushed on May 13, 2026, with 7 open issues and pull requests. Release 6.2.5 shipped on November 7, 2025 and contains specific event-compatibility and transaction-timing fixes, following four other 6.2 patch releases over roughly ten weeks. That cadence shows active conformance work, though the repository is small and its release notes do not promise a support window.
Ecosystem4/5The npm downloads endpoint counted 5,381,207 downloads in the latest completed week, and GitHub reports 690 stars. The README documents direct use with Jest and Dexie and says other IndexedDB wrappers such as idb follow the same injection pattern. Bundled DOM-compatible TypeScript declarations and working ESM and CommonJS entry points make it easy to fit into mixed test stacks, while its narrow Node-testing role limits the surrounding plugin ecosystem.

Use it if

  • Your Node test suite needs to exercise real IndexedDB requests, transactions, indexes, cursors, and upgrade callbacks without launching a browser.
  • Application code already uses Dexie or idb and can receive an IndexedDB factory explicitly or through test-only globals.
  • Each test can start from a new `IDBFactory`, which gives deterministic database state without filesystem cleanup.
  • You need both CommonJS and ESM test runners; our sandbox loaded 6.2.5 through `require()` and `import`.
Skip it if

Setup reality

We installed fake-indexeddb 6.2.5 in a fresh Node 22 Bookworm sandbox. npm finished in 0.7 seconds and left 3 packages using 1 MB on disk. The package itself is 708 KB unpacked with 0 direct and 0 peer dependencies. npm audit found 0 known vulnerabilities. It requires Node 18 or newer and includes TypeScript declarations.

Choose the import style before tests start. fake-indexeddb/auto writes indexedDB, IDBKeyRange, and the other IndexedDB constructors onto the global object. Named imports avoid that mutation and work well with Dexie dependency injection. Our checks loaded the ESM package with both import and require() through its exports map.

State survives for the life of the in-memory factory. Create new IDBFactory() between tests that need isolation, close open database handles, and await transaction completion before asserting. Deleting a database can block while another connection remains open, just as the IndexedDB contract specifies. forceCloseDatabase() can trigger the nonstandard abnormal-close path for a targeted test.

The browser bundle measured 55.7 KB minified and 14.8 KB gzipped in our esbuild check, but shipping it to users defeats its main purpose. Keep it in development dependencies. Node 18 supplies structuredClone; older jsdom environments may hide or omit it, so add the README's polyfill or custom environment before importing fake-indexeddb/auto. Run a smaller set of browser tests for quota, workers, persistence, and timing-sensitive production paths.

Patterns

Install it only for tests install-test-double

npm install --save-dev fake-indexeddb

Version 6.2.5 requires Node 18 or newer. It is an in-memory test implementation, so production browser code should use the platform's IndexedDB object.

Register IndexedDB globals before application imports register-globals

import 'fake-indexeddb/auto';
import { startApp } from './app.js';

startApp();

The auto entry mutates the global object. Import it before modules that read `indexedDB` during evaluation.

Inject the implementation without changing globals inject-factory

import { indexedDB, IDBKeyRange } from 'fake-indexeddb';
import Dexie from 'dexie';

const db = new Dexie('test-db', { indexedDB, IDBKeyRange });

Dexie accepts both objects in its constructor. This keeps the fake scoped to one database instance.

Create a store during a version upgrade open-database

const request = indexedDB.open('catalog', 1);
request.onupgradeneeded = () => {
  const db = request.result;
  db.createObjectStore('books', { keyPath: 'isbn' });
};
const db = await new Promise((resolve, reject) => {
  request.onsuccess = () => resolve(request.result);
  request.onerror = () => reject(request.error);
});

Schema changes belong in `onupgradeneeded`. Opening a higher version while another connection stays open can trigger the normal blocked-upgrade behavior.

Wait for a write transaction to finish write-record

const tx = db.transaction('books', 'readwrite');
tx.objectStore('books').put({ isbn: '978-1', title: 'Test Book' });
await new Promise((resolve, reject) => {
  tx.oncomplete = resolve;
  tx.onerror = () => reject(tx.error);
  tx.onabort = () => reject(tx.error);
});

A successful request does not mean the whole transaction committed. Assert durable transaction state after `oncomplete`.

Convert an IndexedDB request to a promise read-record

const tx = db.transaction('books', 'readonly');
const request = tx.objectStore('books').get('978-1');
const book = await new Promise((resolve, reject) => {
  request.onsuccess = () => resolve(request.result);
  request.onerror = () => reject(request.error);
});

A missing key resolves with `undefined`; it does not reject the request.

Read through a unique index query-index

const store = db.transaction('books').objectStore('books');
const request = store.index('by_title').get('Test Book');
request.onsuccess = () => expect(request.result.isbn).toBe('978-1');

Create `by_title` inside an upgrade transaction before using it. Index constraints are checked when writes run.

Collect rows from a bounded cursor iterate-cursor

const rows = [];
const request = db.transaction('books').objectStore('books')
  .openCursor(IDBKeyRange.lowerBound('978-1'));
await new Promise((resolve, reject) => {
  request.onerror = () => reject(request.error);
  request.onsuccess = () => {
    const cursor = request.result;
    if (!cursor) return resolve();
    rows.push(cursor.value);
    cursor.continue();
  };
});

Call `continue()` inside the success handler. The final success event carries a null result and ends iteration.

Give each test a fresh factory reset-between-tests

import { IDBFactory } from 'fake-indexeddb';

beforeEach(() => {
  globalThis.indexedDB = new IDBFactory();
});

A new factory removes all in-memory databases owned by the previous factory. Resetting globals can conflict with concurrently running tests in the same process.

Delete a test database after closing handles delete-database

db.close();
const request = indexedDB.deleteDatabase('catalog');
await new Promise((resolve, reject) => {
  request.onsuccess = resolve;
  request.onerror = () => reject(request.error);
  request.onblocked = () => reject(new Error('database connection still open'));
});

An open connection can block deletion. Close every handle created by the test before awaiting the request.

Test an abnormal close handler force-close-event

import { forceCloseDatabase } from 'fake-indexeddb';

const closed = new Promise((resolve) => db.addEventListener('close', resolve));
forceCloseDatabase(db);
await closed;

`forceCloseDatabase()` is unique to fake-indexeddb and is not part of the browser IndexedDB API. Use it only to reach the abnormal-close branch.

Supply structuredClone before auto registration patch-jsdom-clone

import structuredClone from 'core-js/stable/structured-clone.js';

globalThis.structuredClone ??= structuredClone;
await import('fake-indexeddb/auto');

fake-indexeddb stopped bundling a `structuredClone` polyfill in version 5. Modern Node has the function, but some jsdom environments do not expose it.

Alternatives

PackageRegistryPick it when
indexeddbshimnpmUse it when an older environment needs IndexedDB behavior backed by WebSQL rather than an in-memory Node test double.
@happy-dom/global-registratornpmUse it when tests need a wider browser-like DOM environment and IndexedDB is only one of several missing globals.
jsdomnpmUse it for DOM-focused Node tests, then add fake-indexeddb separately if those tests also touch IndexedDB.
idbnpmUse it in application code when the native browser database exists and the problem is IndexedDB's callback-heavy API rather than test storage.

More testing guides

pytest · chai · jsdom · vitest · playwright · coverage · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.