codeceptjs 3.3.8-beta.1 → 3.4.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +31 -32
  3. package/docs/advanced.md +48 -24
  4. package/docs/basics.md +115 -40
  5. package/docs/best.md +2 -2
  6. package/docs/build/ApiDataFactory.js +6 -6
  7. package/docs/build/Appium.js +2 -19
  8. package/docs/build/FileSystem.js +2 -2
  9. package/docs/build/GraphQLDataFactory.js +2 -2
  10. package/docs/build/Playwright.js +3 -2
  11. package/docs/build/TestCafe.js +4 -4
  12. package/docs/build/WebDriver.js +29 -164
  13. package/docs/helpers/ApiDataFactory.md +6 -6
  14. package/docs/helpers/FileSystem.md +2 -2
  15. package/docs/helpers/GraphQLDataFactory.md +2 -2
  16. package/docs/helpers/Playwright.md +2 -1
  17. package/docs/index.md +1 -1
  18. package/docs/plugins.md +73 -48
  19. package/docs/reports.md +0 -56
  20. package/docs/typescript.md +2 -8
  21. package/lib/actor.js +2 -1
  22. package/lib/cli.js +3 -3
  23. package/lib/codecept.js +2 -1
  24. package/lib/command/generate.js +3 -1
  25. package/lib/command/gherkin/snippets.js +8 -4
  26. package/lib/command/init.js +0 -8
  27. package/lib/command/run-workers.js +3 -6
  28. package/lib/command/utils.js +0 -10
  29. package/lib/command/workers/runTests.js +2 -2
  30. package/lib/config.js +5 -1
  31. package/lib/helper/ApiDataFactory.js +7 -7
  32. package/lib/helper/Appium.js +2 -19
  33. package/lib/helper/FileSystem.js +3 -3
  34. package/lib/helper/GraphQL.js +1 -1
  35. package/lib/helper/GraphQLDataFactory.js +3 -3
  36. package/lib/helper/JSONResponse.js +1 -1
  37. package/lib/helper/Mochawesome.js +1 -1
  38. package/lib/helper/Nightmare.js +1 -1
  39. package/lib/helper/Playwright.js +4 -3
  40. package/lib/helper/Protractor.js +1 -1
  41. package/lib/helper/Puppeteer.js +1 -1
  42. package/lib/helper/REST.js +1 -1
  43. package/lib/helper/TestCafe.js +5 -5
  44. package/lib/helper/WebDriver.js +30 -165
  45. package/lib/helper.js +0 -2
  46. package/lib/interfaces/bdd.js +1 -1
  47. package/lib/interfaces/featureConfig.js +1 -0
  48. package/lib/interfaces/gherkin.js +38 -25
  49. package/lib/listener/exit.js +2 -2
  50. package/lib/listener/retry.js +67 -0
  51. package/lib/listener/steps.js +1 -1
  52. package/lib/listener/timeout.js +47 -10
  53. package/lib/mochaFactory.js +3 -3
  54. package/lib/plugin/allure.js +14 -323
  55. package/lib/plugin/fakerTransform.js +2 -2
  56. package/lib/recorder.js +1 -1
  57. package/lib/scenario.js +25 -18
  58. package/lib/utils.js +6 -0
  59. package/lib/workers.js +4 -7
  60. package/package.json +13 -17
  61. package/typings/index.d.ts +66 -1
  62. package/typings/promiseBasedTypes.d.ts +12 -12
  63. package/typings/types.d.ts +95 -262
@@ -1,4 +1,5 @@
1
- const { Parser } = require('gherkin');
1
+ const Gherkin = require('@cucumber/gherkin');
2
+ const Messages = require('@cucumber/messages');
2
3
  const { Context, Suite, Test } = require('mocha');
3
4
 
4
5
  const { matchStep } = require('./bdd');
@@ -8,7 +9,10 @@ const Step = require('../step');
8
9
  const DataTableArgument = require('../data/dataTableArgument');
9
10
  const transform = require('../transform');
10
11
 
11
- const parser = new Parser();
12
+ const uuidFn = Messages.IdGenerator.uuid();
13
+ const builder = new Gherkin.AstBuilder(uuidFn);
14
+ const matcher = new Gherkin.GherkinClassicTokenMatcher();
15
+ const parser = new Gherkin.Parser(builder, matcher);
12
16
  parser.stopAtFirstError = false;
13
17
 
14
18
  module.exports = (text, file) => {
@@ -46,14 +50,20 @@ module.exports = (text, file) => {
46
50
  step.metaStep = metaStep;
47
51
  };
48
52
  const fn = matchStep(step.text);
49
- if (step.argument) {
50
- step.argument.parse = () => {
51
- return new DataTableArgument(step.argument);
52
- };
53
- fn.params.push(step.argument);
54
- if (step.argument.type === 'DataTable') metaStep.comment = `\n${transformTable(step.argument)}`;
55
- if (step.argument.content) metaStep.comment = `\n${step.argument.content}`;
53
+
54
+ if (step.dataTable) {
55
+ fn.params.push({
56
+ ...step.dataTable,
57
+ parse: () => new DataTableArgument(step.dataTable),
58
+ });
59
+ metaStep.comment = `\n${transformTable(step.dataTable)}`;
60
+ }
61
+
62
+ if (step.docString) {
63
+ fn.params.push(step.docString);
64
+ metaStep.comment = `\n"""\n${step.docString.content}\n"""`;
56
65
  }
66
+
57
67
  step.startTime = Date.now();
58
68
  step.match = fn.line;
59
69
  event.emit(event.bddStep.before, step);
@@ -74,15 +84,15 @@ module.exports = (text, file) => {
74
84
  };
75
85
 
76
86
  for (const child of ast.feature.children) {
77
- if (child.type === 'Background') {
78
- suite.beforeEach('Before', scenario.injected(async () => runSteps(child.steps), suite, 'before'));
87
+ if (child.background) {
88
+ suite.beforeEach('Before', scenario.injected(async () => runSteps(child.background.steps), suite, 'before'));
79
89
  continue;
80
90
  }
81
- if (child.type === 'ScenarioOutline') {
82
- for (const examples of child.examples) {
91
+ if (child.scenario && child.scenario.keyword === 'Scenario Outline') {
92
+ for (const examples of child.scenario.examples) {
83
93
  const fields = examples.tableHeader.cells.map(c => c.value);
84
94
  for (const example of examples.tableBody) {
85
- let exampleSteps = [...child.steps];
95
+ let exampleSteps = [...child.scenario.steps];
86
96
  const current = {};
87
97
  for (const index in example.cells) {
88
98
  const placeholder = fields[index];
@@ -95,8 +105,8 @@ module.exports = (text, file) => {
95
105
  return step;
96
106
  });
97
107
  }
98
- const tags = child.tags.map(t => t.name).concat(examples.tags.map(t => t.name));
99
- const title = `${child.name} ${JSON.stringify(current)} ${tags.join(' ')}`.trim();
108
+ const tags = child.scenario.tags.map(t => t.name).concat(examples.tags.map(t => t.name));
109
+ const title = `${child.scenario.name} ${JSON.stringify(current)} ${tags.join(' ')}`.trim();
100
110
  const test = new Test(title, async () => runSteps(addExampleInTable(exampleSteps, current)));
101
111
  test.tags = suite.tags.concat(tags);
102
112
  test.file = file;
@@ -105,12 +115,15 @@ module.exports = (text, file) => {
105
115
  }
106
116
  continue;
107
117
  }
108
- const tags = child.tags.map(t => t.name);
109
- const title = `${child.name} ${tags.join(' ')}`.trim();
110
- const test = new Test(title, async () => runSteps(child.steps));
111
- test.tags = suite.tags.concat(tags);
112
- test.file = file;
113
- suite.addTest(scenario.test(test));
118
+
119
+ if (child.scenario) {
120
+ const tags = child.scenario.tags.map(t => t.name);
121
+ const title = `${child.scenario.name} ${tags.join(' ')}`.trim();
122
+ const test = new Test(title, async () => runSteps(child.scenario.steps));
123
+ test.tags = suite.tags.concat(tags);
124
+ test.file = file;
125
+ suite.addTest(scenario.test(test));
126
+ }
114
127
  }
115
128
 
116
129
  return suite;
@@ -130,9 +143,9 @@ function addExampleInTable(exampleSteps, placeholders) {
130
143
  for (const placeholder in placeholders) {
131
144
  steps.map((step) => {
132
145
  step = { ...step };
133
- if (step.argument && step.argument.type === 'DataTable') {
134
- for (const id in step.argument.rows) {
135
- const cells = step.argument.rows[id].cells;
146
+ if (step.dataTable) {
147
+ for (const id in step.dataTable.rows) {
148
+ const cells = step.dataTable.rows[id].cells;
136
149
  cells.map(c => (c.value = c.value.replace(`<${placeholder}>`, placeholders[placeholder])));
137
150
  }
138
151
  }
@@ -6,7 +6,7 @@ module.exports = function () {
6
6
  event.dispatcher.on(event.test.failed, (testOrSuite) => {
7
7
  // NOTE When an error happens in one of the hooks (BeforeAll/BeforeEach...) the event object
8
8
  // is a suite and not a test
9
- const id = testOrSuite.id || (testOrSuite.ctx && testOrSuite.ctx.test.id) || 'empty';
9
+ const id = testOrSuite.uid || (testOrSuite.ctx && testOrSuite.ctx.test.uid) || 'empty';
10
10
  failedTests.push(id);
11
11
  });
12
12
 
@@ -14,7 +14,7 @@ module.exports = function () {
14
14
  event.dispatcher.on(event.test.passed, (testOrSuite) => {
15
15
  // NOTE When an error happens in one of the hooks (BeforeAll/BeforeEach...) the event object
16
16
  // is a suite and not a test
17
- const id = testOrSuite.id || (testOrSuite.ctx && testOrSuite.ctx.test.id) || 'empty';
17
+ const id = testOrSuite.uid || (testOrSuite.ctx && testOrSuite.ctx.test.uid) || 'empty';
18
18
  failedTests = failedTests.filter(failed => id !== failed);
19
19
  });
20
20
 
@@ -0,0 +1,67 @@
1
+ const event = require('../event');
2
+ const output = require('../output');
3
+ const Config = require('../config');
4
+ const { isNotSet } = require('../utils');
5
+
6
+ const hooks = ['Before', 'After', 'BeforeSuite', 'AfterSuite'];
7
+
8
+ module.exports = function () {
9
+ event.dispatcher.on(event.suite.before, (suite) => {
10
+ let retryConfig = Config.get('retry');
11
+ if (!retryConfig) return;
12
+
13
+ if (Number.isInteger(+retryConfig)) {
14
+ // is number
15
+ const retryNum = +retryConfig;
16
+ output.log(`Retries: ${retryNum}`);
17
+ suite.retries(retryNum);
18
+ return;
19
+ }
20
+
21
+ if (!Array.isArray(retryConfig)) {
22
+ retryConfig = [retryConfig];
23
+ }
24
+
25
+ for (const config of retryConfig) {
26
+ if (config.grep) {
27
+ if (!suite.title.includes(config.grep)) continue;
28
+ }
29
+
30
+ hooks.filter(hook => !!config[hook]).forEach((hook) => {
31
+ if (isNotSet(suite.opts[`retry${hook}`])) suite.opts[`retry${hook}`] = config[hook];
32
+ });
33
+
34
+ if (config.Feature) {
35
+ if (isNotSet(suite.retries())) suite.retries(config.Feature);
36
+ }
37
+
38
+ output.log(`Retries: ${JSON.stringify(config)}`);
39
+ }
40
+ });
41
+
42
+ event.dispatcher.on(event.test.before, (test) => {
43
+ let retryConfig = Config.get('retry');
44
+ if (!retryConfig) return;
45
+
46
+ if (Number.isInteger(+retryConfig)) {
47
+ return;
48
+ }
49
+
50
+ if (!Array.isArray(retryConfig)) {
51
+ retryConfig = [retryConfig];
52
+ }
53
+
54
+ retryConfig = retryConfig.filter(config => !!config.Scenario);
55
+
56
+ for (const config of retryConfig) {
57
+ if (config.grep) {
58
+ if (!test.fullTitle().includes(config.grep)) continue;
59
+ }
60
+
61
+ if (config.Scenario) {
62
+ if (isNotSet(test.retries())) test.retries(config.Scenario);
63
+ output.log(`Retries: ${config.Scenario}`);
64
+ }
65
+ }
66
+ });
67
+ };
@@ -81,6 +81,6 @@ module.exports = function () {
81
81
  if (store.debugMode) return;
82
82
  step.finishedAt = +new Date();
83
83
  if (step.startedAt) step.duration = step.finishedAt - step.startedAt;
84
- debug(`Step '${step}' finished; Duration: ${step.duration}ms`);
84
+ debug(`Step '${step}' finished; Duration: ${step.duration || 0}ms`);
85
85
  });
86
86
  };
@@ -7,7 +7,7 @@ const TIMEOUT_ORDER = require('../step').TIMEOUT_ORDER;
7
7
 
8
8
  module.exports = function () {
9
9
  let timeout;
10
- let timeoutStack = [];
10
+ let suiteTimeout = [];
11
11
  let currentTest;
12
12
  let currentTimeout;
13
13
 
@@ -17,21 +17,52 @@ module.exports = function () {
17
17
  }
18
18
 
19
19
  event.dispatcher.on(event.suite.before, (suite) => {
20
- timeoutStack = [];
21
- const globalTimeout = Config.get('timeout');
22
- if (globalTimeout) {
23
- if (globalTimeout >= 1000) {
24
- console.log(`Warning: Timeout was set to ${globalTimeout}secs.\nGlobal timeout should be specified in seconds.`);
20
+ suiteTimeout = [];
21
+ let timeoutConfig = Config.get('timeout');
22
+
23
+ if (timeoutConfig) {
24
+ if (!Number.isNaN(+timeoutConfig)) {
25
+ checkForSeconds(timeoutConfig);
26
+ suiteTimeout.push(timeoutConfig);
27
+ }
28
+
29
+ if (!Array.isArray(timeoutConfig)) {
30
+ timeoutConfig = [timeoutConfig];
31
+ }
32
+
33
+ for (const config of timeoutConfig.filter(c => !!c.Feature)) {
34
+ if (config.grep) {
35
+ if (!suite.title.includes(config.grep)) continue;
36
+ }
37
+ suiteTimeout.push(config.Feature);
25
38
  }
26
- timeoutStack.push(globalTimeout);
27
39
  }
28
- if (suite.totalTimeout) timeoutStack.push(suite.totalTimeout);
29
- output.log(`Timeouts: ${timeoutStack}`);
40
+
41
+ if (suite.totalTimeout) suiteTimeout.push(suite.totalTimeout);
42
+ output.log(`Timeouts: ${suiteTimeout}`);
30
43
  });
31
44
 
32
45
  event.dispatcher.on(event.test.before, (test) => {
33
46
  currentTest = test;
34
- timeout = test.totalTimeout || timeoutStack[timeoutStack.length - 1];
47
+ let testTimeout = null;
48
+
49
+ let timeoutConfig = Config.get('timeout');
50
+
51
+ if (typeof timeoutConfig === 'object' || Array.isArray(timeoutConfig)) {
52
+ if (!Array.isArray(timeoutConfig)) {
53
+ timeoutConfig = [timeoutConfig];
54
+ }
55
+
56
+ for (const config of timeoutConfig.filter(c => !!c.Scenario)) {
57
+ console.log('Test Timeout', config, test.title.includes(config.grep));
58
+ if (config.grep) {
59
+ if (!test.title.includes(config.grep)) continue;
60
+ }
61
+ testTimeout = config.Scenario;
62
+ }
63
+ }
64
+
65
+ timeout = test.totalTimeout || testTimeout || suiteTimeout[suiteTimeout.length - 1];
35
66
  if (!timeout) return;
36
67
  currentTimeout = timeout;
37
68
  output.debug(`Test Timeout: ${timeout}s`);
@@ -70,3 +101,9 @@ module.exports = function () {
70
101
  }
71
102
  });
72
103
  };
104
+
105
+ function checkForSeconds(timeout) {
106
+ if (timeout >= 1000) {
107
+ console.log(`Warning: Timeout was set to ${timeout}secs.\nGlobal timeout should be specified in seconds.`);
108
+ }
109
+ }
@@ -47,13 +47,13 @@ class MochaFactory {
47
47
  let missingFeatureInFile = [];
48
48
  const seenTests = [];
49
49
  mocha.suite.eachTest(test => {
50
- test.id = genTestId(test);
50
+ test.uid = genTestId(test);
51
51
 
52
52
  const name = test.fullTitle();
53
- if (seenTests.includes(test.id)) {
53
+ if (seenTests.includes(test.uid)) {
54
54
  dupes.push(name);
55
55
  }
56
- seenTests.push(test.id);
56
+ seenTests.push(test.uid);
57
57
 
58
58
  if (name.slice(0, name.indexOf(':')) === '') {
59
59
  missingFeatureInFile.push(test.file);
@@ -1,324 +1,15 @@
1
- const Allure = require('allure-js-commons');
2
-
3
- const event = require('../event');
4
- const logger = require('../output');
5
- const { ansiRegExp } = require('../utils');
6
-
7
- const defaultConfig = {
8
- outputDir: global.output_dir,
9
- };
10
-
11
- /**
12
- * Allure reporter
13
- *
14
- * ![](https://user-images.githubusercontent.com/220264/45676511-8e052800-bb3a-11e8-8cbb-db5f73de2add.png)
15
- *
16
- * Enables Allure reporter.
17
- *
18
- * #### Usage
19
- *
20
- * To start please install `allure-commandline` package (which requires Java 8)
21
- *
22
- * ```
23
- * npm install -g allure-commandline --save-dev
24
- * ```
25
- *
26
- * Add this plugin to config file:
27
- *
28
- * ```js
29
- * "plugins": {
30
- * "allure": {}
31
- * }
32
- * ```
33
- *
34
- * Run tests with allure plugin enabled:
35
- *
36
- * ```
37
- * npx codeceptjs run --plugins allure
38
- * ```
39
- *
40
- * By default, allure reports are saved to `output` directory.
41
- * Launch Allure server and see the report like on a screenshot above:
42
- *
43
- * ```
44
- * allure serve output
45
- * ```
46
- *
47
- * #### Configuration
48
- *
49
- * * `outputDir` - a directory where allure reports should be stored. Standard output directory is set by default.
50
- * * `enableScreenshotDiffPlugin` - a boolean flag for add screenshot diff to report.
51
- * To attach, tou need to attach three files to the report - "diff.png", "actual.png", "expected.png".
52
- * See [Allure Screenshot Plugin](https://github.com/allure-framework/allure2/blob/master/plugins/screen-diff-plugin/README.md)
53
- *
54
- * #### Public API
55
- *
56
- * There are few public API methods which can be accessed from other plugins.
57
- *
58
- * ```js
59
- * const allure = codeceptjs.container.plugins('allure');
60
- * ```
61
- *
62
- * `allure` object has following methods:
63
- *
64
- * * `addAttachment(name, buffer, type)` - add an attachment to current test / suite
65
- * * `addLabel(name, value)` - adds a label to current test
66
- * * `addParameter(kind, name, value)` - adds a parameter to current test
67
- * * `createStep(name, stepFunc)` - create a step, stepFunc could consist an attachment
68
- * Example of usage:
69
- * ```js
70
- * allure.createStep('New created step', () => {
71
- * allure.addAttachment(
72
- * 'Request params',
73
- * '{"clientId":123, "name":"Tom", "age":29}',
74
- * 'application/json'
75
- * );
76
- * });
77
- * ```
78
- * ![Created Step Image](https://user-images.githubusercontent.com/63167966/139339384-e6e70a62-3638-406d-a224-f32473071428.png)
79
- * * `severity(value)` - adds severity label
80
- * * `epic(value)` - adds epic label
81
- * * `feature(value)` - adds feature label
82
- * * `story(value)` - adds story label
83
- * * `issue(value)` - adds issue label
84
- * * `setDescription(description, type)` - sets a description
85
- *
86
- */
87
- module.exports = (config) => {
88
- defaultConfig.outputDir = global.output_dir;
89
- config = Object.assign(defaultConfig, config);
90
-
91
- const plugin = {};
92
-
93
- const reporter = new Allure();
94
- reporter.setOptions({ targetDir: config.outputDir });
95
-
96
- let currentMetaStep = [];
97
- let currentStep;
98
-
99
- reporter.pendingCase = function (testName, timestamp, opts = {}) {
100
- reporter.startCase(testName, timestamp);
101
-
102
- if (opts.description) plugin.setDescription(opts.description);
103
- if (opts.severity) plugin.severity(opts.severity);
104
- if (opts.severity) plugin.addLabel('tag', opts.severity);
105
-
106
- reporter.endCase('pending', { message: opts.message || 'Test ignored' }, timestamp);
107
- };
108
-
109
- plugin.addAttachment = (name, buffer, type) => {
110
- reporter.addAttachment(name, buffer, type);
111
- };
112
-
113
- plugin.setDescription = (description, type) => {
114
- const currentTest = reporter.getCurrentTest();
115
- if (currentTest) {
116
- currentTest.setDescription(description, type);
117
- } else {
118
- logger.error(`The test is not run. Please use "setDescription" for events:
119
- "test.start", "test.before", "test.after", "test.passed", "test.failed", "test.finish"`);
120
- }
121
- };
122
-
123
- plugin.createStep = (name, stepFunc = () => { }) => {
124
- let result;
125
- let status = 'passed';
126
- reporter.startStep(name);
127
- try {
128
- result = stepFunc(this.arguments);
129
- } catch (error) {
130
- status = 'broken';
131
- throw error;
132
- } finally {
133
- if (!!result
134
- && (typeof result === 'object' || typeof result === 'function')
135
- && typeof result.then === 'function'
136
- ) {
137
- result.then(() => reporter.endStep('passed'), () => reporter.endStep('broken'));
138
- } else {
139
- reporter.endStep(status);
140
- }
141
- }
142
- return result;
143
- };
144
-
145
- plugin.createAttachment = (name, content, type) => {
146
- if (typeof content === 'function') {
147
- const attachmentName = name;
148
- const buffer = content.apply(this, arguments);
149
- return createAttachment(attachmentName, buffer, type);
150
- } reporter.addAttachment(name, content, type);
151
- };
152
-
153
- plugin.severity = (severity) => {
154
- plugin.addLabel('severity', severity);
155
- };
156
-
157
- plugin.epic = (epic) => {
158
- plugin.addLabel('epic', epic);
159
- };
160
-
161
- plugin.feature = (feature) => {
162
- plugin.addLabel('feature', feature);
163
- };
164
-
165
- plugin.story = (story) => {
166
- plugin.addLabel('story', story);
167
- };
168
-
169
- plugin.issue = (issue) => {
170
- plugin.addLabel('issue', issue);
171
- };
172
-
173
- plugin.addLabel = (name, value) => {
174
- const currentTest = reporter.getCurrentTest();
175
- if (currentTest) {
176
- currentTest.addLabel(name, value);
177
- } else {
178
- logger.error(`The test is not run. Please use "addLabel" for events:
179
- "test.start", "test.before", "test.after", "test.passed", "test.failed", "test.finish"`);
180
- }
181
- };
182
-
183
- plugin.addParameter = (kind, name, value) => {
184
- const currentTest = reporter.getCurrentTest();
185
- if (currentTest) {
186
- currentTest.addParameter(kind, name, value);
187
- } else {
188
- logger.error(`The test is not run. Please use "addParameter" for events:
189
- "test.start", "test.before", "test.after", "test.passed", "test.failed", "test.finish"`);
190
- }
191
- };
192
-
193
- event.dispatcher.on(event.suite.before, (suite) => {
194
- reporter.startSuite(suite.fullTitle());
195
- });
196
-
197
- event.dispatcher.on(event.suite.before, (suite) => {
198
- for (const test of suite.tests) {
199
- if (test.pending) {
200
- reporter.pendingCase(test.title, null, test.opts.skipInfo);
201
- }
202
- }
203
- });
204
-
205
- event.dispatcher.on(event.suite.after, () => {
206
- reporter.endSuite();
207
- });
208
-
209
- event.dispatcher.on(event.test.before, (test) => {
210
- reporter.startCase(test.title);
211
- if (config.enableScreenshotDiffPlugin) {
212
- const currentTest = reporter.getCurrentTest();
213
- currentTest.addLabel('testType', 'screenshotDiff');
214
- }
215
- currentStep = null;
216
- });
217
-
218
- event.dispatcher.on(event.test.started, (test) => {
219
- const currentTest = reporter.getCurrentTest();
220
- for (const tag of test.tags) {
221
- currentTest.addLabel('tag', tag);
222
- }
223
- });
224
-
225
- event.dispatcher.on(event.test.failed, (test, err) => {
226
- if (currentStep) reporter.endStep('failed');
227
- if (currentMetaStep.length) {
228
- currentMetaStep.forEach(() => reporter.endStep('failed'));
229
- currentMetaStep = [];
230
- }
231
-
232
- err.message = err.message.replace(ansiRegExp(), '');
233
- if (reporter.getCurrentTest()) {
234
- reporter.endCase('failed', err);
235
- } else {
236
- // this means before suite failed, we should report this.
237
- reporter.startCase(`BeforeSuite of suite ${reporter.getCurrentSuite().name} failed.`);
238
- reporter.endCase('failed', err);
239
- }
240
- });
241
-
242
- event.dispatcher.on(event.test.passed, () => {
243
- if (currentStep) reporter.endStep('passed');
244
- if (currentMetaStep.length) {
245
- currentMetaStep.forEach(() => reporter.endStep('passed'));
246
- currentMetaStep = [];
247
- }
248
- reporter.endCase('passed');
249
- });
250
-
251
- event.dispatcher.on(event.test.skipped, (test) => {
252
- let loaded = true;
253
- if (test.opts.skipInfo.isFastSkipped) {
254
- loaded = false;
255
- reporter.startSuite(test.parent.fullTitle());
256
- }
257
- reporter.pendingCase(test.title, null, test.opts.skipInfo);
258
- if (!loaded) {
259
- reporter.endSuite();
260
- }
261
- });
262
-
263
- event.dispatcher.on(event.step.started, (step) => {
264
- startMetaStep(step.metaStep);
265
- if (currentStep !== step) {
266
- // In multi-session scenarios, actors' names will be highlighted with ANSI
267
- // escape sequences which are invalid XML values
268
- step.actor = step.actor.replace(ansiRegExp(), '');
269
- reporter.startStep(step.toString());
270
- currentStep = step;
271
- }
272
- });
273
-
274
- event.dispatcher.on(event.step.comment, (step) => {
275
- reporter.startStep(step.toString());
276
- currentStep = step;
277
- reporter.endStep('passed');
278
- currentStep = null;
279
- });
280
-
281
- event.dispatcher.on(event.step.passed, (step) => {
282
- if (currentStep === step) {
283
- reporter.endStep('passed');
284
- currentStep = null;
285
- }
286
- });
287
-
288
- event.dispatcher.on(event.step.failed, (step) => {
289
- if (currentStep === step) {
290
- reporter.endStep('failed');
291
- currentStep = null;
292
- }
293
- });
294
-
295
- let maxLevel;
296
- function finishMetastep(level) {
297
- const metaStepsToFinish = currentMetaStep.splice(maxLevel - level);
298
- metaStepsToFinish.forEach(() => {
299
- // only if the current step is of type Step, end it.
300
- if (reporter.suites && reporter.suites.length && reporter.suites[0].currentStep && reporter.suites[0].currentStep.constructor.name === 'Step') {
301
- reporter.endStep('passed');
302
- }
303
- });
304
- }
305
-
306
- function startMetaStep(metaStep, level = 0) {
307
- maxLevel = level;
308
- if (!metaStep) {
309
- finishMetastep(0);
310
- maxLevel--;
311
- return;
312
- }
313
-
314
- startMetaStep(metaStep.metaStep, level + 1);
315
-
316
- if (metaStep.toString() !== currentMetaStep[maxLevel - level]) {
317
- finishMetastep(level);
318
- currentMetaStep.push(metaStep.toString());
319
- reporter.startStep(metaStep.toString());
320
- }
321
- }
322
-
323
- return plugin;
1
+ module.exports = () => {
2
+ console.log('Allure plugin was moved to @codeceptjs/allure-legacy. Please install it and update your config');
3
+ console.log();
4
+ console.log('npm install @codeceptjs/allure-legacy --save-dev');
5
+ console.log();
6
+ console.log('Then update your config to use it:');
7
+ console.log();
8
+ console.log('plugins: {');
9
+ console.log(' allure: {');
10
+ console.log(' enabled: true,');
11
+ console.log(' require: \'@codeceptjs/allure-legacy\',');
12
+ console.log(' }');
13
+ console.log('}');
14
+ console.log();
324
15
  };
@@ -1,4 +1,4 @@
1
- const faker = require('@faker-js/faker');
1
+ const { faker } = require('@faker-js/faker');
2
2
  const transform = require('../transform');
3
3
 
4
4
  /**
@@ -44,7 +44,7 @@ const transform = require('../transform');
44
44
  module.exports = function (config) {
45
45
  transform.addTransformerBeforeAll('gherkin.examples', (value) => {
46
46
  if (typeof value === 'string' && value.length > 0) {
47
- return faker.fake(value);
47
+ return faker.helpers.fake(value);
48
48
  }
49
49
  return value;
50
50
  });
package/lib/recorder.js CHANGED
@@ -127,7 +127,7 @@ module.exports = {
127
127
  },
128
128
 
129
129
  /**
130
- * @param {string} name
130
+ * @param {string} [name]
131
131
  * @inner
132
132
  */
133
133
  restore(name) {