codeceptjs 2.4.3 → 2.6.2

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 (76) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/README.md +32 -7
  3. package/bin/codecept.js +3 -0
  4. package/docs/basics.md +11 -5
  5. package/docs/bdd.md +4 -4
  6. package/docs/build/MockRequest.js +3 -0
  7. package/docs/build/Nightmare.js +10 -2
  8. package/docs/build/Playwright.js +3187 -0
  9. package/docs/build/Protractor.js +16 -2
  10. package/docs/build/Puppeteer.js +126 -19
  11. package/docs/build/REST.js +3 -1
  12. package/docs/build/TestCafe.js +11 -3
  13. package/docs/build/WebDriver.js +361 -28
  14. package/docs/changelog.md +116 -0
  15. package/docs/configuration.md +2 -2
  16. package/docs/custom-helpers.md +55 -10
  17. package/docs/helpers/Appium.md +81 -1
  18. package/docs/helpers/MockRequest.md +281 -38
  19. package/docs/helpers/Nightmare.md +10 -2
  20. package/docs/helpers/Playwright.md +1770 -0
  21. package/docs/helpers/Protractor.md +15 -3
  22. package/docs/helpers/Puppeteer-firefox.md +32 -1
  23. package/docs/helpers/Puppeteer.md +126 -76
  24. package/docs/helpers/TestCafe.md +10 -2
  25. package/docs/helpers/WebDriver.md +208 -118
  26. package/docs/locators.md +2 -0
  27. package/docs/playwright.md +306 -0
  28. package/docs/plugins.md +103 -0
  29. package/docs/reports.md +12 -0
  30. package/docs/shadow.md +68 -0
  31. package/docs/visual.md +0 -73
  32. package/docs/webapi/forceClick.mustache +27 -0
  33. package/docs/webapi/seeInPopup.mustache +7 -0
  34. package/docs/webapi/setCookie.mustache +10 -2
  35. package/docs/webapi/type.mustache +12 -0
  36. package/docs/webdriver.md +7 -3
  37. package/lib/codecept.js +1 -1
  38. package/lib/command/definitions.js +2 -2
  39. package/lib/command/generate.js +4 -4
  40. package/lib/command/gherkin/snippets.js +4 -4
  41. package/lib/command/init.js +1 -1
  42. package/lib/command/interactive.js +3 -0
  43. package/lib/command/run-multiple.js +2 -2
  44. package/lib/command/run-rerun.js +2 -0
  45. package/lib/command/run-workers.js +22 -8
  46. package/lib/command/run.js +2 -0
  47. package/lib/command/workers/runTests.js +1 -0
  48. package/lib/container.js +1 -1
  49. package/lib/event.js +2 -0
  50. package/lib/helper/MockRequest.js +3 -0
  51. package/lib/helper/Playwright.js +2422 -0
  52. package/lib/helper/Protractor.js +1 -2
  53. package/lib/helper/Puppeteer.js +84 -19
  54. package/lib/helper/REST.js +3 -1
  55. package/lib/helper/TestCafe.js +1 -1
  56. package/lib/helper/WebDriver.js +313 -26
  57. package/lib/helper/extras/PlaywrightPropEngine.js +53 -0
  58. package/lib/helper/scripts/isElementClickable.js +54 -14
  59. package/lib/interfaces/gherkin.js +1 -1
  60. package/lib/listener/helpers.js +3 -0
  61. package/lib/locator.js +5 -0
  62. package/lib/mochaFactory.js +12 -10
  63. package/lib/plugin/allure.js +8 -1
  64. package/lib/plugin/autoDelay.js +1 -8
  65. package/lib/plugin/commentStep.js +133 -0
  66. package/lib/plugin/screenshotOnFail.js +3 -10
  67. package/lib/plugin/selenoid.js +2 -2
  68. package/lib/plugin/standardActingHelpers.js +13 -0
  69. package/lib/plugin/stepByStepReport.js +1 -8
  70. package/lib/plugin/wdio.js +10 -1
  71. package/lib/reporter/cli.js +30 -1
  72. package/lib/session.js +7 -4
  73. package/package.json +13 -10
  74. package/typings/Mocha.d.ts +567 -16
  75. package/typings/index.d.ts +9 -5
  76. package/typings/types.d.ts +1634 -74
@@ -1,24 +1,64 @@
1
- function isElementClickable(elem) {
2
- if (!elem.getBoundingClientRect || !elem.scrollIntoView || !document.elementFromPoint) {
1
+ function isElementClickable(element) {
2
+ if (!element.getBoundingClientRect || !element.scrollIntoView || !element.contains || !element.getClientRects || !document.elementFromPoint) {
3
3
  return false;
4
4
  }
5
5
 
6
- const isElementInViewport = (elem) => {
7
- const rect = elem.getBoundingClientRect();
8
- const verticleInView = (rect.top <= window.innerHeight) && ((rect.top + rect.height) > 0);
9
- const horizontalInView = (rect.left <= window.innerWidth) && ((rect.left + rect.width) > 0);
10
- return horizontalInView && verticleInView;
6
+ const getOverlappingElement = (element, context = document) => {
7
+ const elemDimension = element.getBoundingClientRect();
8
+ const x = elemDimension.left + (element.clientWidth / 2);
9
+ const y = elemDimension.top + (element.clientHeight / 2);
10
+
11
+ return context.elementFromPoint(x, y);
12
+ };
13
+
14
+ const getOverlappingRects = (element, context = document) => {
15
+ const rects = element.getClientRects();
16
+ const rect = rects[0];
17
+ const x = rect.left + (rect.width / 2);
18
+ const y = rect.top + (rect.height / 2);
19
+
20
+ return context.elementFromPoint(x, y);
11
21
  };
12
22
 
13
- const getOverlappingElement = (elem) => {
14
- const rect = elem.getBoundingClientRect();
15
- const x = rect.left + (elem.clientWidth / 2);
16
- const y = rect.top + (elem.clientHeight / 2);
17
- return document.elementFromPoint(x, y);
23
+ const getOverlappingElements = (element, context) => {
24
+ return [getOverlappingElement(element, context), getOverlappingRects(element, context)];
25
+ };
26
+
27
+ const isOverlappingElementMatch = (elementsFromPoint, element) => {
28
+ if (elementsFromPoint.some(elementFromPoint => elementFromPoint === element || element.contains(elementFromPoint))) {
29
+ return true;
30
+ }
31
+
32
+ let elementsWithShadowRoot = [...new Set(elementsFromPoint)];
33
+ elementsWithShadowRoot = elementsWithShadowRoot.filter(elem => elem && elem.shadowRoot && elem.shadowRoot.elementFromPoint);
34
+
35
+ let shadowElementsFromPoint = [];
36
+ for (const shadowElement of elementsWithShadowRoot) {
37
+ shadowElementsFromPoint.push(...getOverlappingElements(element, shadowElement.shadowRoot));
38
+ }
39
+ shadowElementsFromPoint = [...new Set(shadowElementsFromPoint)];
40
+ shadowElementsFromPoint = shadowElementsFromPoint.filter(element => !elementsFromPoint.includes(element));
41
+
42
+ if (shadowElementsFromPoint.length === 0) {
43
+ return false;
44
+ }
45
+
46
+ return isOverlappingElementMatch(shadowElementsFromPoint, element);
47
+ };
48
+
49
+ const isElementInViewport = (element) => {
50
+ const rect = element.getBoundingClientRect();
51
+
52
+ const windowHeight = (window.innerHeight || document.documentElement.clientHeight);
53
+ const windowWidth = (window.innerWidth || document.documentElement.clientWidth);
54
+
55
+ const vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) > 0);
56
+ const horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) > 0);
57
+
58
+ return (vertInView && horInView);
18
59
  };
19
60
 
20
- const isClickable = elem => elem.disabled !== true && isElementInViewport(elem) && getOverlappingElement(elem) === elem;
21
- return isClickable(elem);
61
+ return element.disabled !== true && isElementInViewport(element) && isOverlappingElementMatch(getOverlappingElements(element), element);
22
62
  }
23
63
 
24
64
  module.exports = isElementClickable;
@@ -74,7 +74,7 @@ module.exports = (text) => {
74
74
  return step;
75
75
  });
76
76
  }
77
- const tags = child.tags.map(t => t.name);
77
+ const tags = child.tags.map(t => t.name).concat(examples.tags.map(t => t.name));
78
78
  const title = `${child.name} ${JSON.stringify(current)} ${tags.join(' ')}`.trim();
79
79
  const test = new Test(title, async () => runSteps(addExampleInTable(exampleSteps, current)));
80
80
  test.tags = suite.tags.concat(tags);
@@ -13,6 +13,9 @@ module.exports = function () {
13
13
  const runHelpersHook = (hook, param) => {
14
14
  if (store.dryRun) return;
15
15
  Object.keys(helpers).forEach((key) => {
16
+ if (!helpers[key][hook]) {
17
+ return;
18
+ }
16
19
  helpers[key][hook](param);
17
20
  });
18
21
  };
package/lib/locator.js CHANGED
@@ -3,6 +3,7 @@ const sprintf = require('sprintf-js').sprintf;
3
3
 
4
4
  const xpathLocator = require('./utils').xpathLocator;
5
5
 
6
+ const locatorTypes = ['css', 'by', 'xpath', 'id', 'name', 'fuzzy', 'frame'];
6
7
  /** @class */
7
8
  class Locator {
8
9
  /**
@@ -96,6 +97,10 @@ class Locator {
96
97
  return this.type === 'xpath';
97
98
  }
98
99
 
100
+ isCustom() {
101
+ return this.type && !locatorTypes.includes(this.type);
102
+ }
103
+
99
104
  isStrict() {
100
105
  return this.strict;
101
106
  }
@@ -38,19 +38,21 @@ class MochaFactory {
38
38
  };
39
39
 
40
40
  mocha.loadFiles = (fn) => {
41
- // load features
42
- mocha.files
43
- .filter(file => file.match(/\.feature$/))
44
- .map(file => fs.readFileSync(file, 'utf8'))
45
- .forEach(content => mocha.suite.addSuite(gherkinParser(content)));
41
+ if (mocha.suite.suites.length === 0) {
42
+ // load features
43
+ mocha.files
44
+ .filter(file => file.match(/\.feature$/))
45
+ .map(file => fs.readFileSync(file, 'utf8'))
46
+ .forEach(content => mocha.suite.addSuite(gherkinParser(content)));
46
47
 
47
- // remove feature files
48
- mocha.files = mocha.files.filter(file => !file.match(/\.feature$/));
48
+ // remove feature files
49
+ mocha.files = mocha.files.filter(file => !file.match(/\.feature$/));
49
50
 
50
- Mocha.prototype.loadFiles.call(mocha, fn);
51
+ Mocha.prototype.loadFiles.call(mocha, fn);
51
52
 
52
- // add ids for each test
53
- mocha.suite.eachTest(test => test.id = genTestId(test));
53
+ // add ids for each test
54
+ mocha.suite.eachTest(test => test.id = genTestId(test));
55
+ }
54
56
  };
55
57
 
56
58
  // use standard reporter
@@ -72,6 +72,7 @@ const defaultConfig = {
72
72
  *
73
73
  */
74
74
  module.exports = (config) => {
75
+ defaultConfig.outputDir = global.output_dir;
75
76
  config = Object.assign(defaultConfig, config);
76
77
 
77
78
  const plugin = {};
@@ -215,7 +216,13 @@ module.exports = (config) => {
215
216
  }
216
217
 
217
218
  err.message = err.message.replace(ansiRegExp(), '');
218
- reporter.endCase('failed', err);
219
+ if (reporter.getCurrentTest()) {
220
+ reporter.endCase('failed', err);
221
+ } else {
222
+ // this means before suite failed, we should report this.
223
+ reporter.startCase(`BeforeSuite of suite ${reporter.getCurrentSuite().name} failed.`);
224
+ reporter.endCase('failed', err);
225
+ }
219
226
  });
220
227
 
221
228
  event.dispatcher.on(event.test.passed, () => {
@@ -4,14 +4,7 @@ const recorder = require('../recorder');
4
4
  const event = require('../event');
5
5
  const log = require('../output').log;
6
6
 
7
- const supportedHelpers = [
8
- 'WebDriver',
9
- 'WebDriverIO',
10
- 'Protractor',
11
- 'Appium',
12
- 'Nightmare',
13
- 'Puppeteer',
14
- ];
7
+ const supportedHelpers = require('./standardActingHelpers');
15
8
 
16
9
  const methodsToDelay = [
17
10
  'click',
@@ -0,0 +1,133 @@
1
+ const event = require('../event');
2
+ const recorder = require('../recorder');
3
+ const { MetaStep } = require('../step');
4
+
5
+ let currentCommentStep;
6
+
7
+ const defaultGlobalName = '__';
8
+
9
+ /**
10
+ * Add descriptive nested steps for your tests:
11
+ *
12
+ * ```js
13
+ * Scenario('project update test', async (I) => {
14
+ * __`Given`;
15
+ * const projectId = await I.have('project');
16
+ *
17
+ * __`When`;
18
+ * projectPage.update(projectId, { title: 'new title' });
19
+ *
20
+ * __`Then`;
21
+ * projectPage.open(projectId);
22
+ * I.see('new title', 'h1');
23
+ * })
24
+ * ```
25
+ * Steps prefixed with `__` will be printed as nested steps in `--steps` output:
26
+ *
27
+ * ```
28
+ * Given
29
+ * I have "project"
30
+ * When
31
+ * projectPage update
32
+ * Then
33
+ * projectPage open
34
+ * I see "new title", "h1"
35
+ * ```
36
+ *
37
+ * Also those steps will be exported to allure reports.
38
+ *
39
+ * This plugin can be used
40
+ *
41
+ * ### Config
42
+ *
43
+ * * `enabled` - (default: false) enable a plugin
44
+ * * `regusterGlobal` - (default: false) register `__` template literal function globally. You can override function global name by providing a name as a value.
45
+ *
46
+ * ### Examples
47
+ *
48
+ * Registering `__` globally:
49
+ *
50
+ * ```js
51
+ * plugins: {
52
+ * commentStep: {
53
+ * enabled: true,
54
+ * registerGlobal: true
55
+ * }
56
+ * }
57
+ * ```
58
+ *
59
+ * Registering `Step` globally:
60
+ * ```js
61
+ * plugins: {
62
+ * commentStep: {
63
+ * enabled: true,
64
+ * registerGlobal: 'Step'
65
+ * }
66
+ * }
67
+ * ```
68
+ *
69
+ * Using only local function names:
70
+ * ```js
71
+ * plugins: {
72
+ * commentStep: {
73
+ * enabled: true
74
+ * }
75
+ * }
76
+ * ```
77
+ * Then inside a test import a comment function from a plugin.
78
+ * For instance, you can prepare Given/When/Then functions to use them inside tests:
79
+ *
80
+ * ```js
81
+ * // inside a test
82
+ * const step = codeceptjs.container.plugins('commentStep');
83
+ *
84
+ * const Given = () => step`Given`;
85
+ * const When = () => step`When`;
86
+ * const Then = () => step`Then`;
87
+ * ```
88
+ *
89
+ * Scenario('project update test', async (I) => {
90
+ * Given();
91
+ * const projectId = await I.have('project');
92
+ *
93
+ * When();
94
+ * projectPage.update(projectId, { title: 'new title' });
95
+ *
96
+ * Then();
97
+ * projectPage.open(projectId);
98
+ * I.see('new title', 'h1');
99
+ * });
100
+ * ```
101
+ */
102
+ module.exports = function (config) {
103
+ event.dispatcher.on(event.test.started, (test) => {
104
+ currentCommentStep = null;
105
+ });
106
+
107
+ event.dispatcher.on(event.step.started, (step) => {
108
+ if (currentCommentStep) {
109
+ const metaStep = getRootMetaStep(step);
110
+ metaStep.metaStep = currentCommentStep;
111
+ }
112
+ });
113
+
114
+ if (config.registerGlobal) {
115
+ if (config.registerGlobal === true) {
116
+ config.registerGlobal = defaultGlobalName;
117
+ }
118
+ global[config.registerGlobal] = setCommentString;
119
+ }
120
+
121
+ return setCommentString;
122
+ };
123
+
124
+ function getRootMetaStep(step) {
125
+ if (step.metaStep) return getRootMetaStep(step.metaStep);
126
+ return step;
127
+ }
128
+
129
+ function setCommentString(string) {
130
+ recorder.add('set comment metastep', () => {
131
+ currentCommentStep = new MetaStep(String.raw(string), '');
132
+ });
133
+ }
@@ -14,15 +14,7 @@ const defaultConfig = {
14
14
  fullPageScreenshots: false,
15
15
  };
16
16
 
17
- const supportedHelpers = [
18
- 'Mochawesome',
19
- 'WebDriverIO',
20
- 'WebDriver',
21
- 'Protractor',
22
- 'Appium',
23
- 'Nightmare',
24
- 'Puppeteer',
25
- ];
17
+ const supportedHelpers = require('./standardActingHelpers');
26
18
 
27
19
  /**
28
20
  * Creates screenshot on failure. Screenshot is saved into `output` directory.
@@ -126,6 +118,7 @@ module.exports = function (config) {
126
118
  || err.message.indexOf('no such window: target window already closed') > -1
127
119
  )
128
120
  ) {
121
+ output.log(`Can't make screenshot, ${err}`);
129
122
  helper.isRunning = false;
130
123
  }
131
124
  }
@@ -137,7 +130,7 @@ module.exports = function (config) {
137
130
  return test.uuid;
138
131
  }
139
132
 
140
- if (test.ctx) {
133
+ if (test.ctx && test.ctx.test.uuid) {
141
134
  return test.ctx.test.uuid;
142
135
  }
143
136
 
@@ -3,7 +3,7 @@ const path = require('path');
3
3
  const fs = require('fs');
4
4
  const axios = require('axios').default;
5
5
  const exec = util.promisify(require('child_process').exec);
6
- const { clearString } = require('../utils');
6
+ const { clearString, deepMerge } = require('../utils');
7
7
  const {
8
8
  container, event, recorder, output,
9
9
  } = require('../index');
@@ -336,7 +336,7 @@ function deletePassedTests(passedTests) {
336
336
 
337
337
  function setOptionsForWebdriver(config) {
338
338
  const WebDriver = container.helpers('WebDriver');
339
- WebDriver._setConfig(Object.assign(WebDriver.options, {
339
+ WebDriver._setConfig(deepMerge(WebDriver.options, {
340
340
  capabilities: { 'selenoid:options': config },
341
341
  }));
342
342
  }
@@ -0,0 +1,13 @@
1
+ const standardActingHelpers = [
2
+ 'Mochawesome',
3
+ 'WebDriver',
4
+ 'WebDriverIO',
5
+ 'Protractor',
6
+ 'Appium',
7
+ 'Nightmare',
8
+ 'Puppeteer',
9
+ 'Playwright',
10
+ 'TestCafe',
11
+ ];
12
+
13
+ module.exports = standardActingHelpers;
@@ -11,14 +11,7 @@ const event = require('../event');
11
11
  const output = require('../output');
12
12
  const { template, deleteDir } = require('../utils');
13
13
 
14
- const supportedHelpers = [
15
- 'WebDriverIO',
16
- 'WebDriver',
17
- 'Protractor',
18
- 'Appium',
19
- 'Nightmare',
20
- 'Puppeteer',
21
- ];
14
+ const supportedHelpers = require('./standardActingHelpers');
22
15
 
23
16
  const defaultConfig = {
24
17
  deleteSuccessful: true,
@@ -1,4 +1,6 @@
1
1
  const debug = require('debug')('codeceptjs:plugin:wdio');
2
+ const path = require('path');
3
+ const fs = require('fs');
2
4
 
3
5
  const container = require('../container');
4
6
  const mainConfig = require('../config');
@@ -99,7 +101,14 @@ module.exports = (config) => {
99
101
  if (Service) {
100
102
  if (Service.launcher && typeof Service.launcher === 'function') {
101
103
  const Launcher = Service.launcher;
102
- launchers.push(new Launcher(config));
104
+
105
+ const version = JSON.parse(fs.readFileSync(path.join(require.resolve('webdriverio'), '/../../', 'package.json')).toString()).version;
106
+ if (version.indexOf('5') === 0) {
107
+ launchers.push(new Launcher(config));
108
+ } else {
109
+ const options = { logPath: global.output_dir, installArgs: {}, args: {} };
110
+ launchers.push(new Launcher(options, [config.capabilities], config));
111
+ }
103
112
  }
104
113
  if (typeof Service === 'function') {
105
114
  services.push(new Service(config, config.capabilities));
@@ -11,11 +11,11 @@ class Cli extends Base {
11
11
  constructor(runner, opts) {
12
12
  super(runner);
13
13
  let level = 0;
14
+ this.failedTests = [];
14
15
  opts = opts.reporterOptions || opts;
15
16
  if (opts.steps) level = 1;
16
17
  if (opts.debug) level = 2;
17
18
  if (opts.verbose) level = 3;
18
-
19
19
  output.level(level);
20
20
  output.print(`CodeceptJS v${require('../codecept').version()}`);
21
21
  output.print(`Using test root "${global.codecept_dir}"`);
@@ -42,6 +42,9 @@ class Cli extends Base {
42
42
  });
43
43
 
44
44
  runner.on('fail', (test, err) => {
45
+ if (test.ctx.currentTest) {
46
+ this.failedTests.push(test.ctx.currentTest.id);
47
+ }
45
48
  if (showSteps && test.steps) {
46
49
  return output.scenario.failed(test);
47
50
  }
@@ -90,6 +93,24 @@ class Cli extends Base {
90
93
  });
91
94
  }
92
95
 
96
+ runner.on('suite end', suite => {
97
+ let skippedCount = 0;
98
+ const grep = runner._grep;
99
+ for (const test of suite.tests) {
100
+ if (!test.state && !this.failedTests.includes(test.id)) {
101
+ if (matchTest(grep, test.title)) {
102
+ event.emit(event.test.skipped, test);
103
+ test.state = 'skipped';
104
+ output.test.skipped(test);
105
+ skippedCount += 1;
106
+ }
107
+ }
108
+ }
109
+
110
+ this.stats.pending += skippedCount;
111
+ this.stats.tests += skippedCount;
112
+ });
113
+
93
114
  runner.on('end', this.result.bind(this));
94
115
  }
95
116
 
@@ -129,6 +150,14 @@ class Cli extends Base {
129
150
  output.result(stats.passes, stats.failures, stats.pending, ms(stats.duration));
130
151
  }
131
152
  }
153
+
154
+ function matchTest(grep, test) {
155
+ if (grep) {
156
+ return grep.test(test);
157
+ }
158
+ return true;
159
+ }
160
+
132
161
  module.exports = function (runner, opts) {
133
162
  return new Cli(runner, opts);
134
163
  };
package/lib/session.js CHANGED
@@ -58,14 +58,16 @@ function session(sessionName, config, fn) {
58
58
  delete savedSessions[sessionName];
59
59
  };
60
60
 
61
- event.dispatcher.once(event.test.finished, () => closeBrowsers());
61
+ event.dispatcher.once(event.test.after, () => {
62
+ recorder.add('close session browsers', closeBrowsers);
63
+ });
62
64
 
63
65
  if (!savedSessions[sessionName]) {
64
66
  throw new Error('Configured helpers do not support starting sessions. Please use a helper with session support.');
65
67
  }
66
68
 
67
69
  recorder.add('save vars', async () => {
68
- savedSessions[sessionName].vars = await savedSessions[sessionName].start(config);
70
+ savedSessions[sessionName].vars = await savedSessions[sessionName].start(sessionName, config);
69
71
  });
70
72
  }
71
73
 
@@ -97,13 +99,14 @@ function session(sessionName, config, fn) {
97
99
  });
98
100
  };
99
101
 
102
+ // Indicate when executing this function that we are in a session
100
103
  if (isAsyncFunction(fn)) {
101
104
  return fn.apply(null).then((res) => {
102
105
  finalize();
103
106
  return recorder.promise().then(() => res);
104
107
  }).catch((e) => {
105
108
  output.stepShift = 0;
106
- session.restoreVars();
109
+ session.restoreVars(sessionName);
107
110
  event.dispatcher.removeListener(event.step.after, addContextToStep);
108
111
  recorder.throw(e);
109
112
  return recorder.promise();
@@ -117,7 +120,7 @@ function session(sessionName, config, fn) {
117
120
  recorder.throw(err);
118
121
  } finally {
119
122
  recorder.catch((e) => {
120
- session.restoreVars();
123
+ session.restoreVars(sessionName);
121
124
  output.stepShift = 0;
122
125
  event.dispatcher.removeListener(event.step.after, addContextToStep);
123
126
  throw e;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeceptjs",
3
- "version": "2.4.3",
3
+ "version": "2.6.2",
4
4
  "description": "Supercharged End 2 End Testing Framework for NodeJS",
5
5
  "keywords": [
6
6
  "acceptance",
@@ -46,11 +46,11 @@
46
46
  "test": "npm run test:unit && npm run test:runner",
47
47
  "def": "./runio.js def",
48
48
  "dev:graphql": "nodemon test/data/graphql/index.js",
49
- "publish:site": "./runio.js publish:site"
49
+ "publish:site": "./runio.js publish:site",
50
+ "update-contributor-faces": "contributor-faces ."
50
51
  },
51
52
  "dependencies": {
52
53
  "@codeceptjs/configure": "^0.4.0",
53
- "@types/mocha": "^5.2.7",
54
54
  "allure-js-commons": "^1.3.2",
55
55
  "arrify": "^2.0.1",
56
56
  "axios": "^0.19.1",
@@ -69,19 +69,20 @@
69
69
  "js-beautify": "^1.10.2",
70
70
  "lodash.clonedeep": "^4.5.0",
71
71
  "lodash.merge": "^4.6.2",
72
- "mkdirp": "^0.5.1",
72
+ "mkdirp": "^1.0.3",
73
73
  "mocha": "^6.2.2",
74
74
  "mocha-junit-reporter": "^1.23.1",
75
75
  "ms": "^2.1.2",
76
76
  "parse-function": "^5.5.0",
77
77
  "promise-retry": "^1.1.1",
78
- "requireg": "^0.1.8",
78
+ "requireg": "^0.2.2",
79
79
  "resq": "^1.7.0",
80
80
  "semver": "^6.2.0",
81
81
  "sprintf-js": "^1.1.1"
82
82
  },
83
83
  "devDependencies": {
84
84
  "@codeceptjs/detox-helper": "^1.0.2",
85
+ "@codeceptjs/mock-request": "^0.3.0",
85
86
  "@pollyjs/adapter-puppeteer": "^2.6.3",
86
87
  "@pollyjs/core": "^2.6.3",
87
88
  "@types/inquirer": "^0.0.35",
@@ -93,6 +94,7 @@
93
94
  "chai": "^3.4.1",
94
95
  "chai-as-promised": "^5.2.0",
95
96
  "chai-subset": "^1.6.0",
97
+ "contributor-faces": "^1.0.3",
96
98
  "documentation": "^12.1.4",
97
99
  "eslint": "^6.8.0",
98
100
  "eslint-config-airbnb-base": "^14.0.0",
@@ -105,10 +107,12 @@
105
107
  "jsdoc": "^3.6.2",
106
108
  "jsdoc-typeof-plugin": "^1.0.0",
107
109
  "json-server": "^0.10.1",
110
+ "mocha-parallel-tests": "^2.2.2",
108
111
  "nightmare": "^3.0.2",
109
112
  "nodemon": "^1.19.4",
113
+ "playwright": "^0.14.0",
110
114
  "protractor": "^5.4.1",
111
- "puppeteer": "^1.20.0",
115
+ "puppeteer": "^3.0.0",
112
116
  "qrcode-terminal": "^0.12.0",
113
117
  "rosie": "^1.6.0",
114
118
  "runio.js": "^1.0.20",
@@ -119,10 +123,9 @@
119
123
  "tsd-jsdoc": "^2.3.0",
120
124
  "typescript": "^2.9.2",
121
125
  "wdio-docker-service": "^1.5.0",
122
- "webdriverio": "^5.18.4",
126
+ "webdriverio": "^6.0.4",
123
127
  "xmldom": "^0.1.31",
124
- "xpath": "0.0.27",
125
- "mocha-parallel-tests": "^2.2.2"
128
+ "xpath": "0.0.27"
126
129
  },
127
130
  "engines": {
128
131
  "node": ">=8.9.1",
@@ -132,7 +135,7 @@
132
135
  "husky": {
133
136
  "hooks": {
134
137
  "pre-commit": "npm run lint",
135
- "pre-push": "npm run lint && npm run test"
138
+ "pre-push": "npm run lint && npm run test:unit"
136
139
  }
137
140
  }
138
141
  }