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

Svelte 4 breaks unit tests involving stores #8994

Closed
bw-alessandro opened this issue Jul 18, 2023 · 10 comments
Closed

Svelte 4 breaks unit tests involving stores #8994

bw-alessandro opened this issue Jul 18, 2023 · 10 comments

Comments

@bw-alessandro
Copy link

Describe the bug

My team is attempting to upgrade our company's application to svelte 4. We have been careful to upgrade all necessary dependencies before pulling the trigger. Now the only thing left to upgrade is svelte itself. However, as soon as we do upgrade any unit test we have that involve svelte/stores break.

We are utilizing Svelte with Typescript, and our unit tests are run via Jest.

We get the following output:

 Details:

    /Users/work/Repos/bqp/site/node_modules/svelte/src/runtime/store/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import {
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import { writable, Writable } from 'svelte/store';
        | ^

Reproduction

https://github.com/bw-alessandro/svelte-sample-app

This is a sample app that can reproduce the issue.

  1. npm i
  2. npm run test with svelte 3, the unit test executes successfully.
  3. npx svelte-migrate@latest svelte-4 and upgrade the project.
  4. npm i
  5. npm run test The tests will fail to run.

Logs

FAIL  services/alert-store.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:

    /Users/work/Repos/bqp/site/node_modules/svelte/src/runtime/store/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import {
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import { writable, Writable } from 'svelte/store';
        | ^
      2 | import * as cookie from 'cookie';
      3 |
      4 | export enum AlertType {

      at Runtime.createScriptFromCode (../node_modules/jest-runtime/build/index.js:1496:14)
      at Object.<anonymous> (services/alert-store.ts:1:1)
      at Object.<anonymous> (services/alert-store.spec.ts:1:1)

System Info

System:
    OS: macOS 13.4.1
    CPU: (12) arm64 Apple M2 Pro
    Memory: 968.73 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.16.1 - ~/.nvm/versions/node/v18.16.1/bin/node
    npm: 9.5.1 - ~/.nvm/versions/node/v18.16.1/bin/npm
  Browsers:
    Chrome: 114.0.5735.198
    Edge: 114.0.1823.82
    Safari: 16.5.2
  npmPackages:
    rollup: ^2.79.1 => 2.79.1 
    svelte: ^4.0.0 => 4.0.5

Severity

blocking an upgrade

@hugueschabot
Copy link

I have a similar issue while importing @testing-library/svelte. Maybe it is not strictly related to stores?

    Details:

    /home/hugues/projects/project/node_modules/svelte/src/runtime/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export {
                                                                                      ^^^^^^

    SyntaxError: Unexpected token 'export'

    > 1 | import { render } from "@testing-library/svelte"

@dummdidumm
Copy link
Member

dummdidumm commented Jul 19, 2023

Since Svelte does only provide an ESM version of the runtime now, this probably involves configuring Jest in a way that it transpiles the ESM modules in node_modules/svelte to CJS because Jest can only handle CJS (there's a experimental ESM mode though). How to do that - no idea yet.
When testing things out, remember to call jest --clearCache because that might cache a wrong transformation and then you're left wondering why things don't work.

@benmccann
Copy link
Member

benmccann commented Jul 19, 2023

svelte-jester has been tested to support Svelte 4. You may be able to either use it directly or as an example. I've posted tips on how to set that up over in that repo: svelteness/svelte-jester#121 (comment)

I'll also take a minute to suggest that vitest is better than jest for most Svelte users. It has a largely compatible API, so you might consider migrating, which hopefully wouldn't be too hard given the API similarity. If not for your whole test suite, then at least for a portion that gives you the most difficulty in combination with jest.

@benmccann
Copy link
Member

benmccann commented Jul 19, 2023

I have a similar issue while importing @testing-library/svelte

Svelte 4 support was added to @testing-library/svelte version 4. Note however that it only supports ESM, so you'll have to setup ESM support as described in my previous comment

@bw-alessandro
Copy link
Author

The problem seems to lie with jest. However, I have not been able to find a solution. None of the instructions for supporting ESM dependencies work.
Unfortunately moving to vitest would be a rather large undertaking for us. For now we are stuck on Svelte 3.
I will continue to search for a solution. If I do find one I will post it here.

@bw-alessandro
Copy link
Author

The issue is stemming from helper functions in regular .ts files specifically where we define custom stores and therefore need to import svelte/store.

@sveltejs sveltejs deleted a comment from mlandisbqs Jul 21, 2023
@benmccann
Copy link
Member

benmccann commented Jul 21, 2023

The issue is stemming from helper functions in regular .ts files specifically where we define custom stores and therefore need to import svelte/store.

This is probably because Svelte 4 removed the CJS version of the Svelte runtime, which would include svelte/store. You really need to ensure that you're running in ESM mode with Svelte 4

None of the instructions for supporting ESM dependencies work.

Can you please file an issue in svelte-jester with a reproduction? There's not enough info here to be able to understand what issue you're encountering

Unfortunately moving to vitest would be a rather large undertaking for us

What part in particular? Perhaps you could try the auto migration tool. Is there something we could suggest Vitest to add a method for or improve their migration guide for?

@bw-alessandro
Copy link
Author

@benmccann Thanks for the suggestions. However, I thought with the example project I provided in the repro section would make it pretty clear what the issue is we are facing.

It really has nothing to do with svelte-jester as the unit tests that fail are for helper files that live along side svelte components. And the sample project does not have it as a dependency.

We have hundreds of .spec files that utilize jest for mocking objects, timers, etc. And we have discussed plans to abstract those dependencies away but still it would take a long time to do. I will however review the migration tool you linked to, perhaps that would help us. Thanks for that.

@benmccann
Copy link
Member

@bw-alessandro I was able to migrate the sample project you provided to Svelte 4. The steps I provided in the svelte-jester issue can still be followed, but just skip the first one instructing you to upgrade your svelte-jester version and follow the rest: svelteness/svelte-jester#121 (comment). In your case, there was an additional step needed to configure ts-jest, so I've updated the instructions there to include that step as well. Hopefully with this additional step now listed you'll be unblocked from migrating. I'm going to go ahead and close this since it appears to be working

@benmccann
Copy link
Member

There's an issue in svelte-jester repo about CJS support: svelteness/svelte-jester#166. Users that really cannot migrate to ESM may be able to compile the ESM output to CJS as described there

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

4 participants