@web/test-runner-commands 0.5.11 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@ import {
8
8
  RemoveFilePayload,
9
9
  SnapshotPluginConfig,
10
10
  SaveSnapshotPayload,
11
+ SendMousePayload,
11
12
  } from '../dist/index';
12
13
 
13
14
  /**
@@ -74,6 +75,63 @@ export function setUserAgent(userAgent: string): Promise<void>;
74
75
  **/
75
76
  export function sendKeys(payload: SendKeysPayload): Promise<void>;
76
77
 
78
+ /**
79
+ * Sends an action for the mouse to move it to a specific position or click a mouse button (left, middle, or right).
80
+ *
81
+ * WARNING: When moving the mouse or holding down a mouse button, the mouse stays in this state as long as
82
+ * you do not explicitly move it to another position or release the button. For this reason, it is recommended
83
+ * to reset the mouse state with the `resetMouse` command after each test case manipulating the mouse to avoid
84
+ * unexpected side effects.
85
+ *
86
+ * @param payload An object representing a mouse action specified by the `type` property (move, click, down, up)
87
+ * and including some properties to configure this action.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * await sendMouse({
92
+ * type: 'move',
93
+ * position: [100, 100]
94
+ * });
95
+ * ```
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * await sendMouse({
100
+ * type: 'click',
101
+ * position: [100, 100],
102
+ * button: 'right'
103
+ * });
104
+ * ```
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * await sendMouse({
109
+ * type: 'down'
110
+ * });
111
+ * ```
112
+ *
113
+ **/
114
+ export function sendMouse(payload: SendMousePayload): Promise<void>;
115
+
116
+ /**
117
+ * Resets the mouse position to (0, 0) and releases mouse buttons.
118
+ *
119
+ * Use this command to reset the mouse state after mouse manipulations by the `sendMouse` command.
120
+ *
121
+ * @example
122
+ * ```
123
+ * it('does something with the mouse', () => {
124
+ * await sendMouse({ type: 'move', position: [150, 150] });
125
+ * await sendMouse({ type: 'down', button: 'middle' });
126
+ * });
127
+ *
128
+ * afterEach(() => {
129
+ * await resetMouse();
130
+ * });
131
+ * ```
132
+ */
133
+ export function resetMouse(): Promise<void>;
134
+
77
135
  /**
78
136
  * Request a snapshot of the Accessibility Tree of the entire page or starting from
79
137
  * the element that is obtained via the `selector` property of the `payload` argument.
@@ -155,7 +213,7 @@ export function writeFile(payload: WriteFilePayload): Promise<void>;
155
213
  * const content = await readFile({ path: 'hello-world.txt' });
156
214
  * ```
157
215
  */
158
- export function readFile(payload: WriteFilePayload): Promise<string | undefined>;
216
+ export function readFile(payload: ReadFilePayload): Promise<string | undefined>;
159
217
 
160
218
  /**
161
219
  * Removes a file from disk.
@@ -69,6 +69,14 @@ export function sendKeys(options) {
69
69
  return executeServerCommand('send-keys', options);
70
70
  }
71
71
 
72
+ export function sendMouse(options) {
73
+ return executeServerCommand('send-mouse', options);
74
+ }
75
+
76
+ export function resetMouse(options) {
77
+ return executeServerCommand('reset-mouse', options);
78
+ }
79
+
72
80
  export function a11ySnapshot(options) {
73
81
  return executeServerCommand('a11y-snapshot', options);
74
82
  }
@@ -123,7 +131,7 @@ const ESCAPE_REGEX = /snapshots\[[^\]]+] = (\n)?(?<content>`[^`]*`)/gm;
123
131
 
124
132
  const escapeContent = content => {
125
133
  [...content.matchAll(ESCAPE_REGEX)].forEach(({ groups: { content: itemContent } }) => {
126
- content = content.replaceAll(itemContent, itemContent.replaceAll(/\n/g, '\\n'));
134
+ content = content.replaceAll(itemContent, encodeURIComponent(itemContent));
127
135
  });
128
136
 
129
137
  return content;
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { Viewport, setViewportPlugin } from './setViewportPlugin';
2
2
  export { Media, emulateMediaPlugin } from './emulateMediaPlugin';
3
3
  export { setUserAgentPlugin } from './setUserAgentPlugin';
4
4
  export { sendKeysPlugin, SendKeysPayload } from './sendKeysPlugin';
5
+ export { sendMousePlugin, SendMousePayload } from './sendMousePlugin';
5
6
  export { a11ySnapshotPlugin, A11ySnapshotPayload } from './a11ySnapshotPlugin';
6
7
  export { WriteFilePayload, ReadFilePayload, RemoveFilePayload, filePlugin } from './filePlugin';
7
8
  export { SaveSnapshotPayload, SnapshotPluginConfig, snapshotPlugin } from './snapshotPlugin';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.snapshotPlugin = exports.filePlugin = exports.a11ySnapshotPlugin = exports.sendKeysPlugin = exports.setUserAgentPlugin = exports.emulateMediaPlugin = exports.setViewportPlugin = void 0;
3
+ exports.snapshotPlugin = exports.filePlugin = exports.a11ySnapshotPlugin = exports.sendMousePlugin = exports.sendKeysPlugin = exports.setUserAgentPlugin = exports.emulateMediaPlugin = exports.setViewportPlugin = void 0;
4
4
  var setViewportPlugin_1 = require("./setViewportPlugin");
5
5
  Object.defineProperty(exports, "setViewportPlugin", { enumerable: true, get: function () { return setViewportPlugin_1.setViewportPlugin; } });
6
6
  var emulateMediaPlugin_1 = require("./emulateMediaPlugin");
@@ -9,6 +9,8 @@ var setUserAgentPlugin_1 = require("./setUserAgentPlugin");
9
9
  Object.defineProperty(exports, "setUserAgentPlugin", { enumerable: true, get: function () { return setUserAgentPlugin_1.setUserAgentPlugin; } });
10
10
  var sendKeysPlugin_1 = require("./sendKeysPlugin");
11
11
  Object.defineProperty(exports, "sendKeysPlugin", { enumerable: true, get: function () { return sendKeysPlugin_1.sendKeysPlugin; } });
12
+ var sendMousePlugin_1 = require("./sendMousePlugin");
13
+ Object.defineProperty(exports, "sendMousePlugin", { enumerable: true, get: function () { return sendMousePlugin_1.sendMousePlugin; } });
12
14
  var a11ySnapshotPlugin_1 = require("./a11ySnapshotPlugin");
13
15
  Object.defineProperty(exports, "a11ySnapshotPlugin", { enumerable: true, get: function () { return a11ySnapshotPlugin_1.a11ySnapshotPlugin; } });
14
16
  var filePlugin_1 = require("./filePlugin");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAAkE;AAA/C,sHAAA,iBAAiB,OAAA;AACpC,2DAAiE;AAAjD,wHAAA,kBAAkB,OAAA;AAClC,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA;AAC3B,mDAAmE;AAA1D,gHAAA,cAAc,OAAA;AACvB,2DAA+E;AAAtE,wHAAA,kBAAkB,OAAA;AAC3B,2CAAgG;AAAjC,wGAAA,UAAU,OAAA;AACzE,mDAA6F;AAAzC,gHAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAAkE;AAA/C,sHAAA,iBAAiB,OAAA;AACpC,2DAAiE;AAAjD,wHAAA,kBAAkB,OAAA;AAClC,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA;AAC3B,mDAAmE;AAA1D,gHAAA,cAAc,OAAA;AACvB,qDAAsE;AAA7D,kHAAA,eAAe,OAAA;AACxB,2DAA+E;AAAtE,wHAAA,kBAAkB,OAAA;AAC3B,2CAAgG;AAAjC,wGAAA,UAAU,OAAA;AACzE,mDAA6F;AAAzC,gHAAA,cAAc,OAAA"}
@@ -0,0 +1,24 @@
1
+ import { TestRunnerPlugin } from '@web/test-runner-core';
2
+ declare type MousePosition = [number, number];
3
+ declare type MouseButton = 'left' | 'middle' | 'right';
4
+ export declare type SendMousePayload = MovePayload | ClickPayload | DownPayload | UpPayload;
5
+ export declare type MovePayload = {
6
+ type: 'move';
7
+ position: MousePosition;
8
+ };
9
+ export declare type ClickPayload = {
10
+ type: 'click';
11
+ position: MousePosition;
12
+ button?: MouseButton;
13
+ };
14
+ export declare type DownPayload = {
15
+ type: 'down';
16
+ button?: MouseButton;
17
+ };
18
+ export declare type UpPayload = {
19
+ type: 'up';
20
+ button?: MouseButton;
21
+ };
22
+ export declare function sendMousePlugin(): TestRunnerPlugin<SendMousePayload>;
23
+ export {};
24
+ //# sourceMappingURL=sendMousePlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sendMousePlugin.d.ts","sourceRoot":"","sources":["../src/sendMousePlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAKzD,aAAK,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,aAAK,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/C,oBAAY,gBAAgB,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;AAEpF,oBAAY,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,aAAa,CAAC;CACzB,CAAC;AAEF,oBAAY,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,oBAAY,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,oBAAY,SAAS,GAAG;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AA+CF,wBAAgB,eAAe,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,CAkHpE"}
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendMousePlugin = void 0;
4
+ function isObject(payload) {
5
+ return payload != null && typeof payload === 'object';
6
+ }
7
+ function isSendMousePayload(payload) {
8
+ const validTypes = ['move', 'click', 'down', 'up'];
9
+ const validButtons = ['left', 'middle', 'right'];
10
+ if (!isObject(payload)) {
11
+ throw new Error('You must provide a `SendMousePayload` object');
12
+ }
13
+ if (typeof payload.type !== 'string' || !validTypes.includes(payload.type)) {
14
+ throw new Error(`You must provide a type option with one of the following values: ${validTypes.join(', ')}.`);
15
+ }
16
+ if (['click', 'move'].includes(payload.type)) {
17
+ if (!Array.isArray(payload.position) ||
18
+ typeof payload.position[0] !== 'number' ||
19
+ typeof payload.position[1] !== 'number' ||
20
+ !Number.isInteger(payload.position[0]) ||
21
+ !Number.isInteger(payload.position[1])) {
22
+ throw new Error('You must provide a position option as a [x, y] tuple where x and y are integers.');
23
+ }
24
+ }
25
+ if (['click', 'up', 'down'].includes(payload.type)) {
26
+ if (typeof payload.button === 'string' && !validButtons.includes(payload.button)) {
27
+ throw new Error(`The button option must be one of the following values when provided: ${validButtons.join(', ')}.`);
28
+ }
29
+ }
30
+ return true;
31
+ }
32
+ function sendMousePlugin() {
33
+ return {
34
+ name: 'send-mouse-command',
35
+ async executeCommand({ command, payload, session }) {
36
+ if (command === 'send-mouse') {
37
+ if (!payload || !isSendMousePayload(payload)) {
38
+ throw new Error('You must provide a `SendMousePayload` object');
39
+ }
40
+ // handle specific behavior for playwright
41
+ if (session.browser.type === 'playwright') {
42
+ const page = session.browser.getPage(session.id);
43
+ switch (payload.type) {
44
+ case 'move':
45
+ await page.mouse.move(payload.position[0], payload.position[1]);
46
+ return true;
47
+ case 'click':
48
+ await page.mouse.click(payload.position[0], payload.position[1], {
49
+ button: payload.button,
50
+ });
51
+ return true;
52
+ case 'down':
53
+ await page.mouse.down({ button: payload.button });
54
+ return true;
55
+ case 'up':
56
+ await page.mouse.up({ button: payload.button });
57
+ return true;
58
+ }
59
+ }
60
+ // handle specific behavior for puppeteer
61
+ if (session.browser.type === 'puppeteer') {
62
+ const page = session.browser.getPage(session.id);
63
+ switch (payload.type) {
64
+ case 'move':
65
+ await page.mouse.move(payload.position[0], payload.position[1]);
66
+ return true;
67
+ case 'click':
68
+ await page.mouse.click(payload.position[0], payload.position[1], {
69
+ button: payload.button,
70
+ });
71
+ return true;
72
+ case 'down':
73
+ await page.mouse.down({ button: payload.button });
74
+ return true;
75
+ case 'up':
76
+ await page.mouse.up({ button: payload.button });
77
+ return true;
78
+ }
79
+ }
80
+ // handle specific behavior for webdriver
81
+ if (session.browser.type === 'webdriver') {
82
+ const page = session.browser;
83
+ switch (payload.type) {
84
+ case 'move':
85
+ await page.sendMouseMove(session.id, payload.position[0], payload.position[1]);
86
+ return true;
87
+ case 'click':
88
+ await page.sendMouseClick(session.id, payload.position[0], payload.position[1], payload.button);
89
+ return true;
90
+ case 'down':
91
+ await page.sendMouseDown(session.id, payload.button);
92
+ return true;
93
+ case 'up':
94
+ await page.sendMouseUp(session.id, payload.button);
95
+ return true;
96
+ }
97
+ }
98
+ // you might not be able to support all browser launchers
99
+ throw new Error(`Sending mouse is not supported for browser type ${session.browser.type}.`);
100
+ }
101
+ if (command === 'reset-mouse') {
102
+ // handle specific behavior for playwright
103
+ if (session.browser.type === 'playwright') {
104
+ const page = session.browser.getPage(session.id);
105
+ await page.mouse.up({ button: 'left' });
106
+ await page.mouse.up({ button: 'middle' });
107
+ await page.mouse.up({ button: 'right' });
108
+ await page.mouse.move(0, 0);
109
+ return true;
110
+ }
111
+ // handle specific behavior for puppeteer
112
+ if (session.browser.type === 'puppeteer') {
113
+ const page = session.browser.getPage(session.id);
114
+ await page.mouse.up({ button: 'left' });
115
+ await page.mouse.up({ button: 'middle' });
116
+ await page.mouse.up({ button: 'right' });
117
+ await page.mouse.move(0, 0);
118
+ return true;
119
+ }
120
+ // handle specific behavior for webdriver
121
+ if (session.browser.type === 'webdriver') {
122
+ const page = session.browser;
123
+ await page.resetMouse(session.id);
124
+ return true;
125
+ }
126
+ // you might not be able to support all browser launchers
127
+ throw new Error(`Resetting mouse is not supported for browser type ${session.browser.type}.`);
128
+ }
129
+ },
130
+ };
131
+ }
132
+ exports.sendMousePlugin = sendMousePlugin;
133
+ //# sourceMappingURL=sendMousePlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sendMousePlugin.js","sourceRoot":"","sources":["../src/sendMousePlugin.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@web/test-runner-commands",
3
- "version": "0.5.11",
3
+ "version": "0.6.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -51,7 +51,7 @@
51
51
  "devDependencies": {
52
52
  "@web/test-runner-chrome": "^0.10.2",
53
53
  "@web/test-runner-playwright": "^0.8.8",
54
- "@web/test-runner-webdriver": "^0.4.2",
54
+ "@web/test-runner-webdriver": "^0.5.0",
55
55
  "mocha": "^8.2.1"
56
56
  }
57
57
  }
package/plugins.mjs CHANGED
@@ -6,6 +6,7 @@ const {
6
6
  emulateMediaPlugin,
7
7
  setUserAgentPlugin,
8
8
  sendKeysPlugin,
9
+ sendMousePlugin,
9
10
  a11ySnapshotPlugin,
10
11
  filePlugin,
11
12
  snapshotPlugin,
@@ -16,6 +17,7 @@ export {
16
17
  emulateMediaPlugin,
17
18
  setUserAgentPlugin,
18
19
  sendKeysPlugin,
20
+ sendMousePlugin,
19
21
  a11ySnapshotPlugin,
20
22
  filePlugin,
21
23
  snapshotPlugin,
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export { Viewport, setViewportPlugin } from './setViewportPlugin';
2
2
  export { Media, emulateMediaPlugin } from './emulateMediaPlugin';
3
3
  export { setUserAgentPlugin } from './setUserAgentPlugin';
4
4
  export { sendKeysPlugin, SendKeysPayload } from './sendKeysPlugin';
5
+ export { sendMousePlugin, SendMousePayload } from './sendMousePlugin';
5
6
  export { a11ySnapshotPlugin, A11ySnapshotPayload } from './a11ySnapshotPlugin';
6
7
  export { WriteFilePayload, ReadFilePayload, RemoveFilePayload, filePlugin } from './filePlugin';
7
8
  export { SaveSnapshotPayload, SnapshotPluginConfig, snapshotPlugin } from './snapshotPlugin';
@@ -0,0 +1,191 @@
1
+ import { TestRunnerPlugin } from '@web/test-runner-core';
2
+ import type { ChromeLauncher } from '@web/test-runner-chrome';
3
+ import type { PlaywrightLauncher } from '@web/test-runner-playwright';
4
+ import type { WebdriverLauncher } from '@web/test-runner-webdriver';
5
+
6
+ type MousePosition = [number, number];
7
+ type MouseButton = 'left' | 'middle' | 'right';
8
+
9
+ export type SendMousePayload = MovePayload | ClickPayload | DownPayload | UpPayload;
10
+
11
+ export type MovePayload = {
12
+ type: 'move';
13
+ position: MousePosition;
14
+ };
15
+
16
+ export type ClickPayload = {
17
+ type: 'click';
18
+ position: MousePosition;
19
+ button?: MouseButton;
20
+ };
21
+
22
+ export type DownPayload = {
23
+ type: 'down';
24
+ button?: MouseButton;
25
+ };
26
+
27
+ export type UpPayload = {
28
+ type: 'up';
29
+ button?: MouseButton;
30
+ };
31
+
32
+ function isObject(payload: unknown): payload is Record<string, unknown> {
33
+ return payload != null && typeof payload === 'object';
34
+ }
35
+
36
+ function isSendMousePayload(payload: unknown): payload is SendMousePayload {
37
+ const validTypes = ['move', 'click', 'down', 'up'];
38
+ const validButtons = ['left', 'middle', 'right'];
39
+
40
+ if (!isObject(payload)) {
41
+ throw new Error('You must provide a `SendMousePayload` object');
42
+ }
43
+
44
+ if (typeof payload.type !== 'string' || !validTypes.includes(payload.type)) {
45
+ throw new Error(
46
+ `You must provide a type option with one of the following values: ${validTypes.join(', ')}.`,
47
+ );
48
+ }
49
+
50
+ if (['click', 'move'].includes(payload.type)) {
51
+ if (
52
+ !Array.isArray(payload.position) ||
53
+ typeof payload.position[0] !== 'number' ||
54
+ typeof payload.position[1] !== 'number' ||
55
+ !Number.isInteger(payload.position[0]) ||
56
+ !Number.isInteger(payload.position[1])
57
+ ) {
58
+ throw new Error(
59
+ 'You must provide a position option as a [x, y] tuple where x and y are integers.',
60
+ );
61
+ }
62
+ }
63
+
64
+ if (['click', 'up', 'down'].includes(payload.type)) {
65
+ if (typeof payload.button === 'string' && !validButtons.includes(payload.button)) {
66
+ throw new Error(
67
+ `The button option must be one of the following values when provided: ${validButtons.join(
68
+ ', ',
69
+ )}.`,
70
+ );
71
+ }
72
+ }
73
+
74
+ return true;
75
+ }
76
+
77
+ export function sendMousePlugin(): TestRunnerPlugin<SendMousePayload> {
78
+ return {
79
+ name: 'send-mouse-command',
80
+ async executeCommand({ command, payload, session }): Promise<any> {
81
+ if (command === 'send-mouse') {
82
+ if (!payload || !isSendMousePayload(payload)) {
83
+ throw new Error('You must provide a `SendMousePayload` object');
84
+ }
85
+
86
+ // handle specific behavior for playwright
87
+ if (session.browser.type === 'playwright') {
88
+ const page = (session.browser as PlaywrightLauncher).getPage(session.id);
89
+ switch (payload.type) {
90
+ case 'move':
91
+ await page.mouse.move(payload.position[0], payload.position[1]);
92
+ return true;
93
+ case 'click':
94
+ await page.mouse.click(payload.position[0], payload.position[1], {
95
+ button: payload.button,
96
+ });
97
+ return true;
98
+ case 'down':
99
+ await page.mouse.down({ button: payload.button });
100
+ return true;
101
+ case 'up':
102
+ await page.mouse.up({ button: payload.button });
103
+ return true;
104
+ }
105
+ }
106
+
107
+ // handle specific behavior for puppeteer
108
+ if (session.browser.type === 'puppeteer') {
109
+ const page = (session.browser as ChromeLauncher).getPage(session.id);
110
+ switch (payload.type) {
111
+ case 'move':
112
+ await page.mouse.move(payload.position[0], payload.position[1]);
113
+ return true;
114
+ case 'click':
115
+ await page.mouse.click(payload.position[0], payload.position[1], {
116
+ button: payload.button,
117
+ });
118
+ return true;
119
+ case 'down':
120
+ await page.mouse.down({ button: payload.button });
121
+ return true;
122
+ case 'up':
123
+ await page.mouse.up({ button: payload.button });
124
+ return true;
125
+ }
126
+ }
127
+
128
+ // handle specific behavior for webdriver
129
+ if (session.browser.type === 'webdriver') {
130
+ const page = session.browser as WebdriverLauncher;
131
+ switch (payload.type) {
132
+ case 'move':
133
+ await page.sendMouseMove(session.id, payload.position[0], payload.position[1]);
134
+ return true;
135
+ case 'click':
136
+ await page.sendMouseClick(
137
+ session.id,
138
+ payload.position[0],
139
+ payload.position[1],
140
+ payload.button,
141
+ );
142
+ return true;
143
+ case 'down':
144
+ await page.sendMouseDown(session.id, payload.button);
145
+ return true;
146
+ case 'up':
147
+ await page.sendMouseUp(session.id, payload.button);
148
+ return true;
149
+ }
150
+ }
151
+
152
+ // you might not be able to support all browser launchers
153
+ throw new Error(`Sending mouse is not supported for browser type ${session.browser.type}.`);
154
+ }
155
+
156
+ if (command === 'reset-mouse') {
157
+ // handle specific behavior for playwright
158
+ if (session.browser.type === 'playwright') {
159
+ const page = (session.browser as PlaywrightLauncher).getPage(session.id);
160
+ await page.mouse.up({ button: 'left' });
161
+ await page.mouse.up({ button: 'middle' });
162
+ await page.mouse.up({ button: 'right' });
163
+ await page.mouse.move(0, 0);
164
+ return true;
165
+ }
166
+
167
+ // handle specific behavior for puppeteer
168
+ if (session.browser.type === 'puppeteer') {
169
+ const page = (session.browser as ChromeLauncher).getPage(session.id);
170
+ await page.mouse.up({ button: 'left' });
171
+ await page.mouse.up({ button: 'middle' });
172
+ await page.mouse.up({ button: 'right' });
173
+ await page.mouse.move(0, 0);
174
+ return true;
175
+ }
176
+
177
+ // handle specific behavior for webdriver
178
+ if (session.browser.type === 'webdriver') {
179
+ const page = session.browser as WebdriverLauncher;
180
+ await page.resetMouse(session.id);
181
+ return true;
182
+ }
183
+
184
+ // you might not be able to support all browser launchers
185
+ throw new Error(
186
+ `Resetting mouse is not supported for browser type ${session.browser.type}.`,
187
+ );
188
+ }
189
+ },
190
+ };
191
+ }
package/CHANGELOG.md DELETED
@@ -1,296 +0,0 @@
1
- # @web/test-runner-commands
2
-
3
- ## 0.5.11
4
-
5
- ### Patch Changes
6
-
7
- - 62369e4d: Upgrade playwright to 1.14.0 which enables prefers-reduced-motion
8
-
9
- ## 0.5.10
10
-
11
- ### Patch Changes
12
-
13
- - 33ada3d8: Align @web/test-runner-core version
14
-
15
- ## 0.5.9
16
-
17
- ### Patch Changes
18
-
19
- - 056ba8c8: Add sendKeys support for webdriver
20
-
21
- ## 0.5.8
22
-
23
- ### Patch Changes
24
-
25
- - 687d4750: Downgrade @rollup/plugin-node-resolve to v11
26
-
27
- ## 0.5.7
28
-
29
- ### Patch Changes
30
-
31
- - 09af51ac: Escape the snapshot contents to avoid problems in Firrefox and Webkit
32
-
33
- ## 0.5.6
34
-
35
- ### Patch Changes
36
-
37
- - cb693c71: Use block comments in snapshots to make them work in all browsers
38
-
39
- ## 0.5.5
40
-
41
- ### Patch Changes
42
-
43
- - b362288a: make snapshots work on all browsers
44
-
45
- ## 0.5.4
46
-
47
- ### Patch Changes
48
-
49
- - 270a633a: dynamic import web socket module
50
-
51
- ## 0.5.3
52
-
53
- ### Patch Changes
54
-
55
- - 3af6ff86: improve snapshot formatting
56
-
57
- ## 0.5.2
58
-
59
- ### Patch Changes
60
-
61
- - 91e0e617: add compareSnapshot function
62
-
63
- ## 0.5.1
64
-
65
- ### Patch Changes
66
-
67
- - 339d05f7: add snapshots plugin
68
-
69
- ## 0.5.0
70
-
71
- ### Minor Changes
72
-
73
- - c3ead4fa: Added support for holding and releasing keys to the sendKeys command. The command now supports two additional actions `down` and `up` which hold down, or release a key. This effectively allows to hold down modifier keys while pressing other keys, which allows key combinations such as `Shift+Tab`.
74
-
75
- @example
76
-
77
- ```ts
78
- await sendKeys({
79
- down: 'Shift',
80
- });
81
- await sendKeys({
82
- press: 'Tab',
83
- });
84
- await sendKeys({
85
- up: 'Shift',
86
- });
87
- ```
88
-
89
- ## 0.4.5
90
-
91
- ### Patch Changes
92
-
93
- - 21f53211: add commands for reading/writing files
94
-
95
- ## 0.4.4
96
-
97
- ### Patch Changes
98
-
99
- - a6a018da: fix type references
100
-
101
- ## 0.4.3
102
-
103
- ### Patch Changes
104
-
105
- - 1d9411a3: Export `sendKeysPlugin` from `@web/test-runner-commands/plugins`.
106
- Loosen the typing of the command payload.
107
- - d2389bac: Add a11ySnapshotPlugin to acquire the current accessibility tree from the browser:
108
-
109
- ```js
110
- import { a11ySnapshot, findAccessibilityNode } from '@web/test-runner-commands';
111
-
112
- // ...
113
-
114
- const nodeName = 'Label Text';
115
- const snapshot = await a11ySnapshot();
116
- const foundNode = findAccessibilityNode(snapshot, node => node.name === nodeName);
117
- expect(foundNode).to.not.be.null;
118
- ```
119
-
120
- ## 0.4.2
121
-
122
- ### Patch Changes
123
-
124
- - ce90c7c3: Add the `sendKeys` command
125
-
126
- Sends a string of keys for the browser to press (all at once, as with single keys
127
- or shortcuts; e.g. `{press: 'Tab'}` or `{press: 'Shift+a'}` or
128
- `{press: 'Option+ArrowUp}`) or type (in sequence, e.g. `{type: 'Your name'}`) natively.
129
-
130
- For specific documentation of the strings to leverage here, see the Playwright documentation,
131
- here:
132
-
133
- - `press`: https://playwright.dev/docs/api/class-keyboard#keyboardpresskey-options
134
- - `type`: https://playwright.dev/docs/api/class-keyboard#keyboardtypetext-options
135
-
136
- Or, the Puppeter documentation, here:
137
-
138
- - `press`: https://pptr.dev/#?product=Puppeteer&show=api-keyboardpresskey-options
139
- - `type`: https://pptr.dev/#?product=Puppeteer&show=api-keyboardtypetext-options
140
-
141
- @param payload An object including a `press` or `type` property an the associated string
142
- for the browser runner to apply via that input method.
143
-
144
- @example
145
-
146
- ```ts
147
- await sendKeys({
148
- press: 'Tab',
149
- });
150
- ```
151
-
152
- @example
153
-
154
- ```ts
155
- await sendKeys({
156
- type: 'Your address',
157
- });
158
- ```
159
-
160
- - Updated dependencies [ce90c7c3]
161
- - @web/test-runner-core@0.10.14
162
-
163
- ## 0.4.1
164
-
165
- ### Patch Changes
166
-
167
- - e3314b02: update dependency on core
168
-
169
- ## 0.4.0
170
-
171
- ### Minor Changes
172
-
173
- - a7d74fdc: drop support for node v10 and v11
174
- - 1dd7cd0e: version bump after breaking change in @web/test-runner-core
175
-
176
- ### Patch Changes
177
-
178
- - Updated dependencies [1dd7cd0e]
179
- - Updated dependencies [a7d74fdc]
180
- - @web/test-runner-core@0.10.0
181
-
182
- ## 0.3.0
183
-
184
- ### Minor Changes
185
-
186
- - 6e313c18: merged @web/test-runner-cli package into @web/test-runner
187
-
188
- ### Patch Changes
189
-
190
- - Updated dependencies [6e313c18]
191
- - Updated dependencies [0f613e0e]
192
- - @web/test-runner-core@0.9.0
193
-
194
- ## 0.2.1
195
-
196
- ### Patch Changes
197
-
198
- - 416c0d2: Update dependencies
199
- - Updated dependencies [aadf0fe]
200
- - @web/test-runner-core@0.8.4
201
-
202
- ## 0.2.0
203
-
204
- ### Minor Changes
205
-
206
- - 2291ca1: replaced HTTP with websocket for server-browser communication
207
-
208
- this improves test speed, especially when a test file makes a lot of concurrent requests
209
- it lets us us catch more errors during test execution, and makes us catch them faster
210
-
211
- ### Patch Changes
212
-
213
- - Updated dependencies [2291ca1]
214
- - @web/test-runner-core@0.8.0
215
-
216
- ## 0.1.6
217
-
218
- ### Patch Changes
219
-
220
- - ab97aa8: publish browser folder
221
- - Updated dependencies [ab97aa8]
222
- - @web/test-runner-core@0.7.13
223
-
224
- ## 0.1.5
225
-
226
- ### Patch Changes
227
-
228
- - abf811f: improved error message when session id is missing
229
- - Updated dependencies [431ec8f]
230
- - @web/test-runner-core@0.7.9
231
-
232
- ## 0.1.4
233
-
234
- ### Patch Changes
235
-
236
- - 632eb67: export browser and node types
237
-
238
- ## 0.1.3
239
-
240
- ### Patch Changes
241
-
242
- - ce2a2e6: align dependencies
243
-
244
- ## 0.1.2
245
-
246
- ### Patch Changes
247
-
248
- - 519e6e2: made the plugins import work on node v10
249
-
250
- ## 0.1.1
251
-
252
- ### Patch Changes
253
-
254
- - aa65fd1: run build before publishing
255
- - Updated dependencies [aa65fd1]
256
- - @web/test-runner-core@0.7.1
257
-
258
- ## 0.1.0
259
-
260
- ### Minor Changes
261
-
262
- - fdcf2e5: Merged test runner server into core, and made it no longer possible configure a different server.
263
-
264
- The test runner relies on the server for many things, merging it into core makes the code more maintainable. The server is composable, you can proxy requests to other servers and we can look into adding more composition APIs later.
265
-
266
- - 9be1f95: Added native node es module entrypoints. This is a breaking change. Before, native node es module imports would import a CJS module as a default import and require destructuring afterwards:
267
-
268
- ```js
269
- import playwrightModule from '@web/test-runner-playwright';
270
-
271
- const { playwrightLauncher } = playwrightModule;
272
- ```
273
-
274
- Now, the exports are only available directly as a named export:
275
-
276
- ```js
277
- import { playwrightLauncher } from '@web/test-runner-playwright';
278
- ```
279
-
280
- ### Patch Changes
281
-
282
- - 62ff8b2: make tests work on windows
283
- - Updated dependencies [cdddf68]
284
- - Updated dependencies [fdcf2e5]
285
- - Updated dependencies [62ff8b2]
286
- - Updated dependencies [9be1f95]
287
- - @web/test-runner-core@0.7.0
288
-
289
- ## 0.0.1
290
-
291
- ### Patch Changes
292
-
293
- - 74cc129: implement commands API
294
- - Updated dependencies [02a3926]
295
- - Updated dependencies [74cc129]
296
- - @web/test-runner-core@0.6.22