@web/test-runner-commands 0.0.0-canary-20230403143511

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.
Files changed (58) hide show
  1. package/README.md +7 -0
  2. package/browser/commands.d.ts +297 -0
  3. package/browser/commands.mjs +223 -0
  4. package/dist/a11ySnapshotPlugin.d.ts +6 -0
  5. package/dist/a11ySnapshotPlugin.d.ts.map +1 -0
  6. package/dist/a11ySnapshotPlugin.js +44 -0
  7. package/dist/a11ySnapshotPlugin.js.map +1 -0
  8. package/dist/emulateMediaPlugin.d.ts +9 -0
  9. package/dist/emulateMediaPlugin.d.ts.map +1 -0
  10. package/dist/emulateMediaPlugin.js +55 -0
  11. package/dist/emulateMediaPlugin.js.map +1 -0
  12. package/dist/filePlugin.d.ts +16 -0
  13. package/dist/filePlugin.d.ts.map +1 -0
  14. package/dist/filePlugin.js +95 -0
  15. package/dist/filePlugin.js.map +1 -0
  16. package/dist/index.d.ts +9 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +20 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/selectOptionPlugin.d.ts +17 -0
  21. package/dist/selectOptionPlugin.d.ts.map +1 -0
  22. package/dist/selectOptionPlugin.js +97 -0
  23. package/dist/selectOptionPlugin.js.map +1 -0
  24. package/dist/sendKeysPlugin.d.ts +17 -0
  25. package/dist/sendKeysPlugin.d.ts.map +1 -0
  26. package/dist/sendKeysPlugin.js +104 -0
  27. package/dist/sendKeysPlugin.js.map +1 -0
  28. package/dist/sendMousePlugin.d.ts +24 -0
  29. package/dist/sendMousePlugin.d.ts.map +1 -0
  30. package/dist/sendMousePlugin.js +133 -0
  31. package/dist/sendMousePlugin.js.map +1 -0
  32. package/dist/setUserAgentPlugin.d.ts +3 -0
  33. package/dist/setUserAgentPlugin.d.ts.map +1 -0
  34. package/dist/setUserAgentPlugin.js +23 -0
  35. package/dist/setUserAgentPlugin.js.map +1 -0
  36. package/dist/setViewportPlugin.d.ts +9 -0
  37. package/dist/setViewportPlugin.d.ts.map +1 -0
  38. package/dist/setViewportPlugin.js +48 -0
  39. package/dist/setViewportPlugin.js.map +1 -0
  40. package/dist/snapshotPlugin.d.ts +10 -0
  41. package/dist/snapshotPlugin.d.ts.map +1 -0
  42. package/dist/snapshotPlugin.js +177 -0
  43. package/dist/snapshotPlugin.js.map +1 -0
  44. package/index.d.ts +2 -0
  45. package/package.json +60 -0
  46. package/plugins.d.ts +2 -0
  47. package/plugins.js +2 -0
  48. package/plugins.mjs +24 -0
  49. package/src/a11ySnapshotPlugin.ts +53 -0
  50. package/src/emulateMediaPlugin.ts +75 -0
  51. package/src/filePlugin.ts +108 -0
  52. package/src/index.ts +8 -0
  53. package/src/selectOptionPlugin.ts +122 -0
  54. package/src/sendKeysPlugin.ts +124 -0
  55. package/src/sendMousePlugin.ts +191 -0
  56. package/src/setUserAgentPlugin.ts +25 -0
  57. package/src/setViewportPlugin.ts +59 -0
  58. package/src/snapshotPlugin.ts +205 -0
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # Test Runner Commands
2
+
3
+ Commands for executing code server-side during your tests in the browser. To control the browser page, access the file system, or execute NodeJS libraries.
4
+
5
+ Built-in commands can change the viewport, emulate media queries or set the user agent. You can create custom commands to implement your own functionalities.
6
+
7
+ See [our website](https://modern-web.dev/docs/test-runner/commands/) for full documentation.
@@ -0,0 +1,297 @@
1
+ import {
2
+ Media,
3
+ Viewport,
4
+ SendKeysPayload,
5
+ A11ySnapshotPayload,
6
+ WriteFilePayload,
7
+ ReadFilePayload,
8
+ RemoveFilePayload,
9
+ SnapshotPluginConfig,
10
+ SaveSnapshotPayload,
11
+ SendMousePayload,
12
+ } from '../dist/index';
13
+
14
+ /**
15
+ * Executes a command on the server. If this is a custom command, you need to implement a plugin
16
+ * to execute this command.
17
+ */
18
+ export function executeServerCommand<R, P>(command: string, payload?: P): Promise<R>;
19
+
20
+ /**
21
+ * Sets the viewport of the browser.
22
+ */
23
+ export function setViewport(viewport: Viewport): Promise<void>;
24
+
25
+ /**
26
+ * Emulates browser media, such as screen/print or color scheme, to be used in
27
+ * CSS media queries.
28
+ *
29
+ * The `forcedColors` property is Playwright-only API that does not work in WebKit.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * await emulateMedia({
34
+ * colorScheme: 'dark',
35
+ * reducedMotion: 'reduce',
36
+ * });
37
+ * ```
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * await emulateMedia({
42
+ * media: 'print',
43
+ * });
44
+ * ```
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * await emulateMedia({
49
+ * forcedColors: 'active',
50
+ * });
51
+ * ```
52
+ */
53
+ export function emulateMedia(media: Media): Promise<void>;
54
+
55
+ /**
56
+ * Sets the user agent of the browser. This is a puppeteer-only API.
57
+ */
58
+ export function setUserAgent(userAgent: string): Promise<void>;
59
+
60
+ /**
61
+ * Sends a string of keys for the browser to press (all at once, as with single keys
62
+ * or shortcuts; e.g. `{press: 'Tab'}` or `{press: 'Shift+a'}` or
63
+ * `{press: 'Option+ArrowUp}`) or type (in sequence, e.g. `{type: 'Your name'}`) natively.
64
+ *
65
+ * For specific documentation of the strings to leverage here, see the Playwright documentation,
66
+ * here:
67
+ *
68
+ * - `press`: https://playwright.dev/docs/api/class-keyboard#keyboardpresskey-options
69
+ * - `type`: https://playwright.dev/docs/api/class-keyboard#keyboardtypetext-options
70
+ *
71
+ * Or, the Puppeter documentation, here:
72
+ *
73
+ * - `press`: https://pptr.dev/#?product=Puppeteer&show=api-keyboardpresskey-options
74
+ * - `type`: https://pptr.dev/#?product=Puppeteer&show=api-keyboardtypetext-options
75
+ *
76
+ * Or, the Webdriver documentation, here:
77
+ *
78
+ * https://webdriver.io/docs/api/browser/keys/
79
+ *
80
+ * @param payload An object including a `press` or `type` property an the associated string
81
+ * for the browser runner to apply via that input method.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * await sendKeys({
86
+ * press: 'Tab',
87
+ * });
88
+ * ```
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * await sendKeys({
93
+ * type: 'Your address',
94
+ * });
95
+ * ```
96
+ *
97
+ **/
98
+ export function sendKeys(payload: SendKeysPayload): Promise<void>;
99
+
100
+ /**
101
+ * Sends an action for the mouse to move it to a specific position or click a mouse button (left, middle, or right).
102
+ *
103
+ * WARNING: When moving the mouse or holding down a mouse button, the mouse stays in this state as long as
104
+ * you do not explicitly move it to another position or release the button. For this reason, it is recommended
105
+ * to reset the mouse state with the `resetMouse` command after each test case manipulating the mouse to avoid
106
+ * unexpected side effects.
107
+ *
108
+ * @param payload An object representing a mouse action specified by the `type` property (move, click, down, up)
109
+ * and including some properties to configure this action.
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * await sendMouse({
114
+ * type: 'move',
115
+ * position: [100, 100]
116
+ * });
117
+ * ```
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * await sendMouse({
122
+ * type: 'click',
123
+ * position: [100, 100],
124
+ * button: 'right'
125
+ * });
126
+ * ```
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * await sendMouse({
131
+ * type: 'down'
132
+ * });
133
+ * ```
134
+ *
135
+ **/
136
+ export function sendMouse(payload: SendMousePayload): Promise<void>;
137
+
138
+ /**
139
+ * Resets the mouse position to (0, 0) and releases mouse buttons.
140
+ *
141
+ * Use this command to reset the mouse state after mouse manipulations by the `sendMouse` command.
142
+ *
143
+ * @example
144
+ * ```
145
+ * it('does something with the mouse', () => {
146
+ * await sendMouse({ type: 'move', position: [150, 150] });
147
+ * await sendMouse({ type: 'down', button: 'middle' });
148
+ * });
149
+ *
150
+ * afterEach(() => {
151
+ * await resetMouse();
152
+ * });
153
+ * ```
154
+ */
155
+ export function resetMouse(): Promise<void>;
156
+
157
+ /**
158
+ * Request a snapshot of the Accessibility Tree of the entire page or starting from
159
+ * the element that is obtained via the `selector` property of the `payload` argument.
160
+ *
161
+ * Learn more about the tree that is returned from Playwright here:
162
+ * - https://playwright.dev/docs/api/class-accessibility/
163
+ *
164
+ * Learn more about the tree that is returned from Puppeteer here:
165
+ * - https://pptr.dev/#?product=Puppeteer&show=api-class-accessibility
166
+ *
167
+ * @param payload An object including a `selector` property pointing to the root of the
168
+ * a11y tree you'd like returned.
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * await a11ySnapshot();
173
+ * ```
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * await a11ySnapshot({
178
+ * selector: 'main'
179
+ * });
180
+ * ```
181
+ */
182
+ export function a11ySnapshot(payload: A11ySnapshotPayload): Promise<void>;
183
+
184
+ /**
185
+ * Walk the provided accessibility tree that starts on `node` and test each
186
+ * node in the tree until one is found that meast the `test` provided.
187
+ *
188
+ * Learn more about the tree that is returned from Playwright here:
189
+ * - https://playwright.dev/docs/api/class-accessibility/
190
+ *
191
+ * Learn more about the tree that is returned from Puppeteer here:
192
+ * - https://pptr.dev/#?product=Puppeteer&show=api-class-accessibility
193
+ *
194
+ * @param node
195
+ * @param test
196
+ *
197
+ * @example
198
+ * // return whether a node in the `snapshot` has `name: 'Label Text Value Text'`
199
+ * ```ts
200
+ * findAccessibilityNode<{ name: string }>(
201
+ * snapshot,
202
+ * (node) => node.name === 'Label Text Value Text'
203
+ * )
204
+ * ```
205
+ */
206
+ export function findAccessibilityNode<TNode>(
207
+ node: TNode & { children: TNode[] },
208
+ test: (node: TNode) => boolean,
209
+ ): TNode | null;
210
+
211
+ /**
212
+ * Writes a file to disk.
213
+ *
214
+ * @param payload.filePath the path of the file to save. This is a path relative to the test file
215
+ * being executed. It cannot be an absolute path.
216
+ * @param payload.content the file content to save as a string.
217
+ * @param payload.encoding optional encoding to use when saving the file.
218
+ *
219
+ * @example
220
+ * ```ts
221
+ * await writeFile({ path: 'hello-world.txt', content: 'Hello world!' });
222
+ * ```
223
+ */
224
+ export function writeFile(payload: WriteFilePayload): Promise<void>;
225
+
226
+ /**
227
+ * Reads a file from disk.
228
+ *
229
+ * @param payload.filePath the path of the file to read. This is a path relative to the test file
230
+ * being executed. It cannot be an absolute path.
231
+ * @param payload.encoding optional encoding to use when reading the file.
232
+ *
233
+ * @example
234
+ * ```ts
235
+ * const content = await readFile({ path: 'hello-world.txt' });
236
+ * ```
237
+ */
238
+ export function readFile(payload: ReadFilePayload): Promise<string | undefined>;
239
+
240
+ /**
241
+ * Removes a file from disk.
242
+ *
243
+ * @param payload.filePath the path of the file to remove. This is a path relative to the test file
244
+ * being executed. It cannot be an absolute path.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * await removeFile({ path: 'hello-world.txt' });
249
+ * ```
250
+ */
251
+ export function removeFile(payload: RemoveFilePayload): Promise<void>;
252
+
253
+ /**
254
+ * Gets configuration for snapshot testing.
255
+ *
256
+ * @param payload.updateSnapshots whether to updated snapshots that are not the same
257
+ */
258
+ export function getSnapshotConfig(): Promise<SnapshotPluginConfig>;
259
+
260
+ /**
261
+ * Gets the snapshots stored for this test file.
262
+ */
263
+ export function getSnapshots(): Promise<Record<string, string>>;
264
+
265
+ /**
266
+ * Saves a snapshot for this test file.
267
+ *
268
+ * @param payload.name the name of the snapshot
269
+ */
270
+ export function getSnapshot(options: { name: string }): Promise<string | undefined>;
271
+
272
+ /**
273
+ * Saves a snapshot for this test file.
274
+ *
275
+ * @param payload.name the name of the snapshot
276
+ * @param payload.content the content of the snapshot as a string
277
+ */
278
+ export function saveSnapshot(options: SaveSnapshotPayload): Promise<void>;
279
+
280
+ /**
281
+ * Removes stored snapshots for this test file.
282
+ *
283
+ * @param payload.name the name of the snapshot
284
+ *
285
+ */
286
+ export function removeSnapshot(options: { name: string }): Promise<void>;
287
+
288
+ /**
289
+ * If no snapshot exists on disk or if update-snapshots is set to true server-side,
290
+ * the passed snapshot is saved. Otherwise the snapshot is compared with what's stored
291
+ * on disk. If the snapshots are not equal, an error is thrown.
292
+ *
293
+ * @param options
294
+ */
295
+ export function compareSnapshot(options: { name: string; content: string }): Promise<void>;
296
+
297
+ export { Media, Viewport, SendKeysPayload, WriteFilePayload, ReadFilePayload, RemoveFilePayload };
@@ -0,0 +1,223 @@
1
+ /* eslint-env browser, es2020 */
2
+ const PARAM_SESSION_ID = 'wtr-session-id';
3
+
4
+ const sessionId = new URL(window.location.href).searchParams.get(PARAM_SESSION_ID);
5
+
6
+ function isObject(payload) {
7
+ return payload != null && typeof payload === 'object';
8
+ }
9
+
10
+ export async function executeServerCommand(command, payload, pluginName) {
11
+ if (typeof sessionId !== 'string') {
12
+ throw new Error(
13
+ 'Unable to execute server commands in a browser not controlled by the test runner. ' +
14
+ 'Use the debug option from the watch menu to debug in a controlled browser.',
15
+ );
16
+ }
17
+
18
+ let sendMessageWaitForResponse;
19
+ try {
20
+ const webSocketModule = await import('/__web-dev-server__web-socket.js');
21
+ ({ sendMessageWaitForResponse } = webSocketModule);
22
+ } catch (error) {
23
+ throw new Error(
24
+ 'Could not setup web socket connection. Are you executing this test through Web Test Runner?',
25
+ );
26
+ }
27
+
28
+ try {
29
+ const response = await sendMessageWaitForResponse({
30
+ type: 'wtr-command',
31
+ sessionId,
32
+ command,
33
+ payload,
34
+ });
35
+
36
+ if (!response.executed) {
37
+ let msg;
38
+ if (pluginName) {
39
+ msg = `Unknown command ${command}. Add the ${pluginName} to your config.`;
40
+ } else {
41
+ msg = `Unknown command ${command}. Did you install a plugin to handle this command?`;
42
+ }
43
+ throw new Error(msg);
44
+ }
45
+
46
+ return response.result;
47
+ } catch (error) {
48
+ throw new Error(
49
+ `Error while executing command ${command}${
50
+ payload ? ` with payload ${JSON.stringify(payload)}` : ''
51
+ }: ${error.message}`,
52
+ );
53
+ }
54
+ }
55
+
56
+ export function setViewport(viewport) {
57
+ return executeServerCommand('set-viewport', viewport);
58
+ }
59
+
60
+ export function emulateMedia(media) {
61
+ return executeServerCommand('emulate-media', media);
62
+ }
63
+
64
+ export function setUserAgent(options) {
65
+ return executeServerCommand('set-user-agent', options);
66
+ }
67
+
68
+ export function sendKeys(options) {
69
+ return executeServerCommand('send-keys', options);
70
+ }
71
+
72
+ export function selectOption(options) {
73
+ return executeServerCommand('select-option', options);
74
+ }
75
+
76
+ export function sendMouse(options) {
77
+ return executeServerCommand('send-mouse', options);
78
+ }
79
+
80
+ export function resetMouse(options) {
81
+ return executeServerCommand('reset-mouse', options);
82
+ }
83
+
84
+ export function a11ySnapshot(options) {
85
+ return executeServerCommand('a11y-snapshot', options);
86
+ }
87
+
88
+ export function writeFile(options) {
89
+ return executeServerCommand('write-file', options, 'filePlugin from @web/test-runner-commands');
90
+ }
91
+
92
+ export function readFile(options) {
93
+ return executeServerCommand('read-file', options, 'filePlugin from @web/test-runner-commands');
94
+ }
95
+
96
+ export function removeFile(options) {
97
+ return executeServerCommand('remove-file', options, 'filePlugin from @web/test-runner-commands');
98
+ }
99
+
100
+ export function findAccessibilityNode(node, test) {
101
+ if (test(node)) return node;
102
+ for (const child of node.children || []) {
103
+ const foundNode = findAccessibilityNode(child, test);
104
+ if (foundNode) {
105
+ return foundNode;
106
+ }
107
+ }
108
+ return null;
109
+ }
110
+
111
+ let snapshotConfig;
112
+ let cachedSnapshots;
113
+
114
+ export async function getSnapshotConfig() {
115
+ if (!snapshotConfig) {
116
+ snapshotConfig = await executeServerCommand(
117
+ 'get-snapshot-config',
118
+ undefined,
119
+ 'snapshotPlugin from @web/test-runner-commands',
120
+ );
121
+ }
122
+
123
+ return snapshotConfig;
124
+ }
125
+
126
+ /**
127
+ * This regexp is used to capture the snapshots contents.
128
+ *
129
+ * snapshots\[[^\]]+] = (\n)? - snapshot definition. Sometimes the initial content backtick is placed in the next line
130
+ * (?<content>`[^`]+`) - capture the snapshot content, which is included between backticks "`"
131
+ * /gm - global and multiline
132
+ * @type {RegExp}
133
+ */
134
+ const ESCAPE_REGEX = /snapshots\[[^\]]+] = (\n)?(?<content>`[^`]*`)/gm;
135
+
136
+ const escapeContent = content => {
137
+ [...content.matchAll(ESCAPE_REGEX)].forEach(({ groups: { content: itemContent } }) => {
138
+ content = content.replaceAll(itemContent, encodeURIComponent(itemContent));
139
+ });
140
+
141
+ return content;
142
+ };
143
+
144
+ export async function getSnapshots({ cache = true } = {}) {
145
+ if (cache && cachedSnapshots) {
146
+ return cachedSnapshots;
147
+ }
148
+
149
+ const result = await executeServerCommand(
150
+ 'get-snapshots',
151
+ undefined,
152
+ 'snapshotPlugin from @web/test-runner-commands',
153
+ );
154
+
155
+ if (typeof result?.content !== 'string') {
156
+ throw new Error('Expected a result as string');
157
+ }
158
+
159
+ const content = `${escapeContent(result.content)}/* ${Math.random()} */`;
160
+ const module = await import(`data:text/javascript;charset=utf-8,${content}`);
161
+
162
+ if (!module || !isObject(module.snapshots)) {
163
+ throw new Error('Expected snapshot result to be a module that exports an object.');
164
+ }
165
+
166
+ cachedSnapshots = module.snapshots;
167
+
168
+ return cachedSnapshots;
169
+ }
170
+
171
+ export async function getSnapshot(options) {
172
+ if (!isObject(options)) throw new Error('You must provide a payload object');
173
+ if (typeof options.name !== 'string') throw new Error('You must provide a snapshot name');
174
+
175
+ const snapshots = await getSnapshots(options);
176
+
177
+ return snapshots[options.name];
178
+ }
179
+
180
+ export async function saveSnapshot(options) {
181
+ if (!isObject(options)) throw new Error('You must provide a payload object');
182
+ if (typeof options.name !== 'string') throw new Error('You must provide a snapshot name');
183
+ if (options.content !== undefined && typeof options.content !== 'string')
184
+ throw new Error('You must provide a snapshot content');
185
+
186
+ // ensure snapshots for this file are loaded
187
+ const snapshots = await getSnapshots();
188
+
189
+ // store snapshot in-memory
190
+ snapshots[options.name] = options.content;
191
+
192
+ return executeServerCommand(
193
+ 'save-snapshot',
194
+ options,
195
+ 'snapshotPlugin from @web/test-runner-commands',
196
+ );
197
+ }
198
+
199
+ export function removeSnapshot(options) {
200
+ if (!isObject(options)) throw new Error('You must provide a payload object');
201
+ if (typeof options.name !== 'string') throw new Error('You must provide a snapshot name');
202
+
203
+ return saveSnapshot({ ...options, content: undefined });
204
+ }
205
+
206
+ export async function compareSnapshot({ name, content }) {
207
+ const currentSnapshot = await getSnapshot({ name });
208
+ if (currentSnapshot) {
209
+ const config = await getSnapshotConfig();
210
+ if (!config.updateSnapshots) {
211
+ if (currentSnapshot !== content) {
212
+ throw new Error(
213
+ `Snapshots for ${name} are not equal. \n\n` +
214
+ `Stored:\n${currentSnapshot}\n\n` +
215
+ `New:\n${content}`,
216
+ );
217
+ }
218
+ } else if (currentSnapshot === content) {
219
+ return;
220
+ }
221
+ }
222
+ await saveSnapshot({ name, content });
223
+ }
@@ -0,0 +1,6 @@
1
+ import { TestRunnerPlugin } from '@web/test-runner-core';
2
+ export declare type A11ySnapshotPayload = {
3
+ selector?: string;
4
+ };
5
+ export declare function a11ySnapshotPlugin(): TestRunnerPlugin<A11ySnapshotPayload>;
6
+ //# sourceMappingURL=a11ySnapshotPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11ySnapshotPlugin.d.ts","sourceRoot":"","sources":["../src/a11ySnapshotPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAIzD,oBAAY,mBAAmB,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,wBAAgB,kBAAkB,IAAI,gBAAgB,CAAC,mBAAmB,CAAC,CA8C1E"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.a11ySnapshotPlugin = void 0;
4
+ function a11ySnapshotPlugin() {
5
+ return {
6
+ name: 'a11y-snapshot-command',
7
+ async executeCommand({ command, payload, session }) {
8
+ if (command === 'a11y-snapshot') {
9
+ // handle specific behavior for playwright
10
+ if (session.browser.type === 'playwright') {
11
+ const page = session.browser.getPage(session.id);
12
+ const options = {};
13
+ if (payload && payload.selector) {
14
+ const root = await page.$(payload.selector);
15
+ if (root) {
16
+ options.root = root;
17
+ }
18
+ }
19
+ const snapshot = await page.accessibility.snapshot(options);
20
+ return snapshot;
21
+ }
22
+ // handle specific behavior for puppeteer
23
+ if (session.browser.type === 'puppeteer') {
24
+ const page = session.browser.getPage(session.id);
25
+ const options = {};
26
+ if (payload && payload.selector) {
27
+ // @ts-ignore
28
+ const root = await page.$(payload.selector);
29
+ if (root) {
30
+ options.root = root;
31
+ }
32
+ }
33
+ // @ts-ignore
34
+ const snapshot = await page.accessibility.snapshot(options);
35
+ return snapshot;
36
+ }
37
+ // you might not be able to support all browser launchers
38
+ throw new Error(`Acessibility snapshot is not supported for browser type ${session.browser.type}.`);
39
+ }
40
+ },
41
+ };
42
+ }
43
+ exports.a11ySnapshotPlugin = a11ySnapshotPlugin;
44
+ //# sourceMappingURL=a11ySnapshotPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11ySnapshotPlugin.js","sourceRoot":"","sources":["../src/a11ySnapshotPlugin.ts"],"names":[],"mappings":";;;AAMA,SAAgB,kBAAkB;IAChC,OAAO;QACL,IAAI,EAAE,uBAAuB;QAC7B,KAAK,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAChD,IAAI,OAAO,KAAK,eAAe,EAAE;gBAC/B,0CAA0C;gBAC1C,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY,EAAE;oBACzC,MAAM,IAAI,GAAI,OAAO,CAAC,OAA8B,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACzE,MAAM,OAAO,GAET,EAAE,CAAC;oBACP,IAAI,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE;wBAC/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;wBAC5C,IAAI,IAAI,EAAE;4BACR,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;yBACrB;qBACF;oBACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBAC5D,OAAO,QAAQ,CAAC;iBACjB;gBAED,yCAAyC;gBACzC,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE;oBACxC,MAAM,IAAI,GAAI,OAAO,CAAC,OAA0B,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACrE,MAAM,OAAO,GAET,EAAE,CAAC;oBACP,IAAI,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE;wBAC/B,aAAa;wBACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;wBAC5C,IAAI,IAAI,EAAE;4BACR,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;yBACrB;qBACF;oBACD,aAAa;oBACb,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBAC5D,OAAO,QAAQ,CAAC;iBACjB;gBAED,yDAAyD;gBACzD,MAAM,IAAI,KAAK,CACb,2DAA2D,OAAO,CAAC,OAAO,CAAC,IAAI,GAAG,CACnF,CAAC;aACH;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AA9CD,gDA8CC"}
@@ -0,0 +1,9 @@
1
+ import { TestRunnerPlugin } from '@web/test-runner-core';
2
+ export interface Media {
3
+ media?: 'screen' | 'print';
4
+ colorScheme?: 'dark' | 'light' | 'no-preference';
5
+ reducedMotion?: 'reduce' | 'no-preference';
6
+ forcedColors?: 'active' | 'none';
7
+ }
8
+ export declare function emulateMediaPlugin(): TestRunnerPlugin;
9
+ //# sourceMappingURL=emulateMediaPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emulateMediaPlugin.d.ts","sourceRoot":"","sources":["../src/emulateMediaPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAIzD,MAAM,WAAW,KAAK;IACpB,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,eAAe,CAAC;IACjD,aAAa,CAAC,EAAE,QAAQ,GAAG,eAAe,CAAC;IAC3C,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CAClC;AAuBD,wBAAgB,kBAAkB,IAAI,gBAAgB,CA0CrD"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emulateMediaPlugin = void 0;
4
+ function isObject(payload) {
5
+ return payload != null && typeof payload === 'object';
6
+ }
7
+ function isMediaObject(payload) {
8
+ if (!isObject(payload))
9
+ throw new Error('You must provide a viewport object');
10
+ if (payload.media != null && !(typeof payload.media === 'string')) {
11
+ throw new Error('media should be a string.');
12
+ }
13
+ if (payload.colorScheme != null && !(typeof payload.colorScheme === 'string')) {
14
+ throw new Error('colorScheme should be a string.');
15
+ }
16
+ if (payload.reducedMotion != null && !(typeof payload.reducedMotion === 'string')) {
17
+ throw new Error('reducedMotion should be a string.');
18
+ }
19
+ return true;
20
+ }
21
+ function emulateMediaPlugin() {
22
+ return {
23
+ name: 'emulate-media-command',
24
+ async executeCommand({ command, payload, session }) {
25
+ if (command === 'emulate-media') {
26
+ if (!isMediaObject(payload)) {
27
+ throw new Error('You must provide a viewport object');
28
+ }
29
+ if (session.browser.type === 'puppeteer') {
30
+ const page = session.browser.getPage(session.id);
31
+ const features = [];
32
+ if (payload.colorScheme != null) {
33
+ features.push({ name: 'prefers-color-scheme', value: payload.colorScheme });
34
+ }
35
+ if (payload.reducedMotion != null) {
36
+ features.push({ name: 'prefers-reduced-motion', value: payload.reducedMotion });
37
+ }
38
+ await page.emulateMediaFeatures(features);
39
+ if (payload.media) {
40
+ await page.emulateMediaType(payload.media);
41
+ }
42
+ return true;
43
+ }
44
+ if (session.browser.type === 'playwright') {
45
+ const page = session.browser.getPage(session.id);
46
+ await page.emulateMedia(payload);
47
+ return true;
48
+ }
49
+ throw new Error(`Setting viewport is not supported for browser type ${session.browser.type}.`);
50
+ }
51
+ },
52
+ };
53
+ }
54
+ exports.emulateMediaPlugin = emulateMediaPlugin;
55
+ //# sourceMappingURL=emulateMediaPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emulateMediaPlugin.js","sourceRoot":"","sources":["../src/emulateMediaPlugin.ts"],"names":[],"mappings":";;;AAWA,SAAS,QAAQ,CAAC,OAAgB;IAChC,OAAO,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,CAAC;AACxD,CAAC;AAED,SAAS,aAAa,CAAC,OAAgB;IACrC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAE9E,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,EAAE;QACjE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;KAC9C;IAED,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,CAAC,CAAC,OAAO,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,EAAE;QAC7E,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;KACpD;IAED,IAAI,OAAO,CAAC,aAAa,IAAI,IAAI,IAAI,CAAC,CAAC,OAAO,OAAO,CAAC,aAAa,KAAK,QAAQ,CAAC,EAAE;QACjF,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;KACtD;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,kBAAkB;IAChC,OAAO;QACL,IAAI,EAAE,uBAAuB;QAE7B,KAAK,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAChD,IAAI,OAAO,KAAK,eAAe,EAAE;gBAC/B,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;oBAC3B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;iBACvD;gBAED,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE;oBACxC,MAAM,IAAI,GAAI,OAAO,CAAC,OAA0B,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACrE,MAAM,QAAQ,GAAG,EAAE,CAAC;oBAEpB,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,EAAE;wBAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;qBAC7E;oBACD,IAAI,OAAO,CAAC,aAAa,IAAI,IAAI,EAAE;wBACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;qBACjF;oBAED,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;oBAE1C,IAAI,OAAO,CAAC,KAAK,EAAE;wBACjB,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;qBAC5C;oBAED,OAAO,IAAI,CAAC;iBACb;gBAED,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY,EAAE;oBACzC,MAAM,IAAI,GAAI,OAAO,CAAC,OAA8B,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACzE,MAAM,IAAI,CAAC,YAAY,CAAC,OAAc,CAAC,CAAC;oBACxC,OAAO,IAAI,CAAC;iBACb;gBAED,MAAM,IAAI,KAAK,CACb,sDAAsD,OAAO,CAAC,OAAO,CAAC,IAAI,GAAG,CAC9E,CAAC;aACH;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AA1CD,gDA0CC"}
@@ -0,0 +1,16 @@
1
+ /// <reference types="node" />
2
+ import { TestRunnerPlugin } from '@web/test-runner-core';
3
+ export interface WriteFilePayload {
4
+ path: string;
5
+ content: string;
6
+ encoding?: BufferEncoding;
7
+ }
8
+ export interface ReadFilePayload {
9
+ path: string;
10
+ encoding?: BufferEncoding;
11
+ }
12
+ export interface RemoveFilePayload {
13
+ path: string;
14
+ }
15
+ export declare function filePlugin(): TestRunnerPlugin;
16
+ //# sourceMappingURL=filePlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filePlugin.d.ts","sourceRoot":"","sources":["../src/filePlugin.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAwBzD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AA6BD,wBAAgB,UAAU,IAAI,gBAAgB,CAyC7C"}