codeceptjs 4.0.1-beta.25 → 4.0.1-beta.26
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/bin/codecept.js +1 -2
- package/lib/command/{shell.js → interactive.js} +3 -31
- package/lib/config.js +3 -2
- package/lib/container.js +17 -3
- package/lib/helper/Playwright.js +186 -263
- package/lib/helper/Puppeteer.js +33 -115
- package/lib/helper/WebDriver.js +22 -114
- package/lib/helper/extras/PlaywrightLocator.js +34 -13
- package/lib/helper/extras/PlaywrightReactVueLocator.js +52 -0
- package/lib/locator.js +31 -117
- package/lib/mocha/test.js +4 -2
- package/lib/output.js +2 -2
- package/lib/utils/typescript.js +61 -34
- package/package.json +8 -8
- package/typings/index.d.ts +1 -1
- package/typings/promiseBasedTypes.d.ts +5475 -3929
- package/typings/types.d.ts +5767 -4092
- package/lib/helper/errors/MultipleElementsFound.js +0 -135
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import Locator from '../../locator.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Error thrown when strict mode is enabled and multiple elements are found
|
|
5
|
-
* for a single-element locator operation (click, fillField, etc.)
|
|
6
|
-
*/
|
|
7
|
-
class MultipleElementsFound extends Error {
|
|
8
|
-
/**
|
|
9
|
-
* @param {Locator|string|object} locator - The locator used
|
|
10
|
-
* @param {Array<HTMLElement>} elements - Array of Playwright element handles found
|
|
11
|
-
*/
|
|
12
|
-
constructor(locator, elements) {
|
|
13
|
-
super(`Multiple elements (${elements.length}) found for "${locator}". Call fetchDetails() for full information.`)
|
|
14
|
-
this.name = 'MultipleElementsFound'
|
|
15
|
-
this.locator = locator
|
|
16
|
-
this.elements = elements
|
|
17
|
-
this.count = elements.length
|
|
18
|
-
this._detailsFetched = false
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Fetch detailed information about the found elements asynchronously
|
|
23
|
-
* This updates the error message with XPath and element previews
|
|
24
|
-
*/
|
|
25
|
-
async fetchDetails() {
|
|
26
|
-
if (this._detailsFetched) return
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
if (typeof this.locator === 'object' && !(this.locator instanceof Locator)) {
|
|
30
|
-
this.locator = JSON.stringify(this.locator)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const locatorObj = new Locator(this.locator)
|
|
34
|
-
const elementList = await this._generateElementList(this.elements, this.count)
|
|
35
|
-
|
|
36
|
-
this.message = `Multiple elements (${this.count}) found for "${locatorObj.toString()}" in strict mode.\n` +
|
|
37
|
-
elementList +
|
|
38
|
-
`\nUse a more specific locator or use grabWebElements() to handle multiple elements.`
|
|
39
|
-
} catch (err) {
|
|
40
|
-
this.message = `Multiple elements (${this.count}) found. Failed to fetch details: ${err.message}`
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
this._detailsFetched = true
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Generate a formatted list of found elements with their XPath and preview
|
|
48
|
-
* @param {Array<HTMLElement>} elements
|
|
49
|
-
* @param {number} count
|
|
50
|
-
* @returns {Promise<string>}
|
|
51
|
-
*/
|
|
52
|
-
async _generateElementList(elements, count) {
|
|
53
|
-
const items = []
|
|
54
|
-
const maxToShow = Math.min(count, 10)
|
|
55
|
-
|
|
56
|
-
for (let i = 0; i < maxToShow; i++) {
|
|
57
|
-
const el = elements[i]
|
|
58
|
-
try {
|
|
59
|
-
const info = await this._getElementInfo(el)
|
|
60
|
-
items.push(` ${i + 1}. ${info.xpath} (${info.preview})`)
|
|
61
|
-
} catch (err) {
|
|
62
|
-
// Element might be detached or inaccessible
|
|
63
|
-
items.push(` ${i + 1}. [Unable to get element info: ${err.message}]`)
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (count > 10) {
|
|
68
|
-
items.push(` ... and ${count - 10} more`)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return items.join('\n')
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Get XPath and preview for an element by running JavaScript in browser context
|
|
76
|
-
* @param {HTMLElement} element
|
|
77
|
-
* @returns {Promise<{xpath: string, preview: string}>}
|
|
78
|
-
*/
|
|
79
|
-
async _getElementInfo(element) {
|
|
80
|
-
return element.evaluate((el) => {
|
|
81
|
-
// Generate a unique XPath for this element
|
|
82
|
-
const getUniqueXPath = (element) => {
|
|
83
|
-
if (element.id) {
|
|
84
|
-
return `//*[@id="${element.id}"]`
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const parts = []
|
|
88
|
-
let current = element
|
|
89
|
-
|
|
90
|
-
while (current && current.nodeType === Node.ELEMENT_NODE) {
|
|
91
|
-
let index = 0
|
|
92
|
-
let sibling = current.previousSibling
|
|
93
|
-
|
|
94
|
-
while (sibling) {
|
|
95
|
-
if (sibling.nodeType === Node.ELEMENT_NODE && sibling.tagName === current.tagName) {
|
|
96
|
-
index++
|
|
97
|
-
}
|
|
98
|
-
sibling = sibling.previousSibling
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const tagName = current.tagName.toLowerCase()
|
|
102
|
-
const pathIndex = index > 0 ? `[${index + 1}]` : ''
|
|
103
|
-
parts.unshift(`${tagName}${pathIndex}`)
|
|
104
|
-
|
|
105
|
-
current = current.parentElement
|
|
106
|
-
|
|
107
|
-
// Stop at body to keep XPath reasonable
|
|
108
|
-
if (current && current.tagName === 'BODY') {
|
|
109
|
-
parts.unshift('body')
|
|
110
|
-
break
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return '/' + parts.join('/')
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Get a preview of the element (tag, classes, id)
|
|
118
|
-
const getPreview = (element) => {
|
|
119
|
-
const tag = element.tagName.toLowerCase()
|
|
120
|
-
const id = element.id ? `#${element.id}` : ''
|
|
121
|
-
const classes = element.className
|
|
122
|
-
? '.' + element.className.split(' ').filter(c => c).join('.')
|
|
123
|
-
: ''
|
|
124
|
-
return `${tag}${id}${classes || ''}`
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
xpath: getUniqueXPath(el),
|
|
129
|
-
preview: getPreview(el),
|
|
130
|
-
}
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export default MultipleElementsFound
|