standard-things / esm

Tomorrow's ECMAScript modules today!
Other
5.26k stars 146 forks source link

jest transform support #706

Open kenotron opened 5 years ago

kenotron commented 5 years ago

I'm collecting some esm + jest + react + enzyme "real world" issues as I'm going here: https://github.com/kenotron/esm-jest/

  1. On https://github.com/standard-things/esm/blob/33ee0ac7e8c7aec7db176143f833560f7a09f069/esm.js#L178, _runResult can be undefined it seems, so add a conditional there will help
  2. A package like domutils that is used by jsdom & htmlparser2 will do silly things like this: https://github.com/fb55/domutils/blob/master/index.js where they loop through all the object keys and start calling ".bind" because they didn't expect something else to inject properties into the object (could be a jest + domutils goober? not necessarily esm??)

Anyway, it's almost there with jest as far as I can tell! If I just hack-patch this stuff conditional around the problematic code, jest works with esm!

jdalton commented 5 years ago

What we shipped in v3.1.0 is the beginnings of support.

You can use esm as a Jest transform with --no-cache to run simple ESM test files. I need to abstract our Jest wiring into a hook to allow it to tap more cleanly into the exposed transform method of process() and getCacheKey().

kenotron commented 5 years ago

Thanks so much for working on this tirelessly. I'll try out that --no-cache and report some findings here. I think what I want to do is to create several examples of jest test suites to test out just how "simple" we need to get with our tests.

TrySound commented 5 years ago

@jdalton Does it work now?))

jdalton commented 5 years ago

Hi @TrySound!

Not yet. The v3.1.1 had to be released sooner to address more critical bugs that shook out after the v3.1.0 release. I'm still going to work on wrapping up Jest support soon though :)

ephemer commented 5 years ago

I noticed 3.1.4 is out, but didn't see any commits relating to this in the git history. I guess you'll update this issue when it's ready @jdalton. Thanks for your amazing work on this!

kellengreen commented 5 years ago

Thanks for all your great work @jdalton.

Should anyone else be curious, I can confirm we're still not quite there yet. My testing with esm@3.1.4 and jest@24.0.0 commonly yields the following errors:

TypeError: _.a(...) is not a constructor
TypeError: Cannot read property 'next' of undefined
ashton commented 5 years ago

Same result as @kellengreen here, any news?

matsp commented 5 years ago

Maybe just wait till finished?

jdalton commented 5 years ago

Thanks for the interest y'all! I'll be sure to update this issue when support 🚢

avaly commented 5 years ago

Not sure if the following is a known issue in terms of the work remaining required for jest compatibility (so feel free to ignore this if it is known @jdalton):

The globals defined in jest.config.js are not available in the tests when using esm as a transform in jest (esm@3.2.0 and jest@24.0.0)

dandv commented 5 years ago

Does the v12 release make this work any easier? What would be the recommended way to use Jest with ESM now?

chungchi300 commented 5 years ago

Any updates?

jdalton commented 5 years ago

@dandv

Does the v12 release make this work any easier?

It does not unfortunately.

@dandv @chungchi300

What would be the recommended way to use Jest with ESM now?

Continuing to use Babel is the way at the moment until I can get to making esm work.

onigoetz commented 5 years ago

If that's any help here's how I made it work in the build tool I maintain for work.

I created a small transformer which has only the job of converting import/export, and tries to do so only if needed : https://github.com/swissquote/crafty/blob/master/packages/crafty-preset-jest/src/esm-transformer.js

Which is then added as a jest transform (https://github.com/swissquote/crafty/blob/master/packages/crafty-preset-jest/src/index.js#L50) So I guess you could use that in your own projects by installing:

yarn add @swissquote/crafty-preset-jest

And adding this to your Jest configuration:

{
    "transformIgnorePatterns": [],
    "transform": {
        "[/\\\\]node_modules[/\\\\].+\\.m?js$": "@swissquote/crafty-preset-jest/src/esm-transformer"
    }
}
ActuallyACat commented 5 years ago

@onigoetz Awesome, thanks for posting this! I had a small issue with some of the checks that were in your file (I think it had to do with the version of Babel I was using?), so I stripped it all back to just parse everything. Works well for my use case, but probably not so well for others.

I've credited you here: https://github.com/ActuallyACat/jest-esm-transformer

onigoetz commented 5 years ago

@ActuallyACat cool :) You didn't specify the dependencies in the package.json, maybe add at least peerDependencies so that yarn PNP is happy

The reason I added the checks is that Babel has a cost for processing that is quite high if you have to run it on all the files you require from node_modules (for example trying to change all imports in React ... which has none)

damianobarbati commented 5 years ago

@jdalton is the following statement still valid?

You can use esm as a Jest transform with --no-cache to run simple ESM test files. I need to abstract our Jest wiring into a hook to allow it to tap more cleanly into the exposed transform method of process() and getCacheKey().

I'm trying to run a simple spec with:

npx -n '-r esm' jest func.spec.js

and transforms: {} in my package.json jest section but the:

    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import func from './func.js';
                                                                                                    ^^^^
    SyntaxError: Unexpected identifier

is still afflicting me xD

topheman commented 4 years ago

I tried to use esm with jest as a loader. I had the following problems, maybe it will help for the next steps.

You can find a minimal reproducible case on that repo.

1) Due to the following error:

TypeError: Jest: a transform must export a `process` function.

I had to downgrade from esm@3.2.25 to esm@3.1.0.

2) Then I encountered the following error:

    TypeError: Cannot read property 'next' of undefined

      at Object.n.(anonymous function) (node_modules/esm/esm.js:1:1796)

Which might be due to the fact that might be due to the fact that the src/common.js file is being imported:

Those are basic tests (add, sub, concat), only for example. See topheman/jest-esm-experiments

It is fixable if I use babel-jest as a loader (which I did on the original project where I spotted the bug)

machineghost commented 4 years ago

A salute to the brave people in this thread. It's amazing/unfortunate that this giant thread (with associated repositories and whatnot) exists, and yet using the amazing esm module with Mocha is trivial.

I just don't understand why the Jest people won't simply add a --require arg ... but since they won't, personally I'm going back to Mocha.

scamden commented 4 years ago

@jdalton

Continuing to use Babel is the way at the moment until I can get to making esm work.

Is this still the recommendation? jest is the last barrier between converting our entire code base to esm...

matsp commented 4 years ago

If I understand this correctly, this "issue" is not anymore existing with the newest Node version which enables ESM modules?

victorperin commented 4 years ago

The latest version of node now implemented the new module loader. Does it work on Jest?

scamden commented 4 years ago

From my scans of GitHub threads, it seems like jest has its own require implementation so even on the new experimental module system in node it wasn’t working, but I don’t know for sure and that’s why I was hoping @jdalton might update this thread :)

sheerun commented 4 years ago

Node's ES modules don't solve it at all (they require package.json with "type": "module", require explicit extensions in imports, and they don't allow interop between CJS and ES6 modules).

I'm cheering for this to be added @jdalton Maybe you could publish some simplified (or slow) implementation in the meantime?

machineghost commented 4 years ago

@sheerun instead of the "type": "modules" entry in package.json you can also use the .mjs extension :scream: :scream_cat: ... you know, instead of the .js extension which we've all used, and which has worked just great for over two decades :wink:

Seriously, why does the Node org hate us all so much? Thank god for @jdalton.

damianobarbati commented 4 years ago

Yeah Node guys are definitely making a mess. We won't have ESM working for years because of the incompatibility and exports/type requirement. But I trust those guys so it was probably inevitable.

The only choice nowadays is ESM, thanks @jdalton.

bencondon commented 4 years ago

What's the suggested solution to work with jest and esm in its current state?

damianobarbati commented 4 years ago

@bencondon the solution is using jasmine and wait for better times 😂

JakeChampion commented 4 years ago

I've been adding this to the top of my jest test files and it works great:

const esmImport = require('esm')(module);
const moduleBeingTested = esmImport('../src/module');

E.G.

// ./src/add.js
export function add (a,b) {
  return a + b;
}
// ./test/add.test.js
const esmImport = require('esm')(module);
const add = esmImport('../src/add).add;

describe('add', () => {
  it('works as expected', () => {
    expect(add(1,1).toBe(2);
  });
)};
dandv commented 4 years ago

See also the Native support for ES Modules.

rafaeleyng commented 4 years ago

@JakeChampion Tested your suggestion and it works. It doesn't seem to work with jest.mock, though. Any idea on how to work with jest.mock?

the21st commented 4 years ago

@JakeChampion is it possible to make your solution work in a Typescript project?

JakeChampion commented 4 years ago

@the21st No idea as I don't use TypeScript, sorry about that.

KyranRana commented 4 years ago

Any idea on how this is coming along? When it will be ready?

dav1app commented 3 years ago

It seems that Jest is trying to make ESM modules natively available. I understand why it is hard to make it available for general usage, but I also cannot understand why you simply cannot -r esm to solve this.

https://github.com/facebook/jest/issues/9430

nichegosebe commented 3 years ago

babel.config.js - done jest.config.js - done ... SyntaxError: Cannot use import statement outside a module