Skip to content

Commit

Permalink
feat: validate specPattern root level (#19980)
Browse files Browse the repository at this point in the history
* feat: validate specPattern root level

* Fix/add tests

* Fix test

* Update specExcludePattern

* Fix tests

* Fix/add tests

* Fix/add tests

* Fix tests

* Rename specExcludePattern to excludeSpecPattern

* Fix tests
  • Loading branch information
estrada9166 authored Feb 4, 2022
1 parent 2856124 commit 5d52758
Show file tree
Hide file tree
Showing 41 changed files with 361 additions and 75 deletions.
2 changes: 1 addition & 1 deletion cli/schema/cypress.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"description": "Any values to be set as environment variables. See https://on.cypress.io/environment-variables",
"body": {}
},
"ignoreSpecPattern": {
"excludeSpecPattern": {
"type": [
"string",
"array"
Expand Down
4 changes: 2 additions & 2 deletions cli/types/cypress.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2631,14 +2631,14 @@ declare namespace Cypress {
/**
* A String or Array of glob patterns used to ignore test files that would otherwise be shown in your list of tests. Cypress uses minimatch with the options: {dot: true, matchBase: true}. We suggest using http://globtester.com to test what files would match.
* @default "*.hot-update.js"
* @deprecated use `ignoreSpecPattern` instead
* @deprecated use `excludeSpecPattern` instead
*/
ignoreTestFiles: string | string[]
/**
* A String or Array of glob patterns used to ignore test files that would otherwise be shown in your list of tests. Cypress uses minimatch with the options: {dot: true, matchBase: true}. We suggest using http://globtester.com to test what files would match.
* @default "*.hot-update.js"
*/
ignoreSpecPattern: string | string[]
excludeSpecPattern: string | string[]
/**
* The number of tests for which snapshots and command data are kept in memory. Reduce this number if you are experiencing high memory consumption in your browser during a test run.
* @default 50
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { defineConfig } from 'cypress'

export default defineConfig({
'baseUrl': '<%= baseUrl%>',
e2e: {
'baseUrl': '<%= baseUrl%>',
},
})
8 changes: 4 additions & 4 deletions npm/design-system/cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ module.exports = {
env: {
reactDevtools: true,
},
ignoreSpecPattern: [
'**/__snapshots__/*',
'**/__image_snapshots__/*',
],
fixturesFolder: false,
component: {
excludeSpecPattern: [
'**/__snapshots__/*',
'**/__image_snapshots__/*',
],
devServer (cypressConfig) {
const { startDevServer } = require('@cypress/vite-dev-server')

Expand Down
10 changes: 5 additions & 5 deletions npm/react/cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ module.exports = {
'env': {
'reactDevtools': true,
},
'ignoreSpecPattern': [
'**/__snapshots__/*',
'**/__image_snapshots__/*',
],
'experimentalFetchPolyfill': true,
'component': {
ignoreSpecPattern: 'examples/**/*',
'excludeSpecPattern': [
'**/__snapshots__/*',
'**/__image_snapshots__/*',
'examples/**/*',
],
devServer (cypressConfig, devServerConfig) {
const { startDevServer } = require('@cypress/webpack-dev-server')
const path = require('path')
Expand Down
8 changes: 4 additions & 4 deletions npm/react/examples/snapshots/cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ module.exports = {
'fixturesFolder': false,
'viewportWidth': 500,
'viewportHeight': 500,
'ignoreSpecPattern': [
'**/__snapshots__/*',
'**/__image_snapshots__/*',
],
'env': {
'cypress-plugin-snapshots': {
'prettier': true,
},
},
'component': {
'excludeSpecPattern': [
'**/__snapshots__/*',
'**/__image_snapshots__/*',
],
setupNodeEvents (on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
Expand Down
2 changes: 1 addition & 1 deletion npm/vue/cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default defineConfig({
'supportFile': false,
},
'component': {
ignoreSpecPattern: 'examples/**/*',
excludeSpecPattern: 'examples/**/*',
devServer (cypressConfig) {
const { startDevServer } = require('@cypress/webpack-dev-server')
const webpackConfig = require('./webpack.config')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module.exports = {
'baseUrl': 'http://localhost:3000',
'fixturesFolder': false,
'viewportWidth': 600,
'e2e': {
'baseUrl': 'http://localhost:3000',
'supportFile': false,
},
}
4 changes: 2 additions & 2 deletions packages/config/__snapshots__/index_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ exports['src/index .getDefaultValues returns list of public config keys 1'] = {
"experimentalStudio": false,
"fileServerFolder": "",
"fixturesFolder": "cypress/fixtures",
"ignoreSpecPattern": "*.hot-update.js",
"excludeSpecPattern": "*.hot-update.js",
"includeShadowDom": false,
"keystrokeDelay": 0,
"modifyObstructiveCode": true,
Expand Down Expand Up @@ -109,7 +109,7 @@ exports['src/index .getPublicConfigKeys returns list of public config keys 1'] =
"experimentalStudio",
"fileServerFolder",
"fixturesFolder",
"ignoreSpecPattern",
"excludeSpecPattern",
"includeShadowDom",
"keystrokeDelay",
"modifyObstructiveCode",
Expand Down
8 changes: 7 additions & 1 deletion packages/config/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const _ = require('lodash')
const debug = require('debug')('cypress:config:validator')

const { options, breakingOptions, breakingRootOptions } = require('./options')
const { options, breakingOptions, breakingRootOptions, testingTypeBreakingOptions } = require('./options')

const dashesOrUnderscoresRe = /^(_-)+/

Expand Down Expand Up @@ -120,6 +120,12 @@ module.exports = {
return validateNoBreakingOptions(breakingOptions, cfg, onWarning, onErr)
},

validateNoBreakingTestingTypeConfig: (cfg, testingType, onWarning, onErr) => {
const options = testingTypeBreakingOptions[testingType]

return validateNoBreakingOptions(options, cfg, onWarning, onErr)
},

validateNoReadOnlyConfig: (config, onErr) => {
let errProperty

Expand Down
31 changes: 29 additions & 2 deletions packages/config/lib/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface ResolvedConfigOption {
* Can be mutated with Cypress.config() or test-specific configuration overrides
*/
canUpdateDuringTestTime?: boolean
specificTestingType?: 'e2e' | 'component'
}

interface RuntimeConfigOption {
Expand Down Expand Up @@ -194,8 +195,8 @@ const resolvedOptions: Array<ResolvedConfigOption> = [
isFolder: true,
canUpdateDuringTestTime: false,
}, {
name: 'ignoreSpecPattern',
defaultValue: '*.hot-update.js',
name: 'excludeSpecPattern',
defaultValue: (options: Record<string, any> = {}) => options.testingType === 'component' ? ['**/__snapshots__/*', '**/__image_snapshots__/*'] : '*.hot-update.js',
validation: validate.isStringOrArrayOfStrings,
canUpdateDuringTestTime: true,
}, {
Expand Down Expand Up @@ -540,4 +541,30 @@ export const breakingRootOptions: Array<BreakingOption> = [
errorKey: 'SUPPORT_FILE_ROOT_NOT_SUPPORTED',
isWarning: false,
},
{
name: 'specPattern',
errorKey: 'SPEC_PATTERN_ROOT_NOT_SUPPORTED',
isWarning: false,
},
{
name: 'excludeSpecPattern',
errorKey: 'SPEC_EXCLUDE_PATTERN_ROOT_NOT_SUPPORTED',
isWarning: false,
},
{
name: 'baseUrl',
errorKey: 'BASE_URL_ROOT_NOT_SUPPORTED',
isWarning: false,
},
]

export const testingTypeBreakingOptions: { e2e: Array<BreakingOption>, component: Array<BreakingOption> } = {
e2e: [],
component: [
{
name: 'baseUrl',
errorKey: 'BASE_URL_CT_NOT_SUPPORTED',
isWarning: false,
},
],
}
12 changes: 6 additions & 6 deletions packages/data-context/src/actions/ProjectActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type SetSpecsFoundBySpecPattern = {
path: string
testingType: Cypress.TestingType
specPattern?: Cypress.Config['specPattern']
ignoreSpecPattern?: Cypress.Config['ignoreSpecPattern']
excludeSpecPattern?: Cypress.Config['excludeSpecPattern']
additionalIgnorePattern?: string | string[]
}

Expand Down Expand Up @@ -422,7 +422,7 @@ export class ProjectActions {
path: this.ctx.currentProject,
testingType,
specPattern: cfg[testingType]?.specPattern,
ignoreSpecPattern: cfg[testingType]?.ignoreSpecPattern,
excludeSpecPattern: cfg[testingType]?.excludeSpecPattern,
additionalIgnorePattern: testingType === 'component' ? cfg?.e2e?.specPattern : undefined,
})

Expand All @@ -440,12 +440,12 @@ export class ProjectActions {
}
}

async setSpecsFoundBySpecPattern ({ path, testingType, specPattern, ignoreSpecPattern, additionalIgnorePattern }: SetSpecsFoundBySpecPattern) {
async setSpecsFoundBySpecPattern ({ path, testingType, specPattern, excludeSpecPattern, additionalIgnorePattern }: SetSpecsFoundBySpecPattern) {
const toArray = (val?: string | string[]) => val ? typeof val === 'string' ? [val] : val : undefined

specPattern = toArray(specPattern)

ignoreSpecPattern = toArray(ignoreSpecPattern) || []
excludeSpecPattern = toArray(excludeSpecPattern) || []

// exclude all specs matching e2e if in component testing
additionalIgnorePattern = toArray(additionalIgnorePattern) || []
Expand All @@ -458,13 +458,13 @@ export class ProjectActions {
path,
testingType,
specPattern,
ignoreSpecPattern,
excludeSpecPattern,
additionalIgnorePattern,
)

this.ctx.actions.project.setSpecs(specs)

return { specs, specPattern, ignoreSpecPattern, additionalIgnorePattern }
return { specs, specPattern, excludeSpecPattern, additionalIgnorePattern }
}

async reconfigureProject () {
Expand Down
18 changes: 18 additions & 0 deletions packages/data-context/src/data/ProjectLifecycleManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface InjectedConfigApi {
updateWithPluginValues(config: FullConfig, modifiedConfig: Partial<Cypress.ConfigOptions>): FullConfig
setupFullConfigWithDefaults(config: SetupFullConfigOptions): Promise<FullConfig>
validateRootConfigBreakingChanges<T extends Cypress.ConfigOptions>(config: Partial<T>, onWarning: (warningMsg: string) => void, onErr: (errMsg: string) => never): T
validateTestingTypeConfigBreakingChanges<T extends Cypress.ConfigOptions>(config: Partial<T>, testingType: Cypress.TestingType, onWarning: (warningMsg: string) => void, onErr: (errMsg: string) => never): T
}

type State<S, V = undefined> = V extends undefined ? {state: S, value?: V } : {state: S, value: V}
Expand Down Expand Up @@ -442,6 +443,8 @@ export class ProjectLifecycleManager {
if (this._currentTestingType) {
const testingTypeOverrides = configFileContents[this._currentTestingType] ?? {}

this.validateTestingTypeConfig(testingTypeOverrides)

// TODO: pass in options.config overrides separately, so they are reflected in the UI
configFileContents = { ...configFileContents, ...testingTypeOverrides }
}
Expand Down Expand Up @@ -563,6 +566,21 @@ export class ProjectLifecycleManager {
return promise.then((v) => v.initialConfig)
}

private validateTestingTypeConfig (config: Cypress.ConfigOptions) {
assert(this._currentTestingType)

return this.ctx._apis.configApi.validateTestingTypeConfigBreakingChanges(
config,
this._currentTestingType,
(warning, ...args) => {
return this.ctx.warning(warning, ...args)
},
(err, ...args) => {
throw this.ctx.error(err, ...args)
},
)
}

private validateConfigRoot (config: Cypress.ConfigOptions) {
return this.ctx._apis.configApi.validateRootConfigBreakingChanges(
config,
Expand Down
6 changes: 4 additions & 2 deletions packages/data-context/src/sources/FileDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export class FileDataSource {
}

async getFilesByGlob (cwd: string, glob: string | string[], globOptions?: GlobbyOptions) {
const globs = (Array.isArray(glob) ? glob : [glob]).concat('!**/node_modules/**')
const globs = Array.isArray(glob) ? glob : [glob]

const ignoreGlob = globOptions && Array.isArray(globOptions?.ignore) ? globOptions.ignore.concat('**/node_modules/**') : ['**/node_modules/**']

if (process.platform === 'win32') {
// globby can't work with backwards slashes
Expand All @@ -46,7 +48,7 @@ export class FileDataSource {
}

try {
const files = await globby(globs, { onlyFiles: true, absolute: true, cwd, ...globOptions })
const files = await globby(globs, { onlyFiles: true, absolute: true, cwd, ...globOptions, ignore: ignoreGlob })

return files
} catch (e) {
Expand Down
16 changes: 8 additions & 8 deletions packages/data-context/src/sources/ProjectDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export class ProjectDataSource {

async specPatternsForTestingType (projectRoot: string, testingType: Cypress.TestingType): Promise<{
specPattern?: string[]
ignoreSpecPattern?: string[]
excludeSpecPattern?: string[]
}> {
const toArray = (val?: string | string[]) => val ? typeof val === 'string' ? [val] : val : undefined

Expand All @@ -152,22 +152,22 @@ export class ProjectDataSource {

return {
specPattern: toArray(config[testingType]?.specPattern),
ignoreSpecPattern: toArray(config[testingType]?.ignoreSpecPattern),
excludeSpecPattern: toArray(config[testingType]?.excludeSpecPattern),
}
}

async findSpecs (
projectRoot: string,
testingType: Cypress.TestingType,
specPattern: string[],
ignoreSpecPattern: string[],
excludeSpecPattern: string[],
globToRemove: string[],
): Promise<FoundSpec[]> {
const specAbsolutePaths = await this.ctx.file.getFilesByGlob(
projectRoot,
specPattern, {
absolute: true,
ignore: [...ignoreSpecPattern, ...globToRemove],
ignore: [...excludeSpecPattern, ...globToRemove],
},
)

Expand All @@ -185,7 +185,7 @@ export class ProjectDataSource {
projectRoot: string,
testingType: Cypress.TestingType,
specPattern: string[],
ignoreSpecPattern: string[],
excludeSpecPattern: string[],
additionalIgnore: string[],
) {
this.stopSpecWatcher()
Expand All @@ -197,7 +197,7 @@ export class ProjectDataSource {
}

const onSpecsChanged = debounce(async () => {
const specs = await this.findSpecs(projectRoot, testingType, specPattern, ignoreSpecPattern, additionalIgnore)
const specs = await this.findSpecs(projectRoot, testingType, specPattern, excludeSpecPattern, additionalIgnore)

this.setSpecs(specs)

Expand All @@ -220,9 +220,9 @@ export class ProjectDataSource {

const MINIMATCH_OPTIONS = { dot: true, matchBase: true }

const { specPattern = [], ignoreSpecPattern = [] } = await this.ctx.project.specPatternsForTestingType(this.ctx.currentProject, this.ctx.coreData.currentTestingType)
const { specPattern = [], excludeSpecPattern = [] } = await this.ctx.project.specPatternsForTestingType(this.ctx.currentProject, this.ctx.coreData.currentTestingType)

for (const pattern of ignoreSpecPattern) {
for (const pattern of excludeSpecPattern) {
if (minimatch(specFile, pattern, MINIMATCH_OPTIONS)) {
return false
}
Expand Down
Loading

3 comments on commit 5d52758

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 5d52758 Feb 4, 2022

Choose a reason for hiding this comment

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

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.0.0/circle-10.0-release-5d52758d82c47033803c69c7858fc786a900faaf/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 5d52758 Feb 4, 2022

Choose a reason for hiding this comment

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

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.0.0/circle-10.0-release-5d52758d82c47033803c69c7858fc786a900faaf/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 5d52758 Feb 4, 2022

Choose a reason for hiding this comment

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

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.0.0/circle-10.0-release-5d52758d82c47033803c69c7858fc786a900faaf/cypress.tgz

Please sign in to comment.