Skip to content

Commit 342d020

Browse files
miraoclaude
andauthored
fix(typings): type grabWebElement(s) as CodeceptJS.WebElement (#5786) (#5787)
* fix(typings): type grabWebElement(s) as CodeceptJS.WebElement (#5786) Generate a CodeceptJS.WebElement declaration from lib/element/WebElement.js and use it as the return type of grabWebElement() and grabWebElements(). Fix WebElement JSDoc that jsdoc could not parse or that referenced undefined types, and mark click()/type() options as optional. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(Puppeteer): return WebElement from grabWebElement() A duplicate grabWebElement() overrode the WebElement-returning one and returned the raw ElementHandle, contradicting the new typings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(webapi): check grabWebElement() result via toOuterHTML() getText() is not implemented for CDPBrowser's WebElement, which broke the Lightpanda, Moli and Obscura jobs. toOuterHTML() works on all helpers and still fails on a raw Puppeteer ElementHandle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 533584e commit 342d020

8 files changed

Lines changed: 24 additions & 14 deletions

File tree

‎docs/webapi/grabWebElement.mustache‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ const webElement = await I.grabWebElement('#button');
66
```
77

88
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
9-
@returns {Promise<*>} WebElement of being used Web helper
9+
@returns {Promise<CodeceptJS.WebElement>} WebElement of being used Web helper

‎docs/webapi/grabWebElements.mustache‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ const webElements = await I.grabWebElements('#button');
66
```
77

88
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
9-
@returns {Promise<*>} WebElement of being used Web helper
9+
@returns {Promise<CodeceptJS.WebElement[]>} WebElements of being used Web helper

‎lib/element/WebElement.js‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class WebElement {
2929

3030
/**
3131
* Get the native element instance
32-
* @returns {ElementHandle|WebElement|ElementHandle} Native element
32+
* @returns {any} Native element (Playwright/Puppeteer ElementHandle or WebdriverIO element)
3333
*/
3434
getNativeElement() {
3535
return this.element
@@ -220,7 +220,7 @@ class WebElement {
220220

221221
/**
222222
* Click the element
223-
* @param {Object} options Click options
223+
* @param {Object} [options] Click options
224224
* @returns {Promise<void>}
225225
*/
226226
async click(options = {}) {
@@ -239,7 +239,7 @@ class WebElement {
239239
/**
240240
* Type text into the element
241241
* @param {string} text Text to type
242-
* @param {Object} options Type options
242+
* @param {Object} [options] Type options
243243
* @returns {Promise<void>}
244244
*/
245245
async type(text, options = {}) {
@@ -362,7 +362,7 @@ class WebElement {
362362
* Treat this element as an iframe; invoke `fn` with a WebElement wrapping
363363
* the iframe body. For WebDriver this switches the browser into the frame
364364
* for the duration of the callback and switches back on exit.
365-
* @param {(body: WebElement) => Promise<any>} fn
365+
* @param {function(WebElement): Promise<any>} fn
366366
* @returns {Promise<any>} Return value of fn
367367
*/
368368
async inIframe(fn) {
@@ -530,7 +530,7 @@ class WebElement {
530530
* @param {object} [opts]
531531
* @param {number} [opts.maxHtmlLength=300] passed through to toSimplifiedHTML
532532
* @param {string[]} [opts.attrs] attribute names to surface
533-
* @returns {Promise<{text?: string, html?: string, visible?: boolean, enabled?: boolean, attrs?: object}>}
533+
* @returns {Promise<{text: (string|undefined), html: (string|undefined), visible: (boolean|undefined), enabled: (boolean|undefined), attrs: (Object|undefined)}>}
534534
*/
535535
async describe({ maxHtmlLength = 300, attrs = ['id', 'class', 'name', 'role', 'type', 'href', 'value', 'aria-label', 'placeholder', 'data-testid'] } = {}) {
536536
const out = {}

‎lib/helper/Puppeteer.js‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,12 +1097,6 @@ class Puppeteer extends Helper {
10971097
return new WebElement(elements[0], this)
10981098
}
10991099

1100-
async grabWebElement(locator) {
1101-
const els = await this._locate(locator)
1102-
assertElementExists(els, locator)
1103-
return els[0]
1104-
}
1105-
11061100
/**
11071101
* Switch focus to a particular tab by its number. It waits tabs loading and then switch tab
11081102
*

‎test/helper/webapi.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2744,7 +2744,7 @@ export function tests() {
27442744
// Test grabbing specific element
27452745
if (!isHelper('WebDriver')) {
27462746
const submitButton = await I.grabWebElement({ role: 'button', text: 'Submit' })
2747-
assert.ok(submitButton)
2747+
assert.match(await submitButton.toOuterHTML(), /id="submitBtn"/)
27482748
}
27492749

27502750
// Test grabbing text from role elements

‎typings/jsdoc.conf.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"./lib/data/table.js",
1111
"./lib/data/dataTableArgument.js",
1212
"./lib/effects.js",
13+
"./lib/element/WebElement.js",
1314
"./lib/event.js",
1415
"./lib/index.js",
1516
"./lib/locator.js",

‎typings/tests/helpers/Playwright.types.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ expectType<CodeceptJS.StepPromise>(playwright.dontSeeInField(str, str));
7676
expectType<CodeceptJS.ElementStepPromise>(playwright.attachFile(str, str));
7777
expectType<CodeceptJS.ElementStepPromise>(playwright.selectOption(str, str));
7878
expectType<Promise<number>>(playwright.grabNumberOfVisibleElements(str));
79+
expectType<Promise<CodeceptJS.WebElement[]>>(playwright.grabWebElements(str));
80+
expectType<Promise<CodeceptJS.WebElement>>(playwright.grabWebElement(str));
7981
expectType<CodeceptJS.StepPromise>(playwright.seeInCurrentUrl(str));
8082
expectType<CodeceptJS.StepPromise>(playwright.dontSeeInCurrentUrl(str));
8183
expectType<CodeceptJS.StepPromise>(playwright.seeCurrentUrlEquals(str));
@@ -156,3 +158,14 @@ expectType<CodeceptJS.ElementStepPromise>(playwright.checkOption(str).at(2))
156158
expectType<CodeceptJS.StepPromise>(playwright.see(str).timeout(5))
157159
expectType<CodeceptJS.StepPromise>(playwright.see(str).retry(3))
158160
expectType<CodeceptJS.ElementStepPromise>(playwright.click(str).first().timeout(5).retry(3))
161+
162+
async function webElementTypes(el: CodeceptJS.WebElement) {
163+
expectType<string>(await el.getText());
164+
expectType<string | null>(await el.getAttribute(str));
165+
expectType<boolean>(await el.isVisible());
166+
expectType<void>(await el.click());
167+
expectType<CodeceptJS.WebElement | null>(await el.$(str));
168+
expectType<CodeceptJS.WebElement[]>(await el.$$(str));
169+
expectError(el.getAtribute(str));
170+
expectError(el.getAttribute(num));
171+
}

‎typings/tests/helpers/PlaywrightTs.types.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ expectType<CodeceptJS.StepPromise>(playwright.dontSeeInField(str, str));
7474
expectType<CodeceptJS.ElementStepPromise>(playwright.attachFile(str, str));
7575
expectType<CodeceptJS.ElementStepPromise>(playwright.selectOption(str, str));
7676
expectType<Promise<number>>(playwright.grabNumberOfVisibleElements(str));
77+
expectType<Promise<CodeceptJS.WebElement[]>>(playwright.grabWebElements(str));
78+
expectType<Promise<CodeceptJS.WebElement>>(playwright.grabWebElement(str));
7779
expectType<CodeceptJS.StepPromise>(playwright.seeInCurrentUrl(str));
7880
expectType<CodeceptJS.StepPromise>(playwright.dontSeeInCurrentUrl(str));
7981
expectType<CodeceptJS.StepPromise>(playwright.seeCurrentUrlEquals(str));

0 commit comments

Comments
 (0)