Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/injected/src/recorder/recorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class InspectTool implements RecorderTool {
}

onClick(event: MouseEvent) {
// Shift+click bypasses locator picking and interacts with the page.
if (event.shiftKey)
return;
consumeEvent(event);
if (event.button !== 0)
return;
Expand All @@ -97,22 +100,34 @@ class InspectTool implements RecorderTool {
}

onPointerDown(event: PointerEvent) {
if (event.shiftKey)
return;
consumeEvent(event);
}

onPointerUp(event: PointerEvent) {
if (event.shiftKey)
return;
consumeEvent(event);
}

onMouseDown(event: MouseEvent) {
if (event.shiftKey)
return;
consumeEvent(event);
}

onMouseUp(event: MouseEvent) {
if (event.shiftKey)
return;
consumeEvent(event);
}

onMouseMove(event: MouseEvent) {
if (event.shiftKey) {
this._reset(false);
return;
}
consumeEvent(event);
let target: HTMLElement | null = this._recorder.deepEventTarget(event);
if (!target.isConnected)
Expand All @@ -139,6 +154,8 @@ class InspectTool implements RecorderTool {
}

onMouseEnter(event: MouseEvent) {
if (event.shiftKey)
return;
consumeEvent(event);
}

Expand All @@ -152,6 +169,10 @@ class InspectTool implements RecorderTool {

onKeyDown(event: KeyboardEvent) {
consumeEvent(event);
if (event.key === 'Shift') {
this._reset(false);
return;
}
if (event.key === 'Escape') {
if (this._assertVisibility)
this._recorder.setMode('recording');
Expand Down
30 changes: 30 additions & 0 deletions tests/library/inspector/cli-codegen-pick-locator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,36 @@ test.describe(() => {
`);
});

test('should shift-click to interact with page while picking locator', async ({ openRecorder }) => {
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`
<button onclick="document.getElementById('target').textContent = 'clicked'">Click me</button>
<div id="target">initial</div>
`);

// Enter pick locator mode.
await recorder.page.click('x-pw-tool-item.pick-locator');

// Shift+click the button - should interact with the page, not pick a locator.
const button = recorder.page.getByRole('button', { name: 'Click me' });
await recorder.trustedMove(button);
await recorder.page.keyboard.down('Shift');
await recorder.trustedClick();
await recorder.page.keyboard.up('Shift');

// Verify the page interaction happened.
await expect(recorder.page.locator('#target')).toHaveText('clicked');

// Now click without Shift - should pick the locator.
const target = recorder.page.locator('#target');
await recorder.trustedMove(target);
await recorder.trustedClick();
await recorder.recorderPage.getByRole('tab', { name: 'Locator' }).click();
await expect(recorder.recorderPage.locator('.tab-locator .CodeMirror')).toMatchAriaSnapshot(`
- text: "getByText('clicked')"
`);
});

test('should update locator highlight', async ({ openRecorder }) => {
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`<main>
Expand Down