cypress icon indicating copy to clipboard operation
cypress copied to clipboard

Optional chaining isn't working with `next.js`

Open RaenonX opened this issue 4 years ago β€’ 29 comments

Current behavior

If the test code contains optional chaining, the tester fails to run.

Error: Webpack Compilation Error
./cypress/integration/sandbox.test.ts 5:25
Module parse failed: Unexpected token (5:25)
File was processed with these loaders:
 * C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\ts-loader\index.js
You may need an additional loader to handle the result of these loaders.
|     it('fails', () => {
|         let something;
>         expect(something?.length).to.equal(5);
|     });
| });
    at Watching.handle [as handler] (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\@cypress\webpack-preprocessor\dist\index.js:172:23)
    at C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\webpack\lib\Watching.js:99:9
    at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\tapable\lib\Hook.js:154:20)
    at Watching._done (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\webpack\lib\Watching.js:98:28)
    at C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\webpack\lib\Watching.js:73:19
    at Compiler.emitRecords (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\webpack\lib\Compiler.js:499:39)
    at C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\webpack\lib\Watching.js:54:20
    at C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\webpack\lib\Compiler.js:485:14
    at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\tapable\lib\Hook.js:154:20)
    at C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\webpack\lib\Compiler.js:482:27
    at C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\neo-async\async.js:2818:7
    at done (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\neo-async\async.js:3522:9)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\tapable\lib\Hook.js:154:20)

Desired behavior

Should allow to run the test without any additional configurations.

This seems to an issue coming from webpack and it has been resolved from a version.

Test code to reproduce

  1. npm install cypress
  2. npx cypress open
  3. Have the below in the testing code and run it,.
describe('Optional chaining', () => {
  it('fails', () => {
    let something: string[] | undefined;

    expect(something?.length).to.equal(5);
  });
});

Not forking or creating a repo for repro because it seems that the source of the problem is bundled webpack.

Versions

Cypress package version: 7.5.0
Cypress binary version: 7.5.0
Electron version: 12.0.0-beta.14
Bundled Node version:
14.15.1

Obtained from cypress --version.

RaenonX avatar Jun 13 '21 23:06 RaenonX

What version of webpack do you have installed?

lmiller1990 avatar Jun 14 '21 01:06 lmiller1990

What version of webpack do you have installed?

I am using webpack 5.

Presumably it should be installed along with next.js because every time I start my app in dev mode, it shows Using webpack 5. Reason: no next.config.js https://nextjs.org/docs/messages/webpack5.

RaenonX avatar Jun 14 '21 04:06 RaenonX

You might need to share a minimal reproduction. I followed the guide on installing TypeScript, added a minimal webpack config (using webpack 5) and it works okay for me:

image

Next.js has proven tricky in the past, if you can share a repo I could have a look.

lmiller1990 avatar Jun 14 '21 06:06 lmiller1990

OK, will take some time and see if I can create a repro for investigation

RaenonX avatar Jun 15 '21 23:06 RaenonX

@lmiller1990 May I obtain the webpack config you used? next.js does not require a webpack config, so I think that might be the root cause of the problem.

RaenonX avatar Jun 19 '21 04:06 RaenonX

Sure, this is my plugins/index.js file:

const webpackPreprocessor = require('@cypress/webpack-preprocessor')

/**
 * @type {Cypress.PluginConfig}
 */
module.exports = (on) => {
  on('file:preprocessor', webpackPreprocessor({
    webpackOptions: {
      module: {
        rules: [
          {
            test: /\.ts$/,
            use: 'ts-loader'
          }
        ]
      }
    }
  }))
}

Next.js uses webpack internally, it's hidden away in node_modules/nextjs/......somewhere...... If you can create a minimal reproduction, happy to take a look.

lmiller1990 avatar Jun 21 '21 00:06 lmiller1990

Here's the repro repo: https://github.com/RaenonX/cypress-optional-chaining-repro.

It doesn't re-create this error for some reason, but instead introduced another error.

Reproduction

  1. npx create-next-app --ts
  2. npm i cypress --save-dev
  3. Create the sandbox test file
  4. npx open cypress

Then, because in cypress testing page, it says that ts-loader is not found, so I npm install ts-loader.

After that, cypress testing page yields this instead:

Error: Webpack Compilation Error
./cypress/integration/sandbox.spec.ts
Module build failed (from ./node_modules/ts-loader/index.js):
Error: Cannot find module 'D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\enhanced-resolve\lib\node.js'. Please verify that the package.json has a valid "main" entry
    at Watching.handle [as handler] (D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\@cypress\webpack-preprocessor\dist\index.js:172:23)
    at D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\webpack\lib\Watching.js:99:9
    at AsyncSeriesHook.eval [as callAsync] (eval at create (D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
    at Watching._done (D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\webpack\lib\Watching.js:98:28)
    at D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\webpack\lib\Watching.js:73:19
    at Compiler.emitRecords (D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\webpack\lib\Compiler.js:499:39)
    at D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\webpack\lib\Watching.js:54:20
    at D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\webpack\lib\Compiler.js:485:14
    at AsyncSeriesHook.eval [as callAsync] (eval at create (D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
    at D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\webpack\lib\Compiler.js:482:27
    at D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\neo-async\async.js:2818:7
    at done (D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\neo-async\async.js:3522:9)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
    at D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\webpack\lib\Compiler.js:464:33
    at C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\graceful-fs\graceful-fs.js:111:16
    at D:\UserData\Downloads\cypress-optional-chaining-repro\node_modules\graceful-fs\graceful-fs.js:61:14
    at C:\Users\maple\AppData\Local\Cypress\Cache\7.5.0\Cypress\resources\app\packages\server\node_modules\graceful-fs\graceful-fs.js:45:10
    at FSReqCallback.oncomplete (fs.js:171:23)

I have no idea what this is, so I didn't move forward.


Also, I am using Windows.

Not sure about if this is caused by npx create-next-app because I migrated to next without using create-next-app. I never encountered this kind of error before.

RaenonX avatar Jun 21 '21 01:06 RaenonX

Also, when I was playing around these, my IDE was complaining that @cypress/webpack-preprocessor is not listed as dev dependency from the plugin file you provided.

However, if I do this npm i @cypress/webpack-preprocessor ts-loader, npm yields dependency confliction error.

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! Found: [email protected]
npm ERR! node_modules/webpack
npm ERR!   peerOptional webpack@"^4 || ^5" from @next/[email protected]
npm ERR!   node_modules/@next/react-refresh-utils
npm ERR!     @next/react-refresh-utils@"11.0.0" from [email protected]
npm ERR!     node_modules/next
npm ERR!       peer next@">=10.2.0" from [email protected]
npm ERR!       node_modules/eslint-config-next
npm ERR!         dev eslint-config-next@"11.0.0" from the root project
npm ERR!       1 more (the root project)
npm ERR!   peer webpack@"^5.1.0" from [email protected]
npm ERR!   node_modules/terser-webpack-plugin
npm ERR!     terser-webpack-plugin@"^5.1.1" from [email protected]
npm ERR!   1 more (ts-loader)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! dev @cypress/webpack-preprocessor@"*" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: [email protected]
npm ERR! node_modules/webpack
npm ERR!   peer webpack@"^4.18.1" from @cypress/[email protected]
npm ERR!   node_modules/@cypress/webpack-preprocessor
npm ERR!     dev @cypress/webpack-preprocessor@"*" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See C:\Users\maple\AppData\Local\npm-cache\eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\maple\AppData\Local\npm-cache\_logs\2021-06-21T01_32_20_326Z-debug.log

RaenonX avatar Jun 21 '21 01:06 RaenonX

Right, I understand now. There are a few things at play here.

Because Next.js does not expose the config is uses (Webpack, etc) Cypress cannot use it by default. There are a few options. TS already knows about the ? operator. I was able to get your repo to work by just updating tsconfig.json. I changed "target": "es5" to "target": "esnext". Makes sense - es5 does not have the ? operator.

The other problem is related to webpack 5 support in the preprocessor in general. There is a bug where your tests will hang on the first run. The work-around right now is to just cmd + F5 to start the run. That bug will be fixed and released soon.

lmiller1990 avatar Jun 21 '21 01:06 lmiller1990

Oh good catch, I didn't notice that I was using the wrong target πŸ˜„

I am on Windows, tried Ctrl+F5, Win+F5, Alt+F5, and Shift+F5 but no luck. Since this is a workaround, I guess I will wait until the release then see if that works then.

RaenonX avatar Jun 21 '21 01:06 RaenonX

Yep, please wait a few days - working on getting that PR merged this week.

lmiller1990 avatar Jun 21 '21 06:06 lmiller1990

Very odd, optional chaining is only working when I set "target": "es2019" in my tsconfig.json. es2020, es2021, and esnext all fail.

I prefer leaving "target": "esnext" in my root tsconfig.json, so I've created a cypress/tsconfig.json with this content:

{
  "extends": "../tsconfig",
  "compilerOptions": {
    "target": "es2019"
  }
}

michaelhays avatar Jan 18 '22 22:01 michaelhays

@lmiller1990 @ZachJW34 any chance of supporting es2020, es2021, es2022, esnext and other newer values?

karlhorky avatar Jul 01 '22 16:07 karlhorky

@karlhorky we've done a pretty significant overhaul of CT testing in Cypress 10, can you verify if this is still an issue when trying CT + Next with the latest version of Cypress?

ZachJW34 avatar Jul 01 '22 16:07 ZachJW34

The issue is still occurring for me for any target higher than es2019, but with E2E testing. Component testing works fine.

michaelhays avatar Jul 01 '22 17:07 michaelhays

@ZachJW34 Yep, just ran into it with the latest Cypress 10.3.0.

When I specify my compilerOptions.target to be es2022 in cypress/tsconfig.json, compiling the tests with webpack fails on the optional chaining operator (see below).

When I change it back to es2019, no problems.

Running:  candidateBrowses.cy.ts(2 of 6)
Oops...we found an error preparing this test file:
  > cypress/support/e2e.ts
The error was:
Error: Webpack Compilation Error
./cypress/support/cyLogin.ts 17:50
Module parse failed: Unexpected token (17:50)
File was processed with these loaders:
 * ../../../../../.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/@packages/server/node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
|         cy.get('input[type="password"]').type('{enter}');
|         cy.wait(['@postLogin', '@getHomepageJson']).then(([postLoginInterception, getHomepageInterception]) => {
>             expect(postLoginInterception.response?.statusCode).to.eq(201);
|             expect(getHomepageInterception.response?.statusCode).to.eq(200);
|         });
 @ ./cypress/support/e2e.ts 1:0-19
    at handle (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/@packages/server/node_modules/@cypress/webpack-preprocessor/dist/index.js:180:23)
    at finalCallback (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/webpack/lib/Compiler.js:257:39)
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/webpack/lib/Compiler.js:306:14
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/tapable/lib/Hook.js:[154](https://github.com/upleveled/courses/runs/7152256244?check_suite_focus=true#step:18:155):20)
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/webpack/lib/Compiler.js:304:22
    at Compiler.emitRecords (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/webpack/lib/Compiler.js:499:39)
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/webpack/lib/Compiler.js:298:10
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/webpack/lib/Compiler.js:485:14
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/tapable/lib/Hook.js:154:20)
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/webpack/lib/Compiler.js:482:27
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/neo-async/async.js:2818:7
    at done (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/neo-async/async.js:3522:9)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (/home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/tapable/lib/Hook.js:154:20)
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/webpack/lib/Compiler.js:464:33
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/@packages/server/node_modules/graceful-fs/graceful-fs.js:143:16
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/@packages/server/node_modules/graceful-fs/graceful-fs.js:143:16
    at /home/runner/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/@packages/server/node_modules/graceful-fs/graceful-fs.js:61:14
    at FSReqCallback.oncomplete (node:fs:188:23)
This occurred while Cypress was compiling and bundling your test code. This is usually caused by:
- A missing file or dependency
- A syntax error in the file or one of its dependencies
Fix the error in your code and re-run your tests.

karlhorky avatar Jul 01 '22 18:07 karlhorky

Workaround

What I did for now is keep my cypress/tsconfig.json configured with compilerOptions.target of es2022 (which keeps my editor happy) and then edit this value in GitHub Actions using yq directly before running Cypress (more info about yq on GitHub Actions):

      # Set compilerOptions.target to es2019 for compatibility with Cypress TypeScript compilation
      # https://github.com/cypress-io/cypress/issues/16914#issuecomment-1015883592
      - run: yq '.compilerOptions.target = "es2019"' --output-format=json --inplace cypress/tsconfig.json
      - name: Cypress Tests
        uses: cypress-io/github-action@v3

karlhorky avatar Jul 01 '22 19:07 karlhorky

Ahh I see, I didn't have all the context around this issue and was assuming this was a problem with CT. There should be a solution by importing and modifying the options for @cypress/webpack-preprocessor, you should be able to configure ts-loader to point to a custom tsconfig file. Haven't tried it and would need to dig into it but I'll try and find time to get something running.

ZachJW34 avatar Jul 01 '22 20:07 ZachJW34

Great, thanks for taking a look!

Interesting that it may be related to the config file location πŸ€” because the webpack preprocessor seems to be already reading the cypress/tsconfig.json file (that's why the es2019 config value fixes the error when used in the file). However, using anything newer than es2019 fails (eg. es2020, es2022, esnext), which feels like a very unusual behavior.

karlhorky avatar Jul 01 '22 20:07 karlhorky

Toying around with a fresh next-app and Cypress 10 and was able to get a project with esnext working. You can check out the repo here: https://github.com/ZachJW34/next-app-webpack-preprocessor

The second commit has all of the Cypress tweaks I added. I had to add the

"resolutions": {
    "acorn": "npm:acorn-with-stage3"
  }

referenced in the original webpack issue to get around the optional access error. There is an npm equivalent but haven't tried it.

This is a pretty simple example, so depending on what your setup looks like you may need to tweak the webpack config more but I think this should work for you. It allows you to have separate tsconfig files (and share the common values via extension but override the necessary compilerOptions). You can also set up Cypress specific types inside the cypress/tsconfig.json to make your editor happy.

ZachJW34 avatar Jul 01 '22 20:07 ZachJW34

Here's some context on what's actually happening under the hood, for anyone landing here from Google etc.

Using target: esnext is generally not what you want. That means you are targeting a platform that supports all the latest ES features - like optional chaining. You'll need to run it through something else, like babel, to target all modern browsers.

Example from TS playground - left is es2017, right is esnext:

image

When you say "esnext" you are saying "my compilation target supports all the latest features" which includes optional chaining. So TS will leave it alone. When using Cypress (CT or E2E) you are likely using webpack to compile - so what's happening is the compilation target is not chrome, but either webpack-dev-server or vite-dev-server (in this case webpack, since Next.js does not support vite).

Webpack (at least, the version in this example post) does not support parsing the optional chaining syntax, so it chokes. Cypress 10 should not suffer this problem for CT, we use your version of webpack etc, so it should be πŸ‘Œ .

As for E2E, it does not use a dev-server but a pre-processor - if you are using the default pre-processor we ship, it looks like it does not support the optional chaining. Some context here. We normally grab your webpack version and use that, and default to the one we bundle if we don't find one.

I think the problem here is Next.js doesn't ship webpack in node_modules, but compile is and ship it inside of the next dependency, so we cannot grab it - so we default to an older version we ship in the Cypress binary, which doesn't support optional chaining.

Generally, this problem only happens for projects using webpack that don't have the webpack module in the node_modules directory, which is pretty much only Next.js.

lmiller1990 avatar Jul 02 '22 01:07 lmiller1990

Thanks for the background and reproduction!

However, it still doesn't really address the es2019 part of my comment above:

because the webpack preprocessor seems to be already reading the cypress/tsconfig.json file (that's why the es2019 config value fixes the optional chaining error when configured in cypress/tsconfig.json)

I'll play around with the reproduction to show you a concrete version of it failing with es2022 but succeeding with es2019 - all without any usage of @cypress/webpack-preprocessor or configuration of ts-loader.

Would still be super interested to get to the bottom of why it applies the es2019 configuration but cannot apply anything newer.


Edit: Oh, just thinking - maybe it's because the ts-loader which is built in is too old? (eg. it doesn't support the newer es2022 config)? That would seem to explain it... πŸ€” And then the solution would be to upgrade the ts-loader and webpack inside the Cypress binary. πŸ‘

So if this is all true, there would actually be a path forward without requiring users to configure @cypress/webpack-preprocessor and ts-loader themselves.

karlhorky avatar Jul 02 '22 09:07 karlhorky

Ok, I have created a new repo with a reproduction of the problem, with CI using GitHub Actions: https://github.com/karlhorky/next-app-cypress-es2019-es2022

Guide with Commits:

  1. Run Create Next App using the --typescript flag
  2. Add Cypress (tests pass, target="es5")
  3. Add GitHub Actions workflows (βœ…βœ… passing: 1. Check Types with tsc, 2. Cypress E2E tests)
  4. Upgrade target to es2022 (Cypress tests fail) (βœ… passing: 1. Check Types with tsc, ❌ failing: 2. Cypress E2E tests)
  5. Set target=es2019 in cypress/tsconfig.json, passes (βœ…βœ… passing: 1. Check Types with tsc, 2. Cypress E2E tests)
  6. Add assertion, still passing (βœ…βœ… passing: 1. Check Types with tsc, 2. Cypress E2E tests)
  7. Use default lib for target, still passing (βœ…βœ… passing: 1. Check Types with tsc, 2. Cypress E2E tests)
  8. Switch to unsupported syntax, tsc fails (βœ… passing: 2. Cypress E2E tests, ❌ failing: 1. Check Types with tsc)
  9. Set target=es2022 in cypress/tsconfig.json, Cypress fails (βœ… passing: 1. Check Types with tsc, ❌ failing: 2. Cypress E2E tests)

What we see above is a user who has removed the lib config (which contains esnext by default from Next.js) and then is happily going along using new syntax (eg. .at() on a readonly array). But in order to get the type checking working, a target of es2022 needs to be set inside cypress/tsconfig.json, which causes the Cypress tests to fail 😱

So there's actually not a nice way of doing that except for downloading the extra dependencies @cypress/webpack-preprocessor, ts-loader and webpack, along with a Yarn-only resolution on acorn, and then doing some arcane configuration in the cypress.config.ts.

I would say it's probably therefore a good idea to upgrade the webpack dependencies inside of the Cypress binary, so that they can support these new targets in a zero-config way for users without all of this extra installation and config.

karlhorky avatar Jul 02 '22 10:07 karlhorky

Workaround

Interesting, this leads to another workaround for typechecking failures related to compilerOptions.lib.

Although a maximum compilerOptions.target of es2019 is supported, higher values for compilerOptions.lib are still supported (not sure why this is).

So if you change your cypress/tsconfig.json to the following, you can avoid some problems (such as the unsupported readonly array .at() syntax here):

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "target": "es2019",
    "lib": ["dom", "dom.iterable", "es2022"]
  }
}

Proof here:

  1. Switch es2022 from target to lib config (passing: 1. Check Types with tsc, 2. Cypress E2E tests)

karlhorky avatar Jul 02 '22 15:07 karlhorky

Wow, nice work debugging this. It looks like I'll need quite a bit of time to actually digest this all, please wait a bit.

FYI, might be relevant: https://www.typescriptlang.org/tsconfig#target. Specifically:

Changing target also changes the default value of lib. You may β€œmix and match” target and lib settings as desired, but you could just set target for convenience.

Regarding your recommendation:

I would say it's probably therefore a good idea to upgrade the webpack dependencies inside of the Cypress binary

I would agree this is the path forward. I have not personally looked into this, but I think someone else did, and upgrading from webpack 4 to webpack 5 in this repo is very difficult for reasons (which I don't know).

Other than updating the webpack version, which seems like a non trivial task (for whatever reason), based on your research what's the next best work-around? Simply set es2019?

lmiller1990 avatar Jul 11 '22 02:07 lmiller1990

No worries, glad to document this for anyone running into this.

Other than updating the webpack version, which seems like a non trivial task (for whatever reason), based on your research what's the next best work-around? Simply set es2019?

For now, I think there are two main workarounds for the problem:

  1. In your cypress/tsconfig.json file, set compilerOptions.target to es2019 and then set compilerOptions.lib to an array including es2022, dom and dom.iterable (and any other lib values that your project needs) - as I mentioned in my last Workaround comment above

    Although a maximum compilerOptions.target of es2019 is supported, higher values for compilerOptions.lib are still supported

  2. Installing and configuring the extra dependencies @cypress/webpack-preprocessor, ts-loader and webpack in order to have more capabilities, as mentioned in Zach's comment above

karlhorky avatar Jul 11 '22 05:07 karlhorky

Nice, let's get some :tada: reactions on ^ so people can fix this easily until we can ship a newer version of webpack. I think configuring your app and understanding your config is pretty useful, so while not the smoothest experience, this fix does seem reasonable.

lmiller1990 avatar Jul 12 '22 00:07 lmiller1990

@lmiller1990 Can we do the same with jest + Nuxt? I've tried the workarounds above, but jest is still angry πŸ˜†

sniperadmin avatar Nov 22 '22 21:11 sniperadmin

@sniperadmin what are you asking for?

If there is a Next + Jest issue, please log the issue in vue-jest (unrelated to this project).

lmiller1990 avatar Nov 22 '22 23:11 lmiller1990

Is there anything preventing explicitly specifying ES2019 as the target in @cypress/webpack-batteries-included-preprocessor/index.js ts-loader compilerOptions?

I'm thinking if ES2019 is what the babel-loader expects as an input after TS compilation, the target from tsconfig.json can be disregarded.

In my case, I'm importing some files from my /shared folder, which also contains its own tsconfig.json with an es2020 target. Because of that those files get always compiled to es2020 no matter what i set in my /cypress/tsconfig.json. The end result is cypress throwing the same error.

I've tried and specifying the target in the preprocessor package fixed the issue.

ParallelUniv3rse avatar Dec 06 '22 22:12 ParallelUniv3rse