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

Ship craco (CRA config override) adapter in cypress/react #16273

Closed
cd-a opened this issue Apr 29, 2021 · 12 comments · Fixed by #16333
Closed

Ship craco (CRA config override) adapter in cypress/react #16273

cd-a opened this issue Apr 29, 2021 · 12 comments · Fixed by #16333

Comments

@cd-a
Copy link

cd-a commented Apr 29, 2021

I use craco for react, so I can use Less with create-react-app

It replaces react-scripts start with craco start, so that the Less gets bundled to css.

When using cypress normally, it's all good, because I start up the web server, and then it just gets served from there.

With the component runner however, it just renders the components directly. How can i make the styles work? If I mount a component that directly imports the App.less file, it obviously makes no difference.

@lmiller1990
Copy link
Contributor

Can you post a minimal reproduction? We use the same webpack config as your project does, so everything should work. I have some projects using sass and CSS modules, for example, and it's working fine. Are you using craco less?

It's possible we are missing some edges cases for tools like craco. I have not used craco before, but we can add an example to the npm/react/examples directory as part of this fix.

@lmiller1990 lmiller1990 added component testing stage: needs information Not enough info to reproduce the issue labels Apr 30, 2021
@cd-a
Copy link
Author

cd-a commented Apr 30, 2021

Yes, I'm running craco-less

Here's a simple way to reproduce:

// create new repo
yarn create react-app cypress-craco --template typescript

// enter directory
cd cypress-craco

// install cypress
yarn add cypress @cypress/react @cypress/webpack-dev-server --dev

// install craco and craco-less
yarn add @craco/craco craco-less

Replace the build, start, test in package.json with the following

"start": "craco start",
"build": "craco build",
"test": "craco test",

Then, create craco.config.js in root folder and put this inside

/* eslint-disable @typescript-eslint/no-var-requires */
const CracoLessPlugin = require("craco-less");

module.exports = {
  plugins: [
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          lessOptions: {
            javascriptEnabled: true,
          },
        },
      },
    },
  ],
};

Then, rename the App.css to App.less in the src folder.

Inside the App.tsx file, change css to less

-import './App.css';
+import "./App.less";

Finally, replace App.test.tsx in the src folder with this:

import React from "react";
import { mount } from "@cypress/react";
import App from "./App";

it("renders learn react link", () => {
  mount(<App />);
  cy.get("a").contains("Learn React");
});

Now, when you ran yarn start, it gives you this:
Screenshot 2021-04-30 at 10 15 03

When you run yarn cypress open-ct and select App.test.tsx, it shows you this:

Screenshot 2021-04-30 at 10 16 16

@lmiller1990
Copy link
Contributor

lmiller1990 commented May 5, 2021

Right, this makes perfect sense - using the react-scripts plugin to inject the dev server grabs the unconfigured webpack config from CRA - the whole point of craco is to override that.

I looked into this and learned I can use the craco webpack API, specifically createWebpackDevConfig, to get the modified config.

I wrote this code and was able to get the less styling to work with Cypress. The following is in cypress/plugins/index.js.

const { createWebpackDevConfig } = require("@craco/craco");
const { startDevServer } = require('@cypress/webpack-dev-server')

const cracoConfig = require("../../craco.config.js");
const webpackConfig = createWebpackDevConfig(cracoConfig);

module.exports = (on, config) => {
  on('dev-server:start', options => {
    return startDevServer({
      options,
      webpackConfig
    })
  })

  return config
}

I think we can justify bundling a craco plugin with @cypress/react. I will work on shipping this. For now, you could use the above snippet.

image

Please let me know if this is working for you.

@lmiller1990 lmiller1990 changed the title Component Runner - does not work with preprocessors like less Ship craco (CRA config override) adapter in cypress/react May 5, 2021
@lmiller1990 lmiller1990 removed the stage: needs information Not enough info to reproduce the issue label May 5, 2021
@lmiller1990
Copy link
Contributor

lmiller1990 commented May 7, 2021

We will have a CRACO specific plugin for cypress/react in the next release. See #16333.

@cd-a
Copy link
Author

cd-a commented May 7, 2021

Thank you so much!

@ghost
Copy link

ghost commented Sep 2, 2021

const cracoConfig = require("../../craco.config.js");
const webpackConfig = createWebpackDevConfig(cracoConfig);

module.exports = (on, config) => {
  on('dev-server:start', options => {
    return startDevServer({
      options,
      webpackConfig
    })
  })

  return conf

It works, thank you!

@kirstenlindsmith
Copy link

Is there any update on how to implement this with cypress v10+? I'm implementing the latest version (12.9.0) and it looks like not both the workaround and the "new" (as of 2021) plugin both don't work/don't exist anymore.
startDevServer is no longer exported from @cypress/webpack-dev-server, and @cypress/react/plugins/craco no longer exists at all and I can't find where it went.

@astone123
Copy link
Contributor

@kirstenlindsmith we don't support CRACO internally right now, but you should be able to get something to work in your Cypress configuration file like this

const { devServer } = require("@cypress/webpack-dev-server")
const { defineConfig } = require("cypress");
const { createWebpackDevConfig } = require("@craco/craco");

module.exports = defineConfig({
  component: {
    devServer: (devServerOptions) => devServer({
      ...devServerOptions,
      framework: 'react',
      webpackConfig: async () => {
        const cracoConfig = require("./craco.config.js");
         return createWebpackDevConfig(cracoConfig)
      },
    }),
  },
});

We need to do this because Cypress doesn't know how to get the webpack configuration for the app. We look for it in the root and have special support for Create React App that gets the webpack config that they use. This is a little more complicated - we need to call createWebpackDevConfig with our CRACO config and then return that configuration to Cypress.

Please let me know if this works for you. Thanks!

@khashashin
Copy link

khashashin commented Apr 9, 2023

@kirstenlindsmith did you get it to work? I also have 12.9 installed and can't get the component tests to start. Here is my cypress.json and craco.config.js

cypress.json

const { devServer } = '@cypress/webpack-dev-server';
const { defineConfig } = require('cypress');
const { createWebpackDevConfig } = require('@craco/craco');

module.exports = defineConfig({
  pageLoadTimeout: 180000,
  numTestsKeptInMemory: 0,

  reporterOptions: {
    toConsole: true,
  },

  env: {
    API_GATEWAY_BASE: 'https://development.services.com',
    DEV_SERVER_PORT: 3000,
  },

  e2e: {
    experimentalRunAllSpecs: true,
    excludeSpecPattern: [
      '**/energy_simulation/**',
      '**/debug/**.js',
      '**/_common/**',
    ],
  },

  component: {
    devServer(devServerConfig) {
      const cracoConfigFile = require('../../craco.config.js');
      const cracoConfig = createWebpackDevConfig({
        ...cracoConfigFile,
        webpack: {
          ...cracoConfigFile.webpack,
          devtool: 'eval-source-map',
        },
      });

      return devServer({
        ...devServerConfig,
        framework: 'react',
        webpackConfig: cracoConfig,
      });
    },
  },
});

craco.config.js

const { whenDev } = require('@craco/craco');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = {
  webpack: {
    plugins: [
      new NodePolyfillPlugin({
        excludeAliases: ['console'],
      }),
    ],
    configure: whenDev(() => ({
      devtool: 'eval-source-map',
    })),
  },
};

I get the error:

image

@lmiller1990
Copy link
Contributor

@kirstenlindsmith @khashashin check this example I made. I used the craco config and cypress config from the above post and got it to work:

https://github.com/lmiller1990/cypress-craco

Not sure how you ran into that error, looks like your cypress.config is in a different directory - if you can pots a minimal repro (or fork from mine, maybe, to replicate the issue)? I can take a look, thanks!

@khashashin
Copy link

By moving cypress.config.js to the root folder of the project, I was able to start component testing without configuring anything via craco. @lmiller1990 Thank you for your help

@lmiller1990
Copy link
Contributor

You shouldn't need to move it to the root 🤔 but glad you got it working 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants