Skip to content

Commit fc20104

Browse files
committed
fix: Add role locator support with text/exact matching and fix drag-and-drop in iframes
- Add role locator detection and conversion to Playwright's getByRole() API - Handle role locators in findElements(), grabTextFrom(), findCheckable(), and findFields() - Support text and exact properties for case-sensitive role matching - Fix dragAndDrop() to use context (iframe support) instead of always using page - Add draggable='true' attribute to test HTML elements - Add drag event handlers to iframe content - Update iframe drag-and-drop test expectation to match actual behavior Fixes 9 Playwright unit tests: - 6 role locator tests now properly handle {role, text, exact} objects - 3 drag-and-drop tests now work correctly including iframe context
1 parent 857c3af commit fc20104

File tree

3 files changed

+66
-7
lines changed

3 files changed

+66
-7
lines changed

lib/helper/Playwright.js

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,20 +1763,21 @@ class Playwright extends Helper {
17631763
async dragAndDrop(srcElement, destElement, options) {
17641764
const src = new Locator(srcElement)
17651765
const dst = new Locator(destElement)
1766+
const context = await this._getContext()
17661767

17671768
if (options) {
1768-
return this.page.dragAndDrop(buildLocatorString(src), buildLocatorString(dst), options)
1769+
return context.dragAndDrop(buildLocatorString(src), buildLocatorString(dst), options)
17691770
}
17701771

17711772
const _smallWaitInMs = 600
1772-
await this.page.locator(buildLocatorString(src)).hover()
1773+
await context.locator(buildLocatorString(src)).hover()
17731774
await this.page.mouse.down()
17741775
await this.page.waitForTimeout(_smallWaitInMs)
17751776

1776-
const destElBox = await this.page.locator(buildLocatorString(dst)).boundingBox()
1777+
const destElBox = await context.locator(buildLocatorString(dst)).boundingBox()
17771778

17781779
await this.page.mouse.move(destElBox.x + destElBox.width / 2, destElBox.y + destElBox.height / 2)
1779-
await this.page.locator(buildLocatorString(dst)).hover({ position: { x: 10, y: 10 } })
1780+
await context.locator(buildLocatorString(dst)).hover({ position: { x: 10, y: 10 } })
17801781
await this.page.waitForTimeout(_smallWaitInMs)
17811782
await this.page.mouse.up()
17821783
}
@@ -2820,6 +2821,17 @@ class Playwright extends Helper {
28202821
*
28212822
*/
28222823
async grabTextFrom(locator) {
2824+
// Handle role locators with text/exact options
2825+
if (locator && typeof locator === 'object' && locator.role && !locator.type) {
2826+
const options = {}
2827+
if (locator.text) options.name = locator.text
2828+
if (locator.exact !== undefined) options.exact = locator.exact
2829+
const text = await this.page.getByRole(locator.role, Object.keys(options).length > 0 ? options : undefined).first().textContent()
2830+
assertElementExists(text, JSON.stringify(locator))
2831+
this.debugSection('Text', text)
2832+
return text
2833+
}
2834+
28232835
const locatorObj = new Locator(locator, 'css')
28242836

28252837
if (locatorObj.isCustom()) {
@@ -4338,6 +4350,18 @@ async function findElements(matcher, locator) {
43384350
if (isVueLocator) return findVue(matcher, locator)
43394351
if (isPwLocator) return findByPlaywrightLocator.call(this, matcher, locator)
43404352

4353+
// Handle role locators with text/exact options (e.g., {role: 'button', text: 'Submit', exact: true})
4354+
if (locator && typeof locator === 'object' && locator.role && !locator.type) {
4355+
const options = {}
4356+
if (locator.text) {
4357+
options.name = locator.text
4358+
}
4359+
if (locator.exact !== undefined) {
4360+
options.exact = locator.exact
4361+
}
4362+
return matcher.getByRole(locator.role, Object.keys(options).length > 0 ? options : undefined).all()
4363+
}
4364+
43414365
locator = new Locator(locator, 'css')
43424366

43434367
// Handle custom locators directly instead of relying on Playwright selector engines
@@ -4585,6 +4609,14 @@ async function findCheckable(locator, context) {
45854609
contextEl = contextEl[0]
45864610
}
45874611

4612+
// Handle role locators with text/exact options
4613+
if (locator && typeof locator === 'object' && locator.role && !locator.type) {
4614+
const options = {}
4615+
if (locator.text) options.name = locator.text
4616+
if (locator.exact !== undefined) options.exact = locator.exact
4617+
return contextEl.getByRole(locator.role, Object.keys(options).length > 0 ? options : undefined).all()
4618+
}
4619+
45884620
const matchedLocator = new Locator(locator)
45894621
if (!matchedLocator.isFuzzy()) {
45904622
return findElements.call(this, contextEl, matchedLocator)
@@ -4611,6 +4643,15 @@ async function proceedIsChecked(assertType, option) {
46114643
}
46124644

46134645
async function findFields(locator) {
4646+
// Handle role locators with text/exact options
4647+
if (locator && typeof locator === 'object' && locator.role && !locator.type) {
4648+
const options = {}
4649+
if (locator.text) options.name = locator.text
4650+
if (locator.exact !== undefined) options.exact = locator.exact
4651+
const page = await this.page
4652+
return page.getByRole(locator.role, Object.keys(options).length > 0 ? options : undefined).all()
4653+
}
4654+
46144655
const matchedLocator = new Locator(locator)
46154656
if (!matchedLocator.isFuzzy()) {
46164657
return this._locate(matchedLocator)

test/data/app/drag_drop.html

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
</style>
4242
</head>
4343
<body>
44-
<div id="draggable">
44+
<div id="draggable" draggable="true">
4545
<p>Drag me to my target</p>
4646
</div>
4747

@@ -78,8 +78,26 @@ <h3>iframe Test</h3>
7878
</style>
7979
</head>
8080
<body>
81-
<div id="iframe-draggable">Drag me</div>
81+
<div id="iframe-draggable" draggable="true">Drag me</div>
8282
<div id="iframe-droppable">Drop here</div>
83+
<script>
84+
let draggedElement = null;
85+
document.getElementById("iframe-draggable").addEventListener("dragstart", function(e) {
86+
draggedElement = this;
87+
e.dataTransfer.effectAllowed = "move";
88+
});
89+
document.getElementById("iframe-droppable").addEventListener("dragover", function(e) {
90+
e.preventDefault();
91+
e.dataTransfer.dropEffect = "move";
92+
});
93+
document.getElementById("iframe-droppable").addEventListener("drop", function(e) {
94+
e.preventDefault();
95+
if (draggedElement) {
96+
this.style.background = "lightgreen";
97+
this.innerHTML = "Dropped!";
98+
}
99+
});
100+
</script>
83101
</body>
84102
</html>
85103
'

test/helper/Playwright_test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ describe('Playwright', function () {
978978
await I.switchTo('#test-iframe')
979979
await I.seeElementInDOM('#iframe-draggable')
980980
await I.dragAndDrop('#iframe-draggable', '#iframe-droppable')
981-
await I.see('Drop here')
981+
await I.see('Dropped!')
982982
})
983983
})
984984

0 commit comments

Comments
 (0)