diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index e26eae8263ef..efd1e1bed3e8 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -6,6 +6,7 @@ _Released 10/1/2024 (PENDING)_ **Misc:** - Cypress now consumes [geckodriver](https://firefox-source-docs.mozilla.org/testing/geckodriver/index.html) to help automate the Firefox browser instead of [marionette-client](https://github.com/cypress-io/marionette-client). Addresses [#30217](https://github.com/cypress-io/cypress/issues/30217). +- Pass spec information to protocol's `beforeSpec` to improve troubleshooting when reporting on errors. Addressed in [#30316](https://github.com/cypress-io/cypress/pull/30316). ## 13.15.0 diff --git a/packages/server/lib/cloud/protocol.ts b/packages/server/lib/cloud/protocol.ts index d017f483e7c1..1c33e8ed06e4 100644 --- a/packages/server/lib/cloud/protocol.ts +++ b/packages/server/lib/cloud/protocol.ts @@ -14,7 +14,7 @@ import env from '../util/env' import { putProtocolArtifact } from './api/put_protocol_artifact' import type { Readable } from 'stream' -import type { ProtocolManagerShape, AppCaptureProtocolInterface, CDPClient, ProtocolError, CaptureArtifact, ProtocolErrorReport, ProtocolCaptureMethod, ProtocolManagerOptions, ResponseStreamOptions, ResponseEndedWithEmptyBodyOptions, ResponseStreamTimedOutOptions, AfterSpecDurations } from '@packages/types' +import type { ProtocolManagerShape, AppCaptureProtocolInterface, CDPClient, ProtocolError, CaptureArtifact, ProtocolErrorReport, ProtocolCaptureMethod, ProtocolManagerOptions, ResponseStreamOptions, ResponseEndedWithEmptyBodyOptions, ResponseStreamTimedOutOptions, AfterSpecDurations, SpecWithRelativeRoot } from '@packages/types' const routes = require('./routes') @@ -133,7 +133,7 @@ export class ProtocolManager implements ProtocolManagerShape { this.invokeSync('addRunnables', { isEssential: true }, runnables) } - beforeSpec (spec: { instanceId: string }) { + beforeSpec (spec: SpecWithRelativeRoot & { instanceId: string }) { this._afterSpecDurations = undefined if (!this._protocol) { @@ -157,7 +157,7 @@ export class ProtocolManager implements ProtocolManagerShape { } } - private _beforeSpec (spec: { instanceId: string }) { + private _beforeSpec (spec: SpecWithRelativeRoot & { instanceId: string }) { this._instanceId = spec.instanceId const cypressProtocolDirectory = path.join(os.tmpdir(), 'cypress', 'protocol') const archivePath = path.join(cypressProtocolDirectory, `${spec.instanceId}.tar`) @@ -172,7 +172,7 @@ export class ProtocolManager implements ProtocolManagerShape { this._db = db this._archivePath = archivePath - this.invokeSync('beforeSpec', { isEssential: true }, { workingDirectory: cypressProtocolDirectory, archivePath, dbPath, db }) + this.invokeSync('beforeSpec', { isEssential: true }, { workingDirectory: cypressProtocolDirectory, archivePath, dbPath, db, spec }) } async afterSpec () { diff --git a/packages/server/test/unit/cloud/protocol_spec.ts b/packages/server/test/unit/cloud/protocol_spec.ts index 559cf067d7fb..e68b79a169bb 100644 --- a/packages/server/test/unit/cloud/protocol_spec.ts +++ b/packages/server/test/unit/cloud/protocol_spec.ts @@ -90,9 +90,20 @@ describe('lib/cloud/protocol', () => { }, ] - protocolManager.beforeSpec({ + const spec = { instanceId: 'instanceId', - }) + absolute: '/path/to/spec', + relative: 'spec', + relativeToCommonRoot: 'common/root', + specFileExtension: '.ts', + fileExtension: '.ts', + specType: 'integration' as Cypress.CypressSpecType, + baseName: 'spec', + name: 'spec', + fileName: 'spec.ts', + } + + protocolManager.beforeSpec(spec) expect((protocolManager as any)._errors).to.be.empty @@ -101,6 +112,7 @@ describe('lib/cloud/protocol', () => { archivePath: path.join(os.tmpdir(), 'cypress', 'protocol', 'instanceId.tar'), dbPath: path.join(os.tmpdir(), 'cypress', 'protocol', 'instanceId.db'), db: mockDb, + spec, }) expect(mockDatabase).to.be.calledWith(path.join(os.tmpdir(), 'cypress', 'protocol', 'instanceId.db'), { diff --git a/packages/types/src/protocol.ts b/packages/types/src/protocol.ts index ac81cb2e35e6..85948e9296c7 100644 --- a/packages/types/src/protocol.ts +++ b/packages/types/src/protocol.ts @@ -3,6 +3,7 @@ import type ProtocolMapping from 'devtools-protocol/types/protocol-mapping' import type { IncomingHttpHeaders } from 'http' import type { Readable } from 'stream' import type { ProxyTimings } from './proxy' +import type { SpecWithRelativeRoot } from './spec' type Commands = ProtocolMapping.Commands type Command = Commands[T] @@ -38,7 +39,7 @@ export interface AppCaptureProtocolCommon { export interface AppCaptureProtocolInterface extends AppCaptureProtocolCommon { getDbMetadata (): { offset: number, size: number } | undefined - beforeSpec ({ workingDirectory, archivePath, dbPath, db }: { workingDirectory: string, archivePath: string, dbPath: string, db: Database }): void + beforeSpec ({ spec, workingDirectory, archivePath, dbPath, db }: { spec: SpecWithRelativeRoot & { instanceId: string }, workingDirectory: string, archivePath: string, dbPath: string, db: Database }): void uploadStallSamplingInterval: () => number } @@ -117,7 +118,7 @@ export interface ProtocolManagerShape extends AppCaptureProtocolCommon { protocolEnabled: boolean networkEnableOptions?: { maxTotalBufferSize: number, maxResourceBufferSize: number, maxPostDataSize: number } setupProtocol(script: string, options: ProtocolManagerOptions): Promise - beforeSpec (spec: { instanceId: string }): void + beforeSpec (spec: SpecWithRelativeRoot & { instanceId: string }): void afterSpec (): Promise<{ durations: AfterSpecDurations } | undefined> reportNonFatalErrors (clientMetadata: any): Promise uploadCaptureArtifact(artifact: CaptureArtifact): Promise