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

New Cypress 10 global TypeScript type conflicts with Jest expect #22059

Closed
karlhorky opened this issue Jun 2, 2022 · 57 comments
Closed

New Cypress 10 global TypeScript type conflicts with Jest expect #22059

karlhorky opened this issue Jun 2, 2022 · 57 comments
Assignees
Labels
type: typings Issue related to Cypress types (for TypeScript) v10.0.0 🐛 Issue present since 10.0.0

Comments

@karlhorky
Copy link
Contributor

karlhorky commented Jun 2, 2022

Current behavior

The following new global TypeScript type for expect in node_modules/cypress/types/cypress-expect.d.ts causes conflicts with Jest expect types, if a project has both Jest and Cypress:

declare const expect: Chai.ExpectStatic

Errors:

Property 'toBe' does not exist on type 'Assertion'.

Screen Shot 2022-06-02 at 21 19 56

When looking through the docs, there is a guide here:

Cypress Types Conflict with Jest

However, this guide is based on the fact that Cypress types were not global before (but they are now).

Desired behavior

No response

Test code to reproduce

Jest test code (filename __tests__/colors.test.ts):

import { findWhiteContrastingColor } from '../colors';

test('findWhiteContrastingColor finds colors contrasting with white', () => {
  expect(findWhiteContrastingColor(['#ffffff', '#000000', '#e1e1e1'])).toBe(
    '#000000',
  );
});

Cypress Version

10.0.1

Other

No response

@karlhorky
Copy link
Contributor Author

karlhorky commented Jun 2, 2022

Workarounds

Workaround 1

Use patch-package to patch node_modules/cypress/types/cypress-expect.d.ts with the following content (comment out the global expect type):

// Cypress adds chai expect and assert to global
// declare const expect: Chai.ExpectStatic
declare const assert: Chai.AssertStatic

Then add back the expect variable at the top of all of your test files:

declare const expect: Chai.ExpectStatic;

Workaround 2

Use local-cypress and import expect (more info):

import { expect } from 'local-cypress';

@karlhorky karlhorky changed the title New Cypress 10 global TypeScript types Conflict with Jest expect New Cypress 10 global TypeScript type Conflict with Jest expect Jun 2, 2022
@jennifer-shehane jennifer-shehane added the v10.0.0 🐛 Issue present since 10.0.0 label Jun 2, 2022
@cypress-bot cypress-bot bot added the stage: investigating Someone from Cypress is looking into this label Jun 3, 2022
@Yberion
Copy link

Yberion commented Jun 7, 2022

Hello,

We also have this problem with Karma/Jasmine on Angular.

Do you have any informations on if and when you will fix that issue ?

The workarounds aren't clear enough to be honest, and they are "workaround" anyway which isn't really good.
All Angular projects updating to Cypress 10 will have a clashing problem with describe, it, expect, ...

It's kinda "critical" I think 😄

Have a good day!

@ZachJW34
Copy link
Contributor

ZachJW34 commented Jun 7, 2022

@karlhorky thanks for posting, looks like you're not the only one having issues with Cypress + Jest type collisions.

I was able to reproduce this with the repos linked @karlhorky @mrdrogdrog @wKovacs64. When I checked out the dep update to v10, all of the Jest tests started complaining.

We didn't change our globals very much for v10. For all the cases I reproduced, it was fixed by adding ./cypress.config.ts to the tsconfig.exclude property. Since the cypress.config.ts is being included in the type checking, it is loading the cypress types which is polluting your jest tests.

@ZachJW34 ZachJW34 added stage: awaiting response Potential fix was proposed; awaiting response and removed stage: investigating Someone from Cypress is looking into this labels Jun 7, 2022
@Yberion
Copy link

Yberion commented Jun 7, 2022

Hello @ZachJW34,

Edit: removed the old message, I misread your answer, it indeed work, thank you!

@mjhenkes mjhenkes assigned marktnoonan and unassigned ZachJW34 Jun 7, 2022
@cypress-bot cypress-bot bot added stage: investigating Someone from Cypress is looking into this and removed stage: awaiting response Potential fix was proposed; awaiting response labels Jun 7, 2022
@karlhorky
Copy link
Contributor Author

adding ./cypress.config.ts to the tsconfig.exclude property

This worked for me, thanks @ZachJW34 !

@yuriy1715
Copy link

adding ./cypress.config.ts to the tsconfig.exclude property
Thank you @ZachJW34 it helps for me too

@karlhorky
Copy link
Contributor Author

@marktnoonan @ZachJW34 @mjhenkes should we leave this one open so that the documentation page mentioned in the issue description is updated?

@kuantayevs
Copy link

kuantayevs commented Jun 7, 2022

@karlhorky thanks for posting, looks like you're not the only one having issues with Cypress + Jest type collisions.

I was able to reproduce this with the repos linked @karlhorky @mrdrogdrog @wKovacs64. When I checked out the dep update to v10, all of the Jest tests started complaining.

We didn't change our globals very much for v10. For all the cases I reproduced, it was fixed by adding ./cypress.config.ts to the tsconfig.exclude property. Since the cypress.config.ts is being included in the type checking, it is loading the cypress types which is polluting your jest tests.

Thank you for sharing this @ZachJW34 , but this seems does not work for me, maybe you could help me. I still see errors which is listed at very first messge

structure:
cypress - cypress tests
- tsconfig.json has "exclude": ["../cypress.config.ts"]
src - unit test using jest
cypress.config.ts

tsconfig.json

    "compilerOptions": {
        "baseUrl": ".",
        "esModuleInterop": true,
        "lib": ["dom", "esnext"],
        "noEmit": true,
        "skipLibCheck": true,
        "strict": true
    },
    "include": ["../../node_modules/cypress", "**/*"],
    "exclude": ["../cypress.config.ts"]
}```

@arelra
Copy link

arelra commented Jun 7, 2022

@karlhorky @ZachJW34 Thanks for all your input here

We had the same issue blocking our upgrade to v10.

Adding cypress.config.[js|ts] to tsconfig.json's exclude property worked for us too.

I would also like to echo that this issue be elevated to the v10 migration guide or made much clearer in the documentation please. It is very difficult to diagnose and remedy without any pointers.

Thanks

@marktnoonan
Copy link
Contributor

I've created cypress-io/cypress-documentation#4559 against the docs repo so that we can document the solution there. Thanks everybody for reporting and providing examples, and @ZachJW34 for pointing out the right step to take.

Good point @arelra about maybe mentioning this in the Migration Guide and as part of migration itself, we will consider both.

Going to keep this issue open a little longer since it does seem like we somebody for whom exclude is not working yet. @kuantayevs am I reading your structure correctly, in that your tsconfig.json is nested inside your cypress folder?

@SchroederSteffen
Copy link

Note: I also had to add "files": ["../cypress.config.ts"], to the cypress/tsconfig.json after adding "exclude": ["cypress.config.ts"] to the tsconfig.json.

@karlhorky
Copy link
Contributor Author

karlhorky commented Jun 8, 2022

tsconfig.json has "exclude": ["../cypress.config.ts"]

@kuantayevs what worked for me in my monorepo structure was to add the exclude to the base tsconfig.json in the root of the project:

{
  "exclude": [
    "packages/fusion.upleveled.io/cypress.config.ts",
  ]
}

Adding to the "exclude" array in a tsconfig.json deeper in one of the folders did NOT work.

@karlhorky
Copy link
Contributor Author

Note: I also had to add "files": ["../cypress.config.ts"], to the cypress/tsconfig.json after adding "exclude": ["cypress.config.ts"] to the tsconfig.json.

@SchroederSteffen why did you need to do this? (eg. what were the details of what was happening without this change?)

I didn't need to do this, but maybe I and others would want to for some reason...

@karlhorky karlhorky changed the title New Cypress 10 global TypeScript type Conflict with Jest expect New Cypress 10 global TypeScript type conflicts with Jest expect Jun 8, 2022
@SchroederSteffen
Copy link

SchroederSteffen commented Jun 8, 2022

Note: I also had to add "files": ["../cypress.config.ts"], to the cypress/tsconfig.json after adding "exclude": ["cypress.config.ts"] to the tsconfig.json.

@SchroederSteffen why did you need to do this? (eg. what were the details of what was happening without this change?)

I didn't need to do this, but maybe I and others would want to for some reason...

Yes, sorry for not clarifying! 🤦‍♂️
It was needed, because otherwise the typescript-eslint plugin would raise the following error:

C:\<project-directory>\cypress.config.ts
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: cypress.config.ts.
The file must be included in at least one of the projects provided

Note: Our ESLint config selects files as follows:

  overrides: [
    {
      files: ['*.ts'],
      parserOptions: {
        project: ['tsconfig.json'],
      },
      extends: [
        'plugin:@typescript-eslint/recommended',
        'plugin:@typescript-eslint/recommended-requiring-type-checking',
        [...],
      ],
      [...],
      overrides: [
        {
          files: ['cypress/**/*.ts'],
          parserOptions: {
            project: ['cypress/tsconfig.json'],
          },
          extends: ['plugin:cypress/recommended'],
        },
      ]
    }
  ]

@karlhorky
Copy link
Contributor Author

karlhorky commented Jun 8, 2022

Oh fancy, didn't know that about the overrides config! 😯 I have been creating .eslintrc.js files in all of the sub-directories that I need to configure differently and then adding lines to .eslintignore for those which don't match the include and exclude in my tsconfig.json. But this is a downside because it ignores any lint errors in cypress.config.ts ...

@uKiJo
Copy link

uKiJo commented Apr 17, 2023

For me only this config worked. All my cypress tests are in *.cy.jsx files, so I explicitly excluded them too

  "exclude": [
    "node_modules",
    "cypress",
    "cypress.config.ts",
    "**/*.cy.jsx"
  ],

that worked very well for me, the "cypress" which solved the problem with me!

@felixcatto
Copy link

felixcatto commented Apr 25, 2023

For me that worked well. Jest and Cypress now have correct types.

tsconfig.json

  "include": ["**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules", "cypress.config.ts", "cypress"]

cypress/tsconfig.json

  "compilerOptions": {
    ...
    "types": ["cypress"]
  },
  "include": ["../node_modules/cypress", "./**/*.ts"]

@mnogueron
Copy link

If you are using eslint as well, don't forget to add an override to redefine the parserOptions.project, otherwise eslint will complain that no project file is associated with the cypress specs:

{
	...
	"overrides": [
		{
			"files": ["cypress/**/*.ts", "cypress.config.ts"],
			"parserOptions": {
				"project": "./cypress/tsconfig.json"
			},
			...
		},
		...
	],
	"parser": "@typescript-eslint/parser",
	"parserOptions": {
		"project": "./tsconfig.json",
		...
	},
}

@mmcgee-aya
Copy link

This is still an issue with a brand new install of Angular and cypress as of 7/12/2023.. Is there an official fix/documentation

"dependencies": {
"@angular/animations": "^16.1.0",
"@angular/common": "^16.1.0",
"@angular/compiler": "^16.1.0",
"@angular/core": "^16.1.0",
"@angular/forms": "^16.1.0",
"@angular/platform-browser": "^16.1.0",
"@angular/platform-browser-dynamic": "^16.1.0",
"@angular/router": "^16.1.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.13.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^16.1.1",
"@angular/cli": "~16.1.1",
"@angular/compiler-cli": "^16.1.0",
"@types/jasmine": "~4.3.0",
"cypress": "^12.17.1",
"jasmine-core": "~4.6.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.1.3"
}

@cniemann88
Copy link

Also still an issue for me...Angular with jest tests

Adding these lines to the tsconfig.json file
"exclude": [ "./cypress.config.ts", "node_modules", "**/*.cy.ts" ], "include": ["src/**/*.ts"]
works only for the cypress tests inside the cypress folder...component tests that are co-located with jest tests are throwing errors like below:
image

adding
///<reference types="cypress/jest"/>

only partially works, and is not a sustainable solution for an existing system with hundreds of jest spec files.

@nagash77 nagash77 reopened this Jul 12, 2023
@nagash77 nagash77 removed the stage: awaiting response Potential fix was proposed; awaiting response label Jul 12, 2023
@lmiller1990
Copy link
Contributor

lmiller1990 commented Jul 12, 2023

Other than adding /// reference on a file by file basis, I am unsure if there is any real fix other than test runners exporting their own expect as module. This is one of the many reasons global variables are not good, it's hard to know who defines them and how to type them.

I think Cypress should have a frontend module bundle that does

import { expect, cy, Cypress, describe, it } from 'cypress'

as suggested above in this post: #22059 (comment). It looks like there is already a package that partially implements this: https://github.com/bahmutov/local-cypress#readme

Even if these are dynamically injected at runtime, the exports should just be type safety wrappers and no-ops, in the same way `import { defineConfig } from 'cypress' is a no-op at runtime - it just adds type safety.

I am unsure on the complexity of this or if we are looking to implement this soon. Is someone interested on working on this? If so, I can propose this internally to our product team to get requirements (if we decide to prioritize it).

@kleinfreund
Copy link

@lmiller1990 Regarding your last comment, maybe https://www.npmjs.com/package/@jest/globals can be a point for inspiration. I’m using this package to avoid globally typing "Jest globals" and it works very well.

@maccurt
Copy link

maccurt commented Jul 21, 2023

This is very frustrating. I think I don't want to install cypress into my Angular project, but I want to do Component testing. Very hard to bring this to my team, when it break all the asserts for our unit test. Let us make sure also our custom commands still work with this implementation, etc. I notice I get one thing working, then it breaks something else. WE CAN NOT ACCEPT INSTALLING THIS package if it breaks our unit test asserts. I AM VERY SUPRISED this was allowed to get past QA at cypress. I give a lot of grace, but this is breaking a brand new angular project with YOUR INSTRUCTIONS. I guess I am frustrated because I really want to use component testing, but I think I will separate my MY CYPRESS project from my Angular project so they do not collide AND NOT DO COMPONENT TESTING. All I ask is you follow your own instructions and see it breaks. Just do a simple NG new my-project and then install cypress, RIGHT OUT THE BOX IT IS BROKE..

@etsraphael
Copy link

Please does somebody have a fix about this one? The latest version brought back this issue.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Aug 2, 2023

The problem is multiple tools declaring matching globals. This issue could be opened in Jest and be just as relevant.

It looks like Jest has a module API that exposes these: https://jestjs.io/docs/api

import { expect } from '@globals/jest'

There is also something similar via local-cypress: https://www.npmjs.com/package/local-cypress

Surely this combination could let you both

import { expect } from '@jest/globals'
import { expect } from 'local-cypress'

Or you can use

/// <reference types= "cypress" />

For Cypress files. These are the workarounds suggested above, too: #22059 (comment). Have you tried these, @etsraphael?

@maccurt can you try these? There is no magic way to make it work, you'll need to make sure each spec file knows which test runner / tool it's associated with. It doesn't look like you've tried that yet. Give one of these a try, it should fix your issue.

As an aside, I don't know why any framework still uses global variables. I have run into this too, but the reality is if there are multiple types assigned to the same variable (eg expect) there isn't a good way for the IDE to "know" which one to use reliability without imports or references.

I'm not sure if there's any edge cases with local-cypress - if not, I'd love to see this in core, but I suspect there are some issues that would need to be ironed out.

@maccurt
Copy link

maccurt commented Aug 2, 2023

@lmiller1990 I will give that a try

@jennifer-shehane
Copy link
Member

Please see our docs for recommendations on how to avoid clashing. Docs were updated in this PR: cypress-io/cypress-documentation#5514

We investigated ways to automatically avoid this in our product, but didn't come to a clear solution unfortunately.

@tar-aldev
Copy link

tar-aldev commented Oct 13, 2023

It's still not working for nrwl/nx monorepo.
If you exlucde jest tests in tsconfig.json and then try to import any other lib defined in tsconfig.base.json paths, it won't work.
You can see details here
nrwl/nx#19569

and repo here
https://github.com/tar-aldev/nrwl-nx-cypress-component-testing-issues/tree/with-suggested-cypresss-docs-fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: typings Issue related to Cypress types (for TypeScript) v10.0.0 🐛 Issue present since 10.0.0
Projects
None yet
Development

No branches or pull requests