mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-06 15:20:25 -06:00
* Create cy-prompt-development.md * chore: cy prompt infrastructure (#31748) * feat: cy prompt infrastructure * refactor and add tests * refactor * rename experimental config * prompt * fix test * Update cy-prompt-development.md * Update cy-prompt-development.md * PR comments * Update packages/server/lib/cloud/api/cy-prompt/get_cy_prompt_bundle.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * PR comments --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix test * Delete packages/server/lib/cloud/StudioLifecycleManager.ts * Delete packages/server/test/unit/cloud/StudioLifecycleManager_spec.ts * chore: add cdp connection to cy prompt (#31806) * chore: add cdp connection to cy prompt * minor fix * fix type build * try to fix build * Update packages/server/lib/browsers/browser-cri-client.ts Co-authored-by: Bill Glesias <bglesias@gmail.com> * Update packages/server/lib/browsers/browser-cri-client.ts Co-authored-by: Bill Glesias <bglesias@gmail.com> * do not support prompt in firefox or webkit * rework timing of lifecycle * refactor * fix tests * troubleshooting * troubleshooting * fix tests * additional troubleshooting * additional troubleshooting * additional troubleshooting * attempt to fix build * add back * debugging * debugging * debugging * debugging * clean up * fix unit tests * rework --------- Co-authored-by: Bill Glesias <bglesias@gmail.com> * chore: create infrastructure to support backend function in cy.prompt (#31803) * chore: add promptBackend as an additional Cypress-attached function * Update packages/app/src/runner/event-manager.ts * update types * fix types * fix spacing * refactor * additional refactor * fix type build * fix build * refactor * reword messages * fix * debugging * undo debugging * PR comment * fix tests * fix tests * fix tests * fix test * chore: add watcher for cy-prompt development (#31810) * chore: add watcher for cy-prompt development * test caching * fix types * chore: turn on beta deployments for cy-prompt * internal: (cy.prompt) handle errors better in the command definition (#31835) * internal: (cy.prompt) handle errors better in the command definition * internal: (cy.prompt) add timeout and handle loading errors more cleanly * add process environment variable * clean up test * update JSDoc * chore: handle errors (#31854) * chore: handle errors * Fix ts, add test * Fix error title * Fix ts * Fix ts * chores: (cy.prompt) refactor routing to support both app and driver (#31891) * chore: Share error utils with the cloud (#31887) * share error utils with cloud * additional rework * Fix command, add isOpenMode * Add / fix test * fix ts --------- Co-authored-by: Ryan Manuel <ryanm@cypress.io> * internal: (cy.prompt) add infrastructure to support a Get Code modal (#31904) * chore: (cy.prompt) add infrastructure to support a Get Code modal * fix tests * fix code paths * Update eject button styles * handle errors * update types * Update packages/server/lib/socket-base.ts * Fix cy test * update readme --------- Co-authored-by: estrada9166 <estrada9166@gmail.com> * chore: (cy.prompt) refactor getTestsState to take a runnable id (#31965) * chore: (cy.prompt) refactor getTestsState to take a runnable id * fix tests * minor tweak * chore: (cy.prompt) add manifest for all of the cloud delivered files (#31922) * chore: (cy.prompt) add manifest for all of the cloud delivered files * fix tests and remove environment variables * update strategy * fix build * rework * require manifest * clean up * refactor * refactor * Update packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts Co-authored-by: Matt Schile <mschile@cypress.io> * fix test --------- Co-authored-by: Matt Schile <mschile@cypress.io> * feat: add cy prompt more info needed modal (WIP) (#31970) * feat: add cy prompt more info needed modal * Reset promptStore * additional things exposed for more info * rework * fix tests * fix build * fix types * fix types * Update packages/app/src/runner/event-manager.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * reefactor * chore: (cy.prompt) rework the file save lifecycle * rework types * add unit tests --------- Co-authored-by: estrada9166 <estrada9166@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: (cy.prompt) ensure that we do not attach a vue ref to the react root in the cy.prompt modals (#32011) * fix: (studio) ensure that we do not attach a vue ref to the react root in the studio panel * fix test * chore: Handle cy-prompt error to the cloud (#32009) Co-authored-by: Ryan Manuel <ryanm@cypress.io> * chore: display prompt error message (#32016) * add createCloudRequest to cloudApi, handle errors during createCyPromptServer * render the get code button on failure * chore: update types * chore: move CT and browser error to cloud (#32077) * feat: (cy.prompt) give cy.prompt access to recording information (#32110) * feat: (cy.prompt) give cy.prompt access to recording information * undo bad refactor * undo bad refactor * undo bad refactor * rename * fix typo * Update packages/server/test/unit/modes/record_spec.js * Update packages/server/test/unit/modes/record_spec.js * Update packages/server/test/unit/modes/record_spec.js * Update packages/server/test/unit/modes/record_spec.js * Update packages/server/test/unit/modes/record_spec.js * Update cy-prompt-development.md * Update cy-prompt-development.md * Update cy-prompt-development.md * chore: add CYPRESS_INTERNAL_SIMULATE_OPEN_MODE to simulate running Cypress tests in open mode (#32114) * chore: (cy.prompt) ensure to strip out paths from all data when reporting errors in prompt (#32134) * fix: (cy.prompt) ensure to strip out paths from all data when reporting errors in prompt * refactor * update tests * fix logic error with protocol * add event manager to get code * Apply suggestions from code review * fix: (cy.prompt) improve the get project options performance by running promises in parallel (#32196) * fix: (cy.prompt) improve the get project options performance by running promises in parallel * add awaits in test * bump cache * Update packages/server/lib/cloud/studio/StudioLifecycleManager.ts * fix build * chore: cleanup * blank * Update trigger-publish-binary-pipeline.js * Update packages/server/test/unit/socket_spec.js * get rid of environment variable * fix: (cy.prompt) ensure to reset the prompt state when the event manager is torn down (indicating that we're no longer on the runner page) (#32301) * fix: (cy.prompt) ensure to reset the prompt state when the event manager is torn down (indicating that we're no longer on the runner page) * move test * fix lint issue * feat: (cy.prompt) introduce the concept of log collapse state being open/closed by default (#32262) * feat: (cy.prompt) introduce the concept of logs' collapse state being open/closed by default * update tests * rename * PR comments * fix test due to bad merge of develop * chore: Only allow experimentalPromptCommand within e2e config (#32435) * chore: Only allow experimentalPromptCommand within e2e config * Fix config * Update tests * Update test, update types * Fix test and types * fix tests * Add types * Update cli/types/cypress.d.ts Co-authored-by: Ryan Manuel <ryanm@cypress.io> --------- Co-authored-by: Ryan Manuel <ryanm@cypress.io> * Update workflows.yml * Add optional cyPromptManagerPromise property * Implement error handling in CyPromptManager Added a new method to handle errors uniformly in CyPromptManager. * Fix indentation in socket_spec.js * fix: (cy.prompt) handle when the prompt is executed by in CT or when the experiment is not enabled (#32470) * fix: (cy.prompt) handle when the prompt is executed by in CT or when the experiment is not enabled * Update packages/driver/cypress/e2e/commands/prompt/prompt.cy.ts * Update packages/driver/cypress/e2e/commands/prompt/prompt.cy.ts * update name of errors * Bump cache version to 9-15-2025 * update yarn.lock * fixes * fix snapshot * fix snapshot * internal: fix get code button to be purple with correct margin (#32504) * feat: (cy.prompt) update the types of prompt (#32529) * fix: move currentMoreInfoNeededModalInfo.onCancel to onClose (#32559) * internal: (cy.prompt) various improvements to error messages and time outs (#32582) * internal: (cy.prompt) various improvements to error messages and timeouts * fix test * remove dead code * Update packages/driver/src/cy/commands/prompt/index.ts * update prompt experiment description * fix build * fix tests * fix tests * fix test * update error message * Update packages/server/lib/experiments.ts Co-authored-by: Tim Griesser <tgriesser10@gmail.com> --------- Co-authored-by: Tim Griesser <tgriesser10@gmail.com> * internal: (cy.prompt) ensure that get code can properly work with prompts in cy.origin (#32596) * internal: (cy.prompt) ensure that get code can properly work with prompts in cy.origin * additional tests * additional tests * Apply suggestions from code review * code review comment * fix merge * fix merge * Update packages/data-context/graphql/schemaTypes/index.ts * update workflow * blank * persist binaries * chore: display custom link title (#32567) * chore: display custom link title * Add test * Pass docs as second argument of the error * Revert changes * Use openExternal for links --------- Co-authored-by: Jennifer Shehane <jennifer@cypress.io> * update * internal: (cy.prompt) do not retry on cert failures (#32624) * internal: (cy.prompt) do not retry on cert failures * tests and clean up * additional cleanup and add error message for prompt * fix unit tests * Update report_studio_error.ts * Update packages/network/lib/agent.ts * cursor comment * fix build * fix build * fix test * fix build * fix build * fix build * fix build * fix build * revert * Update packages/driver/src/cypress/error_messages.ts * Update packages/driver/cypress/e2e/commands/prompt/prompt-initialization-error.cy.ts * fix build * cursor comment * add changelog entry * clean up * Update packages/app/src/store/prompt-store.ts * Bump cache version to 10-3-2025 Updated cache version to trigger CI cache recreation. * Revise CHANGELOG for new features and fixes Updated changelog with new features and bug fixes. * index on feat/cy-prompt:3cbcf6c336Bump cache version to 10-3-2025 * index on feat/cy-prompt:3cbcf6c336Bump cache version to 10-3-2025 * index on feat/cy-prompt:3cbcf6c336Bump cache version to 10-3-2025 * blank * fix build --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Bill Glesias <bglesias@gmail.com> Co-authored-by: Alejandro Estrada <estrada9166@gmail.com> Co-authored-by: Matt Schile <mschile@cypress.io> Co-authored-by: Tim Griesser <tgriesser10@gmail.com> Co-authored-by: Jennifer Shehane <jennifer@cypress.io> Co-authored-by: Jennifer Shehane <shehane.jennifer@gmail.com> Co-authored-by: cypress-bot[bot] <+cypress-bot[bot]@users.noreply.github.com>
279 lines
9.8 KiB
JavaScript
279 lines
9.8 KiB
JavaScript
require('../spec_helper')
|
|
|
|
const Bluebird = require('bluebird')
|
|
const browsers = require(`../../lib/browsers`)
|
|
const ProjectBase = require(`../../lib/project-base`).ProjectBase
|
|
const { openProject } = require('../../lib/open_project')
|
|
const preprocessor = require(`../../lib/plugins/preprocessor`).default
|
|
const runEvents = require(`../../lib/plugins/run_events`).default
|
|
const Fixtures = require('@tooling/system-tests')
|
|
const delay = require('lodash/delay')
|
|
|
|
const todosPath = Fixtures.projectPath('todos')
|
|
|
|
describe('lib/open_project', () => {
|
|
beforeEach(function () {
|
|
this.automation = {
|
|
reset: sinon.stub(),
|
|
use: sinon.stub(),
|
|
}
|
|
|
|
this.config = {
|
|
excludeSpecPattern: '**/*.nope',
|
|
projectRoot: todosPath,
|
|
proxyServer: 'http://cy-proxy-server',
|
|
}
|
|
|
|
this.onError = sinon.stub()
|
|
sinon.stub(browsers, 'get').resolves()
|
|
sinon.stub(browsers, 'open')
|
|
sinon.stub(browsers, 'connectToNewSpec')
|
|
sinon.stub(ProjectBase.prototype, 'initializeConfig').resolves({
|
|
specPattern: 'cypress/integration/**/*',
|
|
})
|
|
|
|
sinon.stub(ProjectBase.prototype, 'open').resolves()
|
|
sinon.stub(ProjectBase.prototype, 'reset').resolves()
|
|
sinon.stub(ProjectBase.prototype, 'getConfig').returns(this.config)
|
|
sinon.stub(ProjectBase.prototype, 'getAutomation').returns(this.automation)
|
|
sinon.stub(preprocessor, 'removeFile')
|
|
|
|
return Fixtures.scaffoldProject('todos').then(() => {
|
|
return openProject.create(todosPath, { testingType: 'e2e' }, { onError: this.onError })
|
|
})
|
|
})
|
|
|
|
context('#launch', () => {
|
|
beforeEach(async function () {
|
|
await openProject.create(todosPath, { testingType: 'e2e' }, { onError: this.onError })
|
|
openProject.getProject().__setConfig({
|
|
browserUrl: 'http://localhost:8888/__/',
|
|
projectRoot: todosPath,
|
|
specType: 'integration',
|
|
e2e: {
|
|
specPattern: 'cypress/integration/**/*',
|
|
},
|
|
})
|
|
|
|
openProject.getProject().options = {
|
|
onError: this.onError,
|
|
}
|
|
|
|
this.spec = {
|
|
absolute: 'path/to/spec',
|
|
relative: 'path/to/spec',
|
|
}
|
|
|
|
this.browser = { name: 'chrome' }
|
|
})
|
|
|
|
it('tells preprocessor to remove file on browser close', function () {
|
|
return openProject.launch(this.browser, this.spec)
|
|
.then(() => {
|
|
browsers.open.lastCall.args[1].onBrowserClose()
|
|
|
|
expect(preprocessor.removeFile).to.be.calledWith('path/to/spec')
|
|
})
|
|
})
|
|
|
|
it('does not tell preprocessor to remove file if no spec', function () {
|
|
return openProject.launch(this.browser, {})
|
|
.then(() => {
|
|
browsers.open.lastCall.args[1].onBrowserClose()
|
|
|
|
expect(preprocessor.removeFile).not.to.be.called
|
|
})
|
|
})
|
|
|
|
it('runs original onBrowserClose callback on browser close', function () {
|
|
const onBrowserClose = sinon.stub()
|
|
const options = { onBrowserClose }
|
|
|
|
return openProject.launch(this.browser, this.spec, options)
|
|
.then(() => {
|
|
browsers.open.lastCall.args[1].onBrowserClose()
|
|
|
|
expect(onBrowserClose).to.be.called
|
|
})
|
|
})
|
|
|
|
it('calls project.reset on launch', function () {
|
|
return openProject.launch(this.browser, this.spec)
|
|
.then(() => {
|
|
expect(ProjectBase.prototype.reset).to.be.called
|
|
})
|
|
})
|
|
|
|
it('sets isHeaded + isHeadless if not already defined', function () {
|
|
expect(this.browser.isHeaded).to.be.undefined
|
|
expect(this.browser.isHeadless).to.be.undefined
|
|
|
|
return openProject.launch(this.browser, this.spec)
|
|
.then(() => {
|
|
expect(this.browser.isHeaded).to.be.true
|
|
|
|
expect(this.browser.isHeadless).to.be.false
|
|
})
|
|
})
|
|
|
|
describe('spec events', function () {
|
|
this.beforeEach(function () {
|
|
sinon.stub(runEvents, 'execute').resolves()
|
|
})
|
|
|
|
it('executes after:spec on browser close if in interactive mode', function () {
|
|
this.config.experimentalInteractiveRunEvents = true
|
|
this.config.isTextTerminal = false
|
|
const onBrowserClose = () => Bluebird.resolve()
|
|
|
|
return openProject.launch(this.browser, this.spec, { onBrowserClose })
|
|
.then(() => {
|
|
return browsers.open.lastCall.args[1].onBrowserClose()
|
|
})
|
|
.then(() => {
|
|
expect(runEvents.execute).to.be.calledWith('after:spec', this.spec)
|
|
})
|
|
})
|
|
|
|
it('does not execute after:spec on browser close if not in interactive mode', function () {
|
|
this.config.experimentalInteractiveRunEvents = true
|
|
this.config.isTextTerminal = true
|
|
const onBrowserClose = () => Bluebird.resolve()
|
|
|
|
return openProject.launch(this.browser, this.spec, { onBrowserClose })
|
|
.then(() => {
|
|
return browsers.open.lastCall.args[1].onBrowserClose()
|
|
})
|
|
.then(() => {
|
|
expect(runEvents.execute).not.to.be.calledWith('after:spec')
|
|
})
|
|
})
|
|
|
|
it('does not execute after:spec on browser close if experimental flag is not enabled', function () {
|
|
this.config.experimentalInteractiveRunEvents = false
|
|
this.config.isTextTerminal = false
|
|
const onBrowserClose = () => Bluebird.resolve()
|
|
|
|
return openProject.launch(this.browser, this.spec, { onBrowserClose })
|
|
.then(() => {
|
|
return browsers.open.lastCall.args[1].onBrowserClose()
|
|
})
|
|
.then(() => {
|
|
expect(runEvents.execute).not.to.be.calledWith('after:spec')
|
|
})
|
|
})
|
|
|
|
it('does not execute after:spec on browser close if the project is no longer open', function () {
|
|
this.config.experimentalInteractiveRunEvents = true
|
|
this.config.isTextTerminal = false
|
|
const onBrowserClose = () => Bluebird.resolve()
|
|
|
|
return openProject.launch(this.browser, this.spec, { onBrowserClose })
|
|
.then(() => {
|
|
openProject.__reset()
|
|
|
|
return browsers.open.lastCall.args[1].onBrowserClose()
|
|
})
|
|
.then(() => {
|
|
expect(runEvents.execute).not.to.be.calledWith('after:spec')
|
|
})
|
|
})
|
|
|
|
it('sends after:spec errors through onError option', function () {
|
|
// TODO: fix flaky test https://github.com/cypress-io/cypress/issues/23448
|
|
this.retries(15)
|
|
|
|
const err = new Error('thrown from after:spec handler')
|
|
|
|
this.config.experimentalInteractiveRunEvents = true
|
|
this.config.isTextTerminal = false
|
|
runEvents.execute.withArgs('after:spec').rejects(err)
|
|
|
|
return openProject.launch(this.browser, this.spec, { onError: this.onError })
|
|
.then(() => {
|
|
return browsers.open.lastCall.args[1].onBrowserClose()
|
|
})
|
|
.then(() => {
|
|
return new Bluebird((res) => {
|
|
delay(() => {
|
|
expect(runEvents.execute).to.be.calledWith('after:spec')
|
|
expect(this.onError).to.be.calledWith(err)
|
|
res()
|
|
}, 100)
|
|
})
|
|
})
|
|
})
|
|
|
|
it('calls connectToNewSpec when shouldLaunchNewTab is set and the browser is not electron', async function () {
|
|
await openProject.launch(this.browser, this.spec, { shouldLaunchNewTab: true })
|
|
expect(browsers.connectToNewSpec.lastCall.args[0]).to.be.equal(this.browser)
|
|
})
|
|
|
|
it('calls open when shouldLaunchNewTab is set and the browser is electron', async function () {
|
|
await openProject.launch({ name: 'electron' }, this.spec, { shouldLaunchNewTab: true })
|
|
expect(browsers.open).to.have.been.calledOnce
|
|
})
|
|
})
|
|
})
|
|
|
|
context('#sendFocusBrowserMessage', () => {
|
|
it('focuses browser if runner is connected', async () => {
|
|
// Stubbing out relaunchBrowser function created during launch
|
|
openProject.relaunchBrowser = sinon.stub()
|
|
sinon.stub(ProjectBase.prototype, 'isRunnerSocketConnected').returns(true)
|
|
sinon.stub(ProjectBase.prototype, 'sendFocusBrowserMessage').resolves()
|
|
|
|
await openProject.sendFocusBrowserMessage()
|
|
|
|
expect(ProjectBase.prototype.isRunnerSocketConnected).to.have.been.calledOnce
|
|
expect(ProjectBase.prototype.sendFocusBrowserMessage).to.have.been.calledOnce
|
|
expect(openProject.relaunchBrowser).not.to.have.been.called
|
|
})
|
|
|
|
it('relaunches browser if runner is not connected and relaunch exists', async () => {
|
|
// Stubbing out relaunchBrowser function created during launch
|
|
openProject.relaunchBrowser = sinon.stub()
|
|
sinon.stub(ProjectBase.prototype, 'isRunnerSocketConnected').returns(false)
|
|
sinon.stub(ProjectBase.prototype, 'sendFocusBrowserMessage').resolves()
|
|
|
|
await openProject.sendFocusBrowserMessage()
|
|
|
|
expect(ProjectBase.prototype.isRunnerSocketConnected).to.have.been.calledOnce
|
|
expect(ProjectBase.prototype.sendFocusBrowserMessage).not.to.have.been.called
|
|
expect(openProject.relaunchBrowser).to.have.been.calledOnce
|
|
})
|
|
|
|
it('does not throw if relaunch is not defined', async () => {
|
|
// Stubbing out relaunchBrowser function created during launch
|
|
openProject.relaunchBrowser = null
|
|
sinon.stub(ProjectBase.prototype, 'isRunnerSocketConnected').returns(false)
|
|
sinon.stub(ProjectBase.prototype, 'sendFocusBrowserMessage').resolves()
|
|
|
|
await openProject.sendFocusBrowserMessage()
|
|
|
|
expect(ProjectBase.prototype.isRunnerSocketConnected).to.have.been.calledOnce
|
|
expect(ProjectBase.prototype.sendFocusBrowserMessage).not.to.have.been.called
|
|
})
|
|
})
|
|
|
|
context('#connectProtocolToBrowser', () => {
|
|
it('connects protocol to browser', async () => {
|
|
sinon.stub(browsers, 'connectProtocolToBrowser').resolves()
|
|
const options = sinon.stub()
|
|
|
|
await openProject.connectProtocolToBrowser(options)
|
|
|
|
expect(browsers.connectProtocolToBrowser).to.be.calledWith(options)
|
|
})
|
|
})
|
|
|
|
context('#connectCyPromptToBrowser', () => {
|
|
it('connects cy prompt to browser', async () => {
|
|
sinon.stub(browsers, 'connectCyPromptToBrowser').resolves()
|
|
const options = sinon.stub()
|
|
|
|
await openProject.connectCyPromptToBrowser(options)
|
|
})
|
|
})
|
|
})
|