From d4a08f0dfc36db9ac429f476e41e92fbf6491bce Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Tue, 23 Sep 2025 16:30:23 -0400 Subject: [PATCH 01/16] clean up experimental studio config --- guides/studio-development.md | 2 +- packages/app/cypress.config.ts | 1 - .../app/src/runner/SpecRunnerOpenMode.vue | 6 +-- packages/app/src/runner/reporter.ts | 5 +-- packages/config/src/options.ts | 17 +++----- packages/data-context/schemas/schema.graphql | 2 +- packages/driver/cypress.config.ts | 1 - .../EXPERIMENTAL_STUDIO_E2E_ONLY.html | 40 ------------------- packages/errors/src/errors.ts | 11 +++-- .../frontend-shared/src/locales/en-US.json | 4 -- packages/reporter/cypress.config.ts | 1 - packages/server/lib/experiments.ts | 2 - packages/server/lib/project-base.ts | 2 +- 13 files changed, 16 insertions(+), 78 deletions(-) delete mode 100644 packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_E2E_ONLY.html diff --git a/guides/studio-development.md b/guides/studio-development.md index 633af59ed4d..cb8ee5ab772 100644 --- a/guides/studio-development.md +++ b/guides/studio-development.md @@ -17,7 +17,7 @@ To run against locally developed Studio: - Run `yarn cypress:open` - Log In to the Cloud via the App - Ensure the project has been setup in the `Cypress (staging)` if in staging environment or `Cypress Internal Org` if in production environment and has a `projectId` that represents that. If developing against locally running `cypress-services`, ensure that the project has the feature `studio-ai` enabled for it. - - Open a project that has `experimentalStudio: true` set in the `e2e` config of the `cypress.config.js|ts` file. + - Open a project with `e2e` tests. - Click to 'Add Commands to Test' after hovering over a test command. Note: When using the `CYPRESS_LOCAL_STUDIO_PATH` environment variable or when running the Cypress app via the locally cloned repository, we bypass our error reporting and instead log errors to the browser or node console. diff --git a/packages/app/cypress.config.ts b/packages/app/cypress.config.ts index 9b83e85cf45..893d7d8a326 100644 --- a/packages/app/cypress.config.ts +++ b/packages/app/cypress.config.ts @@ -31,7 +31,6 @@ export default defineConfig({ }, 'e2e': { experimentalRunAllSpecs: true, - experimentalStudio: true, experimentalOriginDependencies: true, baseUrl: 'http://localhost:5555', supportFile: 'cypress/e2e/support/e2eSupport.ts', diff --git a/packages/app/src/runner/SpecRunnerOpenMode.vue b/packages/app/src/runner/SpecRunnerOpenMode.vue index 7973e56d0a9..1c7b0e79a85 100644 --- a/packages/app/src/runner/SpecRunnerOpenMode.vue +++ b/packages/app/src/runner/SpecRunnerOpenMode.vue @@ -275,17 +275,13 @@ const studioBetaAvailable = computed(() => { }) const shouldShowStudioButton = computed(() => { - // Find the experimentalStudio config field - const experimentalStudioConfig = props.gql.currentProject?.config?.find((item) => item.field === 'experimentalStudio') - const experimentalStudioEnabled = experimentalStudioConfig?.value === true - // Check if we're running all specs by looking at the route query const isRunningAllSpecs = route.query.file === '__all' // Studio can only be enabled for e2e testing const isE2ETesting = props.gql.currentProject?.currentTestingType === 'e2e' - return !!cloudStudioRequested.value && !studioStore.isOpen && experimentalStudioEnabled && !isRunningAllSpecs && isE2ETesting + return !!cloudStudioRequested.value && !studioStore.isOpen && !isRunningAllSpecs && isE2ETesting }) const shouldShowStudioPanel = computed(() => { diff --git a/packages/app/src/runner/reporter.ts b/packages/app/src/runner/reporter.ts index 495ff90db76..70e7dc5bcd6 100644 --- a/packages/app/src/runner/reporter.ts +++ b/packages/app/src/runner/reporter.ts @@ -1,7 +1,6 @@ import { getMobxRunnerStore, MobxRunnerStore, useSpecStore } from '../store' import { getReporterElement } from './utils' import { getEventManager } from '.' -import { getRunnerConfigFromWindow } from './get-runner-config-from-window' import type { EventManager } from './event-manager' import { useRunnerUiStore } from '../store/runner-ui-store' @@ -43,8 +42,6 @@ function renderReporter ( const runnerUiStore = useRunnerUiStore() const specsStore = useSpecStore() - const config = getRunnerConfigFromWindow() - const reporter = window.UnifiedRunner.React.createElement(window.UnifiedRunner.Reporter, { runMode: 'single' as const, runner: eventManager.reporterBus, @@ -53,7 +50,7 @@ function renderReporter ( error: null, resetStatsOnSpecChange: true, // Studio can only be enabled for e2e testing - studioEnabled: window.__CYPRESS_TESTING_TYPE__ === 'e2e' && config.experimentalStudio, + studioEnabled: window.__CYPRESS_TESTING_TYPE__ === 'e2e', runnerStore: store, testFilter: specsStore.testFilter, }) diff --git a/packages/config/src/options.ts b/packages/config/src/options.ts index 0208b42dd46..e5123b72865 100644 --- a/packages/config/src/options.ts +++ b/packages/config/src/options.ts @@ -18,6 +18,7 @@ const BREAKING_OPTION_ERROR_KEY: Readonly = [ 'EXPERIMENTAL_SINGLE_TAB_RUN_MODE', 'VIDEO_UPLOAD_ON_PASSES_REMOVED', 'RENAMED_CONFIG_OPTION', + 'EXPERIMENTAL_STUDIO_REMOVED', ] as const type ValidationOptions = { @@ -242,12 +243,6 @@ const driverConfigOptions: Array = [ validation: validate.isBoolean, isExperimental: true, requireRestartOnChange: 'server', - }, { - name: 'experimentalStudio', - defaultValue: false, - validation: validate.isBoolean, - isExperimental: true, - requireRestartOnChange: 'server', }, { name: 'experimentalWebKitSupport', defaultValue: false, @@ -622,6 +617,11 @@ export const breakingOptions: Readonly = [ errorKey: 'VIDEO_UPLOAD_ON_PASSES_REMOVED', isWarning: true, }, + { + name: 'experimentalStudio', + errorKey: 'EXPERIMENTAL_STUDIO_REMOVED', + isWarning: true, + }, ] as const export const breakingRootOptions: Array = [ @@ -709,11 +709,6 @@ export const testingTypeBreakingOptions: { e2e: Array, component errorKey: 'CONFIG_FILE_INVALID_TESTING_TYPE_CONFIG_COMPONENT', isWarning: false, }, - { - name: 'experimentalStudio', - errorKey: 'EXPERIMENTAL_STUDIO_E2E_ONLY', - isWarning: false, - }, { name: 'testIsolation', errorKey: 'CONFIG_FILE_INVALID_TESTING_TYPE_CONFIG_COMPONENT', diff --git a/packages/data-context/schemas/schema.graphql b/packages/data-context/schemas/schema.graphql index ecb460e3bd9..7c3c68aa870 100644 --- a/packages/data-context/schemas/schema.graphql +++ b/packages/data-context/schemas/schema.graphql @@ -1186,7 +1186,7 @@ enum ErrorTypeEnum { EXPERIMENTAL_SESSION_AND_ORIGIN_REMOVED EXPERIMENTAL_SINGLE_TAB_RUN_MODE EXPERIMENTAL_SKIP_DOMAIN_INJECTION_REMOVED - EXPERIMENTAL_STUDIO_E2E_ONLY + EXPERIMENTAL_STUDIO_REMOVED EXTENSION_NOT_LOADED FIREFOX_CDP_FAILED_TO_CONNECT FIREFOX_COULD_NOT_CONNECT diff --git a/packages/driver/cypress.config.ts b/packages/driver/cypress.config.ts index 13c8b45dcf8..8cdd42a99aa 100644 --- a/packages/driver/cypress.config.ts +++ b/packages/driver/cypress.config.ts @@ -4,7 +4,6 @@ import { devServer as cypressWebpackDevServer } from '@cypress/webpack-dev-serve export const baseConfig: Cypress.ConfigOptions = { projectId: 'ypt4pf', - experimentalStudio: true, experimentalMemoryManagement: true, experimentalWebKitSupport: true, hosts: { diff --git a/packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_E2E_ONLY.html b/packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_E2E_ONLY.html deleted file mode 100644 index 597643b3e34..00000000000 --- a/packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_E2E_ONLY.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - -
The experimentalStudio experiment is currently only supported for End to End Testing.
-
-If you have feedback about the experiment, please join the discussion here: http://on.cypress.io/studio-beta
-
\ No newline at end of file diff --git a/packages/errors/src/errors.ts b/packages/errors/src/errors.ts index 2f1094c4074..1876e95c3b9 100644 --- a/packages/errors/src/errors.ts +++ b/packages/errors/src/errors.ts @@ -1225,14 +1225,14 @@ export const AllCypressErrors = { If you have feedback about the experiment, please join the discussion here: http://on.cypress.io/single-tab-run-mode` }, - EXPERIMENTAL_STUDIO_E2E_ONLY: () => { + EXPERIMENTAL_STUDIO_REMOVED: () => { return errTemplate`\ - The ${fmt.highlight(`experimentalStudio`)} experiment is currently only supported for End to End Testing. - - If you have feedback about the experiment, please join the discussion here: http://on.cypress.io/studio-beta` + The ${fmt.highlight(`experimentalStudio`)} was removed in ${fmt.cypressVersion(`13.0.0`)}. + + You can safely remove this option from your config.` }, EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY: () => { - const code = errPartial` + const code = errPartial` { e2e: { experimentalRunAllSpecs: true @@ -1553,7 +1553,6 @@ export const AllCypressErrors = { }, } as const -// eslint-disable-next-line @typescript-eslint/no-unused-vars const _typeCheck: Record ErrTemplateResult> = AllCypressErrors export type AllCypressErrorObj = typeof AllCypressErrors diff --git a/packages/frontend-shared/src/locales/en-US.json b/packages/frontend-shared/src/locales/en-US.json index 526f7b18184..6af897e4a3a 100644 --- a/packages/frontend-shared/src/locales/en-US.json +++ b/packages/frontend-shared/src/locales/en-US.json @@ -609,10 +609,6 @@ "name": "Source rewriting", "description": "Enables AST-based JS/HTML rewriting. This may fix issues caused by the existing regex-based JS/HTML replacement algorithm. See [#5273](https://github.com/cypress-io/cypress/issues/5273) for details." }, - "experimentalStudio": { - "name": "Studio", - "description": "Generate and save commands directly to your test suite by interacting with your app as an end user would." - }, "experimentalWebKitSupport": { "name": "WebKit Support", "description": "Adds support for testing in the WebKit browser engine used by Safari. See https://on.cypress.io/webkit-experiment for more information." diff --git a/packages/reporter/cypress.config.ts b/packages/reporter/cypress.config.ts index 1f983e2649f..d279221fa86 100644 --- a/packages/reporter/cypress.config.ts +++ b/packages/reporter/cypress.config.ts @@ -16,7 +16,6 @@ export default defineConfig({ }, e2e: { - experimentalStudio: true, baseUrl: 'http://localhost:5006', setupNodeEvents (on, config) { const express = require('express') diff --git a/packages/server/lib/experiments.ts b/packages/server/lib/experiments.ts index b043ec1ef06..fd94008c45b 100644 --- a/packages/server/lib/experiments.ts +++ b/packages/server/lib/experiments.ts @@ -55,7 +55,6 @@ const _summaries: StringValues = { experimentalModifyObstructiveThirdPartyCode: 'Applies `modifyObstructiveCode` to third party `.html` and `.js`, removes subresource integrity, and modifies the user agent in Electron.', experimentalSourceRewriting: 'Enables AST-based JS/HTML rewriting. This may fix issues caused by the existing regex-based JS/HTML replacement algorithm.', experimentalSingleTabRunMode: 'Runs all component specs in a single tab, trading spec isolation for faster run mode execution.', - experimentalStudio: 'Generate and save commands directly to your test suite by interacting with your app as an end user would.', experimentalWebKitSupport: 'Adds support for testing in the WebKit browser engine used by Safari. See https://on.cypress.io/webkit-experiment for more information.', experimentalRunAllSpecs: 'Enables the "Run All Specs" UI feature, allowing the execution of multiple specs sequentially', experimentalOriginDependencies: 'Enables support for `Cypress.require()` for including dependencies within the `cy.origin()` callback.', @@ -77,7 +76,6 @@ const _names: StringValues = { experimentalModifyObstructiveThirdPartyCode: 'Modify Obstructive Third Party Code', experimentalSingleTabRunMode: 'Single Tab Run Mode', experimentalSourceRewriting: 'Improved Source Rewriting', - experimentalStudio: 'Studio', experimentalWebKitSupport: 'WebKit Support', experimentalRunAllSpecs: 'Run All Specs', experimentalOriginDependencies: 'Origin Dependencies', diff --git a/packages/server/lib/project-base.ts b/packages/server/lib/project-base.ts index 9bf67392579..3cc95aa6e85 100644 --- a/packages/server/lib/project-base.ts +++ b/packages/server/lib/project-base.ts @@ -158,7 +158,7 @@ export class ProjectBase extends EE { this._server = new ServerBase(cfg) - if (!cfg.isTextTerminal && cfg.resolved.experimentalStudio?.value) { + if (!cfg.isTextTerminal) { const studioLifecycleManager = new StudioLifecycleManager() studioLifecycleManager.initializeStudioManager({ From 0c365e69decc0b5e28f6fa7d25c099825d30f422 Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Tue, 23 Sep 2025 17:11:45 -0400 Subject: [PATCH 02/16] clean up studio test --- packages/app/cypress/e2e/studio/studio.cy.ts | 26 +------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/packages/app/cypress/e2e/studio/studio.cy.ts b/packages/app/cypress/e2e/studio/studio.cy.ts index 6b2a1ef227e..c3fc1f0989e 100644 --- a/packages/app/cypress/e2e/studio/studio.cy.ts +++ b/packages/app/cypress/e2e/studio/studio.cy.ts @@ -29,18 +29,6 @@ describe('Cypress Studio', () => { }) } - it('does not show the studio button if experimentalStudio is not enabled', () => { - loadProjectAndRunSpec({ cliArgs: ['--config', 'experimentalStudio=false'] }) - - cy.findByTestId('studio-button').should('not.exist') - }) - - it('shows the studio button if experimentalStudio is enabled', () => { - loadProjectAndRunSpec({ cliArgs: ['--config', 'experimentalStudio=true'] }) - - cy.findByTestId('studio-button').should('be.visible') - }) - it('does not display the launch studio button when test is pending', () => { loadProjectAndRunSpec({ specName: 'skipped.cy.js' }) @@ -1039,7 +1027,7 @@ it('new-test', function() { cy.percySnapshot() }) - it('hides selector playground and studio controls when experimentalStudio is enabled', () => { + it('hides selector playground and studio controls', () => { launchStudio() cy.findByTestId('studio-panel').should('be.visible') @@ -1232,18 +1220,6 @@ describe('studio functionality', () => { cy.scaffoldProject('run-all-specs') cy.openProject('run-all-specs') - // Enable experimental studio by modifying the config - cy.withCtx(async (ctx) => { - const configPath = 'cypress.config.js' - const configContent = await ctx.actions.file.readFileInProject(configPath) - const updatedConfig = configContent.replace( - 'experimentalRunAllSpecs: true,', - 'experimentalRunAllSpecs: true,\n experimentalStudio: true,', - ) - - await ctx.actions.file.writeFileInProject(configPath, updatedConfig) - }) - cy.startAppServer('e2e') cy.visitApp() cy.specsPageIsVisible() From 203a8e02cfca0f50e97c860595871e754530c54d Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Wed, 24 Sep 2025 13:47:39 -0400 Subject: [PATCH 03/16] clean tests and add a test for new warning --- packages/config/test/project/utils.spec.ts | 261 +++++++++--------- .../cypress/e2e/config-warning.cy.ts | 34 --- packages/server/test/unit/project_spec.js | 27 -- 3 files changed, 127 insertions(+), 195 deletions(-) diff --git a/packages/config/test/project/utils.spec.ts b/packages/config/test/project/utils.spec.ts index a64df10902c..d19e8ed49d1 100644 --- a/packages/config/test/project/utils.spec.ts +++ b/packages/config/test/project/utils.spec.ts @@ -994,6 +994,16 @@ describe('config/src/project/utils', () => { }) }) + it('warns if experimentalStudio is passed', async function () { + const warning = sinon.spy(errors, 'warning') + + await this.defaults('experimentalStudio', true, { + experimentalStudio: true, + }) + + expect(warning).to.be.calledWith('EXPERIMENTAL_STUDIO_REMOVED') + }) + describe('.resolved', () => { it('sets reporter and port to cli', async () => { const obj = { @@ -1008,72 +1018,72 @@ describe('config/src/project/utils', () => { const getFilesByGlob = vi.fn().mockReturnValue(['path/to/file']) - const cfg = await mergeDefaults(obj, options, {}, getFilesByGlob) - - expect(cfg.resolved).toEqual({ - 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' }, - 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' }, + 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' }, + 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' }, + }) }) }) @@ -1121,75 +1131,58 @@ describe('config/src/project/utils', () => { value: 'foo', from: 'config', }, - bar: { - value: 'bar', - from: 'envFile', - }, - baz: { - value: 'baz', - from: 'cli', - }, - quux: { - value: 'quux', - from: 'env', - }, - RECORD_KEY: { - value: 'fooba...zquux', - from: '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' }, + 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' }, }, - 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' }, - 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' }, }) }) diff --git a/packages/launchpad/cypress/e2e/config-warning.cy.ts b/packages/launchpad/cypress/e2e/config-warning.cy.ts index 759d66c1a6f..c395f4cd0c3 100644 --- a/packages/launchpad/cypress/e2e/config-warning.cy.ts +++ b/packages/launchpad/cypress/e2e/config-warning.cy.ts @@ -90,40 +90,6 @@ describe('experimentalSingleTabRunMode', () => { }) }) -describe('experimentalStudio', () => { - it('is not a valid config for component testing', () => { - cy.scaffoldProject('experimentalSingleTabRunMode') - cy.openProject('experimentalSingleTabRunMode', ['--config-file', 'cypress-invalid-studio-experiment.config.js']) - - cy.visitLaunchpad() - cy.get('[data-cy-testingtype="component"]').click() - cy.findByTestId('error-header') - cy.contains('The experimentalStudio experiment is currently only supported for End to End Testing.') - }) - - it('is a valid config for e2e testing', { defaultCommandTimeout: THIRTY_SECONDS }, () => { - cy.scaffoldProject('e2e') - cy.openProject('e2e') - cy.withCtx(async (ctx) => { - await ctx.actions.file.writeFileInProject('cypress.config.js', ` - const { defineConfig } = require('cypress') - - module.exports = defineConfig({ - experimentalStudio: true, - e2e: { - experimentalStudio: true - }, - }) - `) - }) - - cy.visitLaunchpad() - cy.get('[data-cy-testingtype="e2e"]').click() - cy.findByTestId('launchpad-Choose a browser') - cy.get('h1').contains('Choose a browser') - }) -}) - describe('experimentalRunAllSpecs', () => { it('is a valid config for e2e testing', { defaultCommandTimeout: THIRTY_SECONDS }, () => { cy.scaffoldProject('run-all-specs') diff --git a/packages/server/test/unit/project_spec.js b/packages/server/test/unit/project_spec.js index 6cc3b71f545..1797a454ef4 100644 --- a/packages/server/test/unit/project_spec.js +++ b/packages/server/test/unit/project_spec.js @@ -574,36 +574,9 @@ This option will not have an effect in Some-other-name. Tests that rely on web s }) describe('studio initialization', function () { - it('does not create studio lifecycle manager when experimental flag is disabled', async function () { - const cfg = { - isTextTerminal: false, - resolved: { - experimentalStudio: { - value: false, - }, - }, - projectId: 'test-project', - port: 8080, - } - - sinon.stub(this.project, 'initializeConfig').resolves(cfg) - sinon.stub(this.project, 'saveState').resolves() - - sinon.stub(process, 'chdir') - - await this.project.open() - - expect(this.project.ctx.coreData.studioLifecycleManager).to.be.undefined - }) - it('does not create studio lifecycle manager when in text terminal mode', async function () { const cfg = { isTextTerminal: true, - resolved: { - experimentalStudio: { - value: true, - }, - }, projectId: 'test-project', port: 8080, } From 10538f40b47b50737a4afeb3540699830eb7420c Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Thu, 25 Sep 2025 09:07:26 -0400 Subject: [PATCH 04/16] add snapshot tests --- .../EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html | 8 ++-- .../EXPERIMENTAL_STUDIO_REMOVED.html | 40 +++++++++++++++++++ packages/errors/src/errors.ts | 2 +- .../test/unit/visualSnapshotErrors_spec.ts | 2 +- 4 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_REMOVED.html diff --git a/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html b/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html index c1d7c4806c8..8740f5c92d7 100644 --- a/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html +++ b/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html @@ -37,10 +37,10 @@
The experimentalRunAllSpecs experiment is currently only supported for End to End Testing and must be configured as an e2e testing type property: e2e.experimentalRunAllSpecs.
 
 {
-  e2e: {
-    experimentalRunAllSpecs: true
-  },
-}
+    e2e: {
+      experimentalRunAllSpecs: true
+    },
+  }
 
 If you have feedback about the experiment, please join the discussion here: http://on.cypress.io/run-all-specs
 
\ No newline at end of file diff --git a/packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_REMOVED.html b/packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_REMOVED.html new file mode 100644 index 00000000000..f0ae9844645 --- /dev/null +++ b/packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_REMOVED.html @@ -0,0 +1,40 @@ + + + + + + + + + + + +
The experimentalStudio was removed in Cypress version 15.4.0.
+
+You can safely remove this option from your config.
+
\ No newline at end of file diff --git a/packages/errors/src/errors.ts b/packages/errors/src/errors.ts index 1876e95c3b9..f772263c86d 100644 --- a/packages/errors/src/errors.ts +++ b/packages/errors/src/errors.ts @@ -1227,7 +1227,7 @@ export const AllCypressErrors = { }, EXPERIMENTAL_STUDIO_REMOVED: () => { return errTemplate`\ - The ${fmt.highlight(`experimentalStudio`)} was removed in ${fmt.cypressVersion(`13.0.0`)}. + The ${fmt.highlight(`experimentalStudio`)} was removed in ${fmt.cypressVersion(`15.4.0`)}. You can safely remove this option from your config.` }, diff --git a/packages/errors/test/unit/visualSnapshotErrors_spec.ts b/packages/errors/test/unit/visualSnapshotErrors_spec.ts index 18564983391..d673208122d 100644 --- a/packages/errors/test/unit/visualSnapshotErrors_spec.ts +++ b/packages/errors/test/unit/visualSnapshotErrors_spec.ts @@ -1241,7 +1241,7 @@ describe('visual error templates', () => { } }, - EXPERIMENTAL_STUDIO_E2E_ONLY: () => { + EXPERIMENTAL_STUDIO_REMOVED: () => { return { default: [], } From f1d82b18b7a24cbd65ce31e1ee2a044d4dc7e337 Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Thu, 25 Sep 2025 09:11:07 -0400 Subject: [PATCH 05/16] revert unneeded changes --- .../EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html | 8 ++++---- packages/errors/src/errors.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html b/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html index 8740f5c92d7..a221d5ea7a5 100644 --- a/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html +++ b/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html @@ -37,10 +37,10 @@
The experimentalRunAllSpecs experiment is currently only supported for End to End Testing and must be configured as an e2e testing type property: e2e.experimentalRunAllSpecs.
 
 {
-    e2e: {
-      experimentalRunAllSpecs: true
-    },
-  }
+     e2e: {
+       experimentalRunAllSpecs: true
+     },
+   }
 
 If you have feedback about the experiment, please join the discussion here: http://on.cypress.io/run-all-specs
 
\ No newline at end of file diff --git a/packages/errors/src/errors.ts b/packages/errors/src/errors.ts index f772263c86d..0c079c395b2 100644 --- a/packages/errors/src/errors.ts +++ b/packages/errors/src/errors.ts @@ -1232,7 +1232,7 @@ export const AllCypressErrors = { You can safely remove this option from your config.` }, EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY: () => { - const code = errPartial` + const code = errPartial` { e2e: { experimentalRunAllSpecs: true From bbcc0904eba490976ef86a67444bd59e7b149205 Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Thu, 25 Sep 2025 09:12:09 -0400 Subject: [PATCH 06/16] revert unneeded changes --- .../EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html | 8 ++++---- packages/errors/src/errors.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html b/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html index a221d5ea7a5..c1d7c4806c8 100644 --- a/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html +++ b/packages/errors/__snapshot-html__/EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY.html @@ -37,10 +37,10 @@
The experimentalRunAllSpecs experiment is currently only supported for End to End Testing and must be configured as an e2e testing type property: e2e.experimentalRunAllSpecs.
 
 {
-     e2e: {
-       experimentalRunAllSpecs: true
-     },
-   }
+  e2e: {
+    experimentalRunAllSpecs: true
+  },
+}
 
 If you have feedback about the experiment, please join the discussion here: http://on.cypress.io/run-all-specs
 
\ No newline at end of file diff --git a/packages/errors/src/errors.ts b/packages/errors/src/errors.ts index 0c079c395b2..12ad24ab660 100644 --- a/packages/errors/src/errors.ts +++ b/packages/errors/src/errors.ts @@ -1232,7 +1232,7 @@ export const AllCypressErrors = { You can safely remove this option from your config.` }, EXPERIMENTAL_RUN_ALL_SPECS_E2E_ONLY: () => { - const code = errPartial` + const code = errPartial` { e2e: { experimentalRunAllSpecs: true From 02a7e38592d3962ffb7110621ef0d7c142845aec Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Thu, 25 Sep 2025 12:10:55 -0400 Subject: [PATCH 07/16] only initialize studio lifecycle manager when testing type is e2e --- packages/server/lib/project-base.ts | 2 +- packages/server/test/unit/project_spec.js | 28 ++++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/server/lib/project-base.ts b/packages/server/lib/project-base.ts index 3cc95aa6e85..69e3fbf3500 100644 --- a/packages/server/lib/project-base.ts +++ b/packages/server/lib/project-base.ts @@ -158,7 +158,7 @@ export class ProjectBase extends EE { this._server = new ServerBase(cfg) - if (!cfg.isTextTerminal) { + if (!cfg.isTextTerminal && this.testingType === 'e2e') { const studioLifecycleManager = new StudioLifecycleManager() studioLifecycleManager.initializeStudioManager({ diff --git a/packages/server/test/unit/project_spec.js b/packages/server/test/unit/project_spec.js index 1797a454ef4..3b58f666e69 100644 --- a/packages/server/test/unit/project_spec.js +++ b/packages/server/test/unit/project_spec.js @@ -575,13 +575,19 @@ This option will not have an effect in Some-other-name. Tests that rely on web s describe('studio initialization', function () { it('does not create studio lifecycle manager when in text terminal mode', async function () { - const cfg = { - isTextTerminal: true, - projectId: 'test-project', - port: 8080, - } + this.project.cfg.isTextTerminal = true + sinon.stub(this.project, 'saveState').resolves() + + sinon.stub(process, 'chdir') + + await this.project.open() + + expect(this.project.ctx.coreData.studioLifecycleManager).to.be.undefined + }) + + it('does not create studio lifecycle manager for component testing', async function () { + this.project.testingType = 'component' - sinon.stub(this.project, 'initializeConfig').resolves(cfg) sinon.stub(this.project, 'saveState').resolves() sinon.stub(process, 'chdir') @@ -590,6 +596,16 @@ This option will not have an effect in Some-other-name. Tests that rely on web s expect(this.project.ctx.coreData.studioLifecycleManager).to.be.undefined }) + + it('creates studio lifecycle manager for e2e testing', async function () { + sinon.stub(this.project, 'saveState').resolves() + + sinon.stub(process, 'chdir') + + await this.project.open() + + expect(this.project.ctx.coreData.studioLifecycleManager).to.not.be.undefined + }) }) }) From 4a4e277b82d48d6aa1645a4fa632e9dd8b69d19b Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Thu, 25 Sep 2025 12:17:25 -0400 Subject: [PATCH 08/16] update changelog --- cli/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index caf49bf8be4..eb91ccf35e2 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -1,4 +1,10 @@ +## 15.4.0 +_Released 9/30/2025 (PENDING)_ + +**Features:** +- Remove `experimentalStudio` config flag and turn Studio Beta on for all users of Cypress. Addresses [#30997](https://github.com/cypress-io/cypress/issues/30997). Addressed in [#32571](https://github.com/cypress-io/cypress/pull/32571). + ## 15.3.1 _Released 10/07/2025 (PENDING)_ From 3e699ef4c0da6bb413f289eed8516846281d341e Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Thu, 25 Sep 2025 12:22:42 -0400 Subject: [PATCH 09/16] fix changelog --- cli/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index eb91ccf35e2..f9161bbdf1b 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -1,5 +1,6 @@ ## 15.4.0 + _Released 9/30/2025 (PENDING)_ **Features:** From 35f1c7f083e09cda57cf558850e61e60bff02779 Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Thu, 25 Sep 2025 12:23:33 -0400 Subject: [PATCH 10/16] add missing line break --- cli/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index f9161bbdf1b..43cdd88d3a1 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -4,6 +4,7 @@ _Released 9/30/2025 (PENDING)_ **Features:** + - Remove `experimentalStudio` config flag and turn Studio Beta on for all users of Cypress. Addresses [#30997](https://github.com/cypress-io/cypress/issues/30997). Addressed in [#32571](https://github.com/cypress-io/cypress/pull/32571). ## 15.3.1 From 1b8fd34217c98488ed359e683641d50678ba7e47 Mon Sep 17 00:00:00 2001 From: Mabel Amaya Date: Fri, 26 Sep 2025 11:35:39 -0400 Subject: [PATCH 11/16] fix tests --- .../test/__snapshots__/index.spec.ts.snap | 4 +- packages/config/test/project/utils.spec.ts | 261 ++++++++++-------- 2 files changed, 141 insertions(+), 124 deletions(-) diff --git a/packages/config/test/__snapshots__/index.spec.ts.snap b/packages/config/test/__snapshots__/index.spec.ts.snap index 47b32a39d91..b88d7f5eebc 100644 --- a/packages/config/test/__snapshots__/index.spec.ts.snap +++ b/packages/config/test/__snapshots__/index.spec.ts.snap @@ -6,6 +6,7 @@ exports[`config/src/index > .getBreakingKeys > returns list of breaking config k "experimentalSessionAndOrigin", "experimentalSkipDomainInjection", "videoUploadOnPasses", + "experimentalStudio", ] `; @@ -44,7 +45,6 @@ exports[`config/src/index > .getDefaultValues > returns list of public config ke "experimentalRunAllSpecs": false, "experimentalSingleTabRunMode": false, "experimentalSourceRewriting": false, - "experimentalStudio": false, "experimentalWebKitSupport": false, "fileServerFolder": "", "fixturesFolder": "cypress/fixtures", @@ -139,7 +139,6 @@ exports[`config/src/index > .getDefaultValues > returns list of public config ke "experimentalRunAllSpecs": false, "experimentalSingleTabRunMode": false, "experimentalSourceRewriting": false, - "experimentalStudio": false, "experimentalWebKitSupport": false, "fileServerFolder": "", "fixturesFolder": "cypress/fixtures", @@ -223,7 +222,6 @@ exports[`config/src/index > .getPublicConfigKeys > returns list of public config "experimentalOriginDependencies", "experimentalSourceRewriting", "experimentalSingleTabRunMode", - "experimentalStudio", "experimentalWebKitSupport", "fileServerFolder", "fixturesFolder", diff --git a/packages/config/test/project/utils.spec.ts b/packages/config/test/project/utils.spec.ts index d19e8ed49d1..fd48ee95260 100644 --- a/packages/config/test/project/utils.spec.ts +++ b/packages/config/test/project/utils.spec.ts @@ -995,13 +995,17 @@ describe('config/src/project/utils', () => { }) it('warns if experimentalStudio is passed', async function () { - const warning = sinon.spy(errors, 'warning') - - await this.defaults('experimentalStudio', true, { + await defaults('experimentalStudio', true, { experimentalStudio: true, }) - expect(warning).to.be.calledWith('EXPERIMENTAL_STUDIO_REMOVED') + expect(errors.warning).toBeCalledWith('EXPERIMENTAL_STUDIO_REMOVED', { + configFile: 'cypress.config.js', + name: 'experimentalStudio', + newName: undefined, + testingType: undefined, + value: undefined, + }) }) describe('.resolved', () => { @@ -1018,72 +1022,71 @@ describe('config/src/project/utils', () => { const getFilesByGlob = vi.fn().mockReturnValue(['path/to/file']) - 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' }, - 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({ + 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' }, + 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' }, }) }) @@ -1131,58 +1134,74 @@ describe('config/src/project/utils', () => { value: 'foo', from: 'config', }, - 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' }, - 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', + }, + baz: { + value: 'baz', + from: 'cli', + }, + quux: { + value: 'quux', + from: 'env', + }, + RECORD_KEY: { + value: 'fooba...zquux', + from: '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' }, + 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' }, }) }) From e9b1abaf5cebad595bb078c946f5c7ed5aa0e3f7 Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Fri, 26 Sep 2025 13:18:50 -0400 Subject: [PATCH 12/16] remove duplicate pending changelog entries --- cli/CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 43cdd88d3a1..4fee6f07cd9 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -7,10 +7,6 @@ _Released 9/30/2025 (PENDING)_ - Remove `experimentalStudio` config flag and turn Studio Beta on for all users of Cypress. Addresses [#30997](https://github.com/cypress-io/cypress/issues/30997). Addressed in [#32571](https://github.com/cypress-io/cypress/pull/32571). -## 15.3.1 - -_Released 10/07/2025 (PENDING)_ - **Bugfixes:** - Fixed a regression introduced in [`15.0.0`](https://docs.cypress.io/guides/references/changelog#15-0-0) where `dbus` connection error messages appear in docker containers when launching Cypress. Fixes [#32290](https://github.com/cypress-io/cypress/issues/32290). From 8f1c019cbd8d085cf31c066f5c80229add196bb3 Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Thu, 2 Oct 2025 13:17:46 -0400 Subject: [PATCH 13/16] Update packages/errors/src/errors.ts --- packages/errors/src/errors.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/errors/src/errors.ts b/packages/errors/src/errors.ts index 12ad24ab660..3b807a3b9fe 100644 --- a/packages/errors/src/errors.ts +++ b/packages/errors/src/errors.ts @@ -1227,7 +1227,9 @@ export const AllCypressErrors = { }, EXPERIMENTAL_STUDIO_REMOVED: () => { return errTemplate`\ - The ${fmt.highlight(`experimentalStudio`)} was removed in ${fmt.cypressVersion(`15.4.0`)}. + The ${fmt.highlight(`experimentalStudio`)} option was removed in ${fmt.cypressVersion(`15.4.0`)}. + + Cypress Studio is now available for all users. You can safely remove this option from your config.` }, From a019be2b299408ac2a316d3f5683182febdedfc9 Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Thu, 2 Oct 2025 13:27:49 -0400 Subject: [PATCH 14/16] Replace HTML error snapshot with ansi snapshot --- .../EXPERIMENTAL_STUDIO_REMOVED.html | 40 ------------------- .../EXPERIMENTAL_STUDIO_REMOVED.ansi | 5 +++ 2 files changed, 5 insertions(+), 40 deletions(-) delete mode 100644 packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_REMOVED.html create mode 100644 packages/errors/test/__snapshots__/EXPERIMENTAL_STUDIO_REMOVED.ansi diff --git a/packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_REMOVED.html b/packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_REMOVED.html deleted file mode 100644 index f0ae9844645..00000000000 --- a/packages/errors/__snapshot-html__/EXPERIMENTAL_STUDIO_REMOVED.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - -
The experimentalStudio was removed in Cypress version 15.4.0.
-
-You can safely remove this option from your config.
-
\ No newline at end of file diff --git a/packages/errors/test/__snapshots__/EXPERIMENTAL_STUDIO_REMOVED.ansi b/packages/errors/test/__snapshots__/EXPERIMENTAL_STUDIO_REMOVED.ansi new file mode 100644 index 00000000000..e02e6acb631 --- /dev/null +++ b/packages/errors/test/__snapshots__/EXPERIMENTAL_STUDIO_REMOVED.ansi @@ -0,0 +1,5 @@ +The experimentalStudio option was removed in Cypress version 15.4.0. + +Cypress Studio is now available for all users. + +You can safely remove this option from your config. \ No newline at end of file From 073008a91042ae72d6e37f1c10bf619dcfab418c Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Thu, 2 Oct 2025 13:30:20 -0400 Subject: [PATCH 15/16] fix changelog --- cli/CHANGELOG.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 567b535ed7c..cf7fd969df6 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -1,14 +1,11 @@ ## 15.4.0 -_Released 9/30/2025 (PENDING)_ - -**Features:** - -- Remove `experimentalStudio` config flag and turn Studio Beta on for all users of Cypress. Addresses [#30997](https://github.com/cypress-io/cypress/issues/30997). Addressed in [#32571](https://github.com/cypress-io/cypress/pull/32571). +_Released 10/7/2025 (PENDING)_ **Features:** +- Cypress Studio is now available by default. You no longer have to set the `experimentalStudio` flag. Addresses [#30997](https://github.com/cypress-io/cypress/issues/30997). Addressed in [#32571](https://github.com/cypress-io/cypress/pull/32571). - Added the `--posix-exit-codes` flag for the `run` command. When this flag is passed, Cypress will exit with 1 if any tests fail, rather than the number of failed tests. Addresses [#32605](https://github.com/cypress-io/cypress/issues/32605) and [#24695](https://github.com/cypress-io/cypress/issues/24695). Addressed in [#32609](https://github.com/cypress-io/cypress/pull/32609). **Bugfixes:** From a9fe4fa921b6a2ae2b59669e91a56c57e793e7a6 Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Thu, 2 Oct 2025 14:43:21 -0400 Subject: [PATCH 16/16] update system tests results snapshot --- system-tests/__snapshots__/results_spec.ts.js | 1 - 1 file changed, 1 deletion(-) diff --git a/system-tests/__snapshots__/results_spec.ts.js b/system-tests/__snapshots__/results_spec.ts.js index ba61829ae39..5cadb50b069 100644 --- a/system-tests/__snapshots__/results_spec.ts.js +++ b/system-tests/__snapshots__/results_spec.ts.js @@ -30,7 +30,6 @@ exports['module api and after:run results'] = ` "experimentalOriginDependencies": false, "experimentalSourceRewriting": false, "experimentalSingleTabRunMode": false, - "experimentalStudio": false, "experimentalWebKitSupport": false, "fileServerFolder": "/path/to/fileServerFolder", "fixturesFolder": "/path/to/fixturesFolder",