codeceptjs 2.6.7 → 2.6.11

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 (97) hide show
  1. package/CHANGELOG.md +33 -6
  2. package/README.md +11 -11
  3. package/docs/advanced.md +21 -0
  4. package/docs/basics.md +6 -5
  5. package/docs/bdd.md +1 -2
  6. package/docs/books.md +1 -1
  7. package/docs/build/Appium.js +1 -2
  8. package/docs/build/FileSystem.js +3 -3
  9. package/docs/build/Mochawesome.js +1 -1
  10. package/docs/build/Nightmare.js +81 -5
  11. package/docs/build/Playwright.js +100 -17
  12. package/docs/build/Protractor.js +34 -2
  13. package/docs/build/Puppeteer.js +59 -2
  14. package/docs/build/TestCafe.js +23 -0
  15. package/docs/build/WebDriver.js +62 -16
  16. package/docs/changelog.md +152 -125
  17. package/docs/community-helpers.md +7 -3
  18. package/docs/configuration.md +1 -1
  19. package/docs/custom-helpers.md +2 -2
  20. package/docs/data.md +1 -1
  21. package/docs/detox.md +2 -2
  22. package/docs/email.md +1 -1
  23. package/docs/examples.md +12 -2
  24. package/docs/helpers/Appium.md +24 -5
  25. package/docs/helpers/Nightmare.md +42 -0
  26. package/docs/helpers/Playwright.md +41 -4
  27. package/docs/helpers/Protractor.md +14 -0
  28. package/docs/helpers/Puppeteer.md +38 -1
  29. package/docs/helpers/TestCafe.md +14 -0
  30. package/docs/helpers/WebDriver.md +24 -5
  31. package/docs/hooks.md +14 -14
  32. package/docs/locators.md +1 -1
  33. package/docs/playwright.md +13 -0
  34. package/docs/translation.md +21 -1
  35. package/docs/ui.md +2 -2
  36. package/docs/videos.md +4 -4
  37. package/docs/webapi/saveElementScreenshot.mustache +9 -0
  38. package/docs/webapi/type.mustache +11 -6
  39. package/docs/wiki/{Community-Helpers.md → Community-Helpers-&-Plugins.md} +6 -2
  40. package/docs/wiki/Examples.md +11 -1
  41. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +68 -0
  42. package/docs/wiki/Home.md +9 -4
  43. package/docs/wiki/Release-Process.md +24 -0
  44. package/docs/wiki/Tests.md +1391 -0
  45. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +153 -0
  46. package/docs/wiki/Videos.md +3 -3
  47. package/lib/actor.js +1 -1
  48. package/lib/assert/empty.js +1 -1
  49. package/lib/assert/equal.js +1 -1
  50. package/lib/assert/include.js +1 -1
  51. package/lib/assert/truth.js +1 -1
  52. package/lib/codecept.js +2 -3
  53. package/lib/command/configMigrate.js +3 -5
  54. package/lib/command/definitions.js +1 -2
  55. package/lib/command/dryRun.js +1 -2
  56. package/lib/command/gherkin/init.js +1 -1
  57. package/lib/command/gherkin/snippets.js +3 -3
  58. package/lib/command/gherkin/steps.js +2 -3
  59. package/lib/command/info.js +1 -2
  60. package/lib/command/init.js +2 -2
  61. package/lib/command/interactive.js +1 -2
  62. package/lib/command/list.js +3 -4
  63. package/lib/command/run-multiple.js +2 -3
  64. package/lib/command/run-rerun.js +2 -4
  65. package/lib/command/run.js +1 -2
  66. package/lib/container.js +2 -2
  67. package/lib/data/context.js +1 -1
  68. package/lib/event.js +1 -1
  69. package/lib/helper/Appium.js +1 -2
  70. package/lib/helper/FileSystem.js +3 -3
  71. package/lib/helper/Mochawesome.js +1 -1
  72. package/lib/helper/Nightmare.js +54 -5
  73. package/lib/helper/Playwright.js +75 -17
  74. package/lib/helper/Protractor.js +26 -2
  75. package/lib/helper/Puppeteer.js +34 -2
  76. package/lib/helper/TestCafe.js +15 -0
  77. package/lib/helper/WebDriver.js +43 -11
  78. package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
  79. package/lib/hooks.js +1 -2
  80. package/lib/interfaces/gherkin.js +0 -1
  81. package/lib/listener/helpers.js +1 -2
  82. package/lib/listener/mocha.js +0 -1
  83. package/lib/locator.js +2 -2
  84. package/lib/pause.js +1 -1
  85. package/lib/plugin/allure.js +1 -1
  86. package/lib/plugin/autoDelay.js +3 -3
  87. package/lib/plugin/autoLogin.js +1 -1
  88. package/lib/plugin/screenshotOnFail.js +2 -1
  89. package/lib/plugin/standardActingHelpers.js +0 -3
  90. package/lib/recorder.js +1 -1
  91. package/lib/step.js +3 -0
  92. package/lib/ui.js +1 -0
  93. package/package.json +3 -2
  94. package/translations/fr-FR.js +63 -0
  95. package/translations/index.js +5 -4
  96. package/typings/types.d.ts +140 -8
  97. package/docs/wiki/Release-process.md +0 -25
package/CHANGELOG.md CHANGED
@@ -1,3 +1,30 @@
1
+ ## 2.6.11
2
+
3
+ * [Playwright] Playwright 1.4 compatibility
4
+ * [Playwright] Added `ignoreHTTPSErrors` config option (default: false). See #2566 by gurjeetbains
5
+ * Added French translation by @vimar
6
+ * [WebDriver] Updated `dragSlider` to work in WebDriver W3C protocol. Fixes #2557 by suniljaiswal01
7
+
8
+ ## 2.6.10
9
+
10
+ * Fixed saving options for suite via `Feature('title', {key: value})` by @Diokuz. See #2553 and [Docs](https://codecept.io/advanced/#dynamic-configuration)
11
+
12
+ ## 2.6.9
13
+
14
+ * [Puppeteer][Playwright] SessionStorage is now cleared in after hook. See #2524
15
+ * When helper load failed the error stack is now logged by @SkReD. See #2541
16
+ * Small documentation fixes.
17
+
18
+ ## 2.6.8
19
+
20
+ * [WebDriver][Protractor][Playwright][Puppeteer][Nightmare] `saveElementScreenshot` method added to make screenshot of an element. By @suniljaiswal01
21
+ * [Playwright][Puppeteer] Added `type` method to type a text using keyboard with an optional delay.
22
+ * [WebDriver] Added optional `delay` argument to `type` method to slow down typing.
23
+ * [Puppeteer] Fixed `amOnPage` freeze when `getPageTimeout` is 0"; set 30 sec as default timeout by @Vorobeyko.
24
+ * Fixed printing step with null argument in custom helper by @sjana-aj. See #2494
25
+ * Fix missing screenshot on failure when REST helper is in use #2513 by @PeterNgTr
26
+ * Improve error logging in the `screenshotOnFail` plugin #2512 by @pablopaul
27
+
1
28
  ## 2.6.7
2
29
 
3
30
  * Add REST helper into `standardActingHelpers` array #2474 by @PeterNgTr
@@ -164,7 +191,7 @@ I.see('You are logged out');
164
191
  * works with WebDriver helper
165
192
  * Avoid failiure report on successful retry in worker by @koushikmohan1996
166
193
  * Added translation ability to Scenario, Feature and other context methods by @koushikmohan1996
167
- * 📢 Please help us translate context methods to your language! See [italian translation](https://github.com/Codeception/CodeceptJS/blob/master/translations/it-IT.js#L3) as an example and send [patches to vocabularies](https://github.com/Codeception/CodeceptJS/tree/master/translations).
194
+ * 📢 Please help us translate context methods to your language! See [italian translation](https://github.com/codeceptjs/CodeceptJS/blob/master/translations/it-IT.js#L3) as an example and send [patches to vocabularies](https://github.com/codeceptjs/CodeceptJS/tree/master/translations).
168
195
  * allurePlugin: Added `say` comments to allure reports by @PeterNgTr.
169
196
  * Fixed no custom output folder created when executed with run-worker. Fix by @PeterNgTr
170
197
  * [Puppeteer] Fixed error description for context element not found. See #2065. Fix by @PeterNgTr
@@ -249,7 +276,7 @@ I.click('$register_button');
249
276
  Changed pressKey method to resolve issues and extend functionality.
250
277
  * Did not properly recognize 'Meta' (or 'Command') as modifier key.
251
278
  * Right modifier keys did not work in WebDriver using JsonWireProtocol.
252
- * 'Shift' + <key> combination would not reflect actual keyboard behavior.
279
+ * 'Shift' + 'key' combination would not reflect actual keyboard behavior.
253
280
  * Respect sequence with multiple modifier keys passed to pressKey.
254
281
  * Added support to automatic change operation modifier key based on operating system.
255
282
  * [Puppeteer][WebDriver] Added `pressKeyUp` and `pressKeyDown` to press and release modifier keys like `Control` or `Shift`. By @martomo.
@@ -369,7 +396,7 @@ I.mockRequest('POST', '/users', { user: { name: 'fake' }});
369
396
 
370
397
  ## 2.1.5
371
398
 
372
- * **EXPERIMENTAL** [Wix Detox support](https://github.com/Codeception/detox-helper) introduced as standalone helper. Provides a faster alternative to Appium for mobile testing.
399
+ * **EXPERIMENTAL** [Wix Detox support](https://github.com/codeceptjs/detox-helper) introduced as standalone helper. Provides a faster alternative to Appium for mobile testing.
373
400
  * Saving successful commands inside interactive pause into `_output/cli-history` file. By @hubidu
374
401
  * Fixed hanging error handler inside scenario. See #1721 by @haily-lgc.
375
402
  * Fixed by @Vorobeyko: tests did not fail when an exception was raised in async bootstrap.
@@ -602,7 +629,7 @@ Use it with `FileSystem` helper to test availability of a file:
602
629
  * **Using `codecept.conf.js` as default configuration format**
603
630
  * Fixed "enametoolong" error when saving screenshots for data driven tests by @PeterNgTr
604
631
  * Updated NodeJS to 10 in Docker image
605
- * [Pupeteer] Add support to use WSEndpoint. Allows to execute tests remotely. [See #1350] by @gabrielcaires (https://github.com/Codeception/CodeceptJS/pull/1350)
632
+ * [Pupeteer] Add support to use WSEndpoint. Allows to execute tests remotely. [See #1350] by @gabrielcaires (https://github.com/codeceptjs/CodeceptJS/pull/1350)
606
633
  * In interactive shell [Enter] goes to next step. Improvement by @PeterNgTr.
607
634
  * `I.say` accepts second parameter as color to print colorful comments. Improvement by @PeterNgTr.
608
635
 
@@ -1334,7 +1361,7 @@ codeceptjs run users_test.js -c tests
1334
1361
 
1335
1362
  * Protractor ^5.0.0 support (while keeping ^4.0.9 compatibility)
1336
1363
  * Fix 'fullTitle() is not a function' in exit.js by @hubidu. See #388.
1337
- * [Nightmare] Fix for `waitTimeout` by @HughZurname. See #391. Resolves #236* Dockerized CodeceptJS setup by @artiomnist. [See reference](https://github.com/Codeception/CodeceptJS/blob/master/docker/README.md)
1364
+ * [Nightmare] Fix for `waitTimeout` by @HughZurname. See #391. Resolves #236* Dockerized CodeceptJS setup by @artiomnist. [See reference](https://github.com/codeceptjs/CodeceptJS/blob/master/docker/README.md)
1338
1365
 
1339
1366
  ## 0.4.16
1340
1367
 
@@ -1433,7 +1460,7 @@ codeceptjs run -o '{ "bootstrap": "bootstrap.js"}'
1433
1460
  codeceptjs run -o '{ "helpers": {"WebDriverIO": {"browser": "chrome"}}}'
1434
1461
  ```
1435
1462
 
1436
- * Added [regression tests](https://github.com/Codeception/CodeceptJS/tree/master/test/runner) for codeceptjs tests runner.
1463
+ * Added [regression tests](https://github.com/codeceptjs/CodeceptJS/tree/master/test/runner) for codeceptjs tests runner.
1437
1464
 
1438
1465
  ## 0.4.11
1439
1466
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # CodeceptJS
4
4
 
5
- Reference: [Helpers API](https://github.com/Codeception/CodeceptJS/blob/master/docs) | [Demo](https://github.com/Codeception/codeceptjs-demo)
5
+ Reference: [Helpers API](https://github.com/codeceptjs/CodeceptJS/blob/master/docs) | [Demo](https://github.com/codeceptjs/codeceptjs-demo)
6
6
 
7
7
  ## Supercharged E2E Testing
8
8
 
@@ -27,13 +27,13 @@ CodeceptJS tests are:
27
27
 
28
28
  CodeceptJS uses **Helper** modules to provide actions to `I` object. Currently CodeceptJS has these helpers:
29
29
 
30
- * [**Puppeteer**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/Puppeteer.md) - uses Google Chrome's Puppeteer for fast headless testing.
31
- * [**WebDriver**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/WebDriver.md) - uses [webdriverio](http://webdriver.io/) to run tests via WebDriver protocol.
32
- * [**Protractor**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/Protractor.md) - helper empowered by [Protractor](http://protractortest.org/) to run tests via WebDriver protocol.
33
- * [**TestCafe**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/TestCafe.md) - cheap and fast cross-browser test automation.
34
- * [**Nightmare**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/Nightmare.md) - uses Electron and NightmareJS to run tests.
35
- * [**Appium**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/Appium.md) - for **mobile testing** with Appium
36
- * [**Detox**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/Detox.md) - This is a wrapper on top of Detox library, aimied to unify testing experience for CodeceptJS framework. Detox provides a grey box testing for mobile applications, playing especially good for React Native apps.
30
+ * [**Puppeteer**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Puppeteer.md) - uses Google Chrome's Puppeteer for fast headless testing.
31
+ * [**WebDriver**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/WebDriver.md) - uses [webdriverio](http://webdriver.io/) to run tests via WebDriver protocol.
32
+ * [**Protractor**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Protractor.md) - helper empowered by [Protractor](http://protractortest.org/) to run tests via WebDriver protocol.
33
+ * [**TestCafe**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/TestCafe.md) - cheap and fast cross-browser test automation.
34
+ * [**Nightmare**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Nightmare.md) - uses Electron and NightmareJS to run tests.
35
+ * [**Appium**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Appium.md) - for **mobile testing** with Appium
36
+ * [**Detox**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Detox.md) - This is a wrapper on top of Detox library, aimied to unify testing experience for CodeceptJS framework. Detox provides a grey box testing for mobile applications, playing especially good for React Native apps.
37
37
 
38
38
  And more to come...
39
39
 
@@ -113,7 +113,7 @@ Scenario('test some forms', (I) => {
113
113
  ```
114
114
 
115
115
  All actions are performed by I object; assertions functions start with `see` function.
116
- In this examples all methods of `I` are taken from WebDriver helper, see [reference](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/WebDriver.md) to learn how to use them.
116
+ In this examples all methods of `I` are taken from WebDriver helper, see [reference](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/WebDriver.md) to learn how to use them.
117
117
 
118
118
  Let's execute this test with `run` command. Additional option `--steps` will show us the running process. We recommend use `--steps` or `--debug` during development.
119
119
 
@@ -268,8 +268,8 @@ When using typescript, replace `module.exports` with `export` for autocompletion
268
268
 
269
269
  ## Contributing
270
270
 
271
- - ### [Contributing Guide](https://github.com/Codeception/CodeceptJS/blob/master/.github/CONTRIBUTING.md)
272
- - ### [Code of conduct](https://github.com/Codeception/CodeceptJS/blob/master/.github/CODE_OF_CONDUCT.md)
271
+ - ### [Contributing Guide](https://github.com/codeceptjs/CodeceptJS/blob/master/.github/CONTRIBUTING.md)
272
+ - ### [Code of conduct](https://github.com/codeceptjs/CodeceptJS/blob/master/.github/CODE_OF_CONDUCT.md)
273
273
 
274
274
 
275
275
  ## Contributors
package/docs/advanced.md CHANGED
@@ -159,6 +159,27 @@ Feature('My feature', {key: val});
159
159
  Scenario('My scenario', {key: val}, (I) => {});
160
160
  ```
161
161
 
162
+ You can use this options for build your own [plugins](https://codecept.io/hooks/#plugins) with [event listners](https://codecept.io/hooks/#api). Example:
163
+
164
+ ```js
165
+ // for test
166
+ event.dispatcher.on(event.test.before, (test) => {
167
+ ...
168
+ if (test.opts.key) {
169
+ ...
170
+ }
171
+ ...
172
+ });
173
+ // or for suite
174
+ event.dispatcher.on(event.suite.before, (suite) => {
175
+ ...
176
+ if (suite.opts.key) {
177
+ ...
178
+ }
179
+ ...
180
+ });
181
+ ```
182
+
162
183
  ### Timeout
163
184
 
164
185
  By default there is no timeout for tests, however you can change this value for a specific suite:
package/docs/basics.md CHANGED
@@ -213,7 +213,7 @@ I.fillField('password', secret('123456'));
213
213
 
214
214
  ### Assertions
215
215
 
216
- In order to verify the expected behavior of a web application, it's content should be checked.
216
+ In order to verify the expected behavior of a web application, its content should be checked.
217
217
  CodeceptJS provides built-in assertions for that. They start with a `see` (or `dontSee`) prefix.
218
218
 
219
219
  The most general and common assertion is `see`, which checks visilibility of a text on a page:
@@ -296,7 +296,7 @@ Tests are written in a synchronous way. This improves the readability and mainta
296
296
  While writing tests you should not think about promises, and instead should focus on the test scenario.
297
297
 
298
298
  However, behind the scenes **all actions are wrapped in promises**, inside of the `I` object.
299
- [Global promise](https://github.com/codecept-js/CodeceptJS/blob/master/lib/recorder.js) chain is initialized before each test and all `I.*` calls will be appended to it, as well as setup and teardown.
299
+ [Global promise](https://github.com/codeceptjs/CodeceptJS/blob/master/lib/recorder.js) chain is initialized before each test and all `I.*` calls will be appended to it, as well as setup and teardown.
300
300
 
301
301
  > 📺 [Learn how CodeceptJS](https://www.youtube.com/watch?v=MDLLpHAwy_s) works with promises by watching video on YouTube
302
302
 
@@ -402,7 +402,7 @@ You can have multiple configuration files for a the same project, in this case y
402
402
  npx codeceptjs run -c codecept.ci.conf.js
403
403
  ```
404
404
 
405
- Tuning configuration for helpers like WebDriver, Puppeteer can be hard, as it requires good understanding of how these technologies work. Use the [`@codeceptjs/configure`](https://github.com/codecept-js/configure) package with common configuration recipes.
405
+ Tuning configuration for helpers like WebDriver, Puppeteer can be hard, as it requires good understanding of how these technologies work. Use the [`@codeceptjs/configure`](https://github.com/codeceptjs/configure) package with common configuration recipes.
406
406
 
407
407
  For instance, you can set the window size or toggle headless mode, no matter of which helpers are actually used.
408
408
 
@@ -419,7 +419,7 @@ exports.config = {
419
419
  }
420
420
  ```
421
421
 
422
- > ▶ See more [configuration recipes](https://github.com/codecept-js/configure)
422
+ > ▶ See more [configuration recipes](https://github.com/codeceptjs/configure)
423
423
 
424
424
  ## Debug
425
425
 
@@ -616,7 +616,7 @@ AfterSuite((I) => {
616
616
  });
617
617
  ```
618
618
 
619
- [Here are some ideas](https://github.com/codecept-js/CodeceptJS/pull/231#issuecomment-249554933) on where to use BeforeSuite hooks.
619
+ [Here are some ideas](https://github.com/codeceptjs/CodeceptJS/pull/231#issuecomment-249554933) on where to use BeforeSuite hooks.
620
620
 
621
621
  ## Within
622
622
 
@@ -637,6 +637,7 @@ I.see('There were problems creating your account.');
637
637
  ```
638
638
 
639
639
  > ⚠ `within` can cause problems when used incorrectly. If you see a weird behavior of a test try to refactor it to not use `within`. It is recommended to keep within for simplest cases when possible.
640
+ > Since `within` returns a Promise, it may be necessary to `await` the result even when you're not intending to use the return value.
640
641
 
641
642
  `within` can also work with IFrames. A special `frame` locator is required to locate the iframe and get into its context.
642
643
 
package/docs/bdd.md CHANGED
@@ -265,7 +265,7 @@ If we use hashes() with the previous exemple :
265
265
  Given('I have products in my cart', (table) => { // eslint-disable-line
266
266
  //parse the table by header
267
267
  const tableByHeader = table.parse().hashes();
268
- for (const row in tableByHeader) {
268
+ for (const row of tableByHeader) {
269
269
 
270
270
  // take values
271
271
  const name = row.name;
@@ -416,4 +416,3 @@ To run only tests without features use `--tests` option:
416
416
  ```
417
417
  npx codeceptjs run --tests
418
418
  ```
419
-
package/docs/books.md CHANGED
@@ -7,7 +7,7 @@ editLink: false
7
7
  ---
8
8
 
9
9
  # Books & Posts
10
- > Add your own books or posts to our [Wiki Page](https://github.com/Codeception/CodeceptJS/wiki/Books-&-Posts)
10
+ > Add your own books or posts to our [Wiki Page](https://github.com/codeceptjs/CodeceptJS/wiki/Books-&-Posts)
11
11
  ### [Practical End 2 End Testing with CodeceptJS](https://leanpub.com/codeceptjs/)
12
12
 
13
13
  A book by **Paul Vincent Beigang**
@@ -1,13 +1,12 @@
1
1
  let webdriverio;
2
2
  let wdioV4;
3
- let SCREEN_SIZE;
4
3
 
5
4
  const fs = require('fs');
6
5
  const requireg = require('requireg');
7
6
 
8
7
  const Webdriver = require('./WebDriver');
9
8
  const AssertionFailedError = require('../assert/error');
10
- const truth = require('../assert/truth').truth;
9
+ const { truth } = require('../assert/truth');
11
10
  const recorder = require('../recorder');
12
11
  const Locator = require('../locator');
13
12
  const ConnectionRefused = require('./errors/ConnectionRefused');
@@ -3,9 +3,9 @@ const path = require('path');
3
3
  const fs = require('fs');
4
4
 
5
5
  const Helper = require('../helper');
6
- const fileExists = require('../utils').fileExists;
7
- const fileIncludes = require('../assert/include').fileIncludes;
8
- const fileEquals = require('../assert/equal').fileEquals;
6
+ const { fileExists } = require('../utils');
7
+ const { fileIncludes } = require('../assert/include');
8
+ const { fileEquals } = require('../assert/equal');
9
9
 
10
10
  /**
11
11
  * Helper for testing filesystem.
@@ -5,7 +5,7 @@ let currentSuite;
5
5
  const requireg = require('requireg');
6
6
 
7
7
  const Helper = require('../helper');
8
- const clearString = require('../utils').clearString;
8
+ const { clearString } = require('../utils');
9
9
 
10
10
  class Mochawesome extends Helper {
11
11
  constructor(config) {
@@ -3,11 +3,11 @@ const requireg = require('requireg');
3
3
  const urlResolve = require('url').resolve;
4
4
 
5
5
  const Helper = require('../helper');
6
- const stringIncludes = require('../assert/include').includes;
7
- const urlEquals = require('../assert/equal').urlEquals;
8
- const equals = require('../assert/equal').equals;
9
- const empty = require('../assert/empty').empty;
10
- const truth = require('../assert/truth').truth;
6
+ const { includes: stringIncludes } = require('../assert/include');
7
+ const { urlEquals } = require('../assert/equal');
8
+ const { equals } = require('../assert/equal');
9
+ const { empty } = require('../assert/empty');
10
+ const { truth } = require('../assert/truth');
11
11
  const Locator = require('../locator');
12
12
  const ElementNotFound = require('./errors/ElementNotFound');
13
13
  const {
@@ -1600,6 +1600,82 @@ class Nightmare extends Helper {
1600
1600
  return this.browser.refresh();
1601
1601
  }
1602
1602
 
1603
+ /**
1604
+ * Saves screenshot of the specified locator to ouput folder (set in codecept.json or codecept.conf.js).
1605
+ * Filename is relative to output folder.
1606
+ *
1607
+ * ```js
1608
+ * I.saveElementScreenshot(`#submit`,'debug.png');
1609
+ * ```
1610
+ *
1611
+ * @param {string|object} locator element located by CSS|XPath|strict locator.
1612
+ * @param {string} fileName file name to save.
1613
+ *
1614
+ */
1615
+ async saveElementScreenshot(locator, fileName) {
1616
+ const outputFile = screenshotOutputFolder(fileName);
1617
+
1618
+ const rect = await this.grabElementBoundingRect(locator);
1619
+
1620
+ const button_clip = {
1621
+ x: Math.floor(rect.x),
1622
+ y: Math.floor(rect.y),
1623
+ width: Math.floor(rect.width),
1624
+ height: Math.floor(rect.height),
1625
+ };
1626
+
1627
+ this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
1628
+ // take the screenshot
1629
+ await this.browser.screenshot(outputFile, button_clip);
1630
+ }
1631
+
1632
+ /**
1633
+ * Grab the width, height, location of given locator.
1634
+ * Provide `width` or `height`as second param to get your desired prop.
1635
+ * Resumes test execution, so **should be used inside an async function with `await`** operator.
1636
+ *
1637
+ * Returns an object with `x`, `y`, `width`, `height` keys.
1638
+ *
1639
+ * ```js
1640
+ * const value = await I.grabElementBoundingRect('h3');
1641
+ * // value is like { x: 226.5, y: 89, width: 527, height: 220 }
1642
+ * ```
1643
+ *
1644
+ * To get only one metric use second parameter:
1645
+ *
1646
+ * ```js
1647
+ * const width = await I.grabElementBoundingRect('h3', 'width');
1648
+ * // width == 527
1649
+ * ```
1650
+ * @param {string|object} locator element located by CSS|XPath|strict locator.
1651
+ * @param {string} elementSize x, y, width or height of the given element.
1652
+ * @returns {object} Element bounding rectangle
1653
+ */
1654
+ async grabElementBoundingRect(locator, prop) {
1655
+ locator = new Locator(locator, 'css');
1656
+
1657
+ const rect = await this.browser.evaluate(async (by, locator) => {
1658
+ // store the button in a variable
1659
+
1660
+ const build_cluster_btn = await window.codeceptjs.findElement(by, locator);
1661
+
1662
+ // use the getClientRects() function on the button to determine
1663
+ // the size and location
1664
+ const rect = build_cluster_btn.getBoundingClientRect();
1665
+
1666
+ // convert the rectangle to a clip object and return it
1667
+ return {
1668
+ x: rect.left,
1669
+ y: rect.top,
1670
+ width: rect.width,
1671
+ height: rect.height,
1672
+ };
1673
+ }, locator.type, locator.value);
1674
+
1675
+ if (prop) return rect[prop];
1676
+ return rect;
1677
+ }
1678
+
1603
1679
  /**
1604
1680
  * Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
1605
1681
  * Filename is relative to output folder.
@@ -1,7 +1,6 @@
1
1
  const requireg = require('requireg');
2
2
  const path = require('path');
3
3
  const fs = require('fs');
4
- const fsExtra = require('fs-extra');
5
4
 
6
5
  const Helper = require('../helper');
7
6
  const Locator = require('../locator');
@@ -11,7 +10,7 @@ const { urlEquals } = require('../assert/equal');
11
10
  const { equals } = require('../assert/equal');
12
11
  const { empty } = require('../assert/empty');
13
12
  const { truth } = require('../assert/truth');
14
- const isElementClickable = require('./scripts/isElementClickable');
13
+
15
14
  const {
16
15
  xpathLocator,
17
16
  ucfirst,
@@ -160,7 +159,7 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
160
159
  * }
161
160
  * ```
162
161
  *
163
- * #### Example #6: Lunach tests emulating iPhone 6
162
+ * #### Example #6: Launch tests emulating iPhone 6
164
163
  *
165
164
  *
166
165
  *
@@ -234,6 +233,7 @@ class Playwright extends Helper {
234
233
  keepBrowserState: false,
235
234
  show: false,
236
235
  defaultPopupAction: 'accept',
236
+ ignoreHTTPSErrors: false, // Adding it here o that context can be set up to ignore the SSL errors
237
237
  };
238
238
 
239
239
  config = Object.assign(defaults, config);
@@ -348,6 +348,9 @@ class Playwright extends Helper {
348
348
  await this.executeScript('localStorage.clear();').catch((err) => {
349
349
  if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
350
350
  });
351
+ await this.executeScript('sessionStorage.clear();').catch((err) => {
352
+ if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
353
+ });
351
354
  }
352
355
  // await this.closeOtherTabs();
353
356
  return this.browser;
@@ -546,7 +549,7 @@ class Playwright extends Helper {
546
549
  this.browser.on('targetchanged', (target) => {
547
550
  this.debugSection('Url', target.url());
548
551
  });
549
- this.browserContext = await this.browser.newContext({ acceptDownloads: true, ...this.options.emulate });
552
+ this.browserContext = await this.browser.newContext({ ignoreHTTPSErrors: this.options.ignoreHTTPSErrors, acceptDownloads: true, ...this.options.emulate });// Adding the HTTPSError ignore in the context so that we can ignore those errors
550
553
 
551
554
  const existingPages = await this.browserContext.pages();
552
555
 
@@ -722,7 +725,7 @@ class Playwright extends Helper {
722
725
  assertElementExists(els);
723
726
 
724
727
  // Use manual mouse.move instead of .hover() so the offset can be added to the coordinates
725
- const { x, y } = await els[0]._clickablePoint();
728
+ const { x, y } = await clickablePoint(els[0]);
726
729
  await this.page.mouse.move(x + offsetX, y + offsetY);
727
730
  return this._waitForAction();
728
731
  }
@@ -810,7 +813,7 @@ class Playwright extends Helper {
810
813
  const els = await this._locate(locator);
811
814
  assertElementExists(els, locator, 'Element');
812
815
  await els[0].scrollIntoViewIfNeeded();
813
- const elementCoordinates = await els[0]._clickablePoint();
816
+ const elementCoordinates = await clickablePoint(els[0]);
814
817
  await this.executeScript((offsetX, offsetY) => window.scrollBy(offsetX, offsetY), { offsetX: elementCoordinates.x + offsetX, offsetY: elementCoordinates.y + offsetY });
815
818
  } else {
816
819
  await this.executeScript(({ offsetX, offsetY }) => window.scrollTo(offsetX, offsetY), { offsetX, offsetY });
@@ -1432,7 +1435,7 @@ class Playwright extends Helper {
1432
1435
  * @param {string|string[]} key key or array of keys to press.
1433
1436
  *
1434
1437
  *
1435
- * _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([GoogleChrome/Playwright#1313](https://github.com/GoogleChrome/Playwright/issues/1313)).
1438
+ * _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([GoogleChrome/Puppeteer#1313](https://github.com/GoogleChrome/puppeteer/issues/1313)).
1436
1439
  */
1437
1440
  async pressKey(key) {
1438
1441
  const modifiers = [];
@@ -1459,6 +1462,37 @@ class Playwright extends Helper {
1459
1462
  return this._waitForAction();
1460
1463
  }
1461
1464
 
1465
+ /**
1466
+ * Types out the given text into an active field.
1467
+ * To slow down typing use a second parameter, to set interval between key presses.
1468
+ * _Note:_ Should be used when [`fillField`](#fillfield) is not an option.
1469
+ *
1470
+ * ```js
1471
+ * // passing in a string
1472
+ * I.type('Type this out.');
1473
+ *
1474
+ * // typing values with a 100ms interval
1475
+ * I.type('4141555311111111', 100);
1476
+ *
1477
+ * // passing in an array
1478
+ * I.type(['T', 'E', 'X', 'T']);
1479
+ * ```
1480
+ *
1481
+ * @param {string|string[]} key or array of keys to type.
1482
+ * @param {?number} [delay=null] (optional) delay in ms between key presses
1483
+ *
1484
+ */
1485
+ async type(keys, delay = null) {
1486
+ if (!Array.isArray(keys)) {
1487
+ keys = keys.split('');
1488
+ }
1489
+
1490
+ for (const key of keys) {
1491
+ await this.page.keyboard.press(key);
1492
+ if (delay) await this.wait(delay / 1000);
1493
+ }
1494
+ }
1495
+
1462
1496
  /**
1463
1497
  * Fills a text field or textarea, after clearing its value, with the given string.
1464
1498
  * Field is located by name, label, CSS, or XPath.
@@ -2176,8 +2210,8 @@ class Playwright extends Helper {
2176
2210
  const src = await this._locate(locator);
2177
2211
  assertElementExists(src, locator, 'Slider Element');
2178
2212
 
2179
- // Note: Using private api ._clickablePoint because the .BoundingBox does not take into account iframe offsets!
2180
- const sliderSource = await src[0]._clickablePoint();
2213
+ // Note: Using clickablePoint private api because the .BoundingBox does not take into account iframe offsets!
2214
+ const sliderSource = await clickablePoint(src[0]);
2181
2215
 
2182
2216
  // Drag start point
2183
2217
  await this.page.mouse.move(sliderSource.x, sliderSource.y, { steps: 5 });
@@ -2216,6 +2250,29 @@ class Playwright extends Helper {
2216
2250
  return array.length === 1 ? array[0] : array;
2217
2251
  }
2218
2252
 
2253
+ /**
2254
+ * Saves screenshot of the specified locator to ouput folder (set in codecept.json or codecept.conf.js).
2255
+ * Filename is relative to output folder.
2256
+ *
2257
+ * ```js
2258
+ * I.saveElementScreenshot(`#submit`,'debug.png');
2259
+ * ```
2260
+ *
2261
+ * @param {string|object} locator element located by CSS|XPath|strict locator.
2262
+ * @param {string} fileName file name to save.
2263
+ *
2264
+ */
2265
+ async saveElementScreenshot(locator, fileName) {
2266
+ const outputFile = screenshotOutputFolder(fileName);
2267
+
2268
+ const res = await this._locate(locator);
2269
+ assertElementExists(res, locator);
2270
+ if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`);
2271
+ const elem = res[0];
2272
+ this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
2273
+ return elem.screenshot({ path: outputFile, type: 'png' });
2274
+ }
2275
+
2219
2276
  /**
2220
2277
  * Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
2221
2278
  * Filename is relative to output folder.
@@ -2674,7 +2731,7 @@ class Playwright extends Helper {
2674
2731
  /**
2675
2732
  * Waits for navigation to finish. By default takes configured `waitForNavigation` option.
2676
2733
  *
2677
- * See [Pupeteer's reference](https://github.com/GoogleChrome/Playwright/blob/master/docs/api.md#pagewaitfornavigationoptions)
2734
+ * See [Pupeteer's reference](https://github.com/microsoft/Playwright/blob/master/docs/api.md#pagewaitfornavigationoptions)
2678
2735
  *
2679
2736
  * @param {*} opts
2680
2737
  */
@@ -2835,7 +2892,14 @@ async function proceedClick(locator, context = null, options = {}) {
2835
2892
  } else {
2836
2893
  assertElementExists(els, locator, 'Clickable element');
2837
2894
  }
2838
- await els[0].click(options);
2895
+ /*
2896
+ using the force true options itself but instead dispatching a click
2897
+ */
2898
+ if (options.force) {
2899
+ await els[0].dispatchEvent('click');
2900
+ } else {
2901
+ await els[0].click(options);
2902
+ }
2839
2903
  const promises = [];
2840
2904
  if (options.waitForNavigation) {
2841
2905
  promises.push(this.waitForNavigation());
@@ -2957,9 +3021,9 @@ async function proceedDragAndDrop(sourceLocator, destinationLocator, options = {
2957
3021
  const dst = await this._locate(destinationLocator);
2958
3022
  assertElementExists(dst, destinationLocator, 'Destination Element');
2959
3023
 
2960
- // Note: Using private api ._clickablePoint becaues the .BoundingBox does not take into account iframe offsets!
2961
- const dragSource = await src[0]._clickablePoint();
2962
- const dragDestination = await dst[0]._clickablePoint();
3024
+ // Note: Using clickablePoint private api becaues the .BoundingBox does not take into account iframe offsets!
3025
+ const dragSource = await clickablePoint(src[0]);
3026
+ const dragDestination = await clickablePoint(dst[0]);
2963
3027
 
2964
3028
  // Drag start point
2965
3029
  await this.page.mouse.move(dragSource.x, dragSource.y, { steps: 5 });
@@ -3084,10 +3148,20 @@ function $XPath(element, selector) {
3084
3148
  async function targetCreatedHandler(page) {
3085
3149
  if (!page) return;
3086
3150
  this.withinLocator = null;
3087
- page.on('load', (frame) => {
3151
+ page.on('load', () => {
3088
3152
  page.$('body')
3089
3153
  .catch(() => null)
3090
- .then(context => this.context = context);
3154
+ .then(async context => {
3155
+ if (this.context._type === 'Frame') {
3156
+ // we are inside iframe?
3157
+ const frameEl = await this.context.frameElement();
3158
+ this.context = await frameEl.contentFrame();
3159
+ return;
3160
+ }
3161
+ // if context element was in iframe - keep it
3162
+ // if (await this.context.ownerFrame()) return;
3163
+ this.context = context;
3164
+ });
3091
3165
  });
3092
3166
  page.on('console', (msg) => {
3093
3167
  this.debugSection(`Browser:${ucfirst(msg.type())}`, (msg._text || '') + msg.args().join(' '));
@@ -3106,7 +3180,7 @@ async function targetCreatedHandler(page) {
3106
3180
  }
3107
3181
 
3108
3182
  // List of key values to key definitions
3109
- // https://github.com/GoogleChrome/Playwright/blob/v1.20.0/lib/USKeyboardLayout.js
3183
+ // https://github.com/puppeteer/puppeteer/blob/v1.20.0/lib/USKeyboardLayout.js
3110
3184
  const keyDefinitionMap = {
3111
3185
  /* eslint-disable quote-props */
3112
3186
  '0': 'Digit0',
@@ -3170,3 +3244,12 @@ function getNormalizedKey(key) {
3170
3244
  }
3171
3245
  return normalizedKey;
3172
3246
  }
3247
+
3248
+ async function clickablePoint(el) {
3249
+ const rect = await el.boundingBox();
3250
+ if (!rect) throw new ElementNotFound(el);
3251
+ const {
3252
+ x, y, width, height,
3253
+ } = rect;
3254
+ return { x: x + width / 2, y: y + height / 2 };
3255
+ }