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

Support vite v5 for component testing #28347

Closed
MikeMcC399 opened this issue Nov 16, 2023 · 40 comments · Fixed by #29518
Closed

Support vite v5 for component testing #28347

MikeMcC399 opened this issue Nov 16, 2023 · 40 comments · Fixed by #29518
Assignees
Labels
CT Issue related to component testing type: enhancement Requested enhancement of existing feature

Comments

@MikeMcC399
Copy link
Contributor

What would you like?

Cypress component testing should support vite v5 (React, Vue and Svelte) - see announcement Vite 5.0 is out! Nov 16, 2023.

Why is this needed?

According to https://docs.cypress.io/guides/component-testing/overview "Vite 2+" is supported, however in practice only up to Vite v4 is supported by Cypress 13.x at this time.

export const WIZARD_DEPENDENCY_VITE = {
type: 'vite',
name: 'Vite',
package: 'vite',
installer: 'vite',
description: 'Vite is dev server that serves your source files over native ES modules',
minVersion: '^2.0.0 || ^3.0.0 || ^4.0.0',
} as const

Other

See Migration from (vite) v4 and note that the CJS Node API has been deprecated.

@MikeMcC399
Copy link
Contributor Author

The CJS build of Vite's Node API is deprecated. See https://vitejs.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.

@MikeMcC399
Copy link
Contributor Author

@jordanpowell88

The examples in cypress-io/component-testing-quickstart-apps are left using [email protected] until this enhancement request is addressed.

@rstoneIDBS
Copy link

I'm currently experiencing issues with component testing when trying Vite 5.0.7 with Cypress 13.6.1. It looks like 'public' folder mapping is broken which (for me anyway) breaks the use of mock service worker amongst other things. Is this likely to be fixed by the work mentioned in this ticket or would you like a new issue raised?

@jennifer-shehane jennifer-shehane added type: enhancement Requested enhancement of existing feature CT Issue related to component testing labels Dec 17, 2023
@juliandreas
Copy link

I'm currently experiencing issues with component testing when trying Vite 5.0.7 with Cypress 13.6.1. It looks like 'public' folder mapping is broken which (for me anyway) breaks the use of mock service worker amongst other things. Is this likely to be fixed by the work mentioned in this ticket or would you like a new issue raised?

Same.

@MikeMcC399
Copy link
Contributor Author

@rstoneIDBS / @juliandreas

Did you try using the latest Vite version v5.0.10?

@juliandreas
Copy link

juliandreas commented Dec 19, 2023

Did you try using the latest Vite version v5.0.10?

Yep.

@MikeMcC399
Copy link
Contributor Author

@rstoneIDBS
Copy link

Just tried again with the latest versions of Cypress (13.6.2) and Vite (5.0.10) and I'm still seeing the same issue.

@steveworkman
Copy link

I'm currently experiencing issues with component testing when trying Vite 5.0.7 with Cypress 13.6.1. It looks like 'public' folder mapping is broken which (for me anyway) breaks the use of mock service worker amongst other things. Is this likely to be fixed by the work mentioned in this ticket or would you like a new issue raised?

Same.

public folder mapping has had a small change in vite 5. In aligning dev and preview behaviour vite 5 now returns the index.html file in more cases, so if you're trying to access /locales/en.json which is inside public then you need to get ./locales/en.json instead

@rstoneIDBS
Copy link

I'm currently experiencing issues with component testing when trying Vite 5.0.7 with Cypress 13.6.1. It looks like 'public' folder mapping is broken which (for me anyway) breaks the use of mock service worker amongst other things. Is this likely to be fixed by the work mentioned in this ticket or would you like a new issue raised?

Same.

public folder mapping has had a small change in vite 5. In aligning dev and preview behaviour vite 5 now returns the index.html file in more cases, so if you're trying to access /locales/en.json which is inside public then you need to get ./locales/en.json instead

Yes, I noticed that in the release notes. I think the code that needs to change is part of the Cypress Vite dev server integration - I couldn't see any way of doing this from the consumer side. My app works fine in Vite dev mode (with Vite 5), it only fails when running Cypress component tests.

@SamGeodynamics
Copy link

SamGeodynamics commented Jan 3, 2024

Just tried again with the latest versions of Cypress (13.6.2) and Vite (5.0.10) and I'm still seeing the same issue.

as said; it's not working. (cypress v13.6.2 & vite 5.0.10), you can press skip, then you are greeted with a huge version mismatch notification.

image

@juliandreas
Copy link

I think the code that needs to change is part of the Cypress Vite dev server integration - I couldn't see any way of doing this from the consumer side. My app works fine in Vite dev mode (with Vite 5), it only fails when running Cypress component tests.

Same. Imports works fine in the app with Vite 5, but it fails when running Cypress. Changing a path from /locales/en.json to ./locales/en.json, for example, is not helping in that scenario. The Cypress team needs to update their package to support Vite 5.

@jennifer-shehane
Copy link
Member

We'd be open to a PR to help support Vite 5.

@MikeMcC399
Copy link
Contributor Author

@jennifer-shehane

We'd be open to a PR to help support Vite 5.

Just for the sake of clarity, since I'm the author of this issue, I'm not able to provide a PR to update Cypress for Vite 5 compatibility. I don't have the skills to do this.

@essenmitsosse
Copy link

Giving the hefty sums Cypress charges for their service, asking the community to implement support for the latest version of industry-standard tooling, while ignoring the issue for over four month, seems like pretty bad optics. I understand Cypress itself is free and open source, but the lack of Vite 5 support is a road block for Cypress-only users as well as Cypress cloud customers.

@waldemarennsaed
Copy link

Giving the hefty sums Cypress charges for their service, asking the community to implement support for the latest version of industry-standard tooling, while ignoring the issue for over four month, seems like pretty bad optics. I understand Cypress itself is free and open source, but the lack of Vite 5 support is a road block for Cypress-only users as well as Cypress cloud customers.

I agree on what @essenmitsosse says. Vite 5 is released for a while now. We are currently migrating our whole stack to Vue 3, including Vuetify 3 and the latest Vite version. I do not understand why the Cypress org does not see their responsibility in keeping their tooling up-to-date.

@MikeMcC399
Copy link
Contributor Author

MikeMcC399 commented Apr 5, 2024

Vite's blog announced release of 5.1 in February 2024.

Vite's GitHub releases currently show 5.2.8 as latest and there is a first appearance of a 6.0.0 alpha version.

@waldemarennsaed
Copy link

Vite's blog announced release of 5.1 in February 2024.

Vite's GitHub releases currently show 5.2.8 as latest and there is a first appearance of a 6.0.0 alpha version.

Well, a new major release within two months is really quick. However, Vite 5 is out a while now. IMHO cypress should have supported it already.

@jennifer-shehane
Copy link
Member

We do plan to evaluate the effort to support Vite 5.

@AtofStryker
Copy link
Contributor

I had some time to build binaries for vite@5 support if anyone wants to give it a try d129a64. This is still a work in progress so hoping for feedback to see if there is anything we missed here!

@rstoneIDBS
Copy link

I've just tried this and I still see exactly the same problem. Looking at the code in this fix I can't see anything that addresses how Vite 5 changed how 'public' folders are handled - see comment here #28347 (comment).
This appears to be what is causing the issue for me as Cypress no longer loads Mock Service Worker correctly which causes my tests to fail.

@rstoneIDBS
Copy link

I've found a fix for the MSW issue :)

I already had a section in my component.js that was configuring the MSW service worker, this also allows you to specify the URL of the worker so I changed it to this:

const { worker, graphql } = await import('../../src/mocks/browser');

Cypress.on('test:before:run:async', () => {
  if (worker.context.isMockingEnabled) {
    return;
  }
  return worker.start({
    serviceWorker: {
      url: '../src/public/mockServiceWorker.js',
    },
    // Disable logging of matched requests as this can occasionally result in test failures
    quiet: true,
  });
});

window.msw = {
  worker,
  graphql,
};

The key bit is the url setting as this ensures that MSW loads its code from the correct location.

This fixes MSW, but it won't fix anything else being served from the 'public' directory so it would be good if Cypress could figure out how to handle this in a more generic fashion.

@whitespacecode
Copy link

The issue is still present inCypress V13.8.1
image

@rstoneIDBS
Copy link

The issue is still present inCypress V13.8.1 image

See #28347 (comment) - it looks like 13.9.0 might fix this

@AtofStryker
Copy link
Contributor

The issue is still present inCypress V13.8.1 image

See #28347 (comment) - it looks like 13.9.0 might fix this

This did not make it into 13.9.0 since more work needs to be done, but the plan is for me to look back at this in next few days to make sure #28347 (comment) is addressed as well as other possible breaking changes.

@AtofStryker
Copy link
Contributor

I've found a fix for the MSW issue :)

I already had a section in my component.js that was configuring the MSW service worker, this also allows you to specify the URL of the worker so I changed it to this:

const { worker, graphql } = await import('../../src/mocks/browser');

Cypress.on('test:before:run:async', () => {
  if (worker.context.isMockingEnabled) {
    return;
  }
  return worker.start({
    serviceWorker: {
      url: '../src/public/mockServiceWorker.js',
    },
    // Disable logging of matched requests as this can occasionally result in test failures
    quiet: true,
  });
});

window.msw = {
  worker,
  graphql,
};

The key bit is the url setting as this ensures that MSW loads its code from the correct location.

This fixes MSW, but it won't fix anything else being served from the 'public' directory so it would be good if Cypress could figure out how to handle this in a more generic fashion.

Glad you found a work around for this @rstoneIDBS .

I'm currently trying to look into the public path issues but I am a bit stuck. The thread above mentions the fallback behavior to index.html and aligning html preview behavior, but the later only applies to html files. I'm struggling to recreate the public path issues at a very basic level since I can see assets still being served from the cypress public path
image.

Pardon my ignorance, but what is it that I am missing? Would either you, @juliandreas , or anyone really, be able to help me reproduce the public path issues so I can work on getting this supported?

@rstoneIDBS
Copy link

rstoneIDBS commented May 14, 2024

In you example above, change line 13 of App.jsx from:
<img src={viteLogo} className="logo" alt="Vite logo" />
to
<img src="/vite.svg" className="logo" alt="Vite logo" />
This will pull the logo directly from the public folder, now if you re-run your Cypress test you will see a broken image where the Vite logo should be. This is simulating the issue I'm seeing with MSW

@AtofStryker
Copy link
Contributor

In you example above, change line 13 of App.jsx from: <img src={viteLogo} className="logo" alt="Vite logo" /> to <img src="/vite.svg" className="logo" alt="Vite logo" /> This will pull the logo directly from the public folder, now if you re-run your Cypress test you will see a broken image where the Vite logo should be. This is simulating the issue I'm seeing with MSW

I appreciate the help! I was able to reproduce the problem on my end. Replacing the src with /vite.svg yields the asset can't be found and we need to somehow prefix this with the public path (default /__cypress/src/vite.svg).

@rstoneIDBS
Copy link

rstoneIDBS commented May 14, 2024

In you example above, change line 13 of App.jsx from: <img src={viteLogo} className="logo" alt="Vite logo" /> to <img src="/vite.svg" className="logo" alt="Vite logo" /> This will pull the logo directly from the public folder, now if you re-run your Cypress test you will see a broken image where the Vite logo should be. This is simulating the issue I'm seeing with MSW

I appreciate the help! I was able to reproduce the problem on my end. Replacing the src with /vite.svg yields the asset can't be found and we need to somehow prefix this with the public path (default /__cypress/src/vite.svg).

I think there might be a way of letting Vite know about additional public directories which I think is what you want to do here - i.e. tell Vite that '/__cypress/src/' is also a public folder. This was where I got to when looking at it before but I couldn't figure out how to configure that part of Vite from the Cypress code that starts the Vite dev server.

Edit: You might need to look at this vitejs/vite#5129

@AtofStryker
Copy link
Contributor

In you example above, change line 13 of App.jsx from: <img src={viteLogo} className="logo" alt="Vite logo" /> to <img src="/vite.svg" className="logo" alt="Vite logo" /> This will pull the logo directly from the public folder, now if you re-run your Cypress test you will see a broken image where the Vite logo should be. This is simulating the issue I'm seeing with MSW

I appreciate the help! I was able to reproduce the problem on my end. Replacing the src with /vite.svg yields the asset can't be found and we need to somehow prefix this with the public path (default /__cypress/src/vite.svg).

I think there might be a way of letting Vite know about additional public directories which I think is what you want to do here - i.e. tell Vite that '/__cypress/src/' is also a public folder. This was where I got to when looking at it before but I couldn't figure out how to configure that part of Vite from the Cypress code that starts the Vite dev server.

Edit: You might need to look at this vitejs/vite#5129

I think this actually requires the assets in the specified directories to be on disk. I am wondering if we can accomplish the same thing with a simple proxy?

        proxy: {
          '/': {
            target: `${devServerPublicPathRoute}/`,
            bypass: (
              req,
            ) => {
              // If the request comes from the root folder (i.e. the alias public path in Vite v5)
              // then proxy the assets to the public path for them to resolve correctly as they should.
              if (!req.url?.includes(devServerPublicPathRoute)) {
                const proxyPath = `${devServerPublicPathRoute}${req.url}`

                debug(`Proxying request ${req.url} to public path ${proxyPath}`)

                return `${devServerPublicPathRoute}${req.url}`
              }

              return req.url
            },
          },
        },

Though I would think you might want the ability to turn this off, especially if your server has more complex middleware and is spoofing an api server, so I don't think this is an ideal/perfect solution by any means. We might be able to narrow it down to just assets

@AtofStryker
Copy link
Contributor

In you example above, change line 13 of App.jsx from: <img src={viteLogo} className="logo" alt="Vite logo" /> to <img src="/vite.svg" className="logo" alt="Vite logo" /> This will pull the logo directly from the public folder, now if you re-run your Cypress test you will see a broken image where the Vite logo should be. This is simulating the issue I'm seeing with MSW

I appreciate the help! I was able to reproduce the problem on my end. Replacing the src with /vite.svg yields the asset can't be found and we need to somehow prefix this with the public path (default /__cypress/src/vite.svg).

I think there might be a way of letting Vite know about additional public directories which I think is what you want to do here - i.e. tell Vite that '/__cypress/src/' is also a public folder. This was where I got to when looking at it before but I couldn't figure out how to configure that part of Vite from the Cypress code that starts the Vite dev server.
Edit: You might need to look at this vitejs/vite#5129

I think this actually requires the assets in the specified directories to be on disk. I am wondering if we can accomplish the same thing with a simple proxy?

        proxy: {
          '/': {
            target: `${devServerPublicPathRoute}/`,
            bypass: (
              req,
            ) => {
              // If the request comes from the root folder (i.e. the alias public path in Vite v5)
              // then proxy the assets to the public path for them to resolve correctly as they should.
              if (!req.url?.includes(devServerPublicPathRoute)) {
                const proxyPath = `${devServerPublicPathRoute}${req.url}`

                debug(`Proxying request ${req.url} to public path ${proxyPath}`)

                return `${devServerPublicPathRoute}${req.url}`
              }

              return req.url
            },
          },
        },

Though I would think you might want the ability to turn this off, especially if your server has more complex middleware and is spoofing an api server, so I don't think this is an ideal/perfect solution by any means. We might be able to narrow it down to just assets

This is a bit of a smell to me. @rstoneIDBS out of curiousity have you tried setting the devServerPublicPathRoute to root to fix asset resolution, like this:

cypress.config.js

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
  },

  component: {
    devServer: {
      framework: "react",
      bundler: "vite",
    },
    devServerPublicPathRoute: '',
  },
});

@rstoneIDBS
Copy link

@AtofStryker setting devServerPublicPathRoute breaks the test with the following error:

> Failed to resolve module specifier '\cypress\support\component.js'

@AtofStryker
Copy link
Contributor

AtofStryker commented May 15, 2024

@AtofStryker setting devServerPublicPathRoute breaks the test with the following error:

> Failed to resolve module specifier '\cypress\support\component.js'

@rstoneIDBS I'm struggling to reproduce this error. Are you able to share a reproduction? Also, are you on Windows or running an ESM project?

@rstoneIDBS
Copy link

@AtofStryker all I did was:

  1. create a new Vite project (npm create vite@latest)
  2. selected React & JavaScript
  3. install and run Cypress
  4. select React + Vite + Component testing.

Modified the App.jsx file as described above and then changed cypress.config to include the devServerPublicPathRoute setting described above - this gave me the described error when running the created Cypress test.

I'm using Windows and the default Vite project is ESM

@AtofStryker
Copy link
Contributor

devServerPublicPathRoute: '',

Interesting I did the identical steps and everything works fine. The main difference is that I am not on Windows and am on MacOS 14.3. I bet this is some type of pathing issue specific to Windows. Will try the same steps as well but on Windows.

@AtofStryker
Copy link
Contributor

devServerPublicPathRoute: '',

Interesting I did the identical steps and everything works fine. The main difference is that I am not on Windows and am on MacOS 14.3. I bet this is some type of pathing issue specific to Windows. Will try the same steps as well but on Windows.

@rstoneIDBS After investigating it does look like a pathing issue. Hardcoding some values inside @cypress/vite-dev-server gets its going inside windows 37c01ca. Exploring solutions and will keep the thread updated.

@AtofStryker
Copy link
Contributor

@rstoneIDBS are you able to try the binary for windows on this commit ac6e96d?

@rstoneIDBS
Copy link

rstoneIDBS commented May 16, 2024

@rstoneIDBS are you able to try the binary for windows on this commit ac6e96d?

Just tried it with my test case (mentioned above) and with my real code (using MSW) and it appears to be working fine :) Thanks @AtofStryker

I guess the Cypress documentation will be updated to mention this - I can imagine others running into it and the solution (devServerPublicPathRoute) isn't obvious so making this discoverable is going to be a challenge.

@AtofStryker
Copy link
Contributor

@rstoneIDBS are you able to try the binary for windows on this commit ac6e96d?

Just tried it with my test case (mentioned above) and with my real code (using MSW) and it appears to be working fine :) Thanks @AtofStryker

@rstoneIDBS glad it works!

I guess the Cypress documentation will be updated to mention this - I can imagine others running into it and the solution (devServerPublicPathRoute) isn't obvious so making this discoverable is going to be a challenge.

This is the tricky part. We don't have a lot of documentation on our bundler dev-servers, but I did add a snippet into the package readme https://github.com/cypress-io/cypress/pull/29518/files#diff-07cdfa8a3a7320f94daa82c1155a2c8de98dc257e0749be5a72dd6789fdfed06R59. Discoverability here is difficult, but it at least gives us something to reference.

@cypress-bot
Copy link
Contributor

cypress-bot bot commented May 21, 2024

Released in 13.10.0.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v13.10.0, please open a new issue.

@cypress-bot cypress-bot bot locked as resolved and limited conversation to collaborators May 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
CT Issue related to component testing type: enhancement Requested enhancement of existing feature
Projects
Status: Generally Available
Development

Successfully merging a pull request may close this issue.

10 participants