Refactor the click helper to use Puppeteer's methods
The click helper now only accepts selectors so that it is
able to recover from unstable DOM situations. A new deprecated
helper clickElement is introduced for tests that cannot use a
selector currently. This should serve as a red flag that the
test might suffer from flakiness.
Bounding box and offset computation is removed for now. New
Puppeteer version allows providing relative click coordinates
so we need to use that.
Bug: 1411188, 1409768, 1411196, 1410437
Change-Id: I94a272184530842476bb2a879d862c4bd0930dba
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/4194329
Reviewed-by: Philip Pfaffe <[email protected]>
Commit-Queue: Alex Rudenko <[email protected]>
diff --git a/test/e2e/application/reporting-api_test.ts b/test/e2e/application/reporting-api_test.ts
index 00a687d..3207e0d 100644
--- a/test/e2e/application/reporting-api_test.ts
+++ b/test/e2e/application/reporting-api_test.ts
@@ -7,6 +7,7 @@
import {
$,
click,
+ clickElement,
getBrowserAndPages,
getTestServerPort,
goToResource,
@@ -38,7 +39,7 @@
assert.strictEqual(innerText[0][5], reportBody);
const rows = await getDataGridRows(1, dataGrid, false);
- await click(rows[rows.length - 1][0]);
+ await clickElement(rows[rows.length - 1][0]);
const jsonView = await waitFor('.json-view');
const jsonViewText = await jsonView.evaluate(el => (el as HTMLElement).innerText);
diff --git a/test/e2e/application/shared-storage_test.ts b/test/e2e/application/shared-storage_test.ts
index 56e8aa2..9c87b00 100644
--- a/test/e2e/application/shared-storage_test.ts
+++ b/test/e2e/application/shared-storage_test.ts
@@ -7,7 +7,7 @@
import {expectError} from '../../conductor/events.js';
import {
$$,
- click,
+ clickElement,
getBrowserAndPages,
getTestServerPort,
goToResource,
@@ -77,7 +77,7 @@
innerText[2][3], '{"key":"secondKey","value":"{\\"field\\":\\"complexValue\\",\\"primitive\\":2}"}');
const rows = await getDataGridRows(3, dataGrid, false);
- await click(rows[rows.length - 1][0]);
+ await clickElement(rows[rows.length - 1][0]);
const jsonView = await waitFor('.json-view');
const jsonViewText = await jsonView.evaluate(el => (el as HTMLElement).innerText);
@@ -134,7 +134,7 @@
await step('verify that preview loads', async () => {
const dataGridNodes = await $$('.data-grid-data-grid-node:not(.creation-node)');
- await click(dataGridNodes[dataGridNodes.length - 1]);
+ await clickElement(dataGridNodes[dataGridNodes.length - 1]);
const jsonView = await waitFor('.json-view');
const jsonViewText = await jsonView.evaluate(el => (el as HTMLElement).innerText);
diff --git a/test/e2e/console/console-context-selector_test.ts b/test/e2e/console/console-context-selector_test.ts
index 63e8de2..510c40c 100644
--- a/test/e2e/console/console-context-selector_test.ts
+++ b/test/e2e/console/console-context-selector_test.ts
@@ -8,6 +8,7 @@
$textContent,
assertNotNullOrUndefined,
click,
+ clickElement,
getBrowserAndPages,
goToResource,
hasClass,
@@ -47,7 +48,7 @@
await step('switch to the iframe context', async () => {
await contextSelectorButton.press('Enter');
const frameMenuItem = await waitForMenuItemWithText(FRAME_CONTEXT_LABEL);
- await click(frameMenuItem);
+ await clickElement(frameMenuItem);
await pressKey('Enter');
contextSelectorButton = await waitFor(`[aria-label="JavaScript context: ${FRAME_CONTEXT_LABEL}"]`);
});
diff --git a/test/e2e/cross_tool_integration/workflow_test.ts b/test/e2e/cross_tool_integration/workflow_test.ts
index 20b934b..3f7bcde 100644
--- a/test/e2e/cross_tool_integration/workflow_test.ts
+++ b/test/e2e/cross_tool_integration/workflow_test.ts
@@ -5,6 +5,7 @@
import {
assertNotNullOrUndefined,
click,
+ clickElement,
reloadDevTools,
waitFor,
waitForFunction,
@@ -88,7 +89,7 @@
});
assertNotNullOrUndefined(link);
- await click(link);
+ await clickElement(link);
await waitFor('.panel[aria-label="sources"]');
});
});
diff --git a/test/e2e/elements/accessibility-pane_test.ts b/test/e2e/elements/accessibility-pane_test.ts
index c3f6625..cd0f8b6 100644
--- a/test/e2e/elements/accessibility-pane_test.ts
+++ b/test/e2e/elements/accessibility-pane_test.ts
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import {click, goToResource, waitForAria, waitForElementWithTextContent} from '../../shared/helper.js';
+import {clickElement, goToResource, waitForAria, waitForElementWithTextContent} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
import {toggleAccessibilityPane} from '../helpers/elements-helpers.js';
@@ -17,7 +17,7 @@
await goToResource('elements/accessibility-simple-page.html');
await toggleAccessibilityPane();
const titleElement = await waitForAria('<h1>');
- await click(titleElement);
+ await clickElement(titleElement);
await waitForAria('Contents:\xa0"Title"');
});
@@ -26,7 +26,7 @@
await toggleAccessibilityPane();
const a11yPane = await waitForAria('Accessibility panel');
const spanElement = await waitForElementWithTextContent('span-name');
- await click(spanElement);
+ await clickElement(spanElement);
await waitForAria('Name:\xa0"span-name"', a11yPane);
});
});
diff --git a/test/e2e/elements/color-picker_test.ts b/test/e2e/elements/color-picker_test.ts
index 8253733..f8dea2a 100644
--- a/test/e2e/elements/color-picker_test.ts
+++ b/test/e2e/elements/color-picker_test.ts
@@ -7,6 +7,7 @@
$textContent,
assertNotNullOrUndefined,
click,
+ clickElement,
prepareWaitForEvent,
waitFor,
waitForEvent,
@@ -20,7 +21,7 @@
await goToResourceAndWaitForStyleSection('elements/css-variables-many.html');
const swatch = await waitForFunction(() => getColorSwatch(/* parent*/ undefined, 0));
- await click(swatch);
+ await clickElement(swatch);
const panel = await waitFor('.palette-panel');
await click('.spectrum-palette-switcher');
@@ -33,7 +34,7 @@
assertNotNullOrUndefined(overlay);
await prepareWaitForEvent(overlay, 'transitionend');
- await click(palette);
+ await clickElement(palette);
await waitForEvent(overlay, 'transitionend');
await click('.spectrum-palette-switcher');
diff --git a/test/e2e/elements/computed-pane-properties_test.ts b/test/e2e/elements/computed-pane-properties_test.ts
index 818329b..1e3b057 100644
--- a/test/e2e/elements/computed-pane-properties_test.ts
+++ b/test/e2e/elements/computed-pane-properties_test.ts
@@ -96,8 +96,9 @@
await frontend.keyboard.press('ArrowDown');
const colorProperty = await waitFor(
'CSS property name: color : CSS property value: rgb(255, 0, 102) ;', undefined, undefined, 'aria');
- const arrowIcon = await waitFor('.arrow-icon', colorProperty);
- await click(arrowIcon);
+ await click('.arrow-icon', {
+ root: colorProperty,
+ });
const isExpandedBefore = await colorProperty.evaluate(element => element.ariaExpanded);
assert(isExpandedBefore);
await focusElementsTree();
diff --git a/test/e2e/elements/element-breadcrumbs_test.ts b/test/e2e/elements/element-breadcrumbs_test.ts
index 73e498f..3586311 100644
--- a/test/e2e/elements/element-breadcrumbs_test.ts
+++ b/test/e2e/elements/element-breadcrumbs_test.ts
@@ -4,7 +4,7 @@
import {assert} from 'chai';
-import {click, goToResource, waitForElementWithTextContent} from '../../shared/helper.js';
+import {clickElement, goToResource, waitForElementWithTextContent} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
import {
assertSelectedElementsNodeTextIncludes,
@@ -29,7 +29,7 @@
// expand the tree and then navigate down to the target node
await expandSelectedNodeRecursively();
const targetChildNode = await waitForElementWithTextContent(EXPECTED_TEXT_CONTENT);
- await click(targetChildNode);
+ await clickElement(targetChildNode);
// double check we got to the node we expect
await waitForSelectedTreeElementSelectorWithTextcontent(EXPECTED_TEXT_CONTENT);
diff --git a/test/e2e/elements/reveal-correct-node_test.ts b/test/e2e/elements/reveal-correct-node_test.ts
index 0cebf90..f269e26 100644
--- a/test/e2e/elements/reveal-correct-node_test.ts
+++ b/test/e2e/elements/reveal-correct-node_test.ts
@@ -48,8 +48,7 @@
it('has link from a slot to assigned elements', async () => {
await goToResource('elements/slot-element.html');
await expandSelectedNodeRecursively();
- const revealElementLink = await waitFor('[aria-label="reveal"]', undefined, undefined);
- await click(revealElementLink);
+ await click('[aria-label="reveal"]');
await waitForPartialContentOfSelectedElementsNode('<h1>headline</h1>');
});
@@ -60,8 +59,7 @@
await waitForAdorners(([
{textContent: 'slot', isActive: false},
]));
- const revealSlotLink = await waitFor('[aria-label="slot"]', undefined, undefined);
- await click(revealSlotLink);
+ await click('[aria-label="slot"]');
await waitForPartialContentOfSelectedElementsNode('<slot>');
});
});
diff --git a/test/e2e/elements/selection-after-delete_test.ts b/test/e2e/elements/selection-after-delete_test.ts
index 0570bae..a4bde57 100644
--- a/test/e2e/elements/selection-after-delete_test.ts
+++ b/test/e2e/elements/selection-after-delete_test.ts
@@ -2,7 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import {click, getBrowserAndPages, goToResource, waitForElementWithTextContent} from '../../shared/helper.js';
+import {
+ clickElement,
+ getBrowserAndPages,
+ goToResource,
+ waitForElementWithTextContent,
+} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
import {
expandSelectedNodeRecursively,
@@ -27,7 +32,7 @@
// Wait for the expansion and select the final child in the tree.
const child = await waitForElementWithTextContent('child2');
- await click(child);
+ await clickElement(child);
const expected = [
'<div class=\u200B"child3">\u200B</div>\u200B',
diff --git a/test/e2e/elements/style-pane-properties_test.ts b/test/e2e/elements/style-pane-properties_test.ts
index 2c865a3..87627a8 100644
--- a/test/e2e/elements/style-pane-properties_test.ts
+++ b/test/e2e/elements/style-pane-properties_test.ts
@@ -11,6 +11,7 @@
click,
getBrowserAndPages,
waitFor,
+ clickElement,
waitForFunction,
} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
@@ -96,7 +97,7 @@
await waitForContentOfSelectedElementsNode('<div id=\u200B"properties-to-inspect">\u200B</div>\u200B');
const testElementRule = await getStyleRule(PROPERTIES_TO_INSPECT_SELECTOR);
- await click(FIRST_PROPERTY_VALUE_SELECTOR, {root: testElementRule});
+ await click('.link-swatch-link', {root: testElementRule});
await waitForPropertyToHighlight('html', '--title-color');
});
@@ -109,7 +110,7 @@
await waitForContentOfSelectedElementsNode('<div id=\u200B"properties-to-inspect">\u200B</div>\u200B');
const testElementRule = await getStyleRule(PROPERTIES_TO_INSPECT_SELECTOR);
- await click(FIRST_PROPERTY_VALUE_SELECTOR, {root: testElementRule});
+ await click('.link-swatch-link', {root: testElementRule});
await waitForPropertyToHighlight('html', '--color56');
});
@@ -126,7 +127,7 @@
const propertyValue = await waitFor(FIRST_PROPERTY_VALUE_SELECTOR, propertiesSection);
// Specifying 10px from the left of the value to click on the word var rather than in the middle which would jump to
// the property definition.
- await click(propertyValue, {maxPixelsFromLeft: 10});
+ await propertyValue.click();
const editedValueText = await propertyValue.evaluate(node => node.textContent);
assert.strictEqual(editedValueText, 'var(--title-color)', 'The value is incorrect when being edited');
});
@@ -417,8 +418,7 @@
await waitForAndClickTreeElementWithPartialText('<div class=\u200B"rule1">\u200B</div>\u200B');
await waitForContentOfSelectedElementsNode('<div class=\u200B"rule1">\u200B</div>\u200B');
- const overruleButton = await waitFor('overrule[role="button"]', undefined, undefined, 'aria');
- await click(overruleButton);
+ await click('aria/overrule[role="button"]');
const treeElement = await waitFor('[data-node-key="2: overrule"]');
assertNotNullOrUndefined(treeElement);
@@ -987,7 +987,7 @@
await target.evaluate('loadIframe()');
await expandSelectedNodeRecursively();
const iframeBody = await waitFor('onload', undefined, undefined, 'pierceShadowText');
- await click(iframeBody);
+ await clickElement(iframeBody);
await waitForStyleRule('#iframeBody');
const inspectedRulesAfter = await getDisplayedStyleRulesCompact();
const expectedInspectedRulesAfter = [
diff --git a/test/e2e/emulation/custom-devices_test.ts b/test/e2e/emulation/custom-devices_test.ts
index c480b58..e0272ef 100644
--- a/test/e2e/emulation/custom-devices_test.ts
+++ b/test/e2e/emulation/custom-devices_test.ts
@@ -12,6 +12,7 @@
typeText,
waitFor,
waitForAria,
+ clickElement,
} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
import {waitForDomNodeToBeVisible} from '../helpers/elements-helpers.js';
@@ -52,8 +53,7 @@
it('can add and then edit a custom device with UA-CH emulation', async () => {
await selectEdit();
- const add = await waitFor(ADD_DEVICE_BUTTON_SELECTOR);
- await click(add);
+ await click(ADD_DEVICE_BUTTON_SELECTOR);
await waitFor(FOCUSED_DEVICE_NAME_FIELD_SELECTOR);
await typeText('Test device');
@@ -115,7 +115,7 @@
const finishAdd = await waitFor(FOCUSED_SELECTOR);
const finishAddText = await elementTextContent(finishAdd);
assert.strictEqual(finishAddText, 'Add');
- await click(finishAdd);
+ await clickElement(finishAdd);
// Select the device in the menu.
await selectTestDevice();
@@ -183,8 +183,7 @@
it('can add and properly display a device with a custom resolution', async () => {
await selectEdit();
- const add = await waitFor(ADD_DEVICE_BUTTON_SELECTOR);
- await click(add);
+ await click(ADD_DEVICE_BUTTON_SELECTOR);
await waitFor(FOCUSED_DEVICE_NAME_FIELD_SELECTOR);
await typeText('Prime numbers');
@@ -200,7 +199,7 @@
const finishAdd = await waitFor(EDITOR_ADD_BUTTON_SELECTOR);
const finishAddText = await elementTextContent(finishAdd);
assert.strictEqual(finishAddText, 'Add');
- await click(finishAdd);
+ await clickElement(finishAdd);
// Select the device in the menu.
await selectDevice('Prime numbers');
@@ -216,7 +215,7 @@
assert.strictEqual(await elementTextContent(zoomButton), '51%');
const zoomTo100Button = await waitFor('[aria-label*="100%"]');
- await click(zoomTo100Button);
+ await clickElement(zoomTo100Button);
assert.strictEqual(await elementTextContent(fitButton), 'Fit to window (51%)');
assert.strictEqual(await elementTextContent(zoomButton), '100%');
});
diff --git a/test/e2e/extensions/debugger-language-plugins_test.ts b/test/e2e/extensions/debugger-language-plugins_test.ts
index 338e11b..dd05b8b 100644
--- a/test/e2e/extensions/debugger-language-plugins_test.ts
+++ b/test/e2e/extensions/debugger-language-plugins_test.ts
@@ -18,7 +18,6 @@
pressKey,
typeText,
waitFor,
- waitForAria,
waitForFunction,
waitForMany,
waitForNone,
@@ -1256,10 +1255,8 @@
const capturedFileNames = await captureAddedSourceFiles(1, async () => {
await openFileInEditor('global_variable.wasm');
- const editor = await waitForAria('Code editor');
- await click(editor, {clickOptions: {button: 'right'}});
- const menuItem = await waitForAria('Add DWARF debug info…');
- await click(menuItem);
+ await click('aria/Code editor', {clickOptions: {button: 'right'}});
+ await click('aria/Add DWARF debug info…');
await waitFor('.add-source-map');
await typeText('foobar81');
await pressKey('Enter');
diff --git a/test/e2e/helpers/console-helpers.ts b/test/e2e/helpers/console-helpers.ts
index 2ad8bd9..9a5b583 100644
--- a/test/e2e/helpers/console-helpers.ts
+++ b/test/e2e/helpers/console-helpers.ts
@@ -333,8 +333,7 @@
}
export async function clickOnContextMenu(selectorForNode: string, ctxMenuItemName: string) {
- const node = await waitFor(selectorForNode);
- await click(node, {clickOptions: {button: 'right'}});
+ await click(selectorForNode, {clickOptions: {button: 'right'}});
const copyButton = await waitForAria(ctxMenuItemName);
await copyButton.click();
}
diff --git a/test/e2e/helpers/cross-tool-helper.ts b/test/e2e/helpers/cross-tool-helper.ts
index f15ad4c..f46d115 100644
--- a/test/e2e/helpers/cross-tool-helper.ts
+++ b/test/e2e/helpers/cross-tool-helper.ts
@@ -15,8 +15,7 @@
export async function clickOnContextMenuItemFromTab(tabId: string, menuItemSelector: string) {
// Find the selected node, right click.
- const selectedNode = await waitFor(tabId);
- await click(selectedNode, {clickOptions: {button: 'right'}});
+ await click(tabId, {clickOptions: {button: 'right'}});
// Click on the context menu option
await click(menuItemSelector);
diff --git a/test/e2e/helpers/elements-helpers.ts b/test/e2e/helpers/elements-helpers.ts
index d738bee..6aac5db 100644
--- a/test/e2e/helpers/elements-helpers.ts
+++ b/test/e2e/helpers/elements-helpers.ts
@@ -19,6 +19,7 @@
typeText,
waitFor,
waitForAria,
+ clickElement,
waitForFunction,
} from '../../shared/helper.js';
@@ -212,7 +213,7 @@
export const clickTreeElementWithPartialText = async (text: string) => {
const handle = await elementWithPartialText(text);
if (handle) {
- await click(handle);
+ await clickElement(handle);
return true;
}
@@ -305,8 +306,7 @@
const EXPAND_RECURSIVELY = '[aria-label="Expand recursively"]';
// Find the selected node, right click.
- const selectedNode = await waitFor(SELECTED_TREE_ELEMENT_SELECTOR);
- await click(selectedNode, {clickOptions: {button: 'right'}});
+ await click(SELECTED_TREE_ELEMENT_SELECTOR, {clickOptions: {button: 'right'}});
// Wait for the 'expand recursively' option, and click it.
await waitFor(EXPAND_RECURSIVELY);
@@ -352,8 +352,9 @@
const initialContent = await getContentOfComputedPane();
const computedPanel = await waitFor(COMPUTED_STYLES_PANEL_SELECTOR);
- const filterInput = await waitFor('[aria-label="Filter Computed Styles"]', computedPanel);
- await click(filterInput);
+ await click('[aria-label="Filter Computed Styles"]', {
+ root: computedPanel,
+ });
await typeText(filterString);
await waitForComputedPaneChange(initialContent);
};
@@ -362,8 +363,7 @@
const initialContent = await getContentOfComputedPane();
const computedPanel = await waitFor(COMPUTED_STYLES_PANEL_SELECTOR);
- const showAllButton = await waitFor(COMPUTED_STYLES_SHOW_ALL_SELECTOR, computedPanel);
- await click(showAllButton);
+ await click(COMPUTED_STYLES_SHOW_ALL_SELECTOR, {root: computedPanel});
await waitForComputedPaneChange(initialContent);
};
@@ -373,7 +373,9 @@
const wasChecked = await groupCheckbox.evaluate(checkbox => (checkbox as HTMLInputElement).checked);
- await click(groupCheckbox);
+ await click(COMPUTED_STYLES_GROUP_SELECTOR, {
+ root: computedPanel,
+ });
if (wasChecked) {
await waitFor('[role="tree"].alphabetical-list', computedPanel);
@@ -526,7 +528,7 @@
const swatch = await getColorSwatch(ruleSection, index);
const {frontend} = getBrowserAndPages();
await frontend.keyboard.down('Shift');
- await click(swatch);
+ await clickElement(swatch);
await frontend.keyboard.up('Shift');
};
@@ -570,8 +572,20 @@
export const focusCSSPropertyValue = async (selector: string, propertyName: string) => {
await waitForStyleRule(selector);
- const property = await getCSSPropertyInRule(selector, propertyName);
- await click(CSS_PROPERTY_VALUE_SELECTOR, {root: property});
+ let property = await getCSSPropertyInRule(selector, propertyName);
+ // Clicking on the semicolon element to make sure we don't hit the swatch or other
+ // non-editable elements.
+ await click(CSS_PROPERTY_VALUE_SELECTOR + ' + .styles-semicolon', {root: property});
+ await waitForFunction(async () => {
+ property = await getCSSPropertyInRule(selector, propertyName);
+ const value = await $(CSS_PROPERTY_VALUE_SELECTOR, property);
+ if (!value) {
+ assert.fail(`Could not find property ${propertyName} in rule ${selector}`);
+ }
+ return await value.evaluate(node => {
+ return node.classList.contains('text-prompt') && node.hasAttribute('contenteditable');
+ });
+ });
};
/**
@@ -768,15 +782,14 @@
if (!a11yPane) {
const elementsPanel = await waitForAria('Elements panel');
const moreTabs = await waitForAria('More tabs', elementsPanel);
- await click(moreTabs);
+ await clickElement(moreTabs);
a11yPane = await waitForAria('Accessibility');
}
- await click(a11yPane);
+ await clickElement(a11yPane);
};
export const toggleAccessibilityTree = async () => {
- const treeToggleButton = await waitForAria('Switch to Accessibility Tree view');
- await click(treeToggleButton);
+ await click('aria/Switch to Accessibility Tree view');
};
export const getPropertiesWithHints = async () => {
diff --git a/test/e2e/helpers/emulation-helpers.ts b/test/e2e/helpers/emulation-helpers.ts
index 4985d9f..42346ba 100644
--- a/test/e2e/helpers/emulation-helpers.ts
+++ b/test/e2e/helpers/emulation-helpers.ts
@@ -11,6 +11,7 @@
goToResource,
reloadDevTools,
waitFor,
+ clickElement,
} from '../../shared/helper.js';
const DEVICE_TOOLBAR_TOGGLER_SELECTOR = '[aria-label="Toggle device toolbar"]';
@@ -36,7 +37,7 @@
if (isOpen) {
return;
}
- await click(deviceToolbarToggler);
+ await clickElement(deviceToolbarToggler);
await waitFor(DEVICE_TOOLBAR_SELECTOR);
};
@@ -66,15 +67,15 @@
};
export const clickDevicesDropDown = async () => {
+ // TODO(crbug.com/1411196): the dropdown might be clickable but not handling the events properly.
+ await new Promise(resolve => setTimeout(resolve, 100));
const toolbar = await waitFor(DEVICE_TOOLBAR_SELECTOR);
- const button = await waitFor(DEVICE_LIST_DROPDOWN_SELECTOR, toolbar);
- await click(button);
+ await click(DEVICE_LIST_DROPDOWN_SELECTOR, {root: toolbar});
};
export const clickZoomDropDown = async () => {
const toolbar = await waitFor(DEVICE_TOOLBAR_SELECTOR);
- const button = await waitFor(ZOOM_LIST_DROPDOWN_SELECTOR, toolbar);
- await click(button);
+ await click(ZOOM_LIST_DROPDOWN_SELECTOR, {root: toolbar});
};
export const selectToggleButton = async () => {
@@ -85,33 +86,29 @@
export const selectEdit = async () => {
await clickDevicesDropDown();
- const edit = await waitFor(EDIT_MENU_ITEM_SELECTOR);
- await click(edit);
+ await click(EDIT_MENU_ITEM_SELECTOR);
};
export const selectDevice = async (name: string) => {
await clickDevicesDropDown();
- const edit = await waitFor(`[aria-label*="${name}, unchecked"]`);
- await click(edit);
+ await click(`[aria-label*="${name}, unchecked"]`);
};
export const selectTestDevice = async () => {
await clickDevicesDropDown();
- const edit = await waitFor(TEST_DEVICE_MENU_ITEM_SELECTOR);
- await click(edit);
+ await click(TEST_DEVICE_MENU_ITEM_SELECTOR);
};
// Test if span button works when emulating a dual screen device.
export const selectDualScreen = async () => {
await clickDevicesDropDown();
- const duo = await waitFor(SURFACE_DUO_MENU_ITEM_SELECTOR);
- await click(duo);
+ await click(SURFACE_DUO_MENU_ITEM_SELECTOR);
};
export const clickToggleButton = async () => {
// make sure the toggle button is clickable.
const toggleButton = await selectToggleButton();
- await click(toggleButton);
+ await clickElement(toggleButton);
};
export const getWidthOfDevice = async () => {
@@ -125,6 +122,5 @@
// Test if span button is clickable when emulating a non-dual-screen device.
export const selectNonDualScreenDevice = async () => {
await clickDevicesDropDown();
- const nonDual = await waitFor(IPAD_MENU_ITEM_SELECTOR);
- await click(nonDual);
+ await click(IPAD_MENU_ITEM_SELECTOR);
};
diff --git a/test/e2e/helpers/issues-helpers.ts b/test/e2e/helpers/issues-helpers.ts
index 7694a7a..6a87e67 100644
--- a/test/e2e/helpers/issues-helpers.ts
+++ b/test/e2e/helpers/issues-helpers.ts
@@ -5,7 +5,16 @@
import {assert} from 'chai';
import type * as puppeteer from 'puppeteer';
-import {$$, click, hasClass, matchStringTable, waitFor, waitForClass, waitForFunction} from '../../shared/helper.js';
+import {
+ $$,
+ click,
+ hasClass,
+ matchStringTable,
+ waitFor,
+ waitForClass,
+ clickElement,
+ waitForFunction,
+} from '../../shared/helper.js';
import {openPanelViaMoreTools} from './settings-helpers.js';
export const CATEGORY = '.issue-category:not(.hidden-issues)';
@@ -109,7 +118,7 @@
}
return undefined;
});
- await click(issueMessageElement);
+ await clickElement(issueMessageElement);
await waitFor('.message');
return getIssueByTitleElement(issueMessageElement);
}
@@ -159,8 +168,8 @@
await expandCategory();
}
- await waitFor(ISSUE);
- await click(ISSUE);
+ const issue = await waitFor(ISSUE);
+ await clickElement(issue);
await waitFor('.message');
}
diff --git a/test/e2e/helpers/media-helpers.ts b/test/e2e/helpers/media-helpers.ts
index 4945cbd..6a8f326 100644
--- a/test/e2e/helpers/media-helpers.ts
+++ b/test/e2e/helpers/media-helpers.ts
@@ -28,8 +28,8 @@
}
export async function getPlayerErrors(count: number) {
- await click(await waitFor('.player-entry-player-title'));
- await click(await waitFor('#tab-messages'));
+ await click('.player-entry-player-title');
+ await click('#tab-messages');
return await waitForMany('.media-message-error', count);
}
diff --git a/test/e2e/helpers/memory-helpers.ts b/test/e2e/helpers/memory-helpers.ts
index 0d2c6ac..54b12e4 100644
--- a/test/e2e/helpers/memory-helpers.ts
+++ b/test/e2e/helpers/memory-helpers.ts
@@ -6,7 +6,16 @@
import type * as puppeteer from 'puppeteer';
import {$, platform, waitForElementWithTextContent} from '../../shared/helper.js';
-import {$$, click, getBrowserAndPages, pasteText, waitFor, waitForFunction, waitForNone} from '../../shared/helper.js';
+import {
+ $$,
+ click,
+ clickElement,
+ getBrowserAndPages,
+ pasteText,
+ waitFor,
+ waitForFunction,
+ waitForNone,
+} from '../../shared/helper.js';
const NEW_HEAP_SNAPSHOT_BUTTON = 'button[aria-label="Take heap snapshot"]';
const MEMORY_PANEL_CONTENT = 'div[aria-label="Memory panel"]';
@@ -22,7 +31,7 @@
export async function takeAllocationProfile() {
const radioButton = await $('//label[text()="Allocation sampling"]', undefined, 'xpath');
- await click(radioButton);
+ await clickElement(radioButton);
await click('button[aria-label="Start heap profiling"]');
await new Promise(r => setTimeout(r, 200));
await click('button[aria-label="Stop heap profiling"]');
@@ -34,7 +43,7 @@
recordStacks: false,
}) {
const radioButton = await $('//label[text()="Allocation instrumentation on timeline"]', undefined, 'xpath');
- await click(radioButton);
+ await clickElement(radioButton);
if (recordStacks) {
await click('input[aria-label="Record stack traces of allocations (extra performance overhead)"]');
}
diff --git a/test/e2e/helpers/performance-helpers.ts b/test/e2e/helpers/performance-helpers.ts
index 29ff580..c62db5a 100644
--- a/test/e2e/helpers/performance-helpers.ts
+++ b/test/e2e/helpers/performance-helpers.ts
@@ -90,6 +90,5 @@
}
export async function clickOnFunctionLink() {
- const link = await waitFor('.timeline-details.devtools-link');
- await click(link);
+ await click('.timeline-details.devtools-link');
}
diff --git a/test/e2e/helpers/settings-helpers.ts b/test/e2e/helpers/settings-helpers.ts
index 4cb0327..3070b22 100644
--- a/test/e2e/helpers/settings-helpers.ts
+++ b/test/e2e/helpers/settings-helpers.ts
@@ -2,20 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import {click, scrollElementIntoView, waitFor, waitForAria, waitForFunction} from '../../shared/helper.js';
+import {
+ click,
+ clickElement,
+ scrollElementIntoView,
+ waitFor,
+ waitForAria,
+ waitForFunction,
+} from '../../shared/helper.js';
export const openPanelViaMoreTools = async (panelTitle: string) => {
// Head to the triple dot menu.
- const tripleDotMenu = await waitForAria('Customize and control DevTools');
- await click(tripleDotMenu);
+ await click('aria/Customize and control DevTools');
// Open the “More Tools” option.
const moreTools = await waitForAria('More tools[role="menuitem"]');
await moreTools.hover();
// Click the desired menu item
- const menuItem = await waitForAria(`${panelTitle}[role="menuitem"]`);
- await click(menuItem);
+ await click(`aria/${panelTitle}[role="menuitem"]`);
// Wait for the corresponding panel to appear.
await waitForAria(`${panelTitle} panel[role="tabpanel"]`);
@@ -49,7 +54,7 @@
const value = await preference.evaluate(checkbox => (checkbox as HTMLInputElement).checked);
if (value !== shouldBeChecked) {
- await click(preference);
+ await clickElement(preference);
await waitForFunction(async () => {
const newValue = await preference.evaluate(checkbox => (checkbox as HTMLInputElement).checked);
@@ -64,7 +69,7 @@
await openSettingsTab('Ignore List');
await click('[aria-label="Add filename pattern"]');
const textBox = await waitFor('[aria-label="Add Pattern"]');
- await click(textBox);
+ await clickElement(textBox);
await textBox.type(pattern);
await textBox.type('\n');
await waitFor(`[title="Ignore scripts whose names match '${pattern}'"]`);
diff --git a/test/e2e/helpers/settings-shortcuts-helpers.ts b/test/e2e/helpers/settings-shortcuts-helpers.ts
index 8a74830..043a0c5 100644
--- a/test/e2e/helpers/settings-shortcuts-helpers.ts
+++ b/test/e2e/helpers/settings-shortcuts-helpers.ts
@@ -10,6 +10,7 @@
platform,
selectOption,
waitFor,
+ clickElement,
waitForElementsWithTextContent,
waitForElementWithTextContent,
waitForFunction,
@@ -80,7 +81,7 @@
export const editShortcutListItem = async (shortcutText: string) => {
const listItemElement = await getShortcutListItemElement(shortcutText) as ElementHandle;
- await click(listItemElement);
+ await clickElement(listItemElement);
await waitFor(EDIT_BUTTON_SELECTOR, listItemElement);
await click(EDIT_BUTTON_SELECTOR, {root: listItemElement});
@@ -122,7 +123,7 @@
assert.fail('could not find add shortcut link');
}
- await click(addShortcutLinkElement);
+ await clickElement(addShortcutLinkElement);
};
export const clickShortcutConfirmButton = async () => {
@@ -142,7 +143,7 @@
if (deleteButtons.length <= index) {
assert.fail(`shortcut delete button #${index} not found`);
}
- await click(deleteButtons[index]);
+ await clickElement(deleteButtons[index]);
};
export const waitForEmptyShortcutInput = async () => {
diff --git a/test/e2e/helpers/sources-helpers.ts b/test/e2e/helpers/sources-helpers.ts
index 058cab6..20cb92b 100644
--- a/test/e2e/helpers/sources-helpers.ts
+++ b/test/e2e/helpers/sources-helpers.ts
@@ -27,6 +27,7 @@
timeout,
typeText,
waitFor,
+ clickElement,
waitForFunction,
waitForFunctionWithTries,
} from '../../shared/helper.js';
@@ -86,8 +87,7 @@
}
export async function doubleClickSourceTreeItem(selector: string) {
- const item = await waitFor(selector);
- await click(item, {clickOptions: {clickCount: 2}, maxPixelsFromLeft: 40});
+ await click(selector, {clickOptions: {clickCount: 2, offset: {x: 40, y: 10}}});
}
export async function openSourcesPanel() {
@@ -246,7 +246,7 @@
assertNotNullOrUndefined(breakpointLine);
await waitForFunction(async () => !(await isBreakpointSet(index)));
- await click(breakpointLine);
+ await clickElement(breakpointLine);
await waitForFunction(async () => await isBreakpointSet(index));
}
@@ -256,7 +256,7 @@
assertNotNullOrUndefined(breakpointLine);
await waitForFunction(async () => await isBreakpointSet(index));
- await click(breakpointLine);
+ await clickElement(breakpointLine);
await waitForFunction(async () => !(await isBreakpointSet(index)));
}
@@ -547,8 +547,7 @@
export async function clickOnContextMenu(selector: string, label: string) {
// Find the selected node, right click.
- const selectedNode = await waitFor(selector);
- await click(selectedNode, {clickOptions: {button: 'right'}});
+ await click(selector, {clickOptions: {button: 'right'}});
// Wait for the context menu option, and click it.
const labelSelector = `[aria-label="${label}"]`;
diff --git a/test/e2e/issues/issue-view-caching_test.ts b/test/e2e/issues/issue-view-caching_test.ts
index a4fc65f..022c718 100644
--- a/test/e2e/issues/issue-view-caching_test.ts
+++ b/test/e2e/issues/issue-view-caching_test.ts
@@ -49,15 +49,17 @@
await triggerIssue();
await navigateToIssuesTab();
async function waitForResources(numberOfAggregatedIssues: number, expectedTableRows: string[][]) {
- await expandIssue();
- const issueElement = await getIssueByTitle('Ensure CORS requests include credentials only when allowed');
- assertNotNullOrUndefined(issueElement);
- const section = await getResourcesElement('requests', issueElement, '.cors-issue-affected-resource-label');
await waitForFunction(async () => {
+ await expandIssue();
+ const issueElement = await getIssueByTitle('Ensure CORS requests include credentials only when allowed');
+ assertNotNullOrUndefined(issueElement);
+ const section = await getResourcesElement('requests', issueElement, '.cors-issue-affected-resource-label');
const text = await section.label.evaluate(el => el.textContent);
const expected = numberOfAggregatedIssues === 1 ? '1 request' : `${numberOfAggregatedIssues} requests`;
return text === expected;
});
+ const issueElement = await getIssueByTitle('Ensure CORS requests include credentials only when allowed');
+ const section = await getResourcesElement('requests', issueElement, '.cors-issue-affected-resource-label');
await ensureResourceSectionIsExpanded(section);
await waitForTableFromResourceSectionContents(section.content, expectedTableRows);
const adorner = await waitFor('devtools-adorner');
diff --git a/test/e2e/memory/memory_test.ts b/test/e2e/memory/memory_test.ts
index 0a30f8d..30c5c77 100644
--- a/test/e2e/memory/memory_test.ts
+++ b/test/e2e/memory/memory_test.ts
@@ -8,11 +8,11 @@
$$,
$,
assertNotNullOrUndefined,
- click,
getBrowserAndPages,
goToResource,
step,
waitFor,
+ clickElement,
waitForElementsWithTextContent,
waitForElementWithTextContent,
waitForFunction,
@@ -136,7 +136,7 @@
const pendingActivitiesSpan = await waitFor('//span[text()="Pending activities"]', undefined, undefined, 'xpath');
const pendingActiviesRow = await $('ancestor-or-self::tr', pendingActivitiesSpan, 'xpath');
await waitForFunction(async () => {
- await click(pendingActivitiesSpan);
+ await clickElement(pendingActivitiesSpan);
const res = await pendingActiviesRow.evaluate(x => x.classList.toString());
return res.includes('selected');
});
@@ -146,7 +146,7 @@
undefined, undefined, 'xpath');
const internalNodeRow = await $('ancestor-or-self::tr', internalNodeSpan, 'xpath');
await waitForFunction(async () => {
- await click(internalNodeSpan);
+ await clickElement(internalNodeSpan);
const res = await internalNodeRow.evaluate(x => x.classList.toString());
return res.includes('selected');
});
@@ -225,7 +225,7 @@
// Have to click it not in the middle as the middle can hold the link to the
// file in the sources pane and we want to avoid clicking that.
- await click(sharedInLeakingElementRow, {maxPixelsFromLeft: 10});
+ await clickElement(sharedInLeakingElementRow /* TODO(crbug.com/1363150): {maxPixelsFromLeft: 10} */);
const {frontend} = getBrowserAndPages();
// Expand the data-grid for the shared list
await frontend.keyboard.press('ArrowRight');
diff --git a/test/e2e/network/network-datagrid_test.ts b/test/e2e/network/network-datagrid_test.ts
index a808946..dfba73d 100644
--- a/test/e2e/network/network-datagrid_test.ts
+++ b/test/e2e/network/network-datagrid_test.ts
@@ -11,7 +11,6 @@
pressKey,
step,
waitFor,
- waitForAria,
waitForElementWithTextContent,
waitForFunction,
} from '../../shared/helper.js';
@@ -86,13 +85,11 @@
});
await step('Click "Response Headers" submenu', async () => {
- const responseHeaders = await waitForAria('Response Headers');
- await click(responseHeaders);
+ await click('aria/Response Headers');
});
await step('Enable the Last-Modified column in the network datagrid', async () => {
- const lastModified = await waitForAria('Last-Modified, unchecked');
- await click(lastModified);
+ await click('aria/Last-Modified, unchecked');
});
await step('Wait for the "Last-Modified" column to have the expected values', async () => {
@@ -231,8 +228,7 @@
});
await step('Enable the Initiator Address Space column in the network datagrid', async () => {
- const initiatorAddressSpace = await waitForAria('Initiator Address Space, unchecked');
- await click(initiatorAddressSpace);
+ await click('aria/Initiator Address Space, unchecked');
});
await step('Wait for the Initiator Address Space column to have the expected values', async () => {
@@ -262,8 +258,7 @@
});
await step('Enable the Remote Address Space column in the network datagrid', async () => {
- const remoteAddressSpace = await waitForAria('Remote Address Space, unchecked');
- await click(remoteAddressSpace);
+ await click('aria/Remote Address Space, unchecked');
});
await step('Wait for the Remote Address Space column to have the expected values', async () => {
diff --git a/test/e2e/network/network-filter_test.ts b/test/e2e/network/network-filter_test.ts
index 853102b..482e599 100644
--- a/test/e2e/network/network-filter_test.ts
+++ b/test/e2e/network/network-filter_test.ts
@@ -7,13 +7,14 @@
import {
click,
+ waitFor,
reloadDevTools,
typeText,
- waitFor,
waitForAria,
waitForMany,
waitForNone,
getTestServerPort,
+ clickElement,
} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
@@ -36,7 +37,12 @@
}
async function clearFilter() {
- await click(await waitFor('.filter-input-clear-button'));
+ await click('.filter-input-container');
+ try {
+ await clickElement(await waitFor('.filter-input-clear-button'));
+ } catch {
+ // if the field is empty, clicking fails.
+ }
}
describe('The Network Tab', async function() {
@@ -136,7 +142,7 @@
it('can filter by partial URL in the log view', async () => {
await clearFilter();
- await typeText(`https://localhost:${getTestServerPort()}//`);
+ await typeText(`https://localhost:${getTestServerPort()}`);
const nodes = await waitForMany('.data-grid-data-grid-node > .name-column', 1);
expect(nodes.length).to.equal(11);
});
@@ -167,7 +173,7 @@
const invertCheckbox = await (await waitForAria('Invert')).toElement('input');
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
await typeText('5');
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(true);
const nodes = await waitForMany('.data-grid-data-grid-node > .name-column', 10);
const output = [...RESULTS];
@@ -177,7 +183,7 @@
expect(await elementTextContent(nodes[i])).to.equal(output[i]);
}
// Cleanup
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
});
@@ -185,7 +191,7 @@
const invertCheckbox = await (await waitForAria('Invert')).toElement('input');
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
await typeText('/4/');
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(true);
const nodes = await waitForMany('.data-grid-data-grid-node > .name-column', 10);
const output = [...RESULTS];
@@ -195,7 +201,7 @@
expect(await elementTextContent(nodes[i])).to.equal(output[i]);
}
// Cleanup
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
});
@@ -203,13 +209,13 @@
const invertCheckbox = await (await waitForAria('Invert')).toElement('input');
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
await typeText('-10');
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(true);
const nodes = await waitForMany('.data-grid-data-grid-node > .name-column', 1);
expect(nodes.length).to.equal(1);
expect(await elementTextContent(nodes[0])).to.equal(RESULTS[0]);
// Cleanup
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
});
@@ -217,13 +223,13 @@
const invertCheckbox = await (await waitForAria('Invert')).toElement('input');
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
await typeText('-/10/');
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(true);
const nodes = await waitForMany('.data-grid-data-grid-node > .name-column', 1);
expect(nodes.length).to.equal(1);
expect(await elementTextContent(nodes[0])).to.equal(RESULTS[0]);
// Cleanup
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
});
@@ -232,7 +238,7 @@
{
const invertCheckbox = await (await waitForAria('Invert')).toElement('input');
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(true);
}
// Verify persistence when enabled.
@@ -240,7 +246,7 @@
{
const invertCheckbox = await (await waitForAria('Invert')).toElement('input');
expect(await checkboxIsChecked(invertCheckbox)).to.equal(true);
- await click(invertCheckbox);
+ await clickElement(invertCheckbox);
expect(await checkboxIsChecked(invertCheckbox)).to.equal(false);
}
// Verify persistence when disabled.
diff --git a/test/e2e/network/network-request-view_test.ts b/test/e2e/network/network-request-view_test.ts
index 62d4c9e..550596e 100644
--- a/test/e2e/network/network-request-view_test.ts
+++ b/test/e2e/network/network-request-view_test.ts
@@ -38,12 +38,14 @@
const configureAndCheckHeaderOverrides = async () => {
const infoBar = await waitForAria('Select a folder to store override files in.');
- const button = await waitFor('.infobar-main-row .infobar-button', infoBar);
- await click(button);
+ await click('.infobar-main-row .infobar-button', {
+ root: infoBar,
+ });
let networkView = await waitFor('.network-item-view');
- let headersTabHeader = await waitFor('#tab-headersComponent', networkView);
- await click(headersTabHeader);
+ await click('#tab-headersComponent', {
+ root: networkView,
+ });
await waitFor('#tab-headersComponent[role=tab][aria-selected=true]', networkView);
let responseHeaderSection = await waitFor('[aria-label="Response Headers"]', networkView);
@@ -66,8 +68,9 @@
await navigateToNetworkTab('hello.html');
await selectRequestByName('hello.html');
networkView = await waitFor('.network-item-view');
- headersTabHeader = await waitFor('#tab-headersComponent', networkView);
- await click(headersTabHeader);
+ await click('#tab-headersComponent', {
+ root: networkView,
+ });
responseHeaderSection = await waitFor('[aria-label="Response Headers"]');
row = await waitFor('.row.header-overridden', responseHeaderSection);
@@ -89,8 +92,9 @@
await step('select the "Timing" tab', async () => {
const networkView = await waitFor('.network-item-view');
- const timingTabHeader = await waitFor('[aria-label=Timing][role="tab"]', networkView);
- await click(timingTabHeader);
+ await click('[aria-label=Timing][role="tab"]', {
+ root: networkView,
+ });
await waitFor('[aria-label=Timing][role=tab][aria-selected=true]', networkView);
});
@@ -121,8 +125,9 @@
await selectRequestByName('webbundle.wbn');
const networkView = await waitFor('.network-item-view');
- const previewTabHeader = await waitFor('[aria-label=Preview][role=tab]', networkView);
- await click(previewTabHeader);
+ await click('[aria-label=Preview][role=tab]', {
+ root: networkView,
+ });
await waitFor('[aria-label=Preview][role=tab][aria-selected=true]', networkView);
await waitForElementWithTextContent('webbundle.wbn', networkView);
@@ -155,8 +160,9 @@
const styleSrcError = expectError(`Refused to load the stylesheet '${stylesheet}'`);
const networkView = await waitFor('.network-item-view');
- const previewTabHeader = await waitFor('[aria-label=Preview][role=tab]', networkView);
- await click(previewTabHeader);
+ await click('[aria-label=Preview][role=tab]', {
+ root: networkView,
+ });
await waitFor('[aria-label=Preview][role=tab][aria-selected=true]', networkView);
const frame = await waitFor('.html-preview-frame');
@@ -187,8 +193,9 @@
await selectRequestByName(name);
const networkView = await waitFor('.network-item-view');
- const previewTabHeader = await waitFor('[aria-label=Preview][role=tab]', networkView);
- await click(previewTabHeader);
+ await click('[aria-label=Preview][role=tab]', {
+ root: networkView,
+ });
await waitFor('[aria-label=Preview][role=tab][aria-selected=true]', networkView);
const frame = await waitFor('.html-preview-frame');
@@ -209,8 +216,9 @@
await selectRequestByName('localhost');
const networkView = await waitFor('.network-item-view');
- const messagesTabHeader = await waitFor('[aria-label=Messages][role=tab]', networkView);
- await click(messagesTabHeader);
+ await click('[aria-label=Messages][role=tab]', {
+ root: networkView,
+ });
await waitFor('[aria-label=Messages][role=tab][aria-selected=true]', networkView);
return waitFor('.websocket-frame-view');
};
@@ -264,8 +272,9 @@
await selectRequestByName('image.svg?id=42¶m=a%20b');
const networkView = await waitFor('.network-item-view');
- const headersTabHeader = await waitFor('[aria-label=Headers][role="tab"]', networkView);
- await click(headersTabHeader);
+ await click('[aria-label=Headers][role="tab"]', {
+ root: networkView,
+ });
await waitFor('[aria-label=Headers][role=tab][aria-selected=true]', networkView);
const headersView = await waitFor('.request-headers-view');
const headersOutline = await $$('[role=treeitem]:not(.hidden)', headersView);
@@ -312,8 +321,9 @@
await assertOutlineMatches(expectedHeadersContent, headersOutline);
- const payloadTabHeader = await waitFor('[aria-label=Payload][role="tab"]', networkView);
- await click(payloadTabHeader);
+ await click('[aria-label=Payload][role="tab"]', {
+ root: networkView,
+ });
await waitFor('[aria-label=Payload][role=tab][aria-selected=true]', networkView);
const payloadView = await waitFor('.request-payload-view');
const payloadOutline = await $$('[role=treeitem]:not(.hidden)', payloadView);
@@ -340,13 +350,15 @@
await selectRequestByName('image.svg?id=42¶m=a%20b');
const networkView = await waitFor('.network-item-view');
- const headersTabHeader = await waitFor('[aria-label=Headers][role="tab"]', networkView);
- await click(headersTabHeader);
+ await click('[aria-label=Headers][role="tab"]', {
+ root: networkView,
+ });
await waitFor('[aria-label=Headers][role=tab][aria-selected=true]', networkView);
const headersView = await waitFor('.request-headers-view');
const responseHeadersTitle = await waitForElementWithTextContent('Response Headers (7)View source');
- const rawHeadersToggle = await waitFor('.header-toggle', responseHeadersTitle);
- await click(rawHeadersToggle);
+ await click('.header-toggle', {
+ root: responseHeadersTitle,
+ });
const headersOutline = await $$('[role=treeitem]:not(.hidden)', headersView);
const expectedHeadersContent = [
@@ -402,8 +414,9 @@
await selectRequestByName('image.svg?id=42¶m=a%20b');
const networkView = await waitFor('.network-item-view');
- const payloadTabHeader = await waitFor('[aria-label=Payload][role="tab"]', networkView);
- await click(payloadTabHeader);
+ await click('[aria-label=Payload][role="tab"]', {
+ root: networkView,
+ });
await waitFor('[aria-label=Payload][role=tab][aria-selected=true]', networkView);
await selectRequestByName('image.svg');
@@ -425,8 +438,7 @@
await navigateToNetworkTab('hello.html');
await selectRequestByName('hello.html', {button: 'right'});
- const createHeaderOverrideMenuEntry = await waitForAria('Override headers');
- await click(createHeaderOverrideMenuEntry);
+ await click('aria/Override headers');
await configureAndCheckHeaderOverrides();
});
@@ -437,8 +449,9 @@
await selectRequestByName('hello.html');
const networkView = await waitFor('.network-item-view');
- const headersTabHeader = await waitFor('#tab-headersComponent', networkView);
- await click(headersTabHeader);
+ await click('#tab-headersComponent', {
+ root: networkView,
+ });
await click('devtools-button.enable-editing');
await configureAndCheckHeaderOverrides();
diff --git a/test/e2e/quick_open/QuickOpen_test.ts b/test/e2e/quick_open/QuickOpen_test.ts
index 9d4cfe5..cb1a0d2 100644
--- a/test/e2e/quick_open/QuickOpen_test.ts
+++ b/test/e2e/quick_open/QuickOpen_test.ts
@@ -4,7 +4,7 @@
import {assert} from 'chai';
-import {$$, click, enableExperiment, goToResource, step, waitFor} from '../../shared/helper.js';
+import {$$, clickElement, enableExperiment, goToResource, step, waitFor} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
import {navigateToElementsTab} from '../helpers/elements-helpers.js';
import {getMenuItemAtPosition, getMenuItemTitleAtPosition, openFileQuickOpen} from '../helpers/quick_open-helpers.js';
@@ -22,7 +22,7 @@
await goToResource('pages/hello-world.html');
await openFileQuickOpen();
const firstItem = await getMenuItemAtPosition(0);
- await click(firstItem);
+ await clickElement(firstItem);
});
await step('check the sources panel is open with the selected file', async () => {
await waitFor('.navigator-file-tree-item');
diff --git a/test/e2e/settings/Preferences_test.ts b/test/e2e/settings/Preferences_test.ts
index 0b70573..f77b57d 100644
--- a/test/e2e/settings/Preferences_test.ts
+++ b/test/e2e/settings/Preferences_test.ts
@@ -4,7 +4,12 @@
import {assert} from 'chai';
-import {click, waitFor, waitForAria, waitForElementWithTextContent} from '../../shared/helper.js';
+import {
+ clickElement,
+ waitFor,
+ waitForAria,
+ waitForElementWithTextContent,
+} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
import {openSettingsTab} from '../helpers/settings-helpers.js';
@@ -21,7 +26,7 @@
const icon = await waitFor('devtools-icon', label);
assert.include(await icon.evaluate(icon => icon.getAttribute('title')), 'This setting is deprecated');
- await click(icon);
+ await clickElement(icon);
await waitFor('.tabbed-pane-header-tab[aria-label="Experiments"][aria-selected="true"]');
});
});
diff --git a/test/e2e/sources/breakpoint-csp-violations_test.ts b/test/e2e/sources/breakpoint-csp-violations_test.ts
index cfbfa50..45e18a6 100644
--- a/test/e2e/sources/breakpoint-csp-violations_test.ts
+++ b/test/e2e/sources/breakpoint-csp-violations_test.ts
@@ -8,8 +8,7 @@
import {describe, it} from '../../shared/mocha-extensions.js';
import {getPausedMessages, openSourcesPanel, PAUSE_ON_UNCAUGHT_EXCEPTION_SELECTOR} from '../helpers/sources-helpers.js';
-// Fails flakily on Mac
-describe.skipOnPlatforms(['mac'], '[crbug.com/1409768] Breakpoints on CSP Violation', async () => {
+describe('Breakpoints on CSP Violation', async () => {
it('CSP Violations should come up before break on exceptions', async () => {
await openSourcesPanel();
await click('[aria-label="CSP Violation Breakpoints"]');
diff --git a/test/e2e/sources/breakpoint-javascript_test.ts b/test/e2e/sources/breakpoint-javascript_test.ts
index f51bb15..890c167 100644
--- a/test/e2e/sources/breakpoint-javascript_test.ts
+++ b/test/e2e/sources/breakpoint-javascript_test.ts
@@ -6,6 +6,7 @@
import {
click,
+ clickElement,
enableExperiment,
getBrowserAndPages,
goToResource,
@@ -198,7 +199,7 @@
const firstItemTitle = await getMenuItemTitleAtPosition(0);
const firstItem = await getMenuItemAtPosition(0);
assert.strictEqual(firstItemTitle, 'hello.js');
- await click(firstItem);
+ await clickElement(firstItem);
});
await step('add a breakpoint to the beginning of the inline script with sourceURL', async () => {
diff --git a/test/e2e/sources/breakpoints-sidebarpane_test.ts b/test/e2e/sources/breakpoints-sidebarpane_test.ts
index c10abf8..18f06ab 100644
--- a/test/e2e/sources/breakpoints-sidebarpane_test.ts
+++ b/test/e2e/sources/breakpoints-sidebarpane_test.ts
@@ -17,7 +17,6 @@
import {
$,
assertNotNullOrUndefined,
- click,
enableExperiment,
waitForFunction,
waitFor,
@@ -25,6 +24,7 @@
type puppeteer,
getBrowserAndPages,
waitForMany,
+ clickElement,
} from '../../shared/helper.js';
const BREAKPOINT_VIEW_COMPONENT = 'devtools-breakpoint-view';
@@ -61,7 +61,7 @@
// Set a breakpoint on the original source.
const breakpointLineHandle = await getLineNumberElement(setBreakpointLine);
assertNotNullOrUndefined(breakpointLineHandle);
- await click(breakpointLineHandle);
+ await clickElement(breakpointLineHandle);
await waitForFunction(async () => await isBreakpointSet(expectedResolvedLineNumber));
// Check if the breakpoint sidebar correctly shows the original source breakpoint.
@@ -122,7 +122,7 @@
const slidBreakpointLine = 5;
const breakpointLine = await getLineNumberElement(originalBreakpointLine);
assertNotNullOrUndefined(breakpointLine);
- await click(breakpointLine);
+ await clickElement(breakpointLine);
await waitForFunction(async () => await isBreakpointSet(slidBreakpointLine));
const breakpointView = await $(BREAKPOINT_VIEW_COMPONENT);
@@ -134,7 +134,7 @@
const checkbox = await breakpointItem.$('input');
assertNotNullOrUndefined(checkbox);
- await click(checkbox);
+ await clickElement(checkbox);
// Wait until the click has propagated: the line is updated with the new location.
await waitForFunction(async () => await isBreakpointSet(originalBreakpointLine));
diff --git a/test/e2e/sources/can-open-linear-memory-inspector_test.ts b/test/e2e/sources/can-open-linear-memory-inspector_test.ts
index 90a7bd8..e4627ae 100644
--- a/test/e2e/sources/can-open-linear-memory-inspector_test.ts
+++ b/test/e2e/sources/can-open-linear-memory-inspector_test.ts
@@ -120,8 +120,10 @@
return sharedBufferTab.evaluate(e => e.getAttribute('aria-selected') === 'true');
});
// There should only be two tabs
- const tabs = await $$(LINEAR_MEMORY_INSPECTOR_TABBED_PANE_TAB_SELECTOR, lmiTabbedPane);
- assert.strictEqual(tabs.length, 2);
+ await waitForFunction(async () => {
+ const tabs = await $$(LINEAR_MEMORY_INSPECTOR_TABBED_PANE_TAB_SELECTOR, lmiTabbedPane);
+ return tabs.length === 2;
+ });
});
await step('resume and pause in other worker (hitting a debugger statement)', async () => {
@@ -141,8 +143,10 @@
return sharedBufferTab.evaluate(e => e.getAttribute('aria-selected') === 'false');
});
// Now there are three tabs
- const tabs = await $$(LINEAR_MEMORY_INSPECTOR_TABBED_PANE_TAB_SELECTOR, lmiTabbedPane);
- assert.strictEqual(tabs.length, 3);
+ await waitForFunction(async () => {
+ const tabs = await $$(LINEAR_MEMORY_INSPECTOR_TABBED_PANE_TAB_SELECTOR, lmiTabbedPane);
+ return tabs.length === 3;
+ });
});
await step('open shared buffer in other worker', async () => {
@@ -152,8 +156,10 @@
return sharedBufferTab.evaluate(e => e.getAttribute('aria-selected') === 'true');
});
// Still three tabs
- const tabs = await $$(LINEAR_MEMORY_INSPECTOR_TABBED_PANE_TAB_SELECTOR, lmiTabbedPane);
- assert.strictEqual(tabs.length, 3);
+ await waitForFunction(async () => {
+ const tabs = await $$(LINEAR_MEMORY_INSPECTOR_TABBED_PANE_TAB_SELECTOR, lmiTabbedPane);
+ return tabs.length === 3;
+ });
});
});
});
diff --git a/test/e2e/sources/header-overrides_test.ts b/test/e2e/sources/header-overrides_test.ts
index c08c3ac..c67e515 100644
--- a/test/e2e/sources/header-overrides_test.ts
+++ b/test/e2e/sources/header-overrides_test.ts
@@ -60,8 +60,9 @@
async function openHeadersTab() {
const networkView = await waitFor(NETWORK_VIEW_SELECTOR);
- const headersTabHeader = await waitFor(HEADERS_TAB_SELECTOR, networkView);
- await click(headersTabHeader);
+ await click(HEADERS_TAB_SELECTOR, {
+ root: networkView,
+ });
await waitFor(ACTIVE_HEADERS_TAB_SELECTOR, networkView);
}
diff --git a/test/e2e/sources/icon-row-bucket_test.ts b/test/e2e/sources/icon-row-bucket_test.ts
index 2f71690..79b3617 100644
--- a/test/e2e/sources/icon-row-bucket_test.ts
+++ b/test/e2e/sources/icon-row-bucket_test.ts
@@ -11,6 +11,7 @@
disableExperiment,
goToResource,
waitFor,
+ clickElement,
waitForFunction,
waitForWithTries,
} from '../../shared/helper.js';
@@ -65,7 +66,7 @@
async function waitForExpandedIssueTitle(issueIconComponent: puppeteer.ElementHandle<Element>): Promise<Set<string>> {
return await waitForFunction(async () => {
- await click(issueIconComponent);
+ await clickElement(issueIconComponent);
const expandedIssues = await getExpandedIssuesTitle();
if (expandedIssues.size) {
return expandedIssues;
@@ -152,7 +153,7 @@
const bucketIssueIconComponents = await getIconComponents('cm-messageIcon-issue');
assert.strictEqual(bucketIssueIconComponents.length, 1);
const issueIconComponent = bucketIssueIconComponents[0];
- await click(issueIconComponent);
+ await clickElement(issueIconComponent);
const expandedIssues = await waitForExpandedIssueTitle(issueIconComponent);
assert.isTrue(expandedIssues.has('Trusted Type policy creation blocked by Content Security Policy'));
diff --git a/test/e2e/sources/live-edit-moving-breakpoint_test.ts b/test/e2e/sources/live-edit-moving-breakpoint_test.ts
index 3ec09bf..30b184a 100644
--- a/test/e2e/sources/live-edit-moving-breakpoint_test.ts
+++ b/test/e2e/sources/live-edit-moving-breakpoint_test.ts
@@ -7,7 +7,7 @@
import {
$textContent,
assertNotNullOrUndefined,
- click,
+ clickElement,
getBrowserAndPages,
pressKey,
step,
@@ -34,7 +34,7 @@
// Place the caret at the end of the marker line by clicking in the middle of the
// line element and then pressing 'End'.
- await click(markerLine);
+ await clickElement(markerLine);
await frontend.keyboard.press('End');
await frontend.keyboard.press('Enter');
diff --git a/test/e2e/sources/sourcemap_test.ts b/test/e2e/sources/sourcemap_test.ts
index 5c34380..0fccb37 100644
--- a/test/e2e/sources/sourcemap_test.ts
+++ b/test/e2e/sources/sourcemap_test.ts
@@ -6,6 +6,7 @@
import {
click,
+ clickElement,
enableExperiment,
getBrowserAndPages,
goToResource,
@@ -545,6 +546,12 @@
});
describe('The Elements Tab', async () => {
+ async function clickStyleValueWithModifiers(selector: string, name: string, value: string, location: string) {
+ const element = await waitForCSSPropertyValue(selector, name, value, location);
+ // Click with offset to skip swatches.
+ await withControlOrMetaKey(() => clickElement(element, {clickOptions: {offset: {x: 20, y: 5}}}));
+ }
+
it('links to the right SASS source for inline CSS with relative sourcemap (crbug.com/787792)', async () => {
await goToResource('sources/sourcemap-css-inline-relative.html');
await step('Prepare elements tab', async () => {
@@ -553,8 +560,7 @@
await focusElementsTree();
await clickNthChildOfSelectedElementNode(1);
});
- const value = await waitForCSSPropertyValue('body .text', 'color', 'green', 'app.scss:6');
- await withControlOrMetaKey(() => click(value));
+ await clickStyleValueWithModifiers('body .text', 'color', 'green', 'app.scss:6');
await waitForElementWithTextContent('Line 12, Column 9');
});
@@ -566,8 +572,7 @@
await focusElementsTree();
await clickNthChildOfSelectedElementNode(1);
});
- const value = await waitForCSSPropertyValue('body .text', 'color', 'green', 'app.scss:6');
- await withControlOrMetaKey(() => click(value));
+ await clickStyleValueWithModifiers('body .text', 'color', 'green', 'app.scss:6');
await waitForElementWithTextContent('Line 12, Column 9');
});
@@ -579,8 +584,7 @@
await focusElementsTree();
await clickNthChildOfSelectedElementNode(1);
});
- const value = await waitForCSSPropertyValue('body .text', 'color', 'green', 'app.scss:6');
- await withControlOrMetaKey(() => click(value));
+ await clickStyleValueWithModifiers('body .text', 'color', 'green', 'app.scss:6');
await waitForElementWithTextContent('Line 12, Column 9');
});
@@ -592,8 +596,7 @@
await focusElementsTree();
await clickNthChildOfSelectedElementNode(1);
});
- const value = await waitForCSSPropertyValue('body .text', 'color', 'green', 'app.scss:6');
- await withControlOrMetaKey(() => click(value));
+ await clickStyleValueWithModifiers('body .text', 'color', 'green', 'app.scss:6');
await waitForElementWithTextContent('Line 12, Column 9');
});
});
diff --git a/test/interactions/data_grid/data_grid_test.ts b/test/interactions/data_grid/data_grid_test.ts
index 8cfd5f4..4c9f644 100644
--- a/test/interactions/data_grid/data_grid_test.ts
+++ b/test/interactions/data_grid/data_grid_test.ts
@@ -171,11 +171,7 @@
/**
* The value column is visible by default, so clicking this will hide it.
*/
- const toggleValueColumnButton = await $('.value-visibility-toggle');
- if (!toggleValueColumnButton) {
- assert.fail('Could not find value column toggle button.');
- }
- await click(toggleValueColumnButton);
+ await click('.value-visibility-toggle');
await waitForFunction(async () => {
const dataGrid = await getDataGrid();
@@ -263,8 +259,7 @@
assertNumberBetween(columnPixelWidths[0], 348, 352); // 58.35% of 600 = ~350
assertNumberBetween(columnPixelWidths[1], 247, 252); // 42% of 600 = ~249
- const addButton = await waitFor('#add');
- await click(addButton);
+ await click('#add');
await getDataGridRows(11, dataGrid);
const newColumnPixelWidths = await getColumnPixelWidths(columns);
@@ -299,11 +294,7 @@
const dataGrid = await getDataGrid();
await assertDataGridNotScrolled(dataGrid);
- const firstBodyCell = await $('tr[aria-rowindex="1"] > td[aria-colindex="1"]', dataGrid);
- if (!firstBodyCell) {
- throw new Error('Could not find first body cell to click.');
- }
- await click(firstBodyCell);
+ await click('tr[aria-rowindex="1"] > td[aria-colindex="1"]');
await waitFor('tr.selected', dataGrid);
const {frontend} = getBrowserAndPages();
await frontend.evaluate('window.addNewRow()');
@@ -327,11 +318,7 @@
const dataGrid = await getDataGrid();
await assertDataGridNotScrolled(dataGrid);
- const firstBodyCell = await $('tr[aria-rowindex="1"] > td[aria-colindex="1"]', dataGrid);
- if (!firstBodyCell) {
- throw new Error('Could not find first body cell to click.');
- }
- await click(firstBodyCell);
+ await click('tr[aria-rowindex="1"] > td[aria-colindex="1"]');
await waitFor('tr.selected', dataGrid);
await clickAddButton();
await getDataGridRows(11, dataGrid);
@@ -344,11 +331,7 @@
const dataGrid = await getDataGrid();
await assertDataGridNotScrolled(dataGrid);
- const firstBodyCell = await $('tr[aria-rowindex="1"] > td[aria-colindex="1"]', dataGrid);
- if (!firstBodyCell) {
- throw new Error('Could not find first body cell to click.');
- }
- await click(firstBodyCell);
+ await click('tr[aria-rowindex="1"] > td[aria-colindex="1"]');
await waitFor('tr.selected', dataGrid);
// And new row and ensure we have not auto scrolled as we have a cell selected.
await frontend.evaluate('window.addNewRow()');
diff --git a/test/interactions/data_grid_controller/data_grid_controller_test.ts b/test/interactions/data_grid_controller/data_grid_controller_test.ts
index 80461cd..b79c95f 100644
--- a/test/interactions/data_grid_controller/data_grid_controller_test.ts
+++ b/test/interactions/data_grid_controller/data_grid_controller_test.ts
@@ -11,7 +11,7 @@
platformSpecificTextForSubMenuEntryItem,
} from '../../e2e/helpers/context-menu-helpers.js';
import {getDataGrid, getDataGridController, getInnerTextOfDataGridCells} from '../../e2e/helpers/datagrid-helpers.js';
-import {$, $$, $textContent, click, waitFor, waitForFunction} from '../../shared/helper.js';
+import {$, $$, $textContent, click, clickElement, waitFor, waitForFunction} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
import {loadComponentDocExample, preloadForCodeCoverage} from '../helpers/shared.js';
@@ -22,7 +22,7 @@
if (!headerCell) {
assert.fail(`Could not find header cell with text ${headerText}`);
}
- await click(headerCell, {
+ await clickElement(headerCell, {
clickOptions: {
button: 'right',
},
@@ -37,7 +37,7 @@
if (!headerCell) {
assert.fail(`Could not find body cell with text ${cellText}`);
}
- await click(headerCell, {
+ await clickElement(headerCell, {
clickOptions: {
button: 'right',
},
@@ -72,11 +72,7 @@
await activateContextMenuOnColumnHeader('Key');
const contextMenu = await $('.soft-context-menu');
assert.isNotNull(contextMenu);
- const valueColumnOption = await $('[aria-label="Value, checked"]');
- if (!valueColumnOption) {
- assert.fail('Could not find Value column in context menu.');
- }
- await click(valueColumnOption);
+ await click('[aria-label="Value, checked"]');
const dataGrid = await getDataGrid();
await waitForFunction(async () => {
diff --git a/test/interactions/tree_outline/tree_outline_test.ts b/test/interactions/tree_outline/tree_outline_test.ts
index b5beffa..40c2284 100644
--- a/test/interactions/tree_outline/tree_outline_test.ts
+++ b/test/interactions/tree_outline/tree_outline_test.ts
@@ -73,11 +73,9 @@
it('lets the user click to expand a node', async () => {
await loadComponentDocExample('tree_outline/basic.html');
const treeOutline = await getTreeOutline();
- const firstArrow = await $('.arrow-icon', treeOutline);
- if (!firstArrow) {
- assert.fail('Could not find arrow icon to click');
- }
- await click(firstArrow);
+ await click('.arrow-icon', {
+ root: treeOutline,
+ });
await waitForFunction(async () => {
const visibleNodes = await $$('li[role="treeitem"]', treeOutline);
// 3: 2 original root nodes, and the 1 child of the first root node.
diff --git a/test/shared/helper.ts b/test/shared/helper.ts
index 9b4b804..c259025 100644
--- a/test/shared/helper.ts
+++ b/test/shared/helper.ts
@@ -47,52 +47,6 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const globalThis: any = global;
-/**
- * Returns an {x, y} position within the element identified by the selector within the root.
- * By default the position is the center of the bounding box. If the element's bounding box
- * extends beyond that of a containing element, this position may not correspond to the element.
- * In this case, specifying maxPixelsFromLeft will constrain the returned point to be close to
- * the left edge of the bounding box.
- */
-export const getElementPosition =
- async (selector: string|puppeteer.ElementHandle, root?: puppeteer.JSHandle, maxPixelsFromLeft?: number) => {
- const rectData = await waitForFunction(async () => {
- let element: puppeteer.ElementHandle;
- if (typeof selector === 'string') {
- element = await waitFor(selector, root);
- } else {
- element = selector;
- }
-
- return element.evaluate((element: Element) => {
- if (!element) {
- return {};
- }
-
- if (!element.isConnected) {
- return undefined;
- }
-
- const {left, top, width, height} = element.getBoundingClientRect();
- return {left, top, width, height};
- });
- });
-
- if (rectData.left === undefined) {
- throw new Error(`Unable to find element with selector "${selector}"`);
- }
-
- let pixelsFromLeft = rectData.width * 0.5;
- if (maxPixelsFromLeft && pixelsFromLeft > maxPixelsFromLeft) {
- pixelsFromLeft = maxPixelsFromLeft;
- }
-
- return {
- x: rectData.left + pixelsFromLeft,
- y: rectData.top + rectData.height * 0.5,
- };
-};
-
export interface ClickOptions {
root?: puppeteer.JSHandle;
clickOptions?: puppeteer.ClickOptions;
@@ -112,23 +66,45 @@
});
};
-export const click = async (selector: string|puppeteer.ElementHandle, options?: ClickOptions) => {
- const {frontend} = getBrowserAndPages();
- const clickableElement =
- await getElementPosition(selector, options && options.root, options && options.maxPixelsFromLeft);
-
- if (!clickableElement) {
- throw new Error(`Unable to locate clickable element "${selector}".`);
+export const click = async(selector: string, options?: ClickOptions): Promise<puppeteer.ElementHandle> => {
+ // TODO(crbug.com/1410168): we should refactor waitFor to be compatible with
+ // Puppeteer's syntax for selectors.
+ const queryHandlers = new Set([
+ 'pierceShadowText',
+ 'pierce',
+ 'aria',
+ 'xpath',
+ 'text',
+ ]);
+ let queryHandler = 'pierce';
+ for (const handler of queryHandlers) {
+ const prefix = handler + '/';
+ if (selector.startsWith(prefix)) {
+ queryHandler = handler;
+ selector = selector.substring(prefix.length);
+ break;
+ }
}
-
- // Click on the button and wait for the console to load. The reason we use this method
- // rather than elementHandle.click() is because the frontend attaches the behavior to
- // a 'mousedown' event (not the 'click' event). To avoid attaching the test behavior
- // to a specific event we instead locate the button in question and ask Puppeteer to
- // click on it instead.
- await frontend.mouse.click(clickableElement.x, clickableElement.y, options && options.clickOptions);
+ return waitForFunction(async () => {
+ const element = await waitFor(selector, options?.root, undefined, queryHandler);
+ try {
+ await element.click(options?.clickOptions);
+ return element;
+ } catch (err) {
+ // A bit of delay to not retry too often.
+ await new Promise(resolve => setTimeout(resolve, 50));
+ }
+ return undefined;
+ });
};
+/**
+ * @deprecated This method is not able to recover from unstable DOM. Use click() instead.
+ */
+export async function clickElement(element: puppeteer.ElementHandle, options?: ClickOptions): Promise<void> {
+ await element.click(options?.clickOptions);
+}
+
export const doubleClick =
async (selector: string, options?: {root?: puppeteer.JSHandle, clickOptions?: puppeteer.ClickOptions}) => {
const passedClickOptions = (options && options.clickOptions) || {};