Skip to content

Commit

Permalink
Support clicking multiple items (#970)
Browse files Browse the repository at this point in the history
* First pass on multiple clicks

* Stub out tests

* Fix minor bug

* Ensure we're testing truthiness for the multiple key

* remove .only

---------

Co-authored-by: Shane Osbourne <[email protected]>
Co-authored-by: Shane Osbourne <[email protected]>
  • Loading branch information
3 people authored Jun 4, 2024
1 parent f8e95c3 commit a327af5
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 10 deletions.
12 changes: 11 additions & 1 deletion integration-test/playwright/broker-protection.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,17 @@ test.describe('Broker Protection communications', () => {
await page.waitForURL(url => url.hash === '#2', { timeout: 2000 })
})

test('click multiple targets', async ({ page }, workerInfo) => {
const dbp = BrokerProtectionPage.create(page, workerInfo)
await dbp.enabled()
await dbp.navigatesTo('click-multiple.html')
await dbp.receivesAction('click-multiple.json')
const response = await dbp.waitForMessage('actionCompleted')

dbp.isSuccessMessage(response)
await page.waitForURL(url => url.hash === '#1-2', { timeout: 2000 })
})

test('getCaptchaInfo', async ({ page }, workerInfo) => {
const dbp = BrokerProtectionPage.create(page, workerInfo)
await dbp.enabled()
Expand Down Expand Up @@ -504,7 +515,6 @@ test.describe('Broker Protection communications', () => {
}
}
})

await page.getByRole('heading', { name: 'Retry' }).waitFor({ timeout: 5000 })

const response = await dbp.waitForMessage('actionCompleted')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"state": {
"action": {
"actionType": "click",
"id": "1",
"elements": [
{
"type": "button",
"selector": ".view-more",
"multiple": true
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Broker Protection</title>
</head>
<body>
<div class="result">
<div class="name">John Doe</div>
<div class="age">32</div>
<div class="locations" data-id="1">
<span>New York, NY</span>
<span>Los Angeles, CA</span>
<a href="#" class="view-more">View More</a>
</div>
</div>
<div class="result">
<div class="name">Jane Doe</div>
<div class="age">32</div>
<div class="locations" data-id="2">
<span>Chicago, IL</span>
<span>San Francisco, CA</span>
<a href="#" class="view-more">View More</a>
</div>
</div>
<script>
const locations = {
1: ['Dallas, TX', 'Miami, FL'],
2: ['Houston, TX', 'San Jose, CA']
};

document.querySelectorAll('.view-more').forEach(viewMore =>
viewMore.addEventListener('click', function(e) {
e.preventDefault();
const id = this.parentNode.getAttribute('data-id');

locations[id].forEach(location => {
const newLocation = document.createElement('span');
newLocation.textContent = location;
this.parentNode.insertBefore(newLocation, this);
});
window.location.hash ? window.location.hash += '-' + id : window.location.hash = id;
this.removeEventListener('click', arguments.callee);
})
);
</script>
</body>
</html>
25 changes: 16 additions & 9 deletions src/features/broker-protection/actions/click.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getElement } from '../utils.js'
import { getElements } from '../utils.js'
import { ErrorResponse, SuccessResponse } from '../types.js'
import { extractProfiles } from './extract.js'

Expand All @@ -12,18 +12,25 @@ export function click (action, userData, root = document) {
// there can be multiple elements provided by the action
for (const element of action.elements) {
const rootElement = selectRootElement(element, userData, root)
const elem = getElement(rootElement, element.selector)
const elements = getElements(rootElement, element.selector)

if (!elem) {
if (!elements?.length) {
return new ErrorResponse({ actionID: action.id, message: `could not find element to click with selector '${element.selector}'!` })
}
if ('disabled' in elem) {
if (elem.disabled) {
return new ErrorResponse({ actionID: action.id, message: `could not click disabled element ${element.selector}'!` })

const loopLength = element.multiple && element.multiple === true ? elements.length : 1

for (let i = 0; i < loopLength; i++) {
const elem = elements[i]

if ('disabled' in elem) {
if (elem.disabled) {
return new ErrorResponse({ actionID: action.id, message: `could not click disabled element ${element.selector}'!` })
}
}
if ('click' in elem && typeof elem.click === 'function') {
elem.click()
}
}
if ('click' in elem && typeof elem.click === 'function') {
elem.click()
}
}

Expand Down

0 comments on commit a327af5

Please sign in to comment.