Skip to content

Commit 98625af

Browse files
feat: Add shiftKey modifier to keyboard events (#514)
* add shiftKey option to some events * add test cases * revert unrelated formatting changes * add shiftKey option for mouseUp event * one more formatting revert --------- Co-authored-by: Dmitriy <[email protected]>
1 parent d96a23a commit 98625af

File tree

9 files changed

+120
-8
lines changed

9 files changed

+120
-8
lines changed

cypress/e2e/modifiers.cy.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
describe("Events behavior with shiftKey modifier applied", () => {
2+
beforeEach(() => {
3+
cy.visit("./cypress/fixtures/modifiers-test.html");
4+
});
5+
6+
it("detects shift key modifier on click", () => {
7+
cy.get("#action-button").realClick({ shiftKey: true });
8+
cy.contains("Shift key was pressed");
9+
});
10+
11+
it("detects shift key modifier on hover", () => {
12+
cy.get("#mouse-move-div").realHover({ shiftKey: true });
13+
cy.contains("Shift key was pressed");
14+
});
15+
16+
it("detects shift key modifier on mousedown", () => {
17+
cy.get("#mouse-down-div").realMouseDown({ shiftKey: true });
18+
cy.contains("Shift key was pressed");
19+
});
20+
21+
it("detects shift key modifier on mpuseup", () => {
22+
cy.get("#mouse-up-div").realMouseUp({ shiftKey: true });
23+
cy.contains("Shift key was pressed");
24+
});
25+
26+
it("detects shift key modifier on mousemove", () => {
27+
cy.get("#mouse-move-div").realMouseMove(100, 50, { shiftKey: true });
28+
cy.contains("Shift key was pressed");
29+
});
30+
});

cypress/fixtures/modifiers-test.html

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<body>
4+
<button id="action-button">Click on me with shift pressed</button>
5+
<hr />
6+
<div id="mouse-move-div">Hover/mousemove over me with shift pressed</div>
7+
<hr />
8+
<div id="mouse-down-div">Initiate mouse down with shift pressed</div>
9+
<hr />
10+
<div id="mouse-up-div">Initiate mouse up with shift pressed</div>
11+
<hr />
12+
13+
<p id="result"></p>
14+
</body>
15+
<script>
16+
const resultBox = document.getElementById("result");
17+
18+
function commonHandler(e) {
19+
resultBox.innerHTML = "";
20+
if (e.shiftKey) resultBox.innerHTML = "Shift key was pressed";
21+
}
22+
23+
document
24+
.getElementById("action-button")
25+
.addEventListener("click", commonHandler);
26+
27+
document
28+
.getElementById("mouse-move-div")
29+
.addEventListener("mousemove", commonHandler);
30+
31+
document
32+
.getElementById("mouse-down-div")
33+
.addEventListener("mousedown", commonHandler);
34+
35+
document
36+
.getElementById("mouse-up-div")
37+
.addEventListener("mouseup", commonHandler);
38+
</script>
39+
<style>
40+
div {
41+
width: 100%;
42+
height: 100px;
43+
background-color: aqua;
44+
}
45+
</style>
46+
</html>

src/commands/mouseDown.ts

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
Position,
66
} from "../getCypressElementCoordinates";
77
import { mouseButtonNumbers } from "../mouseButtonNumbers";
8+
import { keyToModifierBitMap } from "../keyToModifierBitMap";
89

910
export interface realMouseDownOptions {
1011
/** Pointer type for realMouseDown, if "pen" touch simulated */
@@ -24,6 +25,11 @@ export interface realMouseDownOptions {
2425
* @default "left"
2526
*/
2627
button?: keyof typeof mouseButtonNumbers;
28+
/**
29+
* Indicates whether the shift key was pressed or not when an event occurred
30+
* @example cy.realMouseDown({ shiftKey: true });
31+
*/
32+
shiftKey?: boolean;
2733
}
2834

2935
/** @ignore this, update documentation for this function at index.d.ts */
@@ -51,6 +57,7 @@ export async function realMouseDown(
5157
buttons: mouseButtonNumbers[options.button ?? "left"],
5258
pointerType: options.pointer ?? "mouse",
5359
button: options.button ?? "left",
60+
modifiers: options.shiftKey ? keyToModifierBitMap.Shift : 0,
5461
});
5562

5663
log.snapshot("after").end();

src/commands/mouseMove.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Position,
55
ScrollBehaviorOptions,
66
} from "../getCypressElementCoordinates";
7+
import { keyToModifierBitMap } from "../keyToModifierBitMap";
78

89
export interface RealMouseMoveOptions {
910
/**
@@ -14,9 +15,14 @@ export interface RealMouseMoveOptions {
1415
position?: Position;
1516
/**
1617
* Controls how the page is scrolled to bring the subject into view, if needed.
17-
* @example cy.realClick({ scrollBehavior: "top" });
18+
* @example cy.realMouseMove({ scrollBehavior: "top" });
1819
*/
1920
scrollBehavior?: ScrollBehaviorOptions;
21+
/**
22+
* Indicates whether the shift key was pressed or not when an event occurred
23+
* @example cy.realMouseMove({ shiftKey: true });
24+
*/
25+
shiftKey?: boolean;
2026
}
2127

2228
/** @ignore this, update documentation for this function at index.d.ts */
@@ -46,6 +52,7 @@ export async function realMouseMove(
4652
type: "mouseMoved",
4753
x: x * basePosition.frameScale + basePosition.x,
4854
y: y * basePosition.frameScale + basePosition.y,
55+
modifiers: options.shiftKey ? keyToModifierBitMap.Shift : 0,
4956
});
5057

5158
log.snapshot("after").end();

src/commands/mouseUp.ts

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
Position,
66
} from "../getCypressElementCoordinates";
77
import { mouseButtonNumbers } from "../mouseButtonNumbers";
8+
import { keyToModifierBitMap } from "../keyToModifierBitMap";
89

910
export interface realMouseUpOptions {
1011
/** Pointer type for realMouseUp, if "pen" touch simulated */
@@ -23,6 +24,11 @@ export interface realMouseUpOptions {
2324
* @default "left"
2425
*/
2526
button?: keyof typeof mouseButtonNumbers;
27+
/**
28+
* Indicates whether the shift key was pressed or not when an event occurred
29+
* @example cy.realMouseUp({ shiftKey: true });
30+
*/
31+
shiftKey?: boolean;
2632
}
2733

2834
/** @ignore this, update documentation for this function at index.d.ts */
@@ -50,6 +56,7 @@ export async function realMouseUp(
5056
buttons: mouseButtonNumbers[options.button ?? "left"],
5157
pointerType: options.pointer ?? "mouse",
5258
button: options.button ?? "left",
59+
modifiers: options.shiftKey ? keyToModifierBitMap.Shift : 0,
5360
});
5461

5562
log.snapshot("after").end();

src/commands/realClick.ts

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
Position,
66
} from "../getCypressElementCoordinates";
77
import { mouseButtonNumbers } from "../mouseButtonNumbers";
8+
import { keyToModifierBitMap } from "../keyToModifierBitMap";
89

910
export interface RealClickOptions {
1011
/** Pointer type for realClick, if "pen" touch simulated */
@@ -38,6 +39,11 @@ export interface RealClickOptions {
3839
* @example cy.realClick({ clickCount: 2 });
3940
*/
4041
clickCount?: number;
42+
/**
43+
* Indicates whether the shift key was pressed or not when an event occurred
44+
* @example cy.realClick({ shiftKey: true });
45+
*/
46+
shiftKey?: boolean;
4147
}
4248

4349
/** @ignore this, update documentation for this function at index.d.ts */
@@ -78,6 +84,7 @@ export async function realClick(
7884
buttons: mouseButtonNumbers[options.button ?? "left"],
7985
pointerType: options.pointer ?? "mouse",
8086
button: options.button ?? "left",
87+
modifiers: options.shiftKey ? keyToModifierBitMap.Shift : 0,
8188
});
8289

8390
await fireCdpCommand("Input.dispatchMouseEvent", {
@@ -88,6 +95,7 @@ export async function realClick(
8895
buttons: mouseButtonNumbers[options.button ?? "left"],
8996
pointerType: options.pointer ?? "mouse",
9097
button: options.button ?? "left",
98+
modifiers: options.shiftKey ? keyToModifierBitMap.Shift : 0,
9199
});
92100
}
93101

src/commands/realHover.ts

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
ScrollBehaviorOptions,
55
getCypressElementCoordinates,
66
} from "../getCypressElementCoordinates";
7+
import { keyToModifierBitMap } from "../keyToModifierBitMap";
78

89
export interface RealHoverOptions {
910
/**
@@ -20,6 +21,11 @@ export interface RealHoverOptions {
2021
* @example cy.realHover({ scrollBehavior: "top" });
2122
*/
2223
scrollBehavior?: ScrollBehaviorOptions;
24+
/**
25+
* Indicates whether the shift key was pressed or not when an event occurred
26+
* @example cy.realHover({ shiftKey: true });
27+
*/
28+
shiftKey?: boolean;
2329
}
2430

2531
/** @ignore this, update documentation for this function at index.d.ts */
@@ -44,6 +50,7 @@ export async function realHover(
4450
type: "mouseMoved",
4551
button: "none",
4652
pointerType: options.pointer ?? "mouse",
53+
modifiers: options.shiftKey ? keyToModifierBitMap.Shift : 0,
4754
});
4855

4956
log.snapshot().end();

src/commands/realPress.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { fireCdpCommand } from "../fireCdpCommand";
22
import { keyCodeDefinitions } from "../keyCodeDefinitions";
3+
import { keyToModifierBitMap } from "../keyToModifierBitMap";
34

45
export interface RealPressOptions {
56
/**
@@ -34,13 +35,6 @@ function getKeyDefinition(key: keyof typeof keyCodeDefinitions) {
3435
};
3536
}
3637

37-
const keyToModifierBitMap: Record<string, number> = {
38-
Alt: 1,
39-
Control: 2,
40-
Meta: 4,
41-
Shift: 8,
42-
};
43-
4438
type Key = keyof typeof keyCodeDefinitions;
4539
// unfortunately passing a string like Shift+P is not possible cause typescript template literals can not handle such giant union
4640
type KeyOrShortcut = Key | Array<Key>;

src/keyToModifierBitMap.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const keyToModifierBitMap: Record<string, number> = {
2+
Alt: 1,
3+
Control: 2,
4+
Meta: 4,
5+
Shift: 8,
6+
};

0 commit comments

Comments
 (0)