diff --git a/integration-test/playwright/broker-protection.spec.js b/integration-test/playwright/broker-protection.spec.js index ceb185d3ee..8732a1b66d 100644 --- a/integration-test/playwright/broker-protection.spec.js +++ b/integration-test/playwright/broker-protection.spec.js @@ -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() @@ -504,7 +515,6 @@ test.describe('Broker Protection communications', () => { } } }) - await page.getByRole('heading', { name: 'Retry' }).waitFor({ timeout: 5000 }) const response = await dbp.waitForMessage('actionCompleted') diff --git a/integration-test/test-pages/broker-protection/actions/click-multiple.json b/integration-test/test-pages/broker-protection/actions/click-multiple.json new file mode 100644 index 0000000000..0564a1725a --- /dev/null +++ b/integration-test/test-pages/broker-protection/actions/click-multiple.json @@ -0,0 +1,15 @@ +{ + "state": { + "action": { + "actionType": "click", + "id": "1", + "elements": [ + { + "type": "button", + "selector": ".view-more", + "multiple": true + } + ] + } + } +} \ No newline at end of file diff --git a/integration-test/test-pages/broker-protection/pages/click-multiple.html b/integration-test/test-pages/broker-protection/pages/click-multiple.html new file mode 100644 index 0000000000..c3d6153204 --- /dev/null +++ b/integration-test/test-pages/broker-protection/pages/click-multiple.html @@ -0,0 +1,49 @@ + + + + + + Broker Protection + + +
+
John Doe
+
32
+
+ New York, NY + Los Angeles, CA + View More +
+
+
+
Jane Doe
+
32
+
+ Chicago, IL + San Francisco, CA + View More +
+
+ + + \ No newline at end of file diff --git a/src/features/broker-protection/actions/click.js b/src/features/broker-protection/actions/click.js index 30d8b69523..6c8b89ea93 100644 --- a/src/features/broker-protection/actions/click.js +++ b/src/features/broker-protection/actions/click.js @@ -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' @@ -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() } }