codeceptjs 3.0.6 → 3.0.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.
@@ -396,6 +396,7 @@ class WebDriver extends Helper {
396
396
  this.isRunning = false;
397
397
  this.sessionWindows = {};
398
398
  this.activeSessionName = '';
399
+ this.customLocatorStrategies = config.customLocatorStrategies;
399
400
 
400
401
  this._setConfig(config);
401
402
 
@@ -503,6 +504,33 @@ class WebDriver extends Helper {
503
504
  }
504
505
  }
505
506
 
507
+ _lookupCustomLocator(customStrategy) {
508
+ if (typeof (this.customLocatorStrategies) !== 'object') {
509
+ return null;
510
+ }
511
+ const strategy = this.customLocatorStrategies[customStrategy];
512
+ return typeof (strategy) === 'function' ? strategy : null;
513
+ }
514
+
515
+ _isCustomLocator(locator) {
516
+ const locatorObj = new Locator(locator);
517
+ if (locatorObj.isCustom()) {
518
+ const customLocator = this._lookupCustomLocator(locatorObj.type);
519
+ if (customLocator) {
520
+ return true;
521
+ }
522
+ throw new Error('Please define "customLocatorStrategies" as an Object and the Locator Strategy as a "function".');
523
+ }
524
+ return false;
525
+ }
526
+
527
+ async _res(locator) {
528
+ const res = (this._isShadowLocator(locator) || this._isCustomLocator(locator))
529
+ ? await this._locate(locator)
530
+ : await this.$$(withStrictLocator(locator));
531
+ return res;
532
+ }
533
+
506
534
  async _startBrowser() {
507
535
  try {
508
536
  if (this.options.multiremote) {
@@ -530,9 +558,22 @@ class WebDriver extends Helper {
530
558
  await this._resizeWindowIfNeeded(this.browser, this.options.windowSize);
531
559
 
532
560
  this.$$ = this.browser.$$.bind(this.browser);
561
+
562
+ if (this._isCustomLocatorStrategyDefined()) {
563
+ Object.keys(this.customLocatorStrategies).forEach(async (customLocator) => {
564
+ this.debugSection('Weddriver', `adding custom locator strategy: ${customLocator}`);
565
+ const locatorFunction = this._lookupCustomLocator(customLocator);
566
+ this.browser.addLocatorStrategy(customLocator, locatorFunction);
567
+ });
568
+ }
569
+
533
570
  return this.browser;
534
571
  }
535
572
 
573
+ _isCustomLocatorStrategyDefined() {
574
+ return this.customLocatorStrategies && Object.keys(this.customLocatorStrategies).length;
575
+ }
576
+
536
577
  async _stopBrowser() {
537
578
  if (this.browser && this.isRunning) await this.browser.deleteSession();
538
579
  }
@@ -755,17 +796,34 @@ class WebDriver extends Helper {
755
796
  }
756
797
 
757
798
  if (!this.options.smartWait || !smartWait) {
799
+ if (this._isCustomLocator(locator)) {
800
+ const locatorObj = new Locator(locator);
801
+ return this.browser.custom$$(locatorObj.type, locatorObj.value);
802
+ }
803
+
758
804
  const els = await this.$$(withStrictLocator(locator));
759
805
  return els;
760
806
  }
761
807
 
762
808
  await this._smartWait(locator);
763
809
 
810
+ if (this._isCustomLocator(locator)) {
811
+ const locatorObj = new Locator(locator);
812
+ return this.browser.custom$$(locatorObj.type, locatorObj.value);
813
+ }
814
+
764
815
  const els = await this.$$(withStrictLocator(locator));
765
816
  await this.defineTimeout({ implicit: 0 });
766
817
  return els;
767
818
  }
768
819
 
820
+ _grabCustomLocator(locator) {
821
+ if (typeof locator === 'string') {
822
+ locator = new Locator(locator);
823
+ }
824
+ return locator.value ? locator.value : locator.custom;
825
+ }
826
+
769
827
  /**
770
828
  * Find a checkbox by providing human readable text:
771
829
  *
@@ -1079,6 +1137,7 @@ class WebDriver extends Helper {
1079
1137
  * @param {CodeceptJS.StringOrSecret} value text value to fill.
1080
1138
  *
1081
1139
  * {{ react }}
1140
+ * {{ custom }}
1082
1141
  *
1083
1142
  */
1084
1143
  async fillField(field, value) {
@@ -1723,7 +1782,7 @@ class WebDriver extends Helper {
1723
1782
  *
1724
1783
  */
1725
1784
  async seeElementInDOM(locator) {
1726
- const res = await this.$$(withStrictLocator(locator));
1785
+ const res = await this._res(locator);
1727
1786
  return empty('elements').negate(res);
1728
1787
  }
1729
1788
 
@@ -1738,7 +1797,7 @@ class WebDriver extends Helper {
1738
1797
  *
1739
1798
  */
1740
1799
  async dontSeeElementInDOM(locator) {
1741
- const res = await this.$$(withStrictLocator(locator));
1800
+ const res = await this._res(locator);
1742
1801
  return empty('elements').assert(res);
1743
1802
  }
1744
1803
 
@@ -2787,7 +2846,7 @@ class WebDriver extends Helper {
2787
2846
  }, aSec * 1000, `element (${new Locator(locator)}) still not enabled after ${aSec} sec`);
2788
2847
  }
2789
2848
  return this.browser.waitUntil(async () => {
2790
- const res = await this.$$(withStrictLocator(locator));
2849
+ const res = await this._res(locator);
2791
2850
  if (!res || res.length === 0) {
2792
2851
  return false;
2793
2852
  }
@@ -2823,7 +2882,7 @@ class WebDriver extends Helper {
2823
2882
  }, aSec * 1000, `element (${locator}) still not present on page after ${aSec} sec`);
2824
2883
  }
2825
2884
  return this.browser.waitUntil(async () => {
2826
- const res = await this.$$(withStrictLocator(locator));
2885
+ const res = await this._res(locator);
2827
2886
  return res && res.length;
2828
2887
  }, { timeout: aSec * 1000, timeoutMsg: `element (${locator}) still not present on page after ${aSec} sec` });
2829
2888
  }
@@ -3046,9 +3105,7 @@ class WebDriver extends Helper {
3046
3105
  }, aSec * 1000, `element (${new Locator(locator)}) still not visible after ${aSec} sec`);
3047
3106
  }
3048
3107
  return this.browser.waitUntil(async () => {
3049
- const res = (this._isShadowLocator(locator))
3050
- ? await this._locate(withStrictLocator(locator))
3051
- : await this.$$(withStrictLocator(locator));
3108
+ const res = await this._res(locator);
3052
3109
  if (!res || res.length === 0) return false;
3053
3110
  const selected = await forEachAsync(res, async el => el.isDisplayed());
3054
3111
  if (Array.isArray(selected)) {
@@ -3083,7 +3140,7 @@ class WebDriver extends Helper {
3083
3140
  }, aSec * 1000, `The number of elements (${new Locator(locator)}) is not ${num} after ${aSec} sec`);
3084
3141
  }
3085
3142
  return this.browser.waitUntil(async () => {
3086
- const res = await this.$$(withStrictLocator(locator));
3143
+ const res = await this._res(locator);
3087
3144
  if (!res || res.length === 0) return false;
3088
3145
  let selected = await forEachAsync(res, async el => el.isDisplayed());
3089
3146
 
@@ -3115,7 +3172,7 @@ class WebDriver extends Helper {
3115
3172
  }, aSec * 1000, `element (${new Locator(locator)}) still visible after ${aSec} sec`);
3116
3173
  }
3117
3174
  return this.browser.waitUntil(async () => {
3118
- const res = await this.$$(withStrictLocator(locator));
3175
+ const res = await this._res(locator);
3119
3176
  if (!res || res.length === 0) return true;
3120
3177
  const selected = await forEachAsync(res, async el => el.isDisplayed());
3121
3178
  return !selected.length;
@@ -3152,7 +3209,7 @@ class WebDriver extends Helper {
3152
3209
  const aSec = sec || this.options.waitForTimeout;
3153
3210
  if (isWebDriver5()) {
3154
3211
  return this.browser.waitUntil(async () => {
3155
- const res = await this.$$(withStrictLocator(locator));
3212
+ const res = await this._res(locator);
3156
3213
  if (!res || res.length === 0) {
3157
3214
  return true;
3158
3215
  }
@@ -3160,7 +3217,7 @@ class WebDriver extends Helper {
3160
3217
  }, aSec * 1000, `element (${new Locator(locator)}) still on page after ${aSec} sec`);
3161
3218
  }
3162
3219
  return this.browser.waitUntil(async () => {
3163
- const res = await this.$$(withStrictLocator(locator));
3220
+ const res = await this._res(locator);
3164
3221
  if (!res || res.length === 0) {
3165
3222
  return true;
3166
3223
  }
@@ -3563,12 +3620,9 @@ async function proceedSee(assertType, text, context, strict = false) {
3563
3620
  }
3564
3621
 
3565
3622
  const smartWaitEnabled = assertType === 'assert';
3566
-
3567
3623
  const res = await this._locate(withStrictLocator(context), smartWaitEnabled);
3568
3624
  assertElementExists(res, context);
3569
-
3570
3625
  const selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)));
3571
-
3572
3626
  if (strict) {
3573
3627
  if (Array.isArray(selected) && selected.length !== 0) {
3574
3628
  return selected.map(elText => equals(description)[assertType](text, elText));
@@ -3636,6 +3690,11 @@ async function filterAsync(array, callback) {
3636
3690
 
3637
3691
  async function findClickable(locator, locateFn) {
3638
3692
  locator = new Locator(locator);
3693
+
3694
+ if (this._isCustomLocator(locator)) {
3695
+ return locateFn(locator.value);
3696
+ }
3697
+
3639
3698
  if (locator.isAccessibilityId() && !this.isWeb) return locateFn(locator, true);
3640
3699
  if (!locator.isFuzzy()) return locateFn(locator, true);
3641
3700
 
@@ -3657,6 +3716,10 @@ async function findClickable(locator, locateFn) {
3657
3716
  async function findFields(locator) {
3658
3717
  locator = new Locator(locator);
3659
3718
 
3719
+ if (this._isCustomLocator(locator)) {
3720
+ return this._locate(locator);
3721
+ }
3722
+
3660
3723
  if (locator.isAccessibilityId() && !this.isWeb) return this._locate(locator, true);
3661
3724
  if (!locator.isFuzzy()) return this._locate(locator, true);
3662
3725
 
@@ -3762,6 +3825,10 @@ async function findCheckable(locator, locateFn) {
3762
3825
  let els;
3763
3826
  locator = new Locator(locator);
3764
3827
 
3828
+ if (this._isCustomLocator(locator)) {
3829
+ return locateFn(locator.value);
3830
+ }
3831
+
3765
3832
  if (locator.isAccessibilityId() && !this.isWeb) return locateFn(locator, true);
3766
3833
  if (!locator.isFuzzy()) return locateFn(locator, true);
3767
3834
 
@@ -3807,6 +3874,7 @@ function getElementId(el) {
3807
3874
  if (el.ELEMENT) {
3808
3875
  return el.ELEMENT;
3809
3876
  }
3877
+
3810
3878
  return null;
3811
3879
  }
3812
3880
 
package/docs/changelog.md CHANGED
@@ -7,13 +7,39 @@ layout: Section
7
7
 
8
8
  # Releases
9
9
 
10
+ ## 3.0.7
11
+
12
+ Documentation fixes:
13
+ * Remove broken link from `Nightmare helper`. See [#2860](https://github.com/codeceptjs/CodeceptJS/issues/2860) by **[Arhell](https://github.com/Arhell)**
14
+ * Fixed broken links in `playwright.md`. See [#2848](https://github.com/codeceptjs/CodeceptJS/issues/2848) by **[johnhoodjr](https://github.com/johnhoodjr)**
15
+ * Fix mocha-multi config example. See [#2881](https://github.com/codeceptjs/CodeceptJS/issues/2881) by **[rimesc](https://github.com/rimesc)**
16
+ * Fix small errors in email documentation file. See [#2884](https://github.com/codeceptjs/CodeceptJS/issues/2884) by **[mkrtchian](https://github.com/mkrtchian)**
17
+ * Improve documentation for `Sharing Data Between Workers` section. See [#2891](https://github.com/codeceptjs/CodeceptJS/issues/2891) by **[ngraf](https://github.com/ngraf)**
18
+
19
+ Features:
20
+ * **[WebDriver]** Shadow DOM Support for `Webdriver`. See [#2741](https://github.com/codeceptjs/CodeceptJS/issues/2741) by **[gkushang](https://github.com/gkushang)**
21
+ * [Release management] Introduce the versioning automatically, it follows the semantics versioning. See [#2883](https://github.com/codeceptjs/CodeceptJS/issues/2883) by **[PeterNgTr](https://github.com/PeterNgTr)**
22
+ * Adding opts into `Scenario.skip` that it would be useful for building reports. See [#2867](https://github.com/codeceptjs/CodeceptJS/issues/2867) by **[AlexKo4](https://github.com/AlexKo4)**
23
+ * Added support for attaching screenshots to [cucumberJsonReporter](https://github.com/ktryniszewski-mdsol/codeceptjs-cucumber-json-reporter) See [#2888](https://github.com/codeceptjs/CodeceptJS/issues/2888) by **[fijijavis](https://github.com/fijijavis)**
24
+ * Supported config file for `codeceptjs shell` command. See [#2895](https://github.com/codeceptjs/CodeceptJS/issues/2895) by **[PeterNgTr](https://github.com/PeterNgTr)**:
25
+
26
+ ```
27
+ npx codeceptjs shell -c foo.conf.js
28
+ ```
29
+
30
+ Bug fixes:
31
+ * **[GraphQL]** Use a helper-specific instance of Axios to avoid contaminating global defaults. See [#2868](https://github.com/codeceptjs/CodeceptJS/issues/2868) by **[vanvoljg](https://github.com/vanvoljg)**
32
+ * A default system color is used when passing non supported system color when using I.say(). See [#2874](https://github.com/codeceptjs/CodeceptJS/issues/2874) by **[PeterNgTr](https://github.com/PeterNgTr)**
33
+ * **[Playwright]** Avoid the timout due to calling the click on invisible elements. See [#2875](https://github.com/codeceptjs/CodeceptJS/issues/2875) by cbayer97
34
+
35
+
10
36
  ## 3.0.6
11
37
 
12
- * **[Playwright]** Added `electron` as a browser to config. See [#2834](https://github.com/codeceptjs/CodeceptJS/issues/2834) by **[cbayer97](https://github.com/cbayer97)**
38
+ * **[Playwright]** Added `electron` as a browser to config. See [#2834](https://github.com/codeceptjs/CodeceptJS/issues/2834) by **[cbayer97](https://github.com/cbayer97)**
13
39
  * **[Playwright]** Implemented `launchPersistentContext` to be able to launch persistent remote browsers. See [#2817](https://github.com/codeceptjs/CodeceptJS/issues/2817) by **[brunoqueiros](https://github.com/brunoqueiros)**. Fixes [#2376](https://github.com/codeceptjs/CodeceptJS/issues/2376).
14
40
  * Fixed printing logs and stack traces for `run-workers`. See [#2857](https://github.com/codeceptjs/CodeceptJS/issues/2857) by **[haveac1gar](https://github.com/haveac1gar)**. Fixes [#2621](https://github.com/codeceptjs/CodeceptJS/issues/2621), [#2852](https://github.com/codeceptjs/CodeceptJS/issues/2852)
15
- * Emit custom messages from worker to the main thread. See [#2824](https://github.com/codeceptjs/CodeceptJS/issues/2824) by **[jccguimaraes](https://github.com/jccguimaraes)**
16
- * Improved workers processes output. See [#2804](https://github.com/codeceptjs/CodeceptJS/issues/2804) by **[drfiresign](https://github.com/drfiresign)**
41
+ * Emit custom messages from worker to the main thread. See [#2824](https://github.com/codeceptjs/CodeceptJS/issues/2824) by **[jccguimaraes](https://github.com/jccguimaraes)**
42
+ * Improved workers processes output. See [#2804](https://github.com/codeceptjs/CodeceptJS/issues/2804) by **[drfiresign](https://github.com/drfiresign)**
17
43
  * BDD. Added ability to use an array of feature files inside config in `gherkin.features`. See [#2814](https://github.com/codeceptjs/CodeceptJS/issues/2814) by **[jbergeronjr](https://github.com/jbergeronjr)**
18
44
 
19
45
  ```js
@@ -22,8 +48,8 @@ layout: Section
22
48
  "./features/api_features/*.feature"
23
49
  ],
24
50
  ```
25
- * Added `getQueueId` to reporter to rerun a specific promise. See [#2837](https://github.com/codeceptjs/CodeceptJS/issues/2837) by **[jonatask](https://github.com/jonatask)**
26
- * **Added `fakerTransform` plugin** to use faker data in Gherkin scenarios. See [#2854](https://github.com/codeceptjs/CodeceptJS/issues/2854) by **[adrielcodeco](https://github.com/adrielcodeco)**
51
+ * Added `getQueueId` to reporter to rerun a specific promise. See [#2837](https://github.com/codeceptjs/CodeceptJS/issues/2837) by **[jonatask](https://github.com/jonatask)**
52
+ * **Added `fakerTransform` plugin** to use faker data in Gherkin scenarios. See [#2854](https://github.com/codeceptjs/CodeceptJS/issues/2854) by **[adrielcodeco](https://github.com/adrielcodeco)**
27
53
 
28
54
  ```feature
29
55
  Scenario Outline: ...
@@ -35,7 +61,7 @@ Scenario Outline: ...
35
61
  | productName | customer | email | anythingMore |
36
62
  | {{commerce.product}} | Dr. {{name.findName}} | {{internet.email}} | staticData |
37
63
  ```
38
- * **[REST]** Use class instance of axios, not the global instance, to avoid contaminating global configuration. [#2846](https://github.com/codeceptjs/CodeceptJS/issues/2846) by **[vanvoljg](https://github.com/vanvoljg)**
64
+ * **[REST]** Use class instance of axios, not the global instance, to avoid contaminating global configuration. [#2846](https://github.com/codeceptjs/CodeceptJS/issues/2846) by **[vanvoljg](https://github.com/vanvoljg)**
39
65
  * **[Appium]** Added `tunnelIdentifier` config option to provide tunnel for SauceLabs. See [#2832](https://github.com/codeceptjs/CodeceptJS/issues/2832) by **[gurjeetbains](https://github.com/gurjeetbains)**
40
66
 
41
67
  ## 3.0.5
@@ -43,9 +69,9 @@ Scenario Outline: ...
43
69
 
44
70
  Features:
45
71
 
46
- * **[Official Docker image for CodeceptJS v3](https://hub.docker.com/r/codeceptjs/codeceptjs)**. New Docker image is based on official Playwright image and supports Playwright, Puppeteer, WebDriver engines. Thanks **[VikentyShevyrin](https://github.com/VikentyShevyrin)**
72
+ * **[Official Docker image for CodeceptJS v3](https://hub.docker.com/r/codeceptjs/codeceptjs)**. New Docker image is based on official Playwright image and supports Playwright, Puppeteer, WebDriver engines. Thanks **[VikentyShevyrin](https://github.com/VikentyShevyrin)**
47
73
  * Better support for Typescript `codecept.conf.ts` configuration files. See [#2750](https://github.com/codeceptjs/CodeceptJS/issues/2750) by **[elaichenkov](https://github.com/elaichenkov)**
48
- * Propagate more events for custom parallel script. See [#2796](https://github.com/codeceptjs/CodeceptJS/issues/2796) by **[jccguimaraes](https://github.com/jccguimaraes)**
74
+ * Propagate more events for custom parallel script. See [#2796](https://github.com/codeceptjs/CodeceptJS/issues/2796) by **[jccguimaraes](https://github.com/jccguimaraes)**
49
75
  * [mocha-junit-reporter] Now supports attachments, see documentation for details. See [#2675](https://github.com/codeceptjs/CodeceptJS/issues/2675) by **[Shard](https://github.com/Shard)**
50
76
  * CustomLocators interface for TypeScript to extend from LocatorOrString. See [#2798](https://github.com/codeceptjs/CodeceptJS/issues/2798) by **[danielrentz](https://github.com/danielrentz)**
51
77
  * **[REST]** Mask sensitive data from log messages.
@@ -144,7 +170,7 @@ Scenario('title', (I, loginPage) => {});
144
170
  Scenario('title', ({ I, loginPage }) => {});
145
171
  ```
146
172
 
147
- * **BREAKING** Replaced bootstrap/teardown scripts to accept only functions or async functions. Async function with callback (with done parameter) should be replaced with async/await. [See our upgrde guide](https://bit.ly/codecept3Up).
173
+ * **BREAKING** Replaced bootstrap/teardown scripts to accept only functions or async functions. Async function with callback (with done parameter) should be replaced with async/await. [See our upgrade guide](https://bit.ly/codecept3Up).
148
174
  * **[TypeScript guide](/typescript)** and [boilerplate project](https://github.com/codeceptjs/typescript-boilerplate)
149
175
  * [tryTo](/plugins/#tryto) and [pauseOnFail](/plugins/#pauseOnFail) plugins installed by default
150
176
  * Introduced one-line installer:
package/docs/email.md CHANGED
@@ -6,10 +6,10 @@ title: Email Testing
6
6
  # Email Testing
7
7
 
8
8
  In End 2 End testing we need to interact with emails.
9
- Email delivery can't tested locally or mocked while testing.
10
- That's why for an end to end test you need to use a real emails to be sent and real email address to receive that emails.
9
+ Email delivery can't be tested locally or mocked while testing.
10
+ That's why for an end to end test you need real emails to be sent and real email address to receive that emails.
11
11
 
12
- Setting up an email server can be hard. So we recommend to use a [MailSlurp](https://mailslurp.com/) - a service designed for testing emails. It creates disposable mailboxes and provides you an access to those mailboxes via REST API.
12
+ Setting up an email server can be hard. So we recommend to use [MailSlurp](https://mailslurp.com/) - a service designed for testing emails. It creates disposable mailboxes and provides you an access to those mailboxes via REST API.
13
13
 
14
14
  > You no longer need to open your gmail account in a browser to check for an email!
15
15
 
@@ -41,7 +41,7 @@ npx codeceptjs def
41
41
 
42
42
  ## Creating Mailbox
43
43
 
44
- MailSlurp allows you to create disposable mailboxes. It means that an email address is created for a one test only and is deleted afterwards. So you can be confident that no other emails are received at that address.
44
+ MailSlurp allows you to create disposable mailboxes. It means that an email address is created for one test only and is deleted afterwards. So you can be confident that no other emails are received at that address.
45
45
 
46
46
  To create a mailbox use `I.haveNewMailbox()` command:
47
47
 
@@ -57,7 +57,7 @@ mailbox object contains:
57
57
 
58
58
  > See [MailSlurp's guide](https://www.mailslurp.com/guides/getting-started/#create-email-addresses) for details.
59
59
 
60
- Mailbox is opened on creation. If you need more than one mailboxes and you want to switch between them use `openMailbox` method:
60
+ Mailbox is opened on creation. If you need more than one mailbox and you want to switch between them use `openMailbox` method:
61
61
 
62
62
  ```js
63
63
  const mailbox1 = await I.haveNewMailbox();
@@ -71,7 +71,7 @@ I.openMailbox(mailbox1);
71
71
 
72
72
  A last created mailbox will be activated. It means that it will be used by default to check for emails.
73
73
 
74
- After an action that triggers sending an email is performed on a website you should wait for this email to be received.
74
+ After an action that triggers sending an email is performed on a website, you should wait for this email to be received.
75
75
  A timeout for waiting an email can be set globally for a helper or for a one call.
76
76
 
77
77
  Use `waitForLatestEmail` function to return the first email from a mailbox:
@@ -109,7 +109,7 @@ const email = await I.waitForLatestEmail();
109
109
  ```
110
110
  > Please note, that we use `await` to assign email. This should be declared inside async function
111
111
 
112
- An `email` object contains following fields:
112
+ An `email` object contains the following fields:
113
113
 
114
114
  * `subject`
115
115
  * `for`
@@ -130,7 +130,7 @@ I.amOnPage(url);
130
130
 
131
131
  ## Assertions
132
132
 
133
- Assertions are performed on the currently opened email.Email is opened on `waitFor` email call, however, you can open an exact email by using `openEmail` function.
133
+ Assertions are performed on the currently opened email. Email is opened on `waitFor` email call, however, you can open an exact email by using `openEmail` function.
134
134
 
135
135
  ```js
136
136
  const email1 = await I.waitForLatestEmail();
package/docs/examples.md CHANGED
@@ -8,9 +8,9 @@ editLink: false
8
8
 
9
9
  # Examples
10
10
  > Add your own examples to our [Wiki Page](https://github.com/codeceptjs/CodeceptJS/wiki/Examples)
11
- ## [TodoMVC Examples](https://github.com/codeceptjs/examples)
11
+ ## [TodoMVC Examples](https://github.com/codecept-js/examples)
12
12
 
13
- ![](https://github.com/codeceptjs/examples/raw/master/todo.png)
13
+ ![](https://github.com/codecept-js/examples/raw/master/todo.png)
14
14
 
15
15
  Playground repository where you can run tests in different helpers on a basic single-page website.
16
16
 
@@ -155,4 +155,4 @@ Suggestions and improvements are welcome , please raise a ticket in Issue tab.
155
155
  * Step by step setup in README
156
156
  * Two helpers are added. UI - Puppeteer , API - REST and chai-codeceptJS for assetion
157
157
  * ESLint for code check
158
- * Upcoming : API generic functions , Adaptor design pattern , More utilities
158
+ * Upcoming : API generic functions , Adaptor design pattern , More utilities
@@ -56,7 +56,7 @@ helpers: {
56
56
  Puppeteer: {
57
57
  // regular Puppeteer config here
58
58
  },
59
- MockRequest: {
59
+ MockRequestHelper: {
60
60
  require: '@codeceptjs/mock-request',
61
61
  }
62
62
  }
@@ -67,7 +67,7 @@ helpers: {
67
67
  ```js
68
68
  // sample options
69
69
  helpers: {
70
- MockRequest: {
70
+ MockRequestHelper: {
71
71
  require: '@codeceptjs/mock-request',
72
72
  mode: record,
73
73
  recordIfMissing: true,
@@ -115,7 +115,7 @@ helpers: {
115
115
  WebDriver: {
116
116
  // regular WebDriver config here
117
117
  },
118
- MockRequest: {
118
+ MockRequestHelper: {
119
119
  require: '@codeceptjs/mock-request',
120
120
  }
121
121
  }
@@ -28,7 +28,7 @@ Requires `playwright` package version ^1 to be installed:
28
28
  This helper should be configured in codecept.json or codecept.conf.js
29
29
 
30
30
  - `url`: base url of website to be tested
31
- - `browser`: a browser to test on, either: `chromium`, `firefox`, `webkit`. Default: chromium.
31
+ - `browser`: a browser to test on, either: `chromium`, `firefox`, `webkit`, `electron`. Default: chromium.
32
32
  - `show`: - show browser window.
33
33
  - `restart`: - restart browser between tests.
34
34
  - `disableScreenshots`: - don't save screenshot on failure.
@@ -47,6 +47,7 @@ This helper should be configured in codecept.json or codecept.conf.js
47
47
  - `userAgent`: (optional) user-agent string.
48
48
  - `manualStart`: - do not start browser before a test, start it manually inside a helper with `this.helpers["Playwright"]._startBrowser()`.
49
49
  - `chromium`: (optional) pass additional chromium options
50
+ - `electron`: (optional) pass additional electron options
50
51
 
51
52
  #### Example #1: Wait for 0 network connections.
52
53
 
@@ -175,6 +176,14 @@ Add the 'dialog' event listener to a page
175
176
 
176
177
  - `page`
177
178
 
179
+ ### _contextLocator
180
+
181
+ Grab Locator if called within Context
182
+
183
+ #### Parameters
184
+
185
+ - `locator` **any**
186
+
178
187
  ### _getPageUrl
179
188
 
180
189
  Gets page URL including hash.
@@ -873,6 +873,7 @@ I.fillField({css: 'form#login input[name=username]'}, 'John');
873
873
 
874
874
  This action supports [React locators](https://codecept.io/react#locators)
875
875
 
876
+ {{ custom }}
876
877
 
877
878
  ### forceClick
878
879
 
package/docs/locators.md CHANGED
@@ -297,8 +297,35 @@ codeceptjs.locator.addFilter((providedLocator, locatorObj) => {
297
297
  ```
298
298
  New locator strategy is ready to use:
299
299
 
300
+
300
301
  ```js
301
302
  I.click('=Login');
302
303
  ```
303
304
 
305
+ #### Custom Strategy Locators
306
+
307
+ CodeceptJS provides the option to specify custom locators that uses Custom Locator Strategies defined in the WebDriver configuration. It uses the WebDriverIO's [custom$](https://webdriver.io/docs/api/browser/custom$.html) locators internally to locate the elements on page.
308
+ To use the defined Custom Locator Strategy add your custom strategy to your configuration.
309
+
310
+ ```js
311
+ // in codecept.conf.js
312
+
313
+ const myStrat = (selector) => {
314
+ return document.querySelectorAll(selector)
315
+ }
316
+
317
+ // under WebDriver Helpers Configuration
318
+ WebDriver: {
319
+ ...
320
+ customLocatorStrategies: {
321
+ custom: myStrat
322
+ }
323
+ }
324
+ ```
325
+
326
+ ```js
327
+ I.click({custom: 'my-shadow-element-unique-css'})
328
+ ```
329
+
330
+
304
331
  > For more details on locator object see [Locator](https://github.com/codeceptjs/CodeceptJS/blob/master/lib/locator.js) class implementation.
package/docs/nightmare.md CHANGED
@@ -221,8 +221,3 @@ I.seeAttributeContains('#main img', 'src', '/cat.jpg');
221
221
  This sample assertion used `_locate` helper method which searched for elements
222
222
  by CSS/XPath or a strict locator. Then `browser.evaluate` method was called to
223
223
  use locate found elements on a page and return attribute from the first of them.
224
-
225
- ## Additional Links
226
-
227
- * [Nightmare Tutorial](http://codenroll.it/acceptance-testing-with-codecept-js/) by jploskonka.
228
-
package/docs/parallel.md CHANGED
@@ -26,7 +26,7 @@ This command is similar to `run`, however, steps output can't be shown in worker
26
26
 
27
27
  Each worker spins an instance of CodeceptJS, executes a group of tests, and sends back report to the main process.
28
28
 
29
- By default the tests are assigned one by one to the avaible workers this may lead to multiple execution of `BeforeSuite()`. Use the option `--suites` to assigne the suites one by one to the workers.
29
+ By default the tests are assigned one by one to the available workers this may lead to multiple execution of `BeforeSuite()`. Use the option `--suites` to assigne the suites one by one to the workers.
30
30
 
31
31
  ```sh
32
32
  npx codeceptjs run-workers --suites 2
@@ -196,22 +196,23 @@ workers.on(event.all.result, (status, completedTests, workerStats) => {
196
196
 
197
197
  ## Sharing Data Between Workers
198
198
 
199
- NodeJS Workers can communicate between each other via messaging system. It may happen that you want to pass some data from one of workers to other. For instance, you may want to share user credentials accross all tests. Data will be appended to a container.
199
+ NodeJS Workers can communicate between each other via messaging system. It may happen that you want to pass some data from one of the workers to other. For instance, you may want to share user credentials accross all tests. Data will be appended to a container.
200
200
 
201
- However, you can't access uninitialized data from a container, so to start, you need to initialized data first. Inside `bootstrap` function of the config we execute the `share` function with `local: true` to initialize value locally:
201
+ However, you can't access uninitialized data from a container, so to start, you need to initialize data first. Inside `bootstrap` function of the config we execute the `share` to initialize value:
202
202
 
203
203
 
204
204
  ```js
205
205
  // inside codecept.conf.js
206
206
  exports.config = {
207
207
  bootstrap() {
208
- // append empty userData to container for current worker
209
- share({ userData: false }, { local: true });
208
+ // append empty userData to container
209
+ share({ userData: false });
210
210
  }
211
211
  }
212
212
  ```
213
+
213
214
  Now each worker has `userData` inside a container. However, it is empty.
214
- When you obtain real data in one of tests you can this data accross tests. Use `inject` function to access data inside a container:
215
+ When you obtain real data in one of the tests you can now `share` this data accross tests. Use `inject` function to access data inside a container:
215
216
 
216
217
  ```js
217
218
  // get current value of userData
@@ -220,6 +221,12 @@ let { userData } = inject();
220
221
  if (!userData) {
221
222
  userData = { name: 'user', password: '123456' };
222
223
  // now new userData will be shared accross all workers
223
- share(userData);
224
+ share({userData : userData});
224
225
  }
225
226
  ```
227
+
228
+ If you want to share data only within same worker, and not across all workers, you need to add option `local: true` every time you run `share`
229
+
230
+ ```js
231
+ share({ userData: false }, {local: true });
232
+ ```
@@ -7,7 +7,7 @@ title: Testing with Playwright
7
7
 
8
8
  Playwright is a Node library to automate the [Chromium](https://www.chromium.org/Home), [WebKit](https://webkit.org/) and [Firefox](https://www.mozilla.org/en-US/firefox/new/) browsers as well as [Electron](https://www.electronjs.org/) apps with a single API. It enables **cross-browser** web automation that is **ever-green**, **capable**, **reliable** and **fast**.
9
9
 
10
- Playwright was built similarly to [Puppeteer](https://github.com/puppeteer/puppeteer), using its API and so is very different in usage. However, Playwright has cross browser support with better design for test automaiton.
10
+ Playwright was built similarly to [Puppeteer](https://github.com/puppeteer/puppeteer), using its API and so is very different in usage. However, Playwright has cross browser support with better design for test automation.
11
11
 
12
12
  Take a look at a sample test:
13
13
 
@@ -270,7 +270,7 @@ Playwright can emulate browsers of mobile devices. Instead of paying for expensi
270
270
 
271
271
  Device emulation can be enabled in CodeceptJS globally in a config or per session.
272
272
 
273
- Playwright contains a [list of predefined devices](https://github.com/Microsoft/playwright/blob/master/src/deviceDescriptors.ts) to emulate, for instance this is how you can enable iPhone 6 emulation for all tests:
273
+ Playwright contains a [list of predefined devices](https://github.com/microsoft/playwright/blob/master/src/server/deviceDescriptors.js) to emulate, for instance this is how you can enable iPhone 6 emulation for all tests:
274
274
 
275
275
  ```js
276
276
  const { devices } = require('playwright');
@@ -282,7 +282,7 @@ helpers: {
282
282
  }
283
283
  }
284
284
  ```
285
- To adjust browser settings you can pass [custom options](https://github.com/microsoft/playwright/blob/master/docs/api.md#browsernewcontextoptions)
285
+ To adjust browser settings you can pass [custom options](https://github.com/microsoft/playwright/blob/master/docs/src/api/class-browsercontext.md)
286
286
 
287
287
  ```js
288
288
  helpers: {
@@ -322,7 +322,7 @@ Playwright can be added to GitHub Actions using [official action](https://github
322
322
 
323
323
  ## Accessing Playwright API
324
324
 
325
- To get [Playwright API](https://github.com/microsoft/playwright/blob/master/docs/api.md) inside a test use `I.usePlaywrightTo` method with a callback.
325
+ To get [Playwright API](https://github.com/microsoft/playwright/tree/master/docs/src/api) inside a test use `I.usePlaywrightTo` method with a callback.
326
326
  To keep test readable provide a description of a callback inside the first parameter.
327
327
 
328
328
  ```js
@@ -385,6 +385,6 @@ async setPermissions() {
385
385
  }
386
386
  ```
387
387
 
388
- > [▶ Learn more about BrowserContext](https://github.com/microsoft/playwright/blob/master/docs/api.md#class-browsercontext)
388
+ > [▶ Learn more about BrowserContext](https://github.com/microsoft/playwright/blob/master/docs/src/api/class-browsercontext.md)
389
389
 
390
- > [▶ Learn more about Helpers](http://codecept.io/helpers/)
390
+ > [▶ Learn more about Helpers](https://codecept.io/helpers/)
package/docs/reports.md CHANGED
@@ -352,10 +352,11 @@ Configure mocha-multi with reports that you want:
352
352
  }
353
353
  },
354
354
  "mochawesome": {
355
- "stdout": "./output/console.log",
356
- "options": {
357
- "reportDir": "./output",
358
- "reportFilename": "report"
355
+ "stdout": "./output/console.log",
356
+ "options": {
357
+ "reportDir": "./output",
358
+ "reportFilename": "report"
359
+ }
359
360
  },
360
361
  "mocha-junit-reporter": {
361
362
  "stdout": "./output/console.log",
@@ -8,9 +8,11 @@ module.exports = async function (path, options) {
8
8
  // Backward compatibility for --profile
9
9
  process.profile = options.profile;
10
10
  process.env.profile = options.profile;
11
+ const configFile = options.config;
12
+
13
+ const config = getConfig(configFile);
14
+ const testsPath = getTestRoot(configFile);
11
15
 
12
- const testsPath = getTestRoot(path);
13
- const config = getConfig(testsPath);
14
16
  const codecept = new Codecept(config, options);
15
17
  codecept.init(testsPath);
16
18