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

feat: support ct/e2e specific overrides in cypress.json #15526

Merged
merged 19 commits into from Mar 22, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions cli/schema/cypress.schema.json
Expand Up @@ -276,6 +276,16 @@
"type": "boolean",
"default": false,
"description": "Enables including elements within the shadow DOM when using querying commands (e.g. cy.get(), cy.find()). Can be set globally in cypress.json, per-suite or per-test in the test configuration object, or programmatically with Cypress.config()"
},
"component": {
"type": "object",
"default": {},
"description": "Any component runner specific overrides"
},
"e2e": {
"type": "object",
"default": {},
"description": "Any e2e runner specific overrides"
}
}
}
2 changes: 1 addition & 1 deletion cli/types/cypress.d.ts
Expand Up @@ -8,7 +8,7 @@ declare namespace Cypress {
type RequestBody = string | object
type ViewportOrientation = 'portrait' | 'landscape'
type PrevSubject = 'optional' | 'element' | 'document' | 'window'
type PluginConfig = (on: PluginEvents, config: PluginConfigOptions) => void | ConfigOptions | Promise<ConfigOptions>
type PluginConfig = (on: PluginEvents, config: PluginConfigOptions, mode: 'e2e' | 'component') => void | ConfigOptions | Promise<ConfigOptions>

interface CommandOptions {
prevSubject: boolean | PrevSubject | PrevSubject[]
Expand Down
7 changes: 5 additions & 2 deletions npm/create-cypress-tests/__snapshots__/babel.test.ts.js
Expand Up @@ -4,7 +4,10 @@ const injectDevServer = require('@cypress/react/plugins/babel');
const something = require("something");

module.exports = (on, config) => {
injectDevServer(on, config);
return config; // IMPORTANT to return the config object
if (config.mode === "component") {
injectDevServer(on, config);
}

return config; // IMPORTANT to return a config
};
`
Expand Up @@ -10,8 +10,11 @@ exports['Injected overridden webpack template plugins/index.js'] = `
const injectDevServer = require("@cypress/react/plugins/react-scripts");

module.exports = (on, config) => {
injectDevServer(on, config);
return config; // IMPORTANT to return the config object
if (config.mode === "component") {
injectDevServer(on, config);
}

return config; // IMPORTANT to return a config
};

`
Expand All @@ -32,8 +35,11 @@ exports['injects guessed next.js template plugins/index.js'] = `
const injectDevServer = require("@cypress/react/plugins/next");

module.exports = (on, config) => {
injectDevServer(on, config);
return config; // IMPORTANT to return the config object
if (config.mode === "component") {
injectDevServer(on, config);
}

return config; // IMPORTANT to return a config
};

`
7 changes: 5 additions & 2 deletions npm/create-cypress-tests/__snapshots__/next.test.ts.js
Expand Up @@ -4,7 +4,10 @@ const injectDevServer = require('@cypress/react/plugins/next');
const something = require("something");

module.exports = (on, config) => {
injectDevServer(on, config);
return config; // IMPORTANT to return the config object
if (config.mode === "component") {
injectDevServer(on, config);
}

return config; // IMPORTANT to return a config
};
`
Expand Up @@ -4,7 +4,10 @@ const injectDevServer = require('@cypress/react/plugins/react-scripts');
const something = require("something");

module.exports = (on, config) => {
injectDevServer(on, config);
return config; // IMPORTANT to return the config object
if (config.mode === "component") {
injectDevServer(on, config);
}

return config; // IMPORTANT to return a config
};
`
22 changes: 15 additions & 7 deletions npm/create-cypress-tests/__snapshots__/reactWebpackFile.test.ts.js
Expand Up @@ -4,10 +4,14 @@ 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';
injectDevServer(on, config);
return config; // IMPORTANT to return the config object
if (config.mode === "component") {
injectDevServer(on, config, {
// TODO replace with valid webpack config path
webpackFileName: './webpack.config.js'
});
}

return config; // IMPORTANT to return a config
};
`

Expand All @@ -17,8 +21,12 @@ const injectDevServer = require("@cypress/react/plugins/load-webpack");
const something = require("something");

module.exports = (on, config) => {
config.env.webpackFilename = 'config/webpack.config.js';
injectDevServer(on, config);
return config; // IMPORTANT to return the config object
if (config.mode === "component") {
injectDevServer(on, config, {
webpackFileName: 'config/webpack.config.js'
});
}

return config; // IMPORTANT to return a config
};
`
30 changes: 17 additions & 13 deletions npm/create-cypress-tests/__snapshots__/rollup.test.ts.js
Expand Up @@ -8,14 +8,16 @@ const {
const something = require("something");

module.exports = (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')
if (config.mode === "component") {
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
return config; // IMPORTANT to return the config object
}
};
`

Expand All @@ -29,12 +31,14 @@ const {
const something = require("something");

module.exports = (on, config) => {
on("dev-server:start", async options => {
return startDevServer({
options,
rollupConfig: path.resolve(__dirname, 'config/rollup.config.js')
if (config.mode === "component") {
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
return config; // IMPORTANT to return the config object
}
};
`
8 changes: 5 additions & 3 deletions npm/create-cypress-tests/__snapshots__/vite.test.ts.js
Expand Up @@ -6,8 +6,10 @@ const {
const something = require("something");

module.exports = (on, config) => {
on("dev-server:start", async options => startDevServer({
options
}));
if (config.mode === "component") {
on("dev-server:start", async options => startDevServer({
options
}));
}
};
`
10 changes: 6 additions & 4 deletions npm/create-cypress-tests/__snapshots__/vueCli.test.ts.js
Expand Up @@ -8,9 +8,11 @@ const webpackConfig = require("@vue/cli-service/webpack.config.js");
const something = require("something");

module.exports = (on, config) => {
on('dev-server:start', options => startDevServer({
options,
webpackConfig
}));
if (config.mode === "component") {
on('dev-server:start', options => startDevServer({
options,
webpackConfig
}));
}
};
`
20 changes: 12 additions & 8 deletions npm/create-cypress-tests/__snapshots__/vueWebpackFile.test.ts.js
Expand Up @@ -9,10 +9,12 @@ const webpackConfig = require("./webpack.config.js"); // TODO replace with valid
const something = require("something");

module.exports = (on, config) => {
on('dev-server:start', options => startDevServer({
options,
webpackConfig
}));
if (config.mode === "component") {
on('dev-server:start', options => startDevServer({
options,
webpackConfig
}));
}
};
`

Expand All @@ -26,9 +28,11 @@ const webpackConfig = require("build/webpack.config.js");
const something = require("something");

module.exports = (on, config) => {
on('dev-server:start', options => startDevServer({
options,
webpackConfig
}));
if (config.mode === "component") {
on('dev-server:start', options => startDevServer({
options,
webpackConfig
}));
}
};
`
54 changes: 28 additions & 26 deletions npm/create-cypress-tests/__snapshots__/webpackOptions.test.ts.js
Expand Up @@ -8,31 +8,33 @@ const {
const something = require("something");

module.exports = (on, config) => {
/** @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: {
cacheDirectory: path.resolve(__dirname, '.babel-cache')
}
}]
}
};
on('dev-server:start', options => startDevServer({
options,
webpackConfig
}));
if (config.mode === "component") {
/** @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: {
cacheDirectory: path.resolve(__dirname, '.babel-cache')
}
}]
}
};
on('dev-server:start', options => startDevServer({
options,
webpackConfig
}));
}
};
`
Expand Up @@ -6,8 +6,8 @@ describe('babel transform utils', () => {
context('Plugins config babel plugin', () => {
it('injects code into the plugins file based on ast', () => {
const plugin = createTransformPluginsFileBabelPlugin({
Require: babel.template.ast('require("something")'),
ModuleExportsBody: babel.template.ast('yey()'),
RequireAst: babel.template.ast('require("something")'),
IfComponentTestingPluginsAst: babel.template.ast('yey()'),
})

const output = babel.transformSync([
Expand All @@ -23,7 +23,10 @@ describe('babel transform utils', () => {
'',
'module.exports = (on, config) => {',
' on("do");',
' yey();',
'',
' if (config.mode === "component") {',
' yey();',
' }',
'};',
].join(`\n`))
})
Expand Down
Expand Up @@ -3,7 +3,13 @@ import * as fs from 'fs-extra'
import * as babel from '@babel/core'
import * as babelTypes from '@babel/types'

export type PluginsConfigAst = Record<'Require' | 'ModuleExportsBody', ReturnType<typeof babel.template.ast>>
type AST = ReturnType<typeof babel.template.ast>

export type PluginsConfigAst = {
RequireAst: AST
IfComponentTestingPluginsAst: AST
requiresReturnConfig?: true
}

function tryRequirePrettier () {
try {
Expand Down Expand Up @@ -48,11 +54,13 @@ async function transformFileViaPlugin (filePath: string, babelPlugin: babel.Plug
}
}

const returnConfigAst = babel.template.ast('return config; // IMPORTANT to return a config', { preserveComments: true })

export function createTransformPluginsFileBabelPlugin (ast: PluginsConfigAst): babel.PluginObj {
return {
visitor: {
Program: (path) => {
path.unshiftContainer('body', ast.Require)
path.unshiftContainer('body', ast.RequireAst)
},
Function: (path) => {
if (!babelTypes.isAssignmentExpression(path.parent)) {
Expand Down Expand Up @@ -80,7 +88,24 @@ export function createTransformPluginsFileBabelPlugin (ast: PluginsConfigAst): b
path.parent.right.params.push(babelTypes.identifier('config'))
}

path.get('body').pushContainer('body' as never, ast.ModuleExportsBody)
const statementToInject = Array.isArray(ast.IfComponentTestingPluginsAst)
? ast.IfComponentTestingPluginsAst
: [ast.IfComponentTestingPluginsAst]

const ifComponentMode = babelTypes.ifStatement(
babelTypes.binaryExpression(
'===',
babelTypes.identifier('config.mode'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lmiller1990 once you will came up with the final API – please edit this line

Suggested change
babelTypes.identifier('config.mode'),
babelTypes.identifier('config.testingType'),

And update snapshots to verify everything works as expected

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I can do it.

babelTypes.stringLiteral('component'),
),
babelTypes.blockStatement(statementToInject as babelTypes.Statement[] | babelTypes.Statement[]),
)

path.get('body').pushContainer('body' as never, ifComponentMode as babel.Node)

if (ast.requiresReturnConfig) {
path.get('body').pushContainer('body' as never, returnConfigAst)
}
}
},
},
Expand Down
Expand Up @@ -34,11 +34,11 @@ export const RollupTemplate: Template<{ rollupConfigPath: string }> = {
: 'rollup.config.js'

return {
Require: babel.template.ast([
RequireAst: babel.template.ast([
'const path = require("path")',
'const { startDevServer } = require("@cypress/rollup-dev-server")',
].join('\n')),
ModuleExportsBody: babel.template.ast([
IfComponentTestingPluginsAst: babel.template.ast([
`on("dev-server:start", async (options) => {`,
` return startDevServer({`,
` options,`,
Expand Down