ionic-team / stencil

A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
https://stenciljs.com
Other
12.43k stars 779 forks source link

feat: Support ES modules in jest tests #3230

Open johncrim opened 2 years ago

johncrim commented 2 years ago

Prerequisites

Describe the Feature Request

Stencil tests should be able to run using Jest ES Module support, instead of transpiling all ESM modules to CJS. This needs to be done to improve test perf, and because ESM is preferred in all modern projects that are used in browsers.

Right now, stencil jest support hard-codes CJS output: https://github.com/ionic-team/stencil/blob/main/src/testing/test-transpile.ts

Describe the Use Case

When I run stencil tests, I should have the option to run them in Jest ESM mode.

The lack of this feature causes bugs and wasted dev effort, eg: https://github.com/ionic-team/stencil/issues/2178

Performance should be improved b/c .mjs files (most dependencies) will no longer need to be transpiled. Dev cycle speed is important!

In addition, there are behavioral differences between CJS and ESM, and it's valuable for the test environment to be as similar as possible to the runtime environment.

Describe Preferred Solution

A config option exists for running tests in Jest ESM mode.

Describe Alternatives

No response

Related Code

No response

Additional Information

https://kulshekhar.github.io/ts-jest/docs/next/guides/esm-support/

Related issues:

I'm willing to work on a PR for this - looks like it shouldn't be too hard.

rwaskiewicz commented 2 years ago

Hey @johncrim 👋

I agree that Stencil should support ES Modules when using Jest. To be honest, I had not been considering this support until Jest's ESM support came out of it's 'experimental' phase. But if you're interested, I say go for it!

johncrim commented 2 years ago

Thanks @rwaskiewicz . I certainly understand waiting until the experimental phase ends - I can't fault you for that, though I don't know how long it will remain in experimental.

It's working acceptably with ts-jest and jest + angular (though still a little bumpy). I just migrated our angular jest tests to Jest ESM and would like to tackle this as long as it's not too involved (from a code review it looks pretty straightforward, but I could certainly be wrong about that).

johncrim commented 2 years ago

Hi @rwaskiewicz - I have a working PR that works great for our projects. Lmk when you have time to review.

rwaskiewicz commented 2 years ago

Hey @johncrim - I haven't forgotten about this, I'll circle back as soon as I get a chance

subasically commented 2 years ago

any updates on this?

johncrim commented 1 year ago

Hi @rwaskiewicz - the PR may be outdated (I don't know what has changed since I created it), but would be great to get either my PR merged, or this fixed some other way.

rwaskiewicz commented 1 year ago

@johncrim

Agreed - I've done a little work internally to make Jest easier to upgrade (and easier to change things like ESM support). I'm hoping to move to the prototyping stage later this week, from there I hope to be able to be in a better place to determine how we can work with this PR

ryuran commented 1 year ago

I'm blocked by this situation because one of my component use swiper available only as esm in last version and it make fail the related spec test.

   FAIL  src/components/carousel/carousel.spec.ts
    ● Test suite failed to run

      Jest encountered an unexpected token

      Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

      Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

      By default "node_modules" folder is ignored by transformers.

      Here's what you can do:
       • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
       • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
       • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
       • If you need a custom transformation specify a "transform" option in your config.
       • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

      You'll find more details and examples of these config options in the docs:
      https://jestjs.io/docs/configuration
      For information about custom transformations, see:
      https://jestjs.io/docs/code-transformation

      Details:

      /root/actions-runner/_work/----/----/node_modules/swiper/swiper.esm.js:13
      export { default as Swiper, default } from './core/core.js';
      ^^^^^^

      SyntaxError: Unexpected token 'export'

        12 |   forceUpdate,
        13 | } from '@stencil/core';
      > 14 | import { Swiper, SwiperOptions } from 'swiper';
           | ^
        15 |
        16 | import { defaultSwiperOptions } from './carousel.option.defaults';
        17 |

        at Runtime.createScriptFromCode (../../node_modules/jest-runtime/build/index.js:1728:14)
        at Object.<anonymous> (src/components/carousel/carousel.tsx:14:1)

Current workaround, add a transform option in jest config to transform concerned modules from ESM to CommonJS using babel-jest

cam-narzt commented 1 year ago

The old workaround of editing the jest config doesn't work since stencil 2.14.0 when jest's config file sterted to be ignored (per: https://github.com/ionic-team/stencil/issues/3251) so fixing this is pretty important since there's no workaround anymore.

EduardoFelipeLogcomex commented 1 year ago

this adjustment would be very important for the project I've been developing!

dellfort commented 9 months ago

any news? we also need the es modules working in tests. btw, the workaround with transformIgnorePatterns works only for direct dependencies. steps to reproduce: add a dependency with subsequent dependencies, e.g.:

"dependencies": {
      "wired-elements": "^3.0.0-rc.6"
}

@import "wired-elements"; npm run test -> Jest encountered an unexpected token [...] {export * from './wired-button' [...]

now add to stencil.config.ts

testing: {
        transform: {"^.+\\.(js|ts)x?$": '@stencil/core/testing/jest-preprocessor'},
        transformIgnorePatterns: ['node_modules/(?!(wired-elements)/)'],
}

npm run test -> Jest encountered an unexpected token [...] {import"@lit/reactive-element";import"lit-html";exportfrom"lit-element/lit-element.js";exportfrom"lit-html' [...]

so that has an effect, but subsequent imports are now failing. trying to extend the ignore pattern does not have any effect:

transformIgnorePatterns: ['node_modules/(?!(wired-elements|lit-element|lit-html|lit|@lit|@lit/reactive-element)/)'],

So there is currently no workaround for this right now. This is reproducable with a lot of libraries e.g. ibm carbon and our own library, too.

johncrim commented 7 months ago

I provided a PR for this in Feb 2022, but it never went anywhere...

botandrose commented 7 months ago

@rwaskiewicz Very interested in seeing this resolved, too. I just spent a week porting one of our web components to Stencil (which was a huge improvement), and was very surprised to learn that I can't actually port the tests over to Stencil, because the component has an ESM dependency.

If there's anything I can do to help land @johncrim 's PR (perhaps a rebase), or otherwise assist in getting this fixed, I volunteer my time. Please advise?

TheKonka commented 5 months ago

@ryuran Hello! I have the same problem using stencil@2.22.3 and swiper@11.0.5. I've tried all the solutions I've found, but none of them work, can you share your config code for this?

pfteter commented 2 months ago

Any updates on this, should be quite important ?

@rwaskiewicz @christian-bromann

christian-bromann commented 2 months ago

@pfteter we have been de-prioritizing Stencils Jest integration and worked on better alternatives, e.g. via WebdriverIO or Playwright. At this point I can't tell when this will be picked up. Maintaining this Jest integration adds a lot of work to the team with little value in return. In an ideal world we would want to have users use Jest directly and ESM should work out of the box. I may look into this in one of our next Jedi days.

christian-bromann commented 2 weeks ago

Any updates on this, should be quite important ?

@pfteter with the release of Jest v30 we will be working on a Jest preset plugin (e.g. @stencil/jest) that you can use moving forward. Keep an eye on this issue for updates.