codeceptjs 4.0.0-beta.1 → 4.0.0-beta.10.esm-aria
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/README.md +133 -120
- package/bin/codecept.js +107 -96
- package/bin/test-server.js +64 -0
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/click.mustache +5 -1
- package/lib/actor.js +71 -103
- package/lib/ai.js +159 -188
- package/lib/assert/empty.js +22 -24
- package/lib/assert/equal.js +30 -37
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +43 -48
- package/lib/assert/throws.js +11 -11
- package/lib/assert/truth.js +22 -22
- package/lib/assert.js +20 -18
- package/lib/codecept.js +238 -162
- package/lib/colorUtils.js +50 -52
- package/lib/command/check.js +206 -0
- package/lib/command/configMigrate.js +56 -51
- package/lib/command/definitions.js +96 -109
- package/lib/command/dryRun.js +77 -79
- package/lib/command/generate.js +234 -194
- package/lib/command/gherkin/init.js +42 -33
- package/lib/command/gherkin/snippets.js +76 -74
- package/lib/command/gherkin/steps.js +20 -17
- package/lib/command/info.js +74 -38
- package/lib/command/init.js +300 -290
- package/lib/command/interactive.js +41 -32
- package/lib/command/list.js +28 -27
- package/lib/command/run-multiple/chunk.js +51 -48
- package/lib/command/run-multiple/collection.js +5 -5
- package/lib/command/run-multiple/run.js +5 -1
- package/lib/command/run-multiple.js +97 -97
- package/lib/command/run-rerun.js +19 -25
- package/lib/command/run-workers.js +68 -92
- package/lib/command/run.js +39 -27
- package/lib/command/utils.js +80 -64
- package/lib/command/workers/runTests.js +388 -226
- package/lib/config.js +124 -50
- package/lib/container.js +751 -260
- package/lib/data/context.js +60 -61
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +32 -32
- package/lib/data/table.js +22 -22
- package/lib/effects.js +307 -0
- package/lib/element/WebElement.js +327 -0
- package/lib/els.js +160 -0
- package/lib/event.js +173 -163
- package/lib/globals.js +141 -0
- package/lib/heal.js +89 -85
- package/lib/helper/AI.js +131 -41
- package/lib/helper/ApiDataFactory.js +107 -75
- package/lib/helper/Appium.js +542 -404
- package/lib/helper/FileSystem.js +100 -79
- package/lib/helper/GraphQL.js +44 -43
- package/lib/helper/GraphQLDataFactory.js +52 -52
- package/lib/helper/JSONResponse.js +126 -88
- package/lib/helper/Mochawesome.js +54 -29
- package/lib/helper/Playwright.js +2547 -1316
- package/lib/helper/Puppeteer.js +1578 -1181
- package/lib/helper/REST.js +209 -68
- package/lib/helper/WebDriver.js +1482 -1342
- package/lib/helper/errors/ConnectionRefused.js +6 -6
- package/lib/helper/errors/ElementAssertion.js +11 -16
- package/lib/helper/errors/ElementNotFound.js +5 -9
- package/lib/helper/errors/RemoteBrowserConnectionRefused.js +5 -5
- package/lib/helper/extras/Console.js +11 -11
- package/lib/helper/extras/PlaywrightLocator.js +110 -0
- package/lib/helper/extras/PlaywrightPropEngine.js +18 -18
- package/lib/helper/extras/PlaywrightReactVueLocator.js +17 -8
- package/lib/helper/extras/PlaywrightRestartOpts.js +25 -11
- package/lib/helper/extras/Popup.js +22 -22
- package/lib/helper/extras/React.js +27 -28
- package/lib/helper/network/actions.js +36 -42
- package/lib/helper/network/utils.js +78 -84
- package/lib/helper/scripts/blurElement.js +5 -5
- package/lib/helper/scripts/focusElement.js +5 -5
- package/lib/helper/scripts/highlightElement.js +8 -8
- package/lib/helper/scripts/isElementClickable.js +34 -34
- package/lib/helper.js +2 -3
- package/lib/history.js +23 -19
- package/lib/hooks.js +8 -8
- package/lib/html.js +94 -104
- package/lib/index.js +38 -27
- package/lib/listener/config.js +30 -23
- package/lib/listener/emptyRun.js +54 -0
- package/lib/listener/enhancedGlobalRetry.js +110 -0
- package/lib/listener/exit.js +16 -18
- package/lib/listener/globalRetry.js +70 -0
- package/lib/listener/globalTimeout.js +181 -0
- package/lib/listener/helpers.js +76 -51
- package/lib/listener/mocha.js +10 -11
- package/lib/listener/result.js +11 -0
- package/lib/listener/retryEnhancer.js +85 -0
- package/lib/listener/steps.js +71 -59
- package/lib/listener/store.js +20 -0
- package/lib/locator.js +214 -197
- package/lib/mocha/asyncWrapper.js +274 -0
- package/lib/mocha/bdd.js +167 -0
- package/lib/mocha/cli.js +341 -0
- package/lib/mocha/factory.js +163 -0
- package/lib/mocha/featureConfig.js +89 -0
- package/lib/mocha/gherkin.js +231 -0
- package/lib/mocha/hooks.js +121 -0
- package/lib/mocha/index.js +21 -0
- package/lib/mocha/inject.js +46 -0
- package/lib/{interfaces → mocha}/scenarioConfig.js +58 -34
- package/lib/mocha/suite.js +89 -0
- package/lib/mocha/test.js +184 -0
- package/lib/mocha/types.d.ts +42 -0
- package/lib/mocha/ui.js +242 -0
- package/lib/output.js +141 -71
- package/lib/parser.js +47 -44
- package/lib/pause.js +173 -145
- package/lib/plugin/analyze.js +403 -0
- package/lib/plugin/{autoLogin.js → auth.js} +178 -79
- package/lib/plugin/autoDelay.js +36 -40
- package/lib/plugin/coverage.js +131 -78
- package/lib/plugin/customLocator.js +22 -21
- package/lib/plugin/customReporter.js +53 -0
- package/lib/plugin/enhancedRetryFailedStep.js +99 -0
- package/lib/plugin/heal.js +101 -110
- package/lib/plugin/htmlReporter.js +3648 -0
- package/lib/plugin/pageInfo.js +140 -0
- package/lib/plugin/pauseOnFail.js +12 -11
- package/lib/plugin/retryFailedStep.js +82 -47
- package/lib/plugin/screenshotOnFail.js +111 -92
- package/lib/plugin/stepByStepReport.js +159 -101
- package/lib/plugin/stepTimeout.js +20 -25
- package/lib/plugin/subtitles.js +38 -38
- package/lib/recorder.js +193 -130
- package/lib/rerun.js +94 -49
- package/lib/result.js +238 -0
- package/lib/retryCoordinator.js +207 -0
- package/lib/secret.js +20 -18
- package/lib/session.js +95 -89
- package/lib/step/base.js +239 -0
- package/lib/step/comment.js +10 -0
- package/lib/step/config.js +50 -0
- package/lib/step/func.js +46 -0
- package/lib/step/helper.js +50 -0
- package/lib/step/meta.js +99 -0
- package/lib/step/record.js +74 -0
- package/lib/step/retry.js +11 -0
- package/lib/step/section.js +55 -0
- package/lib/step.js +18 -329
- package/lib/steps.js +54 -0
- package/lib/store.js +38 -7
- package/lib/template/heal.js +3 -12
- package/lib/template/prompts/generatePageObject.js +31 -0
- package/lib/template/prompts/healStep.js +13 -0
- package/lib/template/prompts/writeStep.js +9 -0
- package/lib/test-server.js +334 -0
- package/lib/timeout.js +60 -0
- package/lib/transform.js +8 -8
- package/lib/translation.js +34 -21
- package/lib/utils/mask_data.js +47 -0
- package/lib/utils.js +411 -228
- package/lib/workerStorage.js +37 -34
- package/lib/workers.js +532 -296
- package/package.json +115 -95
- package/translations/de-DE.js +5 -3
- package/translations/fr-FR.js +5 -4
- package/translations/index.js +22 -12
- package/translations/it-IT.js +4 -3
- package/translations/ja-JP.js +4 -3
- package/translations/nl-NL.js +76 -0
- package/translations/pl-PL.js +4 -3
- package/translations/pt-BR.js +4 -3
- package/translations/ru-RU.js +4 -3
- package/translations/utils.js +10 -0
- package/translations/zh-CN.js +4 -3
- package/translations/zh-TW.js +4 -3
- package/typings/index.d.ts +546 -185
- package/typings/promiseBasedTypes.d.ts +150 -879
- package/typings/types.d.ts +547 -996
- package/lib/cli.js +0 -249
- package/lib/dirname.js +0 -5
- package/lib/helper/Expect.js +0 -425
- package/lib/helper/ExpectHelper.js +0 -399
- package/lib/helper/MockServer.js +0 -223
- package/lib/helper/Nightmare.js +0 -1411
- package/lib/helper/Protractor.js +0 -1835
- package/lib/helper/SoftExpectHelper.js +0 -381
- package/lib/helper/TestCafe.js +0 -1410
- package/lib/helper/clientscripts/nightmare.js +0 -213
- package/lib/helper/testcafe/testControllerHolder.js +0 -42
- package/lib/helper/testcafe/testcafe-utils.js +0 -63
- package/lib/interfaces/bdd.js +0 -98
- package/lib/interfaces/featureConfig.js +0 -69
- package/lib/interfaces/gherkin.js +0 -195
- package/lib/listener/artifacts.js +0 -19
- package/lib/listener/retry.js +0 -68
- package/lib/listener/timeout.js +0 -109
- package/lib/mochaFactory.js +0 -110
- package/lib/plugin/allure.js +0 -15
- package/lib/plugin/commentStep.js +0 -136
- package/lib/plugin/debugErrors.js +0 -67
- package/lib/plugin/eachElement.js +0 -127
- package/lib/plugin/fakerTransform.js +0 -49
- package/lib/plugin/retryTo.js +0 -121
- package/lib/plugin/selenoid.js +0 -371
- package/lib/plugin/standardActingHelpers.js +0 -9
- package/lib/plugin/tryTo.js +0 -105
- package/lib/plugin/wdio.js +0 -246
- package/lib/scenario.js +0 -222
- package/lib/ui.js +0 -238
- package/lib/within.js +0 -70
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
function ConnectionRefused(err) {
|
|
2
|
-
this.message = "Can't connect to WebDriver.\n"
|
|
3
|
-
this.message += `${err}\n\n
|
|
4
|
-
this.message += 'Please make sure Selenium Server is running and accessible'
|
|
5
|
-
this.stack = err.stack
|
|
2
|
+
this.message = "Can't connect to WebDriver.\n"
|
|
3
|
+
this.message += `${err}\n\n`
|
|
4
|
+
this.message += 'Please make sure Selenium Server is running and accessible'
|
|
5
|
+
this.stack = err.stack
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
ConnectionRefused.prototype = Object.create(Error.prototype)
|
|
8
|
+
ConnectionRefused.prototype = Object.create(Error.prototype)
|
|
9
9
|
|
|
10
|
-
export default ConnectionRefused
|
|
10
|
+
export default ConnectionRefused
|
|
@@ -1,38 +1,33 @@
|
|
|
1
|
-
import Locator from '../../locator.js'
|
|
1
|
+
import Locator from '../../locator.js'
|
|
2
2
|
|
|
3
|
-
const prefixMessage = 'Element'
|
|
3
|
+
const prefixMessage = 'Element'
|
|
4
4
|
|
|
5
5
|
function seeElementError(locator) {
|
|
6
6
|
if (typeof locator === 'object') {
|
|
7
|
-
locator = JSON.stringify(locator)
|
|
7
|
+
locator = JSON.stringify(locator)
|
|
8
8
|
}
|
|
9
|
-
throw new Error(`${prefixMessage} "${
|
|
9
|
+
throw new Error(`${prefixMessage} "${new Locator(locator)}" is still visible on page.`)
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
function seeElementInDOMError(locator) {
|
|
13
13
|
if (typeof locator === 'object') {
|
|
14
|
-
locator = JSON.stringify(locator)
|
|
14
|
+
locator = JSON.stringify(locator)
|
|
15
15
|
}
|
|
16
|
-
throw new Error(`${prefixMessage} "${
|
|
16
|
+
throw new Error(`${prefixMessage} "${new Locator(locator)}" is still seen in DOM.`)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
function dontSeeElementError(locator) {
|
|
20
20
|
if (typeof locator === 'object') {
|
|
21
|
-
locator = JSON.stringify(locator)
|
|
21
|
+
locator = JSON.stringify(locator)
|
|
22
22
|
}
|
|
23
|
-
throw new Error(`${prefixMessage} "${
|
|
23
|
+
throw new Error(`${prefixMessage} "${new Locator(locator)}" is not visible on page.`)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
function dontSeeElementInDOMError(locator) {
|
|
27
27
|
if (typeof locator === 'object') {
|
|
28
|
-
locator = JSON.stringify(locator)
|
|
28
|
+
locator = JSON.stringify(locator)
|
|
29
29
|
}
|
|
30
|
-
throw new Error(`${prefixMessage} "${
|
|
30
|
+
throw new Error(`${prefixMessage} "${new Locator(locator)}" is not seen in DOM.`)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export {
|
|
34
|
-
seeElementError,
|
|
35
|
-
dontSeeElementError,
|
|
36
|
-
seeElementInDOMError,
|
|
37
|
-
dontSeeElementInDOMError,
|
|
38
|
-
};
|
|
33
|
+
export { seeElementError, dontSeeElementError, seeElementInDOMError, dontSeeElementInDOMError }
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
import Locator from '../../locator.js'
|
|
1
|
+
import Locator from '../../locator.js'
|
|
2
2
|
/**
|
|
3
3
|
* Uses to throw readable element not found error
|
|
4
4
|
* Stringify object's locators
|
|
5
5
|
*/
|
|
6
6
|
class ElementNotFound {
|
|
7
|
-
constructor(
|
|
8
|
-
locator,
|
|
9
|
-
prefixMessage = 'Element',
|
|
10
|
-
postfixMessage = 'was not found by text|CSS|XPath',
|
|
11
|
-
) {
|
|
7
|
+
constructor(locator, prefixMessage = 'Element', postfixMessage = 'was not found by text|CSS|XPath') {
|
|
12
8
|
if (typeof locator === 'object') {
|
|
13
|
-
locator = JSON.stringify(locator)
|
|
9
|
+
locator = JSON.stringify(locator)
|
|
14
10
|
}
|
|
15
|
-
throw new Error(`${prefixMessage} "${
|
|
11
|
+
throw new Error(`${prefixMessage} "${new Locator(locator)}" ${postfixMessage}`)
|
|
16
12
|
}
|
|
17
13
|
}
|
|
18
14
|
|
|
19
|
-
export default ElementNotFound
|
|
15
|
+
export default ElementNotFound
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
function RemoteBrowserConnectionRefused(err) {
|
|
2
|
-
this.message = 'Cannot connect to websocket endpoint.\n\n'
|
|
3
|
-
this.message += 'Please make sure remote browser is running and accessible.'
|
|
4
|
-
this.stack = err.error || err
|
|
2
|
+
this.message = 'Cannot connect to websocket endpoint.\n\n'
|
|
3
|
+
this.message += 'Please make sure remote browser is running and accessible.'
|
|
4
|
+
this.stack = err.error || err
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
RemoteBrowserConnectionRefused.prototype = Object.create(Error.prototype)
|
|
7
|
+
RemoteBrowserConnectionRefused.prototype = Object.create(Error.prototype)
|
|
8
8
|
|
|
9
|
-
export default RemoteBrowserConnectionRefused
|
|
9
|
+
export default RemoteBrowserConnectionRefused
|
|
@@ -3,31 +3,31 @@
|
|
|
3
3
|
*/
|
|
4
4
|
class Console {
|
|
5
5
|
constructor() {
|
|
6
|
-
this._logEntries = []
|
|
6
|
+
this._logEntries = []
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
get entries() {
|
|
10
|
-
return this._logEntries
|
|
10
|
+
return this._logEntries
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
clear() {
|
|
14
|
-
this._logEntries = []
|
|
14
|
+
this._logEntries = []
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
includes(msg) {
|
|
18
|
-
const prev = this._logEntries[this._logEntries.length - 1]
|
|
19
|
-
if (!prev) return false
|
|
20
|
-
const text = msg.text && msg.text() || msg._text || ''
|
|
21
|
-
const prevText = prev.text && prev.text() || prev._text || ''
|
|
22
|
-
return text === prevText
|
|
18
|
+
const prev = this._logEntries[this._logEntries.length - 1]
|
|
19
|
+
if (!prev) return false
|
|
20
|
+
const text = (msg.text && msg.text()) || msg._text || ''
|
|
21
|
+
const prevText = (prev.text && prev.text()) || prev._text || ''
|
|
22
|
+
return text === prevText
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
add(entry) {
|
|
26
26
|
if (Array.isArray(entry)) {
|
|
27
|
-
this._logEntries = this._logEntries.concat(entry)
|
|
27
|
+
this._logEntries = this._logEntries.concat(entry)
|
|
28
28
|
}
|
|
29
|
-
this._logEntries.push(entry)
|
|
29
|
+
this._logEntries.push(entry)
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export default Console
|
|
33
|
+
export default Console
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import Locator from '../../locator.js'
|
|
2
|
+
|
|
3
|
+
function buildLocatorString(locator) {
|
|
4
|
+
if (locator.isCustom()) {
|
|
5
|
+
return `${locator.type}=${locator.value}`
|
|
6
|
+
}
|
|
7
|
+
if (locator.isXPath()) {
|
|
8
|
+
return `xpath=${locator.value}`
|
|
9
|
+
}
|
|
10
|
+
return locator.simplify()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function findElements(matcher, locator) {
|
|
14
|
+
const matchedLocator = new Locator(locator, 'css')
|
|
15
|
+
|
|
16
|
+
if (matchedLocator.type === 'react') return findReact(matcher, matchedLocator)
|
|
17
|
+
if (matchedLocator.type === 'vue') return findVue(matcher, matchedLocator)
|
|
18
|
+
if (matchedLocator.type === 'pw') return findByPlaywrightLocator(matcher, matchedLocator)
|
|
19
|
+
if (matchedLocator.isRole()) return findByRole(matcher, matchedLocator)
|
|
20
|
+
|
|
21
|
+
return matcher.locator(buildLocatorString(matchedLocator)).all()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function findElement(matcher, locator) {
|
|
25
|
+
const matchedLocator = new Locator(locator, 'css')
|
|
26
|
+
|
|
27
|
+
if (matchedLocator.type === 'react') return findReact(matcher, matchedLocator)
|
|
28
|
+
if (matchedLocator.type === 'vue') return findVue(matcher, matchedLocator)
|
|
29
|
+
if (matchedLocator.type === 'pw') return findByPlaywrightLocator(matcher, matchedLocator, { first: true })
|
|
30
|
+
if (matchedLocator.isRole()) return findByRole(matcher, matchedLocator, { first: true })
|
|
31
|
+
|
|
32
|
+
return matcher.locator(buildLocatorString(matchedLocator)).first()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function getVisibleElements(elements) {
|
|
36
|
+
const visibleElements = []
|
|
37
|
+
for (const element of elements) {
|
|
38
|
+
if (await element.isVisible()) {
|
|
39
|
+
visibleElements.push(element)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (visibleElements.length === 0) {
|
|
43
|
+
return elements
|
|
44
|
+
}
|
|
45
|
+
return visibleElements
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function findReact(matcher, locator) {
|
|
49
|
+
const details = locator.locator ?? { react: locator.value }
|
|
50
|
+
let locatorString = `_react=${details.react}`
|
|
51
|
+
|
|
52
|
+
if (details.props) {
|
|
53
|
+
locatorString += propBuilder(details.props)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return matcher.locator(locatorString).all()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function findVue(matcher, locator) {
|
|
60
|
+
const details = locator.locator ?? { vue: locator.value }
|
|
61
|
+
let locatorString = `_vue=${details.vue}`
|
|
62
|
+
|
|
63
|
+
if (details.props) {
|
|
64
|
+
locatorString += propBuilder(details.props)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return matcher.locator(locatorString).all()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function findByPlaywrightLocator(matcher, locator, { first = false } = {}) {
|
|
71
|
+
const details = locator.locator ?? { pw: locator.value }
|
|
72
|
+
const locatorValue = details.pw
|
|
73
|
+
|
|
74
|
+
const handle = matcher.locator(locatorValue)
|
|
75
|
+
return first ? handle.first() : handle.all()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function findByRole(matcher, locator, { first = false } = {}) {
|
|
79
|
+
const details = locator.locator ?? { role: locator.value }
|
|
80
|
+
const { role, text, name, exact, includeHidden, ...rest } = details
|
|
81
|
+
const options = { ...rest }
|
|
82
|
+
|
|
83
|
+
if (includeHidden !== undefined) options.includeHidden = includeHidden
|
|
84
|
+
|
|
85
|
+
const accessibleName = name ?? text
|
|
86
|
+
if (accessibleName !== undefined) {
|
|
87
|
+
options.name = accessibleName
|
|
88
|
+
if (exact === true) options.exact = true
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const roleLocator = matcher.getByRole(role, options)
|
|
92
|
+
return first ? roleLocator.first() : roleLocator.all()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function propBuilder(props) {
|
|
96
|
+
let _props = ''
|
|
97
|
+
|
|
98
|
+
for (const [key, value] of Object.entries(props)) {
|
|
99
|
+
if (typeof value === 'object') {
|
|
100
|
+
for (const [k, v] of Object.entries(value)) {
|
|
101
|
+
_props += `[${key}.${k} = "${v}"]`
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
_props += `[${key} = "${value}"]`
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return _props
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export { buildLocatorString, findElements, findElement, getVisibleElements, findReact, findVue, findByPlaywrightLocator, findByRole }
|
|
@@ -2,54 +2,54 @@ export const createValueEngine = () => {
|
|
|
2
2
|
return {
|
|
3
3
|
// Creates a selector that matches given target when queried at the root.
|
|
4
4
|
// Can return undefined if unable to create one.
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
create(root, target) {
|
|
7
|
-
return null
|
|
7
|
+
return null
|
|
8
8
|
},
|
|
9
9
|
|
|
10
10
|
// Returns the first element matching given selector in the root's subtree.
|
|
11
11
|
query(root, selector) {
|
|
12
12
|
if (!root) {
|
|
13
|
-
return null
|
|
13
|
+
return null
|
|
14
14
|
}
|
|
15
|
-
return `${root.value}`.includes(selector) ? root : null
|
|
15
|
+
return `${root.value}`.includes(selector) ? root : null
|
|
16
16
|
},
|
|
17
17
|
|
|
18
18
|
// Returns all elements matching given selector in the root's subtree.
|
|
19
19
|
queryAll(root, selector) {
|
|
20
20
|
if (!root) {
|
|
21
|
-
return null
|
|
21
|
+
return null
|
|
22
22
|
}
|
|
23
|
-
return `${root.value}`.includes(selector) ? root : null
|
|
23
|
+
return `${root.value}`.includes(selector) ? root : null
|
|
24
24
|
},
|
|
25
|
-
}
|
|
26
|
-
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
27
|
|
|
28
28
|
export const createDisabledEngine = () => {
|
|
29
29
|
return {
|
|
30
30
|
// Creates a selector that matches given target when queried at the root.
|
|
31
31
|
// Can return undefined if unable to create one.
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
create(root, target) {
|
|
34
|
-
return null
|
|
34
|
+
return null
|
|
35
35
|
},
|
|
36
36
|
|
|
37
37
|
// Returns the first element matching given selector in the root's subtree.
|
|
38
38
|
query(root, value) {
|
|
39
|
-
const bool = value === 'true'
|
|
39
|
+
const bool = value === 'true'
|
|
40
40
|
if (!root) {
|
|
41
|
-
return null
|
|
41
|
+
return null
|
|
42
42
|
}
|
|
43
|
-
return root.disabled === bool ? root : null
|
|
43
|
+
return root.disabled === bool ? root : null
|
|
44
44
|
},
|
|
45
45
|
|
|
46
46
|
// Returns all elements matching given selector in the root's subtree.
|
|
47
47
|
queryAll(root, value) {
|
|
48
|
-
const bool = value === 'true'
|
|
48
|
+
const bool = value === 'true'
|
|
49
49
|
if (!root) {
|
|
50
|
-
return null
|
|
50
|
+
return null
|
|
51
51
|
}
|
|
52
|
-
return root.disabled === bool ? root : null
|
|
52
|
+
return root.disabled === bool ? root : null
|
|
53
53
|
},
|
|
54
|
-
}
|
|
55
|
-
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1,28 +1,37 @@
|
|
|
1
1
|
async function findReact(matcher, locator) {
|
|
2
|
-
|
|
2
|
+
// Handle both Locator objects and raw locator objects
|
|
3
|
+
const reactLocator = locator.locator || locator
|
|
4
|
+
let _locator = `_react=${reactLocator.react}`;
|
|
3
5
|
let props = '';
|
|
4
6
|
|
|
5
|
-
if (
|
|
6
|
-
props += propBuilder(
|
|
7
|
+
if (reactLocator.props) {
|
|
8
|
+
props += propBuilder(reactLocator.props);
|
|
7
9
|
_locator += props;
|
|
8
10
|
}
|
|
9
11
|
return matcher.locator(_locator).all();
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
async function findVue(matcher, locator) {
|
|
13
|
-
|
|
15
|
+
// Handle both Locator objects and raw locator objects
|
|
16
|
+
const vueLocator = locator.locator || locator
|
|
17
|
+
let _locator = `_vue=${vueLocator.vue}`;
|
|
14
18
|
let props = '';
|
|
15
19
|
|
|
16
|
-
if (
|
|
17
|
-
props += propBuilder(
|
|
20
|
+
if (vueLocator.props) {
|
|
21
|
+
props += propBuilder(vueLocator.props);
|
|
18
22
|
_locator += props;
|
|
19
23
|
}
|
|
20
24
|
return matcher.locator(_locator).all();
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
async function findByPlaywrightLocator(matcher, locator) {
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
// Handle both Locator objects and raw locator objects
|
|
29
|
+
const pwLocator = locator.locator || locator
|
|
30
|
+
if (pwLocator && pwLocator.toString && pwLocator.toString().includes(process.env.testIdAttribute)) {
|
|
31
|
+
return matcher.getByTestId(pwLocator.pw.value.split('=')[1]);
|
|
32
|
+
}
|
|
33
|
+
const pwValue = typeof pwLocator.pw === 'string' ? pwLocator.pw : pwLocator.pw
|
|
34
|
+
return matcher.locator(pwValue).all();
|
|
26
35
|
}
|
|
27
36
|
|
|
28
37
|
function propBuilder(props) {
|
|
@@ -1,30 +1,44 @@
|
|
|
1
1
|
const RESTART_OPTS = {
|
|
2
2
|
session: 'keep',
|
|
3
|
-
browser: true,
|
|
4
3
|
context: false,
|
|
5
|
-
|
|
4
|
+
browser: true,
|
|
5
|
+
}
|
|
6
6
|
|
|
7
|
-
let restarts = null
|
|
7
|
+
let restarts = null
|
|
8
8
|
|
|
9
9
|
export function setRestartStrategy(options) {
|
|
10
|
-
const { restart } = options
|
|
11
|
-
const stringOpts = Object.keys(RESTART_OPTS)
|
|
10
|
+
const { restart } = options
|
|
11
|
+
const stringOpts = Object.keys(RESTART_OPTS)
|
|
12
12
|
|
|
13
13
|
if (stringOpts.includes(restart)) {
|
|
14
|
-
return restarts = restart
|
|
14
|
+
return (restarts = restart)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
// When restart is false, don't restart anything
|
|
18
|
+
if (restart === false) {
|
|
19
|
+
restarts = null
|
|
20
|
+
return
|
|
21
|
+
}
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
// When restart is true, map to 'browser' restart
|
|
24
|
+
if (restart === true) {
|
|
25
|
+
restarts = 'browser'
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
restarts = Object.keys(RESTART_OPTS).find(key => RESTART_OPTS[key] === restart)
|
|
30
|
+
|
|
31
|
+
if (restarts === null || restarts === undefined) throw new Error('No restart strategy set, use the following values for restart: session, context, browser')
|
|
20
32
|
}
|
|
21
33
|
|
|
22
34
|
export function restartsSession() {
|
|
23
|
-
return restarts === 'session'
|
|
35
|
+
return restarts === 'session'
|
|
24
36
|
}
|
|
37
|
+
|
|
25
38
|
export function restartsContext() {
|
|
26
|
-
return restarts === 'context'
|
|
39
|
+
return restarts === 'context'
|
|
27
40
|
}
|
|
41
|
+
|
|
28
42
|
export function restartsBrowser() {
|
|
29
|
-
return restarts === 'browser'
|
|
43
|
+
return restarts === 'browser'
|
|
30
44
|
}
|
|
@@ -2,66 +2,66 @@
|
|
|
2
2
|
* Class to handle the interaction with the Dialog (Popup) Class from Puppeteer
|
|
3
3
|
*/
|
|
4
4
|
class Popup {
|
|
5
|
-
constructor(popup, defaultAction) {
|
|
6
|
-
this._popup = popup
|
|
7
|
-
this._actionType = ''
|
|
8
|
-
this._defaultAction = defaultAction
|
|
5
|
+
constructor(popup = null, defaultAction = '') {
|
|
6
|
+
this._popup = popup
|
|
7
|
+
this._actionType = ''
|
|
8
|
+
this._defaultAction = defaultAction
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
_assertValidActionType(action) {
|
|
12
12
|
if (['accept', 'cancel'].indexOf(action) === -1) {
|
|
13
|
-
throw new Error('Invalid Popup action type. Only "accept" or "cancel" actions are accepted')
|
|
13
|
+
throw new Error('Invalid Popup action type. Only "accept" or "cancel" actions are accepted')
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
set defaultAction(action) {
|
|
18
|
-
this._assertValidActionType(action)
|
|
19
|
-
this._defaultAction = action
|
|
18
|
+
this._assertValidActionType(action)
|
|
19
|
+
this._defaultAction = action
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
get defaultAction() {
|
|
23
|
-
return this._defaultAction
|
|
23
|
+
return this._defaultAction
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
get popup() {
|
|
27
|
-
return this._popup
|
|
27
|
+
return this._popup
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
set popup(popup) {
|
|
31
31
|
if (this._popup) {
|
|
32
|
-
|
|
32
|
+
return
|
|
33
33
|
}
|
|
34
|
-
this._popup = popup
|
|
34
|
+
this._popup = popup
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
get actionType() {
|
|
38
|
-
return this._actionType
|
|
38
|
+
return this._actionType
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
set actionType(action) {
|
|
42
|
-
this._assertValidActionType(action)
|
|
43
|
-
this._actionType = action
|
|
42
|
+
this._assertValidActionType(action)
|
|
43
|
+
this._actionType = action
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
clear() {
|
|
47
|
-
this._popup = null
|
|
48
|
-
this._actionType = ''
|
|
47
|
+
this._popup = null
|
|
48
|
+
this._actionType = ''
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
assertPopupVisible() {
|
|
52
52
|
if (!this._popup) {
|
|
53
|
-
throw new Error('There is no Popup visible')
|
|
53
|
+
throw new Error('There is no Popup visible')
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
assertPopupActionType(type) {
|
|
58
|
-
this.assertPopupVisible()
|
|
59
|
-
const expectedAction = this._actionType || this._defaultAction
|
|
58
|
+
this.assertPopupVisible()
|
|
59
|
+
const expectedAction = this._actionType || this._defaultAction
|
|
60
60
|
if (expectedAction !== type) {
|
|
61
|
-
throw new Error(`Popup action does not fit the expected action type. Expected popup action to be '${expectedAction}' not '${type}`)
|
|
61
|
+
throw new Error(`Popup action does not fit the expected action type. Expected popup action to be '${expectedAction}' not '${type}`)
|
|
62
62
|
}
|
|
63
|
-
this.clear()
|
|
63
|
+
this.clear()
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
export default Popup
|
|
67
|
+
export default Popup
|
|
@@ -1,66 +1,65 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
1
|
+
import fs from 'fs'
|
|
2
2
|
|
|
3
|
-
let resqScript
|
|
3
|
+
let resqScript
|
|
4
4
|
|
|
5
5
|
export default async function findReact(matcher, locator) {
|
|
6
|
-
if (!resqScript) resqScript = fs.readFileSync(
|
|
7
|
-
await matcher.evaluate(resqScript.toString())
|
|
8
|
-
await matcher
|
|
9
|
-
.evaluate(() => window.resq.waitToLoadReact());
|
|
6
|
+
if (!resqScript) resqScript = fs.readFileSync(new URL('resq', import.meta.resolve('resq')).pathname)
|
|
7
|
+
await matcher.evaluate(resqScript.toString())
|
|
8
|
+
await matcher.evaluate(() => window.resq.waitToLoadReact())
|
|
10
9
|
const arrayHandle = await matcher.evaluateHandle(
|
|
11
|
-
|
|
12
|
-
const { selector, props, state } = obj
|
|
10
|
+
obj => {
|
|
11
|
+
const { selector, props, state } = obj
|
|
13
12
|
|
|
14
|
-
let elements = window.resq.resq$$(selector)
|
|
13
|
+
let elements = window.resq.resq$$(selector)
|
|
15
14
|
if (Object.keys(props).length) {
|
|
16
|
-
elements = elements.byProps(props)
|
|
15
|
+
elements = elements.byProps(props)
|
|
17
16
|
}
|
|
18
17
|
if (Object.keys(state).length) {
|
|
19
|
-
elements = elements.byState(state)
|
|
18
|
+
elements = elements.byState(state)
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
if (!elements.length) {
|
|
23
|
-
return []
|
|
22
|
+
return []
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
// resq returns an array of HTMLElements if the React component is a fragment
|
|
27
26
|
// this avoids having nested arrays of nodes which the driver does not understand
|
|
28
27
|
// [[div, div], [div, div]] => [div, div, div, div]
|
|
29
|
-
let nodes = []
|
|
28
|
+
let nodes = []
|
|
30
29
|
|
|
31
|
-
elements.forEach(
|
|
32
|
-
let { node, isFragment } = element
|
|
30
|
+
elements.forEach(element => {
|
|
31
|
+
let { node, isFragment } = element
|
|
33
32
|
|
|
34
33
|
if (!node) {
|
|
35
|
-
isFragment = true
|
|
36
|
-
node = element.children
|
|
34
|
+
isFragment = true
|
|
35
|
+
node = element.children
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
if (isFragment) {
|
|
40
|
-
nodes = nodes.concat(node)
|
|
39
|
+
nodes = nodes.concat(node)
|
|
41
40
|
} else {
|
|
42
|
-
nodes.push(node)
|
|
41
|
+
nodes.push(node)
|
|
43
42
|
}
|
|
44
|
-
})
|
|
43
|
+
})
|
|
45
44
|
|
|
46
|
-
return [...nodes]
|
|
45
|
+
return [...nodes]
|
|
47
46
|
},
|
|
48
47
|
{
|
|
49
48
|
selector: locator.react,
|
|
50
49
|
props: locator.props || {},
|
|
51
50
|
state: locator.state || {},
|
|
52
51
|
},
|
|
53
|
-
)
|
|
52
|
+
)
|
|
54
53
|
|
|
55
|
-
const properties = await arrayHandle.getProperties()
|
|
56
|
-
await arrayHandle.dispose()
|
|
57
|
-
const result = []
|
|
54
|
+
const properties = await arrayHandle.getProperties()
|
|
55
|
+
await arrayHandle.dispose()
|
|
56
|
+
const result = []
|
|
58
57
|
for (const property of properties.values()) {
|
|
59
|
-
const elementHandle = property.asElement()
|
|
58
|
+
const elementHandle = property.asElement()
|
|
60
59
|
if (elementHandle) {
|
|
61
|
-
result.push(elementHandle)
|
|
60
|
+
result.push(elementHandle)
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
return result
|
|
64
|
+
return result
|
|
66
65
|
}
|