mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-06 23:10:22 -05:00
Merge remote-tracking branch 'origin/develop' into 7.0-release
This commit is contained in:
@@ -7,6 +7,7 @@ build
|
||||
.publish
|
||||
_test-output
|
||||
cypress.zip
|
||||
.babel-cache
|
||||
|
||||
# from extension
|
||||
Cached Theme.pak
|
||||
|
||||
+1
-1
@@ -1108,7 +1108,7 @@ jobs:
|
||||
|
||||
npm-react:
|
||||
<<: *defaults
|
||||
parallelism: 9
|
||||
parallelism: 8
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
exports['babel installation template correctly generates plugins config 1'] = `
|
||||
const preprocessor = require('@cypress/react/plugins/babel');
|
||||
const injectDevServer = require('@cypress/react/plugins/babel');
|
||||
|
||||
const something = require("something");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config);
|
||||
injectDevServer(on, config);
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
`
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
exports['Injects guessed next.js template cypress.json'] = `
|
||||
const preprocessor = require("@cypress/react/plugins/next");
|
||||
const injectDevServer = require("@cypress/react/plugins/next");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config);
|
||||
injectDevServer(on, config);
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
|
||||
`
|
||||
|
||||
exports['Injects guessed next.js template plugins/index.js'] = `
|
||||
const preprocessor = require("@cypress/react/plugins/next");
|
||||
const injectDevServer = require("@cypress/react/plugins/next");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config);
|
||||
injectDevServer(on, config);
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
|
||||
@@ -24,20 +24,20 @@ import "@cypress/react/support";
|
||||
`
|
||||
|
||||
exports['Injected overridden webpack template cypress.json'] = `
|
||||
const preprocessor = require("@cypress/react/plugins/react-scripts");
|
||||
const injectDevServer = require("@cypress/react/plugins/react-scripts");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config);
|
||||
injectDevServer(on, config);
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
|
||||
`
|
||||
|
||||
exports['Injected overridden webpack template plugins/index.js'] = `
|
||||
const preprocessor = require("@cypress/react/plugins/react-scripts");
|
||||
const injectDevServer = require("@cypress/react/plugins/react-scripts");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config);
|
||||
injectDevServer(on, config);
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
exports['next.js install template correctly generates plugins config 1'] = `
|
||||
const preprocessor = require('@cypress/react/plugins/next');
|
||||
const injectDevServer = require('@cypress/react/plugins/next');
|
||||
|
||||
const something = require("something");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config);
|
||||
injectDevServer(on, config);
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
`
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
exports['create-react-app install template correctly generates plugins config 1'] = `
|
||||
const preprocessor = require('@cypress/react/plugins/react-scripts');
|
||||
const injectDevServer = require('@cypress/react/plugins/react-scripts');
|
||||
|
||||
const something = require("something");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config);
|
||||
injectDevServer(on, config);
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
`
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
exports['webpack-file install template correctly generates plugins config when webpack config path is missing 1'] = `
|
||||
const preprocessor = require("@cypress/react/plugins/load-webpack");
|
||||
const injectDevServer = require("@cypress/react/plugins/load-webpack");
|
||||
|
||||
const something = require("something");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// TODO replace with valid webpack config path
|
||||
config.env.webpackFilename = './webpack.config.js';
|
||||
preprocessor(on, config);
|
||||
injectDevServer(on, config);
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
`
|
||||
|
||||
exports['webpack-file install template correctly generates plugins config when webpack config path is provided 1'] = `
|
||||
const preprocessor = require("@cypress/react/plugins/load-webpack");
|
||||
const injectDevServer = require("@cypress/react/plugins/load-webpack");
|
||||
|
||||
const something = require("something");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
config.env.webpackFilename = 'config/webpack.config.js';
|
||||
preprocessor(on, config);
|
||||
injectDevServer(on, config);
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
`
|
||||
|
||||
@@ -1,32 +1,40 @@
|
||||
exports['rollup-file install template correctly generates plugins config when webpack config path is missing 1'] = `
|
||||
const rollupPreprocessor = require("@bahmutov/cy-rollup");
|
||||
const path = require("path");
|
||||
|
||||
const {
|
||||
startDevServer
|
||||
} = require("@cypress/rollup-dev-server");
|
||||
|
||||
const something = require("something");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
on('file:preprocessor', rollupPreprocessor({
|
||||
// TODO replace with valid rollup config path
|
||||
configFile: 'rollup.config.js'
|
||||
}));
|
||||
|
||||
require('@cypress/code-coverage/task')(on, config);
|
||||
|
||||
on("dev-server:start", async options => {
|
||||
return startDevServer({
|
||||
options,
|
||||
// TODO replace with valid rollup config path
|
||||
rollupConfig: path.resolve(__dirname, 'rollup.config.js')
|
||||
});
|
||||
});
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
`
|
||||
|
||||
exports['rollup-file install template correctly generates plugins config when webpack config path is provided 1'] = `
|
||||
const rollupPreprocessor = require("@bahmutov/cy-rollup");
|
||||
const path = require("path");
|
||||
|
||||
const {
|
||||
startDevServer
|
||||
} = require("@cypress/rollup-dev-server");
|
||||
|
||||
const something = require("something");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
on('file:preprocessor', rollupPreprocessor({
|
||||
configFile: 'config/rollup.config.js'
|
||||
}));
|
||||
|
||||
require('@cypress/code-coverage/task')(on, config);
|
||||
|
||||
on("dev-server:start", async options => {
|
||||
return startDevServer({
|
||||
options,
|
||||
rollupConfig: path.resolve(__dirname, 'config/rollup.config.js')
|
||||
});
|
||||
});
|
||||
return config; // IMPORTANT to return the config object
|
||||
};
|
||||
`
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
exports['vue webpack-file install template correctly generates plugins for vue-cli-service 1'] = `
|
||||
const preprocessor = require("@cypress/vue/dist/plugins/webpack");
|
||||
const injectDevServer = require("@cypress/vue/dist/plugins/webpack");
|
||||
|
||||
const something = require("something");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config); // IMPORTANT return the config object
|
||||
injectDevServer(on, config); // IMPORTANT return the config object
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
exports['webpack-options template correctly generates plugins config 1'] = `
|
||||
const webpackPreprocessor = require("@cypress/webpack-preprocessor");
|
||||
const path = require("path");
|
||||
|
||||
const {
|
||||
startDevServer
|
||||
} = require("@cypress/webpack-dev-Server");
|
||||
|
||||
const something = require("something");
|
||||
|
||||
@@ -15,13 +19,13 @@ module.exports = (on, config) => {
|
||||
publicPath: '/',
|
||||
chunkFilename: '[name].bundle.js'
|
||||
},
|
||||
// TODO: update with valid configuration for your app
|
||||
// TODO: update with valid configuration for your components
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\\.(js|jsx|mjs|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
options: { ...babelConfig,
|
||||
cacheDirectory: path.resolve(__dirname, '..', '..', '.babel-cache')
|
||||
options: {
|
||||
cacheDirectory: path.resolve(__dirname, '.babel-cache')
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ export const BabelTemplate: Template = {
|
||||
'webpack',
|
||||
)} to bundle the components for testing.`,
|
||||
recommendedComponentFolder: 'cypress/component',
|
||||
dependencies: ['@cypress/webpack-dev-server'],
|
||||
dependencies: ['webpack', '@cypress/webpack-dev-server'],
|
||||
getExampleUrl: () => 'https://github.com/cypress-io/cypress/tree/develop/npm/react/examples/babel',
|
||||
getPluginsCodeAst: () => {
|
||||
return {
|
||||
Require: babel.template.ast('const preprocessor = require(\'@cypress/react/plugins/babel\')'),
|
||||
Require: babel.template.ast('const injectDevServer = require(\'@cypress/react/plugins/babel\')'),
|
||||
ModuleExportsBody: babel.template.ast([
|
||||
'preprocessor(on, config)',
|
||||
'injectDevServer(on, config)',
|
||||
'return config // IMPORTANT to return the config object',
|
||||
].join('\n'), { preserveComments: true }),
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ export const NextTemplate: Template = {
|
||||
dependencies: ['@cypress/webpack-dev-server'],
|
||||
getPluginsCodeAst: () => {
|
||||
return {
|
||||
Require: babel.template.ast('const preprocessor = require(\'@cypress/react/plugins/next\')'),
|
||||
Require: babel.template.ast('const injectDevServer = require(\'@cypress/react/plugins/next\')'),
|
||||
ModuleExportsBody: babel.template.ast([
|
||||
'preprocessor(on, config)',
|
||||
'injectDevServer(on, config)',
|
||||
'return config // IMPORTANT to return the config object',
|
||||
].join('\n'), { preserveComments: true }),
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ export const ReactScriptsTemplate: Template = {
|
||||
},
|
||||
getPluginsCodeAst: () => {
|
||||
return {
|
||||
Require: babel.template.ast('const preprocessor = require(\'@cypress/react/plugins/react-scripts\')'),
|
||||
Require: babel.template.ast('const injectDevServer = require(\'@cypress/react/plugins/react-scripts\')'),
|
||||
ModuleExportsBody: babel.template.ast([
|
||||
'preprocessor(on, config)',
|
||||
'injectDevServer(on, config)',
|
||||
'return config // IMPORTANT to return the config object',
|
||||
].join('\n'), { preserveComments: true }),
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ export const WebpackTemplate: Template<{ webpackConfigPath: string }> = {
|
||||
: './webpack.config.js'
|
||||
|
||||
return {
|
||||
Require: babel.template.ast('const preprocessor = require("@cypress/react/plugins/load-webpack")'),
|
||||
Require: babel.template.ast('const injectDevServer = require("@cypress/react/plugins/load-webpack")'),
|
||||
ModuleExportsBody: babel.template.ast([
|
||||
includeWarnComment
|
||||
? '// TODO replace with valid webpack config path'
|
||||
: '',
|
||||
`config.env.webpackFilename = '${webpackConfigPath}'`,
|
||||
'preprocessor(on, config)',
|
||||
'injectDevServer(on, config)',
|
||||
'return config // IMPORTANT to return the config object',
|
||||
].join('\n'), { preserveComments: true }),
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export function extractRollupConfigPathFromScript (script: string) {
|
||||
|
||||
export const RollupTemplate: Template<{ rollupConfigPath: string }> = {
|
||||
message:
|
||||
'It looks like you have custom `rollup.config.js`. We can use it to bundle the components for testing.',
|
||||
'It looks like you have custom `rollup.config.js`. We can use it to bundle components for testing.',
|
||||
getExampleUrl: () => {
|
||||
return 'https://github.com/cypress-io/cypress/tree/develop/npm/react/examples/rollup'
|
||||
},
|
||||
@@ -34,19 +34,21 @@ export const RollupTemplate: Template<{ rollupConfigPath: string }> = {
|
||||
: 'rollup.config.js'
|
||||
|
||||
return {
|
||||
Require: babel.template.ast('const rollupPreprocessor = require("@bahmutov/cy-rollup")'),
|
||||
Require: babel.template.ast([
|
||||
'const path = require("path")',
|
||||
'const { startDevServer } = require("@cypress/rollup-dev-server")',
|
||||
].join('\n')),
|
||||
ModuleExportsBody: babel.template.ast([
|
||||
`on(`,
|
||||
` 'file:preprocessor',`,
|
||||
` rollupPreprocessor({`,
|
||||
`on("dev-server:start", async (options) => {`,
|
||||
` return startDevServer({`,
|
||||
` options,`,
|
||||
includeWarnComment
|
||||
? ' // TODO replace with valid rollup config path'
|
||||
? ' // TODO replace with valid rollup config path'
|
||||
: '',
|
||||
` configFile: '${rollupConfigPath}',`,
|
||||
` }),`,
|
||||
`)`,
|
||||
` rollupConfig: path.resolve(__dirname, '${rollupConfigPath}'),`,
|
||||
` })`,
|
||||
`})`,
|
||||
``,
|
||||
`require('@cypress/code-coverage/task')(on, config)`,
|
||||
`return config // IMPORTANT to return the config object`,
|
||||
].join('\n'), { preserveComments: true }),
|
||||
}
|
||||
|
||||
+2
-2
@@ -9,13 +9,13 @@ const webpackConfig = {
|
||||
publicPath: '/',
|
||||
chunkFilename: '[name].bundle.js',
|
||||
},
|
||||
// TODO: update with valid configuration for your app
|
||||
// TODO: update with valid configuration for your components
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx|mjs|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
options: { ...babelConfig, cacheDirectory: path.resolve(__dirname, '..', '..', '.babel-cache') },
|
||||
options: { cacheDirectory: path.resolve(__dirname, '.babel-cache') },
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
@@ -12,10 +12,13 @@ export const WebpackOptions: Template = {
|
||||
},
|
||||
test: () => ({ success: false }),
|
||||
recommendedComponentFolder: 'src',
|
||||
dependencies: ['@cypress/webpack-dev-server'],
|
||||
dependencies: ['webpack', '@cypress/webpack-dev-server'],
|
||||
getPluginsCodeAst: () => {
|
||||
return {
|
||||
Require: babel.template.ast('const webpackPreprocessor = require("@cypress/webpack-preprocessor")'),
|
||||
Require: babel.template.ast([
|
||||
'const path = require("path")',
|
||||
'const { startDevServer } = require("@cypress/webpack-dev-Server")',
|
||||
].join('\n')),
|
||||
ModuleExportsBody: babel.template.ast(
|
||||
fs.readFileSync(path.resolve(__dirname, 'webpack-options-module-exports.template.js'), { encoding: 'utf-8' }),
|
||||
{ preserveComments: true },
|
||||
|
||||
@@ -11,10 +11,10 @@ export const VueCliTemplate: Template = {
|
||||
getPluginsCodeAst: () => {
|
||||
return {
|
||||
Require: babel.template.ast(
|
||||
'const preprocessor = require("@cypress/vue/dist/plugins/webpack");',
|
||||
'const injectDevServer = require("@cypress/vue/dist/plugins/webpack");',
|
||||
),
|
||||
ModuleExportsBody: babel.template.ast([
|
||||
'preprocessor(on, config);',
|
||||
'injectDevServer(on, config);',
|
||||
'// IMPORTANT return the config object',
|
||||
'return config',
|
||||
].join('\n'), { preserveComments: true }),
|
||||
|
||||
@@ -61,7 +61,9 @@ const webpackConfig = {
|
||||
* @type Cypress.PluginConfig
|
||||
*/
|
||||
module.exports = (on, config) => {
|
||||
on('dev-server:start', (options) => startDevServer({ options, webpackConfig, disableLazyCompilation: false }))
|
||||
on('dev-server:start', (options) => {
|
||||
return startDevServer({ options, webpackConfig, disableLazyCompilation: false })
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"description": "Testing component accessibility",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/react": "file:../../dist",
|
||||
|
||||
@@ -27,9 +27,9 @@ describe('NextJS page', () => {
|
||||
})
|
||||
|
||||
it('can be tested with real .getInitialProps call', () => {
|
||||
IndexPage.getInitialProps().then((props) => {
|
||||
mount(<IndexPage {...props} />)
|
||||
})
|
||||
cy
|
||||
.wrap(IndexPage.getServerSideProps())
|
||||
.then((props) => mount(<IndexPage {...props} />))
|
||||
|
||||
cy.contains(
|
||||
'`.getInitialProps()` was called and passed props to this component',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const preprocessor = require('@cypress/react/plugins/next')
|
||||
const injectNextDevServer = require('@cypress/react/plugins/next')
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config)
|
||||
injectNextDevServer(on, config)
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -6,20 +6,21 @@
|
||||
"build": "next build",
|
||||
"build:static": "next build && next out",
|
||||
"check-coverage": "check-coverage components/Search.jsx && check-coverage pages/index.js && check-coverage pages/router.js",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"dev": "next",
|
||||
"only-cove red": "only-covered components/Search.jsx pages/index.js pages/router.js",
|
||||
"only-covered": "only-covered components/Search.jsx pages/index.js pages/router.js",
|
||||
"start": "next start",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/react": "file:../../dist",
|
||||
"@mdx-js/loader": "^1.6.16",
|
||||
"@next/mdx": "^9.5.3",
|
||||
"@next/mdx": "10.0.7",
|
||||
"@zeit/next-sass": "^1.0.1",
|
||||
"check-code-coverage": "1.9.2",
|
||||
"cypress-circleci-reporter": "0.2.0",
|
||||
"next": "^9.5.3"
|
||||
"next": "10.0.7",
|
||||
"webpack": "^4.44.2"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ function IndexPage ({ asyncProp }) {
|
||||
)
|
||||
}
|
||||
|
||||
IndexPage.getInitialProps = async (ctx) => {
|
||||
return { asyncProp: true }
|
||||
IndexPage.getServerSideProps = () => {
|
||||
return Promise.resolve({ asyncProp: true })
|
||||
}
|
||||
|
||||
export default IndexPage
|
||||
|
||||
+741
-1885
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,6 @@
|
||||
import React from 'react'
|
||||
import App from '../../src/App'
|
||||
import { mount } from '@cypress/react'
|
||||
import * as calc from '../../src/calc'
|
||||
import * as child from '../../src/Child'
|
||||
|
||||
describe('App', () => {
|
||||
it('renders learn react link', () => {
|
||||
@@ -17,28 +15,4 @@ describe('App', () => {
|
||||
mount(<div>JSX</div>)
|
||||
cy.contains('JSX')
|
||||
})
|
||||
|
||||
it('controls the random number by stubbing named import', () => {
|
||||
// we are stubbing "getRandomNumber" exported by "calc.js"
|
||||
// and imported into "App.js" and called.
|
||||
cy.stub(calc, 'getRandomNumber')
|
||||
.as('lucky')
|
||||
.returns(777)
|
||||
|
||||
mount(<App />)
|
||||
cy.contains('.random', '777')
|
||||
cy.get('@lucky').should('be.calledOnce')
|
||||
})
|
||||
|
||||
it('stubs an imported child component', () => {
|
||||
cy.stub(child, 'Child')
|
||||
.as('child')
|
||||
.returns(<div className="mock-child">Mock child component</div>)
|
||||
|
||||
mount(<App />)
|
||||
// App component rendered our mock child component!
|
||||
cy.contains('Mock child component')
|
||||
cy.get('@child').should('have.been.calledTwice')
|
||||
cy.get('.mock-child').should('have.length', 2)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"check-coverage": "check-coverage src/App.js src/calc.js src/Child.js",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"only-covered": "only-covered src/App.js src/calc.js src/Child.js",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/react": "file:../../dist",
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"check-coverage": "check-coverage src/App.js src/calc.js src/Child.js src/services.js src/RemotePizza.js cypress/fixtures/add.js",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"only-covered": "only-covered src/App.js src/calc.js src/Child.js src/services.js src/RemotePizza.js cypress/fixtures/add.js",
|
||||
"start": "react-scripts start",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/react": "file:../../dist",
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
import React from 'react'
|
||||
import App from './App'
|
||||
import { mount } from '@cypress/react'
|
||||
import * as calc from './calc'
|
||||
import * as Child from './Child'
|
||||
|
||||
describe('App', () => {
|
||||
it('renders learn react link', () => {
|
||||
@@ -12,28 +10,6 @@ describe('App', () => {
|
||||
cy.contains(/Learn React/)
|
||||
})
|
||||
|
||||
it('controls the random number by stubbing named import', () => {
|
||||
// we are stubbing "getRandomNumber" exported by "calc.js"
|
||||
// and imported into "App.js" and called.
|
||||
cy.stub(calc, 'getRandomNumber').returns(777)
|
||||
mount(<App />)
|
||||
cy.contains('.random', '777')
|
||||
|
||||
// getRandomNumber was also used by the Child component
|
||||
// let's check that it was mocked too
|
||||
cy.contains('.child', 'Real child component, random 777')
|
||||
})
|
||||
|
||||
it('can mock the child component', () => {
|
||||
// Child component we want to stub is the default export
|
||||
cy.stub(Child, 'default')
|
||||
.as('child')
|
||||
.returns(<div className="mock-child">Mock Child component</div>)
|
||||
|
||||
mount(<App />)
|
||||
cy.contains('.mock-child', 'Mock Child')
|
||||
})
|
||||
|
||||
describe('loading .env variables', () => {
|
||||
it('loads the REACT_APP_ variables from .env file', () => {
|
||||
mount(<App />)
|
||||
|
||||
@@ -3,8 +3,11 @@ import React from 'react'
|
||||
import App from './App'
|
||||
import { mount } from '@cypress/react'
|
||||
|
||||
describe('static resources', () => {
|
||||
// NOTE: This doesn't work for some reason, but the font and svg is loading properly
|
||||
describe.skip('static resources', () => {
|
||||
const findResource = (name) => {
|
||||
console.log(window.document)
|
||||
|
||||
return window.performance
|
||||
.getEntriesByType('resource')
|
||||
.find((item) => item.name.endsWith(name))
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
const rollupPreprocessor = require('@bahmutov/cy-rollup')
|
||||
// @ts-check
|
||||
const path = require('path')
|
||||
const { startDevServer } = require('@cypress/rollup-dev-server')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
on(
|
||||
'file:preprocessor',
|
||||
rollupPreprocessor({
|
||||
configFile: 'rollup.config.js',
|
||||
}),
|
||||
)
|
||||
on('dev-server:start', async (options) => {
|
||||
return startDevServer({
|
||||
options,
|
||||
rollupConfig: path.resolve(__dirname, '..', '..', 'rollup.config.js'),
|
||||
})
|
||||
})
|
||||
|
||||
require('@cypress/code-coverage/task')(on, config)
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "7.4.4",
|
||||
@@ -13,10 +13,12 @@
|
||||
"@babel/preset-react": "7.0.0",
|
||||
"@babel/preset-typescript": "7.10.4",
|
||||
"@cypress/react": "file:../../dist",
|
||||
"@cypress/rollup-dev-server": "file:../../../rollup-dev-server/dist",
|
||||
"@rollup/plugin-babel": "5.2.1",
|
||||
"@rollup/plugin-commonjs": "15.1.0",
|
||||
"@rollup/plugin-node-resolve": "9.0.0",
|
||||
"@rollup/plugin-replace": "2.3.3",
|
||||
"cypress-circleci-reporter": "0.2.0"
|
||||
"cypress-circleci-reporter": "0.2.0",
|
||||
"rollup": "2.40.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,10 @@ export default [
|
||||
plugins: [
|
||||
nodeResolve({ extensions }),
|
||||
// make sure that this is required to process @cypress/react code
|
||||
commonjs(),
|
||||
commonjs({ exclude: 'src/**' }),
|
||||
replace({ 'process.env.NODE_ENV': JSON.stringify('development') }),
|
||||
babel({
|
||||
// ...babelOptions,
|
||||
exclude: /node_modules/,
|
||||
babelHelpers: 'inline',
|
||||
extensions,
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
"noEmit": true,
|
||||
"target": "esnext",
|
||||
"types": ["cypress"],
|
||||
// ⚠️ required only for demo purposes, remove from code
|
||||
"paths": {
|
||||
"@cypress/react": ["../../lib/index.ts"]
|
||||
}
|
||||
"moduleResolution": "node",
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["./src/**.ts*"]
|
||||
|
||||
@@ -721,6 +721,9 @@
|
||||
"@cypress/react@file:../../dist":
|
||||
version "0.0.0"
|
||||
|
||||
"@cypress/rollup-dev-server@file:../../../rollup-dev-server/dist":
|
||||
version "0.0.0"
|
||||
|
||||
"@oozcitak/dom@1.15.8":
|
||||
version "1.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@oozcitak/dom/-/dom-1.15.8.tgz#0c0c7bb54cfdaadc07fd637913e706101721d15d"
|
||||
@@ -1031,6 +1034,11 @@ fs.realpath@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||
|
||||
fsevents@~2.3.1:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
@@ -1292,6 +1300,13 @@ resolve@^1.17.0:
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
rollup@2.40.0:
|
||||
version "2.40.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.40.0.tgz#efc218eaede7ab590954df50f96195188999c304"
|
||||
integrity sha512-WiOGAPbXoHu+TOz6hyYUxIksOwsY/21TRWoO593jgYt8mvYafYqQl+axaA8y1z2HFazNUUrsMSjahV2A6/2R9A==
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.1"
|
||||
|
||||
semver@7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// load Webpack file preprocessor that comes with this plugin
|
||||
// https://github.com/bahmutov/cypress-react-unit-test#install
|
||||
const preprocessor = require('@cypress/react/plugins/load-webpack')
|
||||
const injectWebpackDevServer = require('@cypress/react/plugins/load-webpack')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// point at the webpack config file at the root of the project
|
||||
config.env.webpackFilename = 'webpack.config.js'
|
||||
preprocessor(on, config)
|
||||
injectWebpackDevServer(on, config, {
|
||||
webpackFilename: 'webpack.config.js',
|
||||
})
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"check-coverage": "check-coverage src/App.tsx",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"only-covered": "only-covered src/App.tsx",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"dependencies": {
|
||||
"sass-loader": "10.0.2"
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"check-coverage": "check-coverage src/App.js",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"only-covered": "only-covered src/App.js",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/react": "file:../../dist",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// load file preprocessor that comes with this plugin
|
||||
// https://github.com/bahmutov/cypress-react-unit-test#install
|
||||
const preprocessor = require('@cypress/react/plugins/react-scripts')
|
||||
const injectReactScriptsDevServer = require('@cypress/react/plugins/react-scripts')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config)
|
||||
injectReactScriptsDevServer(on, config)
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"scripts": {
|
||||
"build:css": "tailwindcss build src/styles/tailwind.css -o src/styles/main.generated.css",
|
||||
"precy:open": "npm run build:css",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"pretest": "npm run build:css",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/react": "file:../../dist",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// let's bundle spec files and the components they include using
|
||||
// the same bundling settings as the project by loading .babelrc
|
||||
// https://github.com/bahmutov/cypress-react-unit-test#install
|
||||
const preprocessor = require('@cypress/react/plugins/babelrc')
|
||||
const injectWebpackWithBabelDevServer = require('@cypress/react/plugins/babel')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config)
|
||||
injectWebpackWithBabelDevServer(on, config)
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"description": "Component testing for TypeScript projects using Babel config",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.4.5",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// let's bundle spec files and the components they include using
|
||||
// the same bundling settings as the project by loading .babelrc
|
||||
// https://github.com/bahmutov/cypress-react-unit-test#install
|
||||
const preprocessor = require('@cypress/react/plugins/babelrc')
|
||||
const injectWebpackWithBabelDevServer = require('@cypress/react/plugins/babel')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
preprocessor(on, config)
|
||||
injectWebpackWithBabelDevServer(on, config)
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"description": "Component testing for projects using Babel config",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.4.5",
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
"author": "Amith Raravi <amith.raravi@gmail.com>",
|
||||
"scripts": {
|
||||
"build": "react-scripts build",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"docker:run": "docker run -it -v $PWD/../..:/e2e -w /e2e/examples/visual-sudoku cypress/included:4.5.0",
|
||||
"eject": "react-scripts eject",
|
||||
"start": "react-scripts start",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"description": "Visual diffing for component testing using Applittols",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@applitools/eyes-cypress": "3.14.0",
|
||||
|
||||
@@ -17,7 +17,7 @@ describe('Chart', () => {
|
||||
name: 'firefox',
|
||||
},
|
||||
],
|
||||
// ignore "cy.eyes*" commands when using "cypress open"
|
||||
// ignore "cy.eyes*" commands when using "cypress open-ct"
|
||||
isDisabled: Cypress.config('isInteractive'),
|
||||
})
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"description": "Visual component testing using Happo.io",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"test": "node ../../../../scripts/cypress run",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"test": "node ../../../../scripts/cypress run-ct",
|
||||
"test:happo": "../../node_modules/.bin/happo-cypress -- npm test"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"description": "Visual diffing for component testing",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/react": "file:../../dist",
|
||||
|
||||
@@ -6,7 +6,8 @@ import * as calc from './calc'
|
||||
import * as ChildComponent from './ChildComponent'
|
||||
|
||||
describe('Mocking', () => {
|
||||
it('named getRandomNumber imported in the child component', () => {
|
||||
// NOTE: need babel commonjs plugin to mock named imports
|
||||
it.skip('named getRandomNumber imported in the child component', () => {
|
||||
cy.stub(calc, 'getRandomNumber')
|
||||
.as('lucky')
|
||||
.returns(777)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
module.exports = (on, config) => {
|
||||
// from the root of the project (folder with cypress.json file)
|
||||
config.env.webpackFilename = 'webpack.config.js'
|
||||
require('@cypress/react/plugins/load-webpack')(on, config)
|
||||
require('@cypress/react/plugins/load-webpack')(on, config, {
|
||||
// from the root of the project (folder with cypress.json file)
|
||||
webpackFilename: 'webpack.config.js',
|
||||
})
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"check-coverage": "check-coverage Test.js calc.js ParentComponent.js ChildComponent.js",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"only-covered": "only-covered Test.js calc.js ParentComponent.js ChildComponent.js",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/react": "file:../../dist",
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
module.exports = {
|
||||
'presets': ['@babel/preset-env', '@babel/preset-react'],
|
||||
'plugins': ['@babel/plugin-proposal-class-properties'],
|
||||
// place plugins for Cypress tests into "test" environment
|
||||
// so that production bundle is not instrumented
|
||||
env: {
|
||||
'test': {
|
||||
'plugins': [
|
||||
// during Cypress tests we want to instrument source code
|
||||
// to get code coverage from tests
|
||||
'babel-plugin-istanbul',
|
||||
// we also want to export ES6 modules as objects
|
||||
// to allow mocking named imports
|
||||
[
|
||||
'@babel/plugin-transform-modules-commonjs',
|
||||
{
|
||||
'loose': true,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,36 +1,36 @@
|
||||
// @ts-check
|
||||
const webpackPreprocessor = require('@cypress/webpack-preprocessor')
|
||||
const path = require('path')
|
||||
const { startDevServer } = require('@cypress/webpack-dev-server')
|
||||
const babelConfig = require('../../babel.config')
|
||||
|
||||
// Cypress Webpack preprocessor includes Babel env preset,
|
||||
// but to transpile JSX code we need to add Babel React preset
|
||||
module.exports = (on, config) => {
|
||||
// @ts-ignore
|
||||
const opts = webpackPreprocessor.defaultOptions
|
||||
const babelLoader = opts.webpackOptions.module.rules[0].use[0]
|
||||
|
||||
// add React preset to be able to transpile JSX
|
||||
babelLoader.options.presets.push(require.resolve('@babel/preset-react'))
|
||||
|
||||
// We can also push Babel istanbul plugin to instrument the code on the fly
|
||||
// and get code coverage reports from component tests (optional)
|
||||
if (!babelLoader.options.plugins) {
|
||||
babelLoader.options.plugins = []
|
||||
/** @type import("webpack").Configuration */
|
||||
const webpackConfig = {
|
||||
resolve: {
|
||||
extensions: ['.js', '.ts', '.jsx', '.tsx'],
|
||||
},
|
||||
mode: 'development',
|
||||
devtool: false,
|
||||
output: {
|
||||
publicPath: '/',
|
||||
chunkFilename: '[name].bundle.js',
|
||||
},
|
||||
// TODO: update with valid configuration for your components
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx|mjs|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
options: { ...babelConfig, cacheDirectory: path.resolve(__dirname, '.babel-cache') },
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
babelLoader.options.plugins.push(require.resolve('babel-plugin-istanbul'))
|
||||
|
||||
// in order to mock named imports, need to include a plugin
|
||||
babelLoader.options.plugins.push([
|
||||
require.resolve('@babel/plugin-transform-modules-commonjs'),
|
||||
{
|
||||
loose: true,
|
||||
},
|
||||
])
|
||||
|
||||
// add code coverage plugin
|
||||
require('@cypress/code-coverage/task')(on, config)
|
||||
|
||||
on('file:preprocessor', webpackPreprocessor(opts))
|
||||
process.env.BABEL_ENV = 'test' // this is required to load commonjs babel plugin
|
||||
on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))
|
||||
|
||||
// if adding code coverage, important to return updated config
|
||||
return config
|
||||
|
||||
@@ -4,12 +4,20 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"check-coverage": "check-coverage Test.js calc.js ParentComponent.js ChildComponent.js",
|
||||
"cy:open": "node ../../../../scripts/cypress open",
|
||||
"cy:open": "node ../../../../scripts/cypress open-ct",
|
||||
"only-covered": "only-covered Test.js calc.js ParentComponent.js ChildComponent.js",
|
||||
"test": "node ../../../../scripts/cypress run"
|
||||
"test": "node ../../../../scripts/cypress run-ct"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.4.5",
|
||||
"@babel/plugin-proposal-class-properties": "7.4.4",
|
||||
"@babel/plugin-transform-modules-commonjs": "7.13.8",
|
||||
"@babel/preset-env": "7.4.5",
|
||||
"@babel/preset-react": "7.0.0",
|
||||
"@cypress/react": "file:../../dist",
|
||||
"@cypress/webpack-dev-server": "file:../../../webpack-dev-server",
|
||||
"babel-loader": "8.2.2",
|
||||
"babel-plugin-istanbul": "6.0.0",
|
||||
"cypress-circleci-reporter": "0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+8
-13
@@ -19,7 +19,8 @@
|
||||
"dependencies": {
|
||||
"@cypress/webpack-preprocessor": "0.0.0-development",
|
||||
"debug": "4.3.2",
|
||||
"find-webpack": "2.2.1"
|
||||
"find-webpack": "2.2.1",
|
||||
"find-yarn-workspace-root": "2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.4.5",
|
||||
@@ -129,6 +130,11 @@
|
||||
],
|
||||
"unpkg": "dist/cypress-react.browser.js",
|
||||
"module": "dist/cypress-react.esm-bundler.js",
|
||||
"workspaces": {
|
||||
"nohoist": [
|
||||
"cypress-circleci-reporter"
|
||||
]
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@babel/core": {
|
||||
"optional": true
|
||||
@@ -156,18 +162,7 @@
|
||||
"access": "public"
|
||||
},
|
||||
"ciJobs": [
|
||||
"npm-react",
|
||||
"npm-react-axe",
|
||||
"npm-react-next",
|
||||
"npm-react-cra",
|
||||
"npm-react-cra-folder",
|
||||
"npm-react-rollup",
|
||||
"npm-react-sass-ts",
|
||||
"npm-react-snapshots",
|
||||
"npm-react-tailwind",
|
||||
"npm-react-percy",
|
||||
"npm-react-webpack-file",
|
||||
"npm-react-webpack-options"
|
||||
"npm-react"
|
||||
],
|
||||
"standard": {
|
||||
"globals": [
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// @ts-check
|
||||
// uses webpack to load your .babelrc file
|
||||
const debug = require('debug')('@cypress/react')
|
||||
|
||||
const webpackConfigLoadsBabel = {
|
||||
resolve: {
|
||||
extensions: ['.js', '.ts', '.jsx', '.tsx'],
|
||||
},
|
||||
mode: 'development',
|
||||
devtool: false,
|
||||
output: {
|
||||
publicPath: '/',
|
||||
chunkFilename: '[name].bundle.js',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx|mjs|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = (on, config) => {
|
||||
debug('env object %o', config.env)
|
||||
|
||||
debug('initial environments %o', {
|
||||
BABEL_ENV: process.env.BABEL_ENV,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
})
|
||||
|
||||
const nodeEnvironment = 'test'
|
||||
|
||||
if (!process.env.BABEL_ENV) {
|
||||
debug('setting BABEL_ENV to %s', nodeEnvironment)
|
||||
process.env.BABEL_ENV = nodeEnvironment
|
||||
}
|
||||
|
||||
if (!process.env.NODE_ENV) {
|
||||
debug('setting NODE_ENV to %s', nodeEnvironment)
|
||||
process.env.NODE_ENV = nodeEnvironment
|
||||
}
|
||||
|
||||
debug('environments %o', {
|
||||
BABEL_ENV: process.env.BABEL_ENV,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
})
|
||||
|
||||
return webpackConfigLoadsBabel
|
||||
}
|
||||
@@ -1 +1,12 @@
|
||||
module.exports = require('../babelrc')
|
||||
const getBabelWebpackConfig = require('./getBabelWebpackConfig')
|
||||
const { startDevServer } = require('@cypress/webpack-dev-server')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
on('dev-server:start', async (options) => {
|
||||
return startDevServer({ options, webpackConfig: getBabelWebpackConfig(on, config) })
|
||||
})
|
||||
|
||||
config.env.reactDevtools = true
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
// @ts-check
|
||||
// uses webpack to load your .babelrc file
|
||||
const debug = require('debug')('@cypress/react')
|
||||
const webpackPreprocessor = require('@cypress/webpack-preprocessor')
|
||||
const { addImageRedirect } = require('../utils/add-image-redirect')
|
||||
|
||||
const wpPreprocessorOptions = {
|
||||
...webpackPreprocessor.defaultOptions,
|
||||
}
|
||||
|
||||
wpPreprocessorOptions.webpackOptions.resolve = {
|
||||
extensions: ['.js', '.ts', '.jsx', '.tsx', '.json'],
|
||||
}
|
||||
|
||||
wpPreprocessorOptions.webpackOptions.module.rules[0].test = /\.(jsx|tsx|js|ts)?$/
|
||||
|
||||
// note: modifies the input object
|
||||
function enableBabelrc (webpackOptions) {
|
||||
if (!Array.isArray(webpackOptions.module.rules)) {
|
||||
debug('could not find webpack module rules %o', webpackOptions.module)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const jsCodeRule = webpackOptions.module.rules[0]
|
||||
|
||||
debug('js code rule %o', jsCodeRule)
|
||||
if (!jsCodeRule) {
|
||||
debug('could not get first rule %o', webpackOptions.module)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const jsCodeRuleUses = jsCodeRule.use
|
||||
|
||||
if (!Array.isArray(jsCodeRuleUses)) {
|
||||
debug('js code rule use is not an array %o', jsCodeRuleUses)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const babelLoaderOptions = jsCodeRuleUses[0].options
|
||||
|
||||
debug('Babel options %o', babelLoaderOptions)
|
||||
if (!babelLoaderOptions) {
|
||||
debug('Hmm, no babel loader options %o', jsCodeRuleUses)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// by deleting our default presets list
|
||||
// we allow Babel loader to load the presets and plugins
|
||||
// from the project's .babelrc file
|
||||
delete babelLoaderOptions.presets
|
||||
delete babelLoaderOptions.plugins
|
||||
|
||||
debug('babel loader options %o', babelLoaderOptions)
|
||||
}
|
||||
|
||||
module.exports = (config) => {
|
||||
debug('env object %o', config.env)
|
||||
|
||||
debug('initial environments %o', {
|
||||
BABEL_ENV: process.env.BABEL_ENV,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
})
|
||||
|
||||
const nodeEnvironment = 'test'
|
||||
|
||||
if (!process.env.BABEL_ENV) {
|
||||
debug('setting BABEL_ENV to %s', nodeEnvironment)
|
||||
process.env.BABEL_ENV = nodeEnvironment
|
||||
}
|
||||
|
||||
if (!process.env.NODE_ENV) {
|
||||
debug('setting NODE_ENV to %s', nodeEnvironment)
|
||||
process.env.NODE_ENV = nodeEnvironment
|
||||
}
|
||||
|
||||
debug('environments %o', {
|
||||
BABEL_ENV: process.env.BABEL_ENV,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
})
|
||||
|
||||
const coverageIsDisabled =
|
||||
config && config.env && config.env.coverage === false
|
||||
|
||||
debug('coverage is disabled? %o', { coverageIsDisabled })
|
||||
|
||||
enableBabelrc(wpPreprocessorOptions.webpackOptions)
|
||||
debug('webpack options %o', wpPreprocessorOptions.webpackOptions)
|
||||
|
||||
addImageRedirect(wpPreprocessorOptions.webpackOptions)
|
||||
|
||||
return webpackPreprocessor(wpPreprocessorOptions)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
const filePreprocessor = require('./file-preprocessor')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
on('file:preprocessor', filePreprocessor(config))
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
return config
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
// @ts-check
|
||||
const debug = require('debug')('@cypress/react')
|
||||
const findWebpack = require('find-webpack')
|
||||
const webpackPreprocessor = require('@cypress/webpack-preprocessor')
|
||||
const { getTranspileFolders } = require('../utils/get-transpile-folders')
|
||||
const { addImageRedirect } = require('../utils/add-image-redirect')
|
||||
|
||||
const getWebpackPreprocessorOptions = (opts) => {
|
||||
debug('top level opts %o', opts)
|
||||
|
||||
const webpackOptions = findWebpack.getWebpackOptions()
|
||||
|
||||
if (!webpackOptions) {
|
||||
console.error('⚠️ Could not find Webpack options, using defaults')
|
||||
|
||||
return webpackPreprocessor.defaultOptions
|
||||
}
|
||||
|
||||
debug('webpack options: %o', webpackOptions)
|
||||
findWebpack.cleanForCypress(opts, webpackOptions)
|
||||
debug('cleaned webpack options: %o', webpackOptions)
|
||||
|
||||
addImageRedirect(webpackOptions)
|
||||
|
||||
const options = {
|
||||
webpackOptions,
|
||||
watchOptions: {},
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
module.exports = (config) => {
|
||||
debug('env object %o', config.env)
|
||||
|
||||
const coverageIsDisabled =
|
||||
config && config.env && config.env.coverage === false
|
||||
|
||||
debug('coverage is disabled? %o', { coverageIsDisabled })
|
||||
debug('component test folder: %s', config.componentFolder)
|
||||
debug('fixtures folder', config.fixturesFolder)
|
||||
debug('integration test folder: %s', config.integrationFolder)
|
||||
|
||||
const opts = {
|
||||
reactScripts: true,
|
||||
addFolderToTranspile: getTranspileFolders(config),
|
||||
coverage: !coverageIsDisabled,
|
||||
// insert Babel plugin to mock named imports
|
||||
looseModules: true,
|
||||
}
|
||||
const preprocessorOptions = getWebpackPreprocessorOptions(opts)
|
||||
|
||||
debug('final webpack options %o', preprocessorOptions.webpackOptions)
|
||||
|
||||
return webpackPreprocessor(preprocessorOptions)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
const filePreprocessor = require('./file-preprocessor')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
on('file:preprocessor', filePreprocessor(config))
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
return config
|
||||
}
|
||||
@@ -1,59 +1,35 @@
|
||||
// @ts-check
|
||||
const path = require('path')
|
||||
const debug = require('debug')('@cypress/react')
|
||||
const webpackPreprocessor = require('@cypress/webpack-preprocessor')
|
||||
const findWebpack = require('find-webpack')
|
||||
const { getTranspileFolders } = require('../utils/get-transpile-folders')
|
||||
const { addImageRedirect } = require('../utils/add-image-redirect')
|
||||
const { startDevServer } = require('@cypress/webpack-dev-server')
|
||||
const tryLoadWebpackConfig = require('../utils/tryLoadWebpackConfig')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
const webpackFilename = config.env && config.env.webpackFilename
|
||||
/** @type {(config: Cypress.PluginConfigOptions, path: string) => string} */
|
||||
function normalizeWebpackPath (config, webpackConfigPath) {
|
||||
return path.isAbsolute(webpackConfigPath)
|
||||
? webpackConfigPath
|
||||
: path.resolve(config.projectRoot, webpackConfigPath)
|
||||
}
|
||||
|
||||
if (!webpackFilename) {
|
||||
throw new Error(
|
||||
'Could not find "webpackFilename" option in Cypress env variables',
|
||||
)
|
||||
/**
|
||||
* Injects dev-server based on the webpack config file.
|
||||
*
|
||||
* **Important:** `webpackFilename` path is relative to the project root (cypress.json location)
|
||||
* @type {(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions, options: { webpackFilename: string }) => Cypress.PluginConfigOptions}
|
||||
*/
|
||||
function injectWebpackDevServer (on, config, { webpackFilename }) {
|
||||
const webpackConfig = tryLoadWebpackConfig(normalizeWebpackPath(config, webpackFilename))
|
||||
|
||||
if (!webpackConfig) {
|
||||
throw new Error(`Can not load webpack config from path ${webpackFilename}.`)
|
||||
}
|
||||
|
||||
debug('got webpack config filename %s', webpackFilename)
|
||||
const resolved = path.resolve(webpackFilename)
|
||||
on('dev-server:start', async (options) => {
|
||||
return startDevServer({ options, webpackConfig })
|
||||
})
|
||||
|
||||
debug('resolved webpack at %s', resolved)
|
||||
config.env.reactDevtools = true
|
||||
|
||||
const webpackOptions = findWebpack.tryLoadingWebpackConfig(resolved)
|
||||
|
||||
if (!webpackOptions) {
|
||||
throw new Error(`Could not load webpack config from ${resolved}`)
|
||||
}
|
||||
|
||||
debug('webpack options: %o', webpackOptions)
|
||||
|
||||
const coverageIsDisabled =
|
||||
config && config.env && config.env.coverage === false
|
||||
|
||||
debug('coverage is disabled? %o', { coverageIsDisabled })
|
||||
|
||||
const opts = {
|
||||
reactScripts: true,
|
||||
addFolderToTranspile: getTranspileFolders(config),
|
||||
coverage: !coverageIsDisabled,
|
||||
// insert Babel plugin to mock named imports
|
||||
looseModules: true,
|
||||
}
|
||||
|
||||
findWebpack.cleanForCypress(opts, webpackOptions)
|
||||
debug('cleaned webpack options: %o', webpackOptions)
|
||||
|
||||
addImageRedirect(webpackOptions)
|
||||
|
||||
const options = {
|
||||
webpackOptions,
|
||||
watchOptions: {},
|
||||
}
|
||||
|
||||
on('file:preprocessor', webpackPreprocessor(options))
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
return config
|
||||
}
|
||||
|
||||
module.exports = injectWebpackDevServer
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
// @ts-check
|
||||
const debug = require('debug')('@cypress/react')
|
||||
const loadConfig = require('next/dist/next-server/server/config').default
|
||||
const getNextJsBaseWebpackConfig = require('next/dist/build/webpack-config')
|
||||
.default
|
||||
const webpackPreprocessor = require('@cypress/webpack-preprocessor')
|
||||
const findWebpack = require('find-webpack')
|
||||
|
||||
async function getNextWebpackConfig (config) {
|
||||
const coverageIsDisabled =
|
||||
config && config.env && config.env.coverage === false
|
||||
|
||||
debug('coverage is disabled? %o', { coverageIsDisabled })
|
||||
|
||||
const nextConfig = await loadConfig('development', config.projectRoot)
|
||||
const nextWebpackConfig = await getNextJsBaseWebpackConfig(
|
||||
config.projectRoot,
|
||||
{
|
||||
buildId: `@cypress/react-${Math.random().toString()}`,
|
||||
config: nextConfig,
|
||||
dev: false,
|
||||
isServer: false,
|
||||
pagesDir: config.projectRoot,
|
||||
entrypoints: {},
|
||||
rewrites: [],
|
||||
},
|
||||
)
|
||||
|
||||
debug('resolved next.js webpack options: %o', nextWebpackConfig)
|
||||
// Using mode over `dev` true to get rid of next's react-refresh-plugin wrapping
|
||||
// We need do not need all the HMR and webpack dev middlewares as well
|
||||
nextWebpackConfig.mode = 'development'
|
||||
|
||||
findWebpack.cleanForCypress(
|
||||
{
|
||||
coverage: !coverageIsDisabled,
|
||||
// insert Babel plugin to mock named imports
|
||||
// disable because causes an error with double definitions
|
||||
// https://github.com/bahmutov/@cypress/react/issues/439
|
||||
looseModules: false,
|
||||
},
|
||||
nextWebpackConfig,
|
||||
)
|
||||
|
||||
debug('final webpack options %o', nextWebpackConfig)
|
||||
|
||||
return nextWebpackConfig
|
||||
}
|
||||
|
||||
let webpackConfigCache = null
|
||||
|
||||
/** Resolving next.js webpack and all config with plugin takes long, so cache the webpack configuration */
|
||||
async function getCachedWebpackPreprocessor (config) {
|
||||
// ⛔️ ⛔️ Comment this `if` for debugging
|
||||
if (webpackConfigCache !== null) {
|
||||
return webpackConfigCache
|
||||
}
|
||||
|
||||
const webpackOptions = await getNextWebpackConfig(config)
|
||||
|
||||
webpackConfigCache = webpackPreprocessor({ webpackOptions })
|
||||
|
||||
debug('created and cached webpack preprocessor based on next.config.js')
|
||||
|
||||
return webpackConfigCache
|
||||
}
|
||||
|
||||
module.exports = (config) => {
|
||||
return async (fileEvent) => {
|
||||
const preprocessor = await getCachedWebpackPreprocessor(config)
|
||||
|
||||
return preprocessor(fileEvent)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// @ts-check
|
||||
const debug = require('debug')('@cypress/react')
|
||||
const loadConfig = require('next/dist/next-server/server/config').default
|
||||
const getNextJsBaseWebpackConfig = require('next/dist/build/webpack-config').default
|
||||
|
||||
async function getNextWebpackConfig (config) {
|
||||
const nextConfig = await loadConfig('development', config.projectRoot)
|
||||
const nextWebpackConfig = await getNextJsBaseWebpackConfig(
|
||||
config.projectRoot,
|
||||
{
|
||||
buildId: `@cypress/react-${Math.random().toString()}`,
|
||||
config: nextConfig,
|
||||
dev: true,
|
||||
isServer: false,
|
||||
pagesDir: config.projectRoot,
|
||||
entrypoints: {},
|
||||
rewrites: [],
|
||||
},
|
||||
)
|
||||
|
||||
debug('resolved next.js webpack config %o', nextWebpackConfig)
|
||||
|
||||
return nextWebpackConfig
|
||||
}
|
||||
|
||||
let webpackConfigCache = null
|
||||
|
||||
/** Resolving next.js webpack and all config with plugin takes long, so cache the webpack configuration */
|
||||
module.exports = async function findNextWebpackConfig (config) {
|
||||
// ⛔️ ⛔️ Comment this `if` for debugging
|
||||
if (webpackConfigCache !== null) {
|
||||
return webpackConfigCache
|
||||
}
|
||||
|
||||
webpackConfigCache = await getNextWebpackConfig(config)
|
||||
debug('created and cached webpack preprocessor based on next.config.js', webpackConfigCache)
|
||||
|
||||
return webpackConfigCache
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
const filePreprocessor = require('./file-preprocessor')
|
||||
const { startDevServer } = require('@cypress/webpack-dev-server')
|
||||
const findNextWebpackConfig = require('./findNextWebpackConfig')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
on('file:preprocessor', filePreprocessor(config))
|
||||
on('dev-server:start', async (options) => {
|
||||
return startDevServer({ options, webpackConfig: await findNextWebpackConfig(config) })
|
||||
})
|
||||
|
||||
config.env.reactDevtools = true
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
// @ts-check
|
||||
const debug = require('debug')('@cypress/react')
|
||||
const tryLoadWebpackConfig = require('../utils/tryLoadWebpackConfig')
|
||||
const { getTranspileFolders } = require('../utils/get-transpile-folders')
|
||||
const { addFolderToBabelLoaderTranspileInPlace } = require('../utils/babel-helpers')
|
||||
|
||||
/**
|
||||
* Finds the ModuleScopePlugin plugin and adds given folder
|
||||
* to that list. This allows react-scripts to import folders
|
||||
* outside of the default "/src" folder.
|
||||
* WARNING modifies the input webpack options argument.
|
||||
* @see https://github.com/bahmutov/cypress-react-unit-test/issues/289
|
||||
* @param {string} folderName Folder to add, should be absolute
|
||||
*/
|
||||
function allowModuleSourceInPlace (folderName, webpackOptions) {
|
||||
if (!folderName) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!webpackOptions.resolve) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!Array.isArray(webpackOptions.resolve.plugins)) {
|
||||
return
|
||||
}
|
||||
|
||||
const moduleSourcePlugin = webpackOptions.resolve.plugins.find((plugin) => {
|
||||
return Array.isArray(plugin.appSrcs)
|
||||
})
|
||||
|
||||
if (!moduleSourcePlugin) {
|
||||
debug('cannot find module source plugin')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
debug('found module source plugin %o', moduleSourcePlugin)
|
||||
if (!moduleSourcePlugin.appSrcs.includes(folderName)) {
|
||||
moduleSourcePlugin.appSrcs.push(folderName)
|
||||
debug('added folder %s to allowed sources', folderName)
|
||||
}
|
||||
}
|
||||
|
||||
const addCypressToWebpackEslintRulesInPlace = (webpackOptions) => {
|
||||
const globalsToAdd = ['cy', 'Cypress', 'before', 'after', 'context']
|
||||
|
||||
if (webpackOptions.module && Array.isArray(webpackOptions.module.rules)) {
|
||||
const modulePre = webpackOptions.module.rules.find(
|
||||
(rule) => rule.enforce === 'pre',
|
||||
)
|
||||
|
||||
if (modulePre && Array.isArray(modulePre.use)) {
|
||||
debug('found Pre block %o', modulePre)
|
||||
|
||||
const useEslintLoader = modulePre.use.find(
|
||||
(use) => use.loader && use.loader.includes('eslint-loader'),
|
||||
)
|
||||
|
||||
if (useEslintLoader) {
|
||||
debug('found useEslintLoader %o', useEslintLoader)
|
||||
|
||||
if (useEslintLoader.options) {
|
||||
if (Array.isArray(useEslintLoader.options.globals)) {
|
||||
debug(
|
||||
'adding cy to existing globals %o',
|
||||
useEslintLoader.options.globals,
|
||||
)
|
||||
|
||||
useEslintLoader.options.globals.push(...globalsToAdd)
|
||||
} else {
|
||||
debug('setting new list of globals with cy and Cypress')
|
||||
useEslintLoader.options.globals = globalsToAdd
|
||||
}
|
||||
|
||||
debug('updated globals %o', useEslintLoader.options.globals)
|
||||
} else {
|
||||
debug('eslint loader does not have options ⚠️')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function findReactScriptsWebpackConfig (config) {
|
||||
const webpackConfig = tryLoadWebpackConfig('react-scripts/config/webpack.config')
|
||||
|
||||
if (!webpackConfig) {
|
||||
throw new Error('⚠️ Could not find Webpack options for react-scripts. Make sure that you have react-scripts module available.')
|
||||
}
|
||||
|
||||
// because for react-scripts user doesn't have direct access to webpack webpackConfig
|
||||
// we must implicitly inject everything required to run tests
|
||||
addCypressToWebpackEslintRulesInPlace(webpackConfig)
|
||||
|
||||
getTranspileFolders(config).forEach((cypressFolder) => {
|
||||
allowModuleSourceInPlace(cypressFolder, webpackConfig)
|
||||
addFolderToBabelLoaderTranspileInPlace(cypressFolder, webpackConfig)
|
||||
})
|
||||
|
||||
debug('resolved webpack config: %o', webpackConfig)
|
||||
|
||||
return webpackConfig
|
||||
}
|
||||
+7
-2
@@ -1,7 +1,12 @@
|
||||
const filePreprocessor = require('../cra-v3/file-preprocessor')
|
||||
const { startDevServer } = require('@cypress/webpack-dev-server')
|
||||
const findReactScriptsWebpackConfig = require('./findReactScriptsWebpackConfig')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
on('file:preprocessor', filePreprocessor(config))
|
||||
on('dev-server:start', async (options) => {
|
||||
return startDevServer({ options, webpackConfig: findReactScriptsWebpackConfig(config) })
|
||||
})
|
||||
|
||||
config.env.reactDevtools = true
|
||||
|
||||
// IMPORTANT to return the config object
|
||||
// with the any changed environment variables
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
// @ts-check
|
||||
const debug = require('debug')('find-webpack')
|
||||
const path = require('path')
|
||||
|
||||
/**
|
||||
* Returns true if the provided loader path includes "babel-loader".
|
||||
* Uses current OS path separator to split the loader path correctly.
|
||||
*/
|
||||
const isBabelLoader = (loaderPath) => {
|
||||
if (!loaderPath) {
|
||||
return false
|
||||
}
|
||||
|
||||
const loaderPathParts = loaderPath.split(path.sep)
|
||||
|
||||
return loaderPathParts.some((pathPart) => pathPart === 'babel-loader')
|
||||
}
|
||||
|
||||
const findBabelRule = (webpackOptions) => {
|
||||
if (!webpackOptions) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!webpackOptions.module) {
|
||||
return
|
||||
}
|
||||
|
||||
debug('webpackOptions.module %o', webpackOptions.module)
|
||||
if (!Array.isArray(webpackOptions.module.rules)) {
|
||||
return
|
||||
}
|
||||
|
||||
const oneOfRule = webpackOptions.module.rules.find((rule) => {
|
||||
return Array.isArray(rule.oneOf)
|
||||
})
|
||||
|
||||
if (!oneOfRule) {
|
||||
debug('could not find oneOfRule')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
debug('looking through oneOf rules')
|
||||
debug('oneOfRule.oneOf %o', oneOfRule.oneOf)
|
||||
oneOfRule.oneOf.forEach((rule) => debug('rule %o', rule))
|
||||
|
||||
const babelRule = oneOfRule.oneOf.find(
|
||||
(rule) => rule.loader && isBabelLoader(rule.loader),
|
||||
)
|
||||
|
||||
return babelRule
|
||||
}
|
||||
|
||||
// see https://github.com/bahmutov/find-webpack/issues/7
|
||||
const findBabelLoaderRule = (webpackOptions) => {
|
||||
debug('looking for babel-loader rule')
|
||||
if (!webpackOptions) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!webpackOptions.module) {
|
||||
return
|
||||
}
|
||||
|
||||
debug('webpackOptions.module %o', webpackOptions.module)
|
||||
if (!Array.isArray(webpackOptions.module.rules)) {
|
||||
return
|
||||
}
|
||||
|
||||
debug('webpack module rules')
|
||||
webpackOptions.module.rules.forEach((rule) => {
|
||||
debug('rule %o', rule)
|
||||
})
|
||||
|
||||
const babelRule = webpackOptions.module.rules.find(
|
||||
(rule) => rule.loader === 'babel-loader',
|
||||
)
|
||||
|
||||
if (!babelRule) {
|
||||
debug('could not find babel rule')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
debug('found Babel rule that applies to %s', babelRule.test.toString())
|
||||
|
||||
return babelRule
|
||||
}
|
||||
|
||||
const findBabelLoaderUseRule = (webpackOptions) => {
|
||||
debug('looking for babel-loader rule with use property')
|
||||
if (!webpackOptions) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!webpackOptions.module) {
|
||||
return
|
||||
}
|
||||
|
||||
debug('webpackOptions.module %o', webpackOptions.module)
|
||||
if (!Array.isArray(webpackOptions.module.rules)) {
|
||||
return
|
||||
}
|
||||
|
||||
debug('webpack module rules')
|
||||
webpackOptions.module.rules.forEach((rule) => {
|
||||
debug('rule %o', rule)
|
||||
})
|
||||
|
||||
const isBabelLoader = (rule) => rule.use && rule.use.loader === 'babel-loader'
|
||||
const isNextBabelLoader = (rule) => {
|
||||
return rule.use && rule.use.loader === 'next-babel-loader'
|
||||
}
|
||||
|
||||
const babelRule = webpackOptions.module.rules.find(
|
||||
(rule) => isBabelLoader(rule) || isNextBabelLoader(rule),
|
||||
)
|
||||
|
||||
if (!babelRule) {
|
||||
debug('could not find babel rule')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
debug('found Babel use rule that applies to %s', babelRule.test.toString())
|
||||
|
||||
return babelRule.use
|
||||
}
|
||||
|
||||
const findBabelRuleWrap = (webpackOptions) => {
|
||||
let babelRule = findBabelRule(webpackOptions)
|
||||
|
||||
if (!babelRule) {
|
||||
debug('could not find Babel rule using oneOf')
|
||||
babelRule = findBabelLoaderRule(webpackOptions)
|
||||
}
|
||||
|
||||
if (!babelRule) {
|
||||
debug('could not find Babel rule directly')
|
||||
babelRule = findBabelLoaderUseRule(webpackOptions)
|
||||
}
|
||||
|
||||
if (!babelRule) {
|
||||
debug('could not find Babel rule')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
return babelRule
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches through the given Webpack config file to find Babel
|
||||
* loader and its options, then returns the plugins array reference.
|
||||
* If not found, returns undefined.
|
||||
* @returns {Array|undefined}
|
||||
*/
|
||||
const findBabelPlugins = (webpackOptions) => {
|
||||
const babelRule = findBabelRuleWrap(webpackOptions)
|
||||
|
||||
if (!babelRule) {
|
||||
debug('could not find Babel rule')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
debug('babel rule %o', babelRule)
|
||||
if (!babelRule.options) {
|
||||
debug('babel rule does not have options, inserting')
|
||||
babelRule.options = {}
|
||||
}
|
||||
|
||||
if (!Array.isArray(babelRule.options.plugins)) {
|
||||
debug('babel rule options does not have plugins, inserting')
|
||||
babelRule.options.plugins = []
|
||||
}
|
||||
|
||||
return babelRule.options.plugins
|
||||
}
|
||||
|
||||
const addFolderToBabelLoaderTranspileInPlace = (addFolderToTranspile, webpackOptions) => {
|
||||
if (!addFolderToTranspile) {
|
||||
debug('no extra folder to transpile using Babel')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
debug(
|
||||
'trying to transpile additional folder %s using Babel',
|
||||
addFolderToTranspile,
|
||||
)
|
||||
|
||||
const babelRule = findBabelRuleWrap(webpackOptions)
|
||||
|
||||
if (!babelRule) {
|
||||
debug('could not find Babel rule')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
debug('babel rule %o', babelRule)
|
||||
|
||||
if (!babelRule.include) {
|
||||
debug('could not find Babel include condition')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof babelRule.include === 'string') {
|
||||
babelRule.include = [babelRule.include]
|
||||
}
|
||||
|
||||
if (babelRule.include.includes(addFolderToTranspile)) {
|
||||
// do not double include the same folder
|
||||
debug('babel includes rule for folder %s', addFolderToTranspile)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
babelRule.include.push(addFolderToTranspile)
|
||||
debug('added folder %s to babel rules', addFolderToTranspile)
|
||||
}
|
||||
|
||||
module.exports = { findBabelRuleWrap, addFolderToBabelLoaderTranspileInPlace, findBabelPlugins }
|
||||
@@ -0,0 +1,40 @@
|
||||
// @ts-check
|
||||
const debug = require('debug')('@cypress/react')
|
||||
|
||||
/** @type {(configPath: string) => null | import('webpack').Configuration } */
|
||||
module.exports = function tryLoadWebpackConfig (webpackConfigPath) {
|
||||
debug('trying to load webpack config from %s', webpackConfigPath)
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
const envName = 'test'
|
||||
|
||||
// @ts-expect-error override env is possible
|
||||
process.env.NODE_ENV = envName
|
||||
process.env.BABEL_ENV = envName
|
||||
|
||||
try {
|
||||
let webpackOptions = require(webpackConfigPath)
|
||||
|
||||
if (webpackOptions.default) {
|
||||
// we probably loaded TS file
|
||||
debug('loaded webpack options has .default - taking that as the config')
|
||||
webpackOptions = webpackOptions.default
|
||||
}
|
||||
|
||||
if (typeof webpackOptions === 'function') {
|
||||
debug('calling webpack function with environment "%s"', envName)
|
||||
webpackOptions = webpackOptions('development')
|
||||
}
|
||||
|
||||
debug('webpack options: %o', webpackOptions)
|
||||
|
||||
return webpackOptions
|
||||
} catch (err) {
|
||||
debug('could not load react-scripts webpack')
|
||||
debug('error %s', err.message)
|
||||
debug(err)
|
||||
|
||||
console.error(err)
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
+11
-9
@@ -12,7 +12,7 @@ const REACT_PROJECTS_FOR_CI = [
|
||||
'/examples/react-scripts-folder',
|
||||
'/examples/using-babel-typescript',
|
||||
'/examples/webpack-options',
|
||||
'/examples/rollup',
|
||||
// '/examples/rollup',
|
||||
'/examples/sass-and-ts',
|
||||
]
|
||||
|
||||
@@ -20,8 +20,10 @@ const runTests = async (dir) => {
|
||||
try {
|
||||
chdir(dir)
|
||||
|
||||
console.log(`Running yarn install in project ${dir}`)
|
||||
await execa('yarn', ['install', '--frozen-lockfile'], { stdout: 'inherit' })
|
||||
if (dir !== __dirname) {
|
||||
console.log(`Running yarn install in project ${dir}`)
|
||||
await execa('yarn', ['install', '--frozen-lockfile'], { stdout: 'inherit' })
|
||||
}
|
||||
|
||||
console.log(`Running yarn test in project ${dir}`)
|
||||
await execa('yarn', [
|
||||
@@ -32,14 +34,14 @@ const runTests = async (dir) => {
|
||||
`resultsDir=${testResultsDestination}`,
|
||||
], { stdout: 'inherit' })
|
||||
} catch (e) {
|
||||
if (!e.stdout) {
|
||||
// for unexpected errors, just log the entire thing.
|
||||
console.error(e)
|
||||
} else {
|
||||
if (e.stdout) {
|
||||
console.error(e.stdout)
|
||||
console.error(`Exiting with exit code ${e.exitCode}`)
|
||||
process.exit(e.exitCode)
|
||||
}
|
||||
|
||||
const exitCode = e.exitCode ? e.exitCode : 1
|
||||
|
||||
console.error(`Tests failed with exit code ${exitCode}`)
|
||||
process.exit(exitCode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-21
@@ -1,19 +1,11 @@
|
||||
export function setupHooks (rootId: string) {
|
||||
// @ts-ignore
|
||||
const isComponentSpec = () => true
|
||||
|
||||
export function setupHooks (unmount: (opts: { log: boolean }) => void) {
|
||||
// When running component specs, we cannot allow "cy.visit"
|
||||
// because it will wipe out our preparation work, and does not make much sense
|
||||
// thus we overwrite "cy.visit" to throw an error
|
||||
Cypress.Commands.overwrite('visit', (visit, ...args: any[]) => {
|
||||
if (isComponentSpec()) {
|
||||
throw new Error(
|
||||
'cy.visit from a component spec is not allowed',
|
||||
)
|
||||
} else {
|
||||
// allow regular visit to proceed
|
||||
return visit(...args)
|
||||
}
|
||||
Cypress.Commands.overwrite('visit', () => {
|
||||
throw new Error(
|
||||
'cy.visit from a component spec is not allowed',
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -22,10 +14,6 @@ export function setupHooks (rootId: string) {
|
||||
*
|
||||
*/
|
||||
function cleanupStyles () {
|
||||
if (!isComponentSpec()) {
|
||||
return
|
||||
}
|
||||
|
||||
const styles = document.body.querySelectorAll('style')
|
||||
|
||||
styles.forEach((styleElement) => {
|
||||
@@ -44,10 +32,7 @@ export function setupHooks (rootId: string) {
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
if (!isComponentSpec()) {
|
||||
return
|
||||
}
|
||||
|
||||
unmount({ log: false })
|
||||
cleanupStyles()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import { setupHooks } from './hooks'
|
||||
|
||||
const ROOT_ID = '__cy_root'
|
||||
|
||||
setupHooks(ROOT_ID)
|
||||
|
||||
/**
|
||||
* Inject custom style text or CSS file or 3rd party style resources
|
||||
*/
|
||||
@@ -50,7 +48,7 @@ export const mount = (jsx: React.ReactNode, options: MountOptions = {}) => {
|
||||
// @ts-ignore
|
||||
let logInstance: Cypress.Log
|
||||
|
||||
return unmount({ log: false })
|
||||
return cy
|
||||
.then(() => {
|
||||
if (options.log !== false) {
|
||||
logInstance = Cypress.log({
|
||||
@@ -318,3 +316,8 @@ export declare namespace Cypress {
|
||||
): Chainable<any>
|
||||
}
|
||||
}
|
||||
|
||||
// it is required to unmount component in beforeEach hook in order to provide a clean state inside test
|
||||
// because `mount` can be called after some preparation that can side effect unmount
|
||||
// @see npm/react/cypress/component/advanced/set-timeout-example/loading-indicator-spec.js
|
||||
setupHooks(unmount)
|
||||
|
||||
@@ -15,7 +15,7 @@ interface Options {
|
||||
export interface StartDevServer {
|
||||
/* this is the Cypress options object */
|
||||
options: Options
|
||||
rollupConfig?: RollupOptions // TODO: user's rollup configuration.
|
||||
rollupConfig?: RollupOptions | string
|
||||
}
|
||||
|
||||
export interface ResolvedDevServerConfig {
|
||||
|
||||
@@ -5,6 +5,10 @@ import { resolve } from 'path'
|
||||
import NollupDevMiddleware from 'nollup/lib/dev-middleware'
|
||||
import express from 'express'
|
||||
import { RollupOptions, Plugin } from 'rollup'
|
||||
import loadConfigFile from 'rollup/dist/loadConfigFile'
|
||||
import makeDebug from 'debug'
|
||||
|
||||
const debug = makeDebug('cypress:rollup-dev-server')
|
||||
|
||||
/**
|
||||
* Inject HMR runtime into each bundle, since Nollup
|
||||
@@ -37,12 +41,18 @@ interface NollupDevServer {
|
||||
}
|
||||
|
||||
export async function start (devServerOptions: StartDevServer): Promise<NollupDevServer> {
|
||||
const rollupConfigObj = typeof devServerOptions.rollupConfig === 'string'
|
||||
? await loadConfigFile(devServerOptions.rollupConfig).then((configResult) => configResult.options)
|
||||
: devServerOptions.rollupConfig
|
||||
|
||||
debug('Resolved rollup config options', rollupConfigObj)
|
||||
|
||||
const config = devServerOptions.options.specs
|
||||
.map<RollupOptions>((spec) => {
|
||||
return {
|
||||
...devServerOptions.rollupConfig,
|
||||
...rollupConfigObj,
|
||||
input: spec.absolute,
|
||||
plugins: (devServerOptions.rollupConfig.plugins || []).concat(
|
||||
plugins: (rollupConfigObj.plugins || []).concat(
|
||||
injectHmrPlugin(),
|
||||
),
|
||||
}
|
||||
|
||||
+2
-1
@@ -231,7 +231,8 @@
|
||||
"**/@ffmpeg-installer",
|
||||
"**/@ffmpeg-installer/**",
|
||||
"**/webpack-preprocessor/babel-loader",
|
||||
"**/webpack-batteries-included-preprocessor/ts-loader"
|
||||
"**/webpack-batteries-included-preprocessor/ts-loader",
|
||||
"**/cypress-circleci-reporter"
|
||||
]
|
||||
},
|
||||
"lint-staged": {
|
||||
|
||||
@@ -16604,6 +16604,13 @@ find-yarn-workspace-root@1.2.1, find-yarn-workspace-root@^1.2.1:
|
||||
fs-extra "^4.0.3"
|
||||
micromatch "^3.1.4"
|
||||
|
||||
find-yarn-workspace-root@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd"
|
||||
integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==
|
||||
dependencies:
|
||||
micromatch "^4.0.2"
|
||||
|
||||
find@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/find/-/find-0.3.0.tgz#4082e8fc8d8320f1a382b5e4f521b9bc50775cb8"
|
||||
|
||||
Reference in New Issue
Block a user