diff --git a/lib/actor.js b/lib/actor.js index 3ba3895d6..f7da29e53 100644 --- a/lib/actor.js +++ b/lib/actor.js @@ -49,8 +49,10 @@ module.exports = function (obj) { function retryStep(opts) { if (opts === undefined) opts = 1; recorder.retry(opts); + // adding an empty promise to clear retries + recorder.add(_ => null); // remove retry once the step passed - recorder.add(_ => event.dispatcher.once(event.step.passed, _ => recorder.retries.pop())); + recorder.add(_ => event.dispatcher.once(event.step.finished, _ => recorder.retries.pop())); return this; } diff --git a/test/data/sandbox/flaky_test.retry.js b/test/data/sandbox/flaky_test.retry.js index c0fd5668f..53835f600 100644 --- a/test/data/sandbox/flaky_test.retry.js +++ b/test/data/sandbox/flaky_test.retry.js @@ -1,15 +1,32 @@ const assert = require('assert'); +const recorder = codeceptjs.recorder; + let tries = 0; Feature('Retry'); -Scenario('flaky step', async (I) => { +Scenario('flaky step @test1', async (I) => { tries++; await I.retry(3).failWhen(() => { tries++; return tries < 4; }); assert.equal(tries, 4); +}); + +Scenario('flaky step passed globally @test2', (I) => { + recorder.retry({ + retries: 3, + when: err => false, + }); + I.retry(5).asyncStep(); + I.failWhen(() => { + tries++; + return tries < 4; + }); +}); + +After(() => { console.log(`[T] Retries: ${tries}`); }); diff --git a/test/data/sandbox/retry_helper.js b/test/data/sandbox/retry_helper.js index b6081c868..c1ca038c6 100644 --- a/test/data/sandbox/retry_helper.js +++ b/test/data/sandbox/retry_helper.js @@ -8,6 +8,10 @@ class Retry extends Helper { waitForFail(fn) { if (fn()) throw new Error('ups, error'); } + + asyncStep() { + return new Promise(resolve => setTimeout(resolve, 500)); + } } module.exports = Retry; diff --git a/test/runner/interface_test.js b/test/runner/interface_test.js index f2408feff..4e810fb48 100644 --- a/test/runner/interface_test.js +++ b/test/runner/interface_test.js @@ -27,7 +27,7 @@ describe('CodeceptJS Interface', () => { }); it('should rerun retried steps', (done) => { - exec(config_run_config('codecept.retry.json'), (err, stdout, stderr) => { + exec(`${config_run_config('codecept.retry.json')} --grep @test1`, (err, stdout, stderr) => { stdout.should.include('Retry'); // feature stdout.should.include('Retries: 4'); // test name assert(!err); @@ -35,6 +35,14 @@ describe('CodeceptJS Interface', () => { }); }); + it('should not propagate retries to non retried steps', (done) => { + exec(`${config_run_config('codecept.retry.json')} --grep @test2 --verbose`, (err, stdout, stderr) => { + stdout.should.include('Retry'); // feature + stdout.should.include('Retries: 1'); // test name + assert(err); + done(); + }); + }); it('should use retryFailedStep plugin for failed steps', (done) => { exec(`${config_run_config('codecept.retryFailed.json')} --grep @test1`, (err, stdout, stderr) => {