Skip to content

Commit 622c9fa

Browse files
committed
chore(commands): laid out groundwork for state tracking
1 parent cad18f1 commit 622c9fa

12 files changed

+226
-118
lines changed

src/_internalState.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import {mouseButtonNumbers} from './mouseButtonNumbers'
2+
3+
const mouseButtons = new Set<keyof typeof mouseButtonNumbers>()
4+
5+
function getButtonsMask(): number {
6+
let mask = 0;
7+
if (mouseButtons.has('left')) {
8+
mask |= 1;
9+
}
10+
if (mouseButtons.has('right')) {
11+
mask |= 2;
12+
}
13+
if (mouseButtons.has('middle')) {
14+
mask |= 4;
15+
}
16+
if (mouseButtons.has('back')) {
17+
mask |= 8;
18+
}
19+
if (mouseButtons.has('forward')) {
20+
mask |= 16;
21+
}
22+
return mask;
23+
}
24+
25+
export const InternalState = {
26+
clear() {
27+
mouseButtons.clear()
28+
},
29+
mouseButtonDown(button: keyof typeof mouseButtonNumbers) {
30+
mouseButtons.add(button)
31+
},
32+
mouseButtonUp(button: keyof typeof mouseButtonNumbers) {
33+
mouseButtons.delete(button)
34+
},
35+
getButtonsMask,
36+
}

src/commands/realClick.ts

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
import { fireCdpCommand } from "../fireCdpCommand";
21
import {
32
getCypressElementCoordinates,
43
ScrollBehaviorOptions,
54
Position,
65
} from "../getCypressElementCoordinates";
6+
import { rawMouseDown } from './realMouseDown'
7+
import { rawMouseUp } from './realMouseUp'
8+
import { rawMouseMove } from './realHover'
9+
import { mouseButtonNumbers } from "../mouseButtonNumbers";
710

811
export interface RealClickOptions {
912
/** Pointer type for realClick, if "pen" touch simulated */
1013
pointer?: "mouse" | "pen";
1114
/** The button on mouse that clicked. Simulates real browser behavior. */
12-
button?: "none" | "left" | "right" | "middle" | "back" | "forward";
15+
button?: keyof typeof mouseButtonNumbers;
1316
/**
1417
* Position of the click event relative to the element
1518
* @example cy.realClick({ position: "topLeft" })
@@ -65,25 +68,30 @@ export async function realClick(
6568
});
6669

6770
log.snapshot("before");
68-
await fireCdpCommand("Input.dispatchMouseEvent", {
69-
type: "mousePressed",
70-
x,
71-
y,
72-
clickCount: options.clickCount ?? 1,
73-
buttons: 1,
74-
pointerType: options.pointer ?? "mouse",
75-
button: options.button ?? "left",
76-
});
7771

78-
await fireCdpCommand("Input.dispatchMouseEvent", {
79-
type: "mouseReleased",
72+
await rawMouseMove({
73+
...options,
8074
x,
81-
y,
82-
clickCount: options.clickCount ?? 1,
83-
buttons: 1,
84-
pointerType: options.pointer ?? "mouse",
85-
button: options.button ?? "left",
86-
});
75+
y
76+
})
77+
78+
const { clickCount = 1 } = options
79+
80+
for (let currentClick = 1; currentClick <= clickCount; currentClick++) {
81+
await rawMouseDown({
82+
...options,
83+
x,
84+
y,
85+
clickCount: currentClick
86+
})
87+
88+
await rawMouseUp({
89+
...options,
90+
x,
91+
y,
92+
clickCount: currentClick
93+
})
94+
}
8795

8896
log.snapshot("after").end();
8997

src/commands/realHover.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import {
44
ScrollBehaviorOptions,
55
getCypressElementCoordinates,
66
} from "../getCypressElementCoordinates";
7+
import { InternalState } from "../_internalState";
78

89
export interface RealHoverOptions {
910
/**
1011
* If set to `pen`, simulates touch based hover (via long press)
1112
*/
1213
pointer?: "mouse" | "pen";
13-
/**
14+
/**
1415
* Position relative to the element where to hover the element.
1516
* @example cy.realHover({ position: "topLeft" })
1617
*/
@@ -22,6 +23,25 @@ export interface RealHoverOptions {
2223
scrollBehavior?: ScrollBehaviorOptions;
2324
}
2425

26+
export async function rawMouseMove({
27+
x,
28+
y,
29+
pointer = "mouse",
30+
}: {
31+
x: number,
32+
y: number,
33+
pointer?: "mouse" | "pen",
34+
}) {
35+
await fireCdpCommand("Input.dispatchMouseEvent", {
36+
type: "mouseMoved",
37+
pointerType: pointer,
38+
button: "none",
39+
buttons: InternalState.getButtonsMask(),
40+
x,
41+
y,
42+
});
43+
}
44+
2545
/** @ignore this, update documentation for this function at index.d.ts */
2646
export async function realHover(
2747
subject: JQuery,
@@ -38,13 +58,11 @@ export async function realHover(
3858
}),
3959
});
4060

41-
await fireCdpCommand("Input.dispatchMouseEvent", {
61+
await rawMouseMove({
62+
...options,
4263
x,
4364
y,
44-
type: "mouseMoved",
45-
button: "none",
46-
pointerType: options.pointer ?? "mouse",
47-
});
65+
})
4866

4967
log.snapshot().end();
5068

src/commands/mouseDown.ts renamed to src/commands/realMouseDown.ts

Lines changed: 32 additions & 8 deletions
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 { InternalState } from "../_internalState";
89

910
export interface realMouseDownOptions {
1011
/** Pointer type for realMouseDown, if "pen" touch simulated */
@@ -26,6 +27,32 @@ export interface realMouseDownOptions {
2627
button?: keyof typeof mouseButtonNumbers;
2728
}
2829

30+
export async function rawMouseDown({
31+
x,
32+
y,
33+
button = "left",
34+
pointer = "mouse",
35+
clickCount = 1,
36+
}: {
37+
x: number,
38+
y: number,
39+
button?: keyof typeof mouseButtonNumbers,
40+
pointer?: "mouse" | "pen",
41+
clickCount?: number
42+
}) {
43+
InternalState.mouseButtonUp(button)
44+
45+
await fireCdpCommand("Input.dispatchMouseEvent", {
46+
type: "mousePressed",
47+
clickCount,
48+
buttons: InternalState.getButtonsMask(),
49+
pointerType: pointer,
50+
button,
51+
x,
52+
y,
53+
});
54+
}
55+
2956
/** @ignore this, update documentation for this function at index.d.ts */
3057
export async function realMouseDown(
3158
subject: JQuery,
@@ -43,15 +70,12 @@ export async function realMouseDown(
4370
});
4471

4572
log.snapshot("before");
46-
await fireCdpCommand("Input.dispatchMouseEvent", {
47-
type: "mousePressed",
73+
74+
await rawMouseDown({
75+
...options,
4876
x,
49-
y,
50-
clickCount: 1,
51-
buttons: mouseButtonNumbers[options.button ?? "left"],
52-
pointerType: options.pointer ?? "mouse",
53-
button: options.button ?? "left",
54-
});
77+
y
78+
})
5579

5680
log.snapshot("after").end();
5781

src/commands/mouseUp.ts renamed to src/commands/realMouseUp.ts

Lines changed: 31 additions & 8 deletions
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 { InternalState } from "../_internalState";
89

910
export interface realMouseUpOptions {
1011
/** Pointer type for realMouseUp, if "pen" touch simulated */
@@ -25,6 +26,31 @@ export interface realMouseUpOptions {
2526
button?: keyof typeof mouseButtonNumbers;
2627
}
2728

29+
export async function rawMouseUp({
30+
x,
31+
y,
32+
button = "left",
33+
pointer = "mouse",
34+
clickCount = 1,
35+
}: {
36+
x: number,
37+
y: number,
38+
button?: keyof typeof mouseButtonNumbers,
39+
pointer?: "mouse" | "pen",
40+
clickCount?: number
41+
}) {
42+
InternalState.mouseButtonUp(button)
43+
await fireCdpCommand("Input.dispatchMouseEvent", {
44+
type: "mouseReleased",
45+
clickCount,
46+
buttons: InternalState.getButtonsMask(),
47+
pointerType: pointer,
48+
button,
49+
x,
50+
y
51+
});
52+
}
53+
2854
/** @ignore this, update documentation for this function at index.d.ts */
2955
export async function realMouseUp(
3056
subject: JQuery,
@@ -42,15 +68,12 @@ export async function realMouseUp(
4268
});
4369

4470
log.snapshot("before");
45-
await fireCdpCommand("Input.dispatchMouseEvent", {
46-
type: "mouseReleased",
71+
72+
await rawMouseUp({
73+
...options,
4774
x,
48-
y,
49-
clickCount: 1,
50-
buttons: mouseButtonNumbers[options.button ?? "left"],
51-
pointerType: options.pointer ?? "mouse",
52-
button: options.button ?? "left",
53-
});
75+
y
76+
})
5477

5578
log.snapshot("after").end();
5679

src/commands/realPress.ts

Lines changed: 25 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { fireCdpCommand } from "../fireCdpCommand";
2-
import { keyCodeDefinitions } from "../keyCodeDefinitions";
2+
import { getKeyCodeDefinitions, KeyDefinition, KeyOrShortcut } from "../getKeyCodeDefinitions";
33

44
export interface RealPressOptions {
55
/**
@@ -14,58 +14,15 @@ export interface RealPressOptions {
1414
log?: boolean;
1515
}
1616

17-
function getKeyDefinition(key: keyof typeof keyCodeDefinitions) {
18-
const keyDefinition = keyCodeDefinitions[key];
19-
20-
if (!keyDefinition) {
21-
throw new Error(`Unsupported key '${key}'.`);
22-
}
23-
24-
const keyCode = keyDefinition.keyCode ?? 0;
25-
return {
26-
keyCode: keyCode,
27-
key: keyDefinition?.key ?? "",
28-
text: keyDefinition.key.length === 1 ? keyDefinition.key : undefined,
29-
// @ts-expect-error code exists anyway
30-
code: keyDefinition.code ?? "",
31-
// @ts-expect-error location exists anyway
32-
location: keyDefinition.location ?? 0,
33-
windowsVirtualKeyCode: keyCode,
34-
};
35-
}
36-
3717
const keyToModifierBitMap: Record<string, number> = {
3818
Alt: 1,
3919
Control: 2,
4020
Meta: 4,
4121
Shift: 8,
4222
};
4323

44-
type Key = keyof typeof keyCodeDefinitions;
45-
// unfortunately passing a string like Shift+P is not possible cause typescript template literals can not handle such giant union
46-
type KeyOrShortcut = Key | Array<Key>;
47-
48-
/** @ignore this, update documentation for this function at index.d.ts */
49-
export async function realPress(
50-
keyOrShortcut: KeyOrShortcut,
51-
options: RealPressOptions = {}
52-
) {
53-
let log;
54-
24+
export async function rawRealPress(keyDefinitions: KeyDefinition[], options: RealPressOptions = {}) {
5525
let modifiers = 0;
56-
const keys = Array.isArray(keyOrShortcut) ? keyOrShortcut : [keyOrShortcut];
57-
const keyDefinitions = keys.map(getKeyDefinition);
58-
59-
if (options.log ?? true) {
60-
log = Cypress.log({
61-
name: "realPress",
62-
consoleProps: () => ({
63-
"System Key Definition": keyDefinitions,
64-
}),
65-
});
66-
}
67-
68-
log?.snapshot("before").end();
6926

7027
for (const key of keyDefinitions) {
7128
modifiers |= keyToModifierBitMap[key.key] ?? 0;
@@ -76,14 +33,6 @@ export async function realPress(
7633
...key,
7734
});
7835

79-
if (key.code === "Enter") {
80-
await fireCdpCommand("Input.dispatchKeyEvent", {
81-
type: "char",
82-
unmodifiedText: "\r",
83-
text: "\r",
84-
});
85-
}
86-
8736
await new Promise((res) => setTimeout(res, options.pressDelay ?? 25));
8837
}
8938

@@ -96,6 +45,29 @@ export async function realPress(
9645
});
9746
})
9847
);
48+
}
49+
50+
/** @ignore this, update documentation for this function at index.d.ts */
51+
export async function realPress(
52+
keyOrShortcut: KeyOrShortcut,
53+
options: RealPressOptions = {}
54+
) {
55+
let log;
56+
57+
const keyDefinitions = getKeyCodeDefinitions(keyOrShortcut)
58+
59+
if (options.log ?? true) {
60+
log = Cypress.log({
61+
name: "realPress",
62+
consoleProps: () => ({
63+
"System Key Definition": keyDefinitions,
64+
}),
65+
});
66+
}
67+
68+
log?.snapshot("before").end();
69+
70+
await rawRealPress(keyDefinitions, options)
9971

10072
log?.snapshot("after").end();
10173
}

0 commit comments

Comments
 (0)