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: create-cypress-tests auto-inject config #9116

3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ npm/webpack-preprocessor/examples/use-babelrc/cypress/integration/spec.js
/npm/react/bin/*
/npm/react/**/coverage
**/.next/**
/npm/create-cypress-tests/initial-template
/npm/create-cypress-tests/initial-template
/npm/create-cypress-tests/**/*.template.*
10 changes: 10 additions & 0 deletions npm/create-cypress-tests/__snapshots__/babel.test.ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
exports['babel installation template correctly generates plugins config 1'] = `
const preprocessor = require('@cypress/react/plugins/babel');

const something = require("something");

module.exports = (on, config) => {
preprocessor(on, config);
return config; // IMPORTANT to return the config object
};
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
exports['Injects guessed next.js template cypress.json'] = `
const preprocessor = require("@cypress/react/plugins/next");

module.exports = (on, config) => {
preprocessor(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");

module.exports = (on, config) => {
preprocessor(on, config);
return config; // IMPORTANT to return the config object
};

`

exports['Injects guessed next.js template support/index.js'] = `
import "@cypress/react/support";

`

exports['Injected overridden webpack template cypress.json'] = `
const preprocessor = require("@cypress/react/plugins/react-scripts");

module.exports = (on, config) => {
preprocessor(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");

module.exports = (on, config) => {
preprocessor(on, config);
return config; // IMPORTANT to return the config object
};

`

exports['Injected overridden webpack template support/index.js'] = `
import "./commands.js";
import "@cypress/react/support";

`
10 changes: 10 additions & 0 deletions npm/create-cypress-tests/__snapshots__/next.test.ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
exports['next.js install template correctly generates plugins config 1'] = `
const preprocessor = require('@cypress/react/plugins/next');

const something = require("something");

module.exports = (on, config) => {
preprocessor(on, config);
return config; // IMPORTANT to return the config object
};
`
10 changes: 10 additions & 0 deletions npm/create-cypress-tests/__snapshots__/react-scripts.test.ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
exports['create-react-app install template correctly generates plugins config 1'] = `
const preprocessor = require('@cypress/react/plugins/react-scripts');

const something = require("something");

module.exports = (on, config) => {
preprocessor(on, config);
return config; // IMPORTANT to return the config object
};
`
24 changes: 24 additions & 0 deletions npm/create-cypress-tests/__snapshots__/reactWebpackFile.test.ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +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 something = require("something");

module.exports = (on, config) => {
// TODO replace with valid webpack config path
config.env.webpackFilename = './webpack.config.js';
preprocessor(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 something = require("something");

module.exports = (on, config) => {
config.env.webpackFilename = 'config/webpack.config.js';
preprocessor(on, config);
return config; // IMPORTANT to return the config object
};
`
32 changes: 32 additions & 0 deletions npm/create-cypress-tests/__snapshots__/rollup.test.ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
exports['rollup-file install template correctly generates plugins config when webpack config path is missing 1'] = `
const rollupPreprocessor = require("@bahmutov/cy-rollup");

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);

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 something = require("something");

module.exports = (on, config) => {
on('file:preprocessor', rollupPreprocessor({
configFile: 'config/rollup.config.js'
}));

require('@cypress/code-coverage/task')(on, config);

return config; // IMPORTANT to return the config object
};
`
24 changes: 24 additions & 0 deletions npm/create-cypress-tests/__snapshots__/vueWebpackFile.test.ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
exports['vue webpack-file install template correctly generates plugins config when webpack config path is missing 1'] = `
const {
onFilePreprocessor
} = require('@cypress/vue/dist/preprocessor/webpack');

const something = require("something");

module.exports = (on, config) => {
// TODO replace with valid webpack config path
on('file:preprocessor', onFilePreprocessor('./webpack.config.js'));
};
`

exports['vue webpack-file install template correctly generates plugins config when webpack config path is provided 1'] = `
const {
onFilePreprocessor
} = require('@cypress/vue/dist/preprocessor/webpack');

const something = require("something");

module.exports = (on, config) => {
on('file:preprocessor', onFilePreprocessor('build/webpack.config.js'));
};
`
29 changes: 29 additions & 0 deletions npm/create-cypress-tests/__snapshots__/webpackOptions.test.ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
exports['webpack-options template correctly generates plugins config 1'] = `
const webpackPreprocessor = require("@cypress/webpack-preprocessor");

const something = require("something");

module.exports = (on, config) => {
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 = [];
}

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)); // if adding code coverage, important to return updated config

return config;
};
`
8 changes: 7 additions & 1 deletion npm/create-cypress-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@
"scripts": {
"build": "yarn prepare-example && tsc -p ./tsconfig.json && chmod +x dist/src/index.js && node scripts/example copy-to ./dist/initial-template",
"prepare-example": "node scripts/example copy-to ./initial-template",
"test": "cross-env TS_NODE_PROJECT=./tsconfig.test.json mocha --config .mocharc.json './src/**/*.test.ts'"
"test": "cross-env TS_NODE_PROJECT=./tsconfig.test.json mocha --config .mocharc.json './src/**/*.test.ts'",
"test:watch": "yarn test -w"
},
"dependencies": {
"@babel/core": "^7.5.4",
"@babel/plugin-transform-typescript": "^7.2.0",
"@babel/template": "^7.5.4",
"@babel/types": "^7.5.0",
"chalk": "4.1.0",
"cli-highlight": "2.1.4",
"commander": "6.1.0",
Expand All @@ -18,6 +23,7 @@
"ora": "^5.1.0"
},
"devDependencies": {
"@types/babel__core": "^7.1.2",
"@types/inquirer": "7.3.1",
"@types/mock-fs": "4.10.0",
"@types/node": "9.6.49",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import * as babel from '@babel/core'
import { expect } from 'chai'
import { createSupportBabelPlugin, createTransformPluginsFileBabelPlugin } from './babelTransform'

describe('babel transform utils', () => {
context('support babel template', () => {
it('injects import after the last import in the file', () => {
const plugin = createSupportBabelPlugin('import "@cypress/react"')

const output = babel.transformSync([
'import "./commands.js"',
].join('\n'), {
plugins: [plugin],
})?.code

expect(output).to.equal([
'import "./commands.js";',
'import "@cypress/react";',
].join('\n'))
})

it('injects import after the last import if a lot of imports and code inside', () => {
const plugin = createSupportBabelPlugin('import "@cypress/react"')

const output = babel.transformSync([
'import "./commands.js";',
'import "./commands4.js";',
'import "./commands3.js";',
'import "./commands2.js";',
'',
'function hello() {',
' console.log("world");',
'}',
].join('\n'), {
plugins: [plugin],
})?.code

expect(output).to.equal([
'import "./commands.js";',
'import "./commands4.js";',
'import "./commands3.js";',
'import "./commands2.js";',
'import "@cypress/react";',
'',
'function hello() {',
' console.log("world");',
'}',
].join('\n'))
})

it('adds import as 1st line if no imports or require found', () => {
const plugin = createSupportBabelPlugin('import "@cypress/react"')

const output = babel.transformSync('', { plugins: [plugin] })?.code

expect(output).to.equal('import "@cypress/react";')
})
})

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()'),
})

const output = babel.transformSync([
'module.exports = (on, config) => {',
'on("do")',
'}',
].join('\n'), {
plugins: [plugin],
})?.code

expect(output).to.equal([
'require("something");',
'',
'module.exports = (on, config) => {',
' on("do");',
' yey();',
'};',
].join(`\n`))
})
})
})
Loading