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

[7.0.1] Component testing not working with Next.js and future.webpack5 configuration #15864

Closed
edusig opened this issue Apr 7, 2021 · 24 comments · Fixed by #16108
Closed

[7.0.1] Component testing not working with Next.js and future.webpack5 configuration #15864

edusig opened this issue Apr 7, 2021 · 24 comments · Fixed by #16108
Assignees
Labels
npm: @cypress/react @cypress/react package issues

Comments

@edusig
Copy link

edusig commented Apr 7, 2021

Current behavior

Cypress open-ct and run-ct both get stuck while using:
Nextjs: 10.1.3
React: 17.0.2
Cypress: 7.0.1
Webpack: 5.30.0

my next.config.js file:

module.exports = {
  future: {
    webpack5: true,
  },
};

cypress/plugins/index.js file:

module.exports = (on, config) => {
  require("@cypress/react/plugins/next")(on, config);
  return config;
};

Screenshot_2021-04-07_16-36-33
Screenshot_2021-04-07_16-37-59

Desired behavior

It should run normally

Test code to reproduce

I have forked this repo and updated the packages and configurations here -> https://github.com/edusig/next-and-cypress-example

Versions

Cypress: 7.0.1
Last working Cypress version: 6.5.0
OS: Manjaro Linux

More information

@djsilcock
Copy link
Contributor

djsilcock commented Apr 8, 2021

I had this same issue - initially fails as can't find webpack. If webpack is added as dependency then it fails as you describe but with debugging on shows a 'compilation must be an instance of Compilation' error.
Essentially the problem is that next bundles its own version of webpack so there are two versions in play at once. However it adds a require hook so it is possible to use the next vendored webpack as long as the next config is run before the webpack devserver is set up.
Will put in a PR to fix later when I get to my PC.

@JessicaSachs JessicaSachs self-assigned this Apr 12, 2021
@JessicaSachs JessicaSachs added component testing npm: @cypress/react @cypress/react package issues labels Apr 12, 2021
@JessicaSachs JessicaSachs changed the title [7.0.1] Component testing not working with Next.js plugin [7.0.1] Component testing not working with Next.js and future.webpack5 configuration Apr 12, 2021
@JessicaSachs
Copy link
Contributor

Updating this issue to reflect that it's specific to nextjs with the future.webpack5 flag set.

@edusig
Copy link
Author

edusig commented Apr 13, 2021

@JessicaSachs Even with the future.webpack5 set as false it still won't work. You can't try it in the repo I created to reproduce the problem.

@djsilcock Thanks for the quick reply.

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Apr 13, 2021

The code for this is done in cypress-io/cypress#15885, but has yet to be released.
We'll update this issue and reference the changelog when it's released.

@hwhitworth10
Copy link

hwhitworth10 commented Apr 13, 2021

Working through this exact same issue. Is there an estimate on when it will be released? I am pushing to have this be the tool we use to test our components, but without an ETA the team may have me utilize something else. Thanks for the quick responses!

@djsilcock
Copy link
Contributor

It occurred to me earlier that a better approach might be instead of trying to extract the nextjs config and the monkeypatched webpack, that it might be easier to use the actual next devserver instead. Will share some code later

@lmiller1990
Copy link
Contributor

Anything merged into master inside of the npm directory (so npm/react) is released automatically via semantic release. So if you install the latest version of @cypress/react, you will have the latest code.

I just installed it and can confirm the code is there: yarn add @cypress/react && cat node_modules/@cypress/react/plugins/next/index.js

const findNextWebpackConfig = require('./findNextWebpackConfig')

module.exports = (on, config) => {
  on('dev-server:start', async (options) => {
    const webpackConfig = await findNextWebpackConfig(config)

    // require('webpack') now points to nextjs bundled version
    const { startDevServer } = require('@cypress/webpack-dev-server')

    return startDevServer({ options, webpackConfig })
  })

  config.env.reactDevtools = true

  return config
}

Please install it and give it a try! Let us know if there is still any problems.

@edusig
Copy link
Author

edusig commented Apr 16, 2021

@lmiller1990 I updated the packages on my example repo (https://github.com/edusig/next-and-cypress-example) to the latest and now I'm getting another error:

Error [TypeError]: Cannot read property 'version' of undefined
    at Object.<anonymous> (/home/edusig/workspace/edusig/next-and-cypress-example/node_modules/@cypress/webpack-dev-server/node_modules/html-webpack-plugin/lib/file-watcher-api.js:7:67)
    at Module._compile (internal/modules/cjs/loader.js:1078:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12684)
    at Module.require (internal/modules/cjs/loader.js:959:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (/home/edusig/workspace/edusig/next-and-cypress-example/node_modules/@cypress/webpack-dev-server/node_modules/html-webpack-plugin/lib/cached-child-compiler.js:41:24)
    at Module._compile (internal/modules/cjs/loader.js:1078:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12684)
    at Module.require (internal/modules/cjs/loader.js:959:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (/home/edusig/workspace/edusig/next-and-cypress-example/node_modules/@cypress/webpack-dev-server/node_modules/html-webpack-plugin/index.js:19:36)
    at Module._compile (internal/modules/cjs/loader.js:1078:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12684)
TypeError: Cannot read property 'version' of undefined
    at Object.<anonymous> (/home/edusig/workspace/edusig/next-and-cypress-example/node_modules/@cypress/webpack-dev-server/node_modules/html-webpack-plugin/lib/file-watcher-api.js:7:67)
    at Module._compile (internal/modules/cjs/loader.js:1078:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12684)
    at Module.require (internal/modules/cjs/loader.js:959:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (/home/edusig/workspace/edusig/next-and-cypress-example/node_modules/@cypress/webpack-dev-server/node_modules/html-webpack-plugin/lib/cached-child-compiler.js:41:24)
    at Module._compile (internal/modules/cjs/loader.js:1078:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12684)
    at Module.require (internal/modules/cjs/loader.js:959:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (/home/edusig/workspace/edusig/next-and-cypress-example/node_modules/@cypress/webpack-dev-server/node_modules/html-webpack-plugin/index.js:19:36)
    at Module._compile (internal/modules/cjs/loader.js:1078:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12684)

Packages versions:
cypress: 7.1.0
@cypress/react: 5.3.3
@cypress/webpack-dev-server: 1.1.3

I also tested downgrading the @cypress/webpack-dev-server to version 1.1.2 and re-installing html-webpack-plugin and it finally opened, but it stuck loading the first component test file.

@itstheandre
Copy link

I tried cloning @edusig code and moving around dependencies, making webpack 4, removing flags and i still cant get it to work :(

@lmiller1990
Copy link
Contributor

lmiller1990 commented Apr 20, 2021

I reproduced the problem: #16078

The stack trace comes from in html-webpack-plugin:

const webpackMajorVersion = Number(require('webpack/package.json').version.split('.')[0]);

I will dig deeper.

Edit: this problem is unique to the cypress monorepo, since we hoist the dependencies to the root node_modules. html-webpack-plugin assumes that webpack is installed in the root of the project.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Apr 20, 2021

Ok, I think the problem is we have html-webpack-plugin@4 as a direct dependency. It's look inside node_modules/@cypress/webpack-dev-server/node_modules... for html-webpack-plugin and the associated webpack version, which is not there. I think we need to remove this hard dependency and just have webpack and html-webpack-plugin as peer dependencies. The user will need run something like this:

yarn add cypress @cypress/webpack-dev-server html-webpack-plugin@5 webpack@5`

As well as specifying webpack5: true in their next.config.js. I am still not entirely sure how next.js works; I don't see webpack installed in node_modules when I create a new nextjs project - where is the toolchain installed? I guess it's buried somwhere deep inside node_modules/next?

This is proving more complex than expected but I'm working through it and should have something soon.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Apr 21, 2021

Bring your own webpack is exactly what I'm going for. Nextjs seems kind of unique in that they bundle and ship their own webpack implementation.

I made this PR: #16108

Basically users need to have either webpack@4 or webpack@5 installed (and the relevant html-webpack-plugin). Those are listed as peerDependencies, with a range of 4-5. The other main change is to remove html-webpack-plugin from dependencies, so @cypress/webpack-dev-server won't try to install and use it's own one.

The only real downside here is we require quite a lot of peerDependencies.

  • webpack
  • html-webpack-plugin
  • @cypress/webpack-dev-server

I don't think this really a major problem. Most templates will specify their webpack and html-webpack-plugin, which are installed to node_modules. Nextjs is the exception, with its inline webpack.

I think this solution is a little better in terms of long term maintainability. We are also working on a yarn create cypress-tests scaffolder - this would be the place to check for the existence of next.config.js and install the relevant webpack and html-webpack-plugin versions.

@djsilcock
Copy link
Contributor

I actually meant that you could supply webpack to webpack-devserver rather than have it require webpack itself. The webpack module is exposed to the webpack method in next.config.js such that you can use something like:

let webpackModule
nextConfig={
    future:{webpack5:true},
    webpack (config,{webpack}) {
        webpackModule=webpack
        return config
        }
    }
const nextWebpackConfig = await getNextJsBaseWebpackConfig(
config.projectRoot,
{
  buildId: `@cypress/react-${Math.random().toString()}`,
  config: nextConfig,
  dev: true,
  isServer: false,
  pagesDir: config.projectRoot,
  entrypoints: {},
  rewrites: { fallback: [], afterFiles: [], beforeFiles: [] },
},
)
//now webpackModule == require('webpack')

@Norfeldt
Copy link

Hope I'm not side-tracking this issue - but how do you get it to work with just the webpack version that NextJS is using in your application?

I have tried the cypress/plugins/index.js file you wrote (but with .ts) and it's not really working out for me #16136

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Apr 23, 2021

The code for this is done in cypress-io/cypress#16108, but has yet to be released.
We'll update this issue and reference the changelog when it's released.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Apr 23, 2021

I managed to remove the hard requirement of html-webpack-plugin v4 here. #16108

This should fix the problem - all you'll need to do now is install webpack 5 and html-webpack-plugin 5 and it should work. This should minimize the framework specific concerns from leaking too deeply into Cypress.

The above code will go out in the next release. Thanks everyone so far - it's entirely possible that some edge cases are not covered still (nextjs ecosystem is huge), but keep the bug reports coming 👍

I started to use nextjs a little from this - it's really neat, and the DX experience is great! Let's keep this issue open until the code is in the wild and confirmed to be working as expected.

@nottyo
Copy link

nottyo commented May 2, 2021

Next.js just released the new version 10.2 https://nextjs.org/blog/next-10-2 which enables webpack5 by default. Has anyone tried this version with Cypress component testing ?

@edusig
Copy link
Author

edusig commented May 3, 2021

@lmiller1990 and @nottyo I have just updated my example repo (https://github.com/edusig/next-and-cypress-example) and it is working perfectly. I also updated Next.js to v10.2.0 and there was no problem running the tests.

On other projects, which have a more complex Next.js/Babel/Cypress/Yarn workspaces configuration it seems to be working perfectly as well.

Thanks again for all the help and quick resolution :)

@nottyo
Copy link

nottyo commented May 4, 2021

@lmiller1990
Copy link
Contributor

There is a PR for detailed docs with information on how to use Cypress with both next.js + webpack 4 and 5 here: cypress-io/cypress-documentation#3883

Incredibly good blog post @nottyo!

Seems this is working fine now - I'm sure we will find some edge cases for more complex configurations, if so, please open a discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment