From 0ce4a285d2f1b2256f1385d13c05f078e7b86cc0 Mon Sep 17 00:00:00 2001 From: Jaromir Obr Date: Sat, 25 Oct 2025 13:39:01 +0000 Subject: [PATCH] fix: handle missing opts in retryFailedStep plugin (Shell: Command fails: TypeError: Chaining cycle detected for promise Fixes #4844) --- lib/plugin/retryFailedStep.js | 1 + .../retryFailedStep_interactive_shell_test.js | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 test/unit/plugin/retryFailedStep_interactive_shell_test.js diff --git a/lib/plugin/retryFailedStep.js b/lib/plugin/retryFailedStep.js index 6d43bf8da..1bf29641c 100644 --- a/lib/plugin/retryFailedStep.js +++ b/lib/plugin/retryFailedStep.js @@ -108,6 +108,7 @@ module.exports = config => { event.dispatcher.on(event.test.before, test => { // pass disableRetryFailedStep is a preferred way to disable retries // test.disableRetryFailedStep is used for backward compatibility + if (!test.opts) test.opts = {} if (test.opts.disableRetryFailedStep || test.disableRetryFailedStep) { store.autoRetries = false return // disable retry when a test is not active diff --git a/test/unit/plugin/retryFailedStep_interactive_shell_test.js b/test/unit/plugin/retryFailedStep_interactive_shell_test.js new file mode 100644 index 000000000..a0b284412 --- /dev/null +++ b/test/unit/plugin/retryFailedStep_interactive_shell_test.js @@ -0,0 +1,25 @@ +const assert = require('assert') +const event = require('../../../lib/event') +const retryFailedStep = require('../../../lib/plugin/retryFailedStep') + +describe('retryFailedStep plugin (interactive shell regression)', () => { + beforeEach(() => { + // Remove all listeners to avoid side effects + event.cleanDispatcher() + // Re-register plugin + retryFailedStep({ enabled: true }) + }) + + it('should not throw when test.before is emitted without opts (interactive shell)', () => { + // Simulate the event as emitted by the interactive shell (no opts) + assert.doesNotThrow(() => { + event.dispatcher.emit(event.test.before, { title: 'Interactive', artifacts: {} }) + }) + }) + + it('should not throw when test.before is emitted with opts', () => { + assert.doesNotThrow(() => { + event.dispatcher.emit(event.test.before, { title: 'Normal', artifacts: {}, opts: {} }) + }) + }) +})