jest-extended icon indicating copy to clipboard operation
jest-extended copied to clipboard

Support jest esm mode

Open viceice opened this issue 3 years ago • 14 comments

Feature Request

Description:

I'm using jest in esm mode, because my code simply requires it. But i can't use this library as it expects jest globals.

Possible solution:

Import jest from @jest/globals . https://jestjs.io/docs/ecmascript-modules#differences-between-esm-and-commonjs

  • ref #408

viceice avatar Apr 29 '22 06:04 viceice

where does jest-extended use jest? it should only use expect, which is still a global (unless you've disabled it)

SimenB avatar Apr 29 '22 07:04 SimenB

ok, it's disabled 🙃

but I've also type issues after enable. So if i add 'jest-extended' to my tsconfig.json , it also makes all jest types global again and vscode no longer suggests to import them, which of caus will fail when running tests (at least the jest global isn't available)

viceice avatar Apr 29 '22 07:04 viceice

right. if you disable the globals you'll need to extend yourself.

import {expect} from '@jest/globals';
import jestExtendedMatchers from 'jest-extended';

expect.extend(jestExtendedMatchers);

we can probably expose some /all-imported thing which does this. Wanna send a PR?

(some discussion in #333)

SimenB avatar Apr 29 '22 08:04 SimenB

@SimenB unfortunately, what you suggest is not working because import from jest-extended gives this error:

TS2306: File '/Users/aleksey/Code/DOS-liquidation-bot/node_modules/jest-extended/types/index.d.ts' is not a module.

After spending quite a lot of time and trying everything from docs and issues, I didn't find a single workaround - there is just no way jest-extended can be used with ESM and TypeScript :(

Alexsey avatar Jan 31 '23 10:01 Alexsey

Does adding export {} at the bottom of that file work?

SimenB avatar Jan 31 '23 12:01 SimenB

Thank you for the quick reply! It removed the error but types on expect(...) didn't appear

The issue is only with types - adding "setupFilesAfterEnv": ["jest-extended/all"] to jest config itself making the code with @ts-expect-error/@ts-ignore on jest-extended method calls work

UPD: Of course, I have "types": ["node", "jest", "jest-extended"] in compilerOptions of tsconfig. But considering that types is about globals and auto-imports, it shouldn't matter, because with ESM I'm forced to use explicitly imported expect

Alexsey avatar Jan 31 '23 17:01 Alexsey

I'm having the same issue - was not able to get jest-extended to work in jest using ESM. @Alexsey - did you ever find a solution?

I tried a while back and gave up...

johncrim avatar Apr 01 '23 23:04 johncrim

Unfortunately, not

Alexsey avatar Apr 02 '23 07:04 Alexsey

For the reference, @testing-library/jest-dom coped with it in the following way: https://github.com/testing-library/jest-dom/issues/426

mvshmakov avatar Jul 06 '23 08:07 mvshmakov

Update for jest-extended v4.0.0:

  • the error on import from 'jest-extended' has been fixed
  • return value of expect(...) is still missing the jest-extended types

For example expect([]).toBeArray() will give the error:

TS2339: Property 'toBeArray' does not exist on type 'Matchers  & SnapshotMatchers  & Inverse  > & PromiseMatchers '.

Alexsey avatar Jul 06 '23 09:07 Alexsey

It sort of looks like index.d.ts is trying to merge its matchers into the Expect interface, but instead it's just creating a new local Expect interface.

Peeja avatar Aug 07 '23 19:08 Peeja

@Peeja this is a TypeScript feature called declaration merging that allows extending the Expect, even though jest-extended code doesn't own it, by redeclaring it. Of course, Expect is expected to be in global scope, otherwise a dummy local Expect interface would be created

Alexsey avatar Aug 07 '23 20:08 Alexsey

@Alexsey Yes, I know. That's exactly the point I'm making.

Peeja avatar Aug 08 '23 00:08 Peeja

This hacky import and a declaration workaround seems to work for matchers at least.

import {expect} from '@jest/globals'
expect.extend((await import('jest-extended')).default)

declare module '@jest/expect' {
    export interface Matchers<R extends void | Promise<void>> extends CustomMatchers<R> {}
}

For asymmetric matchers, expect can't be declaration merged because it's a type, but it can be casted. ex: (expect as any).toSatisfy(...)

    "@types/jest": "29.5.9",
    "jest": "29.7.0",
    "jest-extended": "4.0.2",
    "ts-jest": "29.1.1",
    "typescript": "5.3.2"

nlwillia avatar Nov 30 '23 00:11 nlwillia