From 86d8b9677cf52a8c9a29be566f0973e463fd06c2 Mon Sep 17 00:00:00 2001 From: Martin Jonson <88532439+Crustum7@users.noreply.github.com> Date: Fri, 8 Sep 2023 22:53:26 +0200 Subject: [PATCH 01/83] docs: fix typo in CONTRIBUTING.md (#27705) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Simon Törnqvist --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 800dd5bd5904..85ddc536a838 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -414,7 +414,7 @@ The repository has one protected branch: We want to publish our [standalone npm packages](./npm) continuously as new features are added. Therefore, after any pull request that changes independent `@cypress/` packages in the [`npm`](./npm) directory will automatically publish when a PR is merged directly into `develop` and the entire build passes. We used [`semantic-release`](https://semantic-release.gitbook.io/semantic-release/) to automate the release of these packages to npm. -We do not continuously deploy the Cypress binary, so `develop` contains all of the new features and fixes that are staged to go out in the next update of the main Cypress app. If you make changes to an npm package that can't be published until the binary is also updated, you should make a pull request against specifying this is not be merged until the scheduled Cypress app release date. +We do not continuously deploy the Cypress binary, so `develop` contains all of the new features and fixes that are staged to go out in the next update of the main Cypress app. If you make changes to an npm package that can't be published until the binary is also updated, the pull request should clearly state that it should not be merged until the next scheduled Cypress app release date. ### Pull Requests From 70248ab9c0bb90e0dd5987d64e2199d46f3dc600 Mon Sep 17 00:00:00 2001 From: Ryan Manuel Date: Sun, 10 Sep 2023 21:41:40 -0500 Subject: [PATCH 02/83] fix: prerequest correlation for various retried and cached requests (#27771) --- cli/CHANGELOG.md | 1 + .../proxy/lib/http/response-middleware.ts | 20 ++++++++- packages/proxy/lib/http/util/prerequests.ts | 2 +- .../unit/http/response-middleware.spec.ts | 45 ++++++++++++++++++- .../test/unit/http/util/prerequests.spec.ts | 15 +++++++ .../server/lib/browsers/cdp_automation.ts | 6 +++ .../test/unit/browsers/cdp_automation_spec.ts | 17 +++++++ 7 files changed, 101 insertions(+), 5 deletions(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index d4ad63cde915..d7e90061321c 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -9,6 +9,7 @@ _Released 09/12/2023 (PENDING)_ **Bugfixes:** +- 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). **Dependency Updates:** diff --git a/packages/proxy/lib/http/response-middleware.ts b/packages/proxy/lib/http/response-middleware.ts index a83f92890a34..641c76d846a9 100644 --- a/packages/proxy/lib/http/response-middleware.ts +++ b/packages/proxy/lib/http/response-middleware.ts @@ -145,6 +145,18 @@ const stringifyFeaturePolicy = (policy: any): string => { return pairs.map((directive) => directive.join(' ')).join('; ') } +const requestIdRegEx = /^(.*)-retry-([\d]+)$/ +const getOriginalRequestId = (requestId: string) => { + let originalRequestId = requestId + const match = requestIdRegEx.exec(requestId) + + if (match) { + [, originalRequestId] = match + } + + return originalRequestId +} + const LogResponse: ResponseMiddleware = function () { this.debug('received response %o', { browserPreRequest: _.pick(this.req.browserPreRequest, 'requestId'), @@ -674,8 +686,10 @@ const ClearCyInitialCookie: ResponseMiddleware = function () { const MaybeEndWithEmptyBody: ResponseMiddleware = function () { if (httpUtils.responseMustHaveEmptyBody(this.req, this.incomingRes)) { if (this.protocolManager && this.req.browserPreRequest?.requestId) { + const requestId = getOriginalRequestId(this.req.browserPreRequest.requestId) + this.protocolManager.responseEndedWithEmptyBody({ - requestId: this.req.browserPreRequest.requestId, + requestId, isCached: this.incomingRes.statusCode === 304, }) } @@ -783,9 +797,11 @@ const MaybeRemoveSecurity: ResponseMiddleware = function () { const GzipBody: ResponseMiddleware = async function () { if (this.protocolManager && this.req.browserPreRequest?.requestId) { + const requestId = getOriginalRequestId(this.req.browserPreRequest.requestId) + const span = telemetry.startSpan({ name: 'gzip:body:protocol-notification', parentSpan: this.resMiddlewareSpan, isVerbose }) const resultingStream = this.protocolManager.responseStreamReceived({ - requestId: this.req.browserPreRequest.requestId, + requestId, responseHeaders: this.incomingRes.headers, isAlreadyGunzipped: this.isGunzipped, responseStream: this.incomingResStream, diff --git a/packages/proxy/lib/http/util/prerequests.ts b/packages/proxy/lib/http/util/prerequests.ts index dcf538c9fd23..d598f9397bb6 100644 --- a/packages/proxy/lib/http/util/prerequests.ts +++ b/packages/proxy/lib/http/util/prerequests.ts @@ -138,7 +138,7 @@ export class PreRequests { removePending (requestId: string) { this.pendingPreRequests.removeMatching(({ browserPreRequest }) => { - return browserPreRequest.requestId !== requestId + return (browserPreRequest.requestId.includes('-retry-') && !browserPreRequest.requestId.startsWith(`${requestId}-`)) || (!browserPreRequest.requestId.includes('-retry-') && browserPreRequest.requestId !== requestId) }) } diff --git a/packages/proxy/test/unit/http/response-middleware.spec.ts b/packages/proxy/test/unit/http/response-middleware.spec.ts index b405b8de9abd..d0f9dc075b09 100644 --- a/packages/proxy/test/unit/http/response-middleware.spec.ts +++ b/packages/proxy/test/unit/http/response-middleware.spec.ts @@ -1847,14 +1847,14 @@ describe('http/response-middleware', function () { }) }) - it('calls responseEndedWithEmptyBody on protocolManager if protocolManager present and request is correlated and response must have empty body and response is not cached', function () { + it('calls responseEndedWithEmptyBody on protocolManager if protocolManager present and retried request is correlated and response must have empty body and response is not cached', function () { prepareContext({ protocolManager: { responseEndedWithEmptyBody: responseEndedWithEmptyBodyStub, }, req: { browserPreRequest: { - requestId: '123', + requestId: '123-retry-1', }, }, incomingRes: { @@ -2285,6 +2285,47 @@ describe('http/response-middleware', function () { }) }) + it('calls responseStreamReceived on protocolManager if protocolManager present and retried request is correlated', function () { + const stream = Readable.from(['foo']) + const headers = { 'content-encoding': 'gzip' } + const res = { + on: (event, listener) => {}, + off: (event, listener) => {}, + } + + prepareContext({ + protocolManager: { + responseStreamReceived: responseStreamReceivedStub, + }, + req: { + browserPreRequest: { + requestId: '123-retry-1', + }, + }, + res, + incomingRes: { + headers, + }, + isGunzipped: true, + incomingResStream: stream, + }) + + return testMiddleware([GzipBody], ctx) + .then(() => { + expect(responseStreamReceivedStub).to.be.calledWith( + sinon.match(function (actual) { + expect(actual.requestId).to.equal('123') + expect(actual.responseHeaders).to.equal(headers) + expect(actual.isAlreadyGunzipped).to.equal(true) + expect(actual.responseStream).to.equal(stream) + expect(actual.res).to.equal(res) + + return true + }), + ) + }) + }) + it('does not call responseStreamReceived on protocolManager if protocolManager present and request is not correlated', function () { const stream = Readable.from(['foo']) const headers = { 'content-encoding': 'gzip' } diff --git a/packages/proxy/test/unit/http/util/prerequests.spec.ts b/packages/proxy/test/unit/http/util/prerequests.spec.ts index bfbe9f0e0e32..08b1fd6a9a4a 100644 --- a/packages/proxy/test/unit/http/util/prerequests.spec.ts +++ b/packages/proxy/test/unit/http/util/prerequests.spec.ts @@ -90,4 +90,19 @@ describe('http/util/prerequests', () => { expectPendingCounts(0, 2) }) + + it('removes a pre-request with a matching requestId with retries', () => { + preRequests.addPending({ requestId: '1234', url: 'foo', method: 'GET' } as BrowserPreRequest) + preRequests.addPending({ requestId: '1235', url: 'foo', method: 'GET' } as BrowserPreRequest) + preRequests.addPending({ requestId: '1235-retry-1', url: 'foo', method: 'GET' } as BrowserPreRequest) + preRequests.addPending({ requestId: '1235-retry-2', url: 'foo', method: 'GET' } as BrowserPreRequest) + preRequests.addPending({ requestId: '1235-retry-3', url: 'foo', method: 'GET' } as BrowserPreRequest) + preRequests.addPending({ requestId: '1236', url: 'foo', method: 'GET' } as BrowserPreRequest) + + expectPendingCounts(0, 6) + + preRequests.removePending('1235') + + expectPendingCounts(0, 2) + }) }) diff --git a/packages/server/lib/browsers/cdp_automation.ts b/packages/server/lib/browsers/cdp_automation.ts index 6f37150298b9..818e81942140 100644 --- a/packages/server/lib/browsers/cdp_automation.ts +++ b/packages/server/lib/browsers/cdp_automation.ts @@ -251,6 +251,12 @@ export class CdpAutomation implements CDPClient { } private onResponseReceived = (params: Protocol.Network.ResponseReceivedEvent) => { + if (params.response.fromDiskCache) { + this.automation.onRequestServedFromCache?.(params.requestId) + + return + } + const browserResponseReceived: BrowserResponseReceived = { requestId: params.requestId, status: params.response.status, diff --git a/packages/server/test/unit/browsers/cdp_automation_spec.ts b/packages/server/test/unit/browsers/cdp_automation_spec.ts index ade10b8513b0..9021b9b63d92 100644 --- a/packages/server/test/unit/browsers/cdp_automation_spec.ts +++ b/packages/server/test/unit/browsers/cdp_automation_spec.ts @@ -181,6 +181,23 @@ context('lib/browsers/cdp_automation', () => { }, ) }) + + it('cleans up prerequests when response is cached from disk', function () { + const browserResponseReceived = { + requestId: '0', + response: { + status: 200, + headers: {}, + fromDiskCache: true, + }, + } + + this.onFn + .withArgs('Network.responseReceived') + .yield(browserResponseReceived) + + expect(this.automation.onRequestEvent).not.to.have.been.called + }) }) describe('.onRequestServedFromCache', function () { From a1161c90e07280b44474d68209570ae222fc4501 Mon Sep 17 00:00:00 2001 From: Ryan Manuel Date: Mon, 11 Sep 2023 12:23:05 -0500 Subject: [PATCH 03/83] fix: hanging on basic auth requests in chromium browsers (#27781) --- cli/CHANGELOG.md | 1 + packages/socket/lib/browser.ts | 31 +++++++++--- packages/socket/lib/cdp-browser.ts | 2 + system-tests/__snapshots__/base_url_spec.js | 55 +++++++++++++++++++++ system-tests/test/base_url_spec.js | 21 ++++++++ 5 files changed, 103 insertions(+), 7 deletions(-) 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: { From 356edfc5e9b52bdf4dc42654314c9aa0ab829bbc Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Mon, 11 Sep 2023 20:17:39 -0400 Subject: [PATCH 04/83] chore: fix the changelog to pass release readiness (#27787) --- cli/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index efe30e2e08f1..70bbc91ee674 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -9,7 +9,7 @@ _Released 09/12/2023 (PENDING)_ **Bugfixes:** -- 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). +- 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/pull/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) From f8b4c59daabf5f60a01aab8db6a1b1a4f853e177 Mon Sep 17 00:00:00 2001 From: Matt Schile Date: Tue, 12 Sep 2023 08:22:33 -0600 Subject: [PATCH 05/83] fix: update net stubbing to not intercept requests sent to dev server (#27788) --- cli/CHANGELOG.md | 5 ++- .../lib/server/middleware/request.ts | 10 +++++ .../test/integration/net-stubbing.spec.ts | 37 +++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 70bbc91ee674..599cb863fd3c 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -10,8 +10,9 @@ _Released 09/12/2023 (PENDING)_ **Bugfixes:** - 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/pull/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) +- 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). +- Fixed a regression in `13.0.0` where component tests using an intercept that matches all requests can potentially hang indefinitely. Addressed in [#27788](https://github.com/cypress-io/cypress/pull/27788). **Dependency Updates:** diff --git a/packages/net-stubbing/lib/server/middleware/request.ts b/packages/net-stubbing/lib/server/middleware/request.ts index 7f0c9e383ebd..00dd34561fff 100644 --- a/packages/net-stubbing/lib/server/middleware/request.ts +++ b/packages/net-stubbing/lib/server/middleware/request.ts @@ -28,6 +28,16 @@ const debug = null export const SetMatchingRoutes: RequestMiddleware = async function () { const span = telemetry.startSpan({ name: 'set:matching:routes', parentSpan: this.reqMiddlewareSpan, isVerbose: true }) + const url = new URL(this.req.proxiedUrl) + + // if this is a request to the dev server, do not match any routes as + // we do not want to allow the user to intercept requests to the dev server + if (url.pathname.startsWith(this.config.devServerPublicPathRoute)) { + span?.end() + + return this.next() + } + if (matchesRoutePreflight(this.netStubbingState.routes, this.req)) { // send positive CORS preflight response return sendStaticResponse(this, { diff --git a/packages/proxy/test/integration/net-stubbing.spec.ts b/packages/proxy/test/integration/net-stubbing.spec.ts index 525c9739f4cf..fd7a50c10d1a 100644 --- a/packages/proxy/test/integration/net-stubbing.spec.ts +++ b/packages/proxy/test/integration/net-stubbing.spec.ts @@ -328,6 +328,43 @@ context('network stubbing', () => { expect(sendContentLength).to.eq(realContentLength) }) + it('does not intercept requests to the dev server', async () => { + destinationApp.get('/__cypress/src/main.js', (req, res) => res.send('it worked')) + + // setup an intercept that matches all requests + // and has a static response + netStubbingState.routes.push({ + id: '1', + routeMatcher: { + url: '*', + }, + hasInterceptor: false, + staticResponse: { + body: 'foo', + }, + getFixture, + matches: 1, + }) + + config.devServerPublicPathRoute = '/__cypress/src' + + // request to the dev server does NOT get intercepted + await supertest(app) + .get(`/http://localhost:${destinationPort}/__cypress/src/main.js`) + .then((res) => { + expect(res.status).to.eq(200) + expect(res.text).to.eq('it worked') + }) + + // request NOT to the dev server DOES get intercepted + await supertest(app) + .get(`/http://localhost:${destinationPort}/`) + .then((res) => { + expect(res.status).to.eq(200) + expect(res.text).to.eq('foo') + }) + }) + describe('CSP Headers', () => { // Loop through valid CSP header names can verify that we handle them [ From 8638abb2d0082809c8eea559f7ba4af74fd61c4a Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Tue, 12 Sep 2023 10:42:17 -0400 Subject: [PATCH 06/83] chore: prep changelog ready for release and bump cypress version (#27794) * chore: get changelog ready for release and bump cypress version * chore: fix typos --- cli/CHANGELOG.md | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 599cb863fd3c..d413af3445ba 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -1,22 +1,22 @@ ## 13.2.0 -_Released 09/12/2023 (PENDING)_ +_Released 09/12/2023_ **Features:** - - Adds support for Nx users who want to run Angular Component Testing in parallel. Addresses [#27723](https://github.com/cypress-io/cypress/pull/27723). + - Adds support for Nx users who want to run Angular Component Testing in parallel. Addressed in [#27723](https://github.com/cypress-io/cypress/pull/27723). **Bugfixes:** - 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/pull/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 an issue where `enter`, `keyup`, and `space` events were 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). - Fixed a regression in `13.0.0` where component tests using an intercept that matches all requests can potentially hang indefinitely. Addressed in [#27788](https://github.com/cypress-io/cypress/pull/27788). **Dependency Updates:** -- Upgraded Electron from `21.0.0` to `25.8.0`, which updates bundled Chromium from `106.0.5249.51` to `114.0.5735.289`. Addresses [#27595](https://github.com/cypress-io/cypress/issues/27595). Additionally, the Node version the binary has been upgraded from from `16.16.0` to `18.15.0`. This does **NOT** have an impact on the node version you are using with Cypress and is merely an internal update to the repository & shipped binary. Addressed in [#27715](https://github.com/cypress-io/cypress/pull/27715). Addresses [#27595](https://github.com/cypress-io/cypress/issues/27595). +- Upgraded Electron from `21.0.0` to `25.8.0`, which updates bundled Chromium from `106.0.5249.51` to `114.0.5735.289`. Additionally, the Node version binary has been upgraded from `16.16.0` to `18.15.0`. This does **NOT** have an impact on the node version you are using with Cypress and is merely an internal update to the repository & shipped binary. Addressed in [#27715](https://github.com/cypress-io/cypress/pull/27715). Addresses [#27595](https://github.com/cypress-io/cypress/issues/27595). ## 13.1.0 diff --git a/package.json b/package.json index 4e6d5b76c3b8..7caf82b86302 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cypress", - "version": "13.1.0", + "version": "13.2.0", "description": "Cypress is a next generation front end testing tool built for the modern web", "private": true, "scripts": { From 0e239bf2108b6a80c0d4a5a4c017b77568101549 Mon Sep 17 00:00:00 2001 From: Dave Kasper Date: Thu, 14 Sep 2023 16:35:12 -0500 Subject: [PATCH 07/83] feat(app): Update Runs page visuals to new layout and card design (#27770) * basic card visuals, working on click * visual tweaks and i18n * match other i18n * redo duration format, should make common too * basic debug, needs validation of relevant run * refactor and move files * working top level state * working grouping, needs subcomponent * switch click target * remove dayjs change * fix current commit * revise commit for message * working view runs button * fix type check * fix tests * fix integration tests * remove old test * add layout * add component test for new layout and cleanup * add count check * standardize cy tags * revise count test * fix typos * fix padding * start wrapping * happy wrap, next trunc * responsive if wonky * clean up and titles * magic resize, needs tests per breakpoint * standardize the rollup * working default rollup * rollup spacing tweaks * center elements * update tests for multiple viewports * add missing breakpoint tests * fix debug tests for status and badge * remove unneeded check * add functional component * fix check_ts * update container test * add changelog * add tooltip, needs aria label and external link update * fix overflow * fix avatar and add aria label to count summary * change to external href * remove popup sizing * add tests * add missing data cy * fix runcard test * Truncate result count * make truncate style conditional * match design truncate position * adddress PR comments * chore:updating styles (#27798) * add tooltip content tests and skeletons * clean up tooltip validation * fix runs selector * Update packages/app/src/runs/RunsSkeletonRow.vue Co-authored-by: Stokes Player * Update packages/app/src/runs/RunTagCount.vue Co-authored-by: Stokes Player * Update packages/app/src/runs/RunsSkeleton.vue Co-authored-by: Stokes Player * Update packages/app/src/runs/RunTagCount.vue Co-authored-by: Stokes Player * Update packages/app/src/runs/RunsSkeleton.vue Co-authored-by: Stokes Player * Update packages/app/src/runs/RunsSkeletonRow.vue Co-authored-by: Stokes Player * Update packages/app/src/runs/RunTagCount.vue Co-authored-by: Stokes Player * Update packages/app/src/runs/RunTagCount.vue Co-authored-by: Stokes Player * remove redundant shrink-1s * more shrinks --------- Co-authored-by: Stokes Player --- cli/CHANGELOG.md | 8 + packages/app/cypress/e2e/debug.cy.ts | 4 +- packages/app/cypress/e2e/runs.cy.ts | 53 ++-- packages/app/package.json | 2 +- packages/app/src/debug/DebugPageHeader.cy.tsx | 8 +- packages/app/src/debug/DebugPageHeader.vue | 12 +- packages/app/src/debug/DebugResults.cy.tsx | 51 --- packages/app/src/debug/DebugResults.vue | 59 ---- packages/app/src/debug/DebugRunNavigation.vue | 10 +- .../app/src/debug/DebugRunNavigationRow.vue | 10 +- packages/app/src/debug/DebugRunNumber.cy.tsx | 14 - packages/app/src/debug/DebugRunNumber.vue | 45 --- packages/app/src/debug/StatsMetadata.vue | 5 +- packages/app/src/pages/Runs.vue | 9 +- packages/app/src/runs/RunCard.cy.tsx | 194 ++++++++---- packages/app/src/runs/RunCard.vue | 290 +++++++++++++----- packages/app/src/runs/RunNumber.cy.tsx | 34 ++ packages/app/src/runs/RunNumber.vue | 58 ++++ packages/app/src/runs/RunResults.cy.tsx | 57 +++- packages/app/src/runs/RunResults.vue | 43 ++- packages/app/src/runs/RunTag.cy.tsx | 37 +++ packages/app/src/runs/RunTag.vue | 34 ++ packages/app/src/runs/RunTagCount.cy.tsx | 81 +++++ packages/app/src/runs/RunTagCount.vue | 126 ++++++++ packages/app/src/runs/RunsComposable.ts | 2 + packages/app/src/runs/RunsContainer.cy.tsx | 5 +- packages/app/src/runs/RunsContainer.vue | 31 +- packages/app/src/runs/RunsLayout.cy.tsx | 171 +++++++++++ packages/app/src/runs/RunsLayout.vue | 157 ++++++++++ packages/app/src/runs/RunsSkeleton.cy.tsx | 10 +- packages/app/src/runs/RunsSkeleton.vue | 90 ++++-- packages/app/src/runs/RunsSkeletonRow.cy.tsx | 7 + packages/app/src/runs/RunsSkeletonRow.vue | 39 +++ packages/app/src/runs/useGitTreeRuns.ts | 11 + packages/app/src/runs/useProjectRuns.ts | 1 + .../src/sources/RelevantRunsDataSource.ts | 2 +- .../src/components/ResultCounts.vue | 1 + .../frontend-shared/src/locales/en-US.json | 12 + packages/graphql/schemas/schema.graphql | 2 +- .../schemaTypes/objectTypes/gql-Mutation.ts | 5 +- yarn.lock | 16 +- 41 files changed, 1378 insertions(+), 428 deletions(-) delete mode 100644 packages/app/src/debug/DebugResults.cy.tsx delete mode 100644 packages/app/src/debug/DebugResults.vue delete mode 100644 packages/app/src/debug/DebugRunNumber.cy.tsx delete mode 100644 packages/app/src/debug/DebugRunNumber.vue create mode 100644 packages/app/src/runs/RunNumber.cy.tsx create mode 100644 packages/app/src/runs/RunNumber.vue create mode 100644 packages/app/src/runs/RunTag.cy.tsx create mode 100644 packages/app/src/runs/RunTag.vue create mode 100644 packages/app/src/runs/RunTagCount.cy.tsx create mode 100644 packages/app/src/runs/RunTagCount.vue create mode 100644 packages/app/src/runs/RunsLayout.cy.tsx create mode 100644 packages/app/src/runs/RunsLayout.vue create mode 100644 packages/app/src/runs/RunsSkeletonRow.cy.tsx create mode 100644 packages/app/src/runs/RunsSkeletonRow.vue diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index d413af3445ba..6418a505b6e8 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -1,4 +1,12 @@ +## 13.3.0 + +_Released 09/19/2023 (PENDING)_ + +**Features:** + + - Introduces new layout for Runs page providing additional run information. Addresses [#27203](https://github.com/cypress-io/cypress/issues/27203). + ## 13.2.0 _Released 09/12/2023_ diff --git a/packages/app/cypress/e2e/debug.cy.ts b/packages/app/cypress/e2e/debug.cy.ts index a5252b99eb56..c2c39129028b 100644 --- a/packages/app/cypress/e2e/debug.cy.ts +++ b/packages/app/cypress/e2e/debug.cy.ts @@ -75,7 +75,7 @@ describe('App - Debug Page', () => { .contains('View in Cypress Cloud') .should('have.attr', 'href', 'https://cloud.cypress.io/projects/7p5uce/runs/2?utm_medium=Debug+Tab&utm_campaign=View+in+Cypress+Cloud&utm_source=Binary%3A+App') - cy.findByTestId('debug-runNumber-PASSED').contains('#2') + cy.findByTestId('runNumber-status-PASSED').contains('#2') cy.findByTestId('debug-commitsAhead').contains('You are 1 commit ahead') cy.findByTestId('metadata').within(() => { @@ -136,7 +136,7 @@ describe('App - Debug Page', () => { cy.findByLabelText('Relevant run had 1 test failure').should('be.visible').contains('1') - cy.findByTestId('debug-runNumber-FAILED').contains('#136') + cy.findByTestId('runNumber-status-FAILED').contains('#136') cy.findByTestId('debug-commitsAhead').contains('You are 1 commit ahead') cy.findByTestId('metadata').within(() => { diff --git a/packages/app/cypress/e2e/runs.cy.ts b/packages/app/cypress/e2e/runs.cy.ts index d89a684b872d..5e6efb766d58 100644 --- a/packages/app/cypress/e2e/runs.cy.ts +++ b/packages/app/cypress/e2e/runs.cy.ts @@ -60,7 +60,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { cy.visitApp() cy.findByTestId('sidebar-link-runs-page').click() - cy.get('[data-cy="runs-loader"]') + cy.get('[data-cy*="runsSkeleton-"]') cy.get('[data-cy="runs"]') }) }) @@ -103,7 +103,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { cy.visitApp() moveToRunsPage() - cy.contains('a', 'OVERLIMIT').click() + cy.findByTestId('runNumber-status-OVERLIMIT').click() cy.withCtx((ctx, o) => { expect((ctx.actions.electron.openExternal as SinonStub).lastCall.lastArg).to.contain('http://dummy.cypress.io/runs/4') @@ -666,29 +666,25 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { cy.visitApp() moveToRunsPage() - cy.get('[href^="http://dummy.cypress.io/runs/0"]').first().within(() => { - cy.findByText('fix: make gql work CANCELLED') - cy.get('[data-cy="run-card-icon-CANCELLED"]') + cy.get('[data-cy="runCard-status-CANCELLED"]').first().within(() => { + cy.get('[data-cy="runNumber-status-CANCELLED"]') }) - cy.get('[href^="http://dummy.cypress.io/runs/1"]').first().within(() => { - cy.findByText('fix: make gql work ERRORED') - cy.get('[data-cy="run-card-icon-ERRORED"]') + cy.get('[data-cy="runCard-status-ERRORED"]').first().within(() => { + cy.get('[data-cy="runNumber-status-ERRORED"]') }) - cy.get('[href^="http://dummy.cypress.io/runs/2"]').first().within(() => { - cy.findByText('fix: make gql work FAILED') - cy.get('[data-cy="run-card-icon-FAILED"]') + cy.get('[data-cy="runCard-status-FAILED"]').first().within(() => { + cy.get('[data-cy="runNumber-status-FAILED"]') }) - cy.get('[href^="http://dummy.cypress.io/runs/0"]').first().as('firstRun') + cy.get('[data-cy="runCard-status-CANCELLED"]').first().as('firstRun') cy.get('@firstRun').within(() => { - cy.get('[data-cy="run-card-author"]').contains('John Appleseed') - cy.get('[data-cy="run-card-avatar"]') - cy.get('[data-cy="run-card-branch"]').contains('main') - cy.get('[data-cy="run-card-created-at"]').contains('an hour ago') - cy.get('[data-cy="run-card-duration"]').contains('01:00') + cy.get('[data-cy="runCard-author"]').contains('John Appleseed') + cy.get('[data-cy="runCard-avatar"]') + cy.get('[data-cy="runCard-branchName"]').contains('main') + cy.get('[data-cy="runCard-createdAt"]').contains('01m 00s (an hour ago)') cy.contains('span', 'skipped') cy.get('span').contains('pending') @@ -702,7 +698,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { cy.visitApp() moveToRunsPage() - cy.get('[data-cy^="runCard-"]').first().click() + cy.get('[data-cy="runNumber-status-CANCELLED"]').first().click() cy.withCtx((ctx) => { expect((ctx.actions.electron.openExternal as SinonStub).lastCall.lastArg).to.contain('http://dummy.cypress.io/runs/0') @@ -765,19 +761,18 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { cy.visitApp() moveToRunsPage() + cy.findByText('fix: using Git data CANCELLED') cy.get('[href^="http://dummy.cypress.io/runs/0"]').first().within(() => { - cy.findByText('fix: using Git data CANCELLED') - cy.get('[data-cy="run-card-icon-CANCELLED"]') + cy.get('[data-cy="runNumber-status-CANCELLED"]') }) - cy.get('[href^="http://dummy.cypress.io/runs/0"]').first().as('firstRun') + cy.get('[data-cy="runCard-status-CANCELLED"]').first().as('firstRun') cy.get('@firstRun').within(() => { - cy.get('[data-cy="run-card-author"]').contains('John Appleseed') - cy.get('[data-cy="run-card-avatar"]') - cy.get('[data-cy="run-card-branch"]').contains('main') - cy.get('[data-cy="run-card-created-at"]').contains('an hour ago') - cy.get('[data-cy="run-card-duration"]').contains('01:00') + cy.get('[data-cy="runCard-author"]').contains('John Appleseed') + cy.get('[data-cy="runCard-avatar"]') + cy.get('[data-cy="runCard-branchName"]').contains('main') + cy.get('[data-cy="runCard-createdAt"]').contains('01m 00s (an hour ago)') cy.contains('span', 'skipped') cy.get('span').contains('pending') @@ -791,7 +786,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { cy.visitApp() moveToRunsPage() - cy.get('[data-cy^="runCard-"]').first().click() + cy.get('[data-cy="runNumber-status-CANCELLED"]').first().click() cy.withCtx((ctx) => { expect((ctx.actions.electron.openExternal as SinonStub).lastCall.lastArg).to.contain('http://dummy.cypress.io/runs/0') @@ -955,7 +950,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { const itSkipIfWindows = Cypress.platform === 'win32' ? it.skip : it itSkipIfWindows('should re-query for executing runs', () => { - cy.get('[data-cy="run-card-icon-RUNNING"]').should('have.length', RUNNING_COUNT).should('be.visible') + cy.get('[data-cy="runNumber-status-RUNNING"]').should('have.length', RUNNING_COUNT).should('be.visible') cy.remoteGraphQLIntercept(async (obj) => { await new Promise((resolve) => setTimeout(resolve, 100)) @@ -976,7 +971,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { }) function completeNext (passed) { - cy.get('[data-cy="run-card-icon-PASSED"]').should('have.length', passed).should('be.visible') + cy.get('[data-cy="runNumber-status-PASSED"]').should('have.length', passed).should('be.visible') if (passed < RUNNING_COUNT) { completeNext(passed + 1) } diff --git a/packages/app/package.json b/packages/app/package.json index c4a45f225676..e2c9505defcf 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -21,7 +21,7 @@ "dependencies": {}, "devDependencies": { "@cypress-design/vue-button": "^0.10.1", - "@cypress-design/vue-icon": "^0.25.0", + "@cypress-design/vue-icon": "^0.26.0", "@cypress-design/vue-statusicon": "^0.5.0", "@cypress-design/vue-tabs": "^0.5.1", "@graphql-typed-document-node/core": "^3.1.0", diff --git a/packages/app/src/debug/DebugPageHeader.cy.tsx b/packages/app/src/debug/DebugPageHeader.cy.tsx index 20a5b574ebb2..b5de9ddd2260 100644 --- a/packages/app/src/debug/DebugPageHeader.cy.tsx +++ b/packages/app/src/debug/DebugPageHeader.cy.tsx @@ -43,11 +43,11 @@ describe('', { cy.findByTestId('debug-results').should('be.visible') - cy.findByTestId('debug-runNumber-FAILED') + cy.findByTestId('runNumber-status-FAILED') .should('have.text', '#432') .children().should('have.length', 2) - cy.findByTestId('debug-flaky-badge') + cy.findByTestId('runResults-flakyBadge') .should('not.exist') defaults.forEach((obj) => { @@ -73,7 +73,7 @@ describe('', { }, }) - cy.findByTestId('debug-flaky-badge') + cy.findByTestId('runResults-flakyBadge') .contains(defaultMessages.specPage.flaky.badgeLabel) cy.findByTestId('total-flaky-tests') @@ -97,7 +97,7 @@ describe('', { }, }) - cy.findByTestId(`debug-runNumber-${status}`).should('be.visible') + cy.findByTestId(`runNumber-status-${status}`).should('be.visible') }) }) diff --git a/packages/app/src/debug/DebugPageHeader.vue b/packages/app/src/debug/DebugPageHeader.vue index 020eaffac4be..ee5f734d598b 100644 --- a/packages/app/src/debug/DebugPageHeader.vue +++ b/packages/app/src/debug/DebugPageHeader.vue @@ -51,12 +51,12 @@
  • - - @@ -92,7 +92,7 @@ v-if="debug.createdAt" data-cy="debug-header-createdAt" > - diff --git a/packages/app/src/debug/DebugRunNavigation.vue b/packages/app/src/debug/DebugRunNavigation.vue index ff2a1c4a260f..7bd9be4e92d2 100644 --- a/packages/app/src/debug/DebugRunNavigation.vue +++ b/packages/app/src/debug/DebugRunNavigation.vue @@ -38,12 +38,12 @@