diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index d7e90061321c..efe30e2e08f1 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -11,6 +11,7 @@ _Released 09/12/2023 (PENDING)_ - Edge cases where `cy.intercept()` would not properly intercept and asset response bodies would not properly be captured for test replay have been addressed. Addressed in [#27771](https://github.com/cypress-io/cypress/issues/27771). - Fixed an issue where `enter`, `keyup`, and `space` events where not triggering `click` events properly in some versions of Firefox. Addressed in [#27715](https://github.com/cypress-io/cypress/pull/27715). +- Fixed a regression in `13.0.0` where tests using Basic Authorization can potentially hang indefinitely on chromium browsers. Addressed in [#27781](https://github.com/cypress-io/cypress/pull/27781) **Dependency Updates:** diff --git a/packages/socket/lib/browser.ts b/packages/socket/lib/browser.ts index e6eb5c5eaa95..1ca9ccc205f1 100644 --- a/packages/socket/lib/browser.ts +++ b/packages/socket/lib/browser.ts @@ -4,18 +4,29 @@ import type { SocketShape } from './types' export type { Socket } from 'socket.io-client' -const sockets: {[key: string]: CDPBrowserSocket} = {} +declare global { + interface Window { + cypressSockets: {[key: string]: CDPBrowserSocket} + } +} + let chromium = false export function client (uri: string, opts?: Partial): SocketShape { if (chromium) { const fullNamespace = `${opts?.path}${uri}` - if (!sockets[fullNamespace]) { - sockets[fullNamespace] = new CDPBrowserSocket(fullNamespace) + // When running in Chromium and with a baseUrl set to something that includes basic auth: (e.g. http://user:pass@localhost:1234), the assets + // will load twice. Thus, we need to add the cypress sockets to the window object rather than just relying on a local variable. + window.cypressSockets ||= {} + if (!window.cypressSockets[fullNamespace]) { + window.cypressSockets[fullNamespace] = new CDPBrowserSocket(fullNamespace) } - return sockets[fullNamespace] + // Connect the socket regardless of whether or not we have newly created it + window.cypressSockets[fullNamespace].connect() + + return window.cypressSockets[fullNamespace] } return io(uri, opts) @@ -27,11 +38,17 @@ export function createWebsocket ({ path, browserFamily }: { path: string, browse const fullNamespace = `${path}/default` - if (!sockets[fullNamespace]) { - sockets[fullNamespace] = new CDPBrowserSocket(fullNamespace) + // When running in Chromium and with a baseUrl set to something that includes basic auth: (e.g. http://user:pass@localhost:1234), the assets + // will load twice. Thus, we need to add the cypress sockets to the window object rather than just relying on a local variable. + window.cypressSockets ||= {} + if (!window.cypressSockets[fullNamespace]) { + window.cypressSockets[fullNamespace] = new CDPBrowserSocket(fullNamespace) } - return sockets[fullNamespace] + // Connect the socket regardless of whether or not we have newly created it + window.cypressSockets[fullNamespace].connect() + + return window.cypressSockets[fullNamespace] } return io({ diff --git a/packages/socket/lib/cdp-browser.ts b/packages/socket/lib/cdp-browser.ts index b444632d2ceb..a5730fd302c1 100644 --- a/packages/socket/lib/cdp-browser.ts +++ b/packages/socket/lib/cdp-browser.ts @@ -43,7 +43,9 @@ export class CDPBrowserSocket extends Emitter implements SocketShape { if (!cypressSocket.send) { cypressSocket.send = send } + } + connect () { // Set timeout so that the connect event is emitted after the constructor returns and the user has a chance to attach a listener setTimeout(() => { super.emit('connect') diff --git a/system-tests/__snapshots__/base_url_spec.js b/system-tests/__snapshots__/base_url_spec.js index eba07bc43a6e..e4cbc1999cf7 100644 --- a/system-tests/__snapshots__/base_url_spec.js +++ b/system-tests/__snapshots__/base_url_spec.js @@ -107,3 +107,58 @@ exports['e2e baseUrl / http / passes'] = ` ` + +exports['e2e baseUrl / https basic auth / passes'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 1 found (base_url.cy.js) │ + │ Searched: cypress/e2e/base_url.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: base_url.cy.js (1 of 1) + + + base url + ✓ can visit + + + 1 passing + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 1 │ + │ Passing: 1 │ + │ Failing: 0 │ + │ Pending: 0 │ + │ Skipped: 0 │ + │ Screenshots: 0 │ + │ Video: false │ + │ Duration: X seconds │ + │ Spec Ran: base_url.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✔ base_url.cy.js XX:XX 1 1 - - - │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✔ All specs passed! XX:XX 1 1 - - - + + +` diff --git a/system-tests/test/base_url_spec.js b/system-tests/test/base_url_spec.js index 86ad33fa479c..38ae2717e6b6 100644 --- a/system-tests/test/base_url_spec.js +++ b/system-tests/test/base_url_spec.js @@ -27,6 +27,27 @@ describe('e2e baseUrl', () => { }) }) + context('https basic auth', () => { + systemTests.setup({ + servers: { + port: 443, + https: true, + onServer, + }, + settings: { + e2e: { + baseUrl: 'https://test:test@localhost/app', + }, + }, + }) + + systemTests.it('passes', { + spec: 'base_url.cy.js', + browser: 'chrome', + snapshot: true, + }) + }) + context('http', () => { systemTests.setup({ servers: {