mirror of
https://github.com/cypress-io/cypress.git
synced 2026-01-06 22:49:46 -06:00
* begin removing migration code * remove migration query * add back actions * remove more migration references * more migration removals * remove call to migration * remove gqp-Migration file * updates to remove migration * update type * remove a lot more migration code - especially errors * Remove other errors/warnins for versions before 10.x * update error snapshots * fix some tests * index on remove-migration:49fa75ab78Merge branch 'remove-migration' of https://github.com/cypress-io/cypress into remove-migration * index on remove-migration:49fa75ab78Merge branch 'remove-migration' of https://github.com/cypress-io/cypress into remove-migration * index on remove-migration:49fa75ab78Merge branch 'remove-migration' of https://github.com/cypress-io/cypress into remove-migration * remove more system tests and references * fix call to refreshMetaState which was lost at initialization * rearrange some system tests to not be dependent on migration * update welcome version test * fix wording of messaging * skip irrelevant test * fix failing assertion * remove tests around cypress-plugin-retries * Remove test from config_spec * Remove screenshot from snapshot * fix tests + remove more migration projects * remove + update system tests * remove + update system tests * remove some invalid dev-server: start errors * remove references and tests around pluginsFile which was removed * remove some more invalid config examples * Add changelog entry * fix changelog link * fix unit test * index on remove-migration:490ddb134cMerge branch 'release/15.0.0' into remove-migration * index on remove-migration:490ddb134cMerge branch 'release/15.0.0' into remove-migration * index on remove-migration:490ddb134cMerge branch 'release/15.0.0' into remove-migration * run all binary/windows tests on this branch * Update packages/scaffold-config/test/unit/detect.spec.ts Co-authored-by: Bill Glesias <bglesias@gmail.com> * Update packages/scaffold-config/test/unit/detect.spec.ts Co-authored-by: Bill Glesias <bglesias@gmail.com> --------- Co-authored-by: cypress-bot[bot] <+cypress-bot[bot]@users.noreply.github.com> Co-authored-by: Bill Glesias <bglesias@gmail.com>
1680 lines
62 KiB
TypeScript
1680 lines
62 KiB
TypeScript
import AU from 'ansi_up'
|
||
import os from 'os'
|
||
/* eslint-disable no-console */
|
||
import chalk from 'chalk'
|
||
import _ from 'lodash'
|
||
import path from 'path'
|
||
import stripAnsi from 'strip-ansi'
|
||
import type { BreakingErrResult, TestingType } from '@packages/types'
|
||
import { humanTime, logError, parseResolvedPattern, pluralize } from './errorUtils'
|
||
import { errPartial, errTemplate, fmt, theme } from './errTemplate'
|
||
import { stackWithoutMessage } from './stackUtils'
|
||
import type { ClonedError, ConfigValidationFailureInfo, CypressError, ErrTemplateResult, ErrorLike } from './errorTypes'
|
||
import { normalizeNetworkErrorMessage } from './normalizeNetworkErrorMessage'
|
||
|
||
const ansi_up = new AU()
|
||
|
||
ansi_up.use_classes = true
|
||
|
||
const displayRetriesRemaining = function (tries: number) {
|
||
const times = tries === 1 ? 'time' : 'times'
|
||
|
||
const lastTryNewLine = tries === 1 ? '\n' : ''
|
||
|
||
return fmt.meta(
|
||
`We will try connecting to it ${tries} more ${times}...${lastTryNewLine}`,
|
||
)
|
||
}
|
||
|
||
const getUsedTestsMessage = (limit: number, usedTestsMessage: string) => {
|
||
return _.isFinite(limit)
|
||
? fmt.off(`The limit is ${chalk.yellow(`${limit}`)} ${usedTestsMessage} results.`)
|
||
: fmt.off('')
|
||
}
|
||
|
||
export const warnIfExplicitCiBuildId = function (ciBuildId?: string | null) {
|
||
if (!ciBuildId) {
|
||
return null
|
||
}
|
||
|
||
return errPartial`\
|
||
It also looks like you also passed in an explicit ${fmt.flag('--ci-build-id')} flag.
|
||
|
||
This is only necessary if you are NOT running in one of our supported CI providers.
|
||
|
||
This flag must be unique for each new run, but must also be identical for each machine you are trying to --group or run in --parallel.\
|
||
`
|
||
}
|
||
|
||
/**
|
||
* All Cypress Errors should be defined here:
|
||
*
|
||
* The errors must return an "errTemplate", this is processed by the
|
||
*/
|
||
export const AllCypressErrors = {
|
||
CANNOT_TRASH_ASSETS: (arg1: Error) => {
|
||
return errTemplate`\
|
||
Warning: We failed to trash the existing run results.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.stackTrace(arg1)}`
|
||
},
|
||
CANNOT_REMOVE_OLD_BROWSER_PROFILES: (arg1: Error) => {
|
||
return errTemplate`\
|
||
Warning: We failed to remove old browser profiles from previous runs.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.stackTrace(arg1)}`
|
||
},
|
||
VIDEO_RECORDING_FAILED: (arg1: Error) => {
|
||
return errTemplate`\
|
||
Warning: We failed to record the video.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.stackTrace(arg1)}`
|
||
},
|
||
VIDEO_CAPTURE_FAILED: (arg1: Error) => {
|
||
return errTemplate`\
|
||
Warning: We failed capturing this video.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.stackTrace(arg1)}`
|
||
},
|
||
VIDEO_COMPRESSION_FAILED: (arg1: Error) => {
|
||
return errTemplate`\
|
||
Warning: We failed compressing this video.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.stackTrace(arg1)}`
|
||
},
|
||
CHROME_WEB_SECURITY_NOT_SUPPORTED: (browser: string) => {
|
||
return errTemplate`\
|
||
Your project has set the configuration option: \`chromeWebSecurity\` to \`false\`.
|
||
|
||
This option will not have an effect in ${fmt.off(_.capitalize(browser))}. Tests that rely on web security being disabled will not run as expected.`
|
||
},
|
||
BROWSER_UNSUPPORTED_LAUNCH_OPTION: (browser: string, options: string[]) => {
|
||
return errTemplate`\
|
||
Warning: The following browser launch options were provided but are not supported by ${fmt.highlightSecondary(browser)}
|
||
|
||
${fmt.listItems(options)}`
|
||
},
|
||
BROWSER_NOT_FOUND_BY_NAME: (browser: string, foundBrowsersStr: string[]) => {
|
||
return errTemplate`\
|
||
Can't run because you've entered an invalid browser name.
|
||
|
||
Browser: ${fmt.highlight(browser)} was not found on your system or is not supported by Cypress.
|
||
|
||
Cypress supports the following browsers:
|
||
${fmt.listItems(['electron', 'chrome', 'chromium', 'chrome-for-testing', 'edge', 'firefox'])}
|
||
|
||
You can also use a custom browser: https://on.cypress.io/customize-browsers
|
||
|
||
Available browsers found on your system are:
|
||
${fmt.listItems(foundBrowsersStr)}`
|
||
},
|
||
BROWSER_NOT_FOUND_BY_PATH: (arg1: string, arg2: string) => {
|
||
return errTemplate`\
|
||
We could not identify a known browser at the path you provided: ${fmt.path(arg1)}
|
||
|
||
Read more about how to troubleshoot launching browsers: https://on.cypress.io/troubleshooting-launching-browsers
|
||
|
||
The output from the command we ran was:
|
||
|
||
${fmt.highlightSecondary(arg2)}`
|
||
},
|
||
TESTS_DID_NOT_START_RETRYING: (arg1: string) => {
|
||
return errTemplate`Timed out waiting for the browser to connect. ${fmt.off(arg1)}`
|
||
},
|
||
FIREFOX_CDP_FAILED_TO_CONNECT: (arg1: string) => {
|
||
return errTemplate`Failed to spawn CDP with Firefox. ${fmt.off(arg1)}`
|
||
},
|
||
TESTS_DID_NOT_START_FAILED: () => {
|
||
return errTemplate`The browser never connected. Something is wrong. The tests cannot run. Aborting...`
|
||
},
|
||
CLOUD_CANCEL_SKIPPED_SPEC: () => {
|
||
return errTemplate`${fmt.off(`\n `)}This spec and its tests were skipped because the run has been canceled.`
|
||
},
|
||
CLOUD_API_RESPONSE_FAILED_RETRYING: (
|
||
arg1: {tries: number, delayMs: number, response: Error },
|
||
) => {
|
||
const time = pluralize('time', arg1.tries)
|
||
const delay = humanTime.long(arg1.delayMs, false)
|
||
|
||
const message = normalizeNetworkErrorMessage(arg1.response)
|
||
|
||
return errTemplate`\
|
||
We encountered an unexpected error communicating with our servers.
|
||
|
||
${fmt.highlightSecondary(message)}
|
||
|
||
We will retry ${fmt.off(arg1.tries)} more ${fmt.off(time)} in ${fmt.off(delay)}...
|
||
`
|
||
/* Because of fmt.listFlags() and fmt.listItems() */
|
||
/* eslint-disable indent */
|
||
},
|
||
CLOUD_CANNOT_PROCEED_IN_PARALLEL: (arg1: {flags: any, response: Error}) => {
|
||
const message = normalizeNetworkErrorMessage(arg1.response)
|
||
|
||
return errTemplate`\
|
||
We encountered an unexpected error communicating with our servers.
|
||
|
||
${fmt.highlightSecondary(message)}
|
||
|
||
Because you passed the ${fmt.flag(`--parallel`)} flag, this run cannot proceed since it requires a valid response from our servers.
|
||
|
||
${fmt.listFlags(arg1.flags, {
|
||
group: '--group',
|
||
ciBuildId: '--ciBuildId',
|
||
})}`
|
||
},
|
||
CLOUD_CANNOT_PROCEED_IN_SERIAL: (arg1: {flags: any, response: Error}) => {
|
||
const message = normalizeNetworkErrorMessage(arg1.response)
|
||
|
||
return errTemplate`\
|
||
We encountered an unexpected error communicating with our servers.
|
||
|
||
${fmt.highlightSecondary(message)}
|
||
|
||
Because you passed the ${fmt.flag(`--record`)} flag, this run cannot proceed since it requires a valid response from our servers.
|
||
|
||
${fmt.listFlags(arg1.flags, {
|
||
group: '--group',
|
||
ciBuildId: '--ciBuildId',
|
||
})}`
|
||
},
|
||
CLOUD_UNKNOWN_INVALID_REQUEST: (arg1: {flags: any, response: Error}) => {
|
||
const message = normalizeNetworkErrorMessage(arg1.response)
|
||
|
||
return errTemplate`\
|
||
We encountered an unexpected error communicating with our servers.
|
||
|
||
${fmt.highlightSecondary(message)}
|
||
|
||
There is likely something wrong with the request.
|
||
|
||
${fmt.listFlags(arg1.flags, {
|
||
tags: '--tag',
|
||
group: '--group',
|
||
parallel: '--parallel',
|
||
ciBuildId: '--ciBuildId',
|
||
})}`
|
||
},
|
||
CLOUD_UNKNOWN_CREATE_RUN_WARNING: (arg1: {props?: any, message: string}) => {
|
||
if (!Object.keys(arg1.props).length) {
|
||
return errTemplate`\
|
||
Warning from Cypress Cloud: ${fmt.highlight(arg1.message)}
|
||
`
|
||
}
|
||
|
||
return errTemplate`\
|
||
Warning from Cypress Cloud: ${fmt.highlight(arg1.message)}
|
||
|
||
Details:
|
||
${fmt.meta(arg1.props)}`
|
||
},
|
||
CLOUD_STALE_RUN: (arg1: {runUrl: string, [key: string]: any}) => {
|
||
return errTemplate`\
|
||
You are attempting to pass the ${fmt.flag(`--parallel`)} flag to a run that was completed over 24 hours ago.
|
||
|
||
The existing run is: ${fmt.url(arg1.runUrl)}
|
||
|
||
You cannot parallelize a run that has been complete for that long.
|
||
|
||
${fmt.listFlags(arg1, {
|
||
tags: '--tag',
|
||
group: '--group',
|
||
parallel: '--parallel',
|
||
ciBuildId: '--ciBuildId',
|
||
})}
|
||
|
||
https://on.cypress.io/stale-run`
|
||
},
|
||
CLOUD_ALREADY_COMPLETE: (props: {runUrl: string, tags: string, group: string, parallel: string, ciBuildId: string}) => {
|
||
return errTemplate`\
|
||
The run you are attempting to access is already complete and will not accept new groups.
|
||
|
||
The existing run is: ${fmt.url(props.runUrl)}
|
||
|
||
When a run finishes all of its groups, it waits for a configurable set of time before finally completing. You must add more groups during that time period.
|
||
|
||
${fmt.listFlags(props, {
|
||
tags: '--tag',
|
||
group: '--group',
|
||
parallel: '--parallel',
|
||
ciBuildId: '--ciBuildId',
|
||
})}
|
||
|
||
https://on.cypress.io/already-complete`
|
||
},
|
||
CLOUD_PARALLEL_REQUIRED: (arg1: {tags: string, group: string, runUrl: string, ciBuildId: string }) => {
|
||
return errTemplate`\
|
||
You did not pass the ${fmt.flag(`--parallel`)} flag, but this run's group was originally created with the --parallel flag.
|
||
|
||
The existing run is: ${fmt.url(arg1.runUrl)}
|
||
|
||
${fmt.listFlags(arg1, {
|
||
tags: '--tag',
|
||
group: '--group',
|
||
parallel: '--parallel',
|
||
ciBuildId: '--ciBuildId',
|
||
})}
|
||
|
||
You must use the --parallel flag with this group.
|
||
|
||
https://on.cypress.io/parallel-required`
|
||
},
|
||
CLOUD_PARALLEL_DISALLOWED: (arg1: {tags: string, group: string, runUrl: string, ciBuildId: string}) => {
|
||
return errTemplate`\
|
||
You passed the ${fmt.flag(`--parallel`)} flag, but this run group was originally created without the --parallel flag.
|
||
|
||
The existing run is: ${fmt.url(arg1.runUrl)}
|
||
|
||
${fmt.listFlags(arg1, {
|
||
tags: '--tag',
|
||
group: '--group',
|
||
parallel: '--parallel',
|
||
ciBuildId: '--ciBuildId',
|
||
})}
|
||
|
||
You can not use the --parallel flag with this group.
|
||
|
||
https://on.cypress.io/parallel-disallowed`
|
||
},
|
||
CLOUD_PARALLEL_GROUP_PARAMS_MISMATCH: (arg1: {group: string, runUrl: string, ciBuildId: string, parameters: any, payload: any }) => {
|
||
let params: any = arg1.parameters
|
||
|
||
if (arg1.payload?.differentParams) {
|
||
params = {}
|
||
|
||
_.map(arg1.parameters, (value, key) => {
|
||
if (key === 'specs' && arg1.payload.differentSpecs?.length) {
|
||
const addedSpecs: string[] = []
|
||
const missingSpecs: string[] = []
|
||
|
||
_.forEach(arg1.payload.differentSpecs, (s) => {
|
||
if (value.includes(s)) {
|
||
addedSpecs.push(s)
|
||
} else {
|
||
missingSpecs.push(s)
|
||
}
|
||
})
|
||
|
||
params['differentSpecs'] = {
|
||
added: addedSpecs,
|
||
missing: missingSpecs,
|
||
}
|
||
} else if (arg1.payload.differentParams[key]?.expected) {
|
||
params[key] = `${value}.... (Expected: ${(arg1.payload.differentParams[key].expected)})`
|
||
} else {
|
||
params[key] = value
|
||
}
|
||
})
|
||
}
|
||
|
||
return errTemplate`\
|
||
You passed the ${fmt.flag(`--parallel`)} flag, but we do not parallelize tests across different environments.
|
||
|
||
This machine is sending different environment parameters than the first machine that started this parallel run.
|
||
|
||
The existing run is: ${fmt.url(arg1.runUrl)}
|
||
|
||
In order to run in parallel mode each machine must send identical environment parameters such as:
|
||
|
||
${fmt.listItems([
|
||
'specs',
|
||
'osName',
|
||
'osVersion',
|
||
'browserName',
|
||
'browserVersion (major)',
|
||
])}
|
||
|
||
This machine sent the following parameters:
|
||
|
||
${fmt.meta(params)}
|
||
|
||
https://on.cypress.io/parallel-group-params-mismatch`
|
||
},
|
||
CLOUD_RUN_GROUP_NAME_NOT_UNIQUE: (arg1: {group: string, runUrl: string, ciBuildId?: string | null}) => {
|
||
return errTemplate`\
|
||
You passed the ${fmt.flag(`--group`)} flag, but this group name has already been used for this run.
|
||
|
||
The existing run is: ${fmt.url(arg1.runUrl)}
|
||
|
||
${fmt.listFlags(arg1, {
|
||
group: '--group',
|
||
parallel: '--parallel',
|
||
ciBuildId: '--ciBuildId',
|
||
})}
|
||
|
||
If you are trying to parallelize this run, then also pass the ${fmt.flag(`--parallel`)} flag, else pass a different group name.
|
||
|
||
${warnIfExplicitCiBuildId(arg1.ciBuildId)}
|
||
|
||
https://on.cypress.io/run-group-name-not-unique`
|
||
},
|
||
CLOUD_AUTO_CANCEL_NOT_AVAILABLE_IN_PLAN: (arg1: {link: string}) => {
|
||
return errTemplate`\
|
||
${fmt.highlightSecondary(`Auto Cancellation`)} is not included under your current billing plan.
|
||
|
||
To enable this service, please visit your billing and upgrade to another plan with Auto Cancellation.
|
||
|
||
${fmt.off(arg1.link)}`
|
||
},
|
||
CLOUD_AUTO_CANCEL_MISMATCH: (arg1: {runUrl: string, tags: string, group: string, parallel: string, ciBuildId: string, autoCancelAfterFailures: string }) => {
|
||
return errTemplate`\
|
||
You passed the ${fmt.flag(`--auto-cancel-after-failures`)} flag, but this run originally started with a different value for the ${fmt.flag(`--auto-cancel-after-failures`)} flag.
|
||
|
||
The existing run is: ${fmt.url(arg1.runUrl)}
|
||
|
||
${fmt.listFlags(arg1, {
|
||
tags: '--tag',
|
||
group: '--group',
|
||
parallel: '--parallel',
|
||
ciBuildId: '--ciBuildId',
|
||
autoCancelAfterFailures: '--auto-cancel-after-failures',
|
||
})}
|
||
|
||
The first setting of --auto-cancel-after-failures for any given run takes precedent.
|
||
|
||
https://on.cypress.io/auto-cancellation-mismatch`
|
||
},
|
||
DUPLICATE_TASK_KEY: (arg1: string[]) => {
|
||
return errTemplate`\
|
||
Warning: Multiple attempts to register the following task(s):
|
||
|
||
${fmt.listItems(arg1, { color: 'yellow' })}
|
||
|
||
Only the last attempt will be registered.`
|
||
},
|
||
INDETERMINATE_CI_BUILD_ID: (arg1: Record<string, string>, arg2: string[]) => {
|
||
return errTemplate`\
|
||
You passed the ${fmt.flag(`--group`)} or ${fmt.flag(`--parallel`)} flag but we could not automatically determine or generate a ciBuildId.
|
||
|
||
${fmt.listFlags(arg1, {
|
||
group: '--group',
|
||
parallel: '--parallel',
|
||
})}
|
||
|
||
In order to use either of these features a ciBuildId must be determined.
|
||
|
||
The ciBuildId is automatically detected if you are running Cypress in any of the these CI providers:
|
||
|
||
${fmt.listItems(arg2)}
|
||
|
||
Because the ciBuildId could not be auto-detected you must pass the --ci-build-id flag manually.
|
||
|
||
https://on.cypress.io/indeterminate-ci-build-id`
|
||
},
|
||
RECORD_PARAMS_WITHOUT_RECORDING: (arg1: Record<string, string>) => {
|
||
return errTemplate`\
|
||
You passed the ${fmt.flag(`--ci-build-id`)}, ${fmt.flag(`--group`)}, ${fmt.flag(`--tag`)}, ${fmt.flag(`--parallel`)}, or ${fmt.flag(`--auto-cancel-after-failures`)} flag without also passing the ${fmt.flag(`--record`)} flag.
|
||
|
||
${fmt.listFlags(arg1, {
|
||
ciBuildId: '--ci-build-id',
|
||
tags: '--tag',
|
||
group: '--group',
|
||
parallel: '--parallel',
|
||
autoCancelAfterFailures: '--auto-cancel-after-failures',
|
||
})}
|
||
|
||
These flags can only be used when recording to Cypress Cloud.
|
||
|
||
https://on.cypress.io/record-params-without-recording`
|
||
},
|
||
INCORRECT_CI_BUILD_ID_USAGE: (arg1: Record<string, string>) => {
|
||
return errTemplate`\
|
||
You passed the ${fmt.flag(`--ci-build-id`)} flag but did not provide either a ${fmt.flag(`--group`)} or ${fmt.flag(`--parallel`)} flag.
|
||
|
||
${fmt.listFlags(arg1, {
|
||
ciBuildId: '--ci-build-id',
|
||
})}
|
||
|
||
The --ci-build-id flag is used to either group or parallelize multiple runs together.
|
||
|
||
https://on.cypress.io/incorrect-ci-build-id-usage`
|
||
/* eslint-enable indent */
|
||
},
|
||
RECORD_KEY_MISSING: () => {
|
||
return errTemplate`\
|
||
You passed the ${fmt.flag(`--record`)} flag but did not provide us your Record Key.
|
||
|
||
You can pass us your Record Key like this:
|
||
|
||
${fmt.terminal(`cypress run --record --key <record_key>`)}
|
||
|
||
You can also set the key as an environment variable with the name: ${fmt.highlightSecondary(`CYPRESS_RECORD_KEY`)}
|
||
|
||
https://on.cypress.io/how-do-i-record-runs`
|
||
},
|
||
// TODO: make this relative path, not absolute
|
||
CANNOT_RECORD_NO_PROJECT_ID: (configFilePath: string) => {
|
||
return errTemplate`\
|
||
You passed the ${fmt.flag(`--record`)} flag but this project has not been setup to record.
|
||
|
||
This project is missing the ${fmt.highlight(`projectId`)} inside of: ${fmt.path(configFilePath)}
|
||
|
||
We cannot uniquely identify this project without this id.
|
||
|
||
You need to setup this project to record. This will generate a unique projectId.
|
||
|
||
Alternatively if you omit the ${fmt.flag(`--record`)} flag this project will run without recording.
|
||
|
||
https://on.cypress.io/recording-project-runs`
|
||
},
|
||
PROJECT_ID_AND_KEY_BUT_MISSING_RECORD_OPTION: (arg1: string) => {
|
||
return errTemplate`\
|
||
This project has been configured to record runs on our Cypress Cloud.
|
||
|
||
It currently has the projectId: ${fmt.highlight(arg1)}
|
||
|
||
You also provided your Record Key, but you did not pass the ${fmt.flag(`--record`)} flag.
|
||
|
||
This run will not be recorded.
|
||
|
||
If you meant to have this run recorded please additionally pass this flag:
|
||
|
||
${fmt.terminal('cypress run --record')}
|
||
|
||
If you don't want to record these runs, you can silence this warning:
|
||
|
||
${fmt.terminal('cypress run --record false')}
|
||
|
||
https://on.cypress.io/recording-project-runs`
|
||
},
|
||
CLOUD_INVALID_RUN_REQUEST: (arg1: {message: string, errors: string[], object: object}) => {
|
||
return errTemplate`\
|
||
Recording this run failed. The request was invalid.
|
||
|
||
${fmt.highlight(arg1.message)}
|
||
|
||
Errors:
|
||
|
||
${fmt.meta(arg1.errors)}
|
||
|
||
Request Sent:
|
||
|
||
${fmt.meta(arg1.object)}`
|
||
},
|
||
RECORDING_FROM_FORK_PR: () => {
|
||
return errTemplate`\
|
||
Warning: It looks like you are trying to record this run from a forked PR.
|
||
|
||
The ${fmt.highlight(`Record Key`)} is missing. Your CI provider is likely not passing private environment variables to builds from forks.
|
||
|
||
These results will not be recorded.
|
||
|
||
This error will not affect or change the exit code.`
|
||
},
|
||
CLOUD_CANNOT_UPLOAD_ARTIFACTS: (apiErr: Error) => {
|
||
return errTemplate`\
|
||
Warning: We encountered an error while uploading screenshots & videos from your run.
|
||
|
||
These results will not be recorded.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.highlightSecondary(apiErr)}`
|
||
},
|
||
CLOUD_CANNOT_CONFIRM_ARTIFACTS: (apiErr: Error) => {
|
||
return errTemplate`\
|
||
Warning: We encountered an error while confirming the upload of artifacts for this spec.
|
||
|
||
These results will not display artifacts.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.highlightSecondary(apiErr)}`
|
||
},
|
||
CLOUD_PROTOCOL_INITIALIZATION_FAILURE: (error: Error) => {
|
||
return errTemplate`\
|
||
Warning: We encountered an error while initializing the Test Replay recording for this spec.
|
||
|
||
These results will not display Test Replay recordings.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.highlightSecondary(error)}`
|
||
},
|
||
CLOUD_PROTOCOL_CAPTURE_FAILURE: (error: Error) => {
|
||
return errTemplate`\
|
||
Warning: We encountered an error while recording Test Replay data for this spec.
|
||
|
||
These results will not display Test Replay recordings.
|
||
|
||
This can happen for many reasons. If this problem persists:
|
||
|
||
- Try increasing the available disk space.
|
||
- Ensure that ${fmt.path(path.join(os.tmpdir(), 'cypress', 'protocol'))} is both readable and writable.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.highlightSecondary(error)}`
|
||
},
|
||
CLOUD_PROTOCOL_CANNOT_UPLOAD_ARTIFACT: (error: Error) => {
|
||
return errTemplate`\
|
||
Warning: We are unable to upload the Test Replay recording of this spec due to a missing or invalid upload URL.
|
||
|
||
These results will not display Test Replay recordings.
|
||
|
||
This error will not affect or change the exit code.
|
||
`
|
||
},
|
||
CLOUD_PROTOCOL_UPLOAD_UNKNOWN_ERROR: (error: Error) => {
|
||
return errTemplate`\
|
||
Warning: We encountered an error while uploading the Test Replay recording of this spec.
|
||
|
||
These results will not display Test Replay recordings.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.highlightSecondary(error)}
|
||
`
|
||
},
|
||
CLOUD_PROTOCOL_UPLOAD_HTTP_FAILURE: (error: Error & { url: string, status: number, statusText: string, responseBody: string }) => {
|
||
return errTemplate`\
|
||
Warning: We encountered an HTTP error while uploading the Test Replay recording for this spec.
|
||
|
||
These results will not display Test Replay recordings.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.url(error.url)} responded with HTTP ${fmt.stringify(error.status)}: ${fmt.highlightSecondary(error.statusText)}
|
||
|
||
${fmt.highlightTertiary(error.responseBody)}`
|
||
},
|
||
CLOUD_PROTOCOL_UPLOAD_NETWORK_FAILURE: (error: Error & { url: string }) => {
|
||
return errTemplate`\
|
||
Warning: We encountered a network error while uploading the Test Replay recording for this spec.
|
||
|
||
Please verify your network configuration for accessing ${fmt.url(error.url)}
|
||
|
||
These results will not display Test Replay recordings.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.highlightSecondary(error)}`
|
||
},
|
||
CLOUD_PROTOCOL_UPLOAD_STREAM_STALL_FAILURE: (error: Error & { chunkSizeBytes: number, maxActivityDwellTime: number }) => {
|
||
const dwellTimeSeconds = error.maxActivityDwellTime / 1000
|
||
const kbpsThreshold = (error.chunkSizeBytes / 1024) / dwellTimeSeconds
|
||
|
||
return errTemplate`\
|
||
Warning: We encountered slow network conditions while uploading the Test Replay recording for this spec.
|
||
|
||
The upload transfer rate fell below ${fmt.highlightSecondary(`${kbpsThreshold}kbps`)} over a sampling period of ${fmt.highlightSecondary(`${dwellTimeSeconds} seconds`)}.
|
||
|
||
To prevent long CI execution durations, this Test Replay recording will not be uploaded.
|
||
|
||
The results for this spec will not display Test Replay recordings.
|
||
|
||
If this error occurs often, the sampling period may be configured by setting the ${fmt.highlightSecondary('CYPRESS_TEST_REPLAY_UPLOAD_SAMPLING_INTERVAL')} environment variable to a higher value than ${fmt.stringify(error.maxActivityDwellTime)}.
|
||
`
|
||
},
|
||
CLOUD_PROTOCOL_UPLOAD_AGGREGATE_ERROR: (error: {
|
||
errors: (Error & { kind?: 'SystemError', url: string } | Error & { kind: 'HttpError', url: string, status?: string, statusText?: string, responseBody?: string })[]
|
||
}) => {
|
||
if (error.errors.length === 1) {
|
||
const firstError = error.errors[0]
|
||
|
||
if (firstError?.kind === 'SystemError') {
|
||
return AllCypressErrors.CLOUD_PROTOCOL_UPLOAD_NETWORK_FAILURE(firstError as Error & { url: string })
|
||
}
|
||
|
||
return AllCypressErrors.CLOUD_PROTOCOL_UPLOAD_HTTP_FAILURE(error.errors[0] as Error & { url: string, status: number, statusText: string, responseBody: string})
|
||
}
|
||
|
||
let systemErr = error.errors.find((err) => {
|
||
return err.kind === 'SystemError'
|
||
})
|
||
const recommendation = systemErr ? errPartial`Some or all of the errors encountered are system-level network errors. Please verify your network configuration for connecting to ${fmt.highlightSecondary(systemErr.url)}` : null
|
||
|
||
const fmtUploadError = ({ message, responseBody }: { message: string, responseBody?: string }) => {
|
||
return `${message}${responseBody ? `:\n${responseBody}\n` : ''}`
|
||
}
|
||
|
||
return errTemplate`\
|
||
Warning: We encountered multiple errors while uploading the Test Replay recording for this spec.
|
||
|
||
We attempted to upload the Test Replay recording ${fmt.stringify(error.errors.length)} times.
|
||
|
||
${recommendation}
|
||
|
||
${fmt.listItems(error.errors.map(fmtUploadError), { prefix: '' })}`
|
||
},
|
||
CLOUD_CANNOT_CREATE_RUN_OR_INSTANCE: (apiErr: Error) => {
|
||
return errTemplate`\
|
||
Warning: We encountered an error communicating with our servers.
|
||
|
||
This run will proceed, but will not be recorded.
|
||
|
||
This error will not affect or change the exit code.
|
||
|
||
${fmt.highlightSecondary(apiErr)}`
|
||
},
|
||
CLOUD_RECORD_KEY_NOT_VALID: (recordKey: string, projectId: string) => {
|
||
return errTemplate`\
|
||
Your Record Key ${fmt.highlight(recordKey)} is not valid with this projectId: ${fmt.highlightSecondary(projectId)}
|
||
|
||
It may have been recently revoked by you or another user.
|
||
|
||
Please log into Cypress Cloud to see the valid Record Keys.
|
||
|
||
https://on.cypress.io/dashboard/projects/${fmt.off(projectId)}`
|
||
},
|
||
CLOUD_PROJECT_NOT_FOUND: (projectId: string, configFileBaseName: string) => {
|
||
return errTemplate`\
|
||
We could not find a Cypress Cloud project with the projectId: ${fmt.highlight(projectId)}
|
||
|
||
This ${fmt.highlightSecondary(`projectId`)} came from your ${fmt.path(configFileBaseName)} file or an environment variable.
|
||
|
||
Please log into Cypress Cloud and find your project.
|
||
|
||
We will list the correct projectId in the 'Settings' tab.
|
||
|
||
Alternatively, you can create a new project directly from within the Cypress app.
|
||
|
||
https://on.cypress.io/cloud`
|
||
},
|
||
// TODO: make this relative path, not absolute
|
||
NO_PROJECT_ID: (configFilePath: string) => {
|
||
return errTemplate`Can't find ${fmt.highlight(`projectId`)} in the config file: ${fmt.path(configFilePath || '')}`
|
||
},
|
||
NO_PROJECT_FOUND_AT_PROJECT_ROOT: (projectRoot: string) => {
|
||
return errTemplate`Can't find a project at the path: ${fmt.path(projectRoot)}`
|
||
},
|
||
CANNOT_FETCH_PROJECT_TOKEN: () => {
|
||
return errTemplate`Can't find project's secret key.`
|
||
},
|
||
CANNOT_CREATE_PROJECT_TOKEN: () => {
|
||
return errTemplate`Can't create project's secret key.`
|
||
},
|
||
PORT_IN_USE_SHORT: (arg1: string | number) => {
|
||
return errTemplate`Port ${fmt.highlight(arg1)} is already in use.`
|
||
},
|
||
PORT_IN_USE_LONG: (arg1: string | number) => {
|
||
return errTemplate`\
|
||
Can't run project because port is currently in use: ${fmt.highlight(arg1)}
|
||
|
||
Assign a different port with the ${fmt.flag(`--port <port>`)} argument or shut down the other running process.`
|
||
},
|
||
ERROR_READING_FILE: (filePath: string, err: Error) => {
|
||
return errTemplate`\
|
||
Error reading from: ${fmt.path(filePath)}
|
||
|
||
${fmt.stackTrace(err)}`
|
||
},
|
||
ERROR_WRITING_FILE: (filePath: string, err: Error) => {
|
||
return errTemplate`\
|
||
Error writing to: ${fmt.path(filePath)}
|
||
|
||
${fmt.stackTrace(err)}`
|
||
},
|
||
NO_SPECS_FOUND: (folderPath: string, globPattern?: string[] | string | null) => {
|
||
// no glob provided, searched all specs
|
||
if (!globPattern) {
|
||
return errTemplate`\
|
||
Can't run because ${fmt.highlightSecondary(`no spec files`)} were found.
|
||
|
||
We searched for specs inside of this folder:
|
||
|
||
${fmt.listItem(folderPath)}`
|
||
}
|
||
|
||
const globPaths = _.castArray(globPattern).map((pattern) => {
|
||
const [resolvedBasePath, resolvedPattern] = parseResolvedPattern(folderPath, pattern)
|
||
|
||
return path.join(resolvedBasePath!, theme.yellow(resolvedPattern!))
|
||
})
|
||
|
||
const phrase = globPaths.length > 1 ? 'these glob patterns' : 'this glob pattern'
|
||
|
||
return errTemplate`\
|
||
Can't run because ${fmt.highlightSecondary(`no spec files`)} were found.
|
||
|
||
We searched for specs matching ${fmt.off(phrase)}:
|
||
|
||
${fmt.listItems(globPaths, { color: 'blue', prefix: ' > ' })}`
|
||
},
|
||
RENDERER_CRASHED: (browserName: string) => {
|
||
return errTemplate`\
|
||
We detected that the ${fmt.highlight(browserName)} Renderer process just crashed.
|
||
|
||
We have failed the current spec but will continue running the next spec.
|
||
|
||
This can happen for a number of different reasons.
|
||
|
||
If you're running lots of tests on a memory intense application.
|
||
- Try increasing the CPU/memory on the machine you're running on.
|
||
- Try enabling ${fmt.highlight('experimentalMemoryManagement')} in your config file.
|
||
- Try lowering ${fmt.highlight('numTestsKeptInMemory')} in your config file during 'cypress open'.
|
||
|
||
You can learn more here:
|
||
|
||
https://on.cypress.io/renderer-process-crashed`
|
||
},
|
||
BROWSER_CRASHED: (browserName: string, code: string | number, signal: string) => {
|
||
return errTemplate`\
|
||
We detected that the ${fmt.highlight(browserName)} process just crashed with code '${fmt.highlight(code)}' and signal '${fmt.highlight(signal)}'.
|
||
|
||
We have failed the current spec but will continue running the next spec.
|
||
|
||
This can happen for many different reasons:
|
||
|
||
- You wrote an endless loop and you must fix your own code
|
||
- You are running lots of tests on a memory intense application
|
||
- You are running in a memory starved VM environment
|
||
- There are problems with your GPU / GPU drivers
|
||
- There are browser bugs`
|
||
},
|
||
AUTOMATION_SERVER_DISCONNECTED: () => {
|
||
return errTemplate`The automation client disconnected. Cannot continue running tests.`
|
||
},
|
||
SUPPORT_FILE_NOT_FOUND: (supportFilePath: string) => {
|
||
return errTemplate`\
|
||
Your ${fmt.highlight(`supportFile`)} is missing or invalid: ${fmt.path(supportFilePath)}
|
||
|
||
The supportFile must be a .js, .ts, .coffee file or be supported by your preprocessor plugin (if configured).
|
||
|
||
Fix your support file, or set supportFile to ${fmt.highlightSecondary(`false`)} if a support file is not necessary for your project.
|
||
|
||
If you have just renamed the extension of your supportFile, restart Cypress.
|
||
|
||
https://on.cypress.io/support-file-missing-or-invalid`
|
||
},
|
||
DEFAULT_SUPPORT_FILE_NOT_FOUND: (supportFilePath: string) => {
|
||
return errTemplate`\
|
||
Your project does not contain a default ${fmt.highlight(`supportFile`)}. We expect a file matching ${fmt.path(supportFilePath)} to exist.
|
||
|
||
If a support file is not necessary for your project, set ${fmt.highlight(`supportFile`)} to ${fmt.highlightSecondary(`false`)}.
|
||
|
||
https://on.cypress.io/support-file-missing-or-invalid`
|
||
},
|
||
// TODO: make this relative path, not absolute
|
||
CONFIG_FILE_REQUIRE_ERROR: (configFilePath: string, err: Error) => {
|
||
return errTemplate`\
|
||
Your ${fmt.highlight(`configFile`)} is invalid: ${fmt.path(configFilePath)}
|
||
|
||
It threw an error when required, check the stack trace below:
|
||
|
||
${fmt.stackTrace(err)}
|
||
`
|
||
},
|
||
// TODO: make this relative path, not absolute
|
||
SETUP_NODE_EVENTS_IS_NOT_FUNCTION: (configFilePath: string, testingType: string, exported: any) => {
|
||
const code = errPartial`
|
||
{
|
||
${fmt.off(testingType)}: {
|
||
setupNodeEvents(on, config) {
|
||
${fmt.comment(`// configure tasks and plugins here`)}
|
||
}
|
||
}
|
||
}`
|
||
|
||
return errTemplate`\
|
||
Your ${fmt.highlight(`configFile`)} is invalid: ${fmt.path(configFilePath)}
|
||
|
||
The ${fmt.highlightSecondary(`${testingType}.setupNodeEvents()`)} function must be defined with the following signature:
|
||
|
||
${fmt.code(code)}
|
||
|
||
Instead we saw:
|
||
|
||
${fmt.stringify(exported)}
|
||
|
||
https://on.cypress.io/plugins-api
|
||
`
|
||
},
|
||
CONFIG_FILE_SETUP_NODE_EVENTS_ERROR: (configFilePath: string, testingType: TestingType, err: ErrorLike) => {
|
||
return errTemplate`
|
||
Your ${fmt.highlightSecondary(`configFile`)} threw an error from: ${fmt.path(configFilePath)}
|
||
|
||
The error was thrown while executing your ${fmt.highlight(`${testingType}.setupNodeEvents()`)} function:
|
||
|
||
${fmt.stackTrace(err)}
|
||
`
|
||
},
|
||
CONFIG_FILE_UNEXPECTED_ERROR: (configFilePath: string, err: ErrorLike) => {
|
||
return errTemplate`
|
||
Your ${fmt.highlight(`configFile`)} threw an error from: ${fmt.path(configFilePath)}
|
||
|
||
We stopped running your tests because your config file crashed.
|
||
|
||
${fmt.stackTrace(err)}
|
||
`
|
||
},
|
||
// TODO: make this relative path, not absolute
|
||
SETUP_NODE_EVENTS_INVALID_EVENT_NAME_ERROR: (configFilePath: string, invalidEventName: string, validEventNames: string[], err: Error) => {
|
||
return errTemplate`
|
||
Your ${fmt.highlightSecondary(`configFile`)} threw a validation error from: ${fmt.path(configFilePath)}
|
||
|
||
You must pass a valid event name when registering a plugin.
|
||
|
||
You passed: ${fmt.highlight(invalidEventName)}
|
||
|
||
The following are valid events:
|
||
|
||
${fmt.listItems(validEventNames)}
|
||
|
||
Learn more at https://on.cypress.io/writing-a-plugin#config
|
||
|
||
${fmt.stackTrace(err)}
|
||
`
|
||
},
|
||
BUNDLE_ERROR: (filePath: string, arg2: string) => {
|
||
// IF YOU MODIFY THIS MAKE SURE TO UPDATE
|
||
// THE ERROR MESSAGE IN THE RUNNER TOO
|
||
return errTemplate`\
|
||
Oops...we found an error preparing this test file:
|
||
|
||
${fmt.listItem(filePath)}
|
||
|
||
The error was:
|
||
|
||
${fmt.highlight(arg2)}
|
||
|
||
This occurred while Cypress was compiling and bundling your test code. This is usually caused by:
|
||
|
||
- A missing file or dependency
|
||
- A syntax error in the file or one of its dependencies
|
||
|
||
Fix the error in your code and re-run your tests.`
|
||
},
|
||
// happens when there is an error in configuration file like "cypress.config.js"
|
||
// TODO: make this relative path, not absolute
|
||
CONFIG_VALIDATION_MSG_ERROR: (fileType: 'configFile' | null, fileName: string | null, validationMsg: string) => {
|
||
if (!fileType) {
|
||
return errTemplate`
|
||
An invalid configuration value was set:
|
||
|
||
${fmt.highlight(validationMsg)}`
|
||
}
|
||
|
||
return errTemplate`
|
||
Your ${fmt.highlight(fileType)} as ${fmt.path(fileName)} set an invalid value:
|
||
|
||
${fmt.highlight(validationMsg)}`
|
||
},
|
||
// TODO: make this relative path, not absolute
|
||
CONFIG_VALIDATION_ERROR: (fileType: 'configFile' | null, filePath: string | null, validationResult: ConfigValidationFailureInfo) => {
|
||
const { key, type, value, list } = validationResult
|
||
|
||
if (!fileType) {
|
||
return errTemplate`\
|
||
An invalid configuration value was set.
|
||
|
||
Expected ${fmt.highlight(key)} to be ${fmt.off(type)}.
|
||
|
||
Instead the value was: ${fmt.stringify(value)}`
|
||
}
|
||
|
||
if (list) {
|
||
return errTemplate`\
|
||
Your ${fmt.highlight(fileType)} at ${fmt.path(filePath)} set an invalid value:
|
||
|
||
The error occurred while validating the ${fmt.highlightSecondary(list)} list.
|
||
|
||
Expected ${fmt.highlight(key)} to be ${fmt.off(type)}.
|
||
|
||
Instead the value was: ${fmt.stringify(value)}`
|
||
}
|
||
|
||
return errTemplate`\
|
||
Your ${fmt.highlight(fileType)} at ${fmt.path(filePath)} set an invalid value:
|
||
|
||
Expected ${fmt.highlight(key)} to be ${fmt.off(type)}.
|
||
|
||
Instead the value was: ${fmt.stringify(value)}`
|
||
},
|
||
RENAMED_CONFIG_OPTION: (arg1: {name: string, newName: string}) => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight(arg1.name)} configuration option you have supplied has been renamed.
|
||
|
||
Please rename ${fmt.highlight(arg1.name)} to ${fmt.highlightSecondary(arg1.newName)}`
|
||
},
|
||
CANNOT_CONNECT_BASE_URL: () => {
|
||
return errTemplate`\
|
||
Cypress failed to verify that your server is running.
|
||
|
||
Please start this server and then run Cypress again.`
|
||
},
|
||
CANNOT_CONNECT_BASE_URL_WARNING: (arg1: string) => {
|
||
return errTemplate`\
|
||
Cypress could not verify that this server is running:
|
||
|
||
${fmt.listItem(arg1)}
|
||
|
||
This server has been configured as your ${fmt.highlight(`baseUrl`)}, and tests will likely fail if it is not running.`
|
||
},
|
||
// TODO: test this
|
||
CANNOT_CONNECT_BASE_URL_RETRYING: (arg1: {attempt: number, baseUrl: string, remaining: number, delay: number}) => {
|
||
switch (arg1.attempt) {
|
||
case 1:
|
||
return errTemplate`\
|
||
Cypress could not verify that this server is running:
|
||
|
||
${fmt.listItem(arg1.baseUrl)}
|
||
|
||
We are verifying this server because it has been configured as your ${fmt.highlight(`baseUrl`)}.
|
||
|
||
Cypress automatically waits until your server is accessible before running tests.
|
||
|
||
${displayRetriesRemaining(arg1.remaining)}`
|
||
default:
|
||
return errTemplate`${displayRetriesRemaining(arg1.remaining)}`
|
||
}
|
||
},
|
||
// TODO: test this
|
||
INVALID_REPORTER_NAME: (arg1: {name: string, paths: string[], error: Error}) => {
|
||
return errTemplate`\
|
||
Error loading the reporter: ${fmt.highlight(arg1.name)}
|
||
|
||
We searched for the reporter in these paths:
|
||
|
||
${fmt.listItems(arg1.paths)}
|
||
|
||
Learn more at https://on.cypress.io/reporters
|
||
|
||
${fmt.stackTrace(arg1.error)}
|
||
`
|
||
},
|
||
// TODO: manually test this
|
||
NO_DEFAULT_CONFIG_FILE_FOUND: (arg1: string) => {
|
||
return errTemplate`\
|
||
Could not find a Cypress configuration file in this folder: ${fmt.path(arg1)}`
|
||
},
|
||
CONFIG_FILES_LANGUAGE_CONFLICT: (projectRoot: string, filesFound: string[]) => {
|
||
return errTemplate`
|
||
Could not load a Cypress configuration file because there are multiple matches.
|
||
|
||
We've found ${fmt.highlight(filesFound.length)} Cypress configuration files named
|
||
${fmt.highlight(filesFound.join(', '))} at the location below:
|
||
|
||
${fmt.listItem(projectRoot)}
|
||
|
||
Please delete the conflicting configuration files.
|
||
`
|
||
},
|
||
CONFIG_FILE_NOT_FOUND: (configFileBaseName: string, projectRoot: string) => {
|
||
return errTemplate`\
|
||
Could not find a Cypress configuration file.
|
||
|
||
We looked but did not find a ${fmt.highlight(configFileBaseName)} file in this folder: ${fmt.path(projectRoot)}`
|
||
},
|
||
INVOKED_BINARY_OUTSIDE_NPM_MODULE: () => {
|
||
return errTemplate`\
|
||
It looks like you are running the Cypress binary directly.
|
||
|
||
This is not the recommended approach, and Cypress may not work correctly.
|
||
|
||
Please install the ${fmt.highlight(`cypress`)} NPM package and follow the instructions here:
|
||
|
||
https://on.cypress.io/installing-cypress`
|
||
},
|
||
FREE_PLAN_EXCEEDS_MONTHLY_TESTS: (arg1: {link: string, usedTestsMessage: string, limit: number}) => {
|
||
return errTemplate`\
|
||
You've exceeded the limit of test results under your free plan this month. ${getUsedTestsMessage(arg1.limit, arg1.usedTestsMessage)}
|
||
|
||
To continue recording tests this month you must upgrade your account. Please visit your billing to upgrade to another billing plan.
|
||
|
||
${fmt.off(arg1.link)}`
|
||
},
|
||
FREE_PLAN_IN_GRACE_PERIOD_EXCEEDS_MONTHLY_TESTS: (arg1: {link: string, usedTestsMessage: string, gracePeriodMessage: string, limit: number}) => {
|
||
return errTemplate`\
|
||
You've exceeded the limit of test results under your free plan this month. ${getUsedTestsMessage(arg1.limit, arg1.usedTestsMessage)}
|
||
|
||
Your plan is now in a grace period, which means you will have the full benefits of your current plan until ${fmt.highlight(arg1.gracePeriodMessage)}.
|
||
|
||
Please visit your billing to upgrade your plan.
|
||
|
||
${fmt.off(arg1.link)}`
|
||
},
|
||
PLAN_EXCEEDS_MONTHLY_TESTS: (arg1: {link: string, planType: string, usedTestsMessage: string, limit: number}) => {
|
||
return errTemplate`\
|
||
You've exceeded the limit of test results under your ${fmt.highlight(arg1.planType)} billing plan this month. ${getUsedTestsMessage(arg1.limit, arg1.usedTestsMessage)}
|
||
|
||
To continue getting the full benefits of your current plan, please visit your billing to upgrade.
|
||
|
||
${fmt.off(arg1.link)}`
|
||
},
|
||
FREE_PLAN_IN_GRACE_PERIOD_PARALLEL_FEATURE: (arg1: {link: string, gracePeriodMessage: string}) => {
|
||
return errTemplate`\
|
||
${fmt.highlightSecondary(`Parallelization`)} is not included under your free plan.
|
||
|
||
Your plan is now in a grace period, which means your tests will still run in parallel until ${fmt.highlight(arg1.gracePeriodMessage)}. Please upgrade your plan to continue running your tests in parallel in the future.
|
||
|
||
${fmt.off(arg1.link)}`
|
||
},
|
||
PARALLEL_FEATURE_NOT_AVAILABLE_IN_PLAN: (arg1: {link: string}) => {
|
||
return errTemplate`\
|
||
${fmt.highlightSecondary(`Parallelization`)} is not included under your current billing plan.
|
||
|
||
To run your tests in parallel, please visit your billing and upgrade to another plan with parallelization.
|
||
|
||
${fmt.off(arg1.link)}`
|
||
},
|
||
PLAN_IN_GRACE_PERIOD_RUN_GROUPING_FEATURE_USED: (arg1: {link: string, gracePeriodMessage: string}) => {
|
||
return errTemplate`\
|
||
${fmt.highlightSecondary(`Grouping`)} is not included under your free plan.
|
||
|
||
Your plan is now in a grace period, which means your tests will still run with groups until ${fmt.highlight(arg1.gracePeriodMessage)}. Please upgrade your plan to continue running your tests with groups in the future.
|
||
|
||
${fmt.off(arg1.link)}`
|
||
},
|
||
RUN_GROUPING_FEATURE_NOT_AVAILABLE_IN_PLAN: (arg1: {link: string}) => {
|
||
return errTemplate`\
|
||
${fmt.highlightSecondary(`Grouping`)} is not included under your current billing plan.
|
||
|
||
To run your tests with groups, please visit your billing and upgrade to another plan with grouping.
|
||
|
||
${fmt.off(arg1.link)}`
|
||
},
|
||
// TODO: fix
|
||
FIXTURE_NOT_FOUND: (arg1: string, arg2: string[]) => {
|
||
return errTemplate`\
|
||
A fixture file could not be found at any of the following paths:
|
||
|
||
${fmt.listItem(arg1)}
|
||
${fmt.listItem(arg1)}.[ext]
|
||
|
||
Cypress looked for these file extensions at the provided path:
|
||
|
||
${fmt.listItem(arg2.join(', '))}
|
||
|
||
Provide a path to an existing fixture file.`
|
||
},
|
||
BAD_POLICY_WARNING: (policyKeys: string[]) => {
|
||
return errTemplate`\
|
||
Cypress detected policy settings on your computer that may cause issues.
|
||
|
||
The following policies were detected that may prevent Cypress from automating Chrome:
|
||
|
||
${fmt.listItems(policyKeys)}
|
||
|
||
For more information, see https://on.cypress.io/bad-browser-policy`
|
||
},
|
||
BAD_POLICY_WARNING_TOOLTIP: () => {
|
||
return errTemplate`Cypress detected policy settings on your computer that may cause issues with using this browser. For more information, see https://on.cypress.io/bad-browser-policy`
|
||
},
|
||
EXTENSION_NOT_LOADED: (browserName: string, extensionPath: string) => {
|
||
return errTemplate`\
|
||
${fmt.off(browserName)} could not install the extension at path: ${fmt.path(extensionPath)}
|
||
|
||
Please verify that this is the path to a valid, unpacked WebExtension.`
|
||
},
|
||
INVALID_CYPRESS_INTERNAL_ENV: (val: string) => {
|
||
return errTemplate`\
|
||
We have detected an unknown or unsupported ${fmt.highlightSecondary(`CYPRESS_INTERNAL_ENV`)} value: ${fmt.highlight(val)}
|
||
|
||
CYPRESS_INTERNAL_ENV is reserved for internal use and cannot be modified.`
|
||
},
|
||
CDP_VERSION_TOO_OLD: (minimumVersion: string, currentVersion: {major: number, minor: string | number}) => {
|
||
const phrase = currentVersion.major !== 0
|
||
? fmt.highlight(`${currentVersion.major}.${currentVersion.minor}`)
|
||
: fmt.off('an older version')
|
||
|
||
return errTemplate`A minimum CDP version of ${fmt.highlight(minimumVersion)} is required, but the current browser has ${phrase}.`
|
||
},
|
||
CDP_COULD_NOT_CONNECT: (browserName: string, port: number, err: Error) => {
|
||
// we include a stack trace here because it may contain useful information
|
||
// to debug since this is an "uncontrolled" error even though it doesn't
|
||
// come from a user
|
||
return errTemplate`\
|
||
Cypress failed to make a connection to the Chrome DevTools Protocol after retrying for 50 seconds.
|
||
|
||
This usually indicates there was a problem opening the ${fmt.off(_.capitalize(browserName))} browser.
|
||
|
||
The CDP port requested was ${fmt.highlight(port)}.
|
||
|
||
${fmt.stackTrace(err)}`
|
||
},
|
||
FIREFOX_COULD_NOT_CONNECT: (arg1: Error) => {
|
||
// we include a stack trace here because it may contain useful information
|
||
// to debug since this is an "uncontrolled" error even though it doesn't
|
||
// come from a user
|
||
return errTemplate`\
|
||
Cypress failed to make a connection to Firefox.
|
||
|
||
This usually indicates there was a problem opening the Firefox browser.
|
||
|
||
${fmt.stackTrace(arg1)}`
|
||
},
|
||
CDP_COULD_NOT_RECONNECT: (arg1: Error) => {
|
||
return errTemplate`\
|
||
There was an error reconnecting to the Chrome DevTools protocol. Please restart the browser.
|
||
|
||
${fmt.stackTrace(arg1)}`
|
||
},
|
||
CDP_RETRYING_CONNECTION: (attempt: string | number, browserName: string, connectRetryThreshold: number) => {
|
||
return errTemplate`Still waiting to connect to ${fmt.off(_.capitalize(browserName))}, retrying in 1 second ${fmt.meta(`(attempt ${attempt}/${connectRetryThreshold})`)}`
|
||
},
|
||
BROWSER_PROCESS_CLOSED_UNEXPECTEDLY: (browserName: string) => {
|
||
return errTemplate`\
|
||
We detected that the ${fmt.highlight(browserName)} browser process closed unexpectedly.
|
||
|
||
We have failed the current spec and aborted the run.`
|
||
},
|
||
BROWSER_PAGE_CLOSED_UNEXPECTEDLY: (browserName: string) => {
|
||
return errTemplate`\
|
||
We detected that the ${fmt.highlight(browserName)} tab running Cypress tests closed unexpectedly.
|
||
|
||
We have failed the current spec and aborted the run.`
|
||
},
|
||
UNEXPECTED_BEFORE_BROWSER_LAUNCH_PROPERTIES: (arg1: string[], arg2: string[]) => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight('launchOptions')} object returned by your plugin's ${fmt.highlightSecondary(`before:browser:launch`)} handler contained unexpected properties:
|
||
|
||
${fmt.listItems(arg1)}
|
||
|
||
launchOptions may only contain the properties:
|
||
|
||
${fmt.listItems(arg2)}
|
||
|
||
https://on.cypress.io/browser-launch-api`
|
||
},
|
||
// TODO: test this
|
||
COULD_NOT_PARSE_ARGUMENTS: (argName: string, argValue: string, errMsg: string) => {
|
||
return errTemplate`\
|
||
Cypress encountered an error while parsing the argument: ${fmt.highlight(`--${argName}`)}
|
||
|
||
You passed: ${fmt.highlightTertiary(argValue)}
|
||
|
||
The error was: ${fmt.highlightSecondary(errMsg)}`
|
||
},
|
||
FIREFOX_GECKODRIVER_FAILURE: (origin: string, err: Error) => {
|
||
return errTemplate`\
|
||
Cypress could not connect to Firefox.
|
||
|
||
An unexpected error was received from GeckoDriver: ${fmt.highlightSecondary(origin)}
|
||
|
||
To avoid this error, ensure that there are no other instances of Firefox launched by Cypress running.
|
||
|
||
${fmt.stackTrace(err)}`
|
||
},
|
||
FOLDER_NOT_WRITABLE: (arg1: string) => {
|
||
return errTemplate`\
|
||
This folder is not writable: ${fmt.path(arg1)}
|
||
|
||
Writing to this directory is required by Cypress in order to store screenshots and videos.
|
||
|
||
Enable write permissions to this directory to ensure screenshots and videos are stored.
|
||
|
||
If you don't require screenshots or videos to be stored you can safely ignore this warning.`
|
||
},
|
||
EXPERIMENTAL_JIT_COMPILE_REMOVED: () => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`experimentalJustInTimeCompile`)} configuration option was removed in ${fmt.cypressVersion(`14.0.0`)}.
|
||
A new ${fmt.highlightSecondary(`justInTimeCompile`)} configuration option is available and is now ${fmt.highlightSecondary(`true`)} by default.
|
||
You can safely remove this option from your config.`
|
||
},
|
||
EXPERIMENTAL_SESSION_AND_ORIGIN_REMOVED: () => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`experimentalSessionAndOrigin`)} configuration option was removed in ${fmt.cypressVersion(`12.0.0`)}.
|
||
|
||
You can safely remove this option from your config.
|
||
|
||
https://on.cypress.io/session
|
||
https://on.cypress.io/origin`
|
||
},
|
||
EXPERIMENTAL_SINGLE_TAB_RUN_MODE: () => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`experimentalSingleTabRunMode`)} experiment is currently only supported for Component Testing.
|
||
|
||
If you have feedback about the experiment, please join the discussion here: http://on.cypress.io/single-tab-run-mode`
|
||
},
|
||
EXPERIMENTAL_STUDIO_E2E_ONLY: () => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`experimentalStudio`)} experiment is currently only supported for End to End Testing.
|
||
|
||
If you have feedback about the experiment, please join the discussion here: http://on.cypress.io/studio-beta`
|
||
},
|
||
EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY: () => {
|
||
const code = errPartial`
|
||
{
|
||
e2e: {
|
||
experimentalRunAllSpecs: true
|
||
},
|
||
}`
|
||
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`experimentalRunAllSpecs`)} experiment is currently only supported for End to End Testing and must be configured as an e2e testing type property: ${fmt.highlightSecondary(`e2e.experimentalRunAllSpecs`)}.
|
||
|
||
${fmt.code(code)}
|
||
|
||
If you have feedback about the experiment, please join the discussion here: http://on.cypress.io/run-all-specs`
|
||
},
|
||
EXPERIMENTAL_ORIGIN_DEPENDENCIES_E2E_ONLY: () => {
|
||
const code = errPartial`
|
||
{
|
||
e2e: {
|
||
experimentalOriginDependencies: true
|
||
},
|
||
}`
|
||
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`experimentalOriginDependencies`)} experiment is currently only supported for End to End Testing and must be configured as an e2e testing type property: ${fmt.highlightSecondary(`e2e.experimentalOriginDependencies`)}.
|
||
|
||
${fmt.code(code)}`
|
||
},
|
||
JIT_COMPONENT_TESTING: () => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`justInTimeCompile`)} configuration is only supported for Component Testing.`
|
||
},
|
||
EXPERIMENTAL_SKIP_DOMAIN_INJECTION_REMOVED: () => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`experimentalSkipDomainInjection`)} experiment is over. ${fmt.highlight('document.domain')} injection is now off by default.
|
||
|
||
Read the migration guide for Cypress v14.0.0: https://on.cypress.io/migration-guide
|
||
`
|
||
},
|
||
// TODO: link to docs on injectDocumentDomain
|
||
INJECT_DOCUMENT_DOMAIN_DEPRECATION: () => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight('injectDocumentDomain')} option is deprecated. Interactions with intra-test navigations to differing hostnames must now be wrapped in ${fmt.highlight('cy.origin')} commands, even if the hostname is a subdomain. This configuration option will be removed in a future version of Cypress.
|
||
|
||
Read the documentation for the injectDocumentDomain configuration option: https://on.cypress.io/inject-document-domain-configuration
|
||
`
|
||
},
|
||
INJECT_DOCUMENT_DOMAIN_E2E_ONLY: () => {
|
||
// TODO: link to docs on injectDocumentDomain
|
||
return errTemplate`\
|
||
The ${fmt.highlight('injectDocumentDomain')} option is only available for E2E testing.
|
||
|
||
Read the documentation for the injectDocumentDomain configuration option: https://on.cypress.io/inject-document-domain-configuration
|
||
`
|
||
},
|
||
INVALID_CONFIG_OPTION: (arg1: string[]) => {
|
||
const phrase = arg1.length > 1 ? 'options are' : 'option is'
|
||
|
||
return errTemplate`\
|
||
The following configuration ${fmt.off(phrase)} invalid:
|
||
|
||
${fmt.listItems(arg1, { color: 'yellow' })}
|
||
|
||
https://on.cypress.io/configuration
|
||
`
|
||
},
|
||
PLUGINS_RUN_EVENT_ERROR: (arg1: string, arg2: Error) => {
|
||
return errTemplate`\
|
||
An error was thrown in your plugins file while executing the handler for the ${fmt.highlight(arg1)} event.
|
||
|
||
The error we received was:
|
||
|
||
${fmt.stackTrace(arg2)}`
|
||
},
|
||
|
||
UNSUPPORTED_BROWSER_VERSION: (errorMsg: string) => {
|
||
return errTemplate`${fmt.off(errorMsg)}`
|
||
},
|
||
|
||
MULTIPLE_SUPPORT_FILES_FOUND: (arg1: string, arg2: string[]) => {
|
||
return errTemplate`\
|
||
There were multiple support files found matching your ${fmt.highlightSecondary(`supportFile`)} pattern.
|
||
|
||
Your supportFile is set to: ${fmt.highlight(arg1)}
|
||
|
||
We found the following files:
|
||
|
||
${fmt.listItems(arg2)}
|
||
|
||
Please remove or combine the support files into a single file.`
|
||
},
|
||
|
||
VIDEO_UPLOAD_ON_PASSES_REMOVED: (_errShape: BreakingErrResult) => {
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`videoUploadOnPasses`)} configuration option was removed in ${fmt.cypressVersion(`13.0.0`)}.
|
||
|
||
You can safely remove this option from your config.
|
||
|
||
https://on.cypress.io/migration-guide`
|
||
},
|
||
|
||
CONFIG_FILE_INVALID_ROOT_CONFIG: (errShape: BreakingErrResult) => {
|
||
const code = errPartial`
|
||
{
|
||
e2e: {
|
||
specPattern: '...',
|
||
},
|
||
component: {
|
||
specPattern: '...',
|
||
},
|
||
}`
|
||
|
||
return errTemplate`\
|
||
The ${fmt.highlight(errShape.name)} configuration option is invalid when set from the root of the config object.
|
||
|
||
Set it within a testing type property: ${fmt.highlightSecondary(`e2e.${errShape.name}`)} and ${fmt.highlightSecondary(`component.${errShape.name}`)}
|
||
|
||
${fmt.code(code)}`
|
||
},
|
||
|
||
CONFIG_FILE_INVALID_ROOT_CONFIG_E2E: (errShape: BreakingErrResult) => {
|
||
const code = errPartial`
|
||
{
|
||
e2e: {
|
||
${fmt.off(errShape.name)}: '...',
|
||
}
|
||
}`
|
||
|
||
return errTemplate`\
|
||
The ${fmt.highlight(errShape.name)} configuration option is invalid when set from the root of the config object.
|
||
|
||
Set it within a testing type property: ${fmt.highlightSecondary(`e2e.${errShape.name}`)}
|
||
|
||
${fmt.code(code)}`
|
||
},
|
||
|
||
CONFIG_FILE_INVALID_ROOT_CONFIG_COMPONENT: (errShape: BreakingErrResult) => {
|
||
const code = errPartial`
|
||
{
|
||
component: {
|
||
${fmt.off(errShape.name)}: '...',
|
||
}
|
||
}`
|
||
|
||
return errTemplate`\
|
||
The ${fmt.highlight(errShape.name)} configuration option is invalid when set from the root of the config object.
|
||
|
||
Set it within a testing type property: ${fmt.highlightSecondary(`component.${errShape.name}`)}
|
||
|
||
${fmt.code(code)}`
|
||
},
|
||
|
||
// TODO: add path to config file
|
||
CONFIG_FILE_INVALID_TESTING_TYPE_CONFIG_COMPONENT: (errShape: BreakingErrResult) => {
|
||
const code = errPartial`
|
||
{
|
||
e2e: {
|
||
${fmt.off(errShape.name)}: '...',
|
||
}
|
||
}`
|
||
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`component.${errShape.name}`)} configuration option is not valid for component testing.
|
||
|
||
Please remove this option or add this as an e2e testing type property: ${fmt.highlightSecondary(`e2e.${errShape.name}`)}
|
||
|
||
${fmt.code(code)}`
|
||
},
|
||
|
||
CONFIG_FILE_INVALID_TESTING_TYPE_CONFIG_E2E: (errShape: BreakingErrResult) => {
|
||
const code = errPartial`
|
||
{
|
||
e2e: {
|
||
${fmt.off(errShape.name)}: '...',
|
||
}
|
||
}`
|
||
|
||
return errTemplate`\
|
||
The ${fmt.highlight(`e2e.${errShape.name}`)} configuration option is not valid for e2e testing.
|
||
|
||
Please remove this option or add this as a component testing type property: ${fmt.highlightSecondary(`component.${errShape.name}`)}
|
||
|
||
${fmt.code(code)}`
|
||
},
|
||
|
||
CONFIG_FILE_DEV_SERVER_IS_NOT_VALID: (configFilePath: string, setupNodeEvents: any) => {
|
||
const re = /.?(cypress\.config.*)/
|
||
const configFile = configFilePath.match(re)?.[1] ?? `configFile`
|
||
|
||
const code = errPartial`
|
||
{
|
||
component: {
|
||
devServer: {
|
||
framework: 'react', ${fmt.comment('// Your framework')}
|
||
bundler: 'webpack' ${fmt.comment('// Your dev server')}
|
||
}
|
||
}
|
||
}`
|
||
|
||
return errTemplate`\
|
||
Your ${fmt.highlightSecondary(configFile)} is invalid: ${fmt.path(configFilePath)}
|
||
|
||
The ${fmt.highlight(`component.devServer`)} must be an object with a supported ${fmt.highlight('framework')} and ${fmt.highlight('bundler')}.
|
||
|
||
${fmt.code(code)}
|
||
|
||
Instead, we saw:
|
||
|
||
${fmt.stringify(setupNodeEvents)}
|
||
|
||
Learn more: https://on.cypress.io/dev-server
|
||
`
|
||
},
|
||
|
||
CONFIG_FILE_DEV_SERVER_INVALID_RETURN: (devServerOptions: any) => {
|
||
return errTemplate`
|
||
The returned value of the ${fmt.highlight('devServer')} function is not valid.
|
||
|
||
The returned value must be an object with a ${fmt.highlight('port')} property of the dev-server that is running.
|
||
|
||
Instead, we saw:
|
||
|
||
${fmt.stringify(devServerOptions)}
|
||
|
||
Learn more: https://on.cypress.io/dev-server
|
||
`
|
||
},
|
||
|
||
UNEXPECTED_MUTATION_ERROR: (mutationField: string, args: any, err: Error) => {
|
||
return errTemplate`
|
||
An unexpected internal error occurred while executing the ${fmt.highlight(mutationField)} operation with payload:
|
||
|
||
${fmt.stringify(args)}
|
||
|
||
${fmt.stackTrace(err)}
|
||
`
|
||
},
|
||
|
||
CLOUD_GRAPHQL_ERROR: (err: Error) => {
|
||
return errTemplate`
|
||
We received an unexpected error response from the request to Cypress Cloud:
|
||
|
||
${fmt.stringify(err.message)}
|
||
`
|
||
},
|
||
|
||
UNEXPECTED_INTERNAL_ERROR: (err: Error) => {
|
||
return errTemplate`
|
||
We encountered an unexpected internal error.
|
||
|
||
Please check GitHub or open a new issue if you don't see one already with the details below:
|
||
|
||
${fmt.stackTrace(err)}
|
||
`
|
||
},
|
||
|
||
DEV_SERVER_CONFIG_FILE_NOT_FOUND: (devServer: 'vite' | 'webpack', root: string, searchedFor: string[]) => {
|
||
const devServerConfigFile = `${devServer}Config`
|
||
|
||
return errTemplate`\
|
||
You are using ${fmt.highlight(devServer)} for your dev server, but a configuration file was not found. We traversed upwards from:
|
||
|
||
${fmt.highlightSecondary(root)}
|
||
|
||
looking for a file named:
|
||
|
||
${fmt.listItems(searchedFor, { prefix: ' - ' })}
|
||
|
||
Add your ${fmt.highlight(devServer)} config at one of the above paths, or import your configuration file and provide it to
|
||
the devServer config as a ${fmt.highlight(devServerConfigFile)} option.
|
||
`
|
||
},
|
||
|
||
TESTING_TYPE_NOT_CONFIGURED: (testingType: TestingType) => {
|
||
return errTemplate`
|
||
The testing type selected (${fmt.highlight(testingType)}) is not configured in your config file.
|
||
|
||
Please run ‘cypress open’ and choose your testing type to automatically update your configuration file.
|
||
|
||
https://on.cypress.io/configuration
|
||
`
|
||
},
|
||
|
||
COMPONENT_TESTING_MISMATCHED_DEPENDENCIES: (dependencies: Cypress.DependencyToInstall[]) => {
|
||
const deps = dependencies.map<string>((dep) => {
|
||
if (dep.detectedVersion) {
|
||
return `\`${dep.dependency.installer}\`. Expected ${dep.dependency.minVersion}, found ${dep.detectedVersion}.`
|
||
}
|
||
|
||
return `\`${dep.dependency.installer}\`. Expected ${dep.dependency.minVersion} but dependency was not found.`
|
||
})
|
||
|
||
return errTemplate`
|
||
We detected that you have versions of dependencies that are not officially supported:
|
||
|
||
${fmt.listItems(deps, { prefix: ' - ' })}
|
||
|
||
If you're experiencing problems, ensure your dependencies are on a supported version and restart Cypress.
|
||
`
|
||
},
|
||
|
||
PROXY_ENCOUNTERED_INVALID_HEADER_NAME: (header: any, method: string, url: string, error: Error) => {
|
||
return errTemplate`
|
||
Warning: While proxying a ${fmt.highlight(method)} request to ${fmt.url(url)}, an HTTP header did not pass validation, and was removed. This header will not be present in the response received by the application under test.
|
||
|
||
Invalid header name: ${fmt.code(JSON.stringify(header, undefined, 2))}
|
||
|
||
${fmt.highlightSecondary(error)}
|
||
`
|
||
},
|
||
|
||
PROXY_ENCOUNTERED_INVALID_HEADER_VALUE: (header: any, method: string, url: string, error: Error) => {
|
||
return errTemplate`
|
||
Warning: While proxying a ${fmt.highlight(method)} request to ${fmt.url(url)}, an HTTP header value did not pass validation, and was removed. This header will not be present in the response received by the application under test.
|
||
|
||
Invalid header value: ${fmt.code(JSON.stringify(header, undefined, 2))}
|
||
|
||
${fmt.highlightSecondary(error)}
|
||
`
|
||
},
|
||
} as const
|
||
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||
const _typeCheck: Record<keyof AllCypressErrorObj, (...args: any[]) => ErrTemplateResult> = AllCypressErrors
|
||
|
||
export type AllCypressErrorObj = typeof AllCypressErrors
|
||
|
||
export type AllCypressErrorNames = keyof typeof AllCypressErrors
|
||
|
||
/**
|
||
* Given an error name & params for the error, returns a "CypressError",
|
||
* with a forBrowser property, used when we want to format the value for sending to
|
||
* the browser rather than the terminal.
|
||
*
|
||
* @param type
|
||
* @param args
|
||
* @returns
|
||
*/
|
||
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(`UNKNOWN ERROR ${JSON.stringify(type)}`) as CypressError
|
||
|
||
err.isCypressErr = false
|
||
err.type = type
|
||
err.messageMarkdown = err.message
|
||
|
||
return err
|
||
}
|
||
|
||
// @ts-expect-error
|
||
const result = AllCypressErrors[type](...args) as ErrTemplateResult
|
||
|
||
const { message, details, originalError, messageMarkdown } = result
|
||
|
||
const err = new Error(message) as CypressError
|
||
|
||
err.isCypressErr = true
|
||
err.type = type
|
||
err.details = details
|
||
err.messageMarkdown = messageMarkdown
|
||
err.originalError = originalError
|
||
|
||
if (originalError) {
|
||
err.stack = originalError.stack
|
||
err.stackWithoutMessage = stackWithoutMessage(originalError.stack ?? '')
|
||
} else {
|
||
const newErr = new Error()
|
||
|
||
Error.captureStackTrace(newErr, getError)
|
||
err.stack = newErr.stack
|
||
err.stackWithoutMessage = stackWithoutMessage(err.stack ?? '')
|
||
}
|
||
|
||
return err
|
||
}
|
||
|
||
export const logWarning = function <Type extends keyof AllCypressErrorObj> (type: Type, ...args: Parameters<AllCypressErrorObj[Type]>) {
|
||
const err = getError(type, ...args)
|
||
|
||
logError(err, 'magenta')
|
||
|
||
return null
|
||
}
|
||
|
||
export const throwErr = function <Type extends keyof AllCypressErrorObj> (type: Type, ...args: Parameters<AllCypressErrorObj[Type]>) {
|
||
const err = getError(type, ...args)
|
||
|
||
if (!err.originalError) {
|
||
Error.captureStackTrace(err, throwErr)
|
||
err.stackWithoutMessage = stackWithoutMessage(err.stack ?? '')
|
||
}
|
||
|
||
throw err
|
||
}
|
||
|
||
// For when the error is passed via the socket-base
|
||
interface GenericError extends Error {
|
||
forBrowser?: never
|
||
stackWithoutMessage?: never
|
||
[key: string]: any
|
||
}
|
||
|
||
export const cloneErr = function (err: CypressError | GenericError, options: {html?: boolean} = {}) {
|
||
_.defaults(options, {
|
||
html: false,
|
||
})
|
||
|
||
// pull off these properties
|
||
const obj = _.pick(err, 'message', 'messageMarkdown', 'type', 'name', 'stack', 'fileName', 'lineNumber', 'columnNumber') as ClonedError
|
||
|
||
if (options.html) {
|
||
obj.message = ansi_up.ansi_to_html(err.message)
|
||
// revert back the distorted characters
|
||
// in case there is an error in a child_process
|
||
// that contains quotes
|
||
.replace(/\&\#x27;/g, '\'')
|
||
.replace(/\"\;/g, '"')
|
||
}
|
||
|
||
// and any own (custom) properties
|
||
// of the err object
|
||
Object.entries(err || {}).forEach(([prop, val]) => {
|
||
obj[prop] = val
|
||
})
|
||
|
||
if (err.stackWithoutMessage) {
|
||
obj.stack = err.stackWithoutMessage
|
||
}
|
||
|
||
return obj
|
||
}
|
||
|
||
export {
|
||
stripAnsi,
|
||
getError as get,
|
||
logWarning as warning,
|
||
}
|
||
|
||
// Re-exporting old namespaces for legacy server access
|
||
export {
|
||
logError as log,
|
||
isCypressErr,
|
||
} from './errorUtils'
|