mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-23 07:39:52 -06:00
This reverts commit a355ad6159.
This commit is contained in:
@@ -6,8 +6,8 @@ import path from 'path'
|
||||
import debugLib from 'debug'
|
||||
import { parse, print } from 'recast'
|
||||
|
||||
import { addCommonJSModuleImportToCypressConfigPlugin, addESModuleImportToCypressConfigPlugin, addToCypressConfigPlugin } from './addToCypressConfigPlugin'
|
||||
import { addCommonJSModuleDefinition, addComponentDefinition, addE2EDefinition, addESModuleDefinition, ASTComponentDefinitionConfig, ModuleToAdd } from './astConfigHelpers'
|
||||
import { addToCypressConfigPlugin } from './addToCypressConfigPlugin'
|
||||
import { addComponentDefinition, addE2EDefinition, ASTComponentDefinitionConfig } from './astConfigHelpers'
|
||||
|
||||
const debug = debugLib('cypress:config:addToCypressConfig')
|
||||
|
||||
@@ -40,26 +40,13 @@ const debug = debugLib('cypress:config:addToCypressConfig')
|
||||
* ...createConfigFn()
|
||||
* }
|
||||
*/
|
||||
export async function addToCypressConfig (filePath: string, code: string, toAdd: {
|
||||
properties?: t.ObjectProperty[]
|
||||
modules?: ModuleToAdd[]
|
||||
}) {
|
||||
export async function addToCypressConfig (filePath: string, code: string, toAdd: t.ObjectProperty) {
|
||||
try {
|
||||
const ast = parse(code, {
|
||||
parser: require('recast/parsers/typescript'),
|
||||
})
|
||||
|
||||
for (const prop of toAdd.properties ?? []) {
|
||||
traverse(ast, addToCypressConfigPlugin(prop).visitor)
|
||||
}
|
||||
|
||||
for (const mod of toAdd.modules ?? []) {
|
||||
if (mod.type === 'ES') {
|
||||
traverse(ast, addESModuleImportToCypressConfigPlugin(mod.node).visitor)
|
||||
} else if (mod.type === 'CommonJS') {
|
||||
traverse(ast, addCommonJSModuleImportToCypressConfigPlugin(mod.node).visitor)
|
||||
}
|
||||
}
|
||||
traverse(ast, addToCypressConfigPlugin(toAdd).visitor)
|
||||
|
||||
return print(ast).code
|
||||
} catch (e) {
|
||||
@@ -76,14 +63,10 @@ export interface AddProjectIdToCypressConfigOptions {
|
||||
export async function addProjectIdToCypressConfig (options: AddProjectIdToCypressConfigOptions) {
|
||||
try {
|
||||
let result = await fs.readFile(options.filePath, 'utf8')
|
||||
const toPrint = await addToCypressConfig(options.filePath, result, {
|
||||
properties: [
|
||||
t.objectProperty(
|
||||
t.identifier('projectId'),
|
||||
t.identifier(options.projectId),
|
||||
),
|
||||
],
|
||||
})
|
||||
const toPrint = await addToCypressConfig(options.filePath, result, t.objectProperty(
|
||||
t.identifier('projectId'),
|
||||
t.identifier(options.projectId),
|
||||
))
|
||||
|
||||
await fs.writeFile(options.filePath, maybeFormatWithPrettier(toPrint, options.filePath))
|
||||
|
||||
@@ -115,26 +98,6 @@ export interface AddTestingTypeToCypressConfigOptions {
|
||||
export async function addTestingTypeToCypressConfig (options: AddTestingTypeToCypressConfigOptions): Promise<AddToCypressConfigResult> {
|
||||
const toAdd = options.info.testingType === 'e2e' ? addE2EDefinition() : addComponentDefinition(options.info)
|
||||
|
||||
const modulesToAdd: ModuleToAdd[] = []
|
||||
|
||||
if (options.info.testingType === 'component') {
|
||||
if (options.info.bundler === 'webpack' && options.info.configPath) {
|
||||
if (options.isProjectUsingESModules) {
|
||||
modulesToAdd.push(addESModuleDefinition(options.info.configPath, 'webpackConfig'))
|
||||
} else {
|
||||
modulesToAdd.push(addCommonJSModuleDefinition(options.info.configPath, 'webpackConfig'))
|
||||
}
|
||||
}
|
||||
|
||||
if (options.info.bundler === 'vite' && options.info.configPath) {
|
||||
if (options.isProjectUsingESModules) {
|
||||
modulesToAdd.push(addESModuleDefinition(options.info.configPath, 'viteConfig'))
|
||||
} else {
|
||||
modulesToAdd.push(addCommonJSModuleDefinition(options.info.configPath, 'viteConfig'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
let result: string | undefined = undefined
|
||||
let resultStatus: 'ADDED' | 'MERGED' = 'MERGED'
|
||||
@@ -154,7 +117,7 @@ export async function addTestingTypeToCypressConfig (options: AddTestingTypeToCy
|
||||
result = getEmptyCodeBlock({ outputType: pathExt as OutputExtension, isProjectUsingESModules: options.isProjectUsingESModules })
|
||||
}
|
||||
|
||||
const toPrint = await addToCypressConfig(options.filePath, result, { properties: [toAdd], modules: modulesToAdd })
|
||||
const toPrint = await addToCypressConfig(options.filePath, result, toAdd)
|
||||
|
||||
await fs.writeFile(options.filePath, maybeFormatWithPrettier(toPrint, options.filePath))
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { NodePath, ParserOptions, PluginObj, Visitor } from '@babel/core'
|
||||
import { last } from 'lodash'
|
||||
import * as t from '@babel/types'
|
||||
import debugLib from 'debug'
|
||||
import { print } from 'recast'
|
||||
@@ -10,20 +9,6 @@ interface AddToCypressConfigPluginOptions {
|
||||
shouldThrow?: boolean
|
||||
}
|
||||
|
||||
function manipulateOptions (_t: any, parserOpts: ParserOptions) {
|
||||
parserOpts.errorRecovery = true
|
||||
parserOpts.plugins ??= []
|
||||
if (
|
||||
parserOpts.plugins.some(
|
||||
(p: any) => (Array.isArray(p) ? p[0] : p) === 'typescript',
|
||||
)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
parserOpts.plugins.push('typescript')
|
||||
}
|
||||
|
||||
/**
|
||||
* Standardizes our approach to writing values into the existing
|
||||
* Cypress config file. Attempts to handle the pragmatic cases,
|
||||
@@ -156,7 +141,19 @@ export function addToCypressConfigPlugin (toAdd: t.ObjectProperty, opts: AddToCy
|
||||
|
||||
return {
|
||||
name: 'addToCypressConfigPlugin',
|
||||
manipulateOptions,
|
||||
manipulateOptions (t, parserOpts: ParserOptions) {
|
||||
parserOpts.errorRecovery = true
|
||||
parserOpts.plugins ??= []
|
||||
if (
|
||||
parserOpts.plugins.some(
|
||||
(p: any) => (Array.isArray(p) ? p[0] : p) === 'typescript',
|
||||
)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
parserOpts.plugins.push('typescript')
|
||||
},
|
||||
visitor: {
|
||||
Program: {
|
||||
enter (path) {
|
||||
@@ -223,77 +220,11 @@ export function addToCypressConfigPlugin (toAdd: t.ObjectProperty, opts: AddToCy
|
||||
}
|
||||
}
|
||||
|
||||
export function addESModuleImportToCypressConfigPlugin (toAdd: t.ImportDeclaration, opts: AddToCypressConfigPluginOptions = {}): PluginObj<any> {
|
||||
return {
|
||||
name: 'addESModuleImportToCypressConfigPlugin',
|
||||
manipulateOptions,
|
||||
visitor: {
|
||||
Program (path) {
|
||||
const lastImport = last(path.get('body').filter((p) => p.isImportDeclaration()))
|
||||
|
||||
if (lastImport) {
|
||||
lastImport.insertAfter(toAdd)
|
||||
} else {
|
||||
path.get('body')?.[0]?.insertBefore(toAdd)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function addCommonJSModuleImportToCypressConfigPlugin (toAdd: t.Statement, opts: AddToCypressConfigPluginOptions = {}): PluginObj<any> {
|
||||
let lastRequireBeforeModuleExports: number
|
||||
let lastSeenRequire: number
|
||||
|
||||
return {
|
||||
name: 'addCommonJSModuleImportToCypressConfigPlugin',
|
||||
visitor: {
|
||||
Program: {
|
||||
exit (path) {
|
||||
const body = path.get('body')?.[0]
|
||||
|
||||
// Should never happen, unless `cypress.config.js` is empty.
|
||||
if (!body) {
|
||||
return
|
||||
}
|
||||
|
||||
const n = body.find((x) => x.node?.loc?.end.line === lastRequireBeforeModuleExports)
|
||||
|
||||
if (n) {
|
||||
/**
|
||||
* insert the require after the last require that appears before
|
||||
* module.exports, if there is some other require statements.
|
||||
* const { defineConfig } = require('cypress')
|
||||
* <------- Insert it here
|
||||
* module.exports = {}
|
||||
*/
|
||||
n.insertAfter(toAdd)
|
||||
} else {
|
||||
/**
|
||||
* Otherwise just put it at the top of the module.
|
||||
*/
|
||||
body.insertBefore(toAdd)
|
||||
}
|
||||
},
|
||||
},
|
||||
CallExpression (path) {
|
||||
if (isRequire(path)) {
|
||||
if (path.node.loc?.end?.line) {
|
||||
lastSeenRequire = path.node.loc?.end?.line
|
||||
}
|
||||
}
|
||||
},
|
||||
AssignmentExpression (path) {
|
||||
if (t.isMemberExpression(path.node.left) && isModuleExports(path.node.left)) {
|
||||
lastRequireBeforeModuleExports = lastSeenRequire
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function isRequire (p: NodePath<t.CallExpression>) {
|
||||
return p.node.callee.type === 'Identifier' && p.node.callee.name === 'require'
|
||||
function spreadResult (expr: t.Expression, toAdd: t.ObjectProperty): t.ObjectExpression {
|
||||
return t.objectExpression([
|
||||
t.spreadElement(expr),
|
||||
toAdd,
|
||||
])
|
||||
}
|
||||
|
||||
function isModuleExports (node: t.MemberExpression) {
|
||||
@@ -304,10 +235,3 @@ function isModuleExports (node: t.MemberExpression) {
|
||||
node.property.name === 'exports'
|
||||
)
|
||||
}
|
||||
|
||||
function spreadResult (expr: t.Expression, toAdd: t.ObjectProperty): t.ObjectExpression {
|
||||
return t.objectExpression([
|
||||
t.spreadElement(expr),
|
||||
toAdd,
|
||||
])
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as t from '@babel/types'
|
||||
import type { WIZARD_BUNDLERS, WIZARD_FRAMEWORKS } from '@packages/scaffold-config'
|
||||
import { parse, visit } from 'recast'
|
||||
import dedent from 'dedent'
|
||||
import assert from 'assert'
|
||||
@@ -27,10 +26,8 @@ export function addE2EDefinition (): t.ObjectProperty {
|
||||
|
||||
export interface ASTComponentDefinitionConfig {
|
||||
testingType: 'component'
|
||||
bundler: typeof WIZARD_BUNDLERS[number]['type']
|
||||
configPath?: string
|
||||
framework?: typeof WIZARD_FRAMEWORKS[number]['configFramework']
|
||||
needsExplicitConfig: boolean
|
||||
bundler: 'vite' | 'webpack'
|
||||
framework?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,66 +41,12 @@ export interface ASTComponentDefinitionConfig {
|
||||
* }
|
||||
*/
|
||||
export function addComponentDefinition (config: ASTComponentDefinitionConfig): t.ObjectProperty {
|
||||
const bundlers = {
|
||||
vite: {
|
||||
name: 'Vite',
|
||||
key: 'viteConfig',
|
||||
},
|
||||
webpack: {
|
||||
name: 'webpack',
|
||||
key: 'webpackConfig',
|
||||
},
|
||||
} as const
|
||||
|
||||
if (config.bundler === 'webpack' && config.needsExplicitConfig && config.configPath) {
|
||||
return extractProperty(`
|
||||
const toMerge = {
|
||||
component: {
|
||||
devServer: {
|
||||
framework: ${config.framework ? `'${config.framework}'` : 'undefined'},
|
||||
bundler: '${config.bundler}',
|
||||
webpackConfig,
|
||||
},
|
||||
},
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
if (config.bundler === 'vite' && config.needsExplicitConfig && config.configPath) {
|
||||
return extractProperty(`
|
||||
const toMerge = {
|
||||
component: {
|
||||
devServer: {
|
||||
framework: ${config.framework ? `'${config.framework}'` : 'undefined'},
|
||||
bundler: '${config.bundler}',
|
||||
viteConfig,
|
||||
},
|
||||
},
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
if (config.needsExplicitConfig) {
|
||||
return extractProperty(`
|
||||
const toMerge = {
|
||||
component: {
|
||||
devServer: {
|
||||
framework: ${config.framework ? `'${config.framework}'` : 'undefined'},
|
||||
bundler: '${config.bundler}',
|
||||
// provide your ${bundlers[config.bundler].name} config here...
|
||||
// ${bundlers[config.bundler].key},
|
||||
},
|
||||
},
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
return extractProperty(`
|
||||
const toMerge = {
|
||||
component: {
|
||||
devServer: {
|
||||
framework: ${config.framework ? `'${config.framework}'` : 'undefined'},
|
||||
bundler: '${config.bundler}',
|
||||
bundler: '${config.bundler}',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -137,46 +80,3 @@ function extractProperty (str: string) {
|
||||
|
||||
return toAdd
|
||||
}
|
||||
|
||||
interface ESModuleToAdd {
|
||||
node: t.ImportDeclaration
|
||||
type: 'ES'
|
||||
}
|
||||
|
||||
interface CommonJSModuleToAdd {
|
||||
node: t.Statement
|
||||
type: 'CommonJS'
|
||||
}
|
||||
|
||||
export type ModuleToAdd = ESModuleToAdd | CommonJSModuleToAdd
|
||||
|
||||
/**
|
||||
* AST definition Node for:
|
||||
*
|
||||
* import webpackConfig from <file>
|
||||
*/
|
||||
export function addESModuleDefinition (file: string, identifier: 'viteConfig' | 'webpackConfig'): ESModuleToAdd {
|
||||
return {
|
||||
node: t.importDeclaration(
|
||||
[t.importDefaultSpecifier(t.identifier(identifier))],
|
||||
t.stringLiteral(file),
|
||||
),
|
||||
type: 'ES',
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AST definition Node for:
|
||||
*
|
||||
* const webpackConfig = require(<file>)
|
||||
*/
|
||||
export function addCommonJSModuleDefinition (file: string, identifier: 'viteConfig' | 'webpackConfig'): CommonJSModuleToAdd {
|
||||
const parsed = parse(`const ${identifier} = require('${file}')`, {
|
||||
parser: require('recast/parsers/typescript'),
|
||||
}) as t.File
|
||||
|
||||
return {
|
||||
node: parsed.program.body[0] as t.Statement,
|
||||
type: 'CommonJS',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import * as fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
function detectConfig (projectRoot: string, dirs: string[], files: string[]): string | undefined {
|
||||
for (const dir of dirs) {
|
||||
for (const f of files) {
|
||||
const p = path.join(projectRoot, dir, f)
|
||||
|
||||
if (fs.existsSync(p)) {
|
||||
return `./${path.posix.join(dir, f)}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks in common places for a webpack.config.
|
||||
*/
|
||||
export const detectRelativeWebpackConfig = (projectRoot: string) => {
|
||||
return detectConfig(projectRoot, ['.', 'config'], ['webpack.config.js', 'webpack.config.ts'])
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks in common places for a vite.config.
|
||||
*/
|
||||
export const detectRelativeViteConfig = (projectRoot: string) => {
|
||||
return detectConfig(projectRoot, ['.', 'config'], ['vite.config.js', 'vite.config.ts'])
|
||||
}
|
||||
@@ -3,8 +3,3 @@
|
||||
export * from './browser'
|
||||
|
||||
export { addProjectIdToCypressConfig, addToCypressConfig, addTestingTypeToCypressConfig, AddTestingTypeToCypressConfigOptions } from './ast-utils/addToCypressConfig'
|
||||
|
||||
export {
|
||||
detectRelativeWebpackConfig,
|
||||
detectRelativeViteConfig,
|
||||
} from './detect/bundleConfig'
|
||||
|
||||
@@ -4,8 +4,7 @@ const myConfig = defineConfig({
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "react",
|
||||
bundler: "webpack", // provide your webpack config here...
|
||||
// webpackConfig,
|
||||
bundler: "webpack",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,8 +4,7 @@ export default cypressDefineConfig({
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "react",
|
||||
bundler: "webpack", // provide your webpack config here...
|
||||
// webpackConfig,
|
||||
bundler: "webpack",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,8 +3,7 @@ export default {
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "react",
|
||||
bundler: "webpack", // provide your webpack config here...
|
||||
// webpackConfig,
|
||||
bundler: "webpack",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,8 +4,7 @@ export default myDefineConfig({
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "react",
|
||||
bundler: "webpack", // provide your webpack config here...
|
||||
// webpackConfig,
|
||||
bundler: "webpack",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,8 +4,7 @@ export default cy.defineConfig({
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "react",
|
||||
bundler: "webpack", // provide your webpack config here...
|
||||
// webpackConfig,
|
||||
bundler: "webpack",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,8 +3,7 @@ module.exports = {
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "react",
|
||||
bundler: "webpack", // provide your webpack config here...
|
||||
// webpackConfig,
|
||||
bundler: "webpack",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
const { defineConfig } = require('cypress')
|
||||
module.exports = defineConfig({
|
||||
e2e: {}
|
||||
})
|
||||
@@ -1,7 +0,0 @@
|
||||
const { defineConfig } = require("cypress");
|
||||
|
||||
const webpackConfig = require("./webpack.config.js");
|
||||
|
||||
module.exports = defineConfig({
|
||||
e2e: {},
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = defineConfig({
|
||||
e2e: {}
|
||||
})
|
||||
@@ -1,5 +0,0 @@
|
||||
const webpackConfig = require("./webpack.config.js");
|
||||
|
||||
module.exports = defineConfig({
|
||||
e2e: {},
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
import { defineConfig } from 'cypress'
|
||||
|
||||
const myConfig = defineConfig({
|
||||
e2e: {}
|
||||
})
|
||||
|
||||
export default myConfig
|
||||
@@ -1,6 +0,0 @@
|
||||
import { defineConfig } from "cypress";
|
||||
import webpackConfig from "./webpack.config.js";
|
||||
const myConfig = defineConfig({
|
||||
e2e: {},
|
||||
});
|
||||
export default myConfig;
|
||||
@@ -1,9 +0,0 @@
|
||||
import { defineConfig } from 'cypress'
|
||||
|
||||
export const foo: string = ""
|
||||
|
||||
const myConfig = defineConfig({
|
||||
e2e: {}
|
||||
})
|
||||
|
||||
export default myConfig
|
||||
@@ -1,7 +0,0 @@
|
||||
import { defineConfig } from "cypress";
|
||||
import webpackConfig from "./webpack.config.js";
|
||||
export const foo: string = "";
|
||||
const myConfig = defineConfig({
|
||||
e2e: {},
|
||||
});
|
||||
export default myConfig;
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
e2e: {},
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import pluginTester from 'babel-plugin-tester'
|
||||
import path from 'path'
|
||||
import { addESModuleImportToCypressConfigPlugin, addCommonJSModuleImportToCypressConfigPlugin } from '../../src/ast-utils/addToCypressConfigPlugin'
|
||||
import { addESModuleDefinition, addCommonJSModuleDefinition } from '../../src/ast-utils/astConfigHelpers'
|
||||
|
||||
pluginTester({
|
||||
pluginName: 'addToCypressConfigPlugin: ESM config w/ component with webpack config',
|
||||
plugin: () => {
|
||||
return addESModuleImportToCypressConfigPlugin(
|
||||
addESModuleDefinition('./webpack.config.js', 'webpackConfig').node,
|
||||
{ shouldThrow: false },
|
||||
)
|
||||
},
|
||||
fixtures: path.join(__dirname, '..', '__babel_fixtures__', 'adding-module-es'),
|
||||
})
|
||||
|
||||
pluginTester({
|
||||
pluginName: 'addToCypressConfigPlugin: CJS config w/ component with webpack config',
|
||||
plugin: () => {
|
||||
return addCommonJSModuleImportToCypressConfigPlugin(
|
||||
addCommonJSModuleDefinition('./webpack.config.js', 'webpackConfig').node,
|
||||
{ shouldThrow: false },
|
||||
)
|
||||
},
|
||||
fixtures: path.join(__dirname, '..', '__babel_fixtures__', 'adding-module-cjs'),
|
||||
})
|
||||
@@ -116,95 +116,4 @@ describe('addToCypressConfig', () => {
|
||||
expect(result.result).to.eq('NEEDS_MERGE')
|
||||
expect(result.error.message).to.eq('Unable to automerge with the config file')
|
||||
})
|
||||
|
||||
it('adds component testing to e2e config', async () => {
|
||||
const result = await addTestingTypeToCypressConfig({
|
||||
filePath: path.join(__dirname, '../__fixtures__/has-e2e.config.ts'),
|
||||
info: {
|
||||
testingType: 'component',
|
||||
bundler: 'webpack',
|
||||
framework: 'react',
|
||||
needsExplicitConfig: true,
|
||||
},
|
||||
isProjectUsingESModules: false,
|
||||
})
|
||||
|
||||
expect(stub.getCall(0).lastArg.trim()).to.eq(dedent`
|
||||
export default {
|
||||
e2e: {},
|
||||
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "react",
|
||||
bundler: "webpack",
|
||||
// provide your webpack config here...
|
||||
// webpackConfig,
|
||||
},
|
||||
},
|
||||
};`.trim())
|
||||
|
||||
expect(result.result).to.eq('MERGED')
|
||||
})
|
||||
|
||||
it('adds vite bundler in component testing to e2e config', async () => {
|
||||
const result = await addTestingTypeToCypressConfig({
|
||||
filePath: path.join(__dirname, '../__fixtures__/has-e2e.config.ts'),
|
||||
info: {
|
||||
testingType: 'component',
|
||||
bundler: 'vite',
|
||||
framework: 'react',
|
||||
needsExplicitConfig: true,
|
||||
},
|
||||
isProjectUsingESModules: false,
|
||||
})
|
||||
|
||||
expect(stub.getCall(0).lastArg.trim()).to.eq(dedent`
|
||||
export default {
|
||||
e2e: {},
|
||||
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "react",
|
||||
bundler: "vite",
|
||||
// provide your Vite config here...
|
||||
// viteConfig,
|
||||
},
|
||||
},
|
||||
};`.trim())
|
||||
|
||||
expect(result.result).to.eq('MERGED')
|
||||
})
|
||||
|
||||
it('adds component testing and webpack config to e2e config', async () => {
|
||||
const result = await addTestingTypeToCypressConfig({
|
||||
filePath: path.join(__dirname, '../__fixtures__/has-e2e.config.ts'),
|
||||
info: {
|
||||
testingType: 'component',
|
||||
bundler: 'webpack',
|
||||
framework: 'react',
|
||||
configPath: './webpack.config.ts',
|
||||
needsExplicitConfig: true,
|
||||
},
|
||||
isProjectUsingESModules: true,
|
||||
})
|
||||
|
||||
// we generate this using Babel which intentionally does **NOT**
|
||||
// handle formatting, so the output format is kind of weird.
|
||||
// we rely on the user's eslint or prettier to format this properly.
|
||||
expect(stub.getCall(0).lastArg.trim()).to.eq(dedent`
|
||||
import webpackConfig from "./webpack.config.ts";
|
||||
export default {
|
||||
e2e: {},
|
||||
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "react",
|
||||
bundler: "webpack",
|
||||
webpackConfig,
|
||||
},
|
||||
},
|
||||
};`.trim())
|
||||
|
||||
expect(result.result).to.eq('MERGED')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -8,7 +8,7 @@ pluginTester({
|
||||
pluginName: 'addToCypressConfigPlugin: component',
|
||||
plugin: () => {
|
||||
return addToCypressConfigPlugin(
|
||||
addComponentDefinition({ testingType: 'component', framework: 'react', bundler: 'webpack', needsExplicitConfig: true }),
|
||||
addComponentDefinition({ testingType: 'component', framework: 'react', bundler: 'webpack' }),
|
||||
{ shouldThrow: false },
|
||||
)
|
||||
},
|
||||
|
||||
@@ -4,11 +4,11 @@ import assert from 'assert'
|
||||
import path from 'path'
|
||||
import Debug from 'debug'
|
||||
import fs from 'fs-extra'
|
||||
import { addTestingTypeToCypressConfig, AddTestingTypeToCypressConfigOptions, detectRelativeViteConfig, detectRelativeWebpackConfig } from '@packages/config'
|
||||
|
||||
const debug = Debug('cypress:data-context:wizard-actions')
|
||||
|
||||
import type { DataContext } from '..'
|
||||
import { addTestingTypeToCypressConfig, AddTestingTypeToCypressConfigOptions } from '@packages/config'
|
||||
|
||||
export class WizardActions {
|
||||
constructor (private ctx: DataContext) {}
|
||||
@@ -215,23 +215,18 @@ export class WizardActions {
|
||||
|
||||
private async scaffoldConfig (testingType: 'e2e' | 'component'): Promise<NexusGenObjects['ScaffoldedFile']> {
|
||||
debug('scaffoldConfig')
|
||||
assert(this.ctx.currentProject)
|
||||
|
||||
if (!this.ctx.lifecycleManager.metaState.hasValidConfigFile) {
|
||||
this.ctx.lifecycleManager.setConfigFilePath(`cypress.config.${this.ctx.lifecycleManager.fileExtensionToUse}`)
|
||||
}
|
||||
|
||||
const configFilePath = this.ctx.lifecycleManager.configFilePath
|
||||
const bundler = this.ctx.coreData.wizard.chosenBundler?.package ?? 'webpack'
|
||||
|
||||
const testingTypeInfo: AddTestingTypeToCypressConfigOptions['info'] = testingType === 'e2e' ? {
|
||||
testingType: 'e2e',
|
||||
} : {
|
||||
testingType: 'component',
|
||||
bundler,
|
||||
bundler: this.ctx.coreData.wizard.chosenBundler?.package ?? 'webpack',
|
||||
framework: this.ctx.coreData.wizard.chosenFramework?.configFramework,
|
||||
configPath: bundler === 'vite' ? detectRelativeViteConfig(this.ctx.currentProject) : detectRelativeWebpackConfig(this.ctx.currentProject),
|
||||
needsExplicitConfig: this.ctx.coreData.wizard.chosenFramework?.category === 'library' ?? false,
|
||||
}
|
||||
|
||||
const result = await addTestingTypeToCypressConfig({
|
||||
|
||||
@@ -315,7 +315,7 @@ describe('Launchpad: Setup Project', () => {
|
||||
verifyChooseABrowserPage()
|
||||
})
|
||||
|
||||
it('can setup e2e testing for a project', () => {
|
||||
it('can setup e2e testing for a project selecting TS', () => {
|
||||
// has `typescript` in `package.json`
|
||||
scaffoldAndOpenProject('pristine-yarn')
|
||||
cy.visitLaunchpad()
|
||||
@@ -326,7 +326,7 @@ describe('Launchpad: Setup Project', () => {
|
||||
|
||||
cy.contains('button', 'E2E Testing')
|
||||
.should('have.focus')
|
||||
.click()
|
||||
.realPress('Enter')
|
||||
|
||||
cy.contains('h1', 'Configuration Files')
|
||||
cy.findByText('We added the following files to your project:')
|
||||
|
||||
@@ -66,13 +66,14 @@ function scaffoldAndOpenCTProject (opts: {
|
||||
cy.visitLaunchpad()
|
||||
|
||||
cy.contains('Welcome to Cypress!').should('be.visible')
|
||||
cy.contains('[data-cy-testingtype="e2e"]', 'Not Configured')
|
||||
cy.contains('[data-cy-testingtype="component"]', 'Not Configured')
|
||||
cy.contains('Component Testing').click()
|
||||
|
||||
cy.contains('React.js(detected)').click()
|
||||
cy.contains(opts.framework).click()
|
||||
if (opts.bundler) {
|
||||
cy.contains('Pick a bundler').click()
|
||||
cy.contains('Webpack(detected)').click()
|
||||
cy.contains(opts.bundler).click()
|
||||
}
|
||||
|
||||
@@ -157,33 +158,4 @@ describe('scaffolding new projects', { defaultCommandTimeout: 7000 }, () => {
|
||||
scaffoldAndOpenCTProject({ name: 'pristine', framework: 'Create React App', removeFixturesFolder: false })
|
||||
assertScaffoldedFilesAreCorrect({ language, testingType: 'component', ctFramework: 'Create React App (v5)', customDirectory: 'without-fixtures' })
|
||||
})
|
||||
|
||||
it('scaffolds CT for a non-framework JS project', () => {
|
||||
const language = 'js'
|
||||
|
||||
scaffoldAndOpenCTProject({ name: 'pristine', framework: 'Vue.js 3', bundler: 'Webpack', removeFixturesFolder: true })
|
||||
assertScaffoldedFilesAreCorrect({ language, testingType: 'component', ctFramework: 'Vue.js 3 Webpack' })
|
||||
})
|
||||
|
||||
it('scaffolds CT for a non-framework ESM TS project w/ webpack.config.js detected', () => {
|
||||
const language = 'ts'
|
||||
|
||||
scaffoldAndOpenCTProject({ name: 'pristine-module', framework: 'Vue.js 3', bundler: 'Webpack', removeFixturesFolder: true })
|
||||
assertScaffoldedFilesAreCorrect({ language, testingType: 'component', ctFramework: 'Vue.js 3 Webpack' })
|
||||
|
||||
// since we added a valid webpack.config, the dev server starts and we are greeted
|
||||
// with the choose browser screen.
|
||||
cy.contains('Choose your preferred browser for component testing.')
|
||||
})
|
||||
|
||||
it('scaffolds CT for a non-framework CJS JS project w/ webpack.config.js detected', () => {
|
||||
const language = 'js'
|
||||
|
||||
scaffoldAndOpenCTProject({ name: 'pristine-cjs-project', framework: 'Vue.js 3', bundler: 'Webpack', removeFixturesFolder: true })
|
||||
assertScaffoldedFilesAreCorrect({ language, testingType: 'component', ctFramework: 'Vue.js 3 Webpack' })
|
||||
|
||||
// since we added a valid webpack.config, the dev server starts and we are greeted
|
||||
// with the choose browser screen.
|
||||
cy.contains('Choose your preferred browser for component testing.')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -153,6 +153,9 @@ const onBack = () => {
|
||||
}
|
||||
|
||||
const canNavigateForward = computed(() => {
|
||||
return props.gql.bundler !== null && props.gql.framework !== null
|
||||
const { bundler, framework } = props.gql
|
||||
|
||||
return bundler !== null && framework !== null
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import { defineConfig } from "cypress";
|
||||
|
||||
import webpackConfig from "./webpack.config.js";
|
||||
|
||||
export default defineConfig({
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "vue",
|
||||
bundler: "webpack",
|
||||
webpackConfig,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>Components App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div data-cy-root></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,27 +0,0 @@
|
||||
// ***********************************************************
|
||||
// This example support/component.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
import { mount } from 'cypress/vue'
|
||||
|
||||
Cypress.Commands.add('mount', mount)
|
||||
|
||||
// Example use:
|
||||
// cy.mount(MyComponent)
|
||||
@@ -1 +0,0 @@
|
||||
export default {}
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = {}
|
||||
@@ -1,13 +0,0 @@
|
||||
const { defineConfig } = require("cypress");
|
||||
|
||||
const webpackConfig = require("./config/webpack.config.js");
|
||||
|
||||
module.exports = defineConfig({
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "vue",
|
||||
bundler: "webpack",
|
||||
webpackConfig,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>Components App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div data-cy-root></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,27 +0,0 @@
|
||||
// ***********************************************************
|
||||
// This example support/component.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
import { mount } from 'cypress/vue'
|
||||
|
||||
Cypress.Commands.add('mount', mount)
|
||||
|
||||
// Example use:
|
||||
// cy.mount(MyComponent)
|
||||
@@ -1,12 +0,0 @@
|
||||
const { defineConfig } = require("cypress");
|
||||
|
||||
module.exports = defineConfig({
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "vue",
|
||||
bundler: "webpack",
|
||||
// provide your webpack config here...
|
||||
// webpackConfig,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,25 +0,0 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>Components App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div data-cy-root></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,27 +0,0 @@
|
||||
// ***********************************************************
|
||||
// This example support/component.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
import { mount } from 'cypress/vue'
|
||||
|
||||
Cypress.Commands.add('mount', mount)
|
||||
|
||||
// Example use:
|
||||
// cy.mount(MyComponent)
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
Reference in New Issue
Block a user