Skip to content

Commit c618d30

Browse files
feat: react-scripts. allow parametrise webpack config path (#16644)
Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
1 parent 4663d2e commit c618d30

File tree

4 files changed

+100
-83
lines changed

4 files changed

+100
-83
lines changed

npm/react/plugins/react-scripts/findReactScriptsWebpackConfig.js

+4-80
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,17 @@
11
// @ts-check
22
const debug = require('debug')('@cypress/react')
33
const tryLoadWebpackConfig = require('../utils/tryLoadWebpackConfig')
4+
const { allowModuleSourceInPlace } = require('../utils/webpack-helpers')
5+
const { addCypressToWebpackEslintRulesInPlace } = require('../utils/eslint-helpers')
46
const { getTranspileFolders } = require('../utils/get-transpile-folders')
57
const { addFolderToBabelLoaderTranspileInPlace } = require('../utils/babel-helpers')
68

7-
/**
8-
* Finds the ModuleScopePlugin plugin and adds given folder
9-
* to that list. This allows react-scripts to import folders
10-
* outside of the default "/src" folder.
11-
* WARNING modifies the input webpack options argument.
12-
* @see https://github.com/bahmutov/cypress-react-unit-test/issues/289
13-
* @param {string} folderName Folder to add, should be absolute
14-
*/
15-
function allowModuleSourceInPlace (folderName, webpackOptions) {
16-
if (!folderName) {
17-
return
18-
}
19-
20-
if (!webpackOptions.resolve) {
21-
return
22-
}
23-
24-
if (!Array.isArray(webpackOptions.resolve.plugins)) {
25-
return
26-
}
27-
28-
const moduleSourcePlugin = webpackOptions.resolve.plugins.find((plugin) => {
29-
return Array.isArray(plugin.appSrcs)
30-
})
31-
32-
if (!moduleSourcePlugin) {
33-
debug('cannot find module source plugin')
34-
35-
return
36-
}
37-
38-
debug('found module source plugin %o', moduleSourcePlugin)
39-
if (!moduleSourcePlugin.appSrcs.includes(folderName)) {
40-
moduleSourcePlugin.appSrcs.push(folderName)
41-
debug('added folder %s to allowed sources', folderName)
42-
}
43-
}
44-
45-
const addCypressToWebpackEslintRulesInPlace = (webpackOptions) => {
46-
const globalsToAdd = ['cy', 'Cypress', 'before', 'after', 'context']
47-
48-
if (webpackOptions.module && Array.isArray(webpackOptions.module.rules)) {
49-
const modulePre = webpackOptions.module.rules.find(
50-
(rule) => rule.enforce === 'pre',
51-
)
52-
53-
if (modulePre && Array.isArray(modulePre.use)) {
54-
debug('found Pre block %o', modulePre)
55-
56-
const useEslintLoader = modulePre.use.find(
57-
(use) => use.loader && use.loader.includes('eslint-loader'),
58-
)
59-
60-
if (useEslintLoader) {
61-
debug('found useEslintLoader %o', useEslintLoader)
62-
63-
if (useEslintLoader.options) {
64-
if (Array.isArray(useEslintLoader.options.globals)) {
65-
debug(
66-
'adding cy to existing globals %o',
67-
useEslintLoader.options.globals,
68-
)
69-
70-
useEslintLoader.options.globals.push(...globalsToAdd)
71-
} else {
72-
debug('setting new list of globals with cy and Cypress')
73-
useEslintLoader.options.globals = globalsToAdd
74-
}
75-
76-
debug('updated globals %o', useEslintLoader.options.globals)
77-
} else {
78-
debug('eslint loader does not have options ⚠️')
79-
}
80-
}
81-
}
82-
}
83-
}
84-
85-
module.exports = function findReactScriptsWebpackConfig (config) {
9+
module.exports = function findReactScriptsWebpackConfig (config, { webpackConfigPath }) {
8610
// this is required because
8711
// 1) we use our own HMR and we don't need react-refresh transpiling overhead
8812
// 2) it doesn't work with process.env=test @see https://github.com/cypress-io/cypress-realworld-app/pull/832
8913
process.env.FAST_REFRESH = 'false'
90-
const webpackConfig = tryLoadWebpackConfig('react-scripts/config/webpack.config')
14+
const webpackConfig = tryLoadWebpackConfig(webpackConfigPath)
9115

9216
if (!webpackConfig) {
9317
throw new Error('⚠️ Could not find Webpack options for react-scripts. Make sure that you have react-scripts module available.')

npm/react/plugins/react-scripts/index.js

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
const { startDevServer } = require('@cypress/webpack-dev-server')
22
const findReactScriptsWebpackConfig = require('./findReactScriptsWebpackConfig')
33

4-
module.exports = (on, config) => {
4+
module.exports = (
5+
on,
6+
config, {
7+
webpackConfigPath,
8+
} = {
9+
webpackConfigPath: 'react-scripts/config/webpack.config',
10+
},
11+
) => {
512
on('dev-server:start', async (options) => {
6-
return startDevServer({ options, webpackConfig: findReactScriptsWebpackConfig(config) })
13+
return startDevServer({
14+
options,
15+
webpackConfig: findReactScriptsWebpackConfig(config, {
16+
webpackConfigPath,
17+
}),
18+
})
719
})
820

921
config.env.reactDevtools = true
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const debug = require('debug')('@cypress/react')
2+
3+
const addCypressToWebpackEslintRulesInPlace = (webpackOptions) => {
4+
const globalsToAdd = ['cy', 'Cypress', 'before', 'after', 'context']
5+
6+
if (webpackOptions.module && Array.isArray(webpackOptions.module.rules)) {
7+
const modulePre = webpackOptions.module.rules.find(
8+
(rule) => rule.enforce === 'pre',
9+
)
10+
11+
if (modulePre && Array.isArray(modulePre.use)) {
12+
debug('found Pre block %o', modulePre)
13+
14+
const useEslintLoader = modulePre.use.find(
15+
(use) => use.loader && use.loader.includes('eslint-loader'),
16+
)
17+
18+
if (useEslintLoader) {
19+
debug('found useEslintLoader %o', useEslintLoader)
20+
21+
if (useEslintLoader.options) {
22+
if (Array.isArray(useEslintLoader.options.globals)) {
23+
debug(
24+
'adding cy to existing globals %o',
25+
useEslintLoader.options.globals,
26+
)
27+
28+
useEslintLoader.options.globals.push(...globalsToAdd)
29+
} else {
30+
debug('setting new list of globals with cy and Cypress')
31+
useEslintLoader.options.globals = globalsToAdd
32+
}
33+
34+
debug('updated globals %o', useEslintLoader.options.globals)
35+
} else {
36+
debug('eslint loader does not have options ⚠️')
37+
}
38+
}
39+
}
40+
}
41+
}
42+
43+
module.exports = { addCypressToWebpackEslintRulesInPlace }

npm/react/plugins/utils/add-image-redirect.js npm/react/plugins/utils/webpack-helpers.js

+39-1
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,42 @@ function addImageRedirect (webpackOptions) {
5959
}
6060
}
6161

62-
module.exports = { addImageRedirect }
62+
/**
63+
* Finds the ModuleScopePlugin plugin and adds given folder
64+
* to that list. This allows react-scripts to import folders
65+
* outside of the default "/src" folder.
66+
* WARNING modifies the input webpack options argument.
67+
* @see https://github.com/bahmutov/cypress-react-unit-test/issues/289
68+
* @param {string} folderName Folder to add, should be absolute
69+
*/
70+
function allowModuleSourceInPlace (folderName, webpackOptions) {
71+
if (!folderName) {
72+
return
73+
}
74+
75+
if (!webpackOptions.resolve) {
76+
return
77+
}
78+
79+
if (!Array.isArray(webpackOptions.resolve.plugins)) {
80+
return
81+
}
82+
83+
const moduleSourcePlugin = webpackOptions.resolve.plugins.find((plugin) => {
84+
return Array.isArray(plugin.appSrcs)
85+
})
86+
87+
if (!moduleSourcePlugin) {
88+
debug('cannot find module source plugin')
89+
90+
return
91+
}
92+
93+
debug('found module source plugin %o', moduleSourcePlugin)
94+
if (!moduleSourcePlugin.appSrcs.includes(folderName)) {
95+
moduleSourcePlugin.appSrcs.push(folderName)
96+
debug('added folder %s to allowed sources', folderName)
97+
}
98+
}
99+
100+
module.exports = { addImageRedirect, allowModuleSourceInPlace }

0 commit comments

Comments
 (0)