diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index ea500ae914d3..8d201ca014ab 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -17,7 +17,7 @@ _Released 10/03/2023 (PENDING)_ _Released 09/27/2023_ **Features:** - + - Added ability to specify the default running browser in cypress config. Addresses [#6646](https://github.com/cypress-io/cypress/issues/6646). - Introduces new layout for Runs page providing additional run information. Addresses [#27203](https://github.com/cypress-io/cypress/issues/27203). **Bugfixes:** diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index a40f2fcdf92c..388bed538127 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -3180,6 +3180,11 @@ declare namespace Cypress { setupNodeEvents: (on: PluginEvents, config: PluginConfigOptions) => Promise | PluginConfigOptions | void indexHtmlFile: string + + /** + * Set a default browser other than electron when user doesn't pass in "--browser". + */ + defaultBrowser: string } interface EndToEndConfigOptions extends Omit { @@ -3536,7 +3541,7 @@ declare namespace Cypress { hosts?: null | {[key: string]: string} } - interface PluginConfigOptions extends ResolvedConfigOptions, RuntimeConfigOptions { + interface PluginConfigOptions extends ResolvedConfigOptions, Omit { /** * Absolute path to the root of the project */ diff --git a/packages/data-context/src/DataContext.ts b/packages/data-context/src/DataContext.ts index e59f89233088..ae47e67605af 100644 --- a/packages/data-context/src/DataContext.ts +++ b/packages/data-context/src/DataContext.ts @@ -83,7 +83,7 @@ export interface GraphQLRequestInfo { export class DataContext { readonly graphqlRequestInfo?: GraphQLRequestInfo private _config: Omit - private _modeOptions: Readonly> + private _modeOptions: Partial private _coreData: CoreDataShape readonly lifecycleManager: ProjectLifecycleManager @@ -423,4 +423,8 @@ export class DataContext { this.#awaitingEmptyRequestCount.push(resolve) }) } + + setModeOptionsBrowser (browser: string) { + this._modeOptions.browser = browser + } } diff --git a/packages/data-context/src/data/ProjectLifecycleManager.ts b/packages/data-context/src/data/ProjectLifecycleManager.ts index b41a505d892d..2f5f67a96cfc 100644 --- a/packages/data-context/src/data/ProjectLifecycleManager.ts +++ b/packages/data-context/src/data/ProjectLifecycleManager.ts @@ -299,10 +299,29 @@ export class ProjectLifecycleManager { /** * Sets the initial `activeBrowser` depending on these criteria, in order of preference: * 1. The value of `--browser` passed via CLI. - * 2. The last browser selected in `open` mode (by name and channel) for this project. - * 3. The first browser found. + * 2. The value of `defaultBrowser` in `cypress.config` + * 3. The last browser selected in `open` mode (by name and channel) for this project. + * 4. The first browser found. */ async setInitialActiveBrowser () { + const configBrowser = this.loadedFullConfig?.defaultBrowser + + if (configBrowser && !this.ctx.coreData.isBrowserGivenByCli) { + await this.setActiveBrowserByNameOrPath(configBrowser) + + if (this.ctx.isRunMode) { + this.ctx.setModeOptionsBrowser(configBrowser) + + return + } + + if (this.ctx.coreData.activeBrowser) { + await this.ctx.actions.project.launchProject(this.ctx.coreData.currentTestingType) + } + + return + } + if (this.ctx.coreData.cliBrowser) { await this.setActiveBrowserByNameOrPath(this.ctx.coreData.cliBrowser) diff --git a/packages/data-context/src/data/coreDataShape.ts b/packages/data-context/src/data/coreDataShape.ts index d14d17cfedb6..9069c4c28ac0 100644 --- a/packages/data-context/src/data/coreDataShape.ts +++ b/packages/data-context/src/data/coreDataShape.ts @@ -142,6 +142,7 @@ interface CloudDataShape { export interface CoreDataShape { cliBrowser: string | null + isBrowserGivenByCli: boolean cliTestingType: string | null activeBrowser: FoundBrowser | null machineId: Promise @@ -180,6 +181,7 @@ export function makeCoreData (modeOptions: Partial = {}): CoreDa return { servers: {}, cliBrowser: modeOptions.browser ?? null, + isBrowserGivenByCli: modeOptions.isBrowserGivenByCli ?? false, cliTestingType: modeOptions.testingType ?? null, machineId: machineId(), machineBrowsers: null, diff --git a/packages/server/lib/modes/index.ts b/packages/server/lib/modes/index.ts index c542b7d807b9..99b7085e8e5f 100644 --- a/packages/server/lib/modes/index.ts +++ b/packages/server/lib/modes/index.ts @@ -10,6 +10,8 @@ export = (mode, options) => { return require('./smoke_test').run(options) } + options.isBrowserGivenByCli = options.browser !== undefined + if (mode === 'run') { _.defaults(options, { socketId: random.id(10), diff --git a/packages/types/src/modeOptions.ts b/packages/types/src/modeOptions.ts index f8ab17f81ec2..1b8b09e8afea 100644 --- a/packages/types/src/modeOptions.ts +++ b/packages/types/src/modeOptions.ts @@ -1,6 +1,7 @@ export interface CommonModeOptions { _?: (string | null)[] | null invokedFromCli: boolean + isBrowserGivenByCli: boolean userNodePath?: string userNodeVersion?: string configFile?: string | null diff --git a/system-tests/projects/config-default-browser/cypress.config.js b/system-tests/projects/config-default-browser/cypress.config.js new file mode 100644 index 000000000000..20d060ec1140 --- /dev/null +++ b/system-tests/projects/config-default-browser/cypress.config.js @@ -0,0 +1,8 @@ +const { defineConfig } = require('cypress') + +module.exports = defineConfig({ + e2e: { + supportFile: false, + }, + defaultBrowser: 'chrome', +}) diff --git a/system-tests/projects/config-default-browser/cypress/e2e/spec.cy.js b/system-tests/projects/config-default-browser/cypress/e2e/spec.cy.js new file mode 100644 index 000000000000..434d054dfaa1 --- /dev/null +++ b/system-tests/projects/config-default-browser/cypress/e2e/spec.cy.js @@ -0,0 +1,3 @@ +it('works', () => { + expect(1).to.eq(1) +}) diff --git a/system-tests/test/config_spec.js b/system-tests/test/config_spec.js index b71c4a206a37..c0ba42a8c0e6 100644 --- a/system-tests/test/config_spec.js +++ b/system-tests/test/config_spec.js @@ -243,4 +243,15 @@ describe('e2e config', () => { snapshot: true, }) }) + + it('launches browser using config.defaultBrowser', async function () { + await Fixtures.scaffoldProject('config-default-browser') + + return systemTests.exec(this, { + project: 'config-default-browser', + onStdout: (stdout) => { + expect(stdout).to.include('Browser: Chrome') + }, + }) + }) })