Skip to content

breaking: remove CDP from firefox with Cypress 15 #31200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 0 additions & 31 deletions .circleci/workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -656,11 +656,6 @@ commands:
description: run subset of tests with injectDocumentDomain config enabled
type: boolean
default: false
is-firefox-cdp:
description: whether or not the group should be associated to the firefox CDP
run or not. This is determined by the browser version.
type: boolean
default: false

steps:
- restore_cached_workspace
Expand Down Expand Up @@ -701,9 +696,6 @@ commands:
if << parameters.inject-document-domain >> ; then
YARN_CMD="cypress:run:inject-document-domain"
PARALLEL="--parallel --group 5x-driver-inject-document-domain-<<parameters.browser>>"
elif << parameters.is-firefox-cdp >> ; then
YARN_CMD="cypress:run"
PARALLEL="--parallel --group 5x-driver-cdp-<<parameters.browser>>"
else
YARN_CMD="cypress:run"
PARALLEL="--parallel --group 5x-driver-<<parameters.browser>>"
Expand Down Expand Up @@ -2136,18 +2128,6 @@ jobs:
- run-driver-integration-tests:
browser: firefox

# Runs the driver tests using firefox 134, which does NOT use WebDriver BiDi
# This is to test and make sure there aren't regressions with the old CDP driver
driver-integration-tests-firefox-cdp:
<<: *defaults
resource_class: medium+
parallelism: 5
steps:
- run-driver-integration-tests:
browser: firefox
firefox-version: "134.0.2"
is-firefox-cdp: true

driver-integration-tests-electron:
<<: *defaults
parallelism: 5
Expand Down Expand Up @@ -2888,7 +2868,6 @@ linux-x64-workflow: &linux-x64-workflow
- run-webpack-dev-server-integration-tests
- run-vite-dev-server-integration-tests
- driver-integration-tests-firefox
- driver-integration-tests-firefox-cdp
- driver-integration-tests-chrome
- driver-integration-tests-chrome-inject-document-domain
- driver-integration-tests-chrome-beta-inject-document-domain
Expand Down Expand Up @@ -2964,10 +2943,6 @@ linux-x64-workflow: &linux-x64-workflow
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-firefox-cdp:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-electron:
context: test-runner:cypress-record-key
requires:
Expand Down Expand Up @@ -3110,7 +3085,6 @@ linux-x64-workflow: &linux-x64-workflow
- linux-lint
- percy-finalize
- driver-integration-tests-firefox
- driver-integration-tests-firefox-cdp
- driver-integration-tests-chrome
- driver-integration-tests-chrome-beta
- driver-integration-tests-chrome-inject-document-domain
Expand Down Expand Up @@ -3366,10 +3340,6 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
context: test-runner:cypress-record-key
requires:
- contributor-pr
- driver-integration-tests-firefox-cdp:
context: test-runner:cypress-record-key
requires:
- contributor-pr
- driver-integration-tests-electron:
context: test-runner:cypress-record-key
requires:
Expand Down Expand Up @@ -3511,7 +3481,6 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
- linux-lint
- percy-finalize
- driver-integration-tests-firefox
- driver-integration-tests-firefox-cdp
- driver-integration-tests-chrome
- driver-integration-tests-chrome-beta
- driver-integration-tests-electron
Expand Down
3 changes: 2 additions & 1 deletion cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<!-- See the ../guides/writing-the-cypress-changelog.md for details on writing the changelog. -->
## 15.0.0

_Released 7/1/2025 (PENDING)_
_Released 07/01/2025 (PENDING)_

**Breaking Changes:**

- Removed support for Node.js 18 and Node.js 23. Addresses [#31302](https://github.com/cypress-io/cypress/issues/31302).
- Removed support for [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol) with the [firefox](https://www.mozilla.org/) browser. Addresses [#31189](https://github.com/cypress-io/cypress/issues/31189).

## 14.2.2

Expand Down
3 changes: 0 additions & 3 deletions packages/errors/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1193,9 +1193,6 @@ export const AllCypressErrors = {
CDP_RETRYING_CONNECTION: (attempt: string | number, browserName: string, connectRetryThreshold: number) => {
return errTemplate`Still waiting to connect to ${fmt.off(_.capitalize(browserName))}, retrying in 1 second ${fmt.meta(`(attempt ${attempt}/${connectRetryThreshold})`)}`
},
CDP_FIREFOX_DEPRECATED: () => {
return errTemplate`Since Firefox 129, Chrome DevTools Protocol (CDP) has been deprecated in Firefox. In Firefox 135 and above, Cypress defaults to automating the Firefox browser with WebDriver BiDi. Cypress will no longer support CDP within Firefox in the future and is planned for removal in Cypress 15.`
},
BROWSER_PROCESS_CLOSED_UNEXPECTEDLY: (browserName: string) => {
return errTemplate`\
We detected that the ${fmt.highlight(browserName)} browser process closed unexpectedly.
Expand Down
5 changes: 0 additions & 5 deletions packages/errors/test/unit/visualSnapshotErrors_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1112,11 +1112,6 @@ describe('visual error templates', () => {
default: [1, 'chrome', 62],
}
},
CDP_FIREFOX_DEPRECATED: () => {
return {
default: [],
}
},
BROWSER_PROCESS_CLOSED_UNEXPECTEDLY: () => {
return {
default: ['chrome'],
Expand Down
48 changes: 0 additions & 48 deletions packages/extension/app/v2/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,6 @@ const checkIfFirefox = async () => {
return name === 'Firefox'
}

// this check only applies to firefox versioning!
const isBiDiEnabled = async (config) => {
if (!browser || !get(browser, 'runtime.getBrowserInfo') || config.IS_CDP_FORCED_FOR_FIREFOX) {
return false
}

const { version } = await browser.runtime.getBrowserInfo()

if (version) {
const [majorVersion] = version.split('.').map(Number)

return majorVersion >= 135
}

return false
}

const connect = function (host, path, extraOpts) {
const listenToCookieChanges = once(() => {
return browser.cookies.onChanged.addListener((info) => {
Expand Down Expand Up @@ -84,30 +67,6 @@ const connect = function (host, path, extraOpts) {
})
})

const listenToOnBeforeHeaders = once(() => {
// adds a header to the request to mark it as a request for the AUT frame
// itself, so the proxy can utilize that for injection purposes
browser.webRequest.onBeforeSendHeaders.addListener((details) => {
if (
// parentFrameId: 0 means the parent is the top-level, so if it isn't
// 0, it's nested inside the AUT and can't be the AUT itself
details.parentFrameId !== 0
// is the spec frame, not the AUT
|| details.url.includes('__cypress')
) return

return {
requestHeaders: [
...details.requestHeaders,
{
name: 'X-Cypress-Is-AUT-Frame',
value: 'true',
},
],
}
}, { urls: ['<all_urls>'], types: ['sub_frame'] }, ['blocking', 'requestHeaders'])
})

const fail = (id, err) => {
return ws.emit('automation:response', id, {
__error: err.message,
Expand Down Expand Up @@ -167,13 +126,6 @@ const connect = function (host, path, extraOpts) {
if (isFirefox) {
// Non-Firefox browsers use CDP for this instead
listenToDownloads()
// if BiDi is enabled, BiDi will handle the network interception.
// Otherwise, CDP does not support it for Firefox and we need to listen for it here.
const isBiDiTurnedOn = await isBiDiEnabled(config)

if (!isBiDiTurnedOn) {
listenToOnBeforeHeaders()
}
}
})

Expand Down
114 changes: 0 additions & 114 deletions packages/extension/test/integration/v2/background_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,120 +293,6 @@ describe('app/background', () => {
})
})

context('add header to aut iframe requests', () => {
beforeEach(() => {
browser.runtime.getBrowserInfo = sinon.stub().resolves({ name: 'Firefox', version: '135.0.1' })
})

it('allows for CDP to be used as an escape hatch if BiDi would otherwise be enabled', async function () {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')

await this.connect({
IS_CDP_FORCED_FOR_FIREFOX: true,
})

expect(browser.webRequest.onBeforeSendHeaders.addListener).to.be.called
})

context('BiDi enabled', () => {
it('does not attach onBeforeSendHeaders listener if BiDi is enabled', async function () {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')

await this.connect()

expect(browser.webRequest.onBeforeSendHeaders.addListener).not.to.be.called
})
})

context('CDP enabled', () => {
beforeEach(() => {
browser.runtime.getBrowserInfo = sinon.stub().resolves({ name: 'Firefox', version: '134' })
})

it('does not add header if it is the top frame', async function () {
const details = {
parentFrameId: -1,
}

sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')

await this.connect()

const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)

expect(result).to.be.undefined
})

it('does not add header if it is a nested frame', async function () {
const details = {
parentFrameId: 12345,
}

sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')

await this.connect()

const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)

expect(result).to.be.undefined
})

it('does not add header if it is a spec frame request', async function () {
const details = {
parentFrameId: 0,
type: 'sub_frame',
url: '/__cypress/integration/spec.js',
}

sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')

await this.connect()
const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)

expect(result).to.be.undefined
})

it('appends X-Cypress-Is-AUT-Frame header to AUT iframe request', async function () {
const details = {
parentFrameId: 0,
type: 'sub_frame',
url: 'http://localhost:3000/index.html',
requestHeaders: [
{ name: 'X-Foo', value: 'Bar' },
],
}

sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')

await this.connect()
const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)

expect(result).to.deep.equal({
requestHeaders: [
{
name: 'X-Foo',
value: 'Bar',
},
{
name: 'X-Cypress-Is-AUT-Frame',
value: 'true',
},
],
})
})

it('does not add before-headers listener if in non-Firefox browser', async function () {
browser.runtime.getBrowserInfo = undefined

const onBeforeSendHeaders = sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')

await this.connect()

expect(onBeforeSendHeaders).not.to.be.called
})
})
})

context('.getAll', () => {
it('resolves with specific cookie properties', () => {
sinon.stub(browser.cookies, 'getAll').resolves([
Expand Down
1 change: 0 additions & 1 deletion packages/graphql/schemas/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1129,7 +1129,6 @@ enum ErrorTypeEnum {
CANNOT_TRASH_ASSETS
CDP_COULD_NOT_CONNECT
CDP_COULD_NOT_RECONNECT
CDP_FIREFOX_DEPRECATED
CDP_RETRYING_CONNECTION
CDP_VERSION_TOO_OLD
CHROME_WEB_SECURITY_NOT_SUPPORTED
Expand Down
24 changes: 23 additions & 1 deletion packages/launcher/lib/known-browsers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
import type { Browser, BrowserValidatorResult, FoundBrowser } from '@packages/types'

const firefoxValidatorFn = (browser: FoundBrowser, platform: NodeJS.Platform): BrowserValidatorResult => {
try {
if (browser.majorVersion) {
const majorVersion = Number(browser.majorVersion)

if (majorVersion < 135) {
return {
isSupported: false,
warningMessage: `Cypress does not support running ${browser.displayName} version ${browser.majorVersion} due to lack of WebDriver BiDi support. To use ${browser.displayName} with Cypress, install version 135 or newer.`,
}
}
}
} catch (e) { /* empty */ }

return {
isSupported: true,
}
}

/** list of the browsers we can detect and use by default */
export const knownBrowsers: Browser[] = [
{
Expand Down Expand Up @@ -62,9 +81,10 @@ export const knownBrowsers: Browser[] = [
family: 'firefox',
channel: 'stable',
displayName: 'Firefox',
// Mozilla Firefox 70.0.1
// Mozilla Firefox 135.0.1
versionRegex: /^Mozilla Firefox ([^\sab]+)$/m,
binary: 'firefox',
validator: firefoxValidatorFn,
},
{
name: 'firefox',
Expand All @@ -75,6 +95,7 @@ export const knownBrowsers: Browser[] = [
versionRegex: /^Mozilla Firefox (\S+b\S*)$/m,
// ubuntu PPAs install it as firefox
binary: ['firefox-developer-edition', 'firefox'],
validator: firefoxValidatorFn,
},
{
name: 'firefox',
Expand All @@ -85,6 +106,7 @@ export const knownBrowsers: Browser[] = [
versionRegex: /^Mozilla Firefox (\S+a\S*)$/m,
// ubuntu PPAs install it as firefox-trunk
binary: ['firefox-nightly', 'firefox-trunk'],
validator: firefoxValidatorFn,
},
{
name: 'edge',
Expand Down
19 changes: 19 additions & 0 deletions packages/launcher/test/unit/browsers_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,25 @@ describe('browsers', () => {
expect(result.isSupported).to.be.true
expect(result.warningMessage).to.be.undefined
})

describe('firefox validation', () => {
const FIREFOX_KNOWN_BROWSER_CHANNELS = knownBrowsers.filter((browser) => {
return browser.family === 'firefox'
})

FIREFOX_KNOWN_BROWSER_CHANNELS.forEach((browser) => {
it(`${browser.channel}: fails validation when Firefox major version is below 135`, () => {
// @ts-expect-error
const result = browser.validator({
majorVersion: '134',
displayName: 'Firefox',
})

expect(result.isSupported).to.be.false
expect(result.warningMessage).to.equal('Cypress does not support running Firefox version 134 due to lack of WebDriver BiDi support. To use Firefox with Cypress, install version 135 or newer.')
})
})
})
})
})
})
Loading