codeceptjs 3.5.4-beta.1 → 3.5.5
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.
- package/CHANGELOG.md +368 -0
- package/README.md +0 -2
- package/docs/build/Appium.js +48 -7
- package/docs/build/GraphQL.js +25 -0
- package/docs/build/Nightmare.js +15 -6
- package/docs/build/Playwright.js +436 -197
- package/docs/build/Protractor.js +17 -8
- package/docs/build/Puppeteer.js +37 -20
- package/docs/build/TestCafe.js +19 -10
- package/docs/build/WebDriver.js +45 -37
- package/docs/changelog.md +375 -0
- package/docs/community-helpers.md +8 -4
- package/docs/examples.md +8 -2
- package/docs/helpers/Appium.md +39 -2
- package/docs/helpers/GraphQL.md +21 -0
- package/docs/helpers/Nightmare.md +1260 -0
- package/docs/helpers/Playwright.md +223 -119
- package/docs/helpers/Protractor.md +1711 -0
- package/docs/helpers/Puppeteer.md +31 -29
- package/docs/helpers/TestCafe.md +18 -17
- package/docs/helpers/WebDriver.md +34 -32
- package/docs/playwright.md +24 -1
- package/docs/webapi/dontSeeInField.mustache +1 -1
- package/docs/webapi/executeAsyncScript.mustache +2 -0
- package/docs/webapi/executeScript.mustache +2 -0
- package/docs/webapi/seeInField.mustache +1 -1
- package/docs/wiki/Books-&-Posts.md +0 -0
- package/docs/wiki/Community-Helpers-&-Plugins.md +8 -4
- package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +46 -14
- package/docs/wiki/Examples.md +8 -2
- package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -0
- package/docs/wiki/Home.md +0 -0
- package/docs/wiki/Migration-to-Appium-v2---CodeceptJS.md +83 -0
- package/docs/wiki/Release-Process.md +0 -0
- package/docs/wiki/Roadmap.md +0 -0
- package/docs/wiki/Tests.md +0 -0
- package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -0
- package/docs/wiki/Videos.md +0 -0
- package/lib/codecept.js +1 -0
- package/lib/command/definitions.js +2 -7
- package/lib/command/init.js +40 -4
- package/lib/command/run-multiple/collection.js +17 -5
- package/lib/command/run-workers.js +4 -0
- package/lib/command/run.js +6 -0
- package/lib/helper/Appium.js +46 -5
- package/lib/helper/GraphQL.js +25 -0
- package/lib/helper/Nightmare.js +1415 -0
- package/lib/helper/Playwright.js +336 -62
- package/lib/helper/Protractor.js +1837 -0
- package/lib/helper/Puppeteer.js +31 -18
- package/lib/helper/TestCafe.js +15 -8
- package/lib/helper/WebDriver.js +39 -35
- package/lib/helper/clientscripts/nightmare.js +213 -0
- package/lib/helper/errors/ElementNotFound.js +2 -1
- package/lib/helper/scripts/highlightElement.js +1 -1
- package/lib/interfaces/bdd.js +1 -1
- package/lib/mochaFactory.js +2 -1
- package/lib/pause.js +6 -4
- package/lib/plugin/heal.js +2 -3
- package/lib/plugin/selenoid.js +6 -1
- package/lib/step.js +27 -10
- package/lib/utils.js +4 -0
- package/lib/workers.js +3 -1
- package/package.json +87 -87
- package/typings/promiseBasedTypes.d.ts +163 -126
- package/typings/types.d.ts +183 -144
- package/docs/build/Polly.js +0 -42
- package/docs/build/SeleniumWebdriver.js +0 -76
package/docs/playwright.md
CHANGED
|
@@ -272,6 +272,29 @@ exports.config = {
|
|
|
272
272
|
}
|
|
273
273
|
```
|
|
274
274
|
|
|
275
|
+
Sometimes, the Electron app is built with [electron-forge](https://www.electronforge.io/), then configuring may a bit different.
|
|
276
|
+
|
|
277
|
+
- First, you should run your electron-forge command to build and pack your app.
|
|
278
|
+
- Then, you would find `index.js` file inside `.webpack/main/index.js`
|
|
279
|
+
|
|
280
|
+
`codecept.conf.js` - CodeceptJS configuration file
|
|
281
|
+
```js
|
|
282
|
+
const path = require("path");
|
|
283
|
+
|
|
284
|
+
exports.config = {
|
|
285
|
+
helpers: {
|
|
286
|
+
Playwright: {
|
|
287
|
+
browser: "electron",
|
|
288
|
+
electron: {
|
|
289
|
+
executablePath: require("electron"),
|
|
290
|
+
args: [path.join(__dirname, ".webpack/main/index.js")],
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
// rest of config
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
275
298
|
### Headless Mode
|
|
276
299
|
|
|
277
300
|
With Electron, headless mode must be set when creating the window. Therefore, CodeceptJS's `show` configuration parameter will not work. However, you can set it in the `main.js` file as shown below:
|
|
@@ -606,4 +629,4 @@ Playwright can be added to GitHub Actions using [official action](https://github
|
|
|
606
629
|
- uses: microsoft/playwright-github-action@v1
|
|
607
630
|
- name: run CodeceptJS tests
|
|
608
631
|
run: npx codeceptjs run
|
|
609
|
-
```
|
|
632
|
+
```
|
|
@@ -7,5 +7,5 @@ I.dontSeeInField({ css: 'form input.email' }, 'user@user.com'); // field by CSS
|
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
@param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
10
|
-
@param {
|
|
10
|
+
@param {CodeceptJS.StringOrSecret} value value to check.
|
|
11
11
|
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -21,4 +21,6 @@ let val = await I.executeAsyncScript(function(url, done) {
|
|
|
21
21
|
|
|
22
22
|
@param {string|function} fn function to be executed in browser context.
|
|
23
23
|
@param {...any} args to be passed to function.
|
|
24
|
+
@returns {Promise<any>} script return value
|
|
25
|
+
|
|
24
26
|
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -23,4 +23,6 @@ let date = await I.executeScript(function(el) {
|
|
|
23
23
|
|
|
24
24
|
@param {string|function} fn function to be executed in browser context.
|
|
25
25
|
@param {...any} args to be passed to function.
|
|
26
|
+
@returns {Promise<any>} script return value
|
|
27
|
+
|
|
26
28
|
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -8,5 +8,5 @@ I.seeInField('form input[type=hidden]','hidden_value');
|
|
|
8
8
|
I.seeInField('#searchform input','Search');
|
|
9
9
|
```
|
|
10
10
|
@param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
11
|
-
@param {
|
|
11
|
+
@param {CodeceptJS.StringOrSecret} value value to check.
|
|
12
12
|
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
File without changes
|
|
@@ -22,9 +22,6 @@ Please **add your own** by editing this page.
|
|
|
22
22
|
* [codeceptjs-bshelper](https://github.com/PeterNgTr/codeceptjs-bshelper) - a helper which updates `Test Names` & `Test Results` on Browserstack
|
|
23
23
|
* [codeceptjs-tbhelper](https://github.com/testingbot/codeceptjs-tbhelper) - a helper which updates `Test Names` & `Test Results` on TestingBot
|
|
24
24
|
|
|
25
|
-
## Integrations
|
|
26
|
-
* [codeceptjs-testrail](https://github.com/PeterNgTr/codeceptjs-testrail) - a plugin to integrate with [Testrail](https://www.gurock.com/testrail)
|
|
27
|
-
|
|
28
25
|
## Visual-Testing
|
|
29
26
|
* [codeceptjs-resemblehelper](https://github.com/puneet0191/codeceptjs-resemblehelper) - a helper which helps with visual testing using resemble.js.
|
|
30
27
|
* [codeceptjs-applitoolshelper](https://www.npmjs.com/package/codeceptjs-applitoolshelper) - a helper which helps interaction with [Applitools](https://applitools.com)
|
|
@@ -33,8 +30,10 @@ Please **add your own** by editing this page.
|
|
|
33
30
|
## Reporters
|
|
34
31
|
* [codeceptjs-rphelper](https://github.com/reportportal/agent-js-codecept) is a CodeceptJS helper which can publish tests results on ReportPortal after execution.
|
|
35
32
|
* [codeceptjs-xray-helper](https://www.npmjs.com/package/codeceptjs-xray-helper) is a CodeceptJS helper which can publish tests results on [XRAY](https://confluence.xpand-it.com/display/XRAYCLOUD/Import+Execution+Results+-+REST).
|
|
33
|
+
* [codeceptjs-xray-cloud-helper](https://www.npmjs.com/package/codeceptjs-xray-cloud-helper) is a helper that automatically retrieves the result of CodeceptJS tests and sends them to XRAY/JIRA(cloud version) via [XRAY Cloud API](https://docs.getxray.app/display/XRAYCLOUD/Import+Execution+Results+-+REST+v2#ImportExecutionResultsRESTv2-XrayJSONresults).
|
|
36
34
|
* [codeceptjs-slack-reporter](https://www.npmjs.com/package/codeceptjs-slack-reporter) Get a Slack notification when one or more scenarios fail.
|
|
37
35
|
* [codeceptjs-browserlogs-plugin](https://github.com/pavkam/codeceptjs-browserlogs-plugin) Record the browser logs for failed tests.
|
|
36
|
+
* [codeceptjs-testrail](https://github.com/PeterNgTr/codeceptjs-testrail) - a plugin to integrate with [Testrail](https://www.gurock.com/testrail)
|
|
38
37
|
|
|
39
38
|
## Browser request control
|
|
40
39
|
* [codeceptjs-resources-check](https://github.com/luarmr/codeceptjs-resources-check) Load a URL with Puppeteer and listen to the requests while the page is loading. Enabling count the number or check the sizes of the requests.
|
|
@@ -46,4 +45,9 @@ Please **add your own** by editing this page.
|
|
|
46
45
|
## Other
|
|
47
46
|
|
|
48
47
|
* [codeceptjs-cmdhelper](https://github.com/thiagodp/codeceptjs-cmdhelper) allows you to run commands in the terminal/console
|
|
49
|
-
* [eslint-plugin-codeceptjs](https://www.npmjs.com/package/eslint-plugin-codeceptjs) Eslint rules for CodeceptJS.
|
|
48
|
+
* [eslint-plugin-codeceptjs](https://www.npmjs.com/package/eslint-plugin-codeceptjs) Eslint rules for CodeceptJS.
|
|
49
|
+
* [codeceptjs-datalayer-helper](https://github.com/kobenguyent/codeceptjs-datalayer-helper) CodeceptJS DataLayer helper helps you to get the datalayer JavaScript array that is used to store information and send this data to the tag manager.
|
|
50
|
+
* [codeceptjs-a11y-helper](https://github.com/kobenguyent/codeceptjs-a11y-helper) accessibility tests integrated with CodeceptJS - Playwright-axe
|
|
51
|
+
* [codeceptjs-lighthouse-helper](https://github.com/kobenguyent/codeceptjs-lighthouse-helper) lighthouse audit integrated with CodeceptJS - Playwright
|
|
52
|
+
* [Snowplow Data analytics](https://www.npmjs.com/package/@viasat/codeceptjs-snowplow-helper) - Test your Snowplow events implementations with CodeceptJS and Snowplow Micro.
|
|
53
|
+
* [codeceptjs-failure-logger](https://github.com/kobenguyent/codeceptjs-failure-logger) - Log failed CodeceptJS tests to file
|
|
@@ -5,25 +5,57 @@ To convert coverage generated from `playwright` to `istanbul` coverage, you firs
|
|
|
5
5
|
|
|
6
6
|
Once installed, convert the coverage to a format which `istanbul` can recognize, by writing a script as shown below.
|
|
7
7
|
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const fs = require('fs/promises');
|
|
8
|
+
```ts
|
|
9
|
+
import glob from 'glob'
|
|
10
|
+
import v8toIstanbul from 'v8-to-istanbul'
|
|
11
|
+
let coverage
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
import fs from 'fs'
|
|
14
|
+
|
|
15
|
+
const coverageFolder = `${process.cwd()}/coverage`
|
|
16
|
+
|
|
17
|
+
async function isExists(path) {
|
|
18
|
+
try {
|
|
19
|
+
await fs.access(path, null)
|
|
20
|
+
return true
|
|
21
|
+
} catch {
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
glob.sync(process.cwd() + '/output/coverage/**/').forEach(item => {
|
|
27
|
+
const directory = fs.opendirSync(item)
|
|
28
|
+
let file
|
|
29
|
+
while ((file = directory.readSync()) !== null) {
|
|
30
|
+
if (file && file.name.includes('.coverage.json') === true) {
|
|
31
|
+
const fileName = file.name
|
|
32
|
+
if (fileName) {
|
|
33
|
+
coverage = require(`${process.cwd()}/output/coverage/${fileName}`)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
directory.closeSync()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
void (async () => {
|
|
15
41
|
for (const entry of coverage) {
|
|
16
42
|
// Used to get file name
|
|
17
|
-
const file = entry.url.match(/(?:http(s)*:\/\/.*\/)(?<file>.*)/)
|
|
18
|
-
const converter = new v8toIstanbul(file.groups.file, 0, {
|
|
19
|
-
source: entry.source
|
|
20
|
-
});
|
|
43
|
+
const file = entry.url.match(/(?:http(s)*:\/\/.*\/)(?<file>.*)/)
|
|
21
44
|
|
|
22
|
-
|
|
23
|
-
|
|
45
|
+
const converter = v8toIstanbul(file.groups.file, 0, {
|
|
46
|
+
source: entry.source,
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
await converter.load()
|
|
50
|
+
converter.applyCoverage(entry.functions)
|
|
24
51
|
|
|
25
52
|
// Store converted coverage file which can later be used to generate report
|
|
26
|
-
|
|
53
|
+
const exist = await isExists(coverageFolder)
|
|
54
|
+
if (!exist) {
|
|
55
|
+
fs.mkdirSync(coverageFolder, {recursive: true})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await fs.writeFileSync(`${coverageFolder}/final.json`, JSON.stringify(converter.toIstanbul(), null, 2))
|
|
27
59
|
}
|
|
28
|
-
})()
|
|
60
|
+
})()
|
|
29
61
|
```
|
package/docs/wiki/Examples.md
CHANGED
|
@@ -6,6 +6,7 @@ Playground repository where you can run tests in different helpers on a basic si
|
|
|
6
6
|
|
|
7
7
|
Tests repository demonstrate usage of
|
|
8
8
|
|
|
9
|
+
* Playwright helper
|
|
9
10
|
* Puppeteer helper
|
|
10
11
|
* WebDriver helper
|
|
11
12
|
* TestCafe plugin
|
|
@@ -18,7 +19,6 @@ Tests repository demonstrate usage of
|
|
|
18
19
|
CodeceptJS repo contains basic tests (both failing and passing) just to show how it works.
|
|
19
20
|
Our team uses it to test new features and run simple scenarios.
|
|
20
21
|
|
|
21
|
-
|
|
22
22
|
## [CodeceptJS Cucumber E2E Framework](https://github.com/gkushang/codeceptjs-e2e)
|
|
23
23
|
|
|
24
24
|
This repository contains complete E2E framework for CodeceptJS with Cucumber and SauceLabs Integration
|
|
@@ -136,4 +136,10 @@ This is necessary if all integrations with TMS and CI/CD are already configured,
|
|
|
136
136
|
* HTTP request client with session support and unit tests
|
|
137
137
|
* Exemplary code control
|
|
138
138
|
* Ready to launch in a CI/CD system as is
|
|
139
|
-
* OOP, Test data models and builders, endpoint decorators
|
|
139
|
+
* OOP, Test data models and builders, endpoint decorators
|
|
140
|
+
|
|
141
|
+
## [Playwright fun with CodeceptJS](https://github.com/PeterNgTr/codeceptjs-playwright-fun)
|
|
142
|
+
* Tests are written in TS
|
|
143
|
+
* CI/CD with Github Actions
|
|
144
|
+
* Page Object Model is applied
|
|
145
|
+
* ReportPortal Integration
|
|
File without changes
|
package/docs/wiki/Home.md
CHANGED
|
File without changes
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Migrating from Appium 1.x to Appium 2.x
|
|
2
|
+
This document is a guide for those who are using Appium 1.x and wish to migrate to Appium 2.x. It contains a list of breaking changes and how to migrate your environments or test suites to ensure compatibility with Appium 2.0.
|
|
3
|
+
|
|
4
|
+
# Overview of Appium 2.0
|
|
5
|
+
Appium 2.0 is the most major new release of Appium in over 5 years. The changes in Appium 2.0 are not primarily related to changes in automation behaviors for specific platforms. Instead, Appium 2.0 reenvisions Appium as a platform where "drivers" (code projects that introduce support for automation of a given platform) and "plugins" (code projects that allow for overriding, altering, extending, or adding behaviors to Appium) can be easily created and shared.
|
|
6
|
+
|
|
7
|
+
At the same time, the Appium project is taking the opportunity to remove many old and deprecated bits of functionality.
|
|
8
|
+
|
|
9
|
+
Together these do introduce a few breaking changes to how Appium is installed, how drivers and various features are managed, and protocol support. These are detailed below.
|
|
10
|
+
|
|
11
|
+
# Breaking Changes
|
|
12
|
+
Here we call out the breaking changes and what you need to do to account for them.
|
|
13
|
+
|
|
14
|
+
## ‼ Default server base path
|
|
15
|
+
With Appium 1.x, the server would accept commands by default on http://localhost:4723/wd/hub. The /wd/hub base path was a legacy convention from the days of migrating from Selenium 1 to Selenium 2, and is no longer relevant. As such the default base path for the server is now /. If you want to retain the old behaviour, you can set the base path via a command line argument as follows:
|
|
16
|
+
|
|
17
|
+
`appium --base-path=/wd/hub`
|
|
18
|
+
|
|
19
|
+
## ‼ Installing drivers during setup
|
|
20
|
+
When you installed Appium 1.x, all available drivers would be installed at the same time as the main Appium server. This is no longer the case. Simply installing Appium 2.0 (e.g., by npm install -g appium@next), will install the Appium server only, but no drivers. To install drivers, you must instead use the new [Appium extension CLI](https://appium.github.io/appium/docs/en/2.0/cli/extensions/). For example, to install the latest versions of the XCUITest and UiAutomator2 drivers, after installing Appium you would run the following commands:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
appium driver install uiautomator2,xcuitest # installs the latest driver version
|
|
24
|
+
```
|
|
25
|
+
At this point, your drivers are installed and ready. There's a lot more you can do with this CLI so be sure to check out the docs on it. If you're running in a CI environment or want to install Appium along with some drivers all in one step, you can do so using some special flags during install, for example:
|
|
26
|
+
|
|
27
|
+
`npm install --global appium --drivers=xcuitest,uiautomator2`
|
|
28
|
+
This will install Appium and the two drivers for you in one go. Please uninstall any existing Appium 1.x npm packages (with npm uninstall -g appium) if you get an installation or startup error.
|
|
29
|
+
|
|
30
|
+
## ‼ Capabilities
|
|
31
|
+
One significant difference between old and new protocols is in the format of capabilities. Previously called "desired capabilities", and now called simply "capabilities", there is now a requirement for a so-called "vendor prefix" on any non-standard capabilities. The list of standard capabilities is given in the [WebDriver Protocol spec](https://www.w3.org/TR/webdriver/#capabilities), and includes a few commonly used capabilities such as browserName and platformName.
|
|
32
|
+
|
|
33
|
+
These standard capabilities continue to be used as-is. All other capabilities must include a "vendor prefix" in their name. A vendor prefix is a string followed by a colon, such as appium:. Most of Appium's capabilities go beyond the standard W3C capabilities and must therefore include vendor prefixes (we recommend that you use appium: unless directed otherwise by documentation). For example:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
`appium:app`
|
|
37
|
+
`appium:noReset`
|
|
38
|
+
`appium:deviceName`
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This requirement may or may not be a breaking change for your test suites when targeting Appium 2.0. If you're using an updated Appium client (at least one maintained by the Appium team), the client will add the appium: prefix for you on all necessary capabilities automatically. New versions of [Appium Inspector](https://github.com/appium/appium-inspector) will also do this. Cloud-based Appium providers may also do this. So simply be aware that if you get any messages to the effect that your capabilities lack a vendor prefix, this is how you solve that problem.
|
|
42
|
+
|
|
43
|
+
To make everyone's lives a bit easier with CodeceptJS, you don't need to update your capabilities to include "vendor prefix", CodeceptJS does it for you out of the box.
|
|
44
|
+
|
|
45
|
+
## ‼ WebdriverIO upgrade
|
|
46
|
+
CodeceptJS should be installed with webdriverio support, as the moment of testing, `webdriverio@8.6.3` works seamlessly:
|
|
47
|
+
```bash
|
|
48
|
+
npm install codeceptjs webdriverio@8.6.3 --save
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## ‼ CodeceptJS configuration
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
...
|
|
55
|
+
appiumV2: true, // set this to true to try out appium 2.x
|
|
56
|
+
'app': `${process.cwd()}/build/Monefy_Pro_v1.15.0.apk`,
|
|
57
|
+
'platform': 'android',
|
|
58
|
+
'device': 'emulator',
|
|
59
|
+
'port': DEFAULT_PORT,
|
|
60
|
+
'path': '/wd/hub',
|
|
61
|
+
browser: '',
|
|
62
|
+
desiredCapabilities: {
|
|
63
|
+
'appPackage': data.packageName,
|
|
64
|
+
'deviceName': process.env.DEVICE || 'Emulator',
|
|
65
|
+
'platformName': process.env.PLATFORM || 'android',
|
|
66
|
+
'platformVersion': process.env.OS_VERSION || '11.0',
|
|
67
|
+
'automationName': process.env.ENGINE || 'UIAutomator2',
|
|
68
|
+
'avd': process.env.UDID || 'Pixel_XL_API_30',
|
|
69
|
+
'newCommandTimeout': 300000,
|
|
70
|
+
'androidDeviceReadyTimeout': 300000,
|
|
71
|
+
'androidInstallTimeout': 90000,
|
|
72
|
+
'appWaitDuration': 300000,
|
|
73
|
+
'autoGrantPermissions': true,
|
|
74
|
+
'gpsEnabled': true,
|
|
75
|
+
'isHeadless': false,
|
|
76
|
+
'noReset': false,
|
|
77
|
+
'noSign': true,
|
|
78
|
+
}
|
|
79
|
+
...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
Demo project to try with Appium v2: https://github.com/kobenguyent/thanh-nguyen/tree/main/task2
|
|
File without changes
|
package/docs/wiki/Roadmap.md
CHANGED
|
File without changes
|
package/docs/wiki/Tests.md
CHANGED
|
File without changes
|
|
File without changes
|
package/docs/wiki/Videos.md
CHANGED
|
File without changes
|
package/lib/codecept.js
CHANGED
|
@@ -17,7 +17,6 @@ const actingHelpers = [...require('../plugin/standardActingHelpers'), 'REST'];
|
|
|
17
17
|
* @param {Map} params.supportObject
|
|
18
18
|
* @param {Array<string>} params.helperNames
|
|
19
19
|
* @param {Array<string>} params.importPaths
|
|
20
|
-
* @param {Array<string>} params.customHelpers
|
|
21
20
|
* @param params.translations
|
|
22
21
|
*
|
|
23
22
|
* @returns {string}
|
|
@@ -29,15 +28,13 @@ const getDefinitionsFileContent = ({
|
|
|
29
28
|
supportObject,
|
|
30
29
|
importPaths,
|
|
31
30
|
translations,
|
|
32
|
-
customHelpers,
|
|
33
31
|
}) => {
|
|
34
32
|
const getHelperListFragment = ({
|
|
35
33
|
hasCustomHelper,
|
|
36
34
|
hasCustomStepsFile,
|
|
37
|
-
customHelpers,
|
|
38
35
|
}) => {
|
|
39
36
|
if (hasCustomHelper && hasCustomStepsFile) {
|
|
40
|
-
return `${['ReturnType<steps_file>',
|
|
37
|
+
return `${['ReturnType<steps_file>', 'WithTranslation<Methods>'].join(', ')}`;
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
if (hasCustomStepsFile) {
|
|
@@ -50,7 +47,6 @@ const getDefinitionsFileContent = ({
|
|
|
50
47
|
const helpersListFragment = getHelperListFragment({
|
|
51
48
|
hasCustomHelper,
|
|
52
49
|
hasCustomStepsFile,
|
|
53
|
-
customHelpers,
|
|
54
50
|
});
|
|
55
51
|
|
|
56
52
|
const importPathsFragment = importPaths.join('\n');
|
|
@@ -143,7 +139,7 @@ module.exports = function (genPath, options) {
|
|
|
143
139
|
}
|
|
144
140
|
|
|
145
141
|
if (!actingHelpers.includes(name)) {
|
|
146
|
-
customHelpers.push(
|
|
142
|
+
customHelpers.push(name);
|
|
147
143
|
}
|
|
148
144
|
}
|
|
149
145
|
|
|
@@ -186,7 +182,6 @@ module.exports = function (genPath, options) {
|
|
|
186
182
|
translations,
|
|
187
183
|
hasCustomStepsFile,
|
|
188
184
|
hasCustomHelper,
|
|
189
|
-
customHelpers,
|
|
190
185
|
});
|
|
191
186
|
|
|
192
187
|
// add aliases for translations
|
package/lib/command/init.js
CHANGED
|
@@ -201,7 +201,13 @@ module.exports = function (initPath) {
|
|
|
201
201
|
// no extra step file for typescript (as it doesn't match TS conventions)
|
|
202
202
|
const stepFile = `./steps_file.${extension}`;
|
|
203
203
|
fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor);
|
|
204
|
-
|
|
204
|
+
|
|
205
|
+
if (isTypeScript) {
|
|
206
|
+
config.include = _actorTranslation('./steps_file', config.translation);
|
|
207
|
+
} else {
|
|
208
|
+
config.include = _actorTranslation(stepFile, config.translation);
|
|
209
|
+
}
|
|
210
|
+
|
|
205
211
|
print(`Steps file created at ${stepFile}`);
|
|
206
212
|
|
|
207
213
|
let configSource;
|
|
@@ -316,7 +322,7 @@ module.exports = function (initPath) {
|
|
|
316
322
|
};
|
|
317
323
|
|
|
318
324
|
print('Configure helpers...');
|
|
319
|
-
inquirer.prompt(helperConfigs).then((helperResult) => {
|
|
325
|
+
inquirer.prompt(helperConfigs).then(async (helperResult) => {
|
|
320
326
|
if (helperResult.Playwright_browser === 'electron') {
|
|
321
327
|
delete helperResult.Playwright_url;
|
|
322
328
|
delete helperResult.Playwright_show;
|
|
@@ -336,12 +342,12 @@ module.exports = function (initPath) {
|
|
|
336
342
|
});
|
|
337
343
|
|
|
338
344
|
print('');
|
|
339
|
-
finish();
|
|
345
|
+
await finish();
|
|
340
346
|
});
|
|
341
347
|
});
|
|
342
348
|
};
|
|
343
349
|
|
|
344
|
-
function install(dependencies
|
|
350
|
+
function install(dependencies) {
|
|
345
351
|
let command;
|
|
346
352
|
let args;
|
|
347
353
|
|
|
@@ -374,9 +380,39 @@ function install(dependencies, verbose) {
|
|
|
374
380
|
].concat(dependencies);
|
|
375
381
|
}
|
|
376
382
|
|
|
383
|
+
if (process.env._INIT_DRY_RUN_INSTALL) {
|
|
384
|
+
args.push('--dry-run');
|
|
385
|
+
}
|
|
386
|
+
|
|
377
387
|
const { status } = spawn.sync(command, args, { stdio: 'inherit' });
|
|
378
388
|
if (status !== 0) {
|
|
379
389
|
throw new Error(`${command} ${args.join(' ')} failed`);
|
|
380
390
|
}
|
|
381
391
|
return true;
|
|
382
392
|
}
|
|
393
|
+
|
|
394
|
+
function _actorTranslation(stepFile, translationSelected) {
|
|
395
|
+
let actor;
|
|
396
|
+
|
|
397
|
+
for (const translationAvailable of translations) {
|
|
398
|
+
if (actor) {
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (translationSelected === translationAvailable) {
|
|
403
|
+
const nameOfActor = require('../../translations')[translationAvailable].I;
|
|
404
|
+
|
|
405
|
+
actor = {
|
|
406
|
+
[nameOfActor]: stepFile,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (!actor) {
|
|
412
|
+
actor = {
|
|
413
|
+
I: stepFile,
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return actor;
|
|
418
|
+
}
|
|
@@ -47,14 +47,26 @@ class Collection {
|
|
|
47
47
|
*/
|
|
48
48
|
prepareRuns(selectedRuns, config) {
|
|
49
49
|
selectedRuns.forEach((selectedRun) => {
|
|
50
|
-
const
|
|
51
|
-
const
|
|
50
|
+
const runConfig = [];
|
|
51
|
+
const runName = [];
|
|
52
52
|
|
|
53
|
-
if (
|
|
54
|
-
|
|
53
|
+
if (selectedRun === 'all') {
|
|
54
|
+
Object.keys(config.multiple).forEach(name => {
|
|
55
|
+
runName.push(name);
|
|
56
|
+
runConfig.push(config.multiple[name]);
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
runName.push(selectedRun.split(':')[0]);
|
|
60
|
+
runConfig.push(config.multiple[runName[0]]);
|
|
55
61
|
}
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
for (let i = 0; i < runConfig.length; i++) {
|
|
64
|
+
if (!runConfig[i]) {
|
|
65
|
+
throw new Error(`run ${runName[i]} was not configured in "multiple" section of config`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.addRun(createRun(runName[i], runConfig[i]));
|
|
69
|
+
}
|
|
58
70
|
});
|
|
59
71
|
|
|
60
72
|
return this;
|
package/lib/command/run.js
CHANGED
|
@@ -28,6 +28,12 @@ module.exports = async function (test, options) {
|
|
|
28
28
|
codecept.init(testRoot);
|
|
29
29
|
await codecept.bootstrap();
|
|
30
30
|
codecept.loadTests(test);
|
|
31
|
+
|
|
32
|
+
if (options.verbose) {
|
|
33
|
+
const getInfo = require('./info');
|
|
34
|
+
await getInfo();
|
|
35
|
+
}
|
|
36
|
+
|
|
31
37
|
await codecept.run();
|
|
32
38
|
} catch (err) {
|
|
33
39
|
printError(err);
|
package/lib/helper/Appium.js
CHANGED
|
@@ -117,6 +117,43 @@ const vendorPrefix = {
|
|
|
117
117
|
* }
|
|
118
118
|
* ```
|
|
119
119
|
*
|
|
120
|
+
* Example Android App using Appiumv2 on BrowserStack:
|
|
121
|
+
*
|
|
122
|
+
* ```js
|
|
123
|
+
* {
|
|
124
|
+
* helpers: {
|
|
125
|
+
* Appium: {
|
|
126
|
+
* appiumV2: true,
|
|
127
|
+
* host: "hub-cloud.browserstack.com",
|
|
128
|
+
* port: 4444,
|
|
129
|
+
* user: process.env.BROWSERSTACK_USER,
|
|
130
|
+
* key: process.env.BROWSERSTACK_KEY,
|
|
131
|
+
* app: `bs://c700ce60cf1gjhgjh3ae8ed9770ghjg5a55b8e022f13c5827cg`,
|
|
132
|
+
* browser: '',
|
|
133
|
+
* desiredCapabilities: {
|
|
134
|
+
* 'appPackage': data.packageName,
|
|
135
|
+
* 'deviceName': process.env.DEVICE || 'Google Pixel 3',
|
|
136
|
+
* 'platformName': process.env.PLATFORM || 'android',
|
|
137
|
+
* 'platformVersion': process.env.OS_VERSION || '10.0',
|
|
138
|
+
* 'automationName': process.env.ENGINE || 'UIAutomator2',
|
|
139
|
+
* 'newCommandTimeout': 300000,
|
|
140
|
+
* 'androidDeviceReadyTimeout': 300000,
|
|
141
|
+
* 'androidInstallTimeout': 90000,
|
|
142
|
+
* 'appWaitDuration': 300000,
|
|
143
|
+
* 'autoGrantPermissions': true,
|
|
144
|
+
* 'gpsEnabled': true,
|
|
145
|
+
* 'isHeadless': false,
|
|
146
|
+
* 'noReset': false,
|
|
147
|
+
* 'noSign': true,
|
|
148
|
+
* 'bstack:options' : {
|
|
149
|
+
* "appiumVersion" : "2.0.1",
|
|
150
|
+
* },
|
|
151
|
+
* }
|
|
152
|
+
* }
|
|
153
|
+
* }
|
|
154
|
+
* }
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
120
157
|
* Additional configuration params can be used from <https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md>
|
|
121
158
|
*
|
|
122
159
|
* ## Access From Helpers
|
|
@@ -234,7 +271,9 @@ class Appium extends Webdriver {
|
|
|
234
271
|
const _convertedCaps = {};
|
|
235
272
|
for (const [key, value] of Object.entries(capabilities)) {
|
|
236
273
|
if (!key.startsWith(vendorPrefix.appium)) {
|
|
237
|
-
|
|
274
|
+
if (key !== 'platformName') {
|
|
275
|
+
_convertedCaps[`${vendorPrefix.appium}:${key}`] = value;
|
|
276
|
+
}
|
|
238
277
|
} else {
|
|
239
278
|
_convertedCaps[`${key}`] = value;
|
|
240
279
|
}
|
|
@@ -1433,8 +1472,9 @@ class Appium extends Webdriver {
|
|
|
1433
1472
|
*
|
|
1434
1473
|
*/
|
|
1435
1474
|
async dontSeeInField(field, value) {
|
|
1436
|
-
|
|
1437
|
-
return super.dontSeeInField(
|
|
1475
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1476
|
+
if (this.isWeb) return super.dontSeeInField(field, _value);
|
|
1477
|
+
return super.dontSeeInField(parseLocator.call(this, field), _value);
|
|
1438
1478
|
}
|
|
1439
1479
|
|
|
1440
1480
|
/**
|
|
@@ -1565,8 +1605,9 @@ class Appium extends Webdriver {
|
|
|
1565
1605
|
*
|
|
1566
1606
|
*/
|
|
1567
1607
|
async seeInField(field, value) {
|
|
1568
|
-
|
|
1569
|
-
return super.seeInField(
|
|
1608
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1609
|
+
if (this.isWeb) return super.seeInField(field, _value);
|
|
1610
|
+
return super.seeInField(parseLocator.call(this, field), _value);
|
|
1570
1611
|
}
|
|
1571
1612
|
|
|
1572
1613
|
/**
|
package/lib/helper/GraphQL.js
CHANGED
|
@@ -81,6 +81,8 @@ class GraphQL extends Helper {
|
|
|
81
81
|
'Content-Type': 'application/json',
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
+
request.headers = { ...this.headers, ...request.headers };
|
|
85
|
+
|
|
84
86
|
if (this.config.onRequest) {
|
|
85
87
|
await this.config.onRequest(request);
|
|
86
88
|
}
|
|
@@ -200,5 +202,28 @@ class GraphQL extends Helper {
|
|
|
200
202
|
_setRequestTimeout(newTimeout) {
|
|
201
203
|
this.options.timeout = newTimeout;
|
|
202
204
|
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Sets request headers for all requests of this test
|
|
208
|
+
*
|
|
209
|
+
* @param {object} headers headers list
|
|
210
|
+
*/
|
|
211
|
+
haveRequestHeaders(headers) {
|
|
212
|
+
this.headers = { ...this.headers, ...headers };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Adds a header for Bearer authentication
|
|
217
|
+
*
|
|
218
|
+
* ```js
|
|
219
|
+
* // we use secret function to hide token from logs
|
|
220
|
+
* I.amBearerAuthenticated(secret('heregoestoken'))
|
|
221
|
+
* ```
|
|
222
|
+
*
|
|
223
|
+
* @param {string | CodeceptJS.Secret} accessToken Bearer access token
|
|
224
|
+
*/
|
|
225
|
+
amBearerAuthenticated(accessToken) {
|
|
226
|
+
this.haveRequestHeaders({ Authorization: `Bearer ${accessToken}` });
|
|
227
|
+
}
|
|
203
228
|
}
|
|
204
229
|
module.exports = GraphQL;
|