fix(recorder): address custom context menus (#31634)

This commit is contained in:
Matt Kleinsmith 2024-07-17 11:45:48 -07:00 committed by GitHub
parent 3cb41739a0
commit e06481a332
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 79 additions and 3 deletions

View file

@ -259,6 +259,28 @@ class RecordActionTool implements RecorderTool {
});
}
onContextMenu(event: MouseEvent) {
// the 'contextmenu' event is triggered by a right-click or equivalent action,
// and it prevents the click event from firing for that action, so we always
// convert 'contextmenu' into a right-click.
if (this._shouldIgnoreMouseEvent(event))
return;
if (this._actionInProgress(event))
return;
if (this._consumedDueToNoModel(event, this._hoveredModel))
return;
this._performAction({
name: 'click',
selector: this._hoveredModel!.selector,
position: positionForEvent(event),
signals: [],
button: 'right',
modifiers: 0,
clickCount: 0
});
}
onPointerDown(event: PointerEvent) {
if (this._shouldIgnoreMouseEvent(event))
return;

View file

@ -559,6 +559,60 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`);
]);
});
test('should consume contextmenu events, despite a custom context menu', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
await recorder.setContentAndWait(`
<button>Right click me.</button>
<div id="menu" style="display: none; position: absolute;">
<button>Menu option 1</button>
<button>Menu option 2</button>
</div>
<script>
const button = document.querySelector('button');
button.addEventListener('contextmenu', e => {
e.preventDefault();
console.log('right-clicked');
// show custom context menu
const menu = document.getElementById("menu");
menu.style.display = "block";
menu.style.left = \`\${e.pageX}px\`;
menu.style.top = \`\${e.pageY}px\`;
});
const log = [];
for (const eventName of ['mousedown', 'mousemove', 'mouseup', 'pointerdown', 'pointermove', 'pointerup', 'click', 'contextmenu']) {
button.addEventListener(eventName, e => log.push('button: ' + e.type));
menu.addEventListener(eventName, e => log.push('menu: ' + e.type));
}
</script>
`);
await recorder.hoverOverElement('button');
expect(await page.evaluate('log')).toEqual(['button: pointermove', 'button: mousemove']);
const [message] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('JavaScript', `button: 'right'`),
recorder.trustedClick({ button: 'right' }),
]);
expect(message.text()).toBe('right-clicked');
expect(await page.evaluate('log')).toEqual([
// hover
'button: pointermove',
'button: mousemove',
// trusted right click
'button: pointerup',
'button: pointermove',
'button: mousemove',
'button: pointerdown',
'button: mousedown',
'button: contextmenu',
'menu: pointerup',
'menu: mouseup'
]);
});
test('should assert value', async ({ openRecorder }) => {
const recorder = await openRecorder();

View file

@ -186,9 +186,9 @@ class Recorder {
await this.page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
}
async trustedClick() {
await this.page.mouse.down();
await this.page.mouse.up();
async trustedClick(options?: { button?: 'left' | 'right' | 'middle' }) {
await this.page.mouse.down(options);
await this.page.mouse.up(options);
}
async focusElement(selector: string): Promise<string> {