From e3d1d5b646eaf3c07fb8d253865c48af857683df Mon Sep 17 00:00:00 2001 From: Ryan Manuel Date: Sat, 25 Oct 2025 07:19:20 -0500 Subject: [PATCH] fix: (cy.prompt) add more context to the error message shown when cy.prompt() fails to download (#32822) --- cli/CHANGELOG.md | 1 + .../cy-prompt/CyPromptLifecycleManager.ts | 6 +- .../CyPromptLifecycleManager_spec.ts | 79 +++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 4af8d8bd1c..734f96fa73 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -12,6 +12,7 @@ _Released 10/20/2025 (PENDING)_ - Fixed an issue where grouped command text jumps up and down when expanding and collapsing in the command log. Addressed in [#32757](https://github.com/cypress-io/cypress/pull/32757). - Fixed an issue where command snapshots were not correctly displayed in Studio. Addressed in [#32808](https://github.com/cypress-io/cypress/pull/32808). - Fixed an issue with grouped console prop items having a hard to read blue color in the console log and duplicate `:` characters being displayed. Addressed in [#32776](https://github.com/cypress-io/cypress/pull/32776). +- Added more context to the error message shown when `cy.prompt()` fails to download. Addressed in [#32822](https://github.com/cypress-io/cypress/pull/32822). **Misc:** diff --git a/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts b/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts index efb2a7cbd0..2fd5f212f8 100644 --- a/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts +++ b/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts @@ -88,6 +88,8 @@ export class CyPromptLifecycleManager { const cloudUrl = ctx.cloud.getCloudUrl(cloudEnv) const cloudHeaders = await ctx.cloud.additionalHeaders() + const lastError = error instanceof AggregateError ? error.errors[error.errors.length - 1] : error + reportCyPromptError({ cloudApi: { cloudUrl, @@ -99,7 +101,7 @@ export class CyPromptLifecycleManager { additionalHeaders: cloudHeaders, cyPromptHash: this.cyPromptHash, projectSlug: (await ctx.project.getConfig()).projectId || undefined, - error, + error: lastError, cyPromptMethod: 'initializeCyPromptManager', cyPromptMethodArgs: [], }) @@ -107,7 +109,7 @@ export class CyPromptLifecycleManager { // Clean up any registered listeners this.listeners = [] - return { error } + return { error: lastError } }) this.cyPromptManagerPromise = cyPromptManagerPromise diff --git a/packages/server/test/unit/cloud/cy-prompt/CyPromptLifecycleManager_spec.ts b/packages/server/test/unit/cloud/cy-prompt/CyPromptLifecycleManager_spec.ts index 762981dda3..7ceae9b79c 100644 --- a/packages/server/test/unit/cloud/cy-prompt/CyPromptLifecycleManager_spec.ts +++ b/packages/server/test/unit/cloud/cy-prompt/CyPromptLifecycleManager_spec.ts @@ -566,6 +566,85 @@ describe('CyPromptLifecycleManager', () => { }, }) }) + + it('handles errors from ensureCyPromptBundle', async () => { + const actualError = new Error('Test error') + + ensureCyPromptBundleStub.rejects(actualError) + cyPromptLifecycleManager.initializeCyPromptManager({ + cloudDataSource: mockCloudDataSource, + ctx: mockCtx, + record: false, + key: '123e4567-e89b-12d3-a456-426614174000', + }) + + // @ts-expect-error - accessing private property + const cyPromptPromise = cyPromptLifecycleManager.cyPromptManagerPromise + + expect(cyPromptPromise).to.not.be.null + + const { error } = (await cyPromptPromise) as { error: Error } + + expect(error.message).to.equal('Test error') + + expect(reportCyPromptErrorStub).to.be.calledWith({ + cloudApi: { + cloudUrl: 'https://cloud.cypress.io', + CloudRequest, + createCloudRequest, + isRetryableError, + asyncRetry, + }, + cyPromptHash: 'abc', + projectSlug: 'test-project-id', + error: actualError, + cyPromptMethod: 'initializeCyPromptManager', + cyPromptMethodArgs: [], + additionalHeaders: { + 'Authorization': 'Bearer test-token', + }, + }) + }) + + it('handles AggregateErrors from ensureCyPromptBundle', async () => { + const aggregateError = new AggregateError([new Error('Test error'), new Error('Second error')], 'Multiple errors') + + ensureCyPromptBundleStub.rejects(aggregateError) + + cyPromptLifecycleManager.initializeCyPromptManager({ + cloudDataSource: mockCloudDataSource, + ctx: mockCtx, + record: false, + key: '123e4567-e89b-12d3-a456-426614174000', + }) + + // @ts-expect-error - accessing private property + const cyPromptPromise = cyPromptLifecycleManager.cyPromptManagerPromise + + expect(cyPromptPromise).to.not.be.null + + const { error } = (await cyPromptPromise) as { error: Error } + + expect(error.message).to.equal('Second error') + + expect(reportCyPromptErrorStub).to.be.calledWith({ + cloudApi: { + cloudUrl: 'https://cloud.cypress.io', + CloudRequest, + createCloudRequest, + isRetryableError, + asyncRetry, + }, + cyPromptHash: 'abc', + projectSlug: 'test-project-id', + error: aggregateError.errors[aggregateError.errors.length - 1], + cyPromptMethod: 'initializeCyPromptManager', + cyPromptMethodArgs: [], + additionalHeaders: { + 'Authorization': 'Bearer test-token', + }, + }) + }) }) describe('getCyPrompt', () => {