Skip to content
Merged
57 changes: 28 additions & 29 deletions cli/types/cypress.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/// <reference path="./cypress-npm-api.d.ts" />
/// <reference path="./cypress-eventemitter.d.ts" />
/// <reference path="./cypress-type-helpers.d.ts" />
Expand Down Expand Up @@ -687,22 +686,22 @@ declare namespace Cypress {
Keyboard: {
defaults(options: Partial<KeyboardDefaultsOptions>): void
Keys: {
DOWN: 'ArrowDown',
LEFT: 'ArrowLeft',
RIGHT: 'ArrowRight',
UP: 'ArrowUp',
END: 'End',
HOME: 'Home',
PAGEDOWN: 'PageDown',
PAGEUP: 'PageUp',
ENTER: 'Enter',
TAB: 'Tab',
BACKSPACE: 'Backspace',
SPACE: 'Space',
DELETE: 'Delete',
INSERT: 'Insert',
ESC: 'Escape',
},
DOWN: 'ArrowDown'
LEFT: 'ArrowLeft'
RIGHT: 'ArrowRight'
UP: 'ArrowUp'
END: 'End'
HOME: 'Home'
PAGEDOWN: 'PageDown'
PAGEUP: 'PageUp'
ENTER: 'Enter'
TAB: 'Tab'
BACKSPACE: 'Backspace'
SPACE: 'Space'
DELETE: 'Delete'
INSERT: 'Insert'
ESC: 'Escape'
}
}

/**
Expand Down Expand Up @@ -758,7 +757,7 @@ declare namespace Cypress {
* Trigger action
* @private
*/
action: <T = (any[] | void) >(action: string, ...args: any[]) => T
action: <T = (any[] | void)>(action: string, ...args: any[]) => T

/**
* Load files
Expand Down Expand Up @@ -1857,7 +1856,7 @@ declare namespace Cypress {
*
* @see https://on.cypress.io/prompt
*/
prompt<T extends any>(steps: string[], options?: PromptOptions): Chainable<T>
prompt<T>(steps: string[], options?: PromptOptions): Chainable<T>
/**
* Read a file and yield its contents.
*
Expand Down Expand Up @@ -2906,27 +2905,27 @@ declare namespace Cypress {
}

type RetryStrategyWithModeSpecs = RetryStrategy & {
openMode: boolean; // defaults to false
runMode: boolean; // defaults to true
openMode: boolean // defaults to false
runMode: boolean // defaults to true
}

type RetryStrategy =
| RetryStrategyDetectFlakeAndPassOnThresholdType
| RetryStrategyDetectFlakeButAlwaysFailType

interface RetryStrategyDetectFlakeAndPassOnThresholdType {
experimentalStrategy: "detect-flake-and-pass-on-threshold"
experimentalStrategy: 'detect-flake-and-pass-on-threshold'
experimentalOptions?: {
maxRetries: number; // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0
passesRequired: number; // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0 and <= maxRetries
maxRetries: number // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0
passesRequired: number // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0 and <= maxRetries
}
}

interface RetryStrategyDetectFlakeButAlwaysFailType {
experimentalStrategy: "detect-flake-but-always-fail"
experimentalStrategy: 'detect-flake-but-always-fail'
experimentalOptions?: {
maxRetries: number; // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0
stopIfAnyPassed: boolean; // defaults to false if experimentalOptions is not provided
maxRetries: number // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0
stopIfAnyPassed: boolean // defaults to false if experimentalOptions is not provided
}
}
interface ResolvedConfigOptions<ComponentDevServerOpts = any> {
Expand Down Expand Up @@ -3148,7 +3147,7 @@ declare namespace Cypress {
* @see https://on.cypress.io/experiments#Experimental-CSP-Allow-List
* @default false
*/
experimentalCspAllowList: boolean | experimentalCspAllowedDirectives[],
experimentalCspAllowList: boolean | experimentalCspAllowedDirectives[]
/**
* Allows listening to the `before:run`, `after:run`, `before:spec`, and `after:spec` events in the plugins file during interactive mode.
* @default false
Expand Down Expand Up @@ -3281,7 +3280,7 @@ declare namespace Cypress {
*/
experimentalOriginDependencies?: boolean
/**
* Enables support for the prompt command.
* Enables support for `cy.prompt`, an AI-powered command that turns natural language steps into executable Cypress test code.
* @default false
*/
experimentalPromptCommand?: boolean
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/runner/event-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,7 @@ export class EventManager {
crossOriginLogs = {}
this.studioStore.setActive(false)
this.promptStore.resetState()
await new Promise((resolve) => this.ws.emit('prompt:reset', resolve))
}

resetReporter () {
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/runner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ function teardownSpec (isRerun: boolean = false) {
export async function teardown () {
UnifiedReporterAPI.setInitializedReporter(false)
_eventManager?.stop()
_eventManager?.teardown(getMobxRunnerStore())
await _eventManager?.teardown(getMobxRunnerStore())
await _eventManager?.resetReporter()
_eventManager = undefined
}
Expand Down
8 changes: 4 additions & 4 deletions packages/config/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,25 +231,25 @@ const driverConfigOptions: Array<DriverConfigOption> = [
overrideLevel: 'any',
requireRestartOnChange: 'browser',
}, {
name: 'experimentalSourceRewriting',
name: 'experimentalPromptCommand',
defaultValue: false,
validation: validate.isBoolean,
isExperimental: true,
requireRestartOnChange: 'server',
}, {
name: 'experimentalSingleTabRunMode',
name: 'experimentalSourceRewriting',
defaultValue: false,
validation: validate.isBoolean,
isExperimental: true,
requireRestartOnChange: 'server',
}, {
name: 'experimentalStudio',
name: 'experimentalSingleTabRunMode',
defaultValue: false,
validation: validate.isBoolean,
isExperimental: true,
requireRestartOnChange: 'server',
}, {
name: 'experimentalPromptCommand',
name: 'experimentalStudio',
defaultValue: false,
validation: validate.isBoolean,
isExperimental: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/config/test/__snapshots__/index.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ exports[`config/src/index > .getPublicConfigKeys > returns list of public config
"experimentalModifyObstructiveThirdPartyCode",
"injectDocumentDomain",
"experimentalOriginDependencies",
"experimentalPromptCommand": false,
"experimentalPromptCommand",
"experimentalSourceRewriting",
"experimentalSingleTabRunMode",
"experimentalStudio",
Expand Down
130 changes: 2 additions & 128 deletions packages/config/test/project/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1008,76 +1008,6 @@ describe('config/src/project/utils', () => {

const getFilesByGlob = vi.fn().mockReturnValue(['path/to/file'])

<<<<<<< HEAD
return mergeDefaults(obj, options, {}, getFilesByGlob)
.then((cfg) => {
expect(cfg.resolved).to.deep.eq({
animationDistanceThreshold: { value: 5, from: 'default' },
arch: { value: os.arch(), from: 'default' },
baseUrl: { value: null, from: 'default' },
blockHosts: { value: null, from: 'default' },
browsers: { value: [], from: 'default' },
chromeWebSecurity: { value: true, from: 'default' },
clientCertificates: { value: [], from: 'default' },
defaultBrowser: { value: null, from: 'default' },
defaultCommandTimeout: { value: 4000, from: 'default' },
downloadsFolder: { value: 'cypress/downloads', from: 'default' },
env: {},
excludeSpecPattern: { value: '*.hot-update.js', from: 'default' },
execTimeout: { value: 60000, from: 'default' },
experimentalModifyObstructiveThirdPartyCode: { value: false, from: 'default' },
experimentalCspAllowList: { value: false, from: 'default' },
experimentalInteractiveRunEvents: { value: false, from: 'default' },
experimentalMemoryManagement: { value: false, from: 'default' },
experimentalOriginDependencies: { value: false, from: 'default' },
experimentalRunAllSpecs: { value: false, from: 'default' },
experimentalSingleTabRunMode: { value: false, from: 'default' },
experimentalStudio: { value: false, from: 'default' },
experimentalPromptCommand: { value: false, from: 'default' },
experimentalSourceRewriting: { value: false, from: 'default' },
experimentalWebKitSupport: { value: false, from: 'default' },
fileServerFolder: { value: '', from: 'default' },
fixturesFolder: { value: 'cypress/fixtures', from: 'default' },
hosts: { value: null, from: 'default' },
includeShadowDom: { value: false, from: 'default' },
injectDocumentDomain: { value: false, from: 'default' },
justInTimeCompile: { value: true, from: 'default' },
isInteractive: { value: true, from: 'default' },
keystrokeDelay: { value: 0, from: 'default' },
modifyObstructiveCode: { value: true, from: 'default' },
numTestsKeptInMemory: { value: 50, from: 'default' },
pageLoadTimeout: { value: 60000, from: 'default' },
platform: { value: os.platform(), from: 'default' },
port: { value: 1234, from: 'cli' },
projectId: { value: null, from: 'default' },
redirectionLimit: { value: 20, from: 'default' },
reporter: { value: 'json', from: 'cli' },
resolvedNodePath: { value: null, from: 'default' },
resolvedNodeVersion: { value: null, from: 'default' },
reporterOptions: { value: null, from: 'default' },
requestTimeout: { value: 5000, from: 'default' },
responseTimeout: { value: 30000, from: 'default' },
retries: { value: { runMode: 0, openMode: 0, experimentalStrategy: undefined, experimentalOptions: undefined }, from: 'default' },
screenshotOnRunFailure: { value: true, from: 'default' },
screenshotsFolder: { value: 'cypress/screenshots', from: 'default' },
specPattern: { value: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}', from: 'default' },
slowTestThreshold: { value: 10000, from: 'default' },
supportFile: { value: false, from: 'config' },
supportFolder: { value: false, from: 'default' },
taskTimeout: { value: 60000, from: 'default' },
testIsolation: { value: true, from: 'default' },
trashAssetsBeforeRuns: { value: true, from: 'default' },
userAgent: { value: null, from: 'default' },
video: { value: false, from: 'default' },
videoCompression: { value: false, from: 'default' },
videosFolder: { value: 'cypress/videos', from: 'default' },
viewportHeight: { value: 660, from: 'default' },
viewportWidth: { value: 1000, from: 'default' },
waitForAnimations: { value: true, from: 'default' },
scrollBehavior: { value: 'top', from: 'default' },
watchForFileChanges: { value: true, from: 'default' },
})
=======
const cfg = await mergeDefaults(obj, options, {}, getFilesByGlob)

expect(cfg.resolved).toEqual({
Expand All @@ -1099,6 +1029,7 @@ describe('config/src/project/utils', () => {
experimentalInteractiveRunEvents: { value: false, from: 'default' },
experimentalMemoryManagement: { value: false, from: 'default' },
experimentalOriginDependencies: { value: false, from: 'default' },
experimentalPromptCommand: { value: false, from: 'default' },
experimentalRunAllSpecs: { value: false, from: 'default' },
experimentalSingleTabRunMode: { value: false, from: 'default' },
experimentalStudio: { value: false, from: 'default' },
Expand Down Expand Up @@ -1144,7 +1075,6 @@ describe('config/src/project/utils', () => {
waitForAnimations: { value: true, from: 'default' },
scrollBehavior: { value: 'top', from: 'default' },
watchForFileChanges: { value: true, from: 'default' },
>>>>>>> origin/develop
})
})

Expand Down Expand Up @@ -1192,62 +1122,6 @@ describe('config/src/project/utils', () => {
value: 'foo',
from: 'config',
},
<<<<<<< HEAD
excludeSpecPattern: { value: '*.hot-update.js', from: 'default' },
execTimeout: { value: 60000, from: 'default' },
experimentalModifyObstructiveThirdPartyCode: { value: false, from: 'default' },
experimentalCspAllowList: { value: false, from: 'default' },
experimentalInteractiveRunEvents: { value: false, from: 'default' },
experimentalMemoryManagement: { value: false, from: 'default' },
experimentalOriginDependencies: { value: false, from: 'default' },
experimentalRunAllSpecs: { value: false, from: 'default' },
experimentalSingleTabRunMode: { value: false, from: 'default' },
experimentalStudio: { value: false, from: 'default' },
experimentalPromptCommand: { value: false, from: 'default' },
experimentalSourceRewriting: { value: false, from: 'default' },
experimentalWebKitSupport: { value: false, from: 'default' },
fileServerFolder: { value: '', from: 'default' },
fixturesFolder: { value: 'cypress/fixtures', from: 'default' },
hosts: { value: null, from: 'default' },
includeShadowDom: { value: false, from: 'default' },
injectDocumentDomain: { value: false, from: 'default' },
justInTimeCompile: { value: true, from: 'default' },
isInteractive: { value: true, from: 'default' },
keystrokeDelay: { value: 0, from: 'default' },
modifyObstructiveCode: { value: true, from: 'default' },
numTestsKeptInMemory: { value: 50, from: 'default' },
pageLoadTimeout: { value: 60000, from: 'default' },
platform: { value: os.platform(), from: 'default' },
port: { value: 2020, from: 'config' },
projectId: { value: 'projectId123', from: 'env' },
redirectionLimit: { value: 20, from: 'default' },
reporter: { value: 'spec', from: 'default' },
resolvedNodePath: { value: null, from: 'default' },
resolvedNodeVersion: { value: null, from: 'default' },
reporterOptions: { value: null, from: 'default' },
requestTimeout: { value: 5000, from: 'default' },
responseTimeout: { value: 30000, from: 'default' },
retries: { value: { runMode: 0, openMode: 0, experimentalStrategy: undefined, experimentalOptions: undefined }, from: 'default' },
screenshotOnRunFailure: { value: true, from: 'default' },
screenshotsFolder: { value: 'cypress/screenshots', from: 'default' },
slowTestThreshold: { value: 10000, from: 'default' },
specPattern: { value: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}', from: 'default' },
supportFile: { value: false, from: 'config' },
supportFolder: { value: false, from: 'default' },
taskTimeout: { value: 60000, from: 'default' },
testIsolation: { value: true, from: 'default' },
trashAssetsBeforeRuns: { value: true, from: 'default' },
userAgent: { value: null, from: 'default' },
video: { value: false, from: 'default' },
videoCompression: { value: false, from: 'default' },
videosFolder: { value: 'cypress/videos', from: 'default' },
viewportHeight: { value: 660, from: 'default' },
viewportWidth: { value: 1000, from: 'default' },
waitForAnimations: { value: true, from: 'default' },
scrollBehavior: { value: 'top', from: 'default' },
watchForFileChanges: { value: true, from: 'default' },
})
=======
bar: {
value: 'bar',
from: 'envFile',
Expand All @@ -1272,6 +1146,7 @@ describe('config/src/project/utils', () => {
experimentalInteractiveRunEvents: { value: false, from: 'default' },
experimentalMemoryManagement: { value: false, from: 'default' },
experimentalOriginDependencies: { value: false, from: 'default' },
experimentalPromptCommand: { value: false, from: 'default' },
experimentalRunAllSpecs: { value: false, from: 'default' },
experimentalSingleTabRunMode: { value: false, from: 'default' },
experimentalStudio: { value: false, from: 'default' },
Expand Down Expand Up @@ -1317,7 +1192,6 @@ describe('config/src/project/utils', () => {
waitForAnimations: { value: true, from: 'default' },
scrollBehavior: { value: 'top', from: 'default' },
watchForFileChanges: { value: true, from: 'default' },
>>>>>>> origin/develop
})
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,30 @@
describe('src/cy/commands/prompt', () => {
it('errors if wait for ready does not return success and error is ENOSPC', (done) => {
const backendStub = cy.stub(Cypress, 'backend').log(false)

const error = new Error(`no space left on device, open '<stripped-path>bundle.tar`)

error.name = 'ENOSPC'

backendStub.callThrough()
backendStub.withArgs('wait:for:prompt:ready').resolves({ success: false, error })

it('errors if download timeout is reached', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include('Failed to download cy.prompt Cloud code')
expect(err.message).to.include(`no space left on device, open '<stripped-path>bundle.tar`)

expect(err.message).to.include('Timed out downloading `cy.prompt` Cloud code')
done()
})

cy.visit('http://www.foobar.com:3500/fixtures/dom.html')

cy['commandFns']['prompt'].__resetPrompt()
cy.prompt(['Hello, world!'])
cy['commandFns']['prompt'].__resetPrompt(10000)
// @ts-expect-error - _downloadTimeout is a private option
cy.prompt(['Click the "click me" button'], { _downloadTimeout: 10 })
})

it('errors if wait for ready does not return success and error is ECONNREFUSED', (done) => {
it('errors if wait for ready does not return success and error is ENOSPC', (done) => {
const backendStub = cy.stub(Cypress, 'backend').log(false)

const error = new Error(`'<stripped-path>bundle.tar' timed out after 10000s`)
const error = new Error(`no space left on device, open /Users/ruby/dev/bundle.tar`)

error.name = 'ECONNREFUSED'
;(error as any).code = 'ENOSPC'

backendStub.callThrough()
backendStub.withArgs('wait:for:prompt:ready').resolves({ success: false, error })

cy.on('fail', (err) => {
expect(err.message).to.include('Timed out waiting for cy.prompt Cloud code:')
expect(err.message).to.include(`'<stripped-path>bundle.tar' timed out after 10000s`)
expect(err.message).to.include('Failed to download `cy.prompt` Cloud code')
expect(err.message).to.include(`no space left on device, open /Users/ruby/dev/bundle.tar`)

done()
})
Expand Down
Loading