codeceptjs 4.0.1-beta.17 → 4.0.1-beta.19
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/lib/helper/Playwright.js +74 -75
- package/lib/helper/extras/PlaywrightLocator.js +13 -34
- package/lib/locator.js +69 -26
- package/package.json +11 -11
- package/typings/promiseBasedTypes.d.ts +3974 -5520
- package/typings/types.d.ts +4146 -5821
- package/lib/helper/extras/PlaywrightReactVueLocator.js +0 -52
package/lib/helper/Playwright.js
CHANGED
|
@@ -30,7 +30,7 @@ import ElementNotFound from './errors/ElementNotFound.js'
|
|
|
30
30
|
import RemoteBrowserConnectionRefused from './errors/RemoteBrowserConnectionRefused.js'
|
|
31
31
|
import Popup from './extras/Popup.js'
|
|
32
32
|
import Console from './extras/Console.js'
|
|
33
|
-
import { findReact, findVue
|
|
33
|
+
import { findReact, findVue } from './extras/PlaywrightLocator.js'
|
|
34
34
|
import WebElement from '../element/WebElement.js'
|
|
35
35
|
|
|
36
36
|
let playwright
|
|
@@ -2489,7 +2489,19 @@ class Playwright extends Helper {
|
|
|
2489
2489
|
* {{> selectOption }}
|
|
2490
2490
|
*/
|
|
2491
2491
|
async selectOption(select, option) {
|
|
2492
|
-
const
|
|
2492
|
+
const selectLocator = Locator.from(select, 'css')
|
|
2493
|
+
let els = null
|
|
2494
|
+
|
|
2495
|
+
if (selectLocator.isFuzzy()) {
|
|
2496
|
+
els = await findByRole(this.page, { role: 'listbox', name: selectLocator.value })
|
|
2497
|
+
if (!els || els.length === 0) {
|
|
2498
|
+
els = await findByRole(this.page, { role: 'combobox', name: selectLocator.value })
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
if (!els || els.length === 0) {
|
|
2503
|
+
els = await findFields.call(this, select)
|
|
2504
|
+
}
|
|
2493
2505
|
assertElementExists(els, select, 'Selectable field')
|
|
2494
2506
|
const el = els[0]
|
|
2495
2507
|
|
|
@@ -2790,17 +2802,6 @@ class Playwright extends Helper {
|
|
|
2790
2802
|
*
|
|
2791
2803
|
*/
|
|
2792
2804
|
async grabTextFrom(locator) {
|
|
2793
|
-
// Handle role locators with text/exact options
|
|
2794
|
-
if (isRoleLocatorObject(locator)) {
|
|
2795
|
-
const elements = await handleRoleLocator(this.page, locator)
|
|
2796
|
-
if (elements && elements.length > 0) {
|
|
2797
|
-
const text = await elements[0].textContent()
|
|
2798
|
-
assertElementExists(text, JSON.stringify(locator))
|
|
2799
|
-
this.debugSection('Text', text)
|
|
2800
|
-
return text
|
|
2801
|
-
}
|
|
2802
|
-
}
|
|
2803
|
-
|
|
2804
2805
|
const locatorObj = new Locator(locator, 'css')
|
|
2805
2806
|
|
|
2806
2807
|
if (locatorObj.isCustom()) {
|
|
@@ -2813,21 +2814,32 @@ class Playwright extends Helper {
|
|
|
2813
2814
|
assertElementExists(text, locatorObj.toString())
|
|
2814
2815
|
this.debugSection('Text', text)
|
|
2815
2816
|
return text
|
|
2816
|
-
}
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2819
|
+
if (locatorObj.isRole()) {
|
|
2820
|
+
// Handle role locators with text/exact options
|
|
2821
|
+
const roleElements = await findByRole(this.page, locator)
|
|
2822
|
+
if (roleElements && roleElements.length > 0) {
|
|
2823
|
+
const text = await roleElements[0].textContent()
|
|
2824
|
+
assertElementExists(text, JSON.stringify(locator))
|
|
2821
2825
|
this.debugSection('Text', text)
|
|
2822
2826
|
return text
|
|
2823
|
-
} catch (error) {
|
|
2824
|
-
// Convert Playwright timeout errors to ElementNotFound for consistency
|
|
2825
|
-
if (error.message && error.message.includes('Timeout')) {
|
|
2826
|
-
throw new ElementNotFound(locator, 'text')
|
|
2827
|
-
}
|
|
2828
|
-
throw error
|
|
2829
2827
|
}
|
|
2830
2828
|
}
|
|
2829
|
+
|
|
2830
|
+
locator = this._contextLocator(locator)
|
|
2831
|
+
try {
|
|
2832
|
+
const text = await this.page.textContent(locator)
|
|
2833
|
+
assertElementExists(text, locator)
|
|
2834
|
+
this.debugSection('Text', text)
|
|
2835
|
+
return text
|
|
2836
|
+
} catch (error) {
|
|
2837
|
+
// Convert Playwright timeout errors to ElementNotFound for consistency
|
|
2838
|
+
if (error.message && error.message.includes('Timeout')) {
|
|
2839
|
+
throw new ElementNotFound(locator, 'text')
|
|
2840
|
+
}
|
|
2841
|
+
throw error
|
|
2842
|
+
}
|
|
2831
2843
|
}
|
|
2832
2844
|
|
|
2833
2845
|
/**
|
|
@@ -4306,50 +4318,26 @@ function buildLocatorString(locator) {
|
|
|
4306
4318
|
if (locator.isXPath()) {
|
|
4307
4319
|
return `xpath=${locator.value}`
|
|
4308
4320
|
}
|
|
4309
|
-
|
|
4321
|
+
return locator.simplify()
|
|
4310
4322
|
}
|
|
4311
4323
|
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
return
|
|
4317
|
-
}
|
|
4318
|
-
|
|
4319
|
-
/**
|
|
4320
|
-
* Handles role locator objects by converting them to Playwright's getByRole() API
|
|
4321
|
-
* Returns elements array if role locator, null otherwise
|
|
4322
|
-
*/
|
|
4323
|
-
async function handleRoleLocator(context, locator) {
|
|
4324
|
-
if (!isRoleLocatorObject(locator)) return null
|
|
4325
|
-
|
|
4326
|
-
const options = {}
|
|
4327
|
-
if (locator.text) options.name = locator.text
|
|
4328
|
-
if (locator.exact !== undefined) options.exact = locator.exact
|
|
4329
|
-
|
|
4330
|
-
return context.getByRole(locator.role, Object.keys(options).length > 0 ? options : undefined).all()
|
|
4324
|
+
async function findByRole(context, locator) {
|
|
4325
|
+
const matchedLocator = Locator.from(locator)
|
|
4326
|
+
if (!matchedLocator.isRole()) return null
|
|
4327
|
+
const roleOptions = matchedLocator.getRoleOptions()
|
|
4328
|
+
return context.getByRole(roleOptions.role, roleOptions.options).all()
|
|
4331
4329
|
}
|
|
4332
4330
|
|
|
4333
4331
|
async function findElements(matcher, locator) {
|
|
4334
|
-
|
|
4335
|
-
const
|
|
4336
|
-
const isVueLocator = locator.type === 'vue' || (locator.locator && locator.locator.vue) || locator.vue
|
|
4337
|
-
const isPwLocator = locator.type === 'pw' || (locator.locator && locator.locator.pw) || locator.pw
|
|
4338
|
-
|
|
4339
|
-
if (isReactLocator) return findReact(matcher, locator)
|
|
4340
|
-
if (isVueLocator) return findVue(matcher, locator)
|
|
4341
|
-
if (isPwLocator) return findByPlaywrightLocator.call(this, matcher, locator)
|
|
4342
|
-
|
|
4343
|
-
// Handle role locators with text/exact options (e.g., {role: 'button', text: 'Submit', exact: true})
|
|
4344
|
-
const roleElements = await handleRoleLocator(matcher, locator)
|
|
4332
|
+
const matchedLocator = Locator.from(locator)
|
|
4333
|
+
const roleElements = await findByRole(matcher, matchedLocator)
|
|
4345
4334
|
if (roleElements) return roleElements
|
|
4346
4335
|
|
|
4347
|
-
|
|
4336
|
+
const isReactLocator = matchedLocator.type === 'react'
|
|
4337
|
+
const isVueLocator = matchedLocator.type === 'vue'
|
|
4348
4338
|
|
|
4349
|
-
|
|
4350
|
-
if (
|
|
4351
|
-
return findCustomElements.call(this, matcher, locator)
|
|
4352
|
-
}
|
|
4339
|
+
if (isReactLocator) return findReact(matcher, matchedLocator)
|
|
4340
|
+
if (isVueLocator) return findVue(matcher, matchedLocator)
|
|
4353
4341
|
|
|
4354
4342
|
// Check if we have a custom context locator and need to search within it
|
|
4355
4343
|
if (this.contextLocator) {
|
|
@@ -4362,12 +4350,12 @@ async function findElements(matcher, locator) {
|
|
|
4362
4350
|
}
|
|
4363
4351
|
|
|
4364
4352
|
// Search within the first context element
|
|
4365
|
-
const locatorString = buildLocatorString(
|
|
4353
|
+
const locatorString = buildLocatorString(matchedLocator)
|
|
4366
4354
|
return contextElements[0].locator(locatorString).all()
|
|
4367
4355
|
}
|
|
4368
4356
|
}
|
|
4369
4357
|
|
|
4370
|
-
const locatorString = buildLocatorString(
|
|
4358
|
+
const locatorString = buildLocatorString(matchedLocator)
|
|
4371
4359
|
|
|
4372
4360
|
return matcher.locator(locatorString).all()
|
|
4373
4361
|
}
|
|
@@ -4460,13 +4448,17 @@ async function findCustomElements(matcher, locator) {
|
|
|
4460
4448
|
}
|
|
4461
4449
|
|
|
4462
4450
|
async function findElement(matcher, locator) {
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
if (
|
|
4451
|
+
const matchedLocator = Locator.from(locator)
|
|
4452
|
+
const roleElements = await findByRole(matcher, matchedLocator)
|
|
4453
|
+
if (roleElements && roleElements.length > 0) return roleElements[0]
|
|
4454
|
+
|
|
4455
|
+
const isReactLocator = matchedLocator.type === 'react'
|
|
4456
|
+
const isVueLocator = matchedLocator.type === 'vue'
|
|
4466
4457
|
|
|
4467
|
-
|
|
4458
|
+
if (isReactLocator) return findReact(matcher, matchedLocator)
|
|
4459
|
+
if (isVueLocator) return findVue(matcher, matchedLocator)
|
|
4468
4460
|
|
|
4469
|
-
return matcher.locator(buildLocatorString(
|
|
4461
|
+
return matcher.locator(buildLocatorString(matchedLocator)).first()
|
|
4470
4462
|
}
|
|
4471
4463
|
|
|
4472
4464
|
async function getVisibleElements(elements) {
|
|
@@ -4518,8 +4510,14 @@ async function proceedClick(locator, context = null, options = {}) {
|
|
|
4518
4510
|
}
|
|
4519
4511
|
|
|
4520
4512
|
async function findClickable(matcher, locator) {
|
|
4513
|
+
// Convert to Locator first to handle JSON strings properly
|
|
4521
4514
|
const matchedLocator = new Locator(locator)
|
|
4522
4515
|
|
|
4516
|
+
// Handle role locators from Locator
|
|
4517
|
+
if (matchedLocator.isRole()) {
|
|
4518
|
+
return findByRole(matcher, matchedLocator)
|
|
4519
|
+
}
|
|
4520
|
+
|
|
4523
4521
|
if (!matchedLocator.isFuzzy()) return findElements.call(this, matcher, matchedLocator)
|
|
4524
4522
|
|
|
4525
4523
|
let els
|
|
@@ -4592,14 +4590,17 @@ async function findCheckable(locator, context) {
|
|
|
4592
4590
|
}
|
|
4593
4591
|
|
|
4594
4592
|
// Handle role locators with text/exact options
|
|
4595
|
-
const roleElements = await
|
|
4593
|
+
const roleElements = await findByRole(contextEl, locator)
|
|
4596
4594
|
if (roleElements) return roleElements
|
|
4597
4595
|
|
|
4598
|
-
const matchedLocator =
|
|
4596
|
+
const matchedLocator = Locator.from(locator)
|
|
4599
4597
|
if (!matchedLocator.isFuzzy()) {
|
|
4600
4598
|
return findElements.call(this, contextEl, matchedLocator)
|
|
4601
4599
|
}
|
|
4602
4600
|
|
|
4601
|
+
const checkboxByRole = await findByRole(contextEl, { role: 'checkbox', name: matchedLocator.value })
|
|
4602
|
+
if (checkboxByRole) return checkboxByRole
|
|
4603
|
+
|
|
4603
4604
|
const literal = xpathLocator.literal(matchedLocator.value)
|
|
4604
4605
|
let els = await findElements.call(this, contextEl, Locator.checkable.byText(literal))
|
|
4605
4606
|
if (els.length) {
|
|
@@ -4621,17 +4622,15 @@ async function proceedIsChecked(assertType, option) {
|
|
|
4621
4622
|
}
|
|
4622
4623
|
|
|
4623
4624
|
async function findFields(locator) {
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
const roleElements = await handleRoleLocator(page, locator)
|
|
4628
|
-
if (roleElements) return roleElements
|
|
4629
|
-
}
|
|
4625
|
+
const page = await this.page
|
|
4626
|
+
const roleElements = await findByRole(page, locator)
|
|
4627
|
+
if (roleElements) return roleElements
|
|
4630
4628
|
|
|
4631
4629
|
const matchedLocator = new Locator(locator)
|
|
4632
4630
|
if (!matchedLocator.isFuzzy()) {
|
|
4633
4631
|
return this._locate(matchedLocator)
|
|
4634
4632
|
}
|
|
4633
|
+
|
|
4635
4634
|
const literal = xpathLocator.literal(locator)
|
|
4636
4635
|
|
|
4637
4636
|
let els = await this._locate({ xpath: Locator.field.labelEquals(literal) })
|
|
@@ -11,22 +11,20 @@ function buildLocatorString(locator) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
async function findElements(matcher, locator) {
|
|
14
|
-
const matchedLocator =
|
|
14
|
+
const matchedLocator = Locator.from(locator, 'css')
|
|
15
15
|
|
|
16
16
|
if (matchedLocator.type === 'react') return findReact(matcher, matchedLocator)
|
|
17
17
|
if (matchedLocator.type === 'vue') return findVue(matcher, matchedLocator)
|
|
18
|
-
if (matchedLocator.type === 'pw') return findByPlaywrightLocator(matcher, matchedLocator)
|
|
19
18
|
if (matchedLocator.isRole()) return findByRole(matcher, matchedLocator)
|
|
20
19
|
|
|
21
20
|
return matcher.locator(buildLocatorString(matchedLocator)).all()
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
async function findElement(matcher, locator) {
|
|
25
|
-
const matchedLocator =
|
|
24
|
+
const matchedLocator = Locator.from(locator, 'css')
|
|
26
25
|
|
|
27
26
|
if (matchedLocator.type === 'react') return findReact(matcher, matchedLocator)
|
|
28
27
|
if (matchedLocator.type === 'vue') return findVue(matcher, matchedLocator)
|
|
29
|
-
if (matchedLocator.type === 'pw') return findByPlaywrightLocator(matcher, matchedLocator, { first: true })
|
|
30
28
|
if (matchedLocator.isRole()) return findByRole(matcher, matchedLocator, { first: true })
|
|
31
29
|
|
|
32
30
|
return matcher.locator(buildLocatorString(matchedLocator)).first()
|
|
@@ -46,49 +44,30 @@ async function getVisibleElements(elements) {
|
|
|
46
44
|
}
|
|
47
45
|
|
|
48
46
|
async function findReact(matcher, locator) {
|
|
49
|
-
const
|
|
50
|
-
let locatorString = `_react=${
|
|
47
|
+
const props = locator.locator?.props
|
|
48
|
+
let locatorString = `_react=${locator.value}`
|
|
51
49
|
|
|
52
|
-
if (
|
|
53
|
-
locatorString += propBuilder(
|
|
50
|
+
if (props) {
|
|
51
|
+
locatorString += propBuilder(props)
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
return matcher.locator(locatorString).all()
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
async function findVue(matcher, locator) {
|
|
60
|
-
const
|
|
61
|
-
let locatorString = `_vue=${
|
|
58
|
+
const props = locator.locator?.props
|
|
59
|
+
let locatorString = `_vue=${locator.value}`
|
|
62
60
|
|
|
63
|
-
if (
|
|
64
|
-
locatorString += propBuilder(
|
|
61
|
+
if (props) {
|
|
62
|
+
locatorString += propBuilder(props)
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
return matcher.locator(locatorString).all()
|
|
68
66
|
}
|
|
69
67
|
|
|
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
68
|
async function findByRole(matcher, locator, { first = false } = {}) {
|
|
79
|
-
const
|
|
80
|
-
const
|
|
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)
|
|
69
|
+
const roleOptions = locator.getRoleOptions()
|
|
70
|
+
const roleLocator = matcher.getByRole(roleOptions.role, roleOptions.options)
|
|
92
71
|
return first ? roleLocator.first() : roleLocator.all()
|
|
93
72
|
}
|
|
94
73
|
|
|
@@ -107,4 +86,4 @@ function propBuilder(props) {
|
|
|
107
86
|
return _props
|
|
108
87
|
}
|
|
109
88
|
|
|
110
|
-
export { buildLocatorString, findElements, findElement, getVisibleElements, findReact, findVue,
|
|
89
|
+
export { buildLocatorString, findElements, findElement, getVisibleElements, findReact, findVue, findByRole }
|
package/lib/locator.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createRequire } from 'module'
|
|
|
5
5
|
const require = createRequire(import.meta.url)
|
|
6
6
|
let cssToXPath
|
|
7
7
|
|
|
8
|
-
const locatorTypes = ['css', 'by', 'xpath', 'id', 'name', 'fuzzy', 'frame', 'shadow', '
|
|
8
|
+
const locatorTypes = ['css', 'by', 'xpath', 'id', 'name', 'fuzzy', 'frame', 'shadow', 'role']
|
|
9
9
|
/** @class */
|
|
10
10
|
class Locator {
|
|
11
11
|
/**
|
|
@@ -29,14 +29,12 @@ class Locator {
|
|
|
29
29
|
Object.assign(this, locator)
|
|
30
30
|
return
|
|
31
31
|
}
|
|
32
|
+
this._applyObjectLocator(locator)
|
|
33
|
+
return
|
|
34
|
+
}
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.value = locator[this.type]
|
|
36
|
-
this.strict = true
|
|
37
|
-
|
|
38
|
-
Locator.filters.forEach(f => f(locator, this))
|
|
39
|
-
|
|
36
|
+
// Try to parse JSON strings that look like objects
|
|
37
|
+
if (this.parsedJsonAsString(locator)) {
|
|
40
38
|
return
|
|
41
39
|
}
|
|
42
40
|
|
|
@@ -53,8 +51,9 @@ class Locator {
|
|
|
53
51
|
if (isShadow(locator)) {
|
|
54
52
|
this.type = 'shadow'
|
|
55
53
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
54
|
+
if (isReactVueLocator(locator)) {
|
|
55
|
+
// React/Vue locators - keep as fuzzy type, helpers will handle them specially
|
|
56
|
+
this.type = 'fuzzy'
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
Locator.filters.forEach(f => f(locator, this))
|
|
@@ -76,8 +75,6 @@ class Locator {
|
|
|
76
75
|
return this.value
|
|
77
76
|
case 'shadow':
|
|
78
77
|
return { shadow: this.value }
|
|
79
|
-
case 'pw':
|
|
80
|
-
return { pw: this.value }
|
|
81
78
|
case 'role':
|
|
82
79
|
return `[role="${this.value}"]`
|
|
83
80
|
}
|
|
@@ -86,9 +83,43 @@ class Locator {
|
|
|
86
83
|
|
|
87
84
|
toStrict() {
|
|
88
85
|
if (!this.type) return null
|
|
86
|
+
if (this.type === 'role' && this.locator) {
|
|
87
|
+
return this.locator
|
|
88
|
+
}
|
|
89
89
|
return { [this.type]: this.value }
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
parsedJsonAsString(locator) {
|
|
93
|
+
if (typeof locator !== 'string') {
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const trimmed = locator.trim()
|
|
98
|
+
if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {
|
|
99
|
+
return false
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const parsed = JSON.parse(trimmed)
|
|
104
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
105
|
+
this._applyObjectLocator(parsed)
|
|
106
|
+
return true
|
|
107
|
+
}
|
|
108
|
+
} catch (e) {
|
|
109
|
+
}
|
|
110
|
+
return false
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_applyObjectLocator(locator) {
|
|
114
|
+
this.strict = true
|
|
115
|
+
this.locator = locator
|
|
116
|
+
const keys = Object.keys(locator)
|
|
117
|
+
const [type] = keys
|
|
118
|
+
this.type = type
|
|
119
|
+
this.value = keys.length > 1 ? locator : locator[type]
|
|
120
|
+
Locator.filters.forEach(f => f(locator, this))
|
|
121
|
+
}
|
|
122
|
+
|
|
92
123
|
/**
|
|
93
124
|
* @returns {string}
|
|
94
125
|
*/
|
|
@@ -127,17 +158,27 @@ class Locator {
|
|
|
127
158
|
/**
|
|
128
159
|
* @returns {boolean}
|
|
129
160
|
*/
|
|
130
|
-
|
|
131
|
-
return this.type === '
|
|
161
|
+
isRole() {
|
|
162
|
+
return this.type === 'role'
|
|
132
163
|
}
|
|
133
164
|
|
|
134
165
|
/**
|
|
135
|
-
* @returns {
|
|
166
|
+
* @returns {{role: string, options: object}|null}
|
|
136
167
|
*/
|
|
137
|
-
|
|
138
|
-
|
|
168
|
+
getRoleOptions() {
|
|
169
|
+
if (!this.isRole()) return null
|
|
170
|
+
const data = this.locator && typeof this.locator === 'object' ? this.locator : { role: this.value }
|
|
171
|
+
const { role, text, name, exact, includeHidden, ...rest } = data
|
|
172
|
+
let options = { ...rest }
|
|
173
|
+
const accessibleName = name ?? text
|
|
174
|
+
if (accessibleName !== undefined) options.name = accessibleName
|
|
175
|
+
if (exact !== undefined) options.exact = exact
|
|
176
|
+
if (includeHidden !== undefined) options.includeHidden = includeHidden
|
|
177
|
+
if (Object.keys(options).length === 0) options = undefined
|
|
178
|
+
return { role, options }
|
|
139
179
|
}
|
|
140
180
|
|
|
181
|
+
|
|
141
182
|
/**
|
|
142
183
|
* @returns {boolean}
|
|
143
184
|
*/
|
|
@@ -404,6 +445,16 @@ Locator.build = locator => {
|
|
|
404
445
|
return new Locator(locator, 'css')
|
|
405
446
|
}
|
|
406
447
|
|
|
448
|
+
/**
|
|
449
|
+
* @param {CodeceptJS.LocatorOrString|Locator} locator
|
|
450
|
+
* @param {string} [defaultType]
|
|
451
|
+
* @returns {Locator}
|
|
452
|
+
*/
|
|
453
|
+
Locator.from = (locator, defaultType = '') => {
|
|
454
|
+
if (locator instanceof Locator) return locator
|
|
455
|
+
return new Locator(locator, defaultType)
|
|
456
|
+
}
|
|
457
|
+
|
|
407
458
|
/**
|
|
408
459
|
* Filters to modify locators
|
|
409
460
|
* @type {Array<function(CodeceptJS.LocatorOrString, Locator): void>}
|
|
@@ -604,20 +655,12 @@ function removePrefix(xpath) {
|
|
|
604
655
|
* @param {string} locator
|
|
605
656
|
* @returns {boolean}
|
|
606
657
|
*/
|
|
607
|
-
function
|
|
658
|
+
function isReactVueLocator(locator) {
|
|
608
659
|
return locator.includes('_react') || locator.includes('_vue')
|
|
609
660
|
}
|
|
610
661
|
|
|
611
662
|
/**
|
|
612
663
|
* @private
|
|
613
|
-
* check if the locator is a role locator
|
|
614
|
-
* @param {{role: string}} locator
|
|
615
|
-
* @returns {boolean}
|
|
616
|
-
*/
|
|
617
|
-
function isRoleLocator(locator) {
|
|
618
|
-
return locator.role !== undefined && typeof locator.role === 'string' && Object.keys(locator).length >= 1
|
|
619
|
-
}
|
|
620
|
-
|
|
621
664
|
/**
|
|
622
665
|
* @private
|
|
623
666
|
* @param {CodeceptJS.LocatorOrString} locator
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "4.0.1-beta.
|
|
3
|
+
"version": "4.0.1-beta.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
6
6
|
"keywords": [
|
|
@@ -88,13 +88,13 @@
|
|
|
88
88
|
"@codeceptjs/configure": "1.0.6",
|
|
89
89
|
"@codeceptjs/helper": "2.0.4",
|
|
90
90
|
"@cucumber/cucumber-expressions": "18",
|
|
91
|
-
"@cucumber/gherkin": "
|
|
92
|
-
"@cucumber/messages": "
|
|
91
|
+
"@cucumber/gherkin": "37.0.0",
|
|
92
|
+
"@cucumber/messages": "31.0.0",
|
|
93
93
|
"@xmldom/xmldom": "0.9.8",
|
|
94
94
|
"acorn": "8.15.0",
|
|
95
95
|
"ai": "^5.0.60",
|
|
96
96
|
"arrify": "3.0.0",
|
|
97
|
-
"axios": "1.
|
|
97
|
+
"axios": "1.13.2",
|
|
98
98
|
"chalk": "4.1.2",
|
|
99
99
|
"cheerio": "^1.0.0",
|
|
100
100
|
"chokidar": "^4.0.3",
|
|
@@ -108,11 +108,11 @@
|
|
|
108
108
|
"fn-args": "4.0.0",
|
|
109
109
|
"fs-extra": "11.3.2",
|
|
110
110
|
"fuse.js": "^7.0.0",
|
|
111
|
-
"glob": ">=9.0.0 <
|
|
111
|
+
"glob": ">=9.0.0 <14",
|
|
112
112
|
"html-minifier-terser": "7.2.0",
|
|
113
113
|
"inquirer": "^8.2.7",
|
|
114
114
|
"invisi-data": "^1.0.0",
|
|
115
|
-
"joi": "18.0.
|
|
115
|
+
"joi": "18.0.2",
|
|
116
116
|
"js-beautify": "1.15.4",
|
|
117
117
|
"lodash.clonedeep": "4.5.0",
|
|
118
118
|
"lodash.merge": "4.6.2",
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"@types/node": "^24.9.2",
|
|
150
150
|
"@wdio/sauce-service": "9.12.5",
|
|
151
151
|
"@wdio/selenium-standalone-service": "8.15.0",
|
|
152
|
-
"@wdio/utils": "9.
|
|
152
|
+
"@wdio/utils": "9.21.0",
|
|
153
153
|
"@xmldom/xmldom": "0.9.8",
|
|
154
154
|
"bunosh": "latest",
|
|
155
155
|
"chai": "^6.2.1",
|
|
@@ -162,8 +162,8 @@
|
|
|
162
162
|
"eslint-plugin-mocha": "11.1.0",
|
|
163
163
|
"expect": "30.2.0",
|
|
164
164
|
"express": "^5.1.0",
|
|
165
|
-
"globals": "16.
|
|
166
|
-
"graphql": "16.
|
|
165
|
+
"globals": "16.5.0",
|
|
166
|
+
"graphql": "16.12.0",
|
|
167
167
|
"graphql-tag": "^2.12.6",
|
|
168
168
|
"husky": "9.1.7",
|
|
169
169
|
"jsdoc": "^3.6.11",
|
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
"mochawesome": "^7.1.3",
|
|
173
173
|
"playwright": "1.55.1",
|
|
174
174
|
"prettier": "^3.3.2",
|
|
175
|
-
"puppeteer": "24.
|
|
175
|
+
"puppeteer": "24.33.0",
|
|
176
176
|
"qrcode-terminal": "0.12.0",
|
|
177
177
|
"rosie": "2.1.1",
|
|
178
178
|
"runok": "^0.9.3",
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
"tsd": "^0.33.0",
|
|
185
185
|
"tsd-jsdoc": "2.5.0",
|
|
186
186
|
"tsx": "^4.19.2",
|
|
187
|
-
"typedoc": "0.28.
|
|
187
|
+
"typedoc": "0.28.15",
|
|
188
188
|
"typedoc-plugin-markdown": "4.9.0",
|
|
189
189
|
"typescript": "5.8.3",
|
|
190
190
|
"wdio-docker-service": "3.2.1",
|