@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.
- package/README.md +7 -0
- package/browser/commands.d.ts +297 -0
- package/browser/commands.mjs +223 -0
- package/dist/a11ySnapshotPlugin.d.ts +6 -0
- package/dist/a11ySnapshotPlugin.d.ts.map +1 -0
- package/dist/a11ySnapshotPlugin.js +44 -0
- package/dist/a11ySnapshotPlugin.js.map +1 -0
- package/dist/emulateMediaPlugin.d.ts +9 -0
- package/dist/emulateMediaPlugin.d.ts.map +1 -0
- package/dist/emulateMediaPlugin.js +55 -0
- package/dist/emulateMediaPlugin.js.map +1 -0
- package/dist/filePlugin.d.ts +16 -0
- package/dist/filePlugin.d.ts.map +1 -0
- package/dist/filePlugin.js +95 -0
- package/dist/filePlugin.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/selectOptionPlugin.d.ts +17 -0
- package/dist/selectOptionPlugin.d.ts.map +1 -0
- package/dist/selectOptionPlugin.js +97 -0
- package/dist/selectOptionPlugin.js.map +1 -0
- package/dist/sendKeysPlugin.d.ts +17 -0
- package/dist/sendKeysPlugin.d.ts.map +1 -0
- package/dist/sendKeysPlugin.js +104 -0
- package/dist/sendKeysPlugin.js.map +1 -0
- package/dist/sendMousePlugin.d.ts +24 -0
- package/dist/sendMousePlugin.d.ts.map +1 -0
- package/dist/sendMousePlugin.js +133 -0
- package/dist/sendMousePlugin.js.map +1 -0
- package/dist/setUserAgentPlugin.d.ts +3 -0
- package/dist/setUserAgentPlugin.d.ts.map +1 -0
- package/dist/setUserAgentPlugin.js +23 -0
- package/dist/setUserAgentPlugin.js.map +1 -0
- package/dist/setViewportPlugin.d.ts +9 -0
- package/dist/setViewportPlugin.d.ts.map +1 -0
- package/dist/setViewportPlugin.js +48 -0
- package/dist/setViewportPlugin.js.map +1 -0
- package/dist/snapshotPlugin.d.ts +10 -0
- package/dist/snapshotPlugin.d.ts.map +1 -0
- package/dist/snapshotPlugin.js +177 -0
- package/dist/snapshotPlugin.js.map +1 -0
- package/index.d.ts +2 -0
- package/package.json +60 -0
- package/plugins.d.ts +2 -0
- package/plugins.js +2 -0
- package/plugins.mjs +24 -0
- package/src/a11ySnapshotPlugin.ts +53 -0
- package/src/emulateMediaPlugin.ts +75 -0
- package/src/filePlugin.ts +108 -0
- package/src/index.ts +8 -0
- package/src/selectOptionPlugin.ts +122 -0
- package/src/sendKeysPlugin.ts +124 -0
- package/src/sendMousePlugin.ts +191 -0
- package/src/setUserAgentPlugin.ts +25 -0
- package/src/setViewportPlugin.ts +59 -0
- package/src/snapshotPlugin.ts +205 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setViewportPlugin = void 0;
|
|
4
|
+
function isObject(payload) {
|
|
5
|
+
return payload != null && typeof payload === 'object';
|
|
6
|
+
}
|
|
7
|
+
function isViewportObject(payload) {
|
|
8
|
+
if (!isObject(payload))
|
|
9
|
+
throw new Error('You must provide a viewport object');
|
|
10
|
+
if (payload.height == null)
|
|
11
|
+
throw new Error('You must provide a viewport width');
|
|
12
|
+
if (payload.width == null)
|
|
13
|
+
throw new Error('You must provide a viewport width');
|
|
14
|
+
if (typeof payload.height !== 'number')
|
|
15
|
+
throw new Error('Viewport height must be a number');
|
|
16
|
+
if (typeof payload.height !== 'number')
|
|
17
|
+
throw new Error('Viewport width must be a number');
|
|
18
|
+
if (payload.isMobile != null)
|
|
19
|
+
throw new Error('isMobile cannot be used because it triggers a page reload');
|
|
20
|
+
if (payload.hasTouch != null)
|
|
21
|
+
throw new Error('hasTouch cannot be used because it triggers a page reload');
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
function setViewportPlugin() {
|
|
25
|
+
return {
|
|
26
|
+
name: 'set-viewport-command',
|
|
27
|
+
async executeCommand({ command, payload, session }) {
|
|
28
|
+
if (command === 'set-viewport') {
|
|
29
|
+
if (!isViewportObject(payload)) {
|
|
30
|
+
throw new Error('You must provide a viewport object');
|
|
31
|
+
}
|
|
32
|
+
if (session.browser.type === 'puppeteer') {
|
|
33
|
+
const page = session.browser.getPage(session.id);
|
|
34
|
+
await page.setViewport(payload);
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
if (session.browser.type === 'playwright') {
|
|
38
|
+
const page = session.browser.getPage(session.id);
|
|
39
|
+
await page.setViewportSize(payload);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
throw new Error(`Setting viewport is not supported for browser type ${session.browser.type}.`);
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
exports.setViewportPlugin = setViewportPlugin;
|
|
48
|
+
//# sourceMappingURL=setViewportPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setViewportPlugin.js","sourceRoot":"","sources":["../src/setViewportPlugin.ts"],"names":[],"mappings":";;;AAaA,SAAS,QAAQ,CAAC,OAAgB;IAChC,OAAO,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,CAAC;AACxD,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAgB;IACxC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAC9E,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACjF,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAChF,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAC5F,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC3F,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI;QAC1B,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI;QAC1B,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,iBAAiB;IAC/B,OAAO;QACL,IAAI,EAAE,sBAAsB;QAE5B,KAAK,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAChD,IAAI,OAAO,KAAK,cAAc,EAAE;gBAC9B,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE;oBAC9B,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,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;oBAChC,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,eAAe,CAAC,OAAO,CAAC,CAAC;oBACpC,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;AA5BD,8CA4BC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { TestRunnerPlugin } from '@web/test-runner-core';
|
|
2
|
+
export interface SaveSnapshotPayload {
|
|
3
|
+
name: string;
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
export interface SnapshotPluginConfig {
|
|
7
|
+
updateSnapshots?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function snapshotPlugin(config?: SnapshotPluginConfig): TestRunnerPlugin;
|
|
10
|
+
//# sourceMappingURL=snapshotPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshotPlugin.d.ts","sourceRoot":"","sources":["../src/snapshotPlugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAyBzD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAuHD,MAAM,WAAW,oBAAoB;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,oBAAoB,GAAG,gBAAgB,CAoD9E"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.snapshotPlugin = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const util_1 = require("util");
|
|
10
|
+
const mkdirp_1 = __importDefault(require("mkdirp"));
|
|
11
|
+
const readFile = util_1.promisify(fs_1.default.readFile);
|
|
12
|
+
const writeFile = util_1.promisify(fs_1.default.writeFile);
|
|
13
|
+
const unlink = util_1.promisify(fs_1.default.unlink);
|
|
14
|
+
const access = util_1.promisify(fs_1.default.access);
|
|
15
|
+
async function fileExists(filePath) {
|
|
16
|
+
try {
|
|
17
|
+
await access(filePath);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
catch (_a) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function isObject(payload) {
|
|
25
|
+
return payload != null && typeof payload === 'object';
|
|
26
|
+
}
|
|
27
|
+
function isSaveSnapshotPayload(payload) {
|
|
28
|
+
if (!isObject(payload))
|
|
29
|
+
throw new Error('You must provide a payload object');
|
|
30
|
+
if (typeof payload.name !== 'string')
|
|
31
|
+
throw new Error('You must provide a path option');
|
|
32
|
+
if (payload.content !== undefined && typeof payload.content !== 'string')
|
|
33
|
+
throw new Error('You must provide a content option');
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
function getSnapshotPath(testFile) {
|
|
37
|
+
const testDir = path_1.default.dirname(testFile);
|
|
38
|
+
const testFileName = path_1.default.basename(testFile);
|
|
39
|
+
const ext = path_1.default.extname(testFileName);
|
|
40
|
+
const fileWithoutExt = testFileName.substring(0, testFileName.length - ext.length);
|
|
41
|
+
return path_1.default.join(testDir, '__snapshots__', `${fileWithoutExt}.snap.js`);
|
|
42
|
+
}
|
|
43
|
+
class SnapshotStore {
|
|
44
|
+
constructor() {
|
|
45
|
+
this.snapshots = new Map();
|
|
46
|
+
this.sessionToSnapshotPath = new Map();
|
|
47
|
+
this.readOperations = new Map();
|
|
48
|
+
}
|
|
49
|
+
async get(testFilePath) {
|
|
50
|
+
var _a, _b;
|
|
51
|
+
const snapshotPath = getSnapshotPath(testFilePath);
|
|
52
|
+
if (this.readOperations.has(snapshotPath)) {
|
|
53
|
+
// something else is already reading, wait for it
|
|
54
|
+
await ((_a = this.readOperations.get(snapshotPath)) === null || _a === void 0 ? void 0 : _a.promise);
|
|
55
|
+
}
|
|
56
|
+
const cachedContent = this.snapshots.get(snapshotPath);
|
|
57
|
+
if (cachedContent) {
|
|
58
|
+
// return from cache
|
|
59
|
+
return cachedContent;
|
|
60
|
+
}
|
|
61
|
+
const promiseObj = { resolve: () => { }, promise: Promise.resolve() };
|
|
62
|
+
promiseObj.promise = new Promise(resolve => {
|
|
63
|
+
promiseObj.resolve = resolve;
|
|
64
|
+
});
|
|
65
|
+
this.readOperations.set(testFilePath, promiseObj);
|
|
66
|
+
// store in cache
|
|
67
|
+
const content = (await fileExists(snapshotPath))
|
|
68
|
+
? await readFile(snapshotPath, 'utf-8')
|
|
69
|
+
: '/* @web/test-runner snapshot v1 */\nexport const snapshots = {};\n\n';
|
|
70
|
+
this.snapshots.set(snapshotPath, content);
|
|
71
|
+
// resolve read promise to let others who are waiting continue
|
|
72
|
+
(_b = this.readOperations.get(snapshotPath)) === null || _b === void 0 ? void 0 : _b.resolve();
|
|
73
|
+
this.readOperations.delete(snapshotPath);
|
|
74
|
+
return content;
|
|
75
|
+
}
|
|
76
|
+
async saveSnapshot(sessionId, testFilePath, name, updatedSnapshot) {
|
|
77
|
+
const snapshotPath = getSnapshotPath(testFilePath);
|
|
78
|
+
const nameStr = JSON.stringify(name);
|
|
79
|
+
const startMarker = `snapshots[${nameStr}]`;
|
|
80
|
+
const endMarker = `/* end snapshot ${name} */\n\n`;
|
|
81
|
+
const replacement = updatedSnapshot
|
|
82
|
+
? `${startMarker} = \n\`${updatedSnapshot}\`;\n${endMarker}`
|
|
83
|
+
: '';
|
|
84
|
+
const content = await this.get(testFilePath);
|
|
85
|
+
let updatedContent;
|
|
86
|
+
const startIndex = content.indexOf(startMarker);
|
|
87
|
+
if (startIndex !== -1) {
|
|
88
|
+
// replace existing snapshot
|
|
89
|
+
const endIndex = content.indexOf(endMarker);
|
|
90
|
+
if (endIndex === -1) {
|
|
91
|
+
throw new Error('Missing snapshot end marker');
|
|
92
|
+
}
|
|
93
|
+
const beforeReplace = content.substring(0, startIndex);
|
|
94
|
+
const afterReplace = content.substring(endIndex + endMarker.length);
|
|
95
|
+
updatedContent = `${beforeReplace}${replacement}${afterReplace}`;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
// add new snapshot
|
|
99
|
+
updatedContent = `${content}${replacement}`;
|
|
100
|
+
}
|
|
101
|
+
if (updatedContent === content) {
|
|
102
|
+
// snapshot did not actually change, avoid marking snapshot as dirty
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.sessionToSnapshotPath.set(sessionId, snapshotPath);
|
|
106
|
+
this.snapshots.set(snapshotPath, updatedContent);
|
|
107
|
+
}
|
|
108
|
+
getSnapshotPathForSession(sessionId) {
|
|
109
|
+
return this.sessionToSnapshotPath.get(sessionId);
|
|
110
|
+
}
|
|
111
|
+
async writeSnapshot(snapshotPath) {
|
|
112
|
+
const updatedContent = this.snapshots.get(snapshotPath);
|
|
113
|
+
if (!updatedContent) {
|
|
114
|
+
throw new Error('Unexpected error while writing snapshots, could not find snapshot content.');
|
|
115
|
+
}
|
|
116
|
+
if (updatedContent.includes('/* end snapshot')) {
|
|
117
|
+
// update or create snapshot
|
|
118
|
+
const fileDir = path_1.default.dirname(snapshotPath);
|
|
119
|
+
await mkdirp_1.default(fileDir);
|
|
120
|
+
await writeFile(snapshotPath, updatedContent);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// snapshot file is empty, remove it
|
|
124
|
+
if (await fileExists(snapshotPath)) {
|
|
125
|
+
await unlink(snapshotPath);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function snapshotPlugin(config) {
|
|
131
|
+
const updateSnapshots = config && config.updateSnapshots;
|
|
132
|
+
const snapshots = new SnapshotStore();
|
|
133
|
+
const writePromises = new Set();
|
|
134
|
+
return {
|
|
135
|
+
name: 'file-commands',
|
|
136
|
+
serverStart({ webSockets }) {
|
|
137
|
+
webSockets.on('message', async ({ data }) => {
|
|
138
|
+
const { type, sessionId } = data;
|
|
139
|
+
if (type === 'wtr-session-finished') {
|
|
140
|
+
if (typeof sessionId !== 'string') {
|
|
141
|
+
throw new Error('Missing session id in wtr-session-finished event');
|
|
142
|
+
}
|
|
143
|
+
const snapshotPath = snapshots.getSnapshotPathForSession(sessionId);
|
|
144
|
+
if (!snapshotPath) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const writePromise = snapshots.writeSnapshot(snapshotPath);
|
|
148
|
+
writePromises.add(writePromise);
|
|
149
|
+
await writePromise;
|
|
150
|
+
writePromises.delete(writePromise);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
async serverStop() {
|
|
155
|
+
// ensure all write operations are finished
|
|
156
|
+
await Promise.all([...writePromises]);
|
|
157
|
+
},
|
|
158
|
+
async executeCommand({ command, payload, session }) {
|
|
159
|
+
if (command === 'get-snapshot-config') {
|
|
160
|
+
return { updateSnapshots };
|
|
161
|
+
}
|
|
162
|
+
if (command === 'get-snapshots') {
|
|
163
|
+
const content = await snapshots.get(session.testFile);
|
|
164
|
+
return { content };
|
|
165
|
+
}
|
|
166
|
+
if (command === 'save-snapshot') {
|
|
167
|
+
if (!isSaveSnapshotPayload(payload)) {
|
|
168
|
+
throw new Error('Invalid save snapshot payload');
|
|
169
|
+
}
|
|
170
|
+
await snapshots.saveSnapshot(session.id, session.testFile, payload.name, payload.content);
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
exports.snapshotPlugin = snapshotPlugin;
|
|
177
|
+
//# sourceMappingURL=snapshotPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshotPlugin.js","sourceRoot":"","sources":["../src/snapshotPlugin.ts"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@web/test-runner-commands",
|
|
3
|
+
"version": "0.0.0-canary-20230403143511",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "Web test runner commands",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/modernweb-dev/web.git",
|
|
12
|
+
"directory": "packages/test-runner-commands"
|
|
13
|
+
},
|
|
14
|
+
"author": "modern-web",
|
|
15
|
+
"homepage": "https://github.com/modernweb-dev/web/tree/master/packages/test-runner-commands",
|
|
16
|
+
"main": "browser/commands.mjs",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./browser/commands.d.ts",
|
|
20
|
+
"default": "./browser/commands.mjs"
|
|
21
|
+
},
|
|
22
|
+
"./plugins": {
|
|
23
|
+
"import": "./plugins.mjs",
|
|
24
|
+
"require": "./dist/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=12.0.0"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"test": "mocha test/**/*.test.ts --require ts-node/register",
|
|
33
|
+
"test:watch": "mocha test/**/*.test.ts --require ts-node/register --watch --watch-files src,test --watch-ignore **/*.snap.js"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"*.d.ts",
|
|
37
|
+
"*.js",
|
|
38
|
+
"*.mjs",
|
|
39
|
+
"browser",
|
|
40
|
+
"dist",
|
|
41
|
+
"src"
|
|
42
|
+
],
|
|
43
|
+
"keywords": [
|
|
44
|
+
"web",
|
|
45
|
+
"test",
|
|
46
|
+
"runner",
|
|
47
|
+
"testrunner",
|
|
48
|
+
"commands"
|
|
49
|
+
],
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@web/test-runner-core": "0.0.0-canary-20230403143511",
|
|
52
|
+
"mkdirp": "^1.0.4"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@web/test-runner-chrome": "0.0.0-canary-20230403143511",
|
|
56
|
+
"@web/test-runner-playwright": "0.0.0-canary-20230403143511",
|
|
57
|
+
"@web/test-runner-webdriver": "^0.5.1",
|
|
58
|
+
"mocha": "^8.2.1"
|
|
59
|
+
}
|
|
60
|
+
}
|
package/plugins.d.ts
ADDED
package/plugins.js
ADDED
package/plugins.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// this file is autogenerated with the generate-mjs-dts-entrypoints script
|
|
2
|
+
import cjsEntrypoint from './dist/index.js';
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
setViewportPlugin,
|
|
6
|
+
emulateMediaPlugin,
|
|
7
|
+
setUserAgentPlugin,
|
|
8
|
+
sendKeysPlugin,
|
|
9
|
+
sendMousePlugin,
|
|
10
|
+
a11ySnapshotPlugin,
|
|
11
|
+
filePlugin,
|
|
12
|
+
snapshotPlugin,
|
|
13
|
+
} = cjsEntrypoint;
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
setViewportPlugin,
|
|
17
|
+
emulateMediaPlugin,
|
|
18
|
+
setUserAgentPlugin,
|
|
19
|
+
sendKeysPlugin,
|
|
20
|
+
sendMousePlugin,
|
|
21
|
+
a11ySnapshotPlugin,
|
|
22
|
+
filePlugin,
|
|
23
|
+
snapshotPlugin,
|
|
24
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { TestRunnerPlugin } from '@web/test-runner-core';
|
|
2
|
+
import type { ChromeLauncher, puppeteerCore } from '@web/test-runner-chrome';
|
|
3
|
+
import type { PlaywrightLauncher, playwright } from '@web/test-runner-playwright';
|
|
4
|
+
|
|
5
|
+
export type A11ySnapshotPayload = { selector?: string };
|
|
6
|
+
|
|
7
|
+
export function a11ySnapshotPlugin(): TestRunnerPlugin<A11ySnapshotPayload> {
|
|
8
|
+
return {
|
|
9
|
+
name: 'a11y-snapshot-command',
|
|
10
|
+
async executeCommand({ command, payload, session }): Promise<any> {
|
|
11
|
+
if (command === 'a11y-snapshot') {
|
|
12
|
+
// handle specific behavior for playwright
|
|
13
|
+
if (session.browser.type === 'playwright') {
|
|
14
|
+
const page = (session.browser as PlaywrightLauncher).getPage(session.id);
|
|
15
|
+
const options: {
|
|
16
|
+
root?: playwright.ElementHandle;
|
|
17
|
+
} = {};
|
|
18
|
+
if (payload && payload.selector) {
|
|
19
|
+
const root = await page.$(payload.selector);
|
|
20
|
+
if (root) {
|
|
21
|
+
options.root = root;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const snapshot = await page.accessibility.snapshot(options);
|
|
25
|
+
return snapshot;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// handle specific behavior for puppeteer
|
|
29
|
+
if (session.browser.type === 'puppeteer') {
|
|
30
|
+
const page = (session.browser as ChromeLauncher).getPage(session.id);
|
|
31
|
+
const options: {
|
|
32
|
+
root?: puppeteerCore.ElementHandle;
|
|
33
|
+
} = {};
|
|
34
|
+
if (payload && payload.selector) {
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
const root = await page.$(payload.selector);
|
|
37
|
+
if (root) {
|
|
38
|
+
options.root = root;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
const snapshot = await page.accessibility.snapshot(options);
|
|
43
|
+
return snapshot;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// you might not be able to support all browser launchers
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Acessibility snapshot is not supported for browser type ${session.browser.type}.`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
|
|
5
|
+
export interface Media {
|
|
6
|
+
media?: 'screen' | 'print';
|
|
7
|
+
colorScheme?: 'dark' | 'light' | 'no-preference';
|
|
8
|
+
reducedMotion?: 'reduce' | 'no-preference';
|
|
9
|
+
forcedColors?: 'active' | 'none';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function isObject(payload: unknown): payload is Record<string, unknown> {
|
|
13
|
+
return payload != null && typeof payload === 'object';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function isMediaObject(payload: unknown): payload is Media {
|
|
17
|
+
if (!isObject(payload)) throw new Error('You must provide a viewport object');
|
|
18
|
+
|
|
19
|
+
if (payload.media != null && !(typeof payload.media === 'string')) {
|
|
20
|
+
throw new Error('media should be a string.');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (payload.colorScheme != null && !(typeof payload.colorScheme === 'string')) {
|
|
24
|
+
throw new Error('colorScheme should be a string.');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (payload.reducedMotion != null && !(typeof payload.reducedMotion === 'string')) {
|
|
28
|
+
throw new Error('reducedMotion should be a string.');
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function emulateMediaPlugin(): TestRunnerPlugin {
|
|
34
|
+
return {
|
|
35
|
+
name: 'emulate-media-command',
|
|
36
|
+
|
|
37
|
+
async executeCommand({ command, payload, session }) {
|
|
38
|
+
if (command === 'emulate-media') {
|
|
39
|
+
if (!isMediaObject(payload)) {
|
|
40
|
+
throw new Error('You must provide a viewport object');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (session.browser.type === 'puppeteer') {
|
|
44
|
+
const page = (session.browser as ChromeLauncher).getPage(session.id);
|
|
45
|
+
const features = [];
|
|
46
|
+
|
|
47
|
+
if (payload.colorScheme != null) {
|
|
48
|
+
features.push({ name: 'prefers-color-scheme', value: payload.colorScheme });
|
|
49
|
+
}
|
|
50
|
+
if (payload.reducedMotion != null) {
|
|
51
|
+
features.push({ name: 'prefers-reduced-motion', value: payload.reducedMotion });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
await page.emulateMediaFeatures(features);
|
|
55
|
+
|
|
56
|
+
if (payload.media) {
|
|
57
|
+
await page.emulateMediaType(payload.media);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (session.browser.type === 'playwright') {
|
|
64
|
+
const page = (session.browser as PlaywrightLauncher).getPage(session.id);
|
|
65
|
+
await page.emulateMedia(payload as any);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Setting viewport is not supported for browser type ${session.browser.type}.`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { TestRunnerPlugin } from '@web/test-runner-core';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
import mkdirp from 'mkdirp';
|
|
6
|
+
|
|
7
|
+
const readFile = promisify(fs.readFile);
|
|
8
|
+
const writeFile = promisify(fs.writeFile);
|
|
9
|
+
const unlink = promisify(fs.unlink);
|
|
10
|
+
const access = promisify(fs.access);
|
|
11
|
+
|
|
12
|
+
async function fileExists(filePath: string) {
|
|
13
|
+
try {
|
|
14
|
+
await access(filePath);
|
|
15
|
+
return true;
|
|
16
|
+
} catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isObject(payload: unknown): payload is Record<string, unknown> {
|
|
22
|
+
return payload != null && typeof payload === 'object';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface WriteFilePayload {
|
|
26
|
+
path: string;
|
|
27
|
+
content: string;
|
|
28
|
+
encoding?: BufferEncoding;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ReadFilePayload {
|
|
32
|
+
path: string;
|
|
33
|
+
encoding?: BufferEncoding;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface RemoveFilePayload {
|
|
37
|
+
path: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function isWriteFilePayload(payload: unknown): payload is WriteFilePayload {
|
|
41
|
+
if (!isObject(payload)) throw new Error('You must provide a payload object');
|
|
42
|
+
if (typeof payload.path !== 'string') throw new Error('You must provide a path option');
|
|
43
|
+
if (typeof payload.content !== 'string') throw new Error('You must provide a content option');
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isReadFilePayload(payload: unknown): payload is ReadFilePayload {
|
|
48
|
+
if (!isObject(payload)) throw new Error('You must provide a payload object');
|
|
49
|
+
if (typeof payload.path !== 'string') throw new Error('You must provide a path option');
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function isRemoveFilePayload(payload: unknown): payload is RemoveFilePayload {
|
|
54
|
+
if (!isObject(payload)) throw new Error('You must provide a payload object');
|
|
55
|
+
if (typeof payload.path !== 'string') throw new Error('You must provide a path option');
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function joinFilePath(testFile: string, relativePath: string) {
|
|
60
|
+
if (path.isAbsolute(relativePath)) {
|
|
61
|
+
throw new Error('file path must not be an absolute path.');
|
|
62
|
+
}
|
|
63
|
+
const dir = path.dirname(testFile);
|
|
64
|
+
return path.join(dir, relativePath.split('/').join(path.sep));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function filePlugin(): TestRunnerPlugin {
|
|
68
|
+
return {
|
|
69
|
+
name: 'file-commands',
|
|
70
|
+
|
|
71
|
+
async executeCommand({ command, payload, session }) {
|
|
72
|
+
if (command === 'write-file') {
|
|
73
|
+
if (!isWriteFilePayload(payload)) {
|
|
74
|
+
throw new Error('You must provide a payload object');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const filePath = joinFilePath(session.testFile, payload.path);
|
|
78
|
+
const fileDir = path.dirname(filePath);
|
|
79
|
+
await mkdirp(fileDir);
|
|
80
|
+
await writeFile(filePath, payload.content, payload.encoding || 'utf-8');
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (command === 'read-file') {
|
|
85
|
+
if (!isReadFilePayload(payload)) {
|
|
86
|
+
throw new Error('You must provide a payload object');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const filePath = joinFilePath(session.testFile, payload.path);
|
|
90
|
+
if (await fileExists(filePath)) {
|
|
91
|
+
return readFile(filePath, payload.encoding || 'utf-8');
|
|
92
|
+
} else {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (command === 'remove-file') {
|
|
98
|
+
if (!isRemoveFilePayload(payload)) {
|
|
99
|
+
throw new Error('You must provide a payload object');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const filePath = joinFilePath(session.testFile, payload.path);
|
|
103
|
+
await unlink(filePath);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Viewport, setViewportPlugin } from './setViewportPlugin';
|
|
2
|
+
export { Media, emulateMediaPlugin } from './emulateMediaPlugin';
|
|
3
|
+
export { setUserAgentPlugin } from './setUserAgentPlugin';
|
|
4
|
+
export { sendKeysPlugin, SendKeysPayload } from './sendKeysPlugin';
|
|
5
|
+
export { sendMousePlugin, SendMousePayload } from './sendMousePlugin';
|
|
6
|
+
export { a11ySnapshotPlugin, A11ySnapshotPayload } from './a11ySnapshotPlugin';
|
|
7
|
+
export { WriteFilePayload, ReadFilePayload, RemoveFilePayload, filePlugin } from './filePlugin';
|
|
8
|
+
export { SaveSnapshotPayload, SnapshotPluginConfig, snapshotPlugin } from './snapshotPlugin';
|