cypress: New Cypress 10 global TypeScript type conflicts with Jest `expect`
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:
Errors:
Property 'toBe' does not exist on type 'Assertion'.
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
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 83
- Comments: 57 (16 by maintainers)
Links to this issue
Commits related to this issue
- build(tsconfig): fix Cypress TS type conflicts with Jest expect https://github.com/cypress-io/cypress/issues/22059#issuecomment-1148921141 — committed to remarkablemark/nextjs-typescript-template by remarkablemark 2 years ago
- cypress に mount コマンドを追加すると jest の型と衝突する個別に import https://github.com/cypress-io/cypress/issues/22059 — committed to ytk6565/vue-migration-testing by ytk6565 2 years ago
- fix type conflict between Jest and Cypress see: https://github.com/cypress-io/cypress/issues/22059#issuecomment-1148921141 — committed to yuki-yamamura/udemy-NEXTJS-TESTING by yuki-yamamura a year ago
- [FIX] unit test error - ref1 : https://github.com/cypress-io/cypress/issues/22059 - ref2 : https://velog.io/@hwnim5324/%EA%B0%9C%EB%B0%9C%EC%9D%BC%EC%A7%80-%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%94%84%EB%A1... — committed to know-how-ai/know-how-FE by songforthemute 9 months ago
@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.tsto thetsconfig.excludeproperty. Since the cypress.config.ts is being included in the type checking, it is loading the cypress types which is polluting your jest tests../tsconfig.json, includetypesandexcludeproperties in config file.cypress/tsconfig.jsonThis worked for me, thanks @ZachJW34 !
Why was this issue closed?
The docs at https://docs.cypress.io/guides/component-testing/component-test-troubleshooting#Cypress-Types-Conflict-with-Jest don’t address the problem sufficiently. This is especially notable when trying to colocate test files with source files. I really don’t want my test files in other directories for component testing.
The guidance to use
/// <reference types="cypress" />won’t be good enough for setups that extend the global Cypress types (like suggested in https://docs.cypress.io/guides/component-testing/mounting-vue#Using-cy-mount-Anywhere).Using
cy.mountwill result inProperty 'mount' does not exist on type 'cy & CyEventEmitter'.. This can be avoided with a separate, top-level ambient type declaration (e.g. in asrc/shims-cypress.d.tsfile) which duplicates the type declaration that by default are incypress/support/component.ts.Additionally, this doesn’t actually seem to allow correct inference of the
describe,it, andexpectkeyword types which in my current setup are inferred as the Jest variant (see next point).There is no guidance on how to restore types for Jest’s
describe,it,expect, etc.People seem to have some success with excluding Cypress-specific files from the base tsconfig.json file via
"exclude": [ "node_modules", "cypress.config.ts", "cypress/**/*.ts" ], but that’s pretty heavy-handed. Cypress shouldn’t just assume that it can override these keywords (sure, it would be lovely if Jest and Cypress required explicitly importing them but neither library chose to do that). This also seems to prevent inference ofdescribe, etc. in a Cypress test file that’s colocated with source files.For the time being, people might need to use the
@jest/globalspackage and import global symbols from it (see https://jestjs.io/docs/api). This works reasonably well.Configuration
tsconfig.json:.eslintrc.js:src/shims-cypress.d.ts:@RafaPolit can you create another issue for what you are seeing?
tsc --noEmitwill use your tsconfig.json, so if you have it structured properly you should be able to exclude any Cypress configuration files and tests. For example, you could haveand it should work. You could add another
tsconfig.cypress.jsonand include your Cypress files if you wanted to typecheck those as well.@denieler Same advice, though it can be admittedly harder to configure with CT tests since they live alongside components but you can use globs to capture an exclude any
*.cy.tsfiles. If this doesn’t work for you, please open another issue. Types can be hard to configure, so reproductions are always helpful!For me that worked well. Jest and Cypress now have correct types.
tsconfig.json
cypress/tsconfig.json
This works for me! Thanks!
Workarounds
Workaround 1
Use
patch-packageto patchnode_modules/cypress/types/cypress-expect.d.tswith the following content (comment out the globalexpecttype):Then add back the
expectvariable at the top of all of your test files:Workaround 2
Use
local-cypressand importexpect(more info):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!
For me only this config worked. All my cypress tests are in
*.cy.jsxfiles, so I explicitly excluded them tooDid anyone find a solution to make
jestwork with Cypress Component Testing?Note: I also had to add
"files": ["../cypress.config.ts"],to thecypress/tsconfig.jsonafter adding"exclude": ["cypress.config.ts"]to thetsconfig.json.It’s still not working for nrwl/nx monorepo. If you exlucde jest tests in
tsconfig.jsonand then try to import any other lib defined in tsconfig.base.jsonpaths, it won’t work. You can see details here https://github.com/nrwl/nx/issues/19569and repo here https://github.com/tar-aldev/nrwl-nx-cypress-component-testing-issues/tree/with-suggested-cypresss-docs-fix
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
There is also something similar via
local-cypress: https://www.npmjs.com/package/local-cypressSurely this combination could let you both
Or you can use
For Cypress files. These are the workarounds suggested above, too: https://github.com/cypress-io/cypress/issues/22059#issuecomment-1145234159. 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.Here is what I did (Angular, Jasmine, Cypress). Hope it also somewhat helps with Jest
In my
tsconfig.jsonI added this:I then created a
tsconfig.jsonfile undercypress/with the following content, which I basically took from the cypress webpage:Then I restarted the TS server in VS code and tried to run both test kinds:
ng testandnpx cypress openBoth work and all IDEA errors are gone
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.jsonhas"exclude": ["../cypress.config.ts"]src - unit test using jest cypress.config.tstsconfig.jsonThis 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…
Please see our docs for recommendations on how to avoid clashing. Docs were updated in this PR: https://github.com/cypress-io/cypress-documentation/pull/5514
We investigated ways to automatically avoid this in our product, but didn’t come to a clear solution unfortunately.
Was a solution ever found for this? Going absolutely insane trying to get it to work. I have tried excluding cypress in every imaginable way, putting it in every imaginable
tsconfigwe have and it just won’t work. Trying things near enough at random now as it’s so frustrating.that worked very well for me, the “cypress” which solved the problem with me!
Thanks, this worked for me!
@ZachJW34 this would not work, no doubts, at least for IDE it’s impossible right now to apply one tsconfig file for one set of files and another tsconfig for another set of files
what about Cypress Component Tests? It doesn’t seem that it can be solved as simple as adding
cypress.config.tstotsconfig.jsonexclude🤔Other than adding
/// referenceon a file by file basis, I am unsure if there is any real fix other than test runners exporting their ownexpectas 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
as suggested above in this post: https://github.com/cypress-io/cypress/issues/22059#issuecomment-1145234159. 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).
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” }
@mjhenkes why the issue is closed? I’ve installed Cypress 12. cypress.config.ts is still installed to the root folder and tsconfig.json doesn’t have ‘exclude cypress.config.ts’ instruction. https://github.com/cypress-io/cypress/issues/22059#issuecomment-1148921141 Has too many upvotes Can this be done automatically by configuration process?
I thought I’d post an example utilizing the Solution Style tsconfig pattern. You have to set up the includes/excludes properly, but once you do the IDE should support Cypress + Jest globals in the same repo.
This is an example utilizing React + Vitest + Cypress: https://github.com/ZachJW34/cypress-react-vitest
This won’t work for all projects such as create-react-app as they don’t support this format
I’ve created https://github.com/cypress-io/cypress-documentation/issues/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
excludeis not working yet. @kuantayevs am I reading your structure correctly, in that yourtsconfig.jsonis nested inside your cypress folder?adding ./cypress.config.ts to the tsconfig.exclude propertyThank you @ZachJW34 it helps for me too@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.
If you are using
eslintas well, don’t forget to add an override to redefine theparserOptions.project, otherwise eslint will complain that no project file is associated with the cypress specs:Hello!
Like other people, I have component tests (Cypress) and unit tests (Jest) in the same folder, along with the original code.
I read all the previous comments, and maybe I missed this, but I managed to solve the problem in a very simple way, in my opinion.
It’s not the best thing in the world, but honestly, it’s pretty simple.
You just need to add
/// <reference types="jest" />at the top of your Jest unit test.My
tsconfig.jsonis configured 100% for Cypress.Downside
For some reason unknown to me, due to my lack of experience with TypeScript, component tests with Cypress are now com two types, the main being Jest and the secondary being Cypress.
So far this hasn’t caused any problems, but it looks like the cause is indeed
/// <reference types="jest">in the*.test.tsfiles.Since I added
"./cypress.config.ts"to the"exclude"list intsconfig.json, the following error started showing up only on CI (Github Actions), although it doesn’t happen locally (MacBook Pro w/ M1) 🤔Type error: Cannot find name ‘cy’.
Which version are you on? Try upgrading to v4 - this made this problem disappear for us
Yes, sorry for not clarifying! 🤦♂️ It was needed, because otherwise the typescript-eslint plugin would raise the following error:
Note: Our ESLint config selects files as follows:
@karlhorky @ZachJW34 Thanks for all your input here
We had the same issue blocking our upgrade to v10.
Adding
cypress.config.[js|ts]totsconfig.json’sexcludeproperty 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