codeceptjs 3.6.7 → 4.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/codecept.js +81 -84
- package/lib/actor.js +13 -13
- package/lib/ai.js +13 -10
- package/lib/assert/empty.js +21 -20
- package/lib/assert/equal.js +39 -37
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +47 -46
- package/lib/assert/throws.js +11 -13
- package/lib/assert/truth.js +22 -19
- package/lib/assert.js +2 -4
- package/lib/cli.js +49 -57
- package/lib/codecept.js +155 -142
- package/lib/colorUtils.js +3 -3
- package/lib/command/configMigrate.js +52 -58
- package/lib/command/definitions.js +89 -88
- package/lib/command/dryRun.js +68 -71
- package/lib/command/generate.js +188 -197
- package/lib/command/gherkin/init.js +16 -27
- package/lib/command/gherkin/snippets.js +20 -20
- package/lib/command/gherkin/steps.js +8 -8
- package/lib/command/info.js +38 -40
- package/lib/command/init.js +288 -290
- package/lib/command/interactive.js +32 -32
- package/lib/command/list.js +26 -26
- package/lib/command/run-multiple/chunk.js +5 -5
- package/lib/command/run-multiple/collection.js +3 -3
- package/lib/command/run-multiple/run.js +2 -6
- package/lib/command/run-multiple.js +93 -113
- package/lib/command/run-rerun.js +25 -20
- package/lib/command/run-workers.js +66 -64
- package/lib/command/run.js +29 -26
- package/lib/command/utils.js +65 -80
- package/lib/command/workers/runTests.js +10 -10
- package/lib/config.js +9 -10
- package/lib/container.js +48 -40
- package/lib/data/context.js +59 -60
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +29 -29
- package/lib/data/table.js +20 -26
- package/lib/dirname.js +5 -0
- package/lib/event.js +167 -163
- package/lib/heal.js +17 -13
- package/lib/helper/AI.js +41 -130
- package/lib/helper/ApiDataFactory.js +69 -73
- package/lib/helper/Appium.js +381 -412
- package/lib/helper/Expect.js +425 -0
- package/lib/helper/ExpectHelper.js +48 -40
- package/lib/helper/FileSystem.js +79 -80
- package/lib/helper/GraphQL.js +43 -44
- package/lib/helper/GraphQLDataFactory.js +50 -50
- package/lib/helper/JSONResponse.js +62 -65
- package/lib/helper/Mochawesome.js +28 -28
- package/lib/helper/MockServer.js +14 -12
- package/lib/helper/Nightmare.js +566 -662
- package/lib/helper/Playwright.js +1216 -1361
- package/lib/helper/Protractor.js +627 -663
- package/lib/helper/Puppeteer.js +1128 -1231
- package/lib/helper/REST.js +68 -159
- package/lib/helper/SoftExpectHelper.js +2 -2
- package/lib/helper/TestCafe.js +484 -490
- package/lib/helper/WebDriver.js +1156 -1297
- package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
- package/lib/helper/errors/ConnectionRefused.js +1 -1
- package/lib/helper/errors/ElementAssertion.js +2 -2
- package/lib/helper/errors/ElementNotFound.js +2 -2
- package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
- package/lib/helper/extras/Console.js +1 -1
- package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
- package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
- package/lib/helper/extras/PlaywrightRestartOpts.js +18 -21
- package/lib/helper/extras/Popup.js +1 -1
- package/lib/helper/extras/React.js +3 -3
- package/lib/helper/network/actions.js +7 -14
- package/lib/helper/network/utils.js +2 -3
- package/lib/helper/scripts/blurElement.js +1 -1
- package/lib/helper/scripts/focusElement.js +1 -1
- package/lib/helper/scripts/highlightElement.js +1 -1
- package/lib/helper/scripts/isElementClickable.js +1 -1
- package/lib/helper/testcafe/testControllerHolder.js +1 -1
- package/lib/helper/testcafe/testcafe-utils.js +7 -6
- package/lib/helper.js +3 -1
- package/lib/history.js +5 -6
- package/lib/hooks.js +6 -6
- package/lib/html.js +7 -7
- package/lib/index.js +41 -25
- package/lib/interfaces/bdd.js +64 -47
- package/lib/interfaces/featureConfig.js +19 -19
- package/lib/interfaces/gherkin.js +118 -124
- package/lib/interfaces/scenarioConfig.js +29 -29
- package/lib/listener/artifacts.js +9 -9
- package/lib/listener/config.js +24 -24
- package/lib/listener/exit.js +12 -12
- package/lib/listener/helpers.js +42 -42
- package/lib/listener/mocha.js +11 -11
- package/lib/listener/retry.js +30 -32
- package/lib/listener/steps.js +53 -50
- package/lib/listener/timeout.js +54 -54
- package/lib/locator.js +10 -6
- package/lib/mochaFactory.js +15 -18
- package/lib/output.js +10 -6
- package/lib/parser.js +12 -15
- package/lib/pause.js +33 -40
- package/lib/plugin/allure.js +15 -15
- package/lib/plugin/autoDelay.js +37 -29
- package/lib/plugin/autoLogin.js +65 -70
- package/lib/plugin/commentStep.js +18 -18
- package/lib/plugin/coverage.js +67 -115
- package/lib/plugin/customLocator.js +20 -21
- package/lib/plugin/debugErrors.js +24 -24
- package/lib/plugin/eachElement.js +38 -38
- package/lib/plugin/fakerTransform.js +6 -6
- package/lib/plugin/heal.js +108 -67
- package/lib/plugin/pauseOnFail.js +11 -11
- package/lib/plugin/retryFailedStep.js +39 -32
- package/lib/plugin/retryTo.js +40 -46
- package/lib/plugin/screenshotOnFail.js +87 -109
- package/lib/plugin/selenoid.js +118 -131
- package/lib/plugin/standardActingHelpers.js +8 -2
- package/lib/plugin/stepByStepReport.js +91 -110
- package/lib/plugin/stepTimeout.js +23 -24
- package/lib/plugin/subtitles.js +35 -34
- package/lib/plugin/tryTo.js +30 -40
- package/lib/plugin/wdio.js +75 -78
- package/lib/recorder.js +17 -14
- package/lib/rerun.js +10 -11
- package/lib/scenario.js +23 -25
- package/lib/secret.js +2 -4
- package/lib/session.js +10 -10
- package/lib/step.js +9 -12
- package/lib/store.js +3 -2
- package/lib/transform.js +1 -1
- package/lib/translation.js +8 -7
- package/lib/ui.js +14 -12
- package/lib/utils.js +72 -70
- package/lib/within.js +10 -10
- package/lib/workerStorage.js +25 -27
- package/lib/workers.js +32 -29
- package/package.json +53 -51
- package/translations/de-DE.js +1 -1
- package/translations/fr-FR.js +1 -1
- package/translations/index.js +13 -9
- package/translations/it-IT.js +1 -1
- package/translations/ja-JP.js +1 -1
- package/translations/pl-PL.js +1 -1
- package/translations/pt-BR.js +1 -1
- package/translations/ru-RU.js +1 -1
- package/translations/zh-CN.js +1 -1
- package/translations/zh-TW.js +1 -1
- package/typings/index.d.ts +65 -415
package/lib/plugin/heal.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
import colors from 'chalk';
|
|
3
|
+
import Container from '../container.js';
|
|
4
|
+
import AiAssistant from '../ai.js';
|
|
5
|
+
import recorder from '../recorder.js';
|
|
6
|
+
import * as event from '../event.js';
|
|
7
|
+
import * as output from '../output.js';
|
|
8
|
+
import supportedHelpers from './standardActingHelpers.js';
|
|
9
|
+
|
|
10
|
+
debug('codeceptjs:heal');
|
|
11
|
+
const heal = require('../heal');
|
|
12
|
+
const store = require('../store');
|
|
8
13
|
|
|
9
14
|
const defaultConfig = {
|
|
10
15
|
healLimit: 2,
|
|
11
|
-
}
|
|
16
|
+
};
|
|
12
17
|
|
|
13
18
|
/**
|
|
14
19
|
* Self-healing tests with AI.
|
|
@@ -28,94 +33,130 @@ const defaultConfig = {
|
|
|
28
33
|
* * `healLimit` - how many steps can be healed in a single test (default: 2)
|
|
29
34
|
*
|
|
30
35
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
|
|
37
|
+
export default function (config = {}) {
|
|
38
|
+
if (store.store.debugMode && !process.env.DEBUG) {
|
|
33
39
|
event.dispatcher.on(event.test.failed, () => {
|
|
34
|
-
output.plugin(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
)
|
|
38
|
-
})
|
|
39
|
-
return
|
|
40
|
+
output.output.plugin('heal', 'Healing is disabled in --debug mode, use DEBUG="codeceptjs:heal" to enable it in debug mode');
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
let currentTest = null
|
|
43
|
-
let currentStep = null
|
|
44
|
-
let healedSteps = 0
|
|
45
|
-
let caughtError
|
|
46
|
-
let healTries = 0
|
|
47
|
-
let isHealing = false
|
|
45
|
+
let currentTest = null;
|
|
46
|
+
let currentStep = null;
|
|
47
|
+
let healedSteps = 0;
|
|
48
|
+
let caughtError;
|
|
49
|
+
let healTries = 0;
|
|
50
|
+
let isHealing = false;
|
|
48
51
|
|
|
49
|
-
config = Object.assign(defaultConfig, config)
|
|
52
|
+
config = Object.assign(defaultConfig, config);
|
|
50
53
|
|
|
51
54
|
event.dispatcher.on(event.test.before, (test) => {
|
|
52
|
-
currentTest = test
|
|
53
|
-
healedSteps = 0
|
|
54
|
-
caughtError = null
|
|
55
|
-
})
|
|
55
|
+
currentTest = test;
|
|
56
|
+
healedSteps = 0;
|
|
57
|
+
caughtError = null;
|
|
58
|
+
});
|
|
56
59
|
|
|
57
|
-
event.dispatcher.on(event.step.started,
|
|
60
|
+
event.dispatcher.on(event.step.started, step => currentStep = step);
|
|
58
61
|
|
|
59
62
|
event.dispatcher.on(event.step.after, (step) => {
|
|
60
|
-
if (isHealing) return
|
|
61
|
-
if (
|
|
63
|
+
if (isHealing) return;
|
|
64
|
+
if (store.store.debugMode) return;
|
|
65
|
+
if (healTries >= config.healLimit) return; // out of limit
|
|
62
66
|
|
|
63
|
-
if (!heal.hasCorrespondingRecipes(step)) return
|
|
67
|
+
if (!heal.hasCorrespondingRecipes(step)) return;
|
|
64
68
|
|
|
65
69
|
recorder.catchWithoutStop(async (err) => {
|
|
66
|
-
isHealing = true
|
|
67
|
-
if (caughtError === err) throw err // avoid double handling
|
|
68
|
-
caughtError = err
|
|
70
|
+
isHealing = true;
|
|
71
|
+
if (caughtError === err) throw err; // avoid double handling
|
|
72
|
+
caughtError = err;
|
|
69
73
|
|
|
70
|
-
const test = currentTest
|
|
74
|
+
const test = currentTest;
|
|
71
75
|
|
|
72
|
-
recorder.session.start('heal')
|
|
76
|
+
recorder.session.start('heal');
|
|
73
77
|
|
|
74
|
-
debug('Self-healing started', step.toCode())
|
|
78
|
+
debug('Self-healing started', step.toCode());
|
|
75
79
|
|
|
76
|
-
await heal.healStep(step, err, { test })
|
|
80
|
+
await heal.healStep(step, err, { test });
|
|
77
81
|
|
|
78
|
-
healTries
|
|
82
|
+
healTries++;
|
|
79
83
|
|
|
80
84
|
recorder.add('close healing session', () => {
|
|
81
|
-
recorder.reset()
|
|
82
|
-
recorder.session.restore('heal')
|
|
83
|
-
recorder.ignoreErr(err)
|
|
84
|
-
})
|
|
85
|
-
await recorder.promise()
|
|
85
|
+
recorder.reset();
|
|
86
|
+
recorder.session.restore('heal');
|
|
87
|
+
recorder.ignoreErr(err);
|
|
88
|
+
});
|
|
89
|
+
await recorder.promise();
|
|
86
90
|
|
|
87
|
-
isHealing = false
|
|
88
|
-
})
|
|
89
|
-
})
|
|
91
|
+
isHealing = false;
|
|
92
|
+
});
|
|
93
|
+
});
|
|
90
94
|
|
|
91
95
|
event.dispatcher.on(event.all.result, () => {
|
|
92
|
-
if (!heal.fixes?.length) return
|
|
96
|
+
if (!heal.fixes?.length) return;
|
|
93
97
|
|
|
94
|
-
const { print } = output
|
|
98
|
+
const { print } = output;
|
|
95
99
|
|
|
96
|
-
print('')
|
|
97
|
-
print('===================')
|
|
98
|
-
print(colors.bold.green('Self-Healing Report:'))
|
|
100
|
+
print('');
|
|
101
|
+
print('===================');
|
|
102
|
+
print(colors.bold.green('Self-Healing Report:'));
|
|
99
103
|
|
|
100
|
-
print(`${colors.bold(heal.fixes.length)} ${heal.fixes.length === 1 ? 'step was' : 'steps were'} healed`)
|
|
104
|
+
print(`${colors.bold(heal.fixes.length)} ${heal.fixes.length === 1 ? 'step was' : 'steps were'} healed`);
|
|
101
105
|
|
|
102
|
-
const suggestions = heal.fixes.filter(
|
|
106
|
+
const suggestions = heal.fixes.filter(fix => fix.recipe && heal.recipes[fix.recipe].suggest);
|
|
103
107
|
|
|
104
|
-
if (!suggestions.length) return
|
|
108
|
+
if (!suggestions.length) return;
|
|
105
109
|
|
|
106
|
-
let i = 1
|
|
107
|
-
print('')
|
|
108
|
-
print('Suggested changes:')
|
|
109
|
-
print('')
|
|
110
|
+
let i = 1;
|
|
111
|
+
print('');
|
|
112
|
+
print('Suggested changes:');
|
|
113
|
+
print('');
|
|
110
114
|
|
|
111
115
|
for (const suggestion of suggestions) {
|
|
112
|
-
print(`${i}. To fix ${colors.bold.magenta(suggestion.test?.title)}`)
|
|
113
|
-
print(' Replace the failed code:', colors.gray(`(suggested by ${colors.bold(suggestion.recipe)})`))
|
|
114
|
-
print(colors.red(`- ${suggestion.step.toCode()}`))
|
|
115
|
-
print(colors.green(`+ ${suggestion.snippet}`))
|
|
116
|
-
print(suggestion.step.line())
|
|
117
|
-
print('')
|
|
118
|
-
i
|
|
116
|
+
print(`${i}. To fix ${colors.bold.magenta(suggestion.test?.title)}`);
|
|
117
|
+
print(' Replace the failed code:', colors.gray(`(suggested by ${colors.bold(suggestion.recipe)})`));
|
|
118
|
+
print(colors.red(`- ${suggestion.step.toCode()}`));
|
|
119
|
+
print(colors.green(`+ ${suggestion.snippet}`));
|
|
120
|
+
print(suggestion.step.line());
|
|
121
|
+
print('');
|
|
122
|
+
i++;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
async function tryToHeal(failedStep, err) {
|
|
127
|
+
output.output.debug(`Running OpenAI to heal ${failedStep.toCode()} step`);
|
|
128
|
+
|
|
129
|
+
const codeSnippets = await AiAssistant.healFailedStep(failedStep, err, currentTest);
|
|
130
|
+
|
|
131
|
+
output.output.debug(`Received ${codeSnippets.length} suggestions from OpenAI`);
|
|
132
|
+
const I = Container.support('I'); // eslint-disable-line
|
|
133
|
+
|
|
134
|
+
for (const codeSnippet of codeSnippets) {
|
|
135
|
+
try {
|
|
136
|
+
debug('Executing', codeSnippet);
|
|
137
|
+
recorder.catch((e) => {
|
|
138
|
+
console.log(e);
|
|
139
|
+
});
|
|
140
|
+
await eval(codeSnippet); // eslint-disable-line
|
|
141
|
+
|
|
142
|
+
let healSuggestions = [];
|
|
143
|
+
healSuggestions.push({
|
|
144
|
+
test: currentTest,
|
|
145
|
+
step: failedStep,
|
|
146
|
+
snippet: codeSnippet,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
recorder.add('healed', () => output.print(colors.bold.green(' Code healed successfully')));
|
|
150
|
+
healedSteps++;
|
|
151
|
+
return;
|
|
152
|
+
} catch (err) {
|
|
153
|
+
debug('Failed to execute code', err);
|
|
154
|
+
recorder.ignoreErr(err); // healing ded not help
|
|
155
|
+
// recorder.catch(() => output.print(colors.bold.red(' Failed healing code')));
|
|
156
|
+
}
|
|
119
157
|
}
|
|
120
|
-
|
|
158
|
+
|
|
159
|
+
output.output.debug(`Couldn't heal the code for ${failedStep.toCode()}`);
|
|
160
|
+
}
|
|
161
|
+
return recorder.promise();
|
|
121
162
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as event from '../event.js';
|
|
2
|
+
import pause from '../pause';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Automatically launches [interactive pause](/basics/#pause) when a test fails.
|
|
@@ -21,18 +21,18 @@ const pause = require('../pause')
|
|
|
21
21
|
* ```
|
|
22
22
|
*
|
|
23
23
|
*/
|
|
24
|
-
|
|
25
|
-
let failed = false
|
|
24
|
+
export default () => {
|
|
25
|
+
let failed = false;
|
|
26
26
|
|
|
27
27
|
event.dispatcher.on(event.test.started, () => {
|
|
28
|
-
failed = false
|
|
29
|
-
})
|
|
28
|
+
failed = false;
|
|
29
|
+
});
|
|
30
30
|
|
|
31
31
|
event.dispatcher.on(event.step.failed, () => {
|
|
32
|
-
failed = true
|
|
33
|
-
})
|
|
32
|
+
failed = true;
|
|
33
|
+
});
|
|
34
34
|
|
|
35
35
|
event.dispatcher.on(event.test.after, () => {
|
|
36
|
-
if (failed) pause()
|
|
37
|
-
})
|
|
38
|
-
}
|
|
36
|
+
if (failed) pause();
|
|
37
|
+
});
|
|
38
|
+
};
|
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import * as event from '../event.js';
|
|
2
|
+
import recorder from '../recorder.js';
|
|
3
|
+
import * as output from '../output.js';
|
|
4
|
+
|
|
5
|
+
import { store } from '../store.js';
|
|
5
6
|
|
|
6
7
|
const defaultConfig = {
|
|
7
8
|
retries: 3,
|
|
8
|
-
defaultIgnoredSteps: [
|
|
9
|
+
defaultIgnoredSteps: [
|
|
10
|
+
'amOnPage',
|
|
11
|
+
'wait*',
|
|
12
|
+
'send*',
|
|
13
|
+
'execute*',
|
|
14
|
+
'run*',
|
|
15
|
+
'have*',
|
|
16
|
+
],
|
|
9
17
|
factor: 1.5,
|
|
10
18
|
ignoredSteps: [],
|
|
11
|
-
}
|
|
19
|
+
};
|
|
12
20
|
|
|
13
21
|
/**
|
|
14
22
|
* Retries each failed step in a test.
|
|
@@ -76,46 +84,45 @@ const defaultConfig = {
|
|
|
76
84
|
* ```
|
|
77
85
|
*
|
|
78
86
|
*/
|
|
79
|
-
|
|
80
|
-
config = Object.assign(defaultConfig, config)
|
|
81
|
-
config.ignoredSteps = config.ignoredSteps.concat(config.defaultIgnoredSteps)
|
|
82
|
-
const customWhen = config.when
|
|
87
|
+
export default (config) => {
|
|
88
|
+
config = Object.assign(defaultConfig, config);
|
|
89
|
+
config.ignoredSteps = config.ignoredSteps.concat(config.defaultIgnoredSteps);
|
|
90
|
+
const customWhen = config.when;
|
|
83
91
|
|
|
84
|
-
let enableRetry = false
|
|
92
|
+
let enableRetry = false;
|
|
85
93
|
|
|
86
94
|
const when = (err) => {
|
|
87
|
-
if (!enableRetry) return
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
config.when = when
|
|
95
|
+
if (!enableRetry) return;
|
|
96
|
+
if (store.debugMode) return false;
|
|
97
|
+
if (customWhen) return customWhen(err);
|
|
98
|
+
return true;
|
|
99
|
+
};
|
|
100
|
+
config.when = when;
|
|
94
101
|
|
|
95
102
|
event.dispatcher.on(event.step.started, (step) => {
|
|
96
103
|
if (process.env.TRY_TO === 'true') {
|
|
97
|
-
log('Info: RetryFailedStep plugin is disabled inside tryTo block')
|
|
98
|
-
return
|
|
104
|
+
output.output.log('Info: RetryFailedStep plugin is disabled inside tryTo block');
|
|
105
|
+
return;
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
// if a step is ignored - return
|
|
102
109
|
for (const ignored of config.ignoredSteps) {
|
|
103
|
-
if (step.name === ignored) return
|
|
110
|
+
if (step.name === ignored) return;
|
|
104
111
|
if (ignored instanceof RegExp) {
|
|
105
|
-
if (step.name.match(ignored)) return
|
|
106
|
-
} else if (ignored.indexOf('*') && step.name.startsWith(ignored.slice(0, -1))) return
|
|
112
|
+
if (step.name.match(ignored)) return;
|
|
113
|
+
} else if (ignored.indexOf('*') && step.name.startsWith(ignored.slice(0, -1))) return;
|
|
107
114
|
}
|
|
108
|
-
enableRetry = true // enable retry for a step
|
|
109
|
-
})
|
|
115
|
+
enableRetry = true; // enable retry for a step
|
|
116
|
+
});
|
|
110
117
|
|
|
111
118
|
event.dispatcher.on(event.step.finished, () => {
|
|
112
|
-
enableRetry = false
|
|
113
|
-
})
|
|
119
|
+
enableRetry = false;
|
|
120
|
+
});
|
|
114
121
|
|
|
115
122
|
event.dispatcher.on(event.test.before, (test) => {
|
|
116
|
-
if (test && test.disableRetryFailedStep) return // disable retry when a test is not active
|
|
123
|
+
if (test && test.disableRetryFailedStep) return; // disable retry when a test is not active
|
|
117
124
|
// this env var is used to set the retries inside _before() block of helpers
|
|
118
|
-
process.env.FAILED_STEP_RETRIES = config.retries
|
|
119
|
-
recorder.retry(config)
|
|
120
|
-
})
|
|
121
|
-
}
|
|
125
|
+
process.env.FAILED_STEP_RETRIES = config.retries;
|
|
126
|
+
recorder.retry(config);
|
|
127
|
+
});
|
|
128
|
+
};
|
package/lib/plugin/retryTo.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import recorder from '../recorder.js';
|
|
2
|
+
import * as output from '../output.js';
|
|
3
3
|
|
|
4
4
|
const defaultConfig = {
|
|
5
5
|
registerGlobal: true,
|
|
6
6
|
pollInterval: 200,
|
|
7
|
-
}
|
|
7
|
+
};
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
*
|
|
@@ -72,56 +72,50 @@ const defaultConfig = {
|
|
|
72
72
|
* const retryTo = codeceptjs.container.plugins('retryTo');
|
|
73
73
|
* ```
|
|
74
74
|
*
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
config = Object.assign(defaultConfig, config)
|
|
78
|
-
function retryTo(callback, maxTries, pollInterval = config.pollInterval) {
|
|
79
|
-
return new Promise((done, reject) => {
|
|
80
|
-
let tries = 1
|
|
75
|
+
*/
|
|
76
|
+
export default function (config) {
|
|
77
|
+
config = Object.assign(defaultConfig, config);
|
|
81
78
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
if (config.registerGlobal) {
|
|
80
|
+
// @ts-ignore
|
|
81
|
+
global.retryTo = retryTo;
|
|
82
|
+
}
|
|
83
|
+
return retryTo;
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
try {
|
|
91
|
-
await callback(tries)
|
|
92
|
-
} catch (err) {
|
|
93
|
-
handleRetryException(err)
|
|
94
|
-
}
|
|
85
|
+
function retryTo(callback, maxTries, pollInterval = undefined) {
|
|
86
|
+
let tries = 1;
|
|
87
|
+
if (!pollInterval) pollInterval = config.pollInterval;
|
|
95
88
|
|
|
96
|
-
|
|
97
|
-
recorder.add(() => {
|
|
98
|
-
recorder.session.restore(`retryTo ${tries}`)
|
|
99
|
-
done(null)
|
|
100
|
-
})
|
|
89
|
+
let err = null;
|
|
101
90
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
91
|
+
return new Promise((done) => {
|
|
92
|
+
const tryBlock = async () => {
|
|
93
|
+
recorder.session.start(`retryTo ${tries}`);
|
|
94
|
+
await callback(tries);
|
|
95
|
+
recorder.add(() => {
|
|
96
|
+
recorder.session.restore(`retryTo ${tries}`);
|
|
97
|
+
done(null);
|
|
98
|
+
});
|
|
99
|
+
recorder.session.catch((e) => {
|
|
100
|
+
err = e;
|
|
101
|
+
recorder.session.restore(`retryTo ${tries}`);
|
|
102
|
+
tries++;
|
|
105
103
|
if (tries <= maxTries) {
|
|
106
|
-
debug(`Error ${err}... Retrying`)
|
|
107
|
-
|
|
104
|
+
output.output.debug(`Error ${err}... Retrying`);
|
|
105
|
+
err = null;
|
|
106
|
+
|
|
107
|
+
recorder.add(`retryTo ${tries}`, () => setTimeout(tryBlock, pollInterval));
|
|
108
108
|
} else {
|
|
109
|
-
|
|
110
|
-
handleRetryException(err)
|
|
109
|
+
done(null);
|
|
111
110
|
}
|
|
112
|
-
})
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
recorder.add('retryTo', tryBlock).catch((err) => {
|
|
116
|
-
console.error('An error occurred:', err)
|
|
117
|
-
done(null)
|
|
118
|
-
})
|
|
119
|
-
})
|
|
120
|
-
}
|
|
111
|
+
});
|
|
112
|
+
};
|
|
121
113
|
|
|
122
|
-
|
|
123
|
-
|
|
114
|
+
recorder.add('retryTo', async () => {
|
|
115
|
+
tryBlock();
|
|
116
|
+
});
|
|
117
|
+
}).then(() => {
|
|
118
|
+
if (err) recorder.throw(err);
|
|
119
|
+
});
|
|
124
120
|
}
|
|
125
|
-
|
|
126
|
-
return retryTo
|
|
127
121
|
}
|