Giter VIP home page Giter VIP logo

fakeindexeddb's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fakeindexeddb's Issues

`DataError: Data provided to an operation does not meet requirements.` when making a simple dexie query

Thank you for making this library, we've been using it since we started using indexeddb.

This codesandbox succeeds with in-browser IndexedDB but fails with fake-indexeddb. I found it while looking into an issue where not all results are returned from a table with a compound primary index.

https://codesandbox.io/s/dexie-bug-tr8ml

I don't know how to reduce this to a more minimal case for fake-indexeddb, but I have also opened a ticket on dexie. dexie/Dexie.js#954

Dev dependencies installed during production install

First off, awesome project! 👍

When running npm install fake-indexeddb the dev dependencies of the project are also installed like browserify and phantomjs. Running ls node_modules/fake-indexeddb/node_modules confirms this.

Looking at the package.json this shouldn't be happening so I'm somewhat confused. This may be due to the use of shrinkwrapping which appears to include the dev dependencies alongside the production ones.

Error from npm test on Mac OS

Using v2.0.1 of io.js, I cloned and did npm install and then npm test and got:

W3C IDBCursor.advance Tests
    asyncness
      1) "before all" hook

  0 passing (15ms)
  1 failing

  1) W3C IDBCursor.advance Tests asyncness "before all" hook:
     Uncaught TypeError: database._rawDatabase.transactions.find is not a function
      at confirmActiveVersionchangeTransaction (lib/FDBDatabase.js:19:58)
      at FDBDatabase.createObjectStore (lib/FDBDatabase.js:65:27)
      at FDBOpenDBRequest.open.onupgradeneeded (test/w3c/IDBCursor.advance.js:19:35)
      at invokeEventListeners (lib/EventTarget.js:32:27)
      at FDBOpenDBRequest.dispatchEvent (lib/EventTarget.js:82:13)
      at waitForOthersClosed (lib/FDBFactory.js:132:17)
      at runVersionchangeTransaction (lib/FDBFactory.js:162:5)
      at openDatabase (lib/FDBFactory.js:186:9)
      at null.<anonymous> (lib/FDBFactory.js:251:13)




npm ERR! Darwin 14.1.0
npm ERR! argv "/usr/local/bin/iojs" "/usr/local/bin/npm" "run" "mocha"
npm ERR! node v2.0.1
npm ERR! npm  v2.9.0
npm ERR! code ELIFECYCLE
npm ERR! [email protected] mocha: `mocha --harmony --timeout 5000 test/w3c test/fakeIndexedDB`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] mocha script 'mocha --harmony --timeout 5000 test/w3c test/fakeIndexedDB'.
npm ERR! This is most likely a problem with the fake-indexeddb package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     mocha --harmony --timeout 5000 test/w3c test/fakeIndexedDB
npm ERR! You can get their info via:
npm ERR!     npm owner ls fake-indexeddb
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/danielearwicker/github/fakeIndexedDB/npm-debug.log
npm ERR! Test failed.  See above for more details.

API to simulate QuotaExceededError

Similar to #50, it would be awesome for fakeindexeddb to have a way to simulate the storage device running out of space and throwing a QuotaExceededError.

Currently this is really hard to repro, even in a browser (it's recommended to create a separate volume and start Chrome with that volume). Having it in fakeindexeddb would be extremely convenient.

Something like:

indexedDB.__simulateQuotaExceeded = true // false by default

Regress: undefined entry during iterating records

The 3.1.0 version introduced a regress bug. The previous 3.0.2 works OK.

I have the following deletion using Dexie.js (3.0.1 version):

db.table('some-table')
  .where('key')
  .startsWith('some-prefix)
  .delete();

It produces the next error:


Error: Could not delete some values. Errors: TypeError: Cannot read property 'key' of undefined

    at /testproject/node_modules/dexie/src/classes/collection/collection.ts:586:36
    at /testproject/node_modules/dexie/src/helpers/promise.js:843:23
    at callListener (/testproject/node_modules/dexie/src/helpers/promise.js:497:19)
    at endMicroTickScope (/testproject/node_modules/dexie/src/helpers/promise.js:583:25)
    at /testproject/node_modules/dexie/src/helpers/promise.js:652:30
    at done (/testproject/node_modules/dexie/src/dbcore/dbcore-indexeddb.ts:194:11)
    at FDBRequest.req.onerror (/testproject/node_modules/dexie/src/dbcore/dbcore-indexeddb.ts:204:11)
    at invokeEventListeners (/testproject/node_modules/fake-indexeddb/build/lib/FakeEventTarget.js:67:31)
    at FDBRequest.Object.<anonymous>.FakeEventTarget.dispatchEvent (/testproject/node_modules/fake-indexeddb/build/lib/FakeEventTarget.js:120:13)
    at FDBTransaction.Object.<anonymous>.FDBTransaction._start (/testproject/node_modules/fake-indexeddb/build/FDBTransaction.js:214:29)
    at processImmediate (internal/timers.js:456:21)
From previous: 
    at DexiePromise.then (/testproject/node_modules/dexie/src/helpers/promise.js:182:22)
    at /testproject/node_modules/dexie/src/classes/collection/collection.ts:585:12
    at /testproject/node_modules/dexie/src/helpers/promise.js:843:23
    at callListener (/testproject/node_modules/dexie/src/helpers/promise.js:497:19)
    at endMicroTickScope (/testproject/node_modules/dexie/src/helpers/promise.js:583:25)
    at FDBRequest.onsuccess (/testproject/node_modules/dexie/src/helpers/promise.js:652:30)
    at invokeEventListeners (/testproject/node_modules/fake-indexeddb/build/lib/FakeEventTarget.js:67:31)
    at FDBRequest.Object.<anonymous>.FakeEventTarget.dispatchEvent (/testproject/node_modules/fake-indexeddb/build/lib/FakeEventTarget.js:120:13)
    at FDBTransaction.Object.<anonymous>.FDBTransaction._start (/testproject/node_modules/fake-indexeddb/build/FDBTransaction.js:214:29)
    at Immediate.<anonymous> (/testproject/node_modules/fake-indexeddb/build/lib/Database.js:26:26)
    at processImmediate (internal/timers.js:456:21)
From previous: 
    at Object.mutate (/testproject/node_modules/dexie/src/dbcore/dbcore-indexeddb.ts:120:14)
    at Object.mutate (/testproject/node_modules/dexie/src/hooks/hooks-middleware.ts:52:28)
    at /testproject/node_modules/dexie/src/classes/collection/collection.ts:584:33
    at /testproject/node_modules/dexie/src/helpers/promise.js:843:23
    at callListener (/testproject/node_modules/dexie/src/helpers/promise.js:497:19)
    at endMicroTickScope (/testproject/node_modules/dexie/src/helpers/promise.js:583:25)
    at FDBRequest.onsuccess (/testproject/node_modules/dexie/src/helpers/promise.js:652:30)
    at invokeEventListeners (/testproject/node_modules/fake-indexeddb/build/lib/FakeEventTarget.js:67:31)
    at FDBRequest.Object.<anonymous>.FakeEventTarget.dispatchEvent (/testproject/node_modules/fake-indexeddb/build/lib/FakeEventTarget.js:120:13)
    at FDBTransaction.Object.<anonymous>.FDBTransaction._start (/testproject/node_modules/fake-indexeddb/build/FDBTransaction.js:214:29)
    at Immediate.<anonymous> (/testproject/node_modules/fake-indexeddb/build/lib/Database.js:26:26)
    at processImmediate (internal/timers.js:456:21)

Blob support

Blobs are corrupted when saved to a store. I believe it is caused by Typeson not supporting blobs. FakeIndexedDB version 2.0.3 kind of supports it, it works but the console is filled with uncaught errors.

Are there any plans on adding blob support?

Reset auto-incrementing after each test

Hi there! First, the library is awesome, great work :)

And now my question, is it possible to reset the db after each test in a way that auto-increment ids begin from 1?
The problem that I have is that I can't write independent tests for stores with auto-incrementing ids (I'm testing those autogenerated values as well, I can explain why I do this if you're interested). For example, in one test I push several items to a store and then ids are created like 1,2,3 and then I continue with another test which pushes to that same store (previously cleared of course) but ids begin from 4 (unless this test is run in isolation).
Can you suggest on how to completely reset the db so it affects this global counter or is there any kind of workaround for this issue?
Thanks!

FBDCursor broken in release/minimised build

When build in release-optimised mode, the FDB Cursor no longer works, due to erroneous runtime type-checking.

The outcome is that a null or undefined value is returned from any Cursor Read operation. No exception is thrown, so it's difficult to debug. Everything works just fine in a normal development environment. To replicate the issue something like the Webpack Terser plugin must be used to optimise the javascript output.

Summary: code similar to the following occurs 3 times in FDBCursor.cs. In an optimised build, the name of the constructor will be different, causing these conditions to never be fulfilled.

if ( !this._keyOnly && this.constructor.name === "FDBCursorWithValue" ) {
Resolution: Since both FDBCursor and the derived class FDBCursorWithValue already implement a toString() function, a quick fix is as follows:

if ( !this._keyOnly && this.toString() === "[object IDBCursorWithValue]" ) {

Be more picky about core-js include

The blanket include of core-js is causing some issues in our project. Specifically there is a package in core-js that introduces numbers as iterators (e.g. you can write for (i of 20) {). React tends to blow up with this, and if you return a number from a render function you get long strings of zeros for some reason. So some of our tests now look like Expected 10, got "000000000000000000000000000000000000000000000000000000000000000"

Suggest that the project be updated to include specific polyfills that are needed as opposed to a blanket include, or at least only enabling stage 2 features

FIDB persistence

Is there any options for permanent storages? If not, does FIDB have any plans for supporting this feature? Something like sync data with the real IndexedDB?

Update old dependencies

Some of the shrinkwrapped dependencies are quite old and are causing deprecation warnings when installing. In particular, graceful-fs and minimatch, which are dependencies of mocha.

I've verified that all tests pass if mocha is upgraded to the latest release ([email protected]).

Iterating an index fails if entries are added in the wrong order

Hi! Thanks for fakeIndexedDB, we're using it in kinto.js for testing and verifying that everything works the same way as it would in a browser.

I'm investigating Kinto/kinto.js#690, which demonstrates our code failing with fakeIndexedDB 2.0.2. Previously we were using fakeIndexedDB 1.0.12 and everything seemed to work OK.

I boiled down this minimal example that demonstrates the problem:

"use strict";

import fakeIndexedDB from "fake-indexeddb";
import { expect } from "chai";

describe("FakeIndexedDB", () => {
    let db;
    beforeEach((done) => {
        const request = fakeIndexedDB.open("test" + Math.random());
        request.onupgradeneeded = (e) => {
            const db2 = e.target.result;
            const collStore = db2.createObjectStore("store", {keyPath: "id"});

            // Primary key (generated by IdSchema, UUID by default)
            collStore.createIndex("id", "id", { unique: true });
            // Local record status ("synced", "created", "updated", "deleted")
            collStore.createIndex("_status", "_status", {unique: false});

            collStore.add({id: "5", _status: "created"});
            collStore.add({id: "0", _status: "created"});
        };
        request.onsuccess = (e) => {
            db = e.target.result;
            done();
        };
        request.onerror = (e) => {
            done(e.target.error);
        };
    });

    it("should be awesome", (done) => {
        const results = [];
        const finish = () => {
            expect(results).lengthOf(2);
            done();
        };

        const txn = db.transaction(["store"]);
        const store = txn.objectStore("store");
        const request = store.index("_status").openCursor();
        request.onsuccess = (event) => {
            const cursor = event.target.result;
            if (!cursor) {
                finish();
                return;
            }
            const { key, value } = cursor;

            if (key > "created") {
                finish();
                return;
            }
            if (key === "created") {
                results.push(value);
                cursor.continue();
            }
            if (key < "created") {
                cursor.continue("created");
            }
        };
        request.onerror = (e) => {
            done(e.target.error);
        };
    });
});

I can construct a complete git repo with this code (and the necessary package.json stuff) if that would make it easier to try out. The behavior is that only the first record ({id: "5", _status: "created"}) is produced by the cursor. The second ({id: "0", _status: "created"}) never gets produced. Changing the second record's ID to "6" or something greater than the first one causes the example to succeed.

I'm not really an expert with IndexedDB so I wasn't sure whether the problem is in my example or in the library. I tried tracing through the fakeIndexedDB code and it seems like the second record gets added later in the index than the first one, but it seems like _iterate method skips the second record because it compares as less than the first one. Does that seem right to you?

Thanks for any help!

Maximum call stack size exceeded

Hello!

I've got this error during testing a plugin for Dexie.js with FakeIndexedDB, more details about a context here: dexie/Dexie.js#1053

Error output:

RangeError: Maximum call stack size exceeded

    at FDBTransaction.Object.<anonymous>.FDBTransaction._start

If I comment out the following lines in FDBTransaction.js, it works (or seems like working):

            // On to the next one
            // if (this._requests.length > 0) {
            //     this._start();
            // }
            // else {
                // Give it another chance for new handlers to be set before finishing
                setImmediate(this._start.bind(this));
            // }

Correct way to refresh DB before each test

I'm trying to refresh the DB before each test to have my tests completely isolated. I imported fake-indexeddb/auto in the top of test file and use beforeEach to call FDBFactory inside (like in README example). Is it a correct way to refresh db ?

import 'fake-indexeddb/auto';
import FDBFactory from 'fake-indexeddb/lib/FDBFactory';

beforeEach(() => {
  new FDBFactory();
});

2.0.1 broken in PhantomJS 2.1

I know, we all love supporting PhantomJS and it's terrible old buggy APIs, but our main reason for using fakeIndexedDB is to work around Phantom's horrifically buggy indexedDB implementation 😞

TypeError: undefined is not a constructor (evaluating 'Array.from(rawDatabase.rawObjectStores.keys())')

Looks like it's caused by

this.objectStoreNames = fakeDOMStringList(Array.from(rawDatabase.rawObjectStores.keys())).sort();
, which I'm guessing is due to Array.from not existing

API to simulate the "close" event

The "close" event on an IDBDatabase only fires when the database closes for an abnormal reason, as described in the spec. (An abnormal reason would be something like the user clearing their browser data while the IDB connection is open.)

For unit testing, it would be neat if fakeIndexedDB had an API for simulating this abnormal close event. Presumably it would just be a matter of running db.close() plus firing an event. (I would do this in userland, but it seems that fakeIndexedDB throws an error if you try to call db.dispatchEvent(new CustomEvent('close')).

setTimeout problems / questions

I'm having some problems since the upgrade to 3.1.4; Jest tests that previously worked fine are now timing out. I did some digging, and if I understand correctly:

  • Starting with 3.1.4, fake-indexeddb uses setTimeout instead of setImmediate.
  • In Node.js, setTimeout enforces a minimum delay of 1ms, so every fake-indexeddb operation takes at least 1 millisecond.
  • On Windows, from what I can tell, the Node.js timer has a resolution of ~15ms, so every fake-indexeddb operation takes at least 15 milliseconds.
  • jsdom uses Node.js's setTimeout implementation unchanged, so all of the above applies in jsdom test environments as well.

I experimented with using Jest's fake timers to speed up my tests, but they don't appear to be a great solution: because IndexedDB operations result in fake-indexeddb timers which resolve promises which may then trigger additional IndexedDB operations (etc.), there's an awkward dance of trying to figure out which timers and promises are outstanding after each operation so that they can all be properly resolved. (See the linked test case for an example of what this looks like - this gets even harder when using third-party code that may do multiple IndexedDB operations in a row. Maybe there's an easier way to do this in Jest? If so please let me know.)

We ran into this using the idb-keyval package, which, in order to keep a simple API, relies on lots of small operations.

Test case: https://github.com/joshkel/fake-indexeddb-settimeout-test-case

Timings for the "create and read a bunch of values" from that project in fake-indexeddb 3.1.4:

  • macOS, Node.js 14.17.1 - 71 ms
  • Windows, Node.js 14.17.0 - 54 ms

In fake-indexeddb 3.1.3:

  • macOS, Node.js 14.17.1 - 734 ms
  • Windows, Node.js 14.17.0 - 6734 ms

devDependencies are installed

I just installed and wonder why all the devDependencies got installed.

npm --version
3.10.2

npm i --save-dev fake-indexeddb                                                                                                                                           ⏎ master ✱ ◼
npm WARN deprecated [email protected]: graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.
npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue

> [email protected] install /Users/bsr/test/node_modules/fake-indexeddb/node_modules/node-qunit-phantomjs/node_modules/phantomjs-prebuilt
> node install.js

PhantomJS not found on PATH
Downloading https://github.com/Medium/phantomjs/releases/download/v2.1.1//phantomjs-2.1.1-macosx.zip
Saving to /var/folders/fc/k8b9ds214nv4lqv2x4395khc0000gn/T/phantomjs/phantomjs-2.1.1-macosx.zip
Receiving...
 [===================================-----] 88%
Received 16746K total.
Extracting zip contents
Removing /Users/bsr/test/node_modules/fake-indexeddb/node_modules/node-qunit-phantomjs/node_modules/phantomjs-prebuilt/lib/phantom
Copying extracted folder /var/folders/fc/k8b9ds214nv4lqv2x4395khc0000gn/T/phantomjs/phantomjs-2.1.1-macosx.zip-extract-1468612535803/phantomjs-2.1.1-macosx -> /Users/bsr/test/node_modules/fake-indexeddb/node_modules/node-qunit-phantomjs/node_modules/phantomjs-prebuilt/lib/phantom
Writing location.js file
Done. Phantomjs binary available at /Users/bsr/test/node_modules/fake-indexeddb/node_modules/node-qunit-phantomjs/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs
[email protected] /Users/bsr/test

ls node_modules/fake-indexeddb/node_modules                                                                                                                                 master ✱ ◼
array.prototype.find       browserify                 mocha                      qunitjs                    setimmediate
array.prototype.findindex  eslint                     node-qunit-phantomjs       realistic-structured-clone

DataCloneErrors with v1.0.10

Started running into failing tests when I upgraded fakeIDB this morning:

beforeEach(function(done) {
  let dbReq = fakeIndexedDB.open('storage', 2);

  dbReq.onerror = (e) => {
    console.error(e);
    done(dbReq.error);
  };

  dbReq.onupgradeneeded = (e) => {
    dbReq.result.createObjectStore('test', { keyPath: 'key' });
  };

  dbReq.onsuccess = (e) => {
    let txn = dbReq.result.transaction(['test'], 'readwrite');
    let os = txn.objectStore('test');

    let p = os.put({key: 'name', value: 'test'});  // <-- FAILING
    p.onsuccess = () => {
      dbReq.result.close();
      done();
    };
  };
});

The put call is now throwing DataCloneError: The data being stored could not be cloned by the internal structured cloning algorithm.

Errored transactions seem to still commit

First of all, fantastic work on this! It's been a great help to me recently, letting me develop in the node environment without having to use something overpowered like puppeteer.

That being said, I think I've found a bug.

We first crease a simple database; it has one object store with an indexed attribute indexed_attr. We then, in two separate transactions, place an object { indexed_attr: 'xxx' } into the database. As we'd expect, since indexed_attr is unique, the first transaction succeeds and the second fails. However, they both seem to commit: we find that the resultant database contains two copies of the object, not just one.

I do not know if this is spec-compliant behaviour or not, but it differs from Chrome, which you note has a 99% pass rate on the W3C IndexedDB test suite. In Chrome, the resultant db has only one copy of the object.

require('fake-indexeddb/auto');

function setup() {
  /* Create database, object store, and unique index */
  return new Promise(resolve => {
    indexedDB.deleteDatabase('mydb').onsuccess = event => {
      const openreq = indexedDB.open('mydb');

      openreq.onupgradeneeded = event => {
        const db = event.target.result;
        const store = db.createObjectStore('mystore', { autoIncrement: true });
        store.createIndex('myindex', 'indexed_attr', { unique: true });
      };

      openreq.onsuccess = _event => resolve();
    };
  });
}

const my_object = { indexed_attr: 'xxx' };

function put() {
  /* Put `my_object` into the db. */
  return new Promise(resolve => {
    indexedDB.open('mydb').onsuccess = event => {
      const db = event.target.result;
      const tx = db.transaction(['mystore'], 'readwrite');
      const store = tx.objectStore('mystore');
      const addreq = store.add(my_object);
      addreq.onsuccess = _event => resolve('succ');
      addreq.onerror = _event => resolve('fail');
    };
  });
}

function read() {
  /* Return list of all objects in the db */
  return new Promise(resolve => {
    indexedDB.open('mydb').onsuccess = event => {
      const db = event.target.result;
      const tx = db.transaction(['mystore'], 'readonly');
      const store = tx.objectStore('mystore');
      store.getAll().onsuccess = event => resolve(event.target.result);
    };
  });
}

await setup();
console.log(await put()); // returns 'succ', as expected
console.log(await put()); // returns 'fail', as expected
console.log(await read()); // returns [my_object, my_object] instead of just [my_object]

DB connection fails to close

I'm using fakeIndexedDB for testing. I am unable to close db connections after calling db.close(). I set an onClose event listener to indicate when the db closes but it never fires. I need to upgrade the db in one of my tests, I can't do this with other connections open. So, I set the db to close onversionchange but alas, the db doesn't close and upgrade request is blocked.

Unable to cover onError scenarios while testing

For our indexedDB usage in app, we have written graceful error handling for indexedDB failure, ex - transaction.onerror, .onerror handler for indexedDB.open() function, .error for read write db. These error handlers are not getting covered while using fake-indexedDB. Can you suggest how to cover them, we are using React testing library with Jest.

Installation of 1.0.4 fails with

Just so you know, installing 1.0.4 currently fails because of a foreign dependency: phantomjs-prebuilt.

$ npm install fake-indexeddb --save-dev
npm WARN package.json [email protected] No description
npm WARN package.json [email protected] No repository field.
npm WARN package.json [email protected] No README data
npm WARN deprecated [email protected]: graceful-fs version 3 and before will fail on newer node releases. Please update to graceful-fs@^4.0.0 as soon as possible.

> [email protected] install /home/niko/tmp/node_modules/fake-indexeddb/node_modules/phantomjs-prebuilt
> node install.js

module.js:339
    throw err;
    ^

Error: Cannot find module './util/assign'
    at Function.Module._resolveFilename (module.js:337:15)
    at Function.Module._load (module.js:287:25)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at Object.<anonymous> (/home/niko/tmp/node_modules/fake-indexeddb/node_modules/fs-extra/lib/index.js:1:76)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Module.require (module.js:366:17)
npm ERR! Linux 4.2.0-34-generic
npm ERR! argv "/home/niko/.nvm/versions/node/v4.2.1/bin/node" "/home/niko/.nvm/versions/node/v4.2.1/bin/npm" "install" "fake-indexeddb" "--save-dev"
npm ERR! node v4.2.1
npm ERR! npm  v2.14.7
npm ERR! code ELIFECYCLE

npm ERR! [email protected] install: `node install.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] install script 'node install.js'.
npm ERR! This is most likely a problem with the phantomjs-prebuilt package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node install.js
npm ERR! You can get their info via:
npm ERR!     npm owner ls phantomjs-prebuilt
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /home/niko/tmp/npm-debug.log

I'm filing this here just so you know about the issue and can track it until it's fixed.

`db.close()` doesn't fire `onclose` despite properly closing the db

(As seen in #46)

Create a database and in the onsuccess handler, .close() and re-open the db. The re-opening will succeed, suggesting that the db properly closed. Despite this, the onclose handler will not have run.

require('fake-indexeddb/auto');

indexedDB.deleteDatabase('mydb').onsuccess = event => {
  const openreq = indexedDB.open('mydb');

  openreq.onsuccess = event => {
    const db_connection = event.target.result;
    db_connection.onclose = () => console.log('closed');
    db_connection.close();
    const reopenreq = indexedDB.open('mydb');
    reopenreq.onsuccess = () => console.log('db re-opened');
  }
};

// 'closed' does not get logged but 'db re-opened' does

FakeDOMStringList should not support array methods

FakeDOMStringList seems to be extending array, but a number of array methods aren't available. Such that tests can pass and then result in failure in production.

I had a migration that executed transaction.objectStoreNames.includes('...') and didn't cause any issues, but then failed in production as should have been transaction.objectStoreNames.contains('...'). Didn't pick up on it with types due to a bug in idb

Removing a 'complete' event listener in a handler can cause later transactions not to complete

Reproduction:

import indexedDB from "fake-indexeddb";

export const STORE = "store";

export const checkForGarbage = () => {
    const dbReq = indexedDB.open("db", 1);
    dbReq.addEventListener("upgradeneeded", (ev) => {
        ev.target.result.createObjectStore(STORE, { autoIncrement: true });
    });
    dbReq.addEventListener("success", (ev) => {
        const db = ev.target.result
        const tx = db.transaction([STORE], "readwrite");
        const complete = () => {
            tx.removeEventListener('complete', complete);
        };
        tx.addEventListener('complete', complete);
        const store = tx.objectStore(STORE);
        store.get(0).addEventListener("success", () => console.log("Done!"));
    });
};

for (let i = 0; i < 5; i++) {
    checkForGarbage();
}

The expected result is to print "Done!" five times. However, only two are produced. Commenting out the body of complete (i.e., removing the removeEventListener call) produces the desired result.

How to deal with jest necessarily traversing into IndexedDB related files

demo repo: https://github.com/ZYinMD/jest-indexeddb-undefined-demo

I encountered an "indexeddb is not defined" issue in jest with a create-react-app project. I tried using this package to fix it, but had no luck. Can someone shed some light?

// a.js
import { openDB } from "idb";
export const dbConnection = openDB("myDB", 1);

// b.js
import { dbConnection } from "./a";
export const foo = 1;
export function doSomethingWithDB() {
  dbConnection.then((db) => {
    //...
  });
}

// c.js
import { foo } from "./b";
export const bar = foo + 1;

// d.js
import { bar } from "./c";
export function notEvenCalled() {
  return sum(bar, 100);
}
export function sum(a, b) {
  return a + b;
}

// d.test.js
import { sum } from "./d";
test("why", () => {
  expect(sum(1, 1)).toBe(2); // fail!! indexeddb is not defined.
});

I think it's because jest traverses all files that are connected to the test file via import/export, and also all files connected to those files, and so on.

Is there an easy fix for things like this?

Consider adding TransactionInactiveError

I see an InvalidStateError from nodejs. When I run the same thing in chrome I get a TransactionInactiveError.

WEB Reports: DOMException: Failed to execute 'add' on 'IDBObjectStore': The transaction is not active.

Node and fake index db (matching InvalidStateError from the spec): An operation was called on an object on which it is not allowed or at a time when it is not allowed. Also occurs if a request is made on a source object that has been deleted or removed. Use TransactionInactiveError or ReadOnlyError when possible, as they are more specific variations of InvalidStateError.'

Use FIDB within web workers

I think FIDB should use self as the global object instead of window. Otherwise, it won't work within web worker contexts.

Unable to cover openCursor onSuccess scenario while testing

We are using fake-indexedDB for our app. We are unable to cover the openCursor().onSuccess scenario, though we are writing test case the same way it is displayed in your npmjs.com page. Can you please suggest how to cover these lines. We are using React testing library and Jest.

Publish Typescript declaration file

Hi @dumbmatter.

Thanks for such an awesome module! I'm currently using this for some tests in a library of mine that I'm transitioning from JavaScript to Typescript. I was wondering if it would be possible to push a new release out with some Typescript declaration files. It shouldn't be too hard to do since you're using Typescript yourself. Just setting declaration: true and removing allowJs: true in tsconfig.json should do the trick.

Using for Dexie tests

I'm using a fairly typical mocha/chai testing strategy which uses Typescript code instead of plain JS). I would like to test my Dexie implementation but when I try to open a connection to the database I get the following error:

indexedDB API not found. If using IE10+, make sure to run your code on a server URL (not locally). If using old Safari versions, make sure to include indexedDB polyfill.

To give context, in the unit test file I am adding the following to the top of the file:

import 'fake-indexeddb/auto';

this import reports no issues but the error above persists. I started to wonder if maybe I needed to adjust my tsconfig file but typically the following params do the trick:

{
    // ...
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
}

and those are both in my configuration.

Now while I'm quite comfortable with a lot of Typescript/Javascript things along with named portability between the browser and node, I must say I don't always catch everything when it comes to "global scope" and I'm not yet entirely sure what the /auto script is doing (will be looking soon I guess).

Anyway thought I'd try:

import indexedDB from "fake-indexeddb";
const window: IDictionary = { indexedDB };

This does of course complain about fake-indexeddb not being typed but I got around that by adding a simple declaration file:

declare module "fake-indexeddb";

This removes the Typescript error but as I was suspecting the underlying error is still thrown. As I finish writing this Issue, I am starting to suspect that I need to dig into Dexie a bit more to diagnose the problem but if you've had an exposure to using your library with Dexie I would sure love some help and for that matter I think a small part of the README might talk to integration strategies for the various IDB wrapper libraries (of which Dexie is just one).

Poor insertion performance when using multiEntry

Hi, thank you so much for making fakeIndexedDB! I love using it in my tests; it's a marvelous piece of software. 🙂

I'm running into an issue where fakeIndexedDB is taking a very long time to insert data. Here is a test where I am inserting 1000 objects, each with 100 multiEntry keys.

On my Dell XPS 13 (i7 processor) running Ubuntu 20.04 and Node v12.16.3, this takes 35.5 seconds to complete. Unfortunately this means that my tests time out, and it's not feasible for me to create/destroy the database between each test.

In contrast, this same code takes 595ms in Chrome, 774ms in Firefox, and 1773ms in GNOME Web (WebKit, like Safari).

Looking at a Node cpuprofile, it appears that the main issue is that FDBTransaction._start queues up many recursive calls (if you insert 10,000 objects it will throw a stack overflow error), and each of those are spending time in Index.storeRecord and RecordStore.add. (Maybe switching to a non-recursive pattern would help?)

Screenshot from 2020-06-04 07-55-24

Attached is the trace file, which you can load into Chrome Dev Tools in the "JavaScript Profiler" section. If you'd like to profile this yourself, you can run node --inspect-brk index.js, then in chrome:inspect open the Node debugger, then in Profiler click "start".

CPU-20200604T075535.cpuprofile.gz

Unresolved Dexie bulkGet

The code below fails when using fake-indexeddb, because at least one of the Dexie bulkGet operations never resolves:

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

const db = new Dexie("test1");
db.version(1).stores({ table1: "++id" });
const table1 = db.table("table1");

const result = await Promise.all([
  table1.bulkGet([1]),
  table1.bulkGet([]),
  table1.bulkGet([3])
]);

I'm guessing this is a fake-indexeddb issue—or an interaction between it and Dexie—because the same Dexie code seems to work fine with Chrome and Firefox indexedDB.

Sandbox demonstrating problem: https://codesandbox.io/s/fakeidb-simultaneous-bulkget-w2j55?file=/src/index.test.ts. You should see tests failing with "Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout."

Same code running successfully with browser indexedDB: https://codesandbox.io/s/dexie-simultaneous-bulkget-test-qemz8?file=/src/index.test.ts

The bulkGet([]) with an empty key list is necessary to reproduce, and it must be preceded and followed by non-empty bulkGets. (Weird, right?) It doesn't seem to matter whether the bulkGets refer to records actually in the store or not.

Versions:
fake-indexeddb v3.1.1 (also 3.0.2 and 3.0.0; haven't tried others)
Dexie v3.0.1 (current latest; haven't tried others)

And in case they're relevant, I've reproed on:
node v10 or v12
typescript 3.9.7 targeting es2018, es2019, or es2020
jest v25 or v26
(I've included core-js in the sandbox, but it doesn't seem to matter; I believe TS is providing any missing core functions.)

getAll (using backboard) fails with fakeIndexedDB but works in Chrome

Hi, I met with below error while using getAll. Below is part of the code.

  async all() {
    const db = await connect();
    return db.sess.getAll();
  }

in my test

const values = await sess.all();
 assert(values.length === 3);
1) Session all, find:
     TypeError: Cannot read property 'apply' of undefined
      at node_modules/backboard/dist/lib/wrap-request.js:24:96
      at new Promise (node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:193:7)
      at exports.default (node_modules/backboard/dist/lib/wrap-request.js:18:12)
      at ObjectStore.(anonymous function) [as getAll] (node_modules/backboard/dist/lib/ObjectStore.js:112:38)
      at Session._callee3$ (src/frontend/bundles/layout/services/Session.js:379:59)
      at tryCatch (node_modules/regenerator-runtime/runtime.js:62:40)
      at GeneratorFunctionPrototype.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:336:22)
      at GeneratorFunctionPrototype.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:95:21)
      at step (Session.js:6:37)
      at Session.js:6:37
      at run (node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:89:22)
      at node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:102:28
      at flush (node_modules/babel-polyfill/node_modules/core-js/modules/_microtask.js:18:9)
      at _combinedTickCallback (internal/process/next_tick.js:67:7)
      at process._tickCallback (internal/process/next_tick.js:98:9)

I tried with bluebird, still the same error

  1) Session all, find:
     TypeError: Cannot read property 'apply' of undefined
      at node_modules/backboard/dist/lib/wrap-request.js:24:96
      at Promise._execute (node_modules/bluebird/js/release/debuggability.js:272:9)
      at Promise._resolveFromExecutor (node_modules/bluebird/js/release/promise.js:475:18)
      at new Promise (node_modules/bluebird/js/release/promise.js:77:14)
      at exports.default (node_modules/backboard/dist/lib/wrap-request.js:18:12)
      at ObjectStore.(anonymous function) [as getAll] (node_modules/backboard/dist/lib/ObjectStore.js:112:38)
      at Session._callee3$ (Session.js:21:15)
      at tryCatch (node_modules/regenerator-runtime/runtime.js:62:40)
      at GeneratorFunctionPrototype.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:336:22)
      at GeneratorFunctionPrototype.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:95:21)
      at step (Session.js:1:1)
      at Session.js:1:1
      at run (node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:89:22)
      at node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:102:28
      at flush (node_modules/babel-polyfill/node_modules/core-js/modules/_microtask.js:18:9)
      at _combinedTickCallback (internal/process/next_tick.js:67:7)
      at process._tickCallback (internal/process/next_tick.js:98:9)

It works fine in Chrome Canary

_recordStoreFactory = recordStoreFactory(mode, resolve, reject)[method]
getAll() { [native code] }

MissingAPIError: IndexedDB API missing

I tried using with latest dexie inside a CRA, but it doesn't seem to work:

import Dexie, { DexieOptions } from "dexie";
import indexedDB from "fake-indexeddb";
import IDBKeyRange from "fake-indexeddb/lib/FDBKeyRange";

interface IMessage {
  id?: number;
  message: string;
}
class TestDatabase extends Dexie {
  messages: Dexie.Table<IMessage, number>;

  constructor(options?: DexieOptions) {
    super("Database", options);
    this.version(1).stores({
      messages: "++id",
    });
    this.messages = this.table("messages");
  }
}

test("should pass", async () => {
  const db = new TestDatabase({
    indexedDB: indexedDB,
    IDBKeyRange: IDBKeyRange,
  });
  const result = await db.messages.put({ message: "a message" });
  console.warn(result);
  expect(result).not.toBeUndefined();
});

Fails with:

FAIL  src/db.test.ts
✕ should pass (22 ms)

● should pass

  MissingAPIError: IndexedDB API missing. Please visit https://tinyurl.com/y2uuvskb

    at cmp (node_modules/dexie/src/functions/cmp.ts:9:25)
        at Array.forEach (<anonymous>)
    From previous:
    From previous:

repro

InvalidStateError when parallely opening a db that needs a versionchange transaction

Here is a STR:

var indexedDB = require("fake-indexeddb");

function openDb() {
  return new Promise((resolve, reject) => {
    var request = indexedDB.open("test", 3);
    request.onupgradeneeded = function () {
      var db = request.result;
      var store = db.createObjectStore("books", {keyPath: "isbn"});
    }
    request.onsuccess = function (event) {
      var db = event.target.result;
      resolve(db);
    };
  });
}

openDb();

openDb().then(db => {
  db.transaction("books");
  console.log('All good!');
});

You can clone the repository here: https://github.com/julienw/fake-indexeddb-bug

You can also see it live (open the Devtools' console to see it, as the page itself is blank):

Collaboration?

In case you weren't aware, IndexedDBShim can also allow Node usage in a manner that creates databases in memory online (or to temporary file): See memoryDatabase under https://github.com/axemclion/IndexedDBShim/#user-content-configuration-options

We also have a high test passing rate, with about 94% of W3C test files completely passing (96% if excluding exception order tests which have issues due to transaction timing limits from our avoiding synchronous operations).

It'd be great to have extra hands working together on what seems to be similar work or at least hear about any disadvantages you may have found with our project relative to yours...

Best wishes!

Compound keys with undefined values

Hi! First, thanks for this lib, I have built a web-app that relies heavily on IndexedDB for functionality and it doesn't seem like Google would index the site properly when using the real IndexedDB, but I've had better success when using the fake lib.

My problem was with compound keys, specifically when the object I try to add did not have one or both of the key values set. To get around the problem I modified extractKey.js to handle undefined values also.

Example indata:

keyPath: ['parent', 'id']
value: { some_other_values: 1 }

In this case validateKey throws an exception since the keys have undefined value.
Here is my workaround:

function extractKey(keyPath, value) {
    if (Array.isArray(keyPath)) {
        var result = [];

        keyPath.forEach(function (item) {
            // This doesn't make sense to me based on the spec, but it is needed to pass the W3C KeyPath tests (see same comment in validateKey)
            if (item !== undefined && item !== null && typeof item !== 'string' && item.toString) {
                item = item.toString();
            }
		var key = extractKey(item, value);
		if(key === undefined || key === null) {
			result.push(undefined);
		} else {			
			result.push(structuredClone(validateKey(key)));
		}
        });

Now, this seems to work for my code at least, but I don't know if this will break specs or introduce other problems.

Feature Request: Ability to totally wipe/reset state

I would love to have an option to be able to delete all databases and totally reset the state of the indexedDB mock.

My use case:

  • Testing some functions using an external library that works with indexedDB
  • That library doesn't tell me the names of the databases that it's creating / working with
  • After each test, I want to be able to totally reset the state of indexedDB, regardless of what databases may or may not have been created

Because of this situation, I'm note able to make the solution found by @jcalfee here.

fakeIndexedDB.deleteDatabase("unknown name") // can't because I don't know the name

And there doesn't seem to be a standard way to do a wipe of all dbs in indexedDB.

So for the sake of testing (especially if testing stuff using 3rd party libraries that interact with indexedDB), it would be great if a special method could be added to totally wipe and reset the state of indexedDB.

Issues with latest version of jest with the jsdom environment

Hey,

Recently, the jest folks removed setImmediate and clearImmediate from the jsdom environment (they had it before incorrectly). This is a good thing.
fakeIndexedDB uses the setimmediate polyfill in case setImmediate isn't present. This is all good.

But... there's a problem when we start using the fake timers. Indeed, the polyfill seems to rely on setTimeout (although I'm not 100% sure why, from their code it should be process.nextTick... which isn't a macrotask either in recent node versions actually), and setTimeout is using the fake timeouts from jest so never ends.

The testing-library folks try to detect if we're in jest with fake timers, and in that case they run some code using the real timers:
https://github.com/testing-library/dom-testing-library/blob/c273ed518cf783591692be8c0c5e5a34feafd4bb/src/helpers.js#L7-L12
Could that be a solution for fakeIndexedDB? Should you move to process.nextTick anyway?

Thanks for this wonderful tool!

Circular import

Hey! Thanks for this lib!

I'm trying to use fakeIndexedDB in node environment and have the following code:

import FDBCursor = require("fake-indexeddb/lib/FDBCursor");

Just trying to import fdbcursor but it throws error:

    TypeError: Object prototype may only be an Object or null: undefined
        at setPrototypeOf (<anonymous>)

      at extendStatics (node_modules/fake-indexeddb/build/FDBCursorWithValue.js:7:16)
      at __extends (node_modules/fake-indexeddb/build/FDBCursorWithValue.js:10:9)
      at node_modules/fake-indexeddb/build/FDBCursorWithValue.js:18:5
      at Object.<anonymous> (node_modules/fake-indexeddb/build/FDBCursorWithValue.js:28:2)

I found that it is because of circular import.

What should i do?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.