• Stars
    star
    561
  • Rank 79,400 (Top 2 %)
  • Language
    JavaScript
  • License
    Apache License 2.0
  • Created over 9 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A pure JS in-memory implementation of the IndexedDB API

fake-indexeddb Build Status

This is a pure JS in-memory implementation of the IndexedDB API. Its main utility is for testing IndexedDB-dependent code in Node.js.

Installation

npm install --save-dev fake-indexeddb

or

yarn add --dev fake-indexeddb

Use

Functionally, it works exactly like IndexedDB except data is not persisted to disk.

The easiest way to use it is to import fake-indexeddb/auto, which will put all the IndexedDB variables in the global scope. (Both import and require are supported, use whichever you like, but the examples here are all import.)

import "fake-indexeddb/auto";

var request = indexedDB.open("test", 3);
request.onupgradeneeded = function () {
    var db = request.result;
    var store = db.createObjectStore("books", {keyPath: "isbn"});
    store.createIndex("by_title", "title", {unique: true});

    store.put({title: "Quarry Memories", author: "Fred", isbn: 123456});
    store.put({title: "Water Buffaloes", author: "Fred", isbn: 234567});
    store.put({title: "Bedrock Nights", author: "Barney", isbn: 345678});
}
request.onsuccess = function (event) {
    var db = event.target.result;

    var tx = db.transaction("books");

    tx.objectStore("books").index("by_title").get("Quarry Memories").addEventListener("success", function (event) {
        console.log("From index:", event.target.result);
    });
    tx.objectStore("books").openCursor(IDBKeyRange.lowerBound(200000)).onsuccess = function (event) {
        var cursor = event.target.result;
        if (cursor) {
            console.log("From cursor:", cursor.value);
            cursor.continue();
        }
    };
    tx.oncomplete = function () {
        console.log("All done!");
    };
};

Alternatively, you can explicitly import individual IndexedDB variables:

import {
    indexedDB,
    IDBCursor,
    IDBCursorWithValue,
    IDBDatabase,
    IDBFactory,
    IDBIndex,
    IDBKeyRange,
    IDBObjectStore,
    IDBOpenDBRequest,
    IDBRequest,
    IDBTransaction,
    IDBVersionChangeEvent,
} from "fake-indexeddb";

// The rest is the same as above.

Like any imported variable, you can rename it if you want, for instance if you don't want to conflict with built-in IndexedDB variables:

import {
    indexedDB as fakeIndexedDB,
} from "fake-indexeddb";

TypeScript

As of version 4, fake-indexeddb includes TypeScript types. As you can see in types.d.ts, it's just using TypeScript's built-in IndexedDB types, rather than generating types from the fake-indexeddb code base. The reason I did this is for compatibility with your application code that may already be using TypeScript's IndexedDB types, so if I used something different for fake-indexeddb, it could lead to spurious type errors. In theory this could lead to other errors if there are differences between Typescript's IndexedDB types and fake-indexeddb's API, but currently I'm not aware of any difference. See issue #23 for more discussion.

Dexie and other IndexedDB API wrappers

If you import fake-indexeddb/auto before importing dexie, it should work:

import "fake-indexeddb/auto";
import Dexie from "dexie";

const db = new Dexie("MyDatabase");

The same likely holds true for other IndexedDB API wrappers like idb.

Alternatively, if you don't want to modify the global scope, then you need to explicitly pass the objects to Dexie:

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

const db = new Dexie("MyDatabase", { indexedDB: indexedDB, IDBKeyRange: IDBKeyRange });

Jest

To use fake-indexeddb in a single Jest test suite, require fake-indexeddb/auto at the beginning of the test file, as described above.

To use it on all Jest tests without having to include it in each file, add the auto setup script to the setupFiles in your Jest config:

{
    "setupFiles": [
        "fake-indexeddb/auto"
    ]
}

Wiping/resetting the indexedDB for a fresh state

If you are keeping your tests completely isolated you might want to "reset" the state of the mocked indexedDB. You can do this by creating a new instance of IDBFactory, which lets you have a totally fresh start.

import "fake-indexeddb/auto";
import { IDBFactory } from "fake-indexeddb";

// Whenever you want a fresh indexedDB
indexedDB = new IDBFactory();

With PhantomJS and other really old environments

PhantomJS (and other really old environments) are missing tons of modern JavaScript features. In fact, that may be why you use fake-indexeddb in such an environment! Prior to v3.0.0, fake-indexeddb imported core-js and automatically applied its polyfills. However, since most fake-indexeddb users are not using really old environments, I got rid of that runtime dependency in v3.0.0. To work around that, you can import core-js yourself before you import fake-indexeddb, like:

import "core-js/stable";
import "fake-indexeddb/auto";

Quality

Here's a comparison of fake-indexeddb and real browser IndexedDB implementations on the W3C IndexedDB test suite as of March 18, 2019:

Implementation Percentage of files that pass completely
Chrome 73 99%
Firefox 65 97%
Safari 12 92%
fake-indexeddb 3.0.0 87%
Edge 18 61%

For browsers, I ran http://w3c-test.org/tools/runner/index.html and counted the passes. For fake-indexeddb, I ran npm run test-w3c.

87% is pretty good, right? Especially considering that fake-indexeddb runs in Node.js where failure is guaranteed for tests involving browser APIs like Web Workers. There are definitley still some weak points of fake-indexeddb, most of which are described in src/test/web-platform-tests/run-all.js. Your app will probably run fine, though.

Potential applications:

  1. Use as a mock database in unit tests.

  2. Use the same API in Node.js and in the browser.

  3. Support IndexedDB in old or crappy browsers.

  4. Somehow use it within a caching layer on top of IndexedDB in the browser, since IndexedDB can be kind of slow.

  5. Abstract the core database functions out, so what is left is a shell that allows the IndexedDB API to easily sit on top of many different backends.

  6. Serve as a playground for experimenting with IndexedDB.

License

Apache 2.0

More Repositories

1

promise-worker-bi

Promise-based messaging for Web Workers and Shared Workers
JavaScript
46
star
2

screw

Play back MP3s with altered pitch and tempo, right in your web browser.
JavaScript
43
star
3

csv-sql-live

Run SQL queries on CSV files in your web browser. The future is now!
JavaScript
29
star
4

sas7bdat-js

Read SAS files in JavaScript. Because you always wanted to do that, right?
JavaScript
27
star
5

realistic-structured-clone

A pure JS implementation of the structured clone algorithm (or at least something pretty close to that).
JavaScript
25
star
6

IndexedDB-getAll-shim

Shim/polyfill for IDBObjectStore.getAll, IDBIndex.getAll, IDBObjectStore.getAllKeys, and IDBIndex.getAllKeys
JavaScript
25
star
7

backboard

A Promise-based wrapper around IndexedDB with sane error and transaction handling
JavaScript
12
star
8

sas7bdat-web-viewer

JavaScript
9
star
9

barbconq

Barbarian Conquest, a minigame built on a partial web-based port of Civ4
TypeScript
9
star
10

find-repeated-words

Highlight words in a text document that are used close together
Python
6
star
11

parfor_progress

MATLAB progress monitor (progress bar) that works with parfor.
MATLAB
6
star
12

atsphp

PHP
4
star
13

nba-blocked-jumper

The effect of a blocked jump shot on future jump shots in the NBA
Python
2
star
14

nba-most-improved-player

Python
2
star
15

babel-async-await-regenerator

JavaScript
1
star
16

browserify-babelify-yarn-workspaces

JavaScript
1
star
17

dumbmatter.com

JavaScript
1
star
18

tablesorter

This is a fork of Christian Bach's http://tablesorter.com/docs/ jQuery Tablesorter 2.0.5b plugin, to fix a bug concerning multiple <tr> tags within a <thead>. In the original version, only the <th> in the lowest row is highlighted when the column is sorter. In my version, all <th>s in the column are highlighted, which I think is a more sensible behavior.
JavaScript
1
star