mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-25 01:49:06 -05:00
dependency(listr): upgrade listr 3.x to 9.x (#33640)
* chore(deps): upgrade listr 3.x to 9.x * use important strings to assert install output instead of fragile snapshots * rm unused `enquirer` dep; write cli test results * revert persisting junit xml for now * ensure VerboseRenderer implements LstrRenderer contract * remove unnecessary vendorized VerboseRenderer; use behavioral assertions in verify instead of brittle snapshots * make most `any` types in cli installer explicit; remove unused deps * changelog * rm trailing slash from pr link * Update cli/lib/tasks/install.ts Co-authored-by: Bill Glesias <bglesias@gmail.com> * simplify task list definitions; improve type annotations * fix version output; improve readability of task generation * rm unused types * revert error handling regression * fix implicit any * more readability improvements; better listr mocking * apply similar readability improvements to verify * fix order of verify -> welcome message * chore: skip adding the install comment on the commit (#33685) * update axios (#33687) --------- Co-authored-by: Bill Glesias <bglesias@gmail.com> Co-authored-by: Matt Schile <mschile@cypress.io>
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
**Dependency Updates:**
|
||||
|
||||
- Upgraded `cachedir` from `^2.3.0` to `^2.4.0`. Addressed in [#33608](https://github.com/cypress-io/cypress/pull/33608).
|
||||
- Upgraded `listr2` from `3.8.3` to `^9.0.5`. Addressed in [#33640](https://github.com/cypress-io/cypress/pull/33640).
|
||||
- Upgraded `simple-git` from `3.33.0` to `3.36.0` to address a [Remote Code Execution](https://security.snyk.io/vuln/SNYK-JS-SIMPLEGIT-15456078) vulnerability reported in security scans. Addressed in [#33680](https://github.com/cypress-io/cypress/pull/33680).
|
||||
- Upgraded `ts-loader` from `9.5.2` to `9.5.7`. Addresses [#33648](https://github.com/cypress-io/cypress/issues/33648). Addressed in [#33691](https://github.com/cypress-io/cypress/pull/33691)
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
// Vendored from @cypress/listr-verbose-renderer
|
||||
import figures from 'figures'
|
||||
import cliCursor from 'cli-cursor'
|
||||
import chalk from 'chalk'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const formattedLog = (options: any, output: string): void => {
|
||||
const timestamp = dayjs().format(options.dateFormat)
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`${chalk.dim(`[${timestamp}]`)} ${output}`)
|
||||
}
|
||||
|
||||
const renderHelper = (task: any, event: any, options: any): void => {
|
||||
const log = formattedLog.bind(undefined, options)
|
||||
|
||||
if (event.type === 'STATE') {
|
||||
const message = task.isPending() ? 'started' : task.state
|
||||
|
||||
log(`${task.title} [${message}]`)
|
||||
|
||||
if (task.isSkipped() && task.output) {
|
||||
log(`${figures.arrowRight} ${task.output}`)
|
||||
}
|
||||
} else if (event.type === 'TITLE') {
|
||||
log(`${task.title} [title changed]`)
|
||||
}
|
||||
}
|
||||
|
||||
const render = (tasks: any[], options: any): void => {
|
||||
for (const task of tasks) {
|
||||
task.subscribe(
|
||||
(event: any) => {
|
||||
if (event.type === 'SUBTASKS') {
|
||||
render(task.subtasks, options)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
renderHelper(task, event, options)
|
||||
},
|
||||
(err: any) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(err)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class VerboseRenderer {
|
||||
private _tasks: any[]
|
||||
private _options: any
|
||||
|
||||
constructor (tasks: any[], options: any) {
|
||||
this._tasks = tasks
|
||||
this._options = Object.assign({
|
||||
dateFormat: 'HH:mm:ss',
|
||||
}, options)
|
||||
}
|
||||
|
||||
static get nonTTY (): boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
render (): void {
|
||||
cliCursor.hide()
|
||||
render(this._tasks, this._options)
|
||||
}
|
||||
|
||||
end (): void {
|
||||
cliCursor.show()
|
||||
}
|
||||
}
|
||||
|
||||
export default VerboseRenderer
|
||||
+122
-133
@@ -4,6 +4,7 @@ import path from 'path'
|
||||
import chalk from 'chalk'
|
||||
import Debug from 'debug'
|
||||
import { Listr } from 'listr2'
|
||||
import type { ListrTask, ListrContext } from 'listr2'
|
||||
import logSymbols from 'log-symbols'
|
||||
import { stripIndent } from 'common-tags'
|
||||
import timers from 'timers/promises'
|
||||
@@ -16,11 +17,23 @@ import state from './state'
|
||||
import unzip from './unzip'
|
||||
import logger from '../logger'
|
||||
import { throwFormErrorText, errors } from '../errors'
|
||||
import verbose from '../VerboseRenderer'
|
||||
import { relativeToRepoRoot } from '../relative-to-repo-root'
|
||||
const debug = Debug('cypress:cli')
|
||||
const debug = Debug('cypress:cli:install')
|
||||
|
||||
function _getBinaryUrlFromBuildInfo (version: string, arch: string, { commitSha, commitBranch }: any): string {
|
||||
interface CypressBuildInfo {
|
||||
commitSha: string
|
||||
commitBranch: string
|
||||
commitDate: string
|
||||
stable: boolean
|
||||
}
|
||||
|
||||
interface BuildPlatform {
|
||||
arch: string
|
||||
envVarVersion?: string
|
||||
buildInfo?: CypressBuildInfo
|
||||
}
|
||||
|
||||
function _getBinaryUrlFromBuildInfo (version: string, arch: string, { commitSha, commitBranch }: { commitSha: string, commitBranch: string }): string {
|
||||
const platform = os.platform()
|
||||
|
||||
if ((platform === 'win32') && (arch === 'arm64')) {
|
||||
@@ -76,71 +89,6 @@ const displayCompletionMsg = (): void => {
|
||||
logger.log()
|
||||
}
|
||||
|
||||
const downloadAndUnzip = ({ version, installDir, downloadDir }: any): any => {
|
||||
const progress = {
|
||||
throttle: 100,
|
||||
onProgress: null,
|
||||
}
|
||||
const downloadDestination = path.join(downloadDir, `cypress-${process.pid}.zip`)
|
||||
const rendererOptions = getRendererOptions()
|
||||
|
||||
// let the user know what version of cypress we're downloading!
|
||||
logger.log(`Installing Cypress ${chalk.gray(`(version: ${version})`)}`)
|
||||
logger.log()
|
||||
|
||||
const tasks = new Listr([
|
||||
{
|
||||
options: { title: util.titleize('Downloading Cypress') },
|
||||
task: async (ctx: any, task: any) => {
|
||||
// as our download progresses indicate the status
|
||||
progress.onProgress = progessify(task, 'Downloading Cypress')
|
||||
|
||||
const redirectVersion = await download.start({ version, downloadDestination, progress })
|
||||
|
||||
if (redirectVersion) version = redirectVersion
|
||||
|
||||
debug(`finished downloading file: ${downloadDestination}`)
|
||||
|
||||
// save the download destination for unzipping
|
||||
util.setTaskTitle(
|
||||
task,
|
||||
util.titleize(chalk.green('Downloaded Cypress')),
|
||||
rendererOptions.renderer,
|
||||
)
|
||||
},
|
||||
},
|
||||
unzipTask({
|
||||
progress,
|
||||
zipFilePath: downloadDestination,
|
||||
installDir,
|
||||
rendererOptions,
|
||||
}),
|
||||
{
|
||||
options: { title: util.titleize('Finishing Installation') },
|
||||
task: async (ctx: any, task: any) => {
|
||||
const cleanup = async () => {
|
||||
debug('removing zip file %s', downloadDestination)
|
||||
|
||||
await fs.remove(downloadDestination)
|
||||
}
|
||||
|
||||
await cleanup()
|
||||
|
||||
debug('finished installation in', installDir)
|
||||
|
||||
util.setTaskTitle(
|
||||
task,
|
||||
util.titleize(chalk.green('Finished Installation'), chalk.gray(installDir)),
|
||||
rendererOptions.renderer,
|
||||
)
|
||||
},
|
||||
},
|
||||
], { rendererOptions })
|
||||
|
||||
// start the tasks!
|
||||
return tasks.run()
|
||||
}
|
||||
|
||||
const validateOS = async (): Promise<RegExpMatchArray | null> => {
|
||||
const platformInfo = await util.getPlatformInfo()
|
||||
|
||||
@@ -151,7 +99,7 @@ const validateOS = async (): Promise<RegExpMatchArray | null> => {
|
||||
* Returns the version to install - either a string like `1.2.3` to be fetched
|
||||
* from the download server or a file path or HTTP URL.
|
||||
*/
|
||||
function getVersionOverride (version: string, { arch, envVarVersion, buildInfo }: any): string | undefined {
|
||||
function getVersionOverride (version: string, { arch, envVarVersion, buildInfo }: BuildPlatform): string | undefined {
|
||||
// let this environment variable reset the binary version we need
|
||||
if (envVarVersion) {
|
||||
return envVarVersion
|
||||
@@ -190,7 +138,12 @@ function getEnvVarVersion (): string | undefined {
|
||||
return envVarVersion
|
||||
}
|
||||
|
||||
const start = async (options: any = {}): Promise<any> => {
|
||||
interface StartOptions {
|
||||
force?: boolean
|
||||
buildInfo?: CypressBuildInfo
|
||||
}
|
||||
|
||||
const start = async (options: StartOptions = {}): Promise<ListrContext | void> => {
|
||||
debug('installing with options %j', options)
|
||||
|
||||
const envVarVersion = getEnvVarVersion()
|
||||
@@ -251,16 +204,16 @@ const start = async (options: any = {}): Promise<any> => {
|
||||
|
||||
try {
|
||||
await fs.ensureDir(cacheDir)
|
||||
} catch (err: any) {
|
||||
if (err.code === 'EACCES') {
|
||||
return throwFormErrorText(errors.invalidCacheDirectory)(stripIndent`
|
||||
Failed to access ${chalk.cyan(cacheDir)}:
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof Error && 'code' in err && err.code === 'EACCES') {
|
||||
return throwFormErrorText(errors.invalidCacheDirectory)(stripIndent`
|
||||
Failed to access ${chalk.cyan(cacheDir)}:
|
||||
|
||||
${err.message}
|
||||
`)
|
||||
${err.message}
|
||||
`)
|
||||
} else {
|
||||
throw err
|
||||
}
|
||||
|
||||
throw err
|
||||
}
|
||||
|
||||
const binaryPkg = await state.getBinaryPkgAsync(binaryDir)
|
||||
@@ -338,35 +291,27 @@ const start = async (options: any = {}): Promise<any> => {
|
||||
|
||||
const pathToLocalFile = await getLocalFilePath()
|
||||
|
||||
if (pathToLocalFile) {
|
||||
const absolutePath = path.resolve(versionToInstall)
|
||||
|
||||
debug('found local file at', absolutePath)
|
||||
debug('skipping download')
|
||||
|
||||
const rendererOptions = getRendererOptions()
|
||||
|
||||
return new Listr([unzipTask({
|
||||
progress: {
|
||||
throttle: 100,
|
||||
onProgress: null,
|
||||
},
|
||||
zipFilePath: absolutePath,
|
||||
installDir,
|
||||
rendererOptions,
|
||||
})], { rendererOptions }).run()
|
||||
}
|
||||
const tasks = pathToLocalFile ?
|
||||
installFromLocal(pathToLocalFile, installDir) :
|
||||
installFromRemote(versionToInstall, installDir)
|
||||
|
||||
if (options.force) {
|
||||
debug('Cypress already installed at', installDir)
|
||||
debug('but the installation was forced')
|
||||
}
|
||||
|
||||
debug('preparing to download and unzip version ', versionToInstall, 'to path', installDir)
|
||||
// let the user know what version of cypress we're downloading!
|
||||
logger.log(`Installing Cypress ${chalk.gray(`(version: ${versionToInstall})`)}`)
|
||||
logger.log()
|
||||
|
||||
const downloadDir = os.tmpdir()
|
||||
const taskRunner = new Listr(
|
||||
tasks,
|
||||
{
|
||||
silentRendererCondition: () => logger.logLevel() === 'silent',
|
||||
},
|
||||
)
|
||||
|
||||
await downloadAndUnzip({ version: versionToInstall, installDir, downloadDir })
|
||||
await taskRunner.run()
|
||||
|
||||
// delay 1 sec for UX, unless we are testing
|
||||
await timers.setTimeout(1000)
|
||||
@@ -374,54 +319,98 @@ const start = async (options: any = {}): Promise<any> => {
|
||||
displayCompletionMsg()
|
||||
}
|
||||
|
||||
const unzipTask = ({ zipFilePath, installDir, progress, rendererOptions }: any): any => {
|
||||
return {
|
||||
options: { title: util.titleize('Unzipping Cypress') },
|
||||
task: async (ctx: any, task: any) => {
|
||||
// as our unzip progresses indicate the status
|
||||
progress.onProgress = progessify(task, 'Unzipping Cypress')
|
||||
function downloadArchive (version: string, downloadDestination: string): ListrTask {
|
||||
const inProgressTitle = 'Downloading Cypress'
|
||||
const completedTitle = chalk.green('Downloaded Cypress')
|
||||
|
||||
await unzip.start({ zipFilePath, installDir, progress })
|
||||
util.setTaskTitle(
|
||||
task,
|
||||
util.titleize(chalk.green('Unzipped Cypress')),
|
||||
rendererOptions.renderer,
|
||||
)
|
||||
return {
|
||||
title: util.titleize(inProgressTitle),
|
||||
task: async (ctx, task) => {
|
||||
await download.start({
|
||||
version,
|
||||
downloadDestination,
|
||||
progress: {
|
||||
throttle: 100,
|
||||
onProgress: (percentComplete: number, remaining: number) => {
|
||||
task.title = progressTitle(inProgressTitle, percentComplete, remaining)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
debug(`finished downloading file: ${downloadDestination}`)
|
||||
|
||||
task.title = util.titleize(completedTitle)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const progessify = (task: any, title: string): any => {
|
||||
// return higher order function
|
||||
return (percentComplete: number, remaining: number) => {
|
||||
const percentCompleteStr = chalk.white(` ${percentComplete}%`)
|
||||
function installFromLocal (pathToLocalFile: string, installDir: string): ListrTask[] {
|
||||
const zipFilePath = path.resolve(pathToLocalFile)
|
||||
|
||||
// pluralize seconds remaining
|
||||
const remainingStr = chalk.gray(`${remaining}s`)
|
||||
debug('found local file at', zipFilePath)
|
||||
debug('skipping download')
|
||||
|
||||
util.setTaskTitle(
|
||||
task,
|
||||
util.titleize(title, percentCompleteStr, remainingStr),
|
||||
getRendererOptions().renderer,
|
||||
)
|
||||
return [
|
||||
unzipArchive(zipFilePath, installDir),
|
||||
]
|
||||
}
|
||||
|
||||
function installFromRemote (version: string, installDir: string): ListrTask[] {
|
||||
const downloadDestination = path.join(os.tmpdir(), `cypress-${process.pid}.zip`)
|
||||
|
||||
debug('preparing to download and unzip version ', version, 'to path', installDir)
|
||||
|
||||
return [
|
||||
downloadArchive(version, downloadDestination),
|
||||
unzipArchive(downloadDestination, installDir),
|
||||
cleanup(downloadDestination, installDir),
|
||||
]
|
||||
}
|
||||
|
||||
function unzipArchive (zipFilePath: string, installDir: string): ListrTask {
|
||||
const inProgressTitle = 'Unzipping Cypress'
|
||||
const completedTitle = chalk.green('Unzipped Cypress')
|
||||
|
||||
return {
|
||||
title: util.titleize(inProgressTitle),
|
||||
task: async (ctx, task) => {
|
||||
await unzip.start({
|
||||
zipFilePath,
|
||||
installDir,
|
||||
progress: {
|
||||
onProgress: (percentComplete: number, remaining: number) => {
|
||||
task.title = progressTitle(inProgressTitle, percentComplete, remaining)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
task.title = util.titleize(completedTitle)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// if we are running in CI then use
|
||||
// the verbose renderer else use
|
||||
// the default
|
||||
const getRendererOptions = (): any => {
|
||||
let renderer = util.isCi() ? verbose : 'default'
|
||||
|
||||
if (logger.logLevel() === 'silent') {
|
||||
renderer = 'silent'
|
||||
}
|
||||
|
||||
function cleanup (archiveLocation: string, installDir: string): ListrTask {
|
||||
return {
|
||||
renderer,
|
||||
title: util.titleize('Finishing Installation'),
|
||||
task: async (ctx, task) => {
|
||||
debug('removing zip file %s', archiveLocation)
|
||||
|
||||
await fs.remove(archiveLocation)
|
||||
|
||||
debug('finished installation in', installDir)
|
||||
|
||||
task.title = util.titleize(chalk.green('Finished Installation'), chalk.gray(installDir))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function progressTitle (title: string, percentComplete: number, remaining: number): string {
|
||||
return util.titleize(title,
|
||||
chalk.white(` ${percentComplete}%`),
|
||||
chalk.gray(`${remaining}s`),
|
||||
)
|
||||
}
|
||||
|
||||
export default {
|
||||
start,
|
||||
_getBinaryUrlFromBuildInfo,
|
||||
|
||||
+50
-73
@@ -6,7 +6,6 @@ import { stripIndent } from 'common-tags'
|
||||
import Bluebird from 'bluebird'
|
||||
import logSymbols from 'log-symbols'
|
||||
import os from 'os'
|
||||
import verbose from '../VerboseRenderer'
|
||||
import { throwFormErrorText, errors } from '../errors'
|
||||
import util from '../util'
|
||||
import logger from '../logger'
|
||||
@@ -181,87 +180,67 @@ const runSmokeTest = (binaryDir: string, options: any): any => {
|
||||
return userFriendlySpawn(linuxWithDisplayEnv)
|
||||
}
|
||||
|
||||
function testBinary (version: string, binaryDir: string, options: any): Promise<any> {
|
||||
debug('running binary verification check', version)
|
||||
function logVersionMismatch (binaryVersion: string, binaryDir: string, packageVersion: string): void {
|
||||
logger.log(`Found binary version ${chalk.green(binaryVersion)} installed in: ${chalk.cyan(binaryDir)}`)
|
||||
logger.log()
|
||||
logger.warn(stripIndent`
|
||||
|
||||
|
||||
${logSymbols.warning} Warning: Binary version ${chalk.green(binaryVersion)} does not match the expected package version ${chalk.green(packageVersion)}
|
||||
|
||||
These versions may not work properly together.
|
||||
`)
|
||||
|
||||
logger.log()
|
||||
}
|
||||
|
||||
async function verifyBinary (installedVersion: string, binaryDir: string, options: any): Promise<void> {
|
||||
debug('running binary verification check', installedVersion)
|
||||
|
||||
// if running from 'cypress verify', don't print this message
|
||||
if (!options.force) {
|
||||
logger.log(stripIndent`
|
||||
It looks like this is your first time using Cypress: ${chalk.cyan(version)}
|
||||
It looks like this is your first time using Cypress: ${chalk.cyan(installedVersion)}
|
||||
`)
|
||||
}
|
||||
|
||||
logger.log()
|
||||
|
||||
// if we are running in CI then use
|
||||
// the verbose renderer else use
|
||||
// the default
|
||||
let renderer = util.isCi() ? verbose : 'default'
|
||||
const verifyTaskRunner = new Listr([{
|
||||
title: util.titleize('Verifying Cypress can run', chalk.gray(binaryDir)),
|
||||
task: async (ctx, task) => {
|
||||
debug('clearing out the verified version')
|
||||
|
||||
// NOTE: under test we set the listr renderer to 'silent' in order to get deterministic snapshots
|
||||
if (logger.logLevel() === 'silent' || options.listrRenderer) renderer = 'silent'
|
||||
await state.clearBinaryStateAsync(binaryDir)
|
||||
|
||||
const rendererOptions = {
|
||||
renderer,
|
||||
}
|
||||
await Promise.all([
|
||||
runSmokeTest(binaryDir, options),
|
||||
Bluebird.delay(1500), // good user experience
|
||||
])
|
||||
|
||||
const tasks = new Listr([
|
||||
{
|
||||
title: util.titleize('Verifying Cypress can run', chalk.gray(binaryDir)),
|
||||
task: async (ctx: any, task: any) => {
|
||||
debug('clearing out the verified version')
|
||||
debug('write verified: true')
|
||||
|
||||
await state.clearBinaryStateAsync(binaryDir)
|
||||
await state.writeBinaryVerifiedAsync(true, binaryDir)
|
||||
|
||||
await Promise.all([
|
||||
runSmokeTest(binaryDir, options),
|
||||
Bluebird.delay(1500), // good user experience
|
||||
])
|
||||
|
||||
debug('write verified: true')
|
||||
|
||||
await state.writeBinaryVerifiedAsync(true, binaryDir)
|
||||
|
||||
util.setTaskTitle(
|
||||
task,
|
||||
util.titleize(
|
||||
chalk.green('Verified Cypress!'),
|
||||
chalk.gray(binaryDir),
|
||||
),
|
||||
rendererOptions.renderer as string,
|
||||
)
|
||||
},
|
||||
task.title = util.titleize(
|
||||
chalk.green('Verified Cypress!'),
|
||||
chalk.gray(binaryDir),
|
||||
)
|
||||
},
|
||||
] as any, rendererOptions as any)
|
||||
}], {
|
||||
silentRendererCondition: () => logger.logLevel() === 'silent',
|
||||
})
|
||||
|
||||
return tasks.run()
|
||||
}
|
||||
await verifyTaskRunner.run()
|
||||
|
||||
const maybeVerify = async (installedVersion: string, binaryDir: string, options: any): Promise<void> => {
|
||||
const isVerified = await state.getBinaryVerifiedAsync(binaryDir)
|
||||
|
||||
debug('is Verified ?', isVerified)
|
||||
|
||||
let shouldVerify = !isVerified
|
||||
|
||||
// force verify if options.force
|
||||
if (options.force) {
|
||||
debug('force verify')
|
||||
shouldVerify = true
|
||||
}
|
||||
|
||||
if (shouldVerify) {
|
||||
await testBinary(installedVersion, binaryDir, options)
|
||||
|
||||
if (options.welcomeMessage) {
|
||||
logger.log()
|
||||
logger.log('Opening Cypress...')
|
||||
}
|
||||
if (options.welcomeMessage) {
|
||||
logger.log()
|
||||
logger.log('Opening Cypress...')
|
||||
}
|
||||
}
|
||||
|
||||
export const start = async (options: any = {}): Promise<void> => {
|
||||
debug('verifying Cypress app')
|
||||
debug('verifying Cypress app with options %j', options)
|
||||
|
||||
_.defaults(options, {
|
||||
dev: false,
|
||||
@@ -351,20 +330,18 @@ export const start = async (options: any = {}): Promise<void> => {
|
||||
if (binaryVersion !== packageVersion) {
|
||||
// warn if we installed with CYPRESS_INSTALL_BINARY or changed version
|
||||
// in the package.json
|
||||
logger.log(`Found binary version ${chalk.green(binaryVersion)} installed in: ${chalk.cyan(binaryDir)}`)
|
||||
logger.log()
|
||||
logger.warn(stripIndent`
|
||||
|
||||
|
||||
${logSymbols.warning} Warning: Binary version ${chalk.green(binaryVersion)} does not match the expected package version ${chalk.green(packageVersion)}
|
||||
|
||||
These versions may not work properly together.
|
||||
`)
|
||||
|
||||
logger.log()
|
||||
logVersionMismatch(binaryVersion, binaryDir, packageVersion)
|
||||
}
|
||||
|
||||
await maybeVerify(binaryVersion, binaryDir, options)
|
||||
const isVerified = options.force ?
|
||||
false :
|
||||
await state.getBinaryVerifiedAsync(binaryDir)
|
||||
|
||||
debug('is Verified ?', isVerified)
|
||||
|
||||
if (!isVerified) {
|
||||
await verifyBinary(binaryVersion, binaryDir, options)
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.known) {
|
||||
throw err
|
||||
|
||||
@@ -21,7 +21,6 @@ import isInstalledGlobally from 'is-installed-globally'
|
||||
import logger from './logger'
|
||||
import Debug from 'debug'
|
||||
import fs from 'fs-extra'
|
||||
import { readFile } from 'fs/promises'
|
||||
import { relativeToRepoRoot } from './relative-to-repo-root'
|
||||
|
||||
const debug = Debug('cypress:cli')
|
||||
@@ -403,13 +402,6 @@ const util = {
|
||||
return (_.isFinite(eta) ? (eta / 1000) : 0).toFixed(0)
|
||||
},
|
||||
|
||||
setTaskTitle (task: any, title: string, renderer: string): void {
|
||||
// only update the renderer title when not running in CI
|
||||
if (renderer === 'default' && task.title !== title) {
|
||||
task.title = title
|
||||
}
|
||||
},
|
||||
|
||||
isInstalledGlobally (): boolean {
|
||||
return isInstalledGlobally
|
||||
},
|
||||
|
||||
+1
-4
@@ -36,22 +36,19 @@
|
||||
"cachedir": "^2.4.0",
|
||||
"chalk": "^4.1.0",
|
||||
"ci-info": "^4.1.0",
|
||||
"cli-cursor": "^3.1.0",
|
||||
"cli-table3": "0.6.1",
|
||||
"commander": "^6.2.1",
|
||||
"common-tags": "^1.8.0",
|
||||
"dayjs": "^1.10.4",
|
||||
"debug": "^4.3.4",
|
||||
"enquirer": "^2.3.6",
|
||||
"eventemitter2": "6.4.7",
|
||||
"execa": "4.1.0",
|
||||
"executable": "^4.1.1",
|
||||
"extract-zip": "2.0.1",
|
||||
"figures": "^3.2.0",
|
||||
"fs-extra": "^9.1.0",
|
||||
"hasha": "5.2.2",
|
||||
"is-installed-globally": "~0.4.0",
|
||||
"listr2": "^3.8.3",
|
||||
"listr2": "^9.0.5",
|
||||
"lodash": "^4.17.23",
|
||||
"log-symbols": "^4.0.0",
|
||||
"minimist": "^1.2.8",
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`/lib/tasks/install > .start > exits with error when installing on unsupported os > error when installing on unsupported os 1`] = `
|
||||
"[31mError: The Cypress App could not be installed. Your machine does not meet the operating system requirements.[39m
|
||||
[31m[39m
|
||||
[31mhttps://on.cypress.io/app/get-started/install-cypress#System-requirements[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: win32-ia32[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > is silent when log level is silent > silent install 1 1`] = `
|
||||
"[STARTED] Task without title.
|
||||
[SUCCESS] Task without title.
|
||||
[STARTED] Task without title.
|
||||
[SUCCESS] Task without title.
|
||||
[STARTED] Task without title.
|
||||
[SUCCESS] Task without title.
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > non-stable builds > logs a warning about installing a pre-release > pre-release warning 1`] = `
|
||||
"[33m⚠ Warning: You are installing a pre-release build of Cypress.[39m
|
||||
[33m[39m
|
||||
[33mBugs may be present which do not exist in production builds.[39m
|
||||
[33m[39m
|
||||
[33mThis build was created from:[39m
|
||||
[33m * Commit SHA: 3b7f0b5c59def1e9b5f385bd585c9b2836706c29[39m
|
||||
[33m * Commit Branch: aBranchName[39m
|
||||
[33m * Commit Timestamp: 1996-11-27T00:00:00.000Z[39m
|
||||
|
||||
Installing Cypress [90m(version: https://cdn.cypress.io/beta/binary/0.0.0-development/darwin-x64/aBranchName-3b7f0b5c59def1e9b5f385bd585c9b2836706c29/cypress.zip)[39m
|
||||
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
[SUCCESS] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
|
||||
You can now open Cypress by running one of the following, depending on your package manager:
|
||||
|
||||
[36m- npx cypress open[39m
|
||||
[36m- yarn cypress open[39m
|
||||
[36m- pnpm cypress open[39m
|
||||
|
||||
[90mhttps://on.cypress.io/opening-the-app[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > as a global install > logs global warning and download > warning installing as global 1 1`] = `
|
||||
"
|
||||
Cypress [32mx.x.x[39m is installed in [36m/cache/Cypress/1.2.3[39m
|
||||
|
||||
Installing Cypress [90m(version: 1.2.3)[39m
|
||||
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
[SUCCESS] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
|
||||
[33m⚠ Warning: It looks like you've installed Cypress globally.[39m
|
||||
[33m[39m
|
||||
[33m The recommended way to install Cypress is as a devDependency per project.[39m
|
||||
[33m[39m
|
||||
[33m You should probably run these commands:[39m
|
||||
[33m[39m
|
||||
[33m - [36mnpm uninstall -g cypress[39m[33m[39m
|
||||
[33m - [36mnpm install --save-dev cypress[39m[33m[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > failed write access to cache directory > logs error on failure > invalid cache directory 1 1`] = `
|
||||
"[31mError: Cypress cannot write to the cache directory due to file permissions[39m
|
||||
[31m[39m
|
||||
[31mSee discussion and possible solutions at[39m
|
||||
[31mhttps://github.com/cypress-io/cypress/issues/1281[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mFailed to access [36m/invalid/cache/dir[39m[31m:[39m
|
||||
[31m[39m
|
||||
[31mEACCES: permission denied, mkdir '/invalid'[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (Foo - OsVersion)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > warns when specifying cypress version in env > specify version in env vars 1 1`] = `
|
||||
"[33m⚠ Warning: Forcing a binary version different than the default.[39m
|
||||
[33m[39m
|
||||
[33m The CLI expected to install version: [32m1.2.3[39m[33m[39m
|
||||
[33m[39m
|
||||
[33m Instead we will install version: [32m0.12.1[39m[33m[39m
|
||||
[33m[39m
|
||||
[33m These versions may not work properly together.[39m
|
||||
|
||||
Installing Cypress [90m(version: 0.12.1)[39m
|
||||
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
[SUCCESS] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
|
||||
You can now open Cypress by running one of the following, depending on your package manager:
|
||||
|
||||
[36m- npx cypress open[39m
|
||||
[36m- yarn cypress open[39m
|
||||
[36m- pnpm cypress open[39m
|
||||
|
||||
[90mhttps://on.cypress.io/opening-the-app[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > when getting installed version does not match needed version > logs message and starts download > installed version does not match needed version 1 1`] = `
|
||||
"
|
||||
Cypress [32mx.x.x[39m is installed in [36m/cache/Cypress/1.2.3[39m
|
||||
|
||||
Installing Cypress [90m(version: 1.2.3)[39m
|
||||
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
[SUCCESS] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
|
||||
You can now open Cypress by running one of the following, depending on your package manager:
|
||||
|
||||
[36m- npx cypress open[39m
|
||||
[36m- yarn cypress open[39m
|
||||
[36m- pnpm cypress open[39m
|
||||
|
||||
[90mhttps://on.cypress.io/opening-the-app[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > when getting installed version fails > logs message and starts download > continues installing on failure 1 1`] = `
|
||||
"Installing Cypress [90m(version: 1.2.3)[39m
|
||||
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
[SUCCESS] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
|
||||
You can now open Cypress by running one of the following, depending on your package manager:
|
||||
|
||||
[36m- npx cypress open[39m
|
||||
[36m- yarn cypress open[39m
|
||||
[36m- pnpm cypress open[39m
|
||||
|
||||
[90mhttps://on.cypress.io/opening-the-app[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > when running in CI > uses verbose renderer > installing in ci 1 1`] = `
|
||||
"
|
||||
Cypress [32mx.x.x[39m is installed in [36m/cache/Cypress/1.2.3[39m
|
||||
|
||||
Installing Cypress [90m(version: 1.2.3)[39m
|
||||
|
||||
[STARTED] Task without title.
|
||||
[SUCCESS] Task without title.
|
||||
[STARTED] Task without title.
|
||||
[SUCCESS] Task without title.
|
||||
[STARTED] Task without title.
|
||||
[SUCCESS] Task without title.
|
||||
|
||||
You can now open Cypress by running one of the following, depending on your package manager:
|
||||
|
||||
[36m- npx cypress open[39m
|
||||
[36m- yarn cypress open[39m
|
||||
[36m- pnpm cypress open[39m
|
||||
|
||||
[90mhttps://on.cypress.io/opening-the-app[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > when there is no install version > logs message and starts download > installs without existing installation 1 1`] = `
|
||||
"Installing Cypress [90m(version: 1.2.3)[39m
|
||||
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
[SUCCESS] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
|
||||
You can now open Cypress by running one of the following, depending on your package manager:
|
||||
|
||||
[36m- npx cypress open[39m
|
||||
[36m- yarn cypress open[39m
|
||||
[36m- pnpm cypress open[39m
|
||||
|
||||
[90mhttps://on.cypress.io/opening-the-app[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > when version is already installed > logs 'skipping install' when explicit cypress install > version already installed - cypress install 1 1`] = `
|
||||
"
|
||||
Cypress [32m1.2.3[39m is installed in [36m/cache/Cypress/1.2.3[39m
|
||||
|
||||
Skipping installation:
|
||||
|
||||
Pass the [33m--force[39m option if you'd like to reinstall anyway.
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > when version is already installed > logs when already installed when run from postInstall > version already installed - postInstall 1 1`] = `
|
||||
"
|
||||
Cypress [32m1.2.3[39m is installed in [36m/cache/Cypress/1.2.3[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > override version > with force: true > logs message and starts download > forcing true always installs 1 1`] = `
|
||||
"
|
||||
Cypress [32m1.2.3[39m is installed in [36m/cache/Cypress/1.2.3[39m
|
||||
|
||||
Installing Cypress [90m(version: 1.2.3)[39m
|
||||
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mDownloaded Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[SUCCESS] [34m [32mUnzipped Cypress[39m[34m[39m
|
||||
[STARTED] Task without title.
|
||||
[TITLE] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
[SUCCESS] [34m [32mFinished Installation[39m[34m [90m/cache/Cypress/1.2.3[39m[34m[39m
|
||||
|
||||
You can now open Cypress by running one of the following, depending on your package manager:
|
||||
|
||||
[36m- npx cypress open[39m
|
||||
[36m- yarn cypress open[39m
|
||||
[36m- pnpm cypress open[39m
|
||||
|
||||
[90mhttps://on.cypress.io/opening-the-app[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`/lib/tasks/install > .start > skips install > when environment variable is set > skip installation 1 1`] = `
|
||||
"[33mNote:[39m Skipping binary installation: Environment variable CYPRESS_INSTALL_BINARY = 0.
|
||||
|
||||
"
|
||||
`;
|
||||
@@ -1,381 +0,0 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`lib/tasks/verify > logs error and exits when executable cannot be found 1`] = `
|
||||
"[31mError: No version of Cypress is installed in: [36m/cache/Cypress/1.2.3/Cypress.app[39m[31m[39m
|
||||
[31m[39m
|
||||
[31mPlease reinstall Cypress by running: [36mcypress install[39m[31m[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mCypress executable not found at: [36m/cache/Cypress/1.2.3/Cypress.app/Contents/MacOS/Cypress[39m[31m[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > logs error and exits when no version of Cypress is installed 1`] = `
|
||||
"[31mError: No version of Cypress is installed in: [36m/cache/Cypress/1.2.3/Cypress.app[39m[31m[39m
|
||||
[31m[39m
|
||||
[31mPlease reinstall Cypress by running: [36mcypress install[39m[31m[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mCypress executable not found at: [36m/cache/Cypress/1.2.3/Cypress.app/Contents/MacOS/Cypress[39m[31m[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > logs error when child process hangs 1`] = `
|
||||
"It looks like this is your first time using Cypress: [36m1.2.3[39m
|
||||
|
||||
[31mError: Cypress verification timed out.[39m
|
||||
[31m[39m
|
||||
[31mThis command failed with the following output:[39m
|
||||
[31m[39m
|
||||
[31m/cache/Cypress/1.2.3/Cypress.app/Contents/MacOS/Cypress --no-sandbox --smoke-test --ping=222[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31msome stderr[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > logs error when child process returns incorrect stdout (stderr when exists) 1`] = `
|
||||
"It looks like this is your first time using Cypress: [36m1.2.3[39m
|
||||
|
||||
[31mError: Cypress failed to start.[39m
|
||||
[31m[39m
|
||||
[31mThis may be due to a missing library or dependency. https://on.cypress.io/required-dependencies[39m
|
||||
[31m[39m
|
||||
[31mPlease refer to the error below for more details.[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31msome stderr[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > logs error when child process returns incorrect stdout (stdout when no stderr) 1`] = `
|
||||
"It looks like this is your first time using Cypress: [36m1.2.3[39m
|
||||
|
||||
[31mError: Cypress failed to start.[39m
|
||||
[31m[39m
|
||||
[31mThis may be due to a missing library or dependency. https://on.cypress.io/required-dependencies[39m
|
||||
[31m[39m
|
||||
[31mPlease refer to the error below for more details.[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > logs warning when installed version does not match verified version 1`] = `
|
||||
"Found binary version [32mbloop[39m installed in: [36m/cache/Cypress/1.2.3/Cypress.app[39m
|
||||
|
||||
[33m⚠ Warning: Binary version [32mbloop[39m[33m does not match the expected package version [32m1.2.3[39m[33m[39m
|
||||
[33m[39m
|
||||
[33m These versions may not work properly together.[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > on linux > logs error and exits when starting xvfb fails > xvfb fails 1`] = `
|
||||
"It looks like this is your first time using Cypress: [36m1.2.3[39m
|
||||
|
||||
[31mError: Xvfb exited with a non zero exit code.[39m
|
||||
[31m[39m
|
||||
[31mThere was a problem spawning Xvfb.[39m
|
||||
[31m[39m
|
||||
[31mThis is likely a problem with your system, permissions, or installation of Xvfb.[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mError: test without xvfb[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > smoke test retries on bad display with our Xvfb > fails on both retries with our Xvfb on Linux > tried to verify twice, on the first try got the DISPLAY error 1`] = `
|
||||
"Cypress verification failed.
|
||||
|
||||
Cypress failed to start after spawning a new Xvfb server.
|
||||
|
||||
The error logs we received were:
|
||||
|
||||
----------
|
||||
|
||||
[some noise here] Gtk: cannot open display: 987
|
||||
some other error
|
||||
again with
|
||||
some weird indent
|
||||
|
||||
----------
|
||||
|
||||
This may be due to a missing library or dependency. [34mhttps://on.cypress.io/required-dependencies[39m
|
||||
|
||||
Please refer to the error above for more detail.
|
||||
|
||||
----------
|
||||
|
||||
Platform: linux-x64 (undefined)
|
||||
Cypress Version: 1.2.3"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > smoke test retries on bad display with our Xvfb > is silent when logLevel is silent > silent verify 1`] = `""`;
|
||||
|
||||
exports[`lib/tasks/verify > smoke test retries on bad display with our Xvfb > logs an error if Cypress executable does not exist > no Cypress executable 1`] = `
|
||||
"[31mError: No version of Cypress is installed in: [36m/cache/Cypress/1.2.3/Cypress.app[39m[31m[39m
|
||||
[31m[39m
|
||||
[31mPlease reinstall Cypress by running: [36mcypress install[39m[31m[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mCypress executable not found at: [36m/cache/Cypress/1.2.3/Cypress.app/Contents/MacOS/Cypress[39m[31m[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > smoke test retries on bad display with our Xvfb > logs an error if Cypress executable does not have permissions > Cypress non-executable permission 1`] = `
|
||||
"[31mError: Cypress cannot run because this binary file does not have executable permissions here:[39m
|
||||
[31m[39m
|
||||
[31m/cache/Cypress/1.2.3/Cypress.app/Contents/MacOS/Cypress[39m
|
||||
[31m[39m
|
||||
[31mReasons this may happen:[39m
|
||||
[31m[39m
|
||||
[31m- node was installed as 'root' or with 'sudo'[39m
|
||||
[31m- the cypress npm package as 'root' or with 'sudo'[39m
|
||||
[31m[39m
|
||||
[31mPlease check that you have the appropriate user permissions.[39m
|
||||
[31m[39m
|
||||
[31mYou can also try clearing the cache with 'cypress cache clear' and reinstalling.[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > smoke test retries on bad display with our Xvfb > logs and runs when current version has not been verified > current version has not been verified 1`] = `
|
||||
"It looks like this is your first time using Cypress: [36m1.2.3[39m
|
||||
|
||||
|
||||
Opening Cypress...
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > smoke test retries on bad display with our Xvfb > logs and runs when installed version is different than package version > different version installed 1`] = `
|
||||
"Found binary version [32m7.8.9[39m installed in: [36m/cache/Cypress/1.2.3/Cypress.app[39m
|
||||
|
||||
[33m⚠ Warning: Binary version [32m7.8.9[39m[33m does not match the expected package version [32m1.2.3[39m[33m[39m
|
||||
[33m[39m
|
||||
[33m These versions may not work properly together.[39m
|
||||
|
||||
It looks like this is your first time using Cypress: [36m7.8.9[39m
|
||||
|
||||
|
||||
Opening Cypress...
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > smoke test retries on bad display with our Xvfb > logs error when fails smoke test unexpectedly without stderr > fails with no stderr 1`] = `
|
||||
"It looks like this is your first time using Cypress: [36m1.2.3[39m
|
||||
|
||||
[31mError: Cypress failed to start.[39m
|
||||
[31m[39m
|
||||
[31mThis may be due to a missing library or dependency. https://on.cypress.io/required-dependencies[39m
|
||||
[31m[39m
|
||||
[31mPlease refer to the error below for more details.[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mError: EPERM NOT PERMITTED[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > smoke test retries on bad display with our Xvfb > turns off Opening Cypress... > no welcome message 1`] = `
|
||||
"Found binary version [32m7.8.9[39m installed in: [36m/cache/Cypress/1.2.3/Cypress.app[39m
|
||||
|
||||
[33m⚠ Warning: Binary version [32m7.8.9[39m[33m does not match the expected package version [32m1.2.3[39m[33m[39m
|
||||
[33m[39m
|
||||
[33m These versions may not work properly together.[39m
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > smoke test with DEBUG output > finds ping value in the verbose output > verbose stdout output 1`] = `
|
||||
"It looks like this is your first time using Cypress: [36m1.2.3[39m
|
||||
|
||||
|
||||
Opening Cypress...
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > when env var CYPRESS_RUN_BINARY > can log error to user on darwin > darwin: error when invalid CYPRESS_RUN_BINARY 1`] = `
|
||||
"[33mNote:[39m You have set the environment variable:
|
||||
|
||||
[37mCYPRESS_RUN_BINARY=[39m[36m/custom/[39m
|
||||
|
||||
This overrides the default Cypress binary path used.
|
||||
|
||||
[31mError: Could not run binary set by environment variable: CYPRESS_RUN_BINARY=/custom/[39m
|
||||
[31m[39m
|
||||
[31mEnsure the environment variable is a path to the Cypress binary, matching **/Contents/MacOS/Cypress[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mENOENT: no such file or directory, stat '/custom/'[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > when env var CYPRESS_RUN_BINARY > can log error to user on linux > linux: error when invalid CYPRESS_RUN_BINARY 1`] = `
|
||||
"[33mNote:[39m You have set the environment variable:
|
||||
|
||||
[37mCYPRESS_RUN_BINARY=[39m[36m/custom/[39m
|
||||
|
||||
This overrides the default Cypress binary path used.
|
||||
|
||||
[31mError: Could not run binary set by environment variable: CYPRESS_RUN_BINARY=/custom/[39m
|
||||
[31m[39m
|
||||
[31mEnsure the environment variable is a path to the Cypress binary, matching **/Cypress[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mENOENT: no such file or directory, stat '/custom/'[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: linux-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > when env var CYPRESS_RUN_BINARY > can log error to user on win32 > win32: error when invalid CYPRESS_RUN_BINARY 1`] = `
|
||||
"[33mNote:[39m You have set the environment variable:
|
||||
|
||||
[37mCYPRESS_RUN_BINARY=[39m[36m/custom/[39m
|
||||
|
||||
This overrides the default Cypress binary path used.
|
||||
|
||||
[31mError: Could not run binary set by environment variable: CYPRESS_RUN_BINARY=/custom/[39m
|
||||
[31m[39m
|
||||
[31mEnsure the environment variable is a path to the Cypress binary, matching **/Cypress.exe[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mENOENT: no such file or directory, stat '/custom/'[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: win32-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > when env var CYPRESS_RUN_BINARY > can validate and use executable > valid CYPRESS_RUN_BINARY 1`] = `
|
||||
"[33mNote:[39m You have set the environment variable:
|
||||
|
||||
[37mCYPRESS_RUN_BINARY=[39m[36m/custom/Contents/MacOS/Cypress[39m
|
||||
|
||||
This overrides the default Cypress binary path used.
|
||||
|
||||
It looks like this is your first time using Cypress: [36m1.2.3[39m
|
||||
|
||||
|
||||
Opening Cypress...
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > when running in CI > logs error when binary not found > error binary not found in ci 1`] = `
|
||||
"[31mError: The cypress npm package is installed, but the Cypress binary is missing.[39m
|
||||
[31m[39m
|
||||
[31mWe expected the binary to be installed here: [36m/cache/Cypress/1.2.3/Cypress.app/Contents/MacOS/Cypress[39m[31m[39m
|
||||
[31m[39m
|
||||
[31mReasons it may be missing:[39m
|
||||
[31m[39m
|
||||
[31m- You're caching 'node_modules' but are not caching this path: /cache/Cypress[39m
|
||||
[31m- You ran 'npm install' at an earlier build step but did not persist: /cache/Cypress[39m
|
||||
[31m[39m
|
||||
[31mProperly caching the binary will fix this error and avoid downloading and unzipping Cypress.[39m
|
||||
[31m[39m
|
||||
[31mAlternatively, you can run 'cypress install' to download the binary again.[39m
|
||||
[31m[39m
|
||||
[31m[34mhttps://on.cypress.io/not-installed-ci-error[39m[31m[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > when running in CI > uses verbose renderer > verifying in ci 1`] = `
|
||||
"It looks like this is your first time using Cypress: [36m1.2.3[39m
|
||||
|
||||
|
||||
Opening Cypress...
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > with force: true > clears verified version from state if verification fails > fails verifying Cypress 1`] = `
|
||||
"
|
||||
[31mError: Cypress failed to start.[39m
|
||||
[31m[39m
|
||||
[31mThis may be due to a missing library or dependency. https://on.cypress.io/required-dependencies[39m
|
||||
[31m[39m
|
||||
[31mPlease refer to the error below for more details.[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31man error about dependencies[39m
|
||||
[31m[39m
|
||||
[31m----------[39m
|
||||
[31m[39m
|
||||
[31mPlatform: darwin-x64 (undefined)[39m
|
||||
[31mCypress Version: 1.2.3[39m
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib/tasks/verify > with force: true > shows full path to executable when verifying > verification with executable 1`] = `
|
||||
"
|
||||
|
||||
Opening Cypress...
|
||||
"
|
||||
`;
|
||||
@@ -2,6 +2,7 @@ import { vi, describe, it, beforeEach, afterEach, expect } from 'vitest'
|
||||
import os from 'os'
|
||||
import path from 'path'
|
||||
import chalk from 'chalk'
|
||||
import stripAnsi from 'strip-ansi'
|
||||
import timers from 'timers/promises'
|
||||
import fs from 'fs-extra'
|
||||
import si, { Systeminformation } from 'systeminformation'
|
||||
@@ -121,18 +122,47 @@ vi.mock('../../../lib/tasks/state', async (importActual) => {
|
||||
})
|
||||
|
||||
const packageVersion = '1.2.3'
|
||||
/** Override used with CYPRESS_INSTALL_BINARY in env-var warning tests */
|
||||
const envForcedBinaryVersion = '0.12.1'
|
||||
const downloadDestination = path.join(os.tmpdir(), `cypress-${process.pid}.zip`)
|
||||
const installDir = '/cache/Cypress/1.2.3'
|
||||
|
||||
/** Matches `logger.log(\`Installing Cypress ${chalk.gray(...)}\`)` prefix */
|
||||
const versionLabel = (version: string) => `version: ${version}`
|
||||
|
||||
/** Substrings expected in stripAnsi(stdout) for install UX (stable across ANSI differences) */
|
||||
const INSTALL_OUTPUT = {
|
||||
skipBinaryNote: 'Skipping binary installation',
|
||||
cypressInstallBinaryZero: 'CYPRESS_INSTALL_BINARY = 0',
|
||||
preReleaseBanner: 'pre-release build of Cypress',
|
||||
cdnBetaBinaryPath: 'cdn.cypress.io/beta/binary',
|
||||
installingCypress: 'Installing Cypress',
|
||||
openingTheAppUrl: 'on.cypress.io/opening-the-app',
|
||||
forceVersionBanner: 'Forcing a binary version different than the default',
|
||||
finishedInstallation: 'Finished Installation',
|
||||
skippingInstall: 'Skipping installation',
|
||||
cliForceFlag: '--force',
|
||||
stubBinaryVersionOther: 'x.x.x',
|
||||
globalInstallWarning: 'installed Cypress globally',
|
||||
devDependencyPerProject: 'devDependency per project',
|
||||
npmUninstallGlobalCypress: 'npm uninstall -g cypress',
|
||||
downloadingCypress: 'Downloading Cypress',
|
||||
cacheWriteDenied: 'cannot write to the cache directory',
|
||||
invalidCacheDir: '/invalid/cache/dir',
|
||||
cachePermissionsIssueUrl: 'github.com/cypress-io/cypress/issues/1281',
|
||||
eaccesCode: 'EACCES',
|
||||
osUnsupported: 'could not be installed',
|
||||
osRequirementsDoc: 'operating system requirements',
|
||||
platformWin32Ia32: 'win32-ia32',
|
||||
} as const
|
||||
|
||||
const PRE_RELEASE_COMMIT_SHA = '3b7f0b5c59def1e9b5f385bd585c9b2836706c29'
|
||||
const PRE_RELEASE_BRANCH = 'aBranchName'
|
||||
const PRE_RELEASE_DOWNLOAD_URL =
|
||||
`https://cdn.cypress.io/beta/binary/0.0.0-development/darwin-x64/${PRE_RELEASE_BRANCH}-${PRE_RELEASE_COMMIT_SHA}/cypress.zip`
|
||||
|
||||
/**
|
||||
* NOTE: icons from listr2 do not render if process.stdout.isTTY is false,
|
||||
* which does not exist when running in a worker thread, which is commonly the case in Vitest.
|
||||
*
|
||||
* This means that the test environment implicitly uses the VerboseRenderer as a fallback,
|
||||
* where as the CLI uses the DefaultRenderer.
|
||||
*
|
||||
* This is the main reason the snapshots look different in testing mode vs when running the commands directly
|
||||
* via the CLI. This also allows us for our snapshot tests to be deterministic because we aren't rerendering icon states.
|
||||
* stdout capture: listr2/chalk emit ANSI; assertions use strip-ansi + toContain so tests stay stable across OS/CI.
|
||||
*
|
||||
* @see https://listr2.kilic.dev/renderer/renderer.html#frontmatter-title
|
||||
*/
|
||||
@@ -144,12 +174,15 @@ describe('/lib/tasks/install', function () {
|
||||
const createStdoutCapture = () => {
|
||||
const logs: string[] = []
|
||||
|
||||
const originalOut = process.stdout.write
|
||||
const originalOut = process.stdout.write.bind(process.stdout)
|
||||
|
||||
vi.spyOn(process.stdout, 'write').mockImplementation((strOrBugger: string | Uint8Array) => {
|
||||
logs.push(strOrBugger as string)
|
||||
vi.spyOn(process.stdout, 'write').mockImplementation(function (
|
||||
this: typeof process.stdout,
|
||||
...args: Parameters<typeof process.stdout.write>
|
||||
): boolean {
|
||||
logs.push(args[0] as string)
|
||||
|
||||
return originalOut(strOrBugger)
|
||||
return originalOut(...args)
|
||||
})
|
||||
|
||||
return () => logs.join('')
|
||||
@@ -176,6 +209,7 @@ describe('/lib/tasks/install', function () {
|
||||
afterEach(() => {
|
||||
globalThis.console = originalConsole // Restore original console
|
||||
chalk.level = previousChalkLevel
|
||||
vi.unstubAllEnvs()
|
||||
})
|
||||
|
||||
describe('.start', function () {
|
||||
@@ -206,24 +240,29 @@ describe('/lib/tasks/install', function () {
|
||||
})
|
||||
|
||||
describe('skips install', function () {
|
||||
beforeEach(() => {
|
||||
vi.stubEnv('CYPRESS_INSTALL_BINARY', '0')
|
||||
})
|
||||
|
||||
it('when environment variable is set', async () => {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
vi.stubEnv('CYPRESS_INSTALL_BINARY', '0')
|
||||
|
||||
await install.start()
|
||||
|
||||
expect(download.start).not.toHaveBeenCalled()
|
||||
|
||||
expect(output()).toMatchSnapshot('skip installation 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.skipBinaryNote)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.cypressInstallBinaryZero)
|
||||
})
|
||||
})
|
||||
|
||||
describe('non-stable builds', () => {
|
||||
const buildInfo = {
|
||||
stable: false,
|
||||
commitSha: '3b7f0b5c59def1e9b5f385bd585c9b2836706c29',
|
||||
commitBranch: 'aBranchName',
|
||||
commitSha: PRE_RELEASE_COMMIT_SHA,
|
||||
commitBranch: PRE_RELEASE_BRANCH,
|
||||
commitDate: new Date('1996-11-27').toISOString(),
|
||||
}
|
||||
|
||||
@@ -235,7 +274,7 @@ describe('/lib/tasks/install', function () {
|
||||
await install.start({ buildInfo })
|
||||
|
||||
expect(download.start).toHaveBeenCalledWith(expect.objectContaining({
|
||||
version: 'https://cdn.cypress.io/beta/binary/0.0.0-development/darwin-x64/aBranchName-3b7f0b5c59def1e9b5f385bd585c9b2836706c29/cypress.zip',
|
||||
version: PRE_RELEASE_DOWNLOAD_URL,
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -243,7 +282,14 @@ describe('/lib/tasks/install', function () {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
await install.start({ buildInfo })
|
||||
expect(output()).toMatchSnapshot('pre-release warning')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.preReleaseBanner)
|
||||
expect(plain).toContain(PRE_RELEASE_COMMIT_SHA)
|
||||
expect(plain).toContain(PRE_RELEASE_BRANCH)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.cdnBetaBinaryPath)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.installingCypress)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.openingTheAppUrl)
|
||||
})
|
||||
|
||||
it('installs to the expected pre-release cache dir', async function () {
|
||||
@@ -253,7 +299,7 @@ describe('/lib/tasks/install', function () {
|
||||
|
||||
await install.start({ buildInfo })
|
||||
expect(unzip.start).toHaveBeenCalledWith(expect.objectContaining({
|
||||
installDir: expect.stringMatching(/\/Cypress\/beta\-1\.2\.3\-aBranchName\-3b7f0b5c$/),
|
||||
installDir: expect.stringMatching(/beta\-1\.2\.3\-aBranchName\-3b7f0b5c$/),
|
||||
}))
|
||||
})
|
||||
})
|
||||
@@ -262,7 +308,7 @@ describe('/lib/tasks/install', function () {
|
||||
it('warns when specifying cypress version in env', async function () {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
const version = '0.12.1'
|
||||
const version = envForcedBinaryVersion
|
||||
|
||||
vi.stubEnv('CYPRESS_INSTALL_BINARY', version)
|
||||
|
||||
@@ -275,7 +321,13 @@ describe('/lib/tasks/install', function () {
|
||||
zipFilePath: downloadDestination,
|
||||
}))
|
||||
|
||||
expect(output()).toMatchSnapshot('specify version in env vars 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.forceVersionBanner)
|
||||
expect(plain).toContain(packageVersion)
|
||||
expect(plain).toContain(envForcedBinaryVersion)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.installingCypress)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.openingTheAppUrl)
|
||||
})
|
||||
|
||||
it('trims environment variable before installing', async function () {
|
||||
@@ -387,7 +439,10 @@ describe('/lib/tasks/install', function () {
|
||||
|
||||
await install.start()
|
||||
|
||||
expect(output()).toMatchSnapshot('version already installed - cypress install 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.skippingInstall)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.cliForceFlag)
|
||||
})
|
||||
|
||||
it('logs when already installed when run from postInstall', async function () {
|
||||
@@ -397,7 +452,10 @@ describe('/lib/tasks/install', function () {
|
||||
|
||||
await install.start()
|
||||
|
||||
expect(output()).toMatchSnapshot('version already installed - postInstall 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(packageVersion)
|
||||
expect(plain).toContain(installDir)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -417,7 +475,13 @@ describe('/lib/tasks/install', function () {
|
||||
installDir,
|
||||
}))
|
||||
|
||||
expect(output()).toMatchSnapshot('continues installing on failure 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.installingCypress)
|
||||
expect(plain).toContain(versionLabel(packageVersion))
|
||||
expect(plain).toContain(INSTALL_OUTPUT.finishedInstallation)
|
||||
expect(plain).toContain(installDir)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.openingTheAppUrl)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -442,7 +506,13 @@ describe('/lib/tasks/install', function () {
|
||||
downloadDestination,
|
||||
)
|
||||
|
||||
expect(output()).toMatchSnapshot('installs without existing installation 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.installingCypress)
|
||||
expect(plain).toContain(versionLabel(packageVersion))
|
||||
expect(plain).toContain(INSTALL_OUTPUT.finishedInstallation)
|
||||
expect(plain).toContain(installDir)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.openingTheAppUrl)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -450,7 +520,7 @@ describe('/lib/tasks/install', function () {
|
||||
it('logs message and starts download', async function () {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
vi.mocked(state.getBinaryPkgAsync).mockResolvedValue({ version: 'x.x.x' })
|
||||
vi.mocked(state.getBinaryPkgAsync).mockResolvedValue({ version: INSTALL_OUTPUT.stubBinaryVersionOther })
|
||||
|
||||
await install.start()
|
||||
expect(download.start).toHaveBeenCalledWith(expect.objectContaining({
|
||||
@@ -461,7 +531,13 @@ describe('/lib/tasks/install', function () {
|
||||
installDir,
|
||||
}))
|
||||
|
||||
expect(output()).toMatchSnapshot('installed version does not match needed version 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.stubBinaryVersionOther)
|
||||
expect(plain).toContain(installDir)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.installingCypress)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.finishedInstallation)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.openingTheAppUrl)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -480,7 +556,13 @@ describe('/lib/tasks/install', function () {
|
||||
installDir,
|
||||
}))
|
||||
|
||||
expect(output()).toMatchSnapshot('forcing true always installs 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(packageVersion)
|
||||
expect(plain).toContain(installDir)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.installingCypress)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.finishedInstallation)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.openingTheAppUrl)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -490,7 +572,7 @@ describe('/lib/tasks/install', function () {
|
||||
|
||||
vi.mocked(util.isInstalledGlobally).mockReturnValue(true)
|
||||
|
||||
vi.mocked(state.getBinaryPkgAsync).mockResolvedValue({ version: 'x.x.x' })
|
||||
vi.mocked(state.getBinaryPkgAsync).mockResolvedValue({ version: INSTALL_OUTPUT.stubBinaryVersionOther })
|
||||
|
||||
await install.start()
|
||||
|
||||
@@ -502,7 +584,12 @@ describe('/lib/tasks/install', function () {
|
||||
installDir,
|
||||
}))
|
||||
|
||||
expect(output()).toMatchSnapshot('warning installing as global 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.globalInstallWarning)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.devDependencyPerProject)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.npmUninstallGlobalCypress)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.finishedInstallation)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -512,11 +599,17 @@ describe('/lib/tasks/install', function () {
|
||||
|
||||
vi.mocked(util.isCi).mockReturnValue(true)
|
||||
|
||||
vi.mocked(state.getBinaryPkgAsync).mockResolvedValue({ version: 'x.x.x' })
|
||||
vi.mocked(state.getBinaryPkgAsync).mockResolvedValue({ version: INSTALL_OUTPUT.stubBinaryVersionOther })
|
||||
|
||||
await install.start()
|
||||
|
||||
expect(output()).toMatchSnapshot('installing in ci 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.installingCypress)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.downloadingCypress)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.finishedInstallation)
|
||||
expect(plain).toContain(installDir)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.openingTheAppUrl)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -542,7 +635,12 @@ describe('/lib/tasks/install', function () {
|
||||
expect(message).not.toEqual('should have caught error')
|
||||
logger.error(err)
|
||||
|
||||
expect(output()).toMatchSnapshot('invalid cache directory 1')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.cacheWriteDenied)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.invalidCacheDir)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.cachePermissionsIssueUrl)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.eaccesCode)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -617,7 +715,7 @@ describe('/lib/tasks/install', function () {
|
||||
|
||||
await install.start()
|
||||
|
||||
expect(output()).toMatchSnapshot('silent install 1')
|
||||
expect(output()).toBe('')
|
||||
})
|
||||
|
||||
it('exits with error when installing on unsupported os', async function () {
|
||||
@@ -634,7 +732,11 @@ describe('/lib/tasks/install', function () {
|
||||
expect(message).not.toEqual('should have caught error')
|
||||
logger.error(err)
|
||||
|
||||
expect(output()).toMatchSnapshot('error when installing on unsupported os')
|
||||
const plain = stripAnsi(output())
|
||||
|
||||
expect(plain).toContain(INSTALL_OUTPUT.osUnsupported)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.osRequirementsDoc)
|
||||
expect(plain).toContain(INSTALL_OUTPUT.platformWin32Ia32)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -10,6 +10,8 @@ import { Console } from 'console'
|
||||
import fs from 'fs-extra'
|
||||
import si, { Systeminformation } from 'systeminformation'
|
||||
import _xvfb from '@cypress/xvfb'
|
||||
import stripAnsi from 'strip-ansi'
|
||||
import { Listr } from 'listr2'
|
||||
|
||||
import util from '../../../lib/util'
|
||||
import logger from '../../../lib/logger'
|
||||
@@ -116,19 +118,39 @@ vi.mock('../../../lib/util', async (importActual) => {
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('listr2', async (importActual) => {
|
||||
const actual = await importActual<typeof import('listr2')>()
|
||||
const { Listr } = actual
|
||||
|
||||
return {
|
||||
...actual,
|
||||
Listr: vi.fn(function (this: unknown, ...args: ConstructorParameters<typeof Listr>) {
|
||||
return new Listr(...args)
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
||||
describe('lib/tasks/verify', () => {
|
||||
const createStdoutCapture = () => {
|
||||
const logs: string[] = []
|
||||
const originalOut = process.stdout.write
|
||||
|
||||
vi.spyOn(process.stdout, 'write').mockImplementation((strOrBugger: string | Uint8Array) => {
|
||||
logs.push(strOrBugger as string)
|
||||
vi.spyOn(process.stdout, 'write').mockImplementation((...args: Parameters<typeof process.stdout.write>) => {
|
||||
const chunk = args[0]
|
||||
|
||||
return originalOut(strOrBugger)
|
||||
if (typeof chunk === 'string') {
|
||||
logs.push(chunk)
|
||||
}
|
||||
|
||||
// Must preserve `stdout` as `this` — unbound calls break Writable (_writableState).
|
||||
return originalOut.apply(process.stdout, args)
|
||||
})
|
||||
|
||||
return () => logs.join('')
|
||||
}
|
||||
|
||||
/** listr2/chalk add ANSI; strip for stable substring assertions. */
|
||||
const plain = (getOutput: () => string): string => stripAnsi(getOutput())
|
||||
let spawnedProcess: any
|
||||
// Direct console to process.stdout/stderr
|
||||
let originalConsole: Console
|
||||
@@ -143,6 +165,8 @@ describe('lib/tasks/verify', () => {
|
||||
vi.unstubAllEnvs()
|
||||
|
||||
vi.stubEnv('npm_config_loglevel', 'notice')
|
||||
// Align `state.getCacheDir()` with mock-fs fixtures (stable across CI/sandbox vs real cachedir()).
|
||||
vi.stubEnv('CYPRESS_CACHE_FOLDER', '/cache/Cypress')
|
||||
|
||||
originalConsole = globalThis.console
|
||||
|
||||
@@ -216,7 +240,7 @@ describe('lib/tasks/verify', () => {
|
||||
it('returns early when `CYPRESS_SKIP_VERIFY` is set to true', async () => {
|
||||
vi.stubEnv('CYPRESS_SKIP_VERIFY', 'true')
|
||||
|
||||
const result = await start({ listrRenderer: 'silent' })
|
||||
const result = await start()
|
||||
|
||||
expect(result).toEqual(undefined)
|
||||
})
|
||||
@@ -225,7 +249,7 @@ describe('lib/tasks/verify', () => {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
try {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
throw new Error('should have caught error')
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err)
|
||||
@@ -233,7 +257,11 @@ describe('lib/tasks/verify', () => {
|
||||
expect(message).not.toContain('should have caught error')
|
||||
logger.error(err)
|
||||
|
||||
expect(output()).toMatchSnapshot()
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('No version of Cypress is installed')
|
||||
expect(out).toContain('/cache/Cypress/1.2.3/Cypress.app')
|
||||
expect(out).toContain('cypress install')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -248,7 +276,7 @@ describe('lib/tasks/verify', () => {
|
||||
// @ts-expect-error - geteuid is potentially undefined
|
||||
vi.mocked(geteuid).mockReturnValue(0) // user is root
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(util.exec).toHaveBeenCalledWith(executablePath, ['--no-sandbox', '--smoke-test', '--ping=222'], expect.anything())
|
||||
})
|
||||
@@ -264,7 +292,7 @@ describe('lib/tasks/verify', () => {
|
||||
// @ts-expect-error - geteuid is potentially undefined
|
||||
vi.mocked(geteuid).mockReturnValue(1000) // user is non-root
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(util.exec).toHaveBeenCalledWith(executablePath, ['--no-sandbox', '--smoke-test', '--ping=222'], expect.anything())
|
||||
})
|
||||
@@ -279,7 +307,7 @@ describe('lib/tasks/verify', () => {
|
||||
packageVersion,
|
||||
})
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(output()).toEqual('')
|
||||
|
||||
@@ -295,16 +323,20 @@ describe('lib/tasks/verify', () => {
|
||||
packageVersion: 'bloop',
|
||||
})
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(output()).toMatchSnapshot()
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Found binary version bloop')
|
||||
expect(out).toContain('does not match the expected package version')
|
||||
expect(out).toContain('1.2.3')
|
||||
})
|
||||
|
||||
it('logs error and exits when executable cannot be found', async () => {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
try {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
throw new Error('should have caught error')
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err)
|
||||
@@ -312,7 +344,10 @@ describe('lib/tasks/verify', () => {
|
||||
expect(message).not.toContain('should have caught error')
|
||||
logger.error(err)
|
||||
|
||||
expect(output()).toMatchSnapshot()
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('No version of Cypress is installed')
|
||||
expect(out).toContain('cypress install')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -332,10 +367,14 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
try {
|
||||
await start({ smokeTestTimeout: 1, listrRenderer: 'silent' })
|
||||
await start({ smokeTestTimeout: 1 })
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
expect(output()).toMatchSnapshot()
|
||||
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Cypress verification timed out')
|
||||
expect(out).toContain('some stderr')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -355,10 +394,15 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
try {
|
||||
await start({ smokeTestTimeout: 1, listrRenderer: 'silent' })
|
||||
await start({ smokeTestTimeout: 1 })
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
expect(output()).toMatchSnapshot()
|
||||
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Cypress failed to start')
|
||||
expect(out).toContain('some stderr')
|
||||
expect(out).toContain('on.cypress.io/required-dependencies')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -377,10 +421,14 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
try {
|
||||
await start({ smokeTestTimeout: 1, listrRenderer: 'silent' })
|
||||
await start({ smokeTestTimeout: 1 })
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
expect(output()).toMatchSnapshot()
|
||||
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Cypress failed to start')
|
||||
expect(out).toContain('on.cypress.io/required-dependencies')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -402,7 +450,7 @@ describe('lib/tasks/verify', () => {
|
||||
stderr: '',
|
||||
} as any)
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(util.exec).toHaveBeenCalledWith(
|
||||
executablePath,
|
||||
@@ -424,9 +472,9 @@ describe('lib/tasks/verify', () => {
|
||||
it('shows full path to executable when verifying', async () => {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
await start({ force: true, listrRenderer: 'silent' })
|
||||
await start({ force: true })
|
||||
|
||||
expect(output()).toMatchSnapshot('verification with executable')
|
||||
expect(plain(output)).toContain('Opening Cypress...')
|
||||
})
|
||||
|
||||
it('clears verified version from state if verification fails', async () => {
|
||||
@@ -438,7 +486,7 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
try {
|
||||
await start({ force: true, listrRenderer: 'silent' })
|
||||
await start({ force: true })
|
||||
throw new Error('Should have thrown')
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
@@ -448,7 +496,10 @@ describe('lib/tasks/verify', () => {
|
||||
|
||||
expect(exists).toEqual(false)
|
||||
|
||||
expect(output()).toMatchSnapshot('fails verifying Cypress')
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Cypress failed to start')
|
||||
expect(out).toContain('an error about dependencies')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -482,9 +533,10 @@ describe('lib/tasks/verify', () => {
|
||||
it('finds ping value in the verbose output', async () => {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(output()).toMatchSnapshot('verbose stdout output')
|
||||
expect(util.exec).toHaveBeenCalled()
|
||||
expect(plain(output)).toContain('Opening Cypress...')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -533,7 +585,7 @@ describe('lib/tasks/verify', () => {
|
||||
return Promise.reject(firstSpawnError)
|
||||
})
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(util.exec).toHaveBeenCalledTimes(2)
|
||||
// user should have been warned
|
||||
@@ -581,19 +633,21 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
try {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
} catch (e) {
|
||||
const message = e instanceof Error ? e.message : String(e)
|
||||
|
||||
expect(util.exec).toHaveBeenCalledTimes(2)
|
||||
// second time around we should have called Xvfb
|
||||
expect(xvfb.start).toHaveBeenCalledOnce
|
||||
expect(xvfb.stop).toHaveBeenCalledOnce
|
||||
expect(xvfb.start).toHaveBeenCalledTimes(1)
|
||||
expect(xvfb.stop).toHaveBeenCalledTimes(1)
|
||||
|
||||
// user should have been warned
|
||||
expect(loggerWarnSpy).toHaveBeenCalledWith(expect.stringContaining('DISPLAY was set to: "test-display"'))
|
||||
|
||||
expect(message).toMatchSnapshot('tried to verify twice, on the first try got the DISPLAY error')
|
||||
expect(message).toContain('Cypress verification failed')
|
||||
expect(message).toContain('Gtk: cannot open display: 987')
|
||||
expect(message).toContain('some other error')
|
||||
|
||||
return
|
||||
}
|
||||
@@ -611,11 +665,14 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
try {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
|
||||
expect(output()).toMatchSnapshot('no Cypress executable')
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('No version of Cypress is installed')
|
||||
expect(out).toContain('cypress install')
|
||||
|
||||
return
|
||||
}
|
||||
@@ -635,11 +692,14 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
try {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
|
||||
expect(output()).toMatchSnapshot('Cypress non-executable permission')
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('does not have executable permissions')
|
||||
expect(out).toContain(executablePath)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -656,9 +716,12 @@ describe('lib/tasks/verify', () => {
|
||||
packageVersion,
|
||||
})
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(output()).toMatchSnapshot('current version has not been verified')
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('first time using Cypress')
|
||||
expect(out).toContain('Opening Cypress...')
|
||||
})
|
||||
|
||||
it('logs and runs when installed version is different than package version', async () => {
|
||||
@@ -670,9 +733,13 @@ describe('lib/tasks/verify', () => {
|
||||
packageVersion: '7.8.9',
|
||||
})
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(output()).toMatchSnapshot('different version installed')
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Found binary version 7.8.9')
|
||||
expect(out).toContain('does not match the expected package version')
|
||||
expect(out).toContain('first time using Cypress')
|
||||
})
|
||||
|
||||
it('is silent when logLevel is silent', async () => {
|
||||
@@ -686,9 +753,9 @@ describe('lib/tasks/verify', () => {
|
||||
|
||||
vi.stubEnv('npm_config_loglevel', 'silent')
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(output()).toMatchSnapshot('silent verify')
|
||||
expect(output()).toEqual('')
|
||||
})
|
||||
|
||||
it('turns off Opening Cypress...', async () => {
|
||||
@@ -702,7 +769,11 @@ describe('lib/tasks/verify', () => {
|
||||
|
||||
await start({ welcomeMessage: false })
|
||||
|
||||
expect(output()).toMatchSnapshot('no welcome message')
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).not.toContain('Opening Cypress...')
|
||||
expect(out).toContain('7.8.9')
|
||||
expect(out).toContain('does not match')
|
||||
})
|
||||
|
||||
it('logs error when fails smoke test unexpectedly without stderr', async () => {
|
||||
@@ -721,11 +792,14 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
try {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
|
||||
expect(output()).toMatchSnapshot('fails with no stderr')
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Cypress failed to start')
|
||||
expect(out).toContain('EPERM NOT PERMITTED')
|
||||
|
||||
return
|
||||
}
|
||||
@@ -746,13 +820,13 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
it('starts xvfb', async () => {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(xvfb.start).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('stops xvfb on spawned process close', async () => {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(xvfb.stop).toHaveBeenCalled()
|
||||
})
|
||||
@@ -776,13 +850,14 @@ describe('lib/tasks/verify', () => {
|
||||
})
|
||||
|
||||
try {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
} catch (err) {
|
||||
expect(xvfb.stop).toHaveBeenCalledOnce
|
||||
|
||||
logger.error(err)
|
||||
|
||||
expect(output()).toMatchSnapshot('xvfb fails')
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Xvfb exited')
|
||||
expect(out).toContain('test without xvfb')
|
||||
|
||||
return
|
||||
}
|
||||
@@ -802,25 +877,21 @@ describe('lib/tasks/verify', () => {
|
||||
vi.mocked(util.isCi).mockReturnValue(true)
|
||||
})
|
||||
|
||||
it('uses verbose renderer', async () => {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
|
||||
expect(output()).toMatchSnapshot('verifying in ci')
|
||||
})
|
||||
|
||||
it('logs error when binary not found', async () => {
|
||||
const output = createStdoutCapture()
|
||||
|
||||
mockfs({})
|
||||
|
||||
try {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
|
||||
expect(output()).toMatchSnapshot('error binary not found in ci')
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Cypress binary is missing')
|
||||
expect(out).toContain('/cache/Cypress')
|
||||
expect(out).toContain('not-installed-ci-error')
|
||||
|
||||
return
|
||||
}
|
||||
@@ -854,10 +925,10 @@ describe('lib/tasks/verify', () => {
|
||||
return Promise.reject(new Error('should have caught error'))
|
||||
})
|
||||
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
|
||||
expect(util.exec).toHaveBeenCalledWith(realEnvBinaryPath, ['--no-sandbox', '--smoke-test', '--ping=222'], expect.anything())
|
||||
expect(output()).toMatchSnapshot('valid CYPRESS_RUN_BINARY')
|
||||
expect(plain(output)).toContain('Opening Cypress...')
|
||||
})
|
||||
|
||||
for (const platform of ['darwin', 'linux', 'win32']) {
|
||||
@@ -869,10 +940,22 @@ describe('lib/tasks/verify', () => {
|
||||
vi.mocked(os.platform).mockReturnValue(platform as NodeJS.Platform)
|
||||
|
||||
try {
|
||||
await start({ listrRenderer: 'silent' })
|
||||
await start()
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
expect(output()).toMatchSnapshot(`${platform}: error when invalid CYPRESS_RUN_BINARY`)
|
||||
|
||||
const out = plain(output)
|
||||
|
||||
expect(out).toContain('Could not run binary set by environment variable')
|
||||
expect(out).toContain('ENOENT')
|
||||
|
||||
if (platform === 'darwin') {
|
||||
expect(out).toContain('Contents/MacOS/Cypress')
|
||||
} else if (platform === 'linux') {
|
||||
expect(out).toContain('**/Cypress')
|
||||
} else {
|
||||
expect(out).toContain('Cypress.exe')
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ export default defineConfig({
|
||||
include: ['test/**/*.spec.ts'],
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
reporters: ['default'],
|
||||
},
|
||||
})
|
||||
|
||||
+1
-1
@@ -165,7 +165,7 @@
|
||||
"lazy-ass": "1.6.0",
|
||||
"lerna": "8.1.9",
|
||||
"lint-staged": "^16",
|
||||
"listr2": "3.8.3",
|
||||
"listr2": "^9.0.5",
|
||||
"lodash": "^4.17.21",
|
||||
"minimist": "1.2.8",
|
||||
"mobx": "6.13.6",
|
||||
|
||||
@@ -59,11 +59,12 @@ program
|
||||
concurrent: process.env.CI ? 4 : 1,
|
||||
renderer: process.env.CI ? 'verbose' : 'default',
|
||||
exitOnError: false,
|
||||
collectErrors: 'minimal',
|
||||
})
|
||||
|
||||
tasks.run()
|
||||
.then(() => {
|
||||
if (tasks.err[0] && tasks.err[0].errors.length > 0) {
|
||||
if (tasks.errors.length > 0) {
|
||||
process.exitCode = 1
|
||||
|
||||
log('')
|
||||
|
||||
@@ -10752,7 +10752,7 @@ ansi-escapes@^3.0.0, ansi-escapes@^3.2.0:
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
|
||||
integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
|
||||
|
||||
ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.1, ansi-escapes@^4.3.2:
|
||||
ansi-escapes@^4.2.1, ansi-escapes@^4.3.1, ansi-escapes@^4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
|
||||
integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
|
||||
@@ -13341,7 +13341,7 @@ color-support@1.1.3, color-support@^1.1.3:
|
||||
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
|
||||
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
|
||||
|
||||
colorette@^1.1.0, colorette@^1.2.2:
|
||||
colorette@^1.1.0:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
|
||||
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
|
||||
@@ -15492,14 +15492,6 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.17.1, enhanced-resolve@^5.7.0, enha
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.2.0"
|
||||
|
||||
enquirer@^2.3.6:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56"
|
||||
integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==
|
||||
dependencies:
|
||||
ansi-colors "^4.1.1"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
enquirer@~2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
|
||||
@@ -17027,7 +17019,7 @@ fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
||||
node-domexception "^1.0.0"
|
||||
web-streams-polyfill "^3.0.3"
|
||||
|
||||
figures@3.2.0, figures@^3.0.0, figures@^3.2.0:
|
||||
figures@3.2.0, figures@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
|
||||
integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
|
||||
@@ -22196,22 +22188,7 @@ listr-verbose-renderer@^0.5.0:
|
||||
date-fns "^1.27.2"
|
||||
figures "^2.0.0"
|
||||
|
||||
listr2@3.8.3, listr2@^3.8.3:
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.8.3.tgz#531f86870440172accd078ca4ebf4870ff5d850e"
|
||||
integrity sha512-2NUXrFxPeccawyOpJXfUuV7FmKG4ummQjY+ByPkhTFJ5dVxU9EQbLh0PzaNSXlgbIK7Kmam18oz+ev8sbukzBA==
|
||||
dependencies:
|
||||
cli-truncate "^2.1.0"
|
||||
colorette "^1.2.2"
|
||||
figures "^3.2.0"
|
||||
indent-string "^4.0.0"
|
||||
log-update "^4.0.0"
|
||||
p-map "^4.0.0"
|
||||
rxjs "^7.1.0"
|
||||
through "^2.3.8"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
listr2@^9.0.3:
|
||||
listr2@^9.0.3, listr2@^9.0.5:
|
||||
version "9.0.5"
|
||||
resolved "https://registry.yarnpkg.com/listr2/-/listr2-9.0.5.tgz#92df7c4416a6da630eb9ef46da469b70de97b316"
|
||||
integrity sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==
|
||||
@@ -22643,16 +22620,6 @@ log-update@^2.3.0:
|
||||
cli-cursor "^2.0.0"
|
||||
wrap-ansi "^3.0.1"
|
||||
|
||||
log-update@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1"
|
||||
integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==
|
||||
dependencies:
|
||||
ansi-escapes "^4.3.0"
|
||||
cli-cursor "^3.1.0"
|
||||
slice-ansi "^4.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
log-update@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz#1a04ff38166f94647ae1af562f4bd6a15b1b7cd4"
|
||||
@@ -28169,7 +28136,7 @@ run-parallel@^1.1.9:
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
rxjs@7.8.2, rxjs@^7.1.0, rxjs@^7.5.5, rxjs@~7.8.2:
|
||||
rxjs@7.8.2, rxjs@^7.5.5, rxjs@~7.8.2:
|
||||
version "7.8.2"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b"
|
||||
integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==
|
||||
@@ -29007,15 +28974,6 @@ slice-ansi@^3.0.0:
|
||||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
slice-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
|
||||
integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
slice-ansi@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz#cd6b4655e298a8d1bdeb04250a433094b347b9a9"
|
||||
|
||||
Reference in New Issue
Block a user