mirror of
https://github.com/cypress-io/cypress.git
synced 2026-04-21 22:49:16 -05:00
fix: types for config changes
This commit is contained in:
@@ -26,7 +26,7 @@ const issuedWarnings = new Set()
|
||||
|
||||
const validateNoBreakingOptions = (breakingCfgOptions, cfg, onWarning, onErr) => {
|
||||
breakingCfgOptions.forEach(({ name, errorKey, newName, isWarning, value }) => {
|
||||
if (cfg.hasOwnProperty(name)) {
|
||||
if (_.has(cfg, name)) {
|
||||
if (value && cfg[name] !== value) {
|
||||
// Bail if a value is specified but the config does not have that value.
|
||||
return
|
||||
|
||||
@@ -538,22 +538,22 @@ export const breakingOptions: Array<BreakingOption> = [
|
||||
export const breakingRootOptions: Array<BreakingOption> = [
|
||||
{
|
||||
name: 'supportFile',
|
||||
errorKey: 'SUPPORT_FILE_ROOT_NOT_SUPPORTED',
|
||||
errorKey: 'REMOVED_ROOT_CONFIG_OPTION',
|
||||
isWarning: false,
|
||||
},
|
||||
{
|
||||
name: 'specPattern',
|
||||
errorKey: 'SPEC_PATTERN_ROOT_NOT_SUPPORTED',
|
||||
errorKey: 'REMOVED_ROOT_CONFIG_OPTION',
|
||||
isWarning: false,
|
||||
},
|
||||
{
|
||||
name: 'excludeSpecPattern',
|
||||
errorKey: 'SPEC_EXCLUDE_PATTERN_ROOT_NOT_SUPPORTED',
|
||||
errorKey: 'REMOVED_ROOT_CONFIG_OPTION',
|
||||
isWarning: false,
|
||||
},
|
||||
{
|
||||
name: 'baseUrl',
|
||||
errorKey: 'BASE_URL_ROOT_NOT_SUPPORTED',
|
||||
errorKey: 'REMOVED_ROOT_CONFIG_OPTION',
|
||||
isWarning: false,
|
||||
},
|
||||
]
|
||||
@@ -563,7 +563,7 @@ export const testingTypeBreakingOptions: { e2e: Array<BreakingOption>, component
|
||||
component: [
|
||||
{
|
||||
name: 'baseUrl',
|
||||
errorKey: 'BASE_URL_CT_NOT_SUPPORTED',
|
||||
errorKey: 'CT_CONFIG_NOT_SUPPORTED',
|
||||
isWarning: false,
|
||||
},
|
||||
],
|
||||
|
||||
Vendored
+20
-13
@@ -1,29 +1,36 @@
|
||||
// TODO: Remove this file when we land type-safe @packages/config
|
||||
type ErrResult = {
|
||||
key: string
|
||||
value: any
|
||||
type: string
|
||||
}
|
||||
|
||||
export default {
|
||||
isValidClientCertificatesSet(_key: string, certsForUrls: any[]): string | true {},
|
||||
isValidClientCertificatesSet(_key: string, certsForUrls: any[]): ErrResult | true {},
|
||||
|
||||
isValidBrowser(browser: any): string | true {},
|
||||
isValidBrowser(browser: any): ErrResult | true {},
|
||||
|
||||
isValidBrowserList(key: string, browsers: any[]): string | true {},
|
||||
isValidBrowserList(key: string, browsers: any[]): ErrResult | true {},
|
||||
|
||||
isValidRetriesConfig(key: string, value: any): string | true {},
|
||||
isValidRetriesConfig(key: string, value: any): ErrResult | true {},
|
||||
|
||||
isPlainObject(key: string, value: any): string | true {},
|
||||
isPlainObject(key: string, value: any): ErrResult | true {},
|
||||
|
||||
isNumber(key: string, value: any): string | true {},
|
||||
isNumber(key: string, value: any): ErrResult | true {},
|
||||
|
||||
isNumberOrFalse(key: string, value: any): string | true {},
|
||||
isNumberOrFalse(key: string, value: any): ErrResult | true {},
|
||||
|
||||
isFullyQualifiedUrl(key: string, value: string): string | true {},
|
||||
isFullyQualifiedUrl(key: string, value: string): ErrResult | true {},
|
||||
|
||||
isBoolean(key: string, value: any): string | true {},
|
||||
isBoolean(key: string, value: any): ErrResult | true {},
|
||||
|
||||
isString(key: string, value: any): string | true {},
|
||||
isString(key: string, value: any): ErrResult | true {},
|
||||
|
||||
isArray(key: string, value: any): string | true {},
|
||||
isArray(key: string, value: any): ErrResult | true {},
|
||||
|
||||
isStringOrFalse(key: string, value: any): string | true {},
|
||||
isStringOrFalse(key: string, value: any): ErrResult | true {},
|
||||
|
||||
isStringOrArrayOfStrings(key: string, value: any): string | true {},
|
||||
isStringOrArrayOfStrings(key: string, value: any): ErrResult | true {},
|
||||
|
||||
isOneOf(...any: any[]): (key: any, value: any) => boolean {},
|
||||
}
|
||||
@@ -80,7 +80,7 @@ export class ProjectConfigIpc extends EventEmitter {
|
||||
* sourcing the config (script error, etc.)
|
||||
*/
|
||||
once(evt: 'loadConfig:reply', listener: (payload: SerializedLoadConfigReply) => void): this
|
||||
once(evt: 'loadConfig:error', listener: (realErrorCode: string, requiredFile: string, message: string) => void): this
|
||||
once(evt: 'loadConfig:error', listener: (err: SerializedError) => void): this
|
||||
|
||||
/**
|
||||
* When
|
||||
|
||||
@@ -16,11 +16,11 @@ import debugLib from 'debug'
|
||||
import pDefer from 'p-defer'
|
||||
import fs from 'fs'
|
||||
|
||||
import { getError, AllCypressErrors, AllCypressErrorNames, CypressError } from '@packages/errors'
|
||||
import { getError, CypressError, ConfigValidationError } from '@packages/errors'
|
||||
import type { DataContext } from '..'
|
||||
import { LoadConfigReply, SetupNodeEventsReply, ProjectConfigIpc, IpcHandler } from './ProjectConfigIpc'
|
||||
import assert from 'assert'
|
||||
import type { AllModeOptions, FoundBrowser, FullConfig, TestingType } from '@packages/types'
|
||||
import type { AllModeOptions, BreakingErrResult, BreakingOption, FoundBrowser, FullConfig, TestingType } from '@packages/types'
|
||||
import type { BaseErrorDataShape, WarningError } from '.'
|
||||
import { autoBindDebug } from '../util/autoBindDebug'
|
||||
|
||||
@@ -39,7 +39,7 @@ export interface SetupFullConfigOptions {
|
||||
options: Partial<AllModeOptions>
|
||||
}
|
||||
|
||||
type ConifigErrHandler<T> = <Name extends AllCypressErrorNames>(msg: Name, ...params: Parameters<typeof AllCypressErrors[Name]>) => T
|
||||
type BreakingValidationFn<T> = (type: BreakingOption, val: BreakingErrResult) => T
|
||||
|
||||
/**
|
||||
* All of the APIs injected from @packages/server & @packages/config
|
||||
@@ -48,12 +48,12 @@ type ConifigErrHandler<T> = <Name extends AllCypressErrorNames>(msg: Name, ...pa
|
||||
export interface InjectedConfigApi {
|
||||
cypressVersion: string
|
||||
getServerPluginHandlers: () => IpcHandler[]
|
||||
validateConfig<T extends Cypress.ConfigOptions>(config: Partial<T>, onErr: (errMsg: string) => never): T
|
||||
validateConfig<T extends Cypress.ConfigOptions>(config: Partial<T>, onErr: (errMsg: ConfigValidationError | string) => never): T
|
||||
allowedConfig(config: Cypress.ConfigOptions): Cypress.ConfigOptions
|
||||
updateWithPluginValues(config: FullConfig, modifiedConfig: Partial<Cypress.ConfigOptions>): FullConfig
|
||||
setupFullConfigWithDefaults(config: SetupFullConfigOptions): Promise<FullConfig>
|
||||
validateRootConfigBreakingChanges<T extends Cypress.ConfigOptions>(config: Partial<T>, onWarning: ConifigErrHandler<CypressError>, onErr: ConifigErrHandler<never>): T
|
||||
validateTestingTypeConfigBreakingChanges<T extends Cypress.ConfigOptions>(config: Partial<T>, testingType: Cypress.TestingType, onWarning: ConifigErrHandler<CypressError>, onErr: ConifigErrHandler<never>): T
|
||||
validateRootConfigBreakingChanges<T extends Cypress.ConfigOptions>(config: Partial<T>, onWarning: BreakingValidationFn<CypressError>, onErr: BreakingValidationFn<never>): T
|
||||
validateTestingTypeConfigBreakingChanges<T extends Cypress.ConfigOptions>(config: Partial<T>, testingType: Cypress.TestingType, onWarning: BreakingValidationFn<CypressError>, onErr: BreakingValidationFn<never>): T
|
||||
}
|
||||
|
||||
type State<S, V = undefined> = V extends undefined ? {state: S, value?: V } : {state: S, value: V}
|
||||
@@ -573,11 +573,11 @@ export class ProjectLifecycleManager {
|
||||
return this.ctx._apis.configApi.validateTestingTypeConfigBreakingChanges(
|
||||
config,
|
||||
this._currentTestingType,
|
||||
(warning, ...args) => {
|
||||
return getError(warning, ...args)
|
||||
(type, ...args) => {
|
||||
return getError(type, ...args)
|
||||
},
|
||||
(err, ...args) => {
|
||||
throw getError(err, ...args)
|
||||
(type, ...args) => {
|
||||
throw getError(type, ...args)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -585,26 +585,22 @@ export class ProjectLifecycleManager {
|
||||
private validateConfigRoot (config: Cypress.ConfigOptions) {
|
||||
return this.ctx._apis.configApi.validateRootConfigBreakingChanges(
|
||||
config,
|
||||
(warning, ...args) => {
|
||||
return getError(warning, ...args)
|
||||
(type, obj) => {
|
||||
return getError(type, obj)
|
||||
},
|
||||
(err, ...args) => {
|
||||
throw getError(err, ...args)
|
||||
(type, obj) => {
|
||||
throw getError(type, obj)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private validateConfigFile (file: string | false, config: Cypress.ConfigOptions) {
|
||||
this.ctx._apis.configApi.validateConfig(config, (errMsg) => {
|
||||
if (!file) {
|
||||
// This should never happen, b/c if the config file is false, the config
|
||||
// should be the default one
|
||||
throw getError('CONFIG_VALIDATION_ERROR', errMsg)
|
||||
if (_.isString(errMsg)) {
|
||||
throw getError('CONFIG_VALIDATION_MSG_ERROR', 'configFile', file || null, errMsg)
|
||||
}
|
||||
|
||||
const base = path.basename(file)
|
||||
|
||||
throw getError('SETTINGS_VALIDATION_ERROR', base, errMsg)
|
||||
throw getError('CONFIG_VALIDATION_ERROR', 'configFile', file || null, errMsg)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1034,21 +1030,13 @@ export class ProjectLifecycleManager {
|
||||
dfd.resolve({ ...val, initialConfig: JSON.parse(val.initialConfig) })
|
||||
})
|
||||
|
||||
ipc.once('loadConfig:error', (type, ...args) => {
|
||||
debug('loadConfig:error %s, rejecting', type)
|
||||
ipc.once('loadConfig:error', (err) => {
|
||||
this.killChildProcess(child)
|
||||
|
||||
const err = getError(type, ...args)
|
||||
|
||||
// if it's a non-cypress error, restore the initial error
|
||||
if (!(err.message?.length)) {
|
||||
err.isCypressErr = false
|
||||
err.message = args[1]
|
||||
err.code = type
|
||||
err.name = type
|
||||
if (err.isCypressErr) {
|
||||
dfd.reject(err)
|
||||
} else {
|
||||
dfd.reject(getError('CHILD_PROCESS_UNEXPECTED_ERROR', this.configFilePath, err))
|
||||
}
|
||||
|
||||
dfd.reject(err)
|
||||
})
|
||||
|
||||
debug('trigger the load of the file')
|
||||
|
||||
@@ -62,7 +62,7 @@ export interface SerializedError {
|
||||
errorType?: string
|
||||
stack?: string
|
||||
annotated?: string
|
||||
message?: string
|
||||
message: string
|
||||
name: string
|
||||
isCypressErr?: boolean
|
||||
}
|
||||
|
||||
@@ -4,11 +4,13 @@ import chalk from 'chalk'
|
||||
import _ from 'lodash'
|
||||
import path from 'path'
|
||||
import stripAnsi from 'strip-ansi'
|
||||
import type { BreakingErrResult } from '@packages/types'
|
||||
|
||||
import { humanTime, logError, parseResolvedPattern, pluralize } from './errorUtils'
|
||||
import { errPartial, errTemplate, fmt, theme, PartialErr } from './errTemplate'
|
||||
import { stackWithoutMessage } from './stackUtils'
|
||||
|
||||
import type { ClonedError, ConfigValidationError, CypressError, ErrorLike, ErrTemplateResult } from './errorTypes'
|
||||
import type { ClonedError, ConfigValidationError, CypressError, ErrTemplateResult, ErrorLike } from './errorTypes'
|
||||
|
||||
const ansi_up = new AU()
|
||||
|
||||
@@ -636,7 +638,7 @@ export const AllCypressErrors = {
|
||||
${fmt.stackTrace(err)}`
|
||||
},
|
||||
|
||||
CHILD_PROCESS_UNEXPECTED_ERROR: (configFilePath: string, err: Error) => {
|
||||
CHILD_PROCESS_UNEXPECTED_ERROR: (configFilePath: string, err: ErrorLike) => {
|
||||
return errTemplate`
|
||||
We stopped running your tests because a plugin.
|
||||
|
||||
@@ -1198,6 +1200,24 @@ export const AllCypressErrors = {
|
||||
`
|
||||
},
|
||||
|
||||
REMOVED_ROOT_CONFIG_OPTION: (errShape: BreakingErrResult) => {
|
||||
return errTemplate`\
|
||||
The ${fmt.highlight(errShape.name)} configuration option was removed from the root of the Cypress config object version 10.0.0.
|
||||
|
||||
Please update this option under each testing type property.
|
||||
|
||||
https://on.cypress.io/migration-guide`
|
||||
},
|
||||
|
||||
CT_CONFIG_NOT_SUPPORTED: (errShape: BreakingErrResult) => {
|
||||
return errTemplate`\
|
||||
The ${fmt.highlight(errShape.name)} configuration option is not valid in Component testing.
|
||||
|
||||
Please remove or add this option under e2e testing type property.
|
||||
|
||||
https://on.cypress.io/migration-guide`
|
||||
},
|
||||
|
||||
} as const
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@@ -1222,12 +1242,14 @@ export function getMsgByType<Type extends keyof AllCypressErrorObj> (type: Type,
|
||||
* @param args
|
||||
* @returns
|
||||
*/
|
||||
export const getError = function <Type extends keyof AllCypressErrorObj> (type: Type, ...args: Parameters<AllCypressErrorObj[Type]>) {
|
||||
export const getError = function <Type extends keyof AllCypressErrorObj> (type: Type, ...args: Parameters<AllCypressErrorObj[Type]>): CypressError {
|
||||
// If we don't know this "type" of error, return as a non-cypress error
|
||||
if (!AllCypressErrors[type]) {
|
||||
const err = new Error(args[1] || type) as ErrorLike
|
||||
const err = new Error(args[1] || type) as CypressError
|
||||
|
||||
err.isCypressErr = false
|
||||
err.type = type
|
||||
err.messageMarkdown = err.message
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1077,5 +1077,15 @@ describe('visual error templates', () => {
|
||||
default: ['spec.{ts,js}', 'spec.ts,spec.js'],
|
||||
}
|
||||
},
|
||||
REMOVED_ROOT_CONFIG_OPTION: () => {
|
||||
return {
|
||||
default: [{ name: 'specPattern', configFile: '/path/to/configFile.ts' }],
|
||||
}
|
||||
},
|
||||
CT_CONFIG_NOT_SUPPORTED: () => {
|
||||
return {
|
||||
default: [{ name: 'baseUrl', configFile: '/path/to/configFile.ts' }],
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@@ -44,3 +44,25 @@ export interface SettingsOptions {
|
||||
testingType?: 'component' |'e2e'
|
||||
args?: AllModeOptions
|
||||
}
|
||||
|
||||
// Todo, move to @packages/config when it becomes type-safe
|
||||
|
||||
export type BreakingOption =
|
||||
| 'RENAMED_CONFIG_OPTION'
|
||||
| 'EXPERIMENTAL_COMPONENT_TESTING_REMOVED'
|
||||
| 'EXPERIMENTAL_SAMESITE_REMOVED'
|
||||
| 'EXPERIMENTAL_NETWORK_STUBBING_REMOVED'
|
||||
| 'EXPERIMENTAL_RUN_EVENTS_REMOVED'
|
||||
| 'EXPERIMENTAL_SHADOW_DOM_REMOVED'
|
||||
| 'FIREFOX_GC_INTERVAL_REMOVED'
|
||||
| 'NODE_VERSION_DEPRECATION_SYSTEM'
|
||||
| 'NODE_VERSION_DEPRECATION_BUNDLED'
|
||||
| 'REMOVED_ROOT_CONFIG_OPTION'
|
||||
| 'CT_CONFIG_NOT_SUPPORTED'
|
||||
|
||||
export type BreakingErrResult = {
|
||||
name: string
|
||||
newName?: string
|
||||
value?: any
|
||||
configFile: string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user