diff --git a/.eslintrc.json b/.eslintrc.json index f6f62b141..7ad2a1d04 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -36,6 +36,7 @@ "no-cond-assign": 0, "import/no-unresolved": 0, "no-await-in-loop": 0, - "arrow-body-style": 0 + "arrow-body-style": 0, + "no-loop-func": 0 } } diff --git a/docs/helpers/Nightmare.md b/docs/helpers/Nightmare.md index d3d92fb79..8ca5df552 100644 --- a/docs/helpers/Nightmare.md +++ b/docs/helpers/Nightmare.md @@ -374,6 +374,7 @@ I.fillField({css: 'form#login input[name=username]'}, 'John'); ### grabAttributeFrom Retrieves an attribute from an element located by CSS or XPath and returns it to test. +An array as a result will be returned if there are more than one matched element. Resumes test execution, so **should be used inside async with `await`** operator. ```js diff --git a/docs/helpers/Protractor.md b/docs/helpers/Protractor.md index 6bea49dc1..548fbf9f4 100644 --- a/docs/helpers/Protractor.md +++ b/docs/helpers/Protractor.md @@ -520,6 +520,7 @@ I.fillField({css: 'form#login input[name=username]'}, 'John'); ### grabAttributeFrom Retrieves an attribute from an element located by CSS or XPath and returns it to test. +An array as a result will be returned if there are more than one matched element. Resumes test execution, so **should be used inside async with `await`** operator. ```js diff --git a/docs/helpers/Puppeteer.md b/docs/helpers/Puppeteer.md index 969123a4a..f5421f52e 100644 --- a/docs/helpers/Puppeteer.md +++ b/docs/helpers/Puppeteer.md @@ -581,6 +581,7 @@ I.fillField({css: 'form#login input[name=username]'}, 'John'); ### grabAttributeFrom Retrieves an attribute from an element located by CSS or XPath and returns it to test. +An array as a result will be returned if there are more than one matched element. Resumes test execution, so **should be used inside async with `await`** operator. ```js diff --git a/docs/helpers/WebDriver.md b/docs/helpers/WebDriver.md index 27783701a..c140f8cbd 100644 --- a/docs/helpers/WebDriver.md +++ b/docs/helpers/WebDriver.md @@ -623,6 +623,7 @@ I.fillField({css: 'form#login input[name=username]'}, 'John'); ### grabAttributeFrom Retrieves an attribute from an element located by CSS or XPath and returns it to test. +An array as a result will be returned if there are more than one matched element. Resumes test execution, so **should be used inside async with `await`** operator. ```js diff --git a/docs/helpers/WebDriverIO.md b/docs/helpers/WebDriverIO.md index 11dbeb571..812faf77b 100644 --- a/docs/helpers/WebDriverIO.md +++ b/docs/helpers/WebDriverIO.md @@ -631,6 +631,7 @@ I.fillField({css: 'form#login input[name=username]'}, 'John'); ### grabAttributeFrom Retrieves an attribute from an element located by CSS or XPath and returns it to test. +An array as a result will be returned if there are more than one matched element. Resumes test execution, so **should be used inside async with `await`** operator. ```js diff --git a/docs/webapi/grabAttributeFrom.mustache b/docs/webapi/grabAttributeFrom.mustache index c6c2f437b..5720c8b9f 100644 --- a/docs/webapi/grabAttributeFrom.mustache +++ b/docs/webapi/grabAttributeFrom.mustache @@ -1,4 +1,5 @@ Retrieves an attribute from an element located by CSS or XPath and returns it to test. +An array as a result will be returned if there are more than one matched element. Resumes test execution, so **should be used inside async with `await`** operator. ```js diff --git a/lib/helper/Nightmare.js b/lib/helper/Nightmare.js index 886bdddcb..f95be1aa7 100644 --- a/lib/helper/Nightmare.js +++ b/lib/helper/Nightmare.js @@ -792,9 +792,16 @@ class Nightmare extends Helper { */ async grabAttributeFrom(locator, attr) { locator = new Locator(locator, 'css'); - const el = await this.browser.findElement(locator.toStrict()); - assertElementExists(el, locator); - return this.browser.evaluate((el, attr) => window.codeceptjs.fetchElement(el).getAttribute(attr), el, attr); + const els = await this.browser.findElements(locator.toStrict()); + const array = []; + + for (let index = 0; index < els.length; index++) { + const el = els[index]; + assertElementExists(el, locator); + array.push(await this.browser.evaluate((el, attr) => window.codeceptjs.fetchElement(el).getAttribute(attr), el, attr)); + } + + return array.length === 1 ? array[0] : array; } diff --git a/lib/helper/Protractor.js b/lib/helper/Protractor.js index 362a25e19..3fa9749f0 100644 --- a/lib/helper/Protractor.js +++ b/lib/helper/Protractor.js @@ -728,9 +728,14 @@ class Protractor extends Helper { async grabAttributeFrom(locator, attr) { const els = await this._locate(locator); assertElementExists(els); - return els[0].getAttribute(attr); - } + const array = []; + for (let index = 0; index < els.length; index++) { + const el = els[index]; + array.push(await el.getAttribute(attr)); + } + return array.length === 1 ? array[0] : array; + } /** * {{> ../webapi/seeInTitle }} */ diff --git a/lib/helper/Puppeteer.js b/lib/helper/Puppeteer.js index 4559a74aa..98451ab83 100644 --- a/lib/helper/Puppeteer.js +++ b/lib/helper/Puppeteer.js @@ -1363,8 +1363,14 @@ class Puppeteer extends Helper { async grabAttributeFrom(locator, attr) { const els = await this._locate(locator); assertElementExists(els, locator); - return this._evaluateHandeInContext((el, attr) => el[attr] || el.getAttribute(attr), els[0], attr) - .then(t => t.jsonValue()); + const array = []; + + for (let index = 0; index < els.length; index++) { + const a = await this._evaluateHandeInContext((el, attr) => el[attr] || el.getAttribute(attr), els[index], attr); + array.push(await a.jsonValue()); + } + + return array.length === 1 ? array[0] : array; } /**