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

Cypress config with monorepo and rewired cra #22521

Closed
MohoiNad opened this issue Jun 25, 2022 · 21 comments
Closed

Cypress config with monorepo and rewired cra #22521

MohoiNad opened this issue Jun 25, 2022 · 21 comments
Assignees
Labels
CT Issue related to component testing stale no activity on this issue for a long period

Comments

@MohoiNad
Copy link

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,

@lmiller1990 lmiller1990 added CT Issue related to component testing stage: routed to ct labels Jun 27, 2022
@lmiller1990
Copy link
Contributor

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 lmiller1990 added the stage: awaiting response Potential fix was proposed; awaiting response label Jun 27, 2022
@MohoiNad
Copy link
Author

MohoiNad commented Jun 29, 2022

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],
      },
    },
  },
})

@cypress-bot cypress-bot bot added stage: investigating Someone from Cypress is looking into this and removed stage: awaiting response Potential fix was proposed; awaiting response labels Jun 29, 2022
@MohoiNad
Copy link
Author

MohoiNad commented Jun 29, 2022

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

@mjhenkes mjhenkes assigned astone123 and unassigned lmiller1990 Jul 11, 2022
@nagash77 nagash77 assigned marktnoonan and unassigned astone123 Jul 19, 2022
@marktnoonan
Copy link
Contributor

@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.

@cypress-bot cypress-bot bot added stage: awaiting response Potential fix was proposed; awaiting response and removed stage: investigating Someone from Cypress is looking into this labels Jul 27, 2022
@mjhenkes mjhenkes assigned rockindahizzy and unassigned marktnoonan Aug 2, 2022
@AtofStryker
Copy link
Contributor

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 AtofStryker removed the stage: awaiting response Potential fix was proposed; awaiting response label Aug 8, 2022
@ntsyhaniuk
Copy link

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

@this-miguel
Copy link

@AtofStryker can this issue be reopen?

@PavloPoimanov
Copy link

PavloPoimanov commented Nov 25, 2022

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

@rockindahizzy
Copy link
Contributor

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

@this-miguel
Copy link

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
Copy link

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

@MohoiNad
Copy link
Author

MohoiNad commented Jan 4, 2023

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.

@lmiller1990
Copy link
Contributor

@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?

@bencergazda
Copy link

bencergazda commented Feb 15, 2023

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

@lmiller1990
Copy link
Contributor

lmiller1990 commented Feb 16, 2023

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: #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?

@bencergazda
Copy link

@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.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Feb 20, 2023

@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 #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!

@mayurnagdev123
Copy link

mayurnagdev123 commented May 31, 2023

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

> pogomaintenance@0.1.0 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"


> pogomaintenance@0.1.0 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.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Jun 5, 2023

Are you using Yarn workspaces? Possibly related: timarney/react-app-rewired#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.

@cypress-app-bot
Copy link
Collaborator

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 cypress-app-bot added the stale no activity on this issue for a long period label Dec 3, 2023
@cypress-app-bot
Copy link
Collaborator

This issue has been closed due to inactivity.

@cypress-app-bot cypress-app-bot closed this as not planned Won't fix, can't repro, duplicate, stale Dec 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CT Issue related to component testing stale no activity on this issue for a long period
Projects
None yet
Development

Successfully merging a pull request may close this issue.