Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A value which is actually Date, but instanceOf Date equals false when use with jest+jsdom. #98

Closed
sjnho opened this issue Mar 19, 2024 · 5 comments

Comments

@sjnho
Copy link
Contributor

sjnho commented Mar 19, 2024

I have a objectStore with index via a Date value.

const request = indexedDB.open('testDB',1);
request.onupgradeneeded=()=>{
   const db = request.result;
   const store = db.createObjectStore('testStore');
   store.createIndex('dateIndex','created',{unique:false})
}

Add some test data like {data:"test",created:new Date()} in jest test suite.
But when I run as follow code.

const store = db.transaction(['testStore'], 'readwrite').objectStore('testStore');
const index = store.index('dateIndex');
const request = index.openCursor();
request.onsuccess = function () {
    const cursor = request.result;
    if (cursor) {
        cursor.delete();
        cursor.continue();
    } else {
        res();
    }
};

The cursor is always null.
And I console.log (index._rawIndex.records). It is an empty array.
After my investigation , the reason is jsdom override Date,
so the date instance check in valueToKey.ts will return false, step into else and throw new DataError()

} else if (input instanceof Date) {

My workaround is override global.Date

import JSDOMEnvironment from 'jest-environment-jsdom';

// https://github.com/facebook/jest/blob/v29.4.3/website/versioned_docs/version-29.4/Configuration.md#testenvironment-string
export default class FixJSDOMEnvironment extends JSDOMEnvironment {
  constructor(...args: ConstructorParameters<typeof JSDOMEnvironment>) {
    super(...args);
    this.global.structuredClone = structuredClone;
    this.global.Date = Date;
  }
}

How do you think about it ?
Do we need fix it using like
Object.prototype.toString.call(input ) === '[object Date]'

Or keep the workaround.

@dumbmatter
Copy link
Owner

I would think that if jsdom is overwriting the Date object, then the code inside fake-indexeddb should also have that Date object and it should work. But I guess that's not working right.

Can you give me a minimal reproduction to help make debugging easier?

@sjnho
Copy link
Contributor Author

sjnho commented Mar 21, 2024

@dumbmatter Sorry for my slow reply.
I create a repo.
https://github.com/sjnho/fakeindexeddb-jest-debug

@dumbmatter
Copy link
Owner

I think Object.prototype.toString.call(input) === '[object Date]' is probably a valid solution... https://stackoverflow.com/a/643827/786644 points out that there are other valid cases where instanceof can fail. In theory someone could make some other object that returns "[object Date]" from toString, but that is probably less likely than using jsdom like you did.

If you want to send a PR feel free! If not just say so and I'll do it, it's only one line of code (and probably a comment explaining it and linking here) - I just want to give you the opportunity to take credit for it with a PR if you want :)

@sjnho
Copy link
Contributor Author

sjnho commented Mar 22, 2024

No problem, I will send a PR. ❤️

sjnho added a commit to sjnho/fakeIndexedDB that referenced this issue Mar 22, 2024
dumbmatter added a commit that referenced this issue May 20, 2024
Fix issue #98: workaround to check date object
@dumbmatter
Copy link
Owner

This is in v6.0.0 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants