Skip to content

Commit b8418d2

Browse files
author
DavertMik
committed
improved context methods
1 parent e011581 commit b8418d2

File tree

5 files changed

+196
-72
lines changed

5 files changed

+196
-72
lines changed

lib/helper/Playwright.js

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,8 +1944,15 @@ class Playwright extends Helper {
19441944
* {{> seeElement }}
19451945
*
19461946
*/
1947-
async seeElement(locator) {
1948-
let els = await this._locate(locator)
1947+
async seeElement(locator, context = null) {
1948+
let els
1949+
if (context) {
1950+
const contextEls = await this._locate(context)
1951+
assertElementExists(contextEls, context, 'Context element')
1952+
els = await findElements.call(this, contextEls[0], locator)
1953+
} else {
1954+
els = await this._locate(locator)
1955+
}
19491956
els = await Promise.all(els.map(el => el.isVisible()))
19501957
try {
19511958
return empty('visible elements').negate(els.filter(v => v).fill('ELEMENT'))
@@ -1958,8 +1965,15 @@ class Playwright extends Helper {
19581965
* {{> dontSeeElement }}
19591966
*
19601967
*/
1961-
async dontSeeElement(locator) {
1962-
let els = await this._locate(locator)
1968+
async dontSeeElement(locator, context = null) {
1969+
let els
1970+
if (context) {
1971+
const contextEls = await this._locate(context)
1972+
assertElementExists(contextEls, context, 'Context element')
1973+
els = await findElements.call(this, contextEls[0], locator)
1974+
} else {
1975+
els = await this._locate(locator)
1976+
}
19631977
els = await Promise.all(els.map(el => el.isVisible()))
19641978
try {
19651979
return empty('visible elements').assert(els.filter(v => v).fill('ELEMENT'))
@@ -2245,8 +2259,8 @@ class Playwright extends Helper {
22452259
* {{> fillField }}
22462260
*
22472261
*/
2248-
async fillField(field, value) {
2249-
const els = await findFields.call(this, field)
2262+
async fillField(field, value, context = null) {
2263+
const els = await findFields.call(this, field, context)
22502264
assertElementExists(els, field, 'Field')
22512265
if (this.options.strict) assertOnlyOneElement(els, field)
22522266
const el = els[0]
@@ -2340,31 +2354,39 @@ class Playwright extends Helper {
23402354
/**
23412355
* {{> selectOption }}
23422356
*/
2343-
async selectOption(select, option) {
2344-
const context = await this.context
2357+
async selectOption(select, option, context = null) {
2358+
const pageContext = await this.context
23452359
const matchedLocator = new Locator(select)
23462360

2361+
let contextEl
2362+
if (context) {
2363+
const contextEls = await this._locate(context)
2364+
assertElementExists(contextEls, context, 'Context element')
2365+
contextEl = contextEls[0]
2366+
}
2367+
23472368
// Strict locator
23482369
if (!matchedLocator.isFuzzy()) {
23492370
this.debugSection('SelectOption', `Strict: ${JSON.stringify(select)}`)
2350-
const els = await this._locate(matchedLocator)
2371+
const els = contextEl ? await findElements.call(this, contextEl, matchedLocator) : await this._locate(matchedLocator)
23512372
assertElementExists(els, select, 'Selectable element')
2352-
return proceedSelect.call(this, context, els[0], option)
2373+
return proceedSelect.call(this, pageContext, els[0], option)
23532374
}
23542375

23552376
// Fuzzy: try combobox
23562377
this.debugSection('SelectOption', `Fuzzy: "${matchedLocator.value}"`)
2357-
let els = await findByRole(context, { role: 'combobox', name: matchedLocator.value })
2358-
if (els?.length) return proceedSelect.call(this, context, els[0], option)
2378+
const comboboxSearchCtx = contextEl || pageContext
2379+
let els = await findByRole(comboboxSearchCtx, { role: 'combobox', name: matchedLocator.value })
2380+
if (els?.length) return proceedSelect.call(this, pageContext, els[0], option)
23592381

23602382
// Fuzzy: try listbox
2361-
els = await findByRole(context, { role: 'listbox', name: matchedLocator.value })
2362-
if (els?.length) return proceedSelect.call(this, context, els[0], option)
2383+
els = await findByRole(comboboxSearchCtx, { role: 'listbox', name: matchedLocator.value })
2384+
if (els?.length) return proceedSelect.call(this, pageContext, els[0], option)
23632385

23642386
// Fuzzy: try native select
2365-
els = await findFields.call(this, select)
2387+
els = await findFields.call(this, select, context)
23662388
assertElementExists(els, select, 'Selectable element')
2367-
return proceedSelect.call(this, context, els[0], option)
2389+
return proceedSelect.call(this, pageContext, els[0], option)
23682390
}
23692391

23702392
/**
@@ -4355,34 +4377,45 @@ async function proceedIsChecked(assertType, option) {
43554377
return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
43564378
}
43574379

4358-
async function findFields(locator) {
4380+
async function findFields(locator, context = null) {
4381+
let contextEl
4382+
if (context) {
4383+
const contextEls = await this._locate(context)
4384+
assertElementExists(contextEls, context, 'Context element')
4385+
contextEl = contextEls[0]
4386+
}
4387+
4388+
const locateFn = contextEl
4389+
? loc => findElements.call(this, contextEl, loc)
4390+
: loc => this._locate(loc)
4391+
43594392
// Handle role locators with text/exact options
43604393
if (isRoleLocatorObject(locator)) {
4361-
const page = await this.page
4362-
const roleElements = await handleRoleLocator(page, locator)
4394+
const matcher = contextEl || (await this.page)
4395+
const roleElements = await handleRoleLocator(matcher, locator)
43634396
if (roleElements) return roleElements
43644397
}
43654398

43664399
const matchedLocator = new Locator(locator)
43674400
if (!matchedLocator.isFuzzy()) {
4368-
return this._locate(matchedLocator)
4401+
return locateFn(matchedLocator)
43694402
}
43704403
const literal = xpathLocator.literal(locator)
43714404

4372-
let els = await this._locate({ xpath: Locator.field.labelEquals(literal) })
4405+
let els = await locateFn({ xpath: Locator.field.labelEquals(literal) })
43734406
if (els.length) {
43744407
return els
43754408
}
43764409

4377-
els = await this._locate({ xpath: Locator.field.labelContains(literal) })
4410+
els = await locateFn({ xpath: Locator.field.labelContains(literal) })
43784411
if (els.length) {
43794412
return els
43804413
}
4381-
els = await this._locate({ xpath: Locator.field.byName(literal) })
4414+
els = await locateFn({ xpath: Locator.field.byName(literal) })
43824415
if (els.length) {
43834416
return els
43844417
}
4385-
return this._locate({ css: locator })
4418+
return locateFn({ css: locator })
43864419
}
43874420

43884421
async function proceedSelect(context, el, option) {

lib/helper/Puppeteer.js

Lines changed: 68 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,8 +1158,16 @@ class Puppeteer extends Helper {
11581158
* {{> seeElement }}
11591159
* {{ react }}
11601160
*/
1161-
async seeElement(locator) {
1162-
let els = await this._locate(locator)
1161+
async seeElement(locator, context = null) {
1162+
let els
1163+
if (context) {
1164+
const contextPage = await this.context
1165+
const contextEls = await findElements.call(this, contextPage, context)
1166+
assertElementExists(contextEls, context, 'Context element')
1167+
els = await findElements.call(this, contextEls[0], locator)
1168+
} else {
1169+
els = await this._locate(locator)
1170+
}
11631171
els = (await Promise.all(els.map(el => el.boundingBox() && el))).filter(v => v)
11641172
// Puppeteer visibility was ignored? | Remove when Puppeteer is fixed
11651173
els = await Promise.all(els.map(async el => (await el.evaluate(node => window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none')) && el))
@@ -1174,8 +1182,16 @@ class Puppeteer extends Helper {
11741182
* {{> dontSeeElement }}
11751183
* {{ react }}
11761184
*/
1177-
async dontSeeElement(locator) {
1178-
let els = await this._locate(locator)
1185+
async dontSeeElement(locator, context = null) {
1186+
let els
1187+
if (context) {
1188+
const contextPage = await this.context
1189+
const contextEls = await findElements.call(this, contextPage, context)
1190+
assertElementExists(contextEls, context, 'Context element')
1191+
els = await findElements.call(this, contextEls[0], locator)
1192+
} else {
1193+
els = await this._locate(locator)
1194+
}
11791195
els = (await Promise.all(els.map(el => el.boundingBox() && el))).filter(v => v)
11801196
// Puppeteer visibility was ignored? | Remove when Puppeteer is fixed
11811197
els = await Promise.all(els.map(async el => (await el.evaluate(node => window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none')) && el))
@@ -1541,8 +1557,8 @@ class Puppeteer extends Helper {
15411557
* {{> fillField }}
15421558
* {{ react }}
15431559
*/
1544-
async fillField(field, value) {
1545-
const els = await findVisibleFields.call(this, field)
1560+
async fillField(field, value, context = null) {
1561+
const els = await findVisibleFields.call(this, field, context)
15461562
assertElementExists(els, field, 'Field')
15471563
const el = els[0]
15481564
const tag = await el.getProperty('tagName').then(el => el.jsonValue())
@@ -1616,31 +1632,39 @@ class Puppeteer extends Helper {
16161632
/**
16171633
* {{> selectOption }}
16181634
*/
1619-
async selectOption(select, option) {
1620-
const context = await this._getContext()
1635+
async selectOption(select, option, context = null) {
1636+
const pageContext = await this._getContext()
16211637
const matchedLocator = new Locator(select)
16221638

1639+
let contextEl
1640+
if (context) {
1641+
const contextEls = await findElements.call(this, pageContext, context)
1642+
assertElementExists(contextEls, context, 'Context element')
1643+
contextEl = contextEls[0]
1644+
}
1645+
16231646
// Strict locator
16241647
if (!matchedLocator.isFuzzy()) {
16251648
this.debugSection('SelectOption', `Strict: ${JSON.stringify(select)}`)
1626-
const els = await this._locate(select)
1649+
const els = contextEl ? await findElements.call(this, contextEl, select) : await this._locate(select)
16271650
assertElementExists(els, select, 'Selectable element')
1628-
return proceedSelect.call(this, context, els[0], option)
1651+
return proceedSelect.call(this, pageContext, els[0], option)
16291652
}
16301653

16311654
// Fuzzy: try combobox
16321655
this.debugSection('SelectOption', `Fuzzy: "${matchedLocator.value}"`)
1633-
let els = await findByRole(context, { role: 'combobox', name: matchedLocator.value })
1634-
if (els?.length) return proceedSelect.call(this, context, els[0], option)
1656+
const comboboxSearchCtx = contextEl || pageContext
1657+
let els = await findByRole(comboboxSearchCtx, { role: 'combobox', name: matchedLocator.value })
1658+
if (els?.length) return proceedSelect.call(this, pageContext, els[0], option)
16351659

16361660
// Fuzzy: try listbox
1637-
els = await findByRole(context, { role: 'listbox', name: matchedLocator.value })
1638-
if (els?.length) return proceedSelect.call(this, context, els[0], option)
1661+
els = await findByRole(comboboxSearchCtx, { role: 'listbox', name: matchedLocator.value })
1662+
if (els?.length) return proceedSelect.call(this, pageContext, els[0], option)
16391663

16401664
// Fuzzy: try native select
1641-
const visibleEls = await findVisibleFields.call(this, select)
1665+
const visibleEls = await findVisibleFields.call(this, select, context)
16421666
assertElementExists(visibleEls, select, 'Selectable field')
1643-
return proceedSelect.call(this, context, visibleEls[0], option)
1667+
return proceedSelect.call(this, pageContext, visibleEls[0], option)
16441668
}
16451669

16461670
/**
@@ -3160,43 +3184,57 @@ async function proceedIsChecked(assertType, option) {
31603184
return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
31613185
}
31623186

3163-
async function findVisibleFields(locator) {
3164-
const els = await findFields.call(this, locator)
3187+
async function findVisibleFields(locator, context = null) {
3188+
const els = await findFields.call(this, locator, context)
31653189
const visible = await Promise.all(els.map(el => el.boundingBox()))
31663190
return els.filter((el, index) => visible[index])
31673191
}
31683192

3169-
async function findFields(locator) {
3193+
async function findFields(locator, context = null) {
3194+
let contextEl
3195+
if (context) {
3196+
const contextPage = await this.context
3197+
const contextEls = await findElements.call(this, contextPage, context)
3198+
assertElementExists(contextEls, context, 'Context element')
3199+
contextEl = contextEls[0]
3200+
}
3201+
3202+
const locateFn = contextEl
3203+
? loc => findElements.call(this, contextEl, loc)
3204+
: loc => this._locate(loc)
3205+
31703206
const matchedLocator = new Locator(locator)
31713207
if (!matchedLocator.isFuzzy()) {
3172-
return this._locate(matchedLocator)
3208+
return locateFn(matchedLocator)
31733209
}
31743210
const literal = xpathLocator.literal(matchedLocator.value)
31753211

3176-
let els = await this._locate({ xpath: Locator.field.labelEquals(literal) })
3212+
let els = await locateFn({ xpath: Locator.field.labelEquals(literal) })
31773213
if (els.length) {
31783214
return els
31793215
}
31803216

3181-
els = await this._locate({ xpath: Locator.field.labelContains(literal) })
3217+
els = await locateFn({ xpath: Locator.field.labelContains(literal) })
31823218
if (els.length) {
31833219
return els
31843220
}
3185-
els = await this._locate({ xpath: Locator.field.byName(literal) })
3221+
els = await locateFn({ xpath: Locator.field.byName(literal) })
31863222
if (els.length) {
31873223
return els
31883224
}
31893225

31903226
// Try ARIA selector for accessible name
3191-
try {
3192-
const page = await this.context
3193-
els = await page.$$(`::-p-aria(${matchedLocator.value})`)
3194-
if (els.length) return els
3195-
} catch (err) {
3196-
// ARIA selector not supported or failed
3227+
if (!contextEl) {
3228+
try {
3229+
const page = await this.context
3230+
els = await page.$$(`::-p-aria(${matchedLocator.value})`)
3231+
if (els.length) return els
3232+
} catch (err) {
3233+
// ARIA selector not supported or failed
3234+
}
31973235
}
31983236

3199-
return this._locate({ css: matchedLocator.value })
3237+
return locateFn({ css: matchedLocator.value })
32003238
}
32013239

32023240
async function proceedDragAndDrop(sourceLocator, destinationLocator) {

0 commit comments

Comments
 (0)