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

feat(testing): Cypress 10 and component testing support #9201

Merged
merged 30 commits into from
Jul 8, 2022

Conversation

barbados-clemens
Copy link
Contributor

@barbados-clemens barbados-clemens commented Mar 4, 2022

Current Behavior

cypress component testing support is lacking

Expected Behavior

quality cypress component testing support within nx

Overview of behavior

# add component testing to a project
nx g @nrwl/<react|next>:cypress-component-configuration --project=my-react-project

# add component testing to a project and generate component tests
nx g @nrwl/<react|next>:cypress-component-configuration --project=my-react-project --generate-tests

# generate component test for a component
nx g @nrwl/react:component-test --project=my-react-project --component-path=src/lib/my-fancy-component

After adding component testing to a project, a new component-test target is available to run the tests. nx component-test my-react-lib

Cypress component tests and Jest unit tests can live side by side.

It's not recommended to use cypress component tests for apps, as it's expected apps will not contain any component worth testing. They will primarily be used within libraries.

Buildable and publishable library support is expected.

Next is not explicitly supported as it's still alpha by Cypress,

Migrating to v10

We will not migrate to v10 automatically to prevent breaking e2e tests. but a generator to run manually is provided to aid in the migration when ready. Min cypress supported version is v8

# convert cypress to v10
nx g @nrwl/cypress:migrate-to-cypress-10

This will

  1. update cypress.json => cypress.config.ts (will handle custom config names as well)
  2. update project structure
    • update support/index.ts => support/e2e.ts
      • and associated imports
    • update integration/ folder => e2e/ folder
    • update .spec. files to .cy. files
  3. if plugins are used, import it into the new config file
  4. update project configuration
  5. install cypress v10

Progress

Framework Project Type Compiler Status
React library babel
React library swc
React app babel
React app swc

@vercel
Copy link

vercel bot commented Mar 4, 2022

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/nrwl/nx-dev/E66fttsnNBPehdhxnvem1cN1t4E4
✅ Preview: https://nx-dev-git-feat-cypress-10-nrwl.vercel.app

[Deployment for d6d5dbe canceled]

@barbados-clemens barbados-clemens self-assigned this Mar 4, 2022
@barbados-clemens barbados-clemens added the scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx label Mar 4, 2022
@barbados-clemens barbados-clemens merged commit 8154191 into master Jul 8, 2022
@barbados-clemens barbados-clemens deleted the feat/cypress-10 branch July 8, 2022 19:34
@rathpc
Copy link
Contributor

rathpc commented Jul 12, 2022

thank you for this! Do you know when this will be in a release?

@estrudels
Copy link

estrudels commented Jul 13, 2022

This is great news that this has been Merged which version do we expect this to be released too?

Is it safe to conclude it would be going into version 14.5.0?

Thanks for the effort, we appreciate it! 🙂

@barbados-clemens
Copy link
Contributor Author

@rathpc @estrudels it should be apart of the 14.5.0 release

@e-oz
Copy link

e-oz commented Jul 19, 2022

Works like a charm! Thank you so much ❤️

@rathpc
Copy link
Contributor

rathpc commented Jul 21, 2022

@rathpc @estrudels it should be apart of the 14.5.0 release

Great news @barbados-clemens! I will try testing out the beta release in the meantime. Do you have a date in mind when the official 14.5.0 will be released?

@DanielSchiavini
Copy link

I had to rename the files manually, but it worked fine otherwise:

  • update integration/ folder => e2e/ folder
  • update .spec. files to .cy. files

@rathpc
Copy link
Contributor

rathpc commented Aug 15, 2022

So I had to end up going with a somewhat custom setup because the default configuration per library which was what I assumed to be the intended setup per several generators did not really work as expected.

For some context, I originally tried having the component test setup love adjacent to the default e2e setup in the automatically created app-e2e folder alongside an app. However if you have any intention of component tests living alongside your components which feels more natural and a practical shift from jest component tests, this setup is not ideal whatsoever and leads to numerous typing issues. The second setup I tried was using a generator to create the config in each library so I could get typing working better and have my component tests adjacent to my components although this added so much config to each and every library it didn't feel worth it. Especially not being able to centralize things like the commands file or types or the component config etc. Additionally if you had any plans of trying to make a target for running these, it would fail if no tests exist in a library as there is no config setting like jest has to pass if no tests are present. Also it wasn't clear how to aggregate those component test results together.

So with all of that said I ended up with the following: cypress folder at the root alongside apps and libs folders with the support folder, fixtures etc in that folder. There is also a tsconfig.json and eslint.config.js to keep things playing nicely. Then at the root are the following files cypress.config.ts, custom tsconfig.cypress.json, vite.config.json, percy.yml, nyc.config.js, nyc.preset.json. My e2e cypress config in apps/app-e2e extends some excluded files from the nyc preset file which I use for coverage, also the vite config uses the same along with the actual nyc config. I have the Percy file because I am also integrating with that plugin for snapshot regression testing. Finally, even though my e2e tests are using webpack as the dev server, a similar setup would just NOT work for component tests and I was forced to go with vite instead. Ironically I think this works way better and I am interested to try to set it up for the e2e tests as well.

Lastly, since this is done at the root I can target a glob to get all component tests from all libs and rely on cypress to parallelize them in ci environments. At least that is what I am hoping for. I haven't gotten far enough to test that yet.

I think it's great we have Cypress 10 support but I am hoping nrwl does a bit more around better config, options and guidelines around how to best set up component tests along with everything else.

Also if anyone from nrwl wants more information on my setup if this sounds like a worthwhile direction feel free to contact me 👍

@barbados-clemens
Copy link
Contributor Author

@rathpc can you explain more on

So I had to end up going with a somewhat custom setup because the default configuration per library which was what I assumed to be the intended setup per several generators did not really work as expected.

as cypress component testing generators are built with the idea of adding to an existing project, so any issues you have with the generators not setting that up would be good to know so they can be fixed.

@rathpc
Copy link
Contributor

rathpc commented Aug 19, 2022

Absolutely (and sorry for the delay!)

So firstly, there are two different generators that almost do the same thing. @nrwl/cypress:cypress-component-project and @nrwl/react:cypress-component-configuration. This is a bit confusing because they do not result in the same set up configuration. One creates a cypress config with nothing in the defineConfig function, and the other somewhat prepares it.

Secondly, when adding this configuration per-project you must ensure that at least one spec file exists with a test before running it because it does not fail gracefully or offer a way to fail gracefully if tests are empty like you can with the Jest executor. If you have a large monorepo with many libraries - odds are you are planning to set up the tooling for them all the same way and be able to leverage nx run or run-many commands. If you did that and any library you set up didn't have any tests yet, the whole command is borked. This was our initial plan because we are hoping to replace all Jest component tests with Cypress component tests and be able to run projects in isolation and collect coverage etc.

So this leads to what I ended up having to do which was initialize a fresh Cypress install at the root of my repo, alongside the apps and libs folder so that I could be able to scope through all libs, but have the config globally available to initiate the cypress runs. Within each library I had to add a reference to a new tsconfig that I put at the root which was specific for cypress files living in libs so that types would work correctly. The other advantage of keeping cypress at the root is if you intend on having any fixtures, helpers or custom commands that would be shared amongst multiple libs it eliminates the need to duplicate all of that effort in each and every lib you are creating those tests in. For example I created a custom mount command which contains all of our main providers as a wrapper so we can simplify the individual component test mount calls to a single source of truth.

Hopefully this helps explain a bit more 😄

@barbados-clemens
Copy link
Contributor Author

@nrwl/cypress:cypress-component-project is the "base" generator that is there to extend for others as desired since it's framework agnostic. i.e. vue plugin wanting to add their own support, they just have to create their own config.

@nrwl/react:cypress-component-configuration adds any react specific needs, such as using the react preset from nx.

the failing on no tests is a cypress related feature that would have to be added to work the same as jest. I'd recommend not setting up the component testing until you're ready to add tests. or "deactivate" the component tests by renaming the target in the project.json to something like xcomponent-test so it won't be picked up via the run-many command.

as for defining once, and using in multiple places, the cypress and nx teams agree the best way to share a global config would be to define a shared config at the root and then spreading that into each projects config.
i.e.

// @ root of repo cypress.shared-config.ts

export default defineConfig({
  // options to globally share across projects
})
// libs/my-fancy-lib/cypress.config.ts

import defaultConfig from '../../cypress.shared-config';

export default defineConfig({
 ...defaultConfig,
 /// project specific options like paths to screenshots/videos
})

if you use a single global cypress component testing project for all your components, then you'll missout on any caching of nx and will end up always having to rerun cypress component tests.

if you use a single config but multiple projects, then you'll run into issues that are path reliant such as screenshots/videos/glob patterns that will be per project.

You can optionally make a nx library and create your own cypress commands (and export a config) that can be imported into each project you wish to use it in.

Here is a showing how to make a command to share, but the same idea would apply to cypress component testing.

https://www.youtube.com/watch?v=YNH4wBUZvkA

if none of those options can work for you, and you must have a single global project for all your cypress component testing, odds are migrations aren't going to work for you without some extra effort as supporting all permutations of using cypress across a project is quite a task. I can only really support most common setups that I described above.

@rathpc
Copy link
Contributor

rathpc commented Aug 19, 2022

@barbados-clemens hmm interesting ok well it could be worth trying some more variations when I have time. Ideally I would love to take advantage of the caching but just kept hitting roadblocks so I had to settle to get other work unblocked. Thank you for your response and help!

@barbados-clemens
Copy link
Contributor Author

@rathpc that's totally fair. component testing is very new and our initial vision was using it similar to jest as it's added to a project and run/cacheable like normal unit testing that people were familiar with.

there are a couple issues with it right now that have been reported around errors getting thrown with different library combinations that I didn't account for. so I understand needed to get it to work today, once I get things more stable for the component testing I can take a look at other ways people have used component testing and see what there might be able to do in regards to smoothing out the transition between different usage patterns.

@rathpc
Copy link
Contributor

rathpc commented Aug 20, 2022

@barbados-clemens one other thing that is worth mentioning is that I wasn't exactly sure how the following would work (although I didn't attempt it yet):

Assuming I add the component test tooling to each lib and am able to leverage nx run or run-many commands and I can manually aggregate coverage reports from each library into a full coverage report across all libs, is there any way to enable and allow for parallelism with cypress dashboard as well? Keeping everything global seems like it would be the easiest path to allow for this.

I guess the same would apply as a question for jest to be able to run across a matrix of machines in a GitHub workflow, how would the logic work there to be able to determine what runs where if nx is attempting to handle dependency task management?

Even if you choose to just always use run-many and enable parallel runs that way, can you further optimize by running say 3 machines in parallel all running parallel task runs? I am assuming all of these scenarios would require a lot of hand crafted logic to manage and there is nothing out of the box that handles this?

@wrslatz
Copy link
Contributor

wrslatz commented Aug 20, 2022

I've used this 10x Faster CI with Nx and GitHub Actions article as a reference in the past, which walks through a custom setup for splitting affected tasks across CI workers.

If Nx commands supported a shard option to automatically split up tasks into groups to spread across CI workers, it would make this a lot easier to manage.

Edit: looks like that's what #3238 requested specifically for Cypress testing. Might be better as a generic feature request?

@rathpc
Copy link
Contributor

rathpc commented Aug 20, 2022

@wrslatz that is an awesome article I will certainly see if I can make use of that! Thank you!

@barbados-clemens
Copy link
Contributor Author

@wrslatz @rathpc I would look into DTE from Nx Cloud, which does this intelligently vs you attempting to load balance all your projects tasks in CI.

@github-actions
Copy link

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for cypress 10.x Deprecate Storybook Component Testing