mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-06 15:00:50 -05:00
misc: convert server/lib/modes files to ts + add more cli options to Cloud terminal error outputs (#31211)
* chore: convert server/lib/modes files to ts * update snapshots * add back require * fix call to errors.warning * Add changelog entry.
This commit is contained in:
@@ -3,6 +3,10 @@
|
||||
|
||||
_Released 3/11/2025 (PENDING)_
|
||||
|
||||
**Misc:**
|
||||
|
||||
- Additional CLI options will be displayed in the terminal for some Cloud error messages. Addressed in [#31211](https://github.com/cypress-io/cypress/pull/31211).
|
||||
|
||||
**Dependency Updates:**
|
||||
|
||||
- Upgraded `cli-table3` from `0.5.1` to `0.6.5`. Addressed in [#31166](https://github.com/cypress-io/cypress/pull/31166).
|
||||
|
||||
@@ -240,7 +240,7 @@ export const AllCypressErrors = {
|
||||
|
||||
https://on.cypress.io/stale-run`
|
||||
},
|
||||
CLOUD_ALREADY_COMPLETE: (props: {runUrl: string}) => {
|
||||
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.
|
||||
|
||||
@@ -257,7 +257,7 @@ export const AllCypressErrors = {
|
||||
|
||||
https://on.cypress.io/already-complete`
|
||||
},
|
||||
CLOUD_PARALLEL_REQUIRED: (arg1: {runUrl: string}) => {
|
||||
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.
|
||||
|
||||
@@ -274,13 +274,14 @@ export const AllCypressErrors = {
|
||||
|
||||
https://on.cypress.io/parallel-required`
|
||||
},
|
||||
CLOUD_PARALLEL_DISALLOWED: (arg1: {runUrl: string}) => {
|
||||
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',
|
||||
@@ -290,7 +291,7 @@ export const AllCypressErrors = {
|
||||
|
||||
https://on.cypress.io/parallel-disallowed`
|
||||
},
|
||||
CLOUD_PARALLEL_GROUP_PARAMS_MISMATCH: (arg1: {runUrl: string, parameters: any, payload: any }) => {
|
||||
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) {
|
||||
@@ -344,7 +345,7 @@ export const AllCypressErrors = {
|
||||
|
||||
https://on.cypress.io/parallel-group-params-mismatch`
|
||||
},
|
||||
CLOUD_RUN_GROUP_NAME_NOT_UNIQUE: (arg1: {runUrl: string, ciBuildId?: string | null}) => {
|
||||
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.
|
||||
|
||||
@@ -370,7 +371,7 @@ export const AllCypressErrors = {
|
||||
|
||||
${fmt.off(arg1.link)}`
|
||||
},
|
||||
CLOUD_AUTO_CANCEL_MISMATCH: (arg1: {runUrl: string}) => {
|
||||
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.
|
||||
|
||||
@@ -1397,7 +1398,6 @@ export const AllCypressErrors = {
|
||||
https://on.cypress.io/test-retries
|
||||
`
|
||||
},
|
||||
// TODO: test this
|
||||
INVALID_CONFIG_OPTION: (arg1: string[]) => {
|
||||
const phrase = arg1.length > 1 ? 'options are' : 'option is'
|
||||
|
||||
@@ -1886,7 +1886,7 @@ export const AllCypressErrors = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const _typeCheck: Record<keyof AllCypressErrorObj, (...args: any[]) => ErrTemplateResult> = AllCypressErrors
|
||||
|
||||
type AllCypressErrorObj = typeof AllCypressErrors
|
||||
export type AllCypressErrorObj = typeof AllCypressErrors
|
||||
|
||||
export type AllCypressErrorNames = keyof typeof AllCypressErrors
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ exports['RECORD_PARAMS_WITHOUT_RECORDING-ciBuildId 1'] = `
|
||||
You passed the --ci-build-id, --group, --tag, --parallel, or --auto-cancel-after-failures flag without also passing the --record flag.
|
||||
|
||||
The --ci-build-id flag you passed was: ciBuildId123
|
||||
The --parallel flag you passed was: undefined
|
||||
The --auto-cancel-after-failures flag you passed was: undefined
|
||||
|
||||
These flags can only be used when recording to Cypress Cloud.
|
||||
|
||||
@@ -22,6 +24,8 @@ exports['RECORD_PARAMS_WITHOUT_RECORDING-group 1'] = `
|
||||
You passed the --ci-build-id, --group, --tag, --parallel, or --auto-cancel-after-failures flag without also passing the --record flag.
|
||||
|
||||
The --group flag you passed was: e2e-tests
|
||||
The --parallel flag you passed was: undefined
|
||||
The --auto-cancel-after-failures flag you passed was: undefined
|
||||
|
||||
These flags can only be used when recording to Cypress Cloud.
|
||||
|
||||
@@ -32,6 +36,7 @@ exports['RECORD_PARAMS_WITHOUT_RECORDING-parallel 1'] = `
|
||||
You passed the --ci-build-id, --group, --tag, --parallel, or --auto-cancel-after-failures flag without also passing the --record flag.
|
||||
|
||||
The --parallel flag you passed was: true
|
||||
The --auto-cancel-after-failures flag you passed was: undefined
|
||||
|
||||
These flags can only be used when recording to Cypress Cloud.
|
||||
|
||||
@@ -43,6 +48,7 @@ You passed the --ci-build-id, --group, --tag, --parallel, or --auto-cancel-after
|
||||
|
||||
The --group flag you passed was: electron-smoke-tests
|
||||
The --parallel flag you passed was: true
|
||||
The --auto-cancel-after-failures flag you passed was: undefined
|
||||
|
||||
These flags can only be used when recording to Cypress Cloud.
|
||||
|
||||
@@ -53,6 +59,7 @@ exports['INDETERMINATE_CI_BUILD_ID-group 1'] = `
|
||||
You passed the --group or --parallel flag but we could not automatically determine or generate a ciBuildId.
|
||||
|
||||
The --group flag you passed was: e2e-tests
|
||||
The --parallel flag you passed was: undefined
|
||||
|
||||
In order to use either of these features a ciBuildId must be determined.
|
||||
|
||||
@@ -221,6 +228,7 @@ You passed the --parallel flag, but this run group was originally created withou
|
||||
|
||||
The existing run is: https://cloud.cypress.io/runs/12345
|
||||
|
||||
The --tag flag you passed was:
|
||||
The --group flag you passed was: electron-smoke-tests
|
||||
The --ciBuildId flag you passed was: ciBuildId123
|
||||
|
||||
@@ -275,6 +283,9 @@ https://on.cypress.io/stale-run
|
||||
exports['RECORD_PARAMS_WITHOUT_RECORDING-tag 1'] = `
|
||||
You passed the --ci-build-id, --group, --tag, --parallel, or --auto-cancel-after-failures flag without also passing the --record flag.
|
||||
|
||||
The --parallel flag you passed was: undefined
|
||||
The --auto-cancel-after-failures flag you passed was: undefined
|
||||
|
||||
These flags can only be used when recording to Cypress Cloud.
|
||||
|
||||
https://on.cypress.io/record-params-without-recording
|
||||
@@ -422,6 +433,7 @@ https://on.cypress.io/record-params-without-recording
|
||||
exports['RECORD_PARAMS_WITHOUT_RECORDING-auto-cancel-after-failures 1'] = `
|
||||
You passed the --ci-build-id, --group, --tag, --parallel, or --auto-cancel-after-failures flag without also passing the --record flag.
|
||||
|
||||
The --parallel flag you passed was: undefined
|
||||
The --auto-cancel-after-failures flag you passed was: 4
|
||||
|
||||
These flags can only be used when recording to Cypress Cloud.
|
||||
|
||||
@@ -239,7 +239,10 @@ const isRetriableError = (err) => {
|
||||
|
||||
export type CreateRunOptions = {
|
||||
projectRoot: string
|
||||
ci: string
|
||||
ci: {
|
||||
params: string
|
||||
provider: string
|
||||
}
|
||||
ciBuildId: string
|
||||
projectId: string
|
||||
recordKey: string
|
||||
@@ -253,6 +256,7 @@ export type CreateRunOptions = {
|
||||
testingType: 'e2e' | 'component'
|
||||
timeout?: number
|
||||
project: ProjectBase
|
||||
autoCancelAfterFailures?: number | undefined
|
||||
}
|
||||
|
||||
type CreateRunResponse = {
|
||||
|
||||
@@ -68,7 +68,7 @@ const toUploadReportPayload = (acc: {
|
||||
type UploadArtifactOptions = {
|
||||
protocolManager?: ProtocolManager
|
||||
videoUploadUrl?: string
|
||||
video?: string // filepath to the video artifact
|
||||
video?: string | null // filepath to the video artifact
|
||||
screenshots?: {
|
||||
screenshotId: string
|
||||
path: string
|
||||
|
||||
@@ -9,16 +9,17 @@ require('./environment')
|
||||
// essentially do it all again when we boot the correct
|
||||
// mode.
|
||||
|
||||
const Promise = require('bluebird')
|
||||
const debug = require('debug')('cypress:server:cypress')
|
||||
const { getPublicConfigKeys } = require('@packages/config')
|
||||
const argsUtils = require('./util/args')
|
||||
const { telemetry } = require('@packages/telemetry')
|
||||
const { getCtx, hasCtx } = require('@packages/data-context')
|
||||
import Promise from 'bluebird'
|
||||
import Debug from 'debug'
|
||||
import { getPublicConfigKeys } from '@packages/config'
|
||||
import argsUtils from './util/args'
|
||||
import { telemetry } from '@packages/telemetry'
|
||||
import { getCtx, hasCtx } from '@packages/data-context'
|
||||
import { warning as errorsWarning } from './errors'
|
||||
|
||||
const warning = (code, args) => {
|
||||
return require('./errors').warning(code, args)
|
||||
}
|
||||
const debug = Debug('cypress:server:cypress')
|
||||
|
||||
type Mode = 'exit' | 'info' | 'interactive' | 'pkg' | 'record' | 'results' | 'run' | 'smokeTest' | 'version' | 'returnPkg' | 'exitWithCode'
|
||||
|
||||
const exit = async (code = 0) => {
|
||||
// TODO: we shouldn't have to do this
|
||||
@@ -27,7 +28,7 @@ const exit = async (code = 0) => {
|
||||
debug('about to exit with code', code)
|
||||
|
||||
if (hasCtx()) {
|
||||
await getCtx().lifecycleManager.mainProcessWillDisconnect().catch((err) => {
|
||||
await getCtx().lifecycleManager.mainProcessWillDisconnect().catch((err: any) => {
|
||||
debug('mainProcessWillDisconnect errored with: ', err)
|
||||
})
|
||||
}
|
||||
@@ -37,14 +38,14 @@ const exit = async (code = 0) => {
|
||||
span?.setAttribute('exitCode', code)
|
||||
span?.end()
|
||||
|
||||
await telemetry.shutdown().catch((err) => {
|
||||
await telemetry.shutdown().catch((err: any) => {
|
||||
debug('telemetry shutdown errored with: ', err)
|
||||
})
|
||||
|
||||
return process.exit(code)
|
||||
}
|
||||
|
||||
const showWarningForInvalidConfig = (options) => {
|
||||
const showWarningForInvalidConfig = (options: any) => {
|
||||
const publicConfigKeys = getPublicConfigKeys()
|
||||
const invalidConfigOptions = require('lodash').keys(options.config).reduce((invalid, option) => {
|
||||
if (!publicConfigKeys.find((configKey) => configKey === option)) {
|
||||
@@ -55,15 +56,17 @@ const showWarningForInvalidConfig = (options) => {
|
||||
}, [])
|
||||
|
||||
if (invalidConfigOptions.length && options.invokedFromCli) {
|
||||
return warning('INVALID_CONFIG_OPTION', invalidConfigOptions)
|
||||
return errorsWarning('INVALID_CONFIG_OPTION', invalidConfigOptions)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
const exit0 = () => {
|
||||
return exit(0)
|
||||
}
|
||||
|
||||
const exitErr = (err) => {
|
||||
const exitErr = (err: any) => {
|
||||
// log errors to the console
|
||||
// and potentially raygun
|
||||
// and exit with 1
|
||||
@@ -77,12 +80,12 @@ const exitErr = (err) => {
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export = {
|
||||
isCurrentlyRunningElectron () {
|
||||
return require('./util/electron-app').isRunning()
|
||||
},
|
||||
|
||||
runElectron (mode, options) {
|
||||
runElectron (mode: Mode, options: any) {
|
||||
// wrap all of this in a promise to force the
|
||||
// promise interface - even if it doesn't matter
|
||||
// in dev mode due to cp.spawn
|
||||
@@ -95,7 +98,7 @@ module.exports = {
|
||||
// if we weren't invoked from the CLI
|
||||
// then display a warning to the user
|
||||
if (!options.invokedFromCli) {
|
||||
warning('INVOKED_BINARY_OUTSIDE_NPM_MODULE')
|
||||
errorsWarning('INVOKED_BINARY_OUTSIDE_NPM_MODULE')
|
||||
}
|
||||
|
||||
debug('running Electron currently')
|
||||
@@ -107,7 +110,7 @@ module.exports = {
|
||||
debug('starting Electron')
|
||||
const cypressElectron = require('@packages/electron')
|
||||
|
||||
const fn = (code) => {
|
||||
const fn = (code: number) => {
|
||||
// juggle up the totalFailed since our outer
|
||||
// promise is expecting this object structure
|
||||
debug('electron finished with', code)
|
||||
@@ -131,7 +134,7 @@ module.exports = {
|
||||
})
|
||||
},
|
||||
|
||||
start (argv = []) {
|
||||
start (argv: any = []) {
|
||||
debug('starting cypress with argv %o', argv)
|
||||
|
||||
// if the CLI passed "--" somewhere, we need to remove it
|
||||
@@ -144,7 +147,7 @@ module.exports = {
|
||||
options = argsUtils.toObject(argv)
|
||||
|
||||
showWarningForInvalidConfig(options)
|
||||
} catch (argumentsError) {
|
||||
} catch (argumentsError: any) {
|
||||
debug('could not parse CLI arguments: %o', argv)
|
||||
|
||||
// note - this is promise-returned call
|
||||
@@ -153,6 +156,7 @@ module.exports = {
|
||||
|
||||
debug('from argv %o got options %o', argv, options)
|
||||
|
||||
// @ts-expect-error TODO: Fix type that says attachRecordKey is not a function
|
||||
telemetry.exporter()?.attachRecordKey(options.key)
|
||||
|
||||
if (options.headless) {
|
||||
@@ -202,14 +206,14 @@ module.exports = {
|
||||
})
|
||||
},
|
||||
|
||||
startInMode (mode, options) {
|
||||
startInMode (mode: Mode, options: any) {
|
||||
debug('starting in mode %s with options %o', mode, options)
|
||||
|
||||
switch (mode) {
|
||||
case 'version':
|
||||
return require('./modes/pkg')(options)
|
||||
.get('version')
|
||||
.then((version) => {
|
||||
.then((version: any) => {
|
||||
return console.log(version) // eslint-disable-line no-console
|
||||
}).then(exit0)
|
||||
.catch(exitErr)
|
||||
@@ -221,7 +225,7 @@ module.exports = {
|
||||
|
||||
case 'smokeTest':
|
||||
return this.runElectron(mode, options)
|
||||
.then((pong) => {
|
||||
.then((pong: any) => {
|
||||
if (!this.isCurrentlyRunningElectron()) {
|
||||
return pong
|
||||
}
|
||||
@@ -236,7 +240,7 @@ module.exports = {
|
||||
|
||||
case 'returnPkg':
|
||||
return require('./modes/pkg')(options)
|
||||
.then((pkg) => {
|
||||
.then((pkg: any) => {
|
||||
return console.log(JSON.stringify(pkg)) // eslint-disable-line no-console
|
||||
}).then(exit0)
|
||||
.catch(exitErr)
|
||||
@@ -250,7 +254,7 @@ module.exports = {
|
||||
// run headlessly and exit
|
||||
// with num of totalFailed
|
||||
return this.runElectron(mode, options)
|
||||
.then((results) => {
|
||||
.then((results: any) => {
|
||||
if (results.runs) {
|
||||
const isCanceled = results.runs.filter((run) => run.skippedSpec).length
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
const _ = require('lodash')
|
||||
const Promise = require('bluebird')
|
||||
|
||||
module.exports = (options) => {
|
||||
return Promise.try(() => {
|
||||
return _.toNumber(options.exitWithCode)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { toNumber } from 'lodash'
|
||||
import Promise from 'bluebird'
|
||||
|
||||
export = (options) => {
|
||||
return Promise.try(() => {
|
||||
return toNumber(options.exitWithCode)
|
||||
})
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
/* eslint-disable no-console */
|
||||
const debug = require('debug')('cypress:server:info')
|
||||
const launcher = require('@packages/launcher')
|
||||
const pluralize = require('pluralize')
|
||||
const { stripIndent } = require('common-tags')
|
||||
const browserUtils = require('../browsers/utils')
|
||||
const _ = require('lodash')
|
||||
const chalk = require('chalk')
|
||||
const { fs } = require('../util/fs')
|
||||
import Debug from 'debug'
|
||||
import { detect as launcherDetect } from '@packages/launcher'
|
||||
import pluralize from 'pluralize'
|
||||
import { stripIndent } from 'common-tags'
|
||||
import browserUtils from '../browsers/utils'
|
||||
import _ from 'lodash'
|
||||
import chalk from 'chalk'
|
||||
import { fs } from '../util/fs'
|
||||
import type { FoundBrowser } from '@packages/types/src/browser'
|
||||
|
||||
const debug = Debug('cypress:server:info')
|
||||
// color for numbers and short values
|
||||
const n = chalk.green
|
||||
// color for paths
|
||||
@@ -21,7 +23,7 @@ const link = chalk.blue.underline
|
||||
* If the list has at least 1 item, picks a random item
|
||||
* and returns it AND the remaining items.
|
||||
*/
|
||||
const pickRandomItem = (list) => {
|
||||
const pickRandomItem = (list: any) => {
|
||||
if (!list.length) {
|
||||
return {
|
||||
item: null,
|
||||
@@ -40,7 +42,7 @@ const pickRandomItem = (list) => {
|
||||
// Usually the full browser name to pass via --browser
|
||||
// is <name>:<channel>. If the channel is stable, you
|
||||
// can just do "--browser <name>"
|
||||
const formBrowserName = (browser) => {
|
||||
const formBrowserName = (browser: FoundBrowser) => {
|
||||
if (browser.channel === 'stable') {
|
||||
return browser.name
|
||||
}
|
||||
@@ -51,9 +53,9 @@ const formBrowserName = (browser) => {
|
||||
// for each browser computes the profile folder
|
||||
// and checks if the folder exists. If exists,
|
||||
// adds it to the browser object as a property
|
||||
const addProfilePath = async (browsers = []) => {
|
||||
const addProfilePath = async (browsers: FoundBrowser[] = []) => {
|
||||
for (const browser of browsers) {
|
||||
const profilePath = browserUtils.getBrowserPath(browser)
|
||||
const profilePath: string = browserUtils.getBrowserPath(browser)
|
||||
|
||||
debug('checking profile path %s for browser %s:%s', profilePath, browser.name, browser.channel)
|
||||
try {
|
||||
@@ -71,11 +73,11 @@ const addProfilePath = async (browsers = []) => {
|
||||
return browsers
|
||||
}
|
||||
|
||||
const print = (browsers = []) => {
|
||||
const print = (browsers: FoundBrowser[] = []) => {
|
||||
console.log('Displaying Cypress info...')
|
||||
console.log('')
|
||||
if (browsers.length) {
|
||||
console.log('Detected %s %s installed:', n(browsers.length), pluralize('browser', browsers.length))
|
||||
console.log('Detected %s %s installed:', n(`${browsers.length}`), pluralize('browser', browsers.length))
|
||||
} else {
|
||||
console.log('Detected no known browsers installed')
|
||||
}
|
||||
@@ -126,7 +128,7 @@ const print = (browsers = []) => {
|
||||
}
|
||||
|
||||
const info = () => {
|
||||
return launcher.detect()
|
||||
return launcherDetect()
|
||||
.then(addProfilePath)
|
||||
.then(print)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
const Promise = require('bluebird')
|
||||
const pkg = require('@packages/root')
|
||||
|
||||
module.exports = () => {
|
||||
return Promise.resolve(pkg)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import Promise from 'bluebird'
|
||||
import pkg from '@packages/root'
|
||||
|
||||
export = () => {
|
||||
return Promise.resolve(pkg)
|
||||
}
|
||||
@@ -1,36 +1,49 @@
|
||||
const _ = require('lodash')
|
||||
const path = require('path')
|
||||
const la = require('lazy-ass')
|
||||
const check = require('check-more-types')
|
||||
const debug = require('debug')('cypress:server:record')
|
||||
const debugCiInfo = require('debug')('cypress:server:record:ci-info')
|
||||
const Promise = require('bluebird')
|
||||
const isForkPr = require('is-fork-pr')
|
||||
const commitInfo = require('@cypress/commit-info')
|
||||
const { telemetry } = require('@packages/telemetry')
|
||||
import _ from 'lodash'
|
||||
import path from 'path'
|
||||
import la from 'lazy-ass'
|
||||
import check from 'check-more-types'
|
||||
import Debug from 'debug'
|
||||
import Promise from 'bluebird'
|
||||
import isForkPr from 'is-fork-pr'
|
||||
import commitInfo from '@cypress/commit-info'
|
||||
import { telemetry } from '@packages/telemetry'
|
||||
import { hideKeys } from '@packages/config'
|
||||
|
||||
const { hideKeys } = require('@packages/config')
|
||||
import { default as api } from '../cloud/api'
|
||||
import exception from '../cloud/exception'
|
||||
import { get as getErrors, warning as errorsWarning, throwErr } from '../errors'
|
||||
import capture from '../capture'
|
||||
import { getResolvedRuntimeConfig } from '../config'
|
||||
import env from '../util/env'
|
||||
import ciProvider from '../util/ci_provider'
|
||||
import { flattenSuiteIntoRunnables } from '../util/tests_utils'
|
||||
import { countStudioUsage } from '../util/spec_writer'
|
||||
import { uploadArtifacts } from '../cloud/artifacts/upload_artifacts'
|
||||
|
||||
const api = require('../cloud/api').default
|
||||
const exception = require('../cloud/exception')
|
||||
import type { Cfg } from '../project-base'
|
||||
import type { RunResult } from './results'
|
||||
import type { ReadyOptions } from './run'
|
||||
|
||||
const errors = require('../errors')
|
||||
const capture = require('../capture')
|
||||
const Config = require('../config')
|
||||
const env = require('../util/env')
|
||||
const ciProvider = require('../util/ci_provider')
|
||||
interface InstanceOptions {
|
||||
spec?: string
|
||||
runId?: string
|
||||
group?: string
|
||||
groupId?: string
|
||||
parallel?: boolean
|
||||
machineId?: string
|
||||
ciBuildId?: string
|
||||
platform?: any
|
||||
}
|
||||
|
||||
const testsUtils = require('../util/tests_utils')
|
||||
const specWriter = require('../util/spec_writer')
|
||||
|
||||
const { uploadArtifacts } = require('../cloud/artifacts/upload_artifacts')
|
||||
const debug = Debug('cypress:server:record')
|
||||
const debugCiInfo = Debug('cypress:server:record:ci-info')
|
||||
|
||||
// dont yell about any errors either
|
||||
const runningInternalTests = () => {
|
||||
return env.get('CYPRESS_INTERNAL_SYSTEM_TESTS') === '1'
|
||||
}
|
||||
|
||||
const haveProjectIdAndKeyButNoRecordOption = (projectId, options) => {
|
||||
const haveProjectIdAndKeyButNoRecordOption = (projectId: Cfg['projectId'], options: ReadyOptions) => {
|
||||
// if we have a project id and we have a key
|
||||
// and record hasn't been set to true or false
|
||||
return (projectId && options.key) && (
|
||||
@@ -38,20 +51,22 @@ const haveProjectIdAndKeyButNoRecordOption = (projectId, options) => {
|
||||
)
|
||||
}
|
||||
|
||||
const warnIfProjectIdButNoRecordOption = (projectId, options) => {
|
||||
const warnIfProjectIdButNoRecordOption = (projectId: Cfg['projectId'], options: ReadyOptions) => {
|
||||
if (haveProjectIdAndKeyButNoRecordOption(projectId, options)) {
|
||||
// log a warning telling the user
|
||||
// that they either need to provide us
|
||||
// with a RECORD_KEY or turn off
|
||||
// record mode
|
||||
return errors.warning('PROJECT_ID_AND_KEY_BUT_MISSING_RECORD_OPTION', projectId)
|
||||
return errorsWarning('PROJECT_ID_AND_KEY_BUT_MISSING_RECORD_OPTION', `${projectId}`)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
const throwCloudCannotProceed = ({ parallel, ciBuildId, group, err }) => {
|
||||
const errMsg = parallel ? 'CLOUD_CANNOT_PROCEED_IN_PARALLEL' : 'CLOUD_CANNOT_PROCEED_IN_SERIAL'
|
||||
|
||||
const errToThrow = errors.get(errMsg, {
|
||||
const errToThrow = getErrors(errMsg, {
|
||||
response: err,
|
||||
flags: {
|
||||
group,
|
||||
@@ -65,46 +80,46 @@ const throwCloudCannotProceed = ({ parallel, ciBuildId, group, err }) => {
|
||||
throw errToThrow
|
||||
}
|
||||
|
||||
const throwIfIndeterminateCiBuildId = (ciBuildId, parallel, group) => {
|
||||
const throwIfIndeterminateCiBuildId = (ciBuildId: ReadyOptions['ciBuildId'], parallel: ReadyOptions['parallel'], group: ReadyOptions['group']) => {
|
||||
if ((!ciBuildId && !ciProvider.provider()) && (parallel || group)) {
|
||||
errors.throwErr(
|
||||
throwErr(
|
||||
'INDETERMINATE_CI_BUILD_ID',
|
||||
{
|
||||
group,
|
||||
parallel,
|
||||
parallel: `${parallel}`,
|
||||
},
|
||||
ciProvider.detectableCiBuildIdProviders(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const throwIfRecordParamsWithoutRecording = (record, ciBuildId, parallel, group, tag, autoCancelAfterFailures) => {
|
||||
const throwIfRecordParamsWithoutRecording = (record: ReadyOptions['record'], ciBuildId: ReadyOptions['ciBuildId'], parallel: ReadyOptions['parallel'], group: ReadyOptions['group'], tag: ReadyOptions['tag'], autoCancelAfterFailures: ReadyOptions['autoCancelAfterFailures']) => {
|
||||
if (!record && _.some([ciBuildId, parallel, group, tag, autoCancelAfterFailures !== undefined])) {
|
||||
errors.throwErr('RECORD_PARAMS_WITHOUT_RECORDING', {
|
||||
throwErr('RECORD_PARAMS_WITHOUT_RECORDING', {
|
||||
ciBuildId,
|
||||
tag,
|
||||
group,
|
||||
parallel,
|
||||
autoCancelAfterFailures,
|
||||
parallel: `${parallel}`,
|
||||
autoCancelAfterFailures: `${autoCancelAfterFailures}`,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const throwIfIncorrectCiBuildIdUsage = (ciBuildId, parallel, group) => {
|
||||
const throwIfIncorrectCiBuildIdUsage = (ciBuildId: ReadyOptions['ciBuildId'], parallel: ReadyOptions['parallel'], group: ReadyOptions['group']) => {
|
||||
// we've been given an explicit ciBuildId
|
||||
// but no parallel or group flag
|
||||
if (ciBuildId && (!parallel && !group)) {
|
||||
errors.throwErr('INCORRECT_CI_BUILD_ID_USAGE', { ciBuildId })
|
||||
throwErr('INCORRECT_CI_BUILD_ID_USAGE', { ciBuildId })
|
||||
}
|
||||
}
|
||||
|
||||
const throwIfNoProjectId = (projectId, configFile) => {
|
||||
const throwIfNoProjectId = (projectId: Cfg['projectId'], configFile: any) => {
|
||||
if (!projectId) {
|
||||
errors.throwErr('CANNOT_RECORD_NO_PROJECT_ID', configFile)
|
||||
throwErr('CANNOT_RECORD_NO_PROJECT_ID', configFile)
|
||||
}
|
||||
}
|
||||
|
||||
const getSpecRelativePath = (spec) => {
|
||||
const getSpecRelativePath = (spec: ReadyOptions['spec']) => {
|
||||
return _.get(spec, 'relative', null)
|
||||
}
|
||||
|
||||
@@ -135,7 +150,7 @@ returns:
|
||||
]
|
||||
*/
|
||||
|
||||
const updateInstanceStdout = async (options = {}) => {
|
||||
const updateInstanceStdout = async (options: any = {}) => {
|
||||
const { runId, instanceId, captured } = options
|
||||
|
||||
const stdout = captured.toString()
|
||||
@@ -144,21 +159,23 @@ const updateInstanceStdout = async (options = {}) => {
|
||||
runId,
|
||||
stdout,
|
||||
instanceId,
|
||||
}).catch((err) => {
|
||||
}).catch((err: any) => {
|
||||
debug('failed updating instance stdout %o', {
|
||||
stack: err.stack,
|
||||
})
|
||||
|
||||
errors.warning('CLOUD_CANNOT_CREATE_RUN_OR_INSTANCE', err)
|
||||
errorsWarning('CLOUD_CANNOT_CREATE_RUN_OR_INSTANCE', err)
|
||||
|
||||
// dont log exceptions if we have a 503 status code
|
||||
if (err.statusCode !== 503) {
|
||||
return exception.create(err)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}).finally(capture.restore)
|
||||
}
|
||||
|
||||
const postInstanceResults = (options = {}) => {
|
||||
const postInstanceResults = (options: any = {}) => {
|
||||
const { runId, instanceId, results, group, parallel, ciBuildId, metadata } = options
|
||||
let { stats, tests, video, screenshots, reporterStats, error } = results
|
||||
|
||||
@@ -187,7 +204,7 @@ const postInstanceResults = (options = {}) => {
|
||||
screenshots,
|
||||
metadata,
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch((err: any) => {
|
||||
debug('failed updating instance %o', {
|
||||
stack: err.stack,
|
||||
})
|
||||
@@ -196,7 +213,7 @@ const postInstanceResults = (options = {}) => {
|
||||
})
|
||||
}
|
||||
|
||||
const getCommitFromGitOrCi = (git) => {
|
||||
const getCommitFromGitOrCi = (git: any) => {
|
||||
la(check.object(git), 'expected git information object', git)
|
||||
|
||||
return ciProvider.commitDefaults({
|
||||
@@ -210,7 +227,7 @@ const getCommitFromGitOrCi = (git) => {
|
||||
})
|
||||
}
|
||||
|
||||
const billingLink = (orgId) => {
|
||||
const billingLink = (orgId: any) => {
|
||||
if (orgId) {
|
||||
return `https://on.cypress.io/dashboard/organizations/${orgId}/billing`
|
||||
}
|
||||
@@ -218,11 +235,11 @@ const billingLink = (orgId) => {
|
||||
return 'https://on.cypress.io/set-up-billing'
|
||||
}
|
||||
|
||||
const gracePeriodMessage = (gracePeriodEnds) => {
|
||||
const gracePeriodMessage = (gracePeriodEnds: any) => {
|
||||
return gracePeriodEnds || 'the grace period ends'
|
||||
}
|
||||
|
||||
const createRun = Promise.method((options = {}) => {
|
||||
const createRun = Promise.method((options: any = {}) => {
|
||||
_.defaults(options, {
|
||||
group: null,
|
||||
tags: null,
|
||||
@@ -242,11 +259,11 @@ const createRun = Promise.method((options = {}) => {
|
||||
// a PR because this logic triggers unintended here
|
||||
if (isForkPr.isForkPr() && !runningInternalTests()) {
|
||||
// bail with a warning
|
||||
return errors.warning('RECORDING_FROM_FORK_PR')
|
||||
return errorsWarning('RECORDING_FROM_FORK_PR')
|
||||
}
|
||||
|
||||
// else throw
|
||||
errors.throwErr('RECORD_KEY_MISSING')
|
||||
throwErr('RECORD_KEY_MISSING')
|
||||
}
|
||||
|
||||
// go back to being a string
|
||||
@@ -289,66 +306,66 @@ const createRun = Promise.method((options = {}) => {
|
||||
autoCancelAfterFailures,
|
||||
project,
|
||||
})
|
||||
.tap((response) => {
|
||||
.tap((response: any) => {
|
||||
if (!(response && response.warnings && response.warnings.length)) {
|
||||
return
|
||||
}
|
||||
|
||||
return _.each(response.warnings, (warning) => {
|
||||
return _.each(response.warnings, (warning: any) => {
|
||||
switch (warning.code) {
|
||||
case 'FREE_PLAN_IN_GRACE_PERIOD_EXCEEDS_MONTHLY_PRIVATE_TESTS':
|
||||
return errors.warning('FREE_PLAN_IN_GRACE_PERIOD_EXCEEDS_MONTHLY_PRIVATE_TESTS', {
|
||||
return errorsWarning('FREE_PLAN_IN_GRACE_PERIOD_EXCEEDS_MONTHLY_PRIVATE_TESTS', {
|
||||
limit: warning.limit,
|
||||
usedTestsMessage: 'private test',
|
||||
gracePeriodMessage: gracePeriodMessage(warning.gracePeriodEnds),
|
||||
link: billingLink(warning.orgId),
|
||||
})
|
||||
case 'FREE_PLAN_IN_GRACE_PERIOD_EXCEEDS_MONTHLY_TESTS':
|
||||
return errors.warning('FREE_PLAN_IN_GRACE_PERIOD_EXCEEDS_MONTHLY_TESTS', {
|
||||
return errorsWarning('FREE_PLAN_IN_GRACE_PERIOD_EXCEEDS_MONTHLY_TESTS', {
|
||||
limit: warning.limit,
|
||||
usedTestsMessage: 'test',
|
||||
gracePeriodMessage: gracePeriodMessage(warning.gracePeriodEnds),
|
||||
link: billingLink(warning.orgId),
|
||||
})
|
||||
case 'FREE_PLAN_IN_GRACE_PERIOD_PARALLEL_FEATURE':
|
||||
return errors.warning('FREE_PLAN_IN_GRACE_PERIOD_PARALLEL_FEATURE', {
|
||||
return errorsWarning('FREE_PLAN_IN_GRACE_PERIOD_PARALLEL_FEATURE', {
|
||||
gracePeriodMessage: gracePeriodMessage(warning.gracePeriodEnds),
|
||||
link: billingLink(warning.orgId),
|
||||
})
|
||||
case 'FREE_PLAN_EXCEEDS_MONTHLY_TESTS_V2':
|
||||
return errors.warning('PLAN_EXCEEDS_MONTHLY_TESTS', {
|
||||
return errorsWarning('PLAN_EXCEEDS_MONTHLY_TESTS', {
|
||||
planType: 'free',
|
||||
limit: warning.limit,
|
||||
usedTestsMessage: 'test',
|
||||
link: billingLink(warning.orgId),
|
||||
})
|
||||
case 'PAID_PLAN_EXCEEDS_MONTHLY_PRIVATE_TESTS':
|
||||
return errors.warning('PLAN_EXCEEDS_MONTHLY_TESTS', {
|
||||
return errorsWarning('PLAN_EXCEEDS_MONTHLY_TESTS', {
|
||||
planType: 'current',
|
||||
limit: warning.limit,
|
||||
usedTestsMessage: 'private test',
|
||||
link: billingLink(warning.orgId),
|
||||
})
|
||||
case 'PAID_PLAN_EXCEEDS_MONTHLY_TESTS':
|
||||
return errors.warning('PLAN_EXCEEDS_MONTHLY_TESTS', {
|
||||
return errorsWarning('PLAN_EXCEEDS_MONTHLY_TESTS', {
|
||||
planType: 'current',
|
||||
limit: warning.limit,
|
||||
usedTestsMessage: 'test',
|
||||
link: billingLink(warning.orgId),
|
||||
})
|
||||
case 'PLAN_IN_GRACE_PERIOD_RUN_GROUPING_FEATURE_USED':
|
||||
return errors.warning('PLAN_IN_GRACE_PERIOD_RUN_GROUPING_FEATURE_USED', {
|
||||
return errorsWarning('PLAN_IN_GRACE_PERIOD_RUN_GROUPING_FEATURE_USED', {
|
||||
gracePeriodMessage: gracePeriodMessage(warning.gracePeriodEnds),
|
||||
link: billingLink(warning.orgId),
|
||||
})
|
||||
default:
|
||||
return errors.warning('CLOUD_UNKNOWN_CREATE_RUN_WARNING', {
|
||||
return errorsWarning('CLOUD_UNKNOWN_CREATE_RUN_WARNING', {
|
||||
message: warning.message,
|
||||
props: _.omit(warning, 'message'),
|
||||
})
|
||||
}
|
||||
})
|
||||
}).catch((err) => {
|
||||
}).catch((err: any) => {
|
||||
debug('failed creating run with status %o',
|
||||
_.pick(err, ['name', 'message', 'statusCode', 'stack']))
|
||||
|
||||
@@ -362,7 +379,7 @@ const createRun = Promise.method((options = {}) => {
|
||||
recordKey = 'undefined'
|
||||
}
|
||||
|
||||
return errors.throwErr('CLOUD_RECORD_KEY_NOT_VALID', recordKey, projectId)
|
||||
return throwErr('CLOUD_RECORD_KEY_NOT_VALID', recordKey, projectId)
|
||||
case 402: {
|
||||
const { code, payload } = err.error
|
||||
|
||||
@@ -371,31 +388,31 @@ const createRun = Promise.method((options = {}) => {
|
||||
|
||||
switch (code) {
|
||||
case 'FREE_PLAN_EXCEEDS_MONTHLY_PRIVATE_TESTS':
|
||||
return errors.throwErr('FREE_PLAN_EXCEEDS_MONTHLY_PRIVATE_TESTS', {
|
||||
return throwErr('FREE_PLAN_EXCEEDS_MONTHLY_PRIVATE_TESTS', {
|
||||
limit,
|
||||
usedTestsMessage: 'private test',
|
||||
link: billingLink(orgId),
|
||||
})
|
||||
case 'FREE_PLAN_EXCEEDS_MONTHLY_TESTS':
|
||||
return errors.throwErr('FREE_PLAN_EXCEEDS_MONTHLY_TESTS', {
|
||||
return throwErr('FREE_PLAN_EXCEEDS_MONTHLY_TESTS', {
|
||||
limit,
|
||||
usedTestsMessage: 'test',
|
||||
link: billingLink(orgId),
|
||||
})
|
||||
case 'PARALLEL_FEATURE_NOT_AVAILABLE_IN_PLAN':
|
||||
return errors.throwErr('PARALLEL_FEATURE_NOT_AVAILABLE_IN_PLAN', {
|
||||
return throwErr('PARALLEL_FEATURE_NOT_AVAILABLE_IN_PLAN', {
|
||||
link: billingLink(orgId),
|
||||
})
|
||||
case 'RUN_GROUPING_FEATURE_NOT_AVAILABLE_IN_PLAN':
|
||||
return errors.throwErr('RUN_GROUPING_FEATURE_NOT_AVAILABLE_IN_PLAN', {
|
||||
return throwErr('RUN_GROUPING_FEATURE_NOT_AVAILABLE_IN_PLAN', {
|
||||
link: billingLink(orgId),
|
||||
})
|
||||
case 'AUTO_CANCEL_NOT_AVAILABLE_IN_PLAN':
|
||||
return errors.throwErr('CLOUD_AUTO_CANCEL_NOT_AVAILABLE_IN_PLAN', {
|
||||
return throwErr('CLOUD_AUTO_CANCEL_NOT_AVAILABLE_IN_PLAN', {
|
||||
link: billingLink(orgId),
|
||||
})
|
||||
default:
|
||||
return errors.throwErr('CLOUD_UNKNOWN_INVALID_REQUEST', {
|
||||
return throwErr('CLOUD_UNKNOWN_INVALID_REQUEST', {
|
||||
response: err,
|
||||
flags: {
|
||||
group,
|
||||
@@ -407,17 +424,17 @@ const createRun = Promise.method((options = {}) => {
|
||||
}
|
||||
}
|
||||
case 404:
|
||||
return errors.throwErr('CLOUD_PROJECT_NOT_FOUND', projectId, path.basename(options.configFile))
|
||||
return throwErr('CLOUD_PROJECT_NOT_FOUND', projectId, path.basename(options.configFile))
|
||||
case 412:
|
||||
return errors.throwErr('CLOUD_INVALID_RUN_REQUEST', err.error)
|
||||
return throwErr('CLOUD_INVALID_RUN_REQUEST', err.error)
|
||||
case 422: {
|
||||
const { code, payload } = err.error
|
||||
|
||||
const runUrl = _.get(payload, 'runUrl')
|
||||
const runUrl: string = _.get(payload, 'runUrl')
|
||||
|
||||
switch (code) {
|
||||
case 'RUN_GROUP_NAME_NOT_UNIQUE':
|
||||
return errors.throwErr('CLOUD_RUN_GROUP_NAME_NOT_UNIQUE', {
|
||||
return throwErr('CLOUD_RUN_GROUP_NAME_NOT_UNIQUE', {
|
||||
group,
|
||||
runUrl,
|
||||
ciBuildId,
|
||||
@@ -425,7 +442,7 @@ const createRun = Promise.method((options = {}) => {
|
||||
case 'PARALLEL_GROUP_PARAMS_MISMATCH': {
|
||||
const { browserName, browserVersion, osName, osVersion } = platform
|
||||
|
||||
return errors.throwErr('CLOUD_PARALLEL_GROUP_PARAMS_MISMATCH', {
|
||||
return throwErr('CLOUD_PARALLEL_GROUP_PARAMS_MISMATCH', {
|
||||
group,
|
||||
runUrl,
|
||||
ciBuildId,
|
||||
@@ -440,21 +457,21 @@ const createRun = Promise.method((options = {}) => {
|
||||
})
|
||||
}
|
||||
case 'PARALLEL_DISALLOWED':
|
||||
return errors.throwErr('CLOUD_PARALLEL_DISALLOWED', {
|
||||
return throwErr('CLOUD_PARALLEL_DISALLOWED', {
|
||||
tags,
|
||||
group,
|
||||
runUrl,
|
||||
ciBuildId,
|
||||
})
|
||||
case 'PARALLEL_REQUIRED':
|
||||
return errors.throwErr('CLOUD_PARALLEL_REQUIRED', {
|
||||
return throwErr('CLOUD_PARALLEL_REQUIRED', {
|
||||
tags,
|
||||
group,
|
||||
runUrl,
|
||||
ciBuildId,
|
||||
})
|
||||
case 'ALREADY_COMPLETE':
|
||||
return errors.throwErr('CLOUD_ALREADY_COMPLETE', {
|
||||
return throwErr('CLOUD_ALREADY_COMPLETE', {
|
||||
runUrl,
|
||||
tags,
|
||||
group,
|
||||
@@ -462,7 +479,7 @@ const createRun = Promise.method((options = {}) => {
|
||||
ciBuildId,
|
||||
})
|
||||
case 'STALE_RUN':
|
||||
return errors.throwErr('CLOUD_STALE_RUN', {
|
||||
return throwErr('CLOUD_STALE_RUN', {
|
||||
runUrl,
|
||||
tags,
|
||||
group,
|
||||
@@ -470,7 +487,7 @@ const createRun = Promise.method((options = {}) => {
|
||||
ciBuildId,
|
||||
})
|
||||
case 'AUTO_CANCEL_MISMATCH':
|
||||
return errors.throwErr('CLOUD_AUTO_CANCEL_MISMATCH', {
|
||||
return throwErr('CLOUD_AUTO_CANCEL_MISMATCH', {
|
||||
runUrl,
|
||||
tags,
|
||||
group,
|
||||
@@ -479,7 +496,7 @@ const createRun = Promise.method((options = {}) => {
|
||||
autoCancelAfterFailures,
|
||||
})
|
||||
default:
|
||||
return errors.throwErr('CLOUD_UNKNOWN_INVALID_REQUEST', {
|
||||
return throwErr('CLOUD_UNKNOWN_INVALID_REQUEST', {
|
||||
response: err,
|
||||
flags: {
|
||||
tags,
|
||||
@@ -496,10 +513,10 @@ const createRun = Promise.method((options = {}) => {
|
||||
})
|
||||
})
|
||||
|
||||
const createInstance = (options = {}) => {
|
||||
const createInstance = (options: InstanceOptions = {}) => {
|
||||
let { runId, group, groupId, parallel, machineId, ciBuildId, platform, spec } = options
|
||||
|
||||
spec = getSpecRelativePath(spec)
|
||||
spec = spec ? getSpecRelativePath(spec) : null
|
||||
|
||||
return api.createInstance({
|
||||
spec,
|
||||
@@ -508,7 +525,7 @@ const createInstance = (options = {}) => {
|
||||
platform,
|
||||
machineId,
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch((err: any) => {
|
||||
debug('failed creating instance %o', {
|
||||
stack: err.stack,
|
||||
})
|
||||
@@ -539,12 +556,12 @@ const _postInstanceTests = ({
|
||||
tests,
|
||||
hooks,
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch((err: any) => {
|
||||
throwCloudCannotProceed({ parallel, ciBuildId, group, err })
|
||||
})
|
||||
}
|
||||
|
||||
const createRunAndRecordSpecs = (options = {}) => {
|
||||
const createRunAndRecordSpecs = (options: any = {}) => {
|
||||
const { specPattern,
|
||||
specs,
|
||||
sys,
|
||||
@@ -568,7 +585,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
const tags = _.split(options.tag, ',')
|
||||
|
||||
return commitInfo.commitInfo(projectRoot)
|
||||
.then((git) => {
|
||||
.then((git: any) => {
|
||||
debugCiInfo('found the following git information')
|
||||
debugCiInfo(git)
|
||||
|
||||
@@ -583,6 +600,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
|
||||
telemetry.startSpan({ name: 'record:createRun' })
|
||||
|
||||
// @ts-expect-error TODO: Fix this saying its expecting 0 args
|
||||
return createRun({
|
||||
projectRoot,
|
||||
git,
|
||||
@@ -600,7 +618,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
autoCancelAfterFailures,
|
||||
project,
|
||||
})
|
||||
.then((resp) => {
|
||||
.then((resp: any) => {
|
||||
telemetry.getSpan('record:createRun')?.end()
|
||||
if (!resp) {
|
||||
// if a forked run, can't record and can't be parallel
|
||||
@@ -616,7 +634,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
let captured = null
|
||||
let instanceId = null
|
||||
|
||||
const beforeSpecRun = (spec) => {
|
||||
const beforeSpecRun = (spec: any) => {
|
||||
telemetry.startSpan({ name: 'record:beforeSpecRun' })
|
||||
project.setOnTestsReceived(onTestsReceived)
|
||||
capture.restore()
|
||||
@@ -633,7 +651,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
ciBuildId,
|
||||
machineId,
|
||||
})
|
||||
.then((resp = {}) => {
|
||||
.then((resp: any = {}) => {
|
||||
instanceId = resp.instanceId
|
||||
|
||||
// pull off only what we need
|
||||
@@ -652,7 +670,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
})
|
||||
}
|
||||
|
||||
const afterSpecRun = (spec, results, config) => {
|
||||
const afterSpecRun = (spec: any, results: RunResult, config: any) => {
|
||||
// don't do anything if we failed to
|
||||
// create the instance
|
||||
if (!instanceId || results.skippedSpec) {
|
||||
@@ -663,7 +681,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
|
||||
debug('after spec run %o', { spec })
|
||||
|
||||
return specWriter.countStudioUsage(spec.absolute)
|
||||
return countStudioUsage(spec.absolute)
|
||||
.then((metadata) => {
|
||||
return postInstanceResults({
|
||||
group,
|
||||
@@ -675,7 +693,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
metadata,
|
||||
})
|
||||
})
|
||||
.then((resp) => {
|
||||
.then((resp: any) => {
|
||||
if (!resp) {
|
||||
return
|
||||
}
|
||||
@@ -686,6 +704,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
|
||||
return uploadArtifacts({
|
||||
runId,
|
||||
// @ts-expect-error TODO: Fix this saying instanceId cannot be null here - we returned earlier if null
|
||||
instanceId,
|
||||
video,
|
||||
screenshots,
|
||||
@@ -712,7 +731,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
})
|
||||
}
|
||||
|
||||
const onTestsReceived = (async (runnables, cb) => {
|
||||
const onTestsReceived = (async (runnables: any, cb: any) => {
|
||||
// we failed createInstance earlier, nothing to do
|
||||
if (!instanceId) {
|
||||
return cb()
|
||||
@@ -722,9 +741,9 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
// this also means runtimeConfig will be missing
|
||||
runnables = runnables || {}
|
||||
|
||||
const r = testsUtils.flattenSuiteIntoRunnables(runnables)
|
||||
const r = flattenSuiteIntoRunnables(runnables)
|
||||
const runtimeConfig = runnables.runtimeConfig
|
||||
const resolvedRuntimeConfig = Config.getResolvedRuntimeConfig(config, runtimeConfig)
|
||||
const resolvedRuntimeConfig = getResolvedRuntimeConfig(config, runtimeConfig)
|
||||
|
||||
const tests = _.chain(r[0])
|
||||
.uniqBy('id')
|
||||
@@ -774,7 +793,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
ciBuildId,
|
||||
group,
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch((err: any) => {
|
||||
onError(err)
|
||||
|
||||
return responseDidFail
|
||||
@@ -788,7 +807,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
}
|
||||
|
||||
if (_.some(response.actions, { type: 'SPEC', action: 'SKIP' })) {
|
||||
errors.warning('CLOUD_CANCEL_SKIPPED_SPEC')
|
||||
errorsWarning('CLOUD_CANCEL_SKIPPED_SPEC')
|
||||
|
||||
// set a property on the response so the browser runner
|
||||
// knows not to start executing tests
|
||||
@@ -812,7 +831,7 @@ const createRunAndRecordSpecs = (options = {}) => {
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export = {
|
||||
createRun,
|
||||
|
||||
createInstance,
|
||||
@@ -5,10 +5,10 @@ import type { FoundBrowser, SpecWithRelativeRoot } from '@packages/types'
|
||||
import path from 'path'
|
||||
|
||||
import type { Cfg } from '../project-base'
|
||||
import type { ScreenshotMetadata } from './run'
|
||||
|
||||
type dateTimeISO = string
|
||||
type ms = number
|
||||
type pixels = number
|
||||
|
||||
interface TestError {
|
||||
message: string
|
||||
@@ -48,20 +48,12 @@ interface HookInformation {
|
||||
body: string
|
||||
}
|
||||
|
||||
interface ScreenshotInformation {
|
||||
height: pixels
|
||||
name: string
|
||||
path: string
|
||||
takenAt: dateTimeISO
|
||||
width: pixels
|
||||
}
|
||||
|
||||
interface RunResult {
|
||||
export interface RunResult {
|
||||
error: string | null
|
||||
hooks: HookInformation[]
|
||||
reporter: string
|
||||
reporterStats: object
|
||||
screenshots: ScreenshotInformation[]
|
||||
screenshots: ScreenshotMetadata[]
|
||||
skippedSpec: boolean
|
||||
spec: SpecWithRelativeRoot
|
||||
stats: {
|
||||
|
||||
@@ -32,7 +32,8 @@ import { CDPFailedToStartFirefox } from '../browsers/firefox'
|
||||
import type { CypressError } from '@packages/errors'
|
||||
|
||||
type SetScreenshotMetadata = (data: TakeScreenshotProps) => void
|
||||
type ScreenshotMetadata = ReturnType<typeof screenshotMetadata>
|
||||
export type ScreenshotMetadata = ReturnType<typeof screenshotMetadata>
|
||||
|
||||
type TakeScreenshotProps = any
|
||||
type RunEachSpec = any
|
||||
type BeforeSpecRun = any
|
||||
@@ -753,7 +754,7 @@ async function waitForTestsToFinishRunning (options: { project: Project, screens
|
||||
return results
|
||||
}
|
||||
|
||||
function screenshotMetadata (data, resp) {
|
||||
function screenshotMetadata (data: any, resp: any) {
|
||||
return {
|
||||
screenshotId: random.id(),
|
||||
name: data.name || null,
|
||||
@@ -1006,7 +1007,7 @@ async function runSpec (config, spec: SpecWithRelativeRoot, options: { project:
|
||||
return { results }
|
||||
}
|
||||
|
||||
interface ReadyOptions {
|
||||
export interface ReadyOptions {
|
||||
autoCancelAfterFailures: number | false
|
||||
browser: string
|
||||
browsers?: FoundBrowser[]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
run (options) {
|
||||
export = {
|
||||
run (options: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(options.pong)
|
||||
|
||||
Reference in New Issue
Block a user