codeceptjs 3.3.6 → 3.3.7

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 (62) hide show
  1. package/docs/basics.md +2 -3
  2. package/docs/bdd.md +33 -0
  3. package/docs/best.md +8 -8
  4. package/docs/build/Appium.js +60 -22
  5. package/docs/build/GraphQL.js +6 -6
  6. package/docs/build/Nightmare.js +4 -4
  7. package/docs/build/Playwright.js +102 -39
  8. package/docs/build/Polly.js +0 -0
  9. package/docs/build/Protractor.js +25 -25
  10. package/docs/build/Puppeteer.js +7 -7
  11. package/docs/build/SeleniumWebdriver.js +0 -0
  12. package/docs/build/TestCafe.js +12 -12
  13. package/docs/build/WebDriver.js +32 -32
  14. package/docs/changelog.md +36 -1
  15. package/docs/helpers/Appium.md +103 -79
  16. package/docs/helpers/GraphQL.md +6 -6
  17. package/docs/helpers/Playwright.md +280 -245
  18. package/docs/helpers/Puppeteer.md +1 -1
  19. package/docs/helpers/REST.md +1 -1
  20. package/docs/helpers/WebDriver.md +2 -2
  21. package/docs/playwright.md +14 -0
  22. package/docs/quickstart.md +40 -13
  23. package/docs/translation.md +83 -56
  24. package/docs/typescript.md +49 -3
  25. package/docs/wiki/Books-&-Posts.md +0 -0
  26. package/docs/wiki/Community-Helpers-&-Plugins.md +0 -0
  27. package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -0
  28. package/docs/wiki/Examples.md +0 -0
  29. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -0
  30. package/docs/wiki/Home.md +0 -0
  31. package/docs/wiki/Release-Process.md +0 -0
  32. package/docs/wiki/Roadmap.md +0 -0
  33. package/docs/wiki/Tests.md +0 -0
  34. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -0
  35. package/docs/wiki/Videos.md +0 -0
  36. package/lib/codecept.js +3 -1
  37. package/lib/command/definitions.js +26 -2
  38. package/lib/command/generate.js +23 -9
  39. package/lib/command/init.js +32 -7
  40. package/lib/command/run.js +5 -1
  41. package/lib/container.js +15 -15
  42. package/lib/helper/Appium.js +60 -22
  43. package/lib/helper/GraphQL.js +6 -6
  44. package/lib/helper/Nightmare.js +4 -4
  45. package/lib/helper/Playwright.js +102 -39
  46. package/lib/helper/Protractor.js +25 -25
  47. package/lib/helper/Puppeteer.js +7 -7
  48. package/lib/helper/TestCafe.js +12 -12
  49. package/lib/helper/WebDriver.js +32 -32
  50. package/lib/helper/errors/ElementNotFound.js +1 -1
  51. package/lib/helper/extras/PlaywrightRestartOpts.js +0 -2
  52. package/lib/interfaces/bdd.js +26 -1
  53. package/lib/listener/artifacts.js +19 -0
  54. package/lib/rerun.js +12 -13
  55. package/lib/step.js +5 -5
  56. package/lib/translation.js +32 -0
  57. package/package.json +11 -17
  58. package/translations/ru-RU.js +1 -0
  59. package/typings/index.d.ts +29 -1
  60. package/typings/promiseBasedTypes.d.ts +10466 -0
  61. package/typings/types.d.ts +62 -12
  62. package/CHANGELOG.md +0 -2340
@@ -44,6 +44,8 @@ const {
44
44
  } = require('./extras/PlaywrightRestartOpts');
45
45
  const { createValueEngine, createDisabledEngine } = require('./extras/PlaywrightPropEngine');
46
46
 
47
+ const pathSeparator = path.sep;
48
+
47
49
  /**
48
50
  * ## Configuration
49
51
  *
@@ -52,7 +54,7 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
52
54
  * @typedef PlaywrightConfig
53
55
  * @type {object}
54
56
  * @prop {string} url - base url of website to be tested
55
- * @prop {string} browser - a browser to test on, either: `chromium`, `firefox`, `webkit`, `electron`. Default: chromium.
57
+ * @prop {string} [browser] - a browser to test on, either: `chromium`, `firefox`, `webkit`, `electron`. Default: chromium.
56
58
  * @prop {boolean} [show=false] - show browser window.
57
59
  * @prop {string|boolean} [restart=false] - restart strategy between tests. Possible values:
58
60
  * * 'context' or **false** - restarts [browser context](https://playwright.dev/docs/api/class-browsercontext) but keeps running browser. Recommended by Playwright team to keep tests isolated.
@@ -80,8 +82,11 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
80
82
  * @prop {string} [locale] - locale string. Example: 'en-GB', 'de-DE', 'fr-FR', ...
81
83
  * @prop {boolean} [manualStart] - do not start browser before a test, start it manually inside a helper with `this.helpers["Playwright"]._startBrowser()`.
82
84
  * @prop {object} [chromium] - pass additional chromium options
85
+ * @prop {object} [firefox] - pass additional firefox options
83
86
  * @prop {object} [electron] - (pass additional electron options
84
87
  * @prop {any} [channel] - (While Playwright can operate against the stock Google Chrome and Microsoft Edge browsers available on the machine. In particular, current Playwright version will support Stable and Beta channels of these browsers. See [Google Chrome & Microsoft Edge](https://playwright.dev/docs/browsers/#google-chrome--microsoft-edge).
88
+ * @prop {string[]} [ignoreLog] - An array with console message types that are not logged to debug log. Default value is `['warning', 'log']`. E.g. you can set `[]` to log all messages. See all possible [values](https://playwright.dev/docs/api/class-consolemessage#console-message-type).
89
+ * @prop {boolean} [ignoreHTTPSErrors] - Allows access to untrustworthy pages, e.g. to a page with an expired certificate. Default value is `false`
85
90
  */
86
91
  const config = {};
87
92
 
@@ -448,7 +453,7 @@ class Playwright extends Helper {
448
453
  const existingPages = await this.browserContext.pages();
449
454
  mainPage = existingPages[0] || await this.browserContext.newPage();
450
455
  }
451
- targetCreatedHandler.call(this, mainPage);
456
+ await targetCreatedHandler.call(this, mainPage);
452
457
 
453
458
  await this._setPage(mainPage);
454
459
 
@@ -513,12 +518,13 @@ class Playwright extends Helper {
513
518
  browserContext = browser.context();
514
519
  page = await browser.firstWindow();
515
520
  } else {
516
- browserContext = await this.browser.newContext(config);
521
+ browserContext = await this.browser.newContext(Object.assign(this.options, config));
517
522
  page = await browserContext.newPage();
518
523
  }
519
524
 
520
- targetCreatedHandler.call(this, page);
521
- this._setPage(page);
525
+ if (this.options.trace) await browserContext.tracing.start({ screenshots: true, snapshots: true });
526
+ await targetCreatedHandler.call(this, page);
527
+ await this._setPage(page);
522
528
  // Create a new page inside context.
523
529
  return browserContext;
524
530
  },
@@ -740,6 +746,19 @@ class Playwright extends Helper {
740
746
  });
741
747
 
742
748
  this.isRunning = true;
749
+ return this.browser;
750
+ }
751
+
752
+ /**
753
+ * Create a new browser context with a page. \
754
+ * Usually it should be run from a custom helper after call of `_startBrowser()`
755
+ * @param {object} [contextOptions] See https://playwright.dev/docs/api/class-browser#browser-new-context
756
+ */
757
+ async _createContextPage(contextOptions) {
758
+ this.browserContext = await this.browser.newContext(contextOptions);
759
+ const page = await this.browserContext.newPage();
760
+ targetCreatedHandler.call(this, page);
761
+ await this._setPage(page);
743
762
  }
744
763
 
745
764
  _getType() {
@@ -818,8 +837,8 @@ class Playwright extends Helper {
818
837
  if (this.isElectron) {
819
838
  throw new Error('Cannot open pages inside an Electron container');
820
839
  }
821
- if (!(/^\w+\:\/\//.test(url))) {
822
- url = this.options.url + url;
840
+ if (!(/^\w+\:(\/\/|.+)/.test(url))) {
841
+ url = this.options.url + (url.startsWith('/') ? url : `/${url}`);
823
842
  }
824
843
 
825
844
  if (this.options.basicAuth && (this.isAuthenticated !== true)) {
@@ -910,7 +929,7 @@ class Playwright extends Helper {
910
929
  */
911
930
  async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
912
931
  const els = await this._locate(locator);
913
- assertElementExists(els);
932
+ assertElementExists(els, locator);
914
933
 
915
934
  // Use manual mouse.move instead of .hover() so the offset can be added to the coordinates
916
935
  const { x, y } = await clickablePoint(els[0]);
@@ -946,6 +965,26 @@ class Playwright extends Helper {
946
965
  return this.page.dragAndDrop(buildLocatorString(src), buildLocatorString(dst), options);
947
966
  }
948
967
 
968
+ /**
969
+ * Restart browser with a new context and a new page
970
+ *
971
+ * ```js
972
+ * // Restart browser and use a new timezone
973
+ * I.restartBrowser({ timezoneId: 'America/Phoenix' });
974
+ * // Open URL in a new page in changed timezone
975
+ * I.amOnPage('/');
976
+ * // Restart browser, allow reading/copying of text from/into clipboard in Chrome
977
+ * I.restartBrowser({ permissions: ['clipboard-read', 'clipboard-write'] });
978
+ * ```
979
+ *
980
+ * @param {object} [contextOptions] [Options for browser context](https://playwright.dev/docs/api/class-browser#browser-new-context) when starting new browser
981
+ */
982
+ async restartBrowser(contextOptions) {
983
+ await this._stopBrowser();
984
+ await this._startBrowser();
985
+ await this._createContextPage(contextOptions);
986
+ }
987
+
949
988
  /**
950
989
  * Reload the current page.
951
990
  *
@@ -1187,7 +1226,7 @@ class Playwright extends Helper {
1187
1226
  if (!page) {
1188
1227
  throw new Error(`There is no ability to switch to next tab with offset ${num}`);
1189
1228
  }
1190
- targetCreatedHandler.call(this, page);
1229
+ await targetCreatedHandler.call(this, page);
1191
1230
  await this._setPage(page);
1192
1231
  return this._waitForAction();
1193
1232
  }
@@ -1271,7 +1310,7 @@ class Playwright extends Helper {
1271
1310
  throw new Error('Cannot open new tabs inside an Electron container');
1272
1311
  }
1273
1312
  const page = await this.browserContext.newPage(options);
1274
- targetCreatedHandler.call(this, page);
1313
+ await targetCreatedHandler.call(this, page);
1275
1314
  await this._setPage(page);
1276
1315
  return this._waitForAction();
1277
1316
  }
@@ -1361,7 +1400,7 @@ class Playwright extends Helper {
1361
1400
  }
1362
1401
 
1363
1402
  /**
1364
- * Handles a file download.Aa file name is required to save the file on disk.
1403
+ * Handles a file download. A file name is required to save the file on disk.
1365
1404
  * Files are saved to "output" directory.
1366
1405
  *
1367
1406
  * Should be used with [FileSystem helper](https://codecept.io/helpers/FileSystem) to check that file were downloaded correctly.
@@ -1370,17 +1409,19 @@ class Playwright extends Helper {
1370
1409
  * I.handleDownloads('downloads/avatar.jpg');
1371
1410
  * I.click('Download Avatar');
1372
1411
  * I.amInPath('output/downloads');
1373
- * I.waitForFile('downloads/avatar.jpg', 5);
1412
+ * I.waitForFile('avatar.jpg', 5);
1374
1413
  *
1375
1414
  * ```
1376
1415
  *
1377
1416
  * @param {string} [fileName] set filename for downloaded file
1378
1417
  * @return {Promise<void>}
1379
1418
  */
1380
- async handleDownloads(fileName = 'downloads') {
1419
+ async handleDownloads(fileName) {
1381
1420
  this.page.waitForEvent('download').then(async (download) => {
1382
1421
  const filePath = await download.path();
1383
- const downloadPath = path.join(global.output_dir, fileName || path.basename(filePath));
1422
+ fileName = fileName || `downloads/${path.basename(filePath)}`;
1423
+
1424
+ const downloadPath = path.join(global.output_dir, fileName);
1384
1425
  if (!fs.existsSync(path.dirname(downloadPath))) {
1385
1426
  fs.mkdirSync(path.dirname(downloadPath), '0777');
1386
1427
  }
@@ -1920,7 +1961,7 @@ class Playwright extends Helper {
1920
1961
  throw new Error(`File at ${file} can not be found on local system`);
1921
1962
  }
1922
1963
  const els = await findFields.call(this, locator);
1923
- assertElementExists(els, 'Field');
1964
+ assertElementExists(els, locator, 'Field');
1924
1965
  await els[0].setInputFiles(file);
1925
1966
  return this._waitForAction();
1926
1967
  }
@@ -2208,7 +2249,7 @@ class Playwright extends Helper {
2208
2249
  */
2209
2250
  async seeNumberOfElements(locator, num) {
2210
2251
  const elements = await this._locate(locator);
2211
- return equals(`expected number of elements (${locator}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
2252
+ return equals(`expected number of elements (${(new Locator(locator))}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
2212
2253
  }
2213
2254
 
2214
2255
  /**
@@ -2228,7 +2269,7 @@ class Playwright extends Helper {
2228
2269
  */
2229
2270
  async seeNumberOfVisibleElements(locator, num) {
2230
2271
  const res = await this.grabNumberOfVisibleElements(locator);
2231
- return equals(`expected number of visible elements (${locator}) is ${num}, but found ${res}`).assert(res, num);
2272
+ return equals(`expected number of visible elements (${(new Locator(locator))}) is ${num}, but found ${res}`).assert(res, num);
2232
2273
  }
2233
2274
 
2234
2275
  /**
@@ -2355,6 +2396,7 @@ class Playwright extends Helper {
2355
2396
  *
2356
2397
  * @param {string|function} fn function to be executed in browser context.
2357
2398
  * @param {any} [arg] optional argument to pass to the function
2399
+ * @returns {Promise<any>}
2358
2400
  */
2359
2401
  async executeScript(fn, arg) {
2360
2402
  let context = this.page;
@@ -2587,7 +2629,7 @@ class Playwright extends Helper {
2587
2629
  }
2588
2630
  return true;
2589
2631
  });
2590
- return equals(`all elements (${locator}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount);
2632
+ return equals(`all elements (${(new Locator(locator))}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount);
2591
2633
  }
2592
2634
 
2593
2635
  /**
@@ -2625,7 +2667,7 @@ class Playwright extends Helper {
2625
2667
  }
2626
2668
  return true;
2627
2669
  });
2628
- return equals(`all elements (${locator}) to have attributes ${JSON.stringify(attributes)}`).assert(chunked.length, elemAmount);
2670
+ return equals(`all elements (${(new Locator(locator))}) to have attributes ${JSON.stringify(attributes)}`).assert(chunked.length, elemAmount);
2629
2671
  }
2630
2672
 
2631
2673
  /**
@@ -2729,7 +2771,7 @@ class Playwright extends Helper {
2729
2771
  assertElementExists(res, locator);
2730
2772
  if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`);
2731
2773
  const elem = res[0];
2732
- this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
2774
+ this.debug(`Screenshot of ${(new Locator(locator))} element has been saved to ${outputFile}`);
2733
2775
  return elem.screenshot({ path: outputFile, type: 'png' });
2734
2776
  }
2735
2777
 
@@ -2824,29 +2866,28 @@ class Playwright extends Helper {
2824
2866
  }
2825
2867
 
2826
2868
  if (this.options.recordVideo && this.page && this.page.video()) {
2827
- const videoPath = `${global.output_dir}/videos/${clearString(test.title)}.failed.webm`;
2828
- test.artifacts.video = await this.page.video().path();
2829
- fs.rename(test.artifacts.video, videoPath, (() => {
2830
- test.artifacts.video = videoPath;
2831
- }));
2869
+ test.artifacts.video = await saveVideoForPage(this.page, `${test.title}.failed`);
2870
+ for (const sessionName in this.sessionPages) {
2871
+ test.artifacts[`video_${sessionName}`] = await saveVideoForPage(this.sessionPages[sessionName], `${test.title}_${sessionName}.failed`);
2872
+ }
2832
2873
  }
2833
2874
 
2834
2875
  if (this.options.trace) {
2835
- const path = `${`${global.output_dir}/trace/${clearString(test.title)}`.slice(0, 251)}.zip`;
2836
- await this.browserContext.tracing.stop({ path });
2837
- test.artifacts.trace = path;
2876
+ test.artifacts.trace = await saveTraceForContext(this.browserContext, `${test.title}.failed`);
2877
+ for (const sessionName in this.sessionPages) {
2878
+ if (!this.sessionPages[sessionName].context) continue;
2879
+ test.artifacts[`trace_${sessionName}`] = await saveTraceForContext(this.sessionPages[sessionName].context(), `${test.title}_${sessionName}.failed`);
2880
+ }
2838
2881
  }
2839
2882
  }
2840
2883
 
2841
2884
  async _passed(test) {
2842
2885
  if (this.options.recordVideo && this.page && this.page.video()) {
2843
- const videoPath = `${global.output_dir}/videos/${clearString(test.title)}.passed.webm`;
2844
-
2845
2886
  if (this.options.keepVideoForPassedTests) {
2846
- test.artifacts.video = await this.page.video().path();
2847
- fs.rename(test.artifacts.video, videoPath, (() => {
2848
- test.artifacts.video = videoPath;
2849
- }));
2887
+ test.artifacts.video = await saveVideoForPage(this.page, `${test.title}.passed`);
2888
+ for (const sessionName of Object.keys(this.sessionPages)) {
2889
+ test.artifacts[`video_${sessionName}`] = await saveVideoForPage(this.sessionPages[sessionName], `${test.title}_${sessionName}.passed`);
2890
+ }
2850
2891
  } else {
2851
2892
  this.page.video().delete().catch(e => {});
2852
2893
  }
@@ -2854,9 +2895,13 @@ class Playwright extends Helper {
2854
2895
 
2855
2896
  if (this.options.trace) {
2856
2897
  if (this.options.keepTraceForPassedTests) {
2857
- const path = `${global.output_dir}/trace/${clearString(test.title)}.zip`;
2858
- await this.browserContext.tracing.stop({ path });
2859
- test.artifacts.trace = path;
2898
+ if (this.options.trace) {
2899
+ test.artifacts.trace = await saveTraceForContext(this.browserContext, `${test.title}.passed`);
2900
+ for (const sessionName in this.sessionPages) {
2901
+ if (!this.sessionPages[sessionName].context) continue;
2902
+ test.artifacts[`trace_${sessionName}`] = await saveTraceForContext(this.sessionPages[sessionName].context(), `${test.title}_${sessionName}.passed`);
2903
+ }
2904
+ }
2860
2905
  } else {
2861
2906
  await this.browserContext.tracing.stop();
2862
2907
  }
@@ -3770,7 +3815,7 @@ async function targetCreatedHandler(page) {
3770
3815
  page.on('load', () => {
3771
3816
  page.$('body')
3772
3817
  .catch(() => null)
3773
- .then(async context => {
3818
+ .then(async () => {
3774
3819
  if (this.context && this.context._type === 'Frame') {
3775
3820
  // we are inside iframe?
3776
3821
  const frameEl = await this.context.frameElement();
@@ -3795,7 +3840,7 @@ async function targetCreatedHandler(page) {
3795
3840
  try {
3796
3841
  await page.setViewportSize(parseWindowSize(this.options.windowSize));
3797
3842
  } catch (err) {
3798
- // target can be already closed, ignoring...
3843
+ this.debug('Target can be already closed, ignoring...');
3799
3844
  }
3800
3845
  }
3801
3846
  }
@@ -3920,3 +3965,21 @@ async function refreshContextSession() {
3920
3965
  });
3921
3966
  }
3922
3967
  }
3968
+
3969
+ async function saveVideoForPage(page, name) {
3970
+ if (!page.video()) return null;
3971
+ const fileName = `${global.output_dir}${pathSeparator}videos${pathSeparator}${Date.now()}_${clearString(name).slice(0, 245)}.webm`;
3972
+ page.video().saveAs(fileName).then(() => {
3973
+ if (!page) return;
3974
+ page.video().delete().catch(e => {});
3975
+ });
3976
+ return fileName;
3977
+ }
3978
+
3979
+ async function saveTraceForContext(context, name) {
3980
+ if (!context) return;
3981
+ if (!context.tracing) return;
3982
+ const fileName = `${`${global.output_dir}${pathSeparator}trace${pathSeparator}${Date.now()}_${clearString(name)}`.slice(0, 245)}.zip`;
3983
+ await context.tracing.stop({ path: fileName });
3984
+ return fileName;
3985
+ }
File without changes
@@ -153,7 +153,7 @@ class Protractor extends Helper {
153
153
  if (config.proxy) config.capabilities.proxy = config.proxy;
154
154
  if (config.browser) config.capabilities.browserName = config.browser;
155
155
 
156
- config.waitForTimeout /= 1000; // convert to seconds
156
+ config.waitForTimeoutInSeconds = config.waitForTimeout / 1000; // convert to seconds
157
157
  return config;
158
158
  }
159
159
 
@@ -1011,7 +1011,7 @@ class Protractor extends Helper {
1011
1011
  */
1012
1012
  async grabTextFrom(locator) {
1013
1013
  const texts = await this.grabTextFromAll(locator);
1014
- assertElementExists(texts);
1014
+ assertElementExists(texts, locator);
1015
1015
  if (texts.length > 1) {
1016
1016
  this.debugSection('GrabText', `Using first element out of ${texts.length}`);
1017
1017
  }
@@ -1056,7 +1056,7 @@ class Protractor extends Helper {
1056
1056
  */
1057
1057
  async grabHTMLFrom(locator) {
1058
1058
  const html = await this.grabHTMLFromAll(locator);
1059
- assertElementExists(html);
1059
+ assertElementExists(html, locator);
1060
1060
  if (html.length > 1) {
1061
1061
  this.debugSection('GrabHTMl', `Using first element out of ${html.length}`);
1062
1062
  }
@@ -1381,7 +1381,7 @@ class Protractor extends Helper {
1381
1381
  */
1382
1382
  async seeNumberOfElements(locator, num) {
1383
1383
  const elements = await this._locate(locator);
1384
- return equals(`expected number of elements (${locator}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
1384
+ return equals(`expected number of elements (${(new Locator(locator))}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
1385
1385
  }
1386
1386
 
1387
1387
  /**
@@ -1399,7 +1399,7 @@ class Protractor extends Helper {
1399
1399
  */
1400
1400
  async seeNumberOfVisibleElements(locator, num) {
1401
1401
  const res = await this.grabNumberOfVisibleElements(locator);
1402
- return equals(`expected number of visible elements (${locator}) is ${num}, but found ${res}`).assert(res, num);
1402
+ return equals(`expected number of visible elements (${(new Locator(locator))}) is ${num}, but found ${res}`).assert(res, num);
1403
1403
  }
1404
1404
 
1405
1405
  /**
@@ -1456,7 +1456,7 @@ class Protractor extends Helper {
1456
1456
  missingAttributes.push(...missing);
1457
1457
  }
1458
1458
  }
1459
- return equals(`all elements (${locator}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(missingAttributes.length, 0);
1459
+ return equals(`all elements (${(new Locator(locator))}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(missingAttributes.length, 0);
1460
1460
  }
1461
1461
 
1462
1462
  /**
@@ -1492,7 +1492,7 @@ class Protractor extends Helper {
1492
1492
  }
1493
1493
  }
1494
1494
 
1495
- return equals(`all elements (${locator}) to have attributes ${JSON.stringify(attributes)}`).assert(missingAttributes.length, 0);
1495
+ return equals(`all elements (${(new Locator(locator))}) to have attributes ${JSON.stringify(attributes)}`).assert(missingAttributes.length, 0);
1496
1496
  }
1497
1497
 
1498
1498
  /**
@@ -1650,7 +1650,7 @@ class Protractor extends Helper {
1650
1650
  assertElementExists(res, locator);
1651
1651
  if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`);
1652
1652
  const elem = res[0];
1653
- this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
1653
+ this.debug(`Screenshot of ${(new Locator(locator))} element has been saved to ${outputFile}`);
1654
1654
  const png = await elem.takeScreenshot();
1655
1655
  return writeFile(png, outputFile);
1656
1656
  }
@@ -1862,8 +1862,8 @@ class Protractor extends Helper {
1862
1862
  async dragAndDrop(srcElement, destElement) {
1863
1863
  const srcEl = await this._locate(srcElement, true);
1864
1864
  const destEl = await this._locate(destElement, true);
1865
- assertElementExists(srcEl);
1866
- assertElementExists(destEl);
1865
+ assertElementExists(srcEl, srcElement);
1866
+ assertElementExists(destEl, destElement);
1867
1867
  return this.browser
1868
1868
  .actions()
1869
1869
  .dragAndDrop(srcEl[0], destEl[0])
@@ -2046,7 +2046,7 @@ class Protractor extends Helper {
2046
2046
  *
2047
2047
  */
2048
2048
  async waitForElement(locator, sec = null) {
2049
- const aSec = sec || this.options.waitForTimeout;
2049
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2050
2050
  const el = global.element(guessLocator(locator) || global.by.css(locator));
2051
2051
  return this.browser.wait(EC.presenceOf(el), aSec * 1000);
2052
2052
  }
@@ -2072,7 +2072,7 @@ class Protractor extends Helper {
2072
2072
  *
2073
2073
  */
2074
2074
  async waitForDetached(locator, sec = null) {
2075
- const aSec = sec || this.options.waitForTimeout;
2075
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2076
2076
  const el = global.element(guessLocator(locator) || global.by.css(locator));
2077
2077
  return this.browser.wait(EC.not(EC.presenceOf(el)), aSec * 1000).catch((err) => {
2078
2078
  if (err.message && err.message.indexOf('Wait timed out after') > -1) {
@@ -2089,7 +2089,7 @@ class Protractor extends Helper {
2089
2089
  * ```
2090
2090
  */
2091
2091
  async waitForClickable(locator, sec = null) {
2092
- const aSec = sec || this.options.waitForTimeout;
2092
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2093
2093
  const el = global.element(guessLocator(locator) || global.by.css(locator));
2094
2094
  return this.browser.wait(EC.elementToBeClickable(el), aSec * 1000);
2095
2095
  }
@@ -2108,7 +2108,7 @@ class Protractor extends Helper {
2108
2108
  *
2109
2109
  */
2110
2110
  async waitForVisible(locator, sec = null) {
2111
- const aSec = sec || this.options.waitForTimeout;
2111
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2112
2112
  const el = global.element(guessLocator(locator) || global.by.css(locator));
2113
2113
  return this.browser.wait(EC.visibilityOf(el), aSec * 1000);
2114
2114
  }
@@ -2144,7 +2144,7 @@ class Protractor extends Helper {
2144
2144
  *
2145
2145
  */
2146
2146
  async waitForInvisible(locator, sec = null) {
2147
- const aSec = sec || this.options.waitForTimeout;
2147
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2148
2148
  const el = global.element(guessLocator(locator) || global.by.css(locator));
2149
2149
  return this.browser.wait(EC.invisibilityOf(el), aSec * 1000);
2150
2150
  }
@@ -2179,12 +2179,12 @@ class Protractor extends Helper {
2179
2179
  };
2180
2180
  }
2181
2181
 
2182
- const aSec = sec || this.options.waitForTimeout;
2182
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2183
2183
  const guessLoc = guessLocator(locator) || global.by.css(locator);
2184
2184
 
2185
2185
  return this.browser.wait(visibilityCountOf(guessLoc, num), aSec * 1000)
2186
2186
  .catch(() => {
2187
- throw Error(`The number of elements (${locator}) is not ${num} after ${aSec} sec`);
2187
+ throw Error(`The number of elements (${(new Locator(locator))}) is not ${num} after ${aSec} sec`);
2188
2188
  });
2189
2189
  }
2190
2190
 
@@ -2198,12 +2198,12 @@ class Protractor extends Helper {
2198
2198
  *
2199
2199
  */
2200
2200
  async waitForEnabled(locator, sec = null) {
2201
- const aSec = sec || this.options.waitForTimeout;
2201
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2202
2202
  const el = global.element(guessLocator(locator) || global.by.css(locator));
2203
2203
 
2204
2204
  return this.browser.wait(EC.elementToBeClickable(el), aSec * 1000)
2205
2205
  .catch(() => {
2206
- throw Error(`element (${locator}) still not enabled after ${aSec} sec`);
2206
+ throw Error(`element (${(new Locator(locator))}) still not enabled after ${aSec} sec`);
2207
2207
  });
2208
2208
  }
2209
2209
 
@@ -2221,7 +2221,7 @@ class Protractor extends Helper {
2221
2221
  *
2222
2222
  */
2223
2223
  async waitForValue(field, value, sec = null) {
2224
- const aSec = sec || this.options.waitForTimeout;
2224
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2225
2225
 
2226
2226
  const valueToBeInElementValue = (loc) => {
2227
2227
  return async () => {
@@ -2271,7 +2271,7 @@ class Protractor extends Helper {
2271
2271
  }
2272
2272
  }
2273
2273
 
2274
- const aSec = sec || this.options.waitForTimeout;
2274
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2275
2275
  return this.browser.wait(() => this.browser.executeScript.call(this.browser, fn, ...args), aSec * 1000);
2276
2276
  }
2277
2277
 
@@ -2288,7 +2288,7 @@ class Protractor extends Helper {
2288
2288
  *
2289
2289
  */
2290
2290
  async waitInUrl(urlPart, sec = null) {
2291
- const aSec = sec || this.options.waitForTimeout;
2291
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2292
2292
  const waitTimeout = aSec * 1000;
2293
2293
 
2294
2294
  return this.browser.wait(EC.urlContains(urlPart), waitTimeout)
@@ -2316,7 +2316,7 @@ class Protractor extends Helper {
2316
2316
  *
2317
2317
  */
2318
2318
  async waitUrlEquals(urlPart, sec = null) {
2319
- const aSec = sec || this.options.waitForTimeout;
2319
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2320
2320
  const waitTimeout = aSec * 1000;
2321
2321
  const baseUrl = this.options.url;
2322
2322
  if (urlPart.indexOf('http') < 0) {
@@ -2355,7 +2355,7 @@ class Protractor extends Helper {
2355
2355
  context = this.context;
2356
2356
  }
2357
2357
  const el = global.element(guessLocator(context) || global.by.css(context));
2358
- const aSec = sec || this.options.waitForTimeout;
2358
+ const aSec = sec || this.options.waitForTimeoutInSeconds;
2359
2359
  return this.browser.wait(EC.textToBePresentInElement(el, text), aSec * 1000);
2360
2360
  }
2361
2361
 
@@ -2414,7 +2414,7 @@ class Protractor extends Helper {
2414
2414
  if (locator) {
2415
2415
  const res = await this._locate(locator, true);
2416
2416
  if (!res || res.length === 0) {
2417
- return truth(`elements of ${locator}`, 'to be seen').assert(false);
2417
+ return truth(`elements of ${(new Locator(locator))}`, 'to be seen').assert(false);
2418
2418
  }
2419
2419
  const elem = res[0];
2420
2420
  const location = await elem.getLocation();
@@ -732,7 +732,7 @@ class Puppeteer extends Helper {
732
732
  */
733
733
  async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
734
734
  const els = await this._locate(locator);
735
- assertElementExists(els);
735
+ assertElementExists(els, locator);
736
736
 
737
737
  // Use manual mouse.move instead of .hover() so the offset can be added to the coordinates
738
738
  const { x, y } = await getClickablePoint(els[0]);
@@ -1795,7 +1795,7 @@ class Puppeteer extends Helper {
1795
1795
  throw new Error(`File at ${file} can not be found on local system`);
1796
1796
  }
1797
1797
  const els = await findFields.call(this, locator);
1798
- assertElementExists(els, 'Field');
1798
+ assertElementExists(els, locator, 'Field');
1799
1799
  await els[0].uploadFile(file);
1800
1800
  return this._waitForAction();
1801
1801
  }
@@ -2084,7 +2084,7 @@ class Puppeteer extends Helper {
2084
2084
  */
2085
2085
  async seeNumberOfElements(locator, num) {
2086
2086
  const elements = await this._locate(locator);
2087
- return equals(`expected number of elements (${locator}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
2087
+ return equals(`expected number of elements (${(new Locator(locator))}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
2088
2088
  }
2089
2089
 
2090
2090
  /**
@@ -2104,7 +2104,7 @@ class Puppeteer extends Helper {
2104
2104
  */
2105
2105
  async seeNumberOfVisibleElements(locator, num) {
2106
2106
  const res = await this.grabNumberOfVisibleElements(locator);
2107
- return equals(`expected number of visible elements (${locator}) is ${num}, but found ${res}`).assert(res, num);
2107
+ return equals(`expected number of visible elements (${(new Locator(locator))}) is ${num}, but found ${res}`).assert(res, num);
2108
2108
  }
2109
2109
 
2110
2110
  /**
@@ -2516,7 +2516,7 @@ class Puppeteer extends Helper {
2516
2516
  }
2517
2517
  return true;
2518
2518
  });
2519
- return equals(`all elements (${locator}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount);
2519
+ return equals(`all elements (${(new Locator(locator))}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount);
2520
2520
  }
2521
2521
 
2522
2522
  /**
@@ -2556,7 +2556,7 @@ class Puppeteer extends Helper {
2556
2556
  }
2557
2557
  return true;
2558
2558
  });
2559
- return equals(`all elements (${locator}) to have attributes ${JSON.stringify(attributes)}`).assert(chunked.length, elemAmount);
2559
+ return equals(`all elements (${(new Locator(locator))}) to have attributes ${JSON.stringify(attributes)}`).assert(chunked.length, elemAmount);
2560
2560
  }
2561
2561
 
2562
2562
  /**
@@ -2659,7 +2659,7 @@ class Puppeteer extends Helper {
2659
2659
  assertElementExists(res, locator);
2660
2660
  if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`);
2661
2661
  const elem = res[0];
2662
- this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
2662
+ this.debug(`Screenshot of ${(new Locator(locator))} element has been saved to ${outputFile}`);
2663
2663
  return elem.screenshot({ path: outputFile, type: 'png' });
2664
2664
  }
2665
2665
 
File without changes