cypress icon indicating copy to clipboard operation
cypress copied to clipboard

Cypress config with monorepo and rewired cra

Open MohoiNad opened this issue 3 years ago • 8 comments

Current behavior

I have a lerna monorepo with 2 cra's in my repo, where is one a customized by cra-customize and react-app-rewired.

package-a includes 2 tests.

One is cypress, second is @testing-library/react

I feel like config-overrides.js are not wotking with cypess, that's why test in red. Can i somehow override the wepback configuration from cypress to same way? Maybe new cypress.config.ts can help me?

Desired behavior

Both tests green.

Test code to reproduce

https://github.com/MohoiNad/cypress-issue

Cypress Version

10.2.0

Other

I have some problems with babel if i am using customize-cra config,

MohoiNad avatar Jun 25 '22 15:06 MohoiNad

I think you are right, it is not finding config-overrides.js. I haven't had a chance to try your repo yet, but one thing you might find useful is the ability to customise the dev server: https://docs.cypress.io/guides/component-testing/component-framework-configuration#Custom-Dev-Server

Eg:

import { defineConfig } from 'cypress'
import defaultConfig from './cypress-webpack.config'
import { devServer } from '@cypress/webpack-dev-server'

export default defineConfig({
  component: {
    devServer: (devServerOptions) => devServer({
      ...devServerOptions,
      framework: 'react',
      webpackConfig: {}, // customize it here!,
    }),
    supportFile: false
  }
})

Where I wrote "customize it here" you could import your config-overrides and do things there. This is how bundler: 'webpack' works under the hood.

lmiller1990 avatar Jun 27 '22 07:06 lmiller1990

Well, i don't wanna create a whole webpack config by myself, because it's too huge - that would be the whole repo of react-scripts.

i thing i have some variant's and some test's of them. I can try to get rid of react-app-rewired with https://www.npmjs.com/package/patch-package which is one of variant's in github, i need to test it before i can say something. That way cypress get it's new patched config and would think that this is normal cra

Also probably there is no way that i can get the config from runtime but i can change the cra's webpack config. after cypress get it?

The cra's webpack-config.js are in /node-modules/react-scripts/config and cypress just get it there, so can i just do this?

module.exports = defineConfig({
  component: {
    devServer: {
      framework: 'create-react-app',
      bundler: 'webpack',
      webpackConfig: {
      ...defaultCraWebpackConfig,
       publicPath: [paths.publicUrlOrPath],
      },
    },
  },
})

MohoiNad avatar Jun 29 '22 21:06 MohoiNad

I think you are right, it is not finding config-overrides.js. I haven't had a chance to try your repo yet, but one thing you might find useful is the ability to customise the dev server: https://docs.cypress.io/guides/component-testing/component-framework-configuration#Custom-Dev-Server

Eg:

import { defineConfig } from 'cypress'
import defaultConfig from './cypress-webpack.config'
import { devServer } from '@cypress/webpack-dev-server'

export default defineConfig({
  component: {
    devServer: (devServerOptions) => devServer({
      ...devServerOptions,
      framework: 'react',
      webpackConfig: {}, // customize it here!,
    }),
    supportFile: false
  }
})

Where I wrote "customize it here" you could import your config-overrides and do things there. This is how bundler: 'webpack' works under the hood.

No way that would be work with cra:

import { defineConfig } from 'cypress'
import defaultConfig from 'react-scripts/config/webpack.config'
// import defaultConfig from 'react-scripts/config/webpackDevServer.config'
import { devServer } from '@cypress/webpack-dev-server'

export default defineConfig({
  component: {
    devServer: (devServerOptions) => devServer({
      ...devServerOptions,
      framework: 'react',
      webpackConfig: defaultConfig,
    }),
    supportFile: false
  }
})

give me that kind of error image

MohoiNad avatar Jun 29 '22 21:06 MohoiNad

@MohoiNad I'd like to pick up investigating this one, but it's been a couple of weeks so please let me know first if you've had and progress in the meantime on your own before I spend much time in it. Mainly I want to figure out

  • is there a bug in Cypress?
  • or is this just challenging from a configuration perspective?
  • is it not bug, but something we could make easier with a preset or recipe?

I can try to get rid of react-app-rewired with npmjs.com/package/patch-package which is one of variant's in github, i need to test it before i can say something.

Did you give this a shot?

I did pull down your repo a though I got past your error (by setting the NODE_ENV NODE_ENV=development npx cypress open --component), and got Cypress to go to the "opening browser" stage, I still encountered compilation errors at that stage which means something else still isn't right. Not personally familiar with CRA (and its customizations), so curious if you were able to work around it.

Generally when using the config from react-scripts/config/webpack.config I seemed to get validation errors like this:

ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
 - configuration.output.chunkFilename should be one of these:
   non-empty string | function

Which could be got around by providing those values, but it feels like that gets a little heavy handed, and it would make more sense if it "just worked" with the existing setup you have for development.

marktnoonan avatar Jul 27 '22 14:07 marktnoonan

Unfortunately we have to close this issue due to inactivity. Please comment if there is new information to provide concerning the original issue and we can reopen.

AtofStryker avatar Aug 08 '22 18:08 AtofStryker

@MohoiNad hi, have you had a chance to solve this issue?

ntsyhaniuk avatar Oct 12 '22 13:10 ntsyhaniuk

@AtofStryker can this issue be reopen?

this-miguel avatar Nov 21 '22 08:11 this-miguel

Hi, I have resolved issues for me with next

const { devServer } = require('@cypress/webpack-dev-server')
require('react-app-rewired/scripts/start')
const defaultConfig = require('react-app-rewired/config/webpack.config')
console.log(defaultConfig().plugins[3].definitions)
module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    video: false,
    viewportHeight: 900,
    viewportWidth: 1240,
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
    retries: {
      runMode: 3,
      openMode: 0
    }
  },

  component: {
    devServer(devServerConfig) {
      return devServer({
        ...devServerConfig,
        framework: 'create-react-app',
        webpackConfig: {
          ...defaultConfig(),
          plugins: [...defaultConfig().plugins ],
          output: {
            ...defaultConfig().output,
            devtoolModuleFilenameTemplate: 'webpack://[namespace]/[resource-path]?[loaders]'
          }
        }
      })
    }
  }
})

The general idea was to extend what @marktnoonan did with the config from cra. I just replaced webpack config with required because it have overrides. Then I was figting with the errors in console, not 100% that this config is correct but at least it work It works for me image

PavloPoimanov avatar Nov 25 '22 19:11 PavloPoimanov

@this-miguel, can you confirm if the suggested steps from @marktnoonan help at all?

rockindahizzy avatar Nov 30 '22 17:11 rockindahizzy

it didn't work for me. If I understand correctly that can't work because if cypress only takes the webpack config from CRA any customisation done with rewired CRA will not be taken on account. I've been trying something like @MohoiNad but I've not been able to make it work yet

this-miguel avatar Jan 04 '23 11:01 this-miguel

is anybody working to solve this issue on the cypress team?

this-miguel avatar Jan 04 '23 11:01 this-miguel

i'm trying to left from cra to nx workspaces. probably https://www.npmjs.com/package/patch-package is looks like the best solution for this issue. i will try to leave a report "how-to" on the week or like so.

MohoiNad avatar Jan 04 '23 18:01 MohoiNad

@this-miguel there is no active work happening as of right now internally to make CRA-rewired a first class citizen, but it can be certainly accomplished. This should be do-able in the same way suggested above. If we were to support this as a first class framework, this is how it would be implemented, too.

import { defineConfig } from 'cypress'
import defaultConfig from './cypress-webpack.config'
import { devServer } from '@cypress/webpack-dev-server'

export default defineConfig({
  component: {
    devServer: (devServerOptions) => devServer({
      ...devServerOptions,
      framework: 'react',
      webpackConfig: async () => {
         // customize it here! your own config, import a rewired one, etc.
         const craRewiredConfig = await import('./your-webpack-config.js')
         return craRewiredConfig
      },
    }),
  }
})

This is how we implement all the frameworks in Cypress - each one just has a custom config, which goes off to find the correct config depending on the framework (next, vite). Basically, framework and bundler just tell Cypress where to look for a config file - you can do the same thing from the outside, too, like this.

Would this help with your use case? Did you try this -- if so, did you get some kind of error/blocker?

lmiller1990 avatar Jan 17 '23 00:01 lmiller1990

I share a simple config example that initializes react-app-rewired before @cypress/webpack-dev-server accesses the webpack config throguhreact.scripts. This seem to be the most "safe" way in my opinion.

import { defineConfig } from 'cypress';

/**
 * "Rewire" the webpack config before `loadWebpackConfig` accesses it through `react-scripts`
 * @see @cypress/webpack-dev-server/dist/helpers/createReactAppHandler.js:41
 */
process.env.NODE_ENV = 'test';
process.env.BABEL_ENV = 'test';
require('react-app-rewired/config/webpack.config')('development');

export default defineConfig({
  component: {
    devServer: {
      framework: 'create-react-app',
      bundler: 'webpack',
    },
  },
});

@marktnoonan @lmiller1990 Storybook has a nice config option in its CRA preset that makes it possible to use custom package name for react-scripts. Would you be open for such change? That would make it possible to use forks of react-scripts, or other, compatible libraries without requiring additional changes.

export default defineConfig({
  component: {
    devServer: {
      framework: 'create-react-app',
      bundler: 'webpack',
      scriptsPackageName: 'react-app-rewired', // `scriptsPackageName` defaults to `react-scripts`
    },
  },
});

Ref: #9688

bencergazda avatar Feb 15 '23 09:02 bencergazda

Hi @bencergazda, that's neat - I did not realize you could do it like that.

Re: API - I'm working on such a public API right now. Tracking: https://github.com/cypress-io/cypress/issues/25637. We are shipping some of it in the next release, I will share the documentation within 1 week. An example implementation will be what you see here: https://github.com/lmiller1990/cypress-ct-solid-js/blob/main/definition.cjs

This only adds support for libraries right now - think Vue, React, etc - so you can choose the dependencies you support, inject a mount function, etc.

Right now there's not a way to inject something like you are describing yet, but there will be, I'm trying to figure out the right API to expose. From a user point of view, it'll like be:

export default defineConfig({
  component: {
    devServer: {
      framework: 'react-app-rewired',
      bundler: 'webpack',
    },
  },
});

If you've got any ideas, that'd be great - I was thinking something like

export default defineComponentFramework({
  type: 'react-app-rewired',
  name: 'React Rewired',
  devServer: async (cypressConfig, bundler) => {
    // you can do something different depending on the bundler?
    // some frameworks have both Vite and Webpack, etc.
    // must return relevant config
    // eg return require('react-app-rewired/config/webpack.config')('development');
  }
})

Would this work for your use case?

lmiller1990 avatar Feb 16 '23 00:02 lmiller1990

@lmiller1990 I think that the defineComponentFramework option could give a really good UX when fine-tuning the config. But I could imagine a more general use-case, with a custom scripts package path. I created a basic example in #25865.

bencergazda avatar Feb 17 '23 10:02 bencergazda

@bencergazda I agree we can give a great UX for fine tuning the config with this new API. There's a lot to consider to make this as robust as possible, we will be exploring it more in our next sprint of work. Follow https://github.com/cypress-io/cypress/issues/25881

If you've got feedback/ideas, you could share them in that issue, too - the more we know about the various use cases, the better!

lmiller1990 avatar Feb 20 '23 06:02 lmiller1990

Hello Cypress team, I am seeing the following issue while running npm run ci-test command


C:\Users\4724663\mywork\pogomaintenance>npm run ci-test

> [email protected] ci-test
> start-server-and-test start-ci http-get://localhost:$npm_config_myport cypress-cli-e2e

1: starting server using command "npm run start-ci"
and when url "[ 'http-get://localhost:$npm_config_myport' ]" is responding with HTTP status code 200
running tests using command "npm run cypress-cli-e2e"


> [email protected] start-ci
> cross-env PORT=$npm_config_myport BROWSER=none react-scripts start

(node:31496) [DEP_WEBPACK_DEV_SERVER_ON_AFTER_SETUP_MIDDLEWARE] DeprecationWarning: 'onAfterSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:31496) [DEP_WEBPACK_DEV_SERVER_ON_BEFORE_SETUP_MIDDLEWARE] DeprecationWarning: 'onBeforeSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
Starting the development server...
Failed to compile.

Module not found: Error: Can't resolve 'stream' in 'C:\Users\4724663\mywork\pogomaintenance\node_modules\json-stream\lib'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
        - install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "stream": false }
WARNING in ./node_modules/sax/lib/sax.js 139:13-37
Module not found: Error: Can't resolve 'stream' in 'C:\Users\4724663\mywork\pogomaintenance\node_modules\sax\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
        - install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "stream": false }

ERROR in ./node_modules/json-stream/lib/json-stream.js 2:20-47
Module not found: Error: Can't resolve 'stream' in 'C:\Users\4724663\mywork\pogomaintenance\node_modules\json-stream\lib'


Here's my cypress.config.js that I copied from one of the threads above

import { defineConfig } from 'cypress';

process.env.NODE_ENV = 'test';
process.env.BABEL_ENV = 'test';
require('react-app-rewired/config/webpack.config')('development');

export default defineConfig({
  component: {
    devServer: {
      framework: 'create-react-app',
      bundler: 'webpack',
    },
  },
});

config-overrides.js

module.exports = function override(config) {
    const fallback = config.resolve.fallback || {};
    Object.assign(fallback, {
        "crypto": require.resolve("crypto-browserify"),
        "stream": require.resolve("stream-browserify"),
        "assert": require.resolve("assert"),
        "http": require.resolve("stream-http"),
        "https": require.resolve("https-browserify"),
        "os": require.resolve("os-browserify"),
        "url": require.resolve("url"),
        "process/browser": require.resolve('process/browser'),
        "path":false,
        "fs":false,
        "timers": false,
        "buffer": false,
        "https": false,
    })
    config.resolve.fallback = fallback;
    config.plugins = (config.plugins || []).concat([
        new webpack.ProvidePlugin({
            process: 'process/browser',
            Buffer: ['buffer', 'Buffer']
        })
    ])
    return config;
}

I have created a question for the same on stackoverflow that also includes my package.json details https://stackoverflow.com/questions/76363432/cypress-not-running-with-react-app-rewired

Can you please help me? I have been stuck on this for days now.

mayurnagdev123 avatar May 31 '23 09:05 mayurnagdev123

Are you using Yarn workspaces? Possibly related: https://github.com/timarney/react-app-rewired/issues/618

Best would be a minimal reproduction - can you share a minimal repo? I don't have the bandwidth to manually reproduce your error. Eg - I'll probably get a different yarn.lock to you, if you can share a repo I can clone and I can run directly, that would help.

lmiller1990 avatar Jun 05 '23 05:06 lmiller1990

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

cypress-app-bot avatar Dec 03 '23 01:12 cypress-app-bot

This issue has been closed due to inactivity.

cypress-app-bot avatar Dec 17 '23 01:12 cypress-app-bot