@wdio/browser-runner 7.20.8-alpha.504
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/LICENSE-MIT +20 -0
- package/README.md +4 -0
- package/build/browser/commands/debug.d.ts +2 -0
- package/build/browser/commands/debug.d.ts.map +1 -0
- package/build/browser/commands/debug.js +6 -0
- package/build/browser/commands/index.d.ts +3 -0
- package/build/browser/commands/index.d.ts.map +1 -0
- package/build/browser/commands/index.js +6 -0
- package/build/browser/driver.d.ts +4 -0
- package/build/browser/driver.d.ts.map +1 -0
- package/build/browser/driver.js +101 -0
- package/build/browser/mock.d.ts +24 -0
- package/build/browser/mock.d.ts.map +1 -0
- package/build/browser/mock.js +18 -0
- package/build/browser/reporter.d.ts +7 -0
- package/build/browser/reporter.d.ts.map +1 -0
- package/build/browser/reporter.js +8 -0
- package/build/browser/setup.d.ts +9 -0
- package/build/browser/setup.d.ts.map +1 -0
- package/build/browser/setup.js +21 -0
- package/build/constants.d.ts +19 -0
- package/build/constants.d.ts.map +1 -0
- package/build/constants.js +31 -0
- package/build/index.d.ts +27 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +98 -0
- package/build/plugins/testrunner.d.ts +3 -0
- package/build/plugins/testrunner.d.ts.map +1 -0
- package/build/plugins/testrunner.js +121 -0
- package/build/types.d.ts +42 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +1 -0
- package/build/utils.d.ts +7 -0
- package/build/utils.d.ts.map +1 -0
- package/build/utils.js +210 -0
- package/package.json +55 -0
package/LICENSE-MIT
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) OpenJS Foundation and other contributors
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
'Software'), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
18
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
19
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
20
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../src/browser/commands/debug.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,UAAU,KAAK,qBAK5B"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export default function debug() {
|
|
2
|
+
return new Promise((resolve) => {
|
|
3
|
+
console.log('%cDebug Mode Enabled', 'background: #ea5906; color: #fff; padding: 3px; border-radius: 5px;', 'enter the command `wdioDebugContinue()` in the console to continue');
|
|
4
|
+
window.wdioDebugContinue = resolve;
|
|
5
|
+
});
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/browser/commands/index.ts"],"names":[],"mappings":";AAGA,wBAG4C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/browser/driver.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,OAAO,OAAO,WAAW;IAC5B,MAAM,CAAC,UAAU,CACb,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,KAAK,EACf,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACjD,cAAc,EAAE,GAAG;CAuG1B"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { commands } from 'virtual:wdio';
|
|
2
|
+
import { webdriverMonad } from '@wdio/utils';
|
|
3
|
+
import { getEnvironmentVars } from 'webdriver';
|
|
4
|
+
import browserCommands from './commands/index.js';
|
|
5
|
+
const COMMAND_TIMEOUT = 30 * 1000; // 30s
|
|
6
|
+
const CONSOLE_METHODS = ['log', 'info', 'warn', 'error', 'debug'];
|
|
7
|
+
export default class ProxyDriver {
|
|
8
|
+
static newSession(params, modifier, userPrototype, commandWrapper) {
|
|
9
|
+
const commandMessages = new Map();
|
|
10
|
+
const wsUrl = 'ws://' + window.location.host + '/ws';
|
|
11
|
+
const [cid] = window.location.pathname.slice(1).split('/');
|
|
12
|
+
if (!cid) {
|
|
13
|
+
throw new Error('"cid" query parameter is missing');
|
|
14
|
+
}
|
|
15
|
+
console.log(`[WDIO] Connect to testrunner: ${wsUrl}`);
|
|
16
|
+
const socket = new WebSocket(wsUrl);
|
|
17
|
+
const connectPromise = new Promise((resolve) => {
|
|
18
|
+
console.log('[WDIO] Connected to testrunner');
|
|
19
|
+
socket.addEventListener('open', resolve);
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* log all console events once connected
|
|
23
|
+
*/
|
|
24
|
+
connectPromise.then(() => {
|
|
25
|
+
for (const method of CONSOLE_METHODS) {
|
|
26
|
+
const origCommand = console[method].bind(console);
|
|
27
|
+
console[method] = (...args) => {
|
|
28
|
+
socket.send(JSON.stringify({
|
|
29
|
+
name: 'consoleEvent',
|
|
30
|
+
type: method,
|
|
31
|
+
args,
|
|
32
|
+
cid
|
|
33
|
+
}));
|
|
34
|
+
origCommand(...args);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
socket.addEventListener('message', (ev) => {
|
|
39
|
+
try {
|
|
40
|
+
const payload = JSON.parse(ev.data);
|
|
41
|
+
if (!payload.id) {
|
|
42
|
+
return console.error(`Message without id: ${JSON.stringify(ev.data)}`);
|
|
43
|
+
}
|
|
44
|
+
const commandMessage = commandMessages.get(payload.id);
|
|
45
|
+
if (!commandMessage) {
|
|
46
|
+
return console.error(`Unknown command id "${payload.id}"`);
|
|
47
|
+
}
|
|
48
|
+
if (payload.error) {
|
|
49
|
+
console.log(`[WDIO] ${(new Date()).toISOString()} - id: ${payload.id} - ERROR: ${JSON.stringify(payload.result)}`);
|
|
50
|
+
return commandMessage.reject(new Error(payload.error));
|
|
51
|
+
}
|
|
52
|
+
console.log(`[WDIO] ${(new Date()).toISOString()} - id: ${payload.id} - RESULT: ${JSON.stringify(payload.result)}`);
|
|
53
|
+
commandMessage.resolve(payload.result);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
console.error(`Failed handling command socket message "${err.message}"`);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
let commandId = 0;
|
|
60
|
+
const environmentPrototype = getEnvironmentVars(params);
|
|
61
|
+
const protocolCommands = commands.reduce((prev, commandName) => {
|
|
62
|
+
prev[commandName] = {
|
|
63
|
+
value: async (...args) => {
|
|
64
|
+
if (socket.readyState !== 1) {
|
|
65
|
+
await connectPromise;
|
|
66
|
+
}
|
|
67
|
+
commandId++;
|
|
68
|
+
console.log(`[WDIO] ${(new Date()).toISOString()} - id: ${commandId} - COMMAND: ${commandName}(${args.join(', ')})`);
|
|
69
|
+
socket.send(JSON.stringify({ commandName, args, id: commandId, cid }));
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
const commandTimeout = setTimeout(() => reject(new Error(`Command "${commandName}" timed out`)), COMMAND_TIMEOUT);
|
|
72
|
+
commandMessages.set(commandId, { resolve, reject, commandTimeout });
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
return prev;
|
|
77
|
+
}, {});
|
|
78
|
+
const prototype = {
|
|
79
|
+
/**
|
|
80
|
+
* custom protocol commands that communicate with Vite
|
|
81
|
+
*/
|
|
82
|
+
...protocolCommands,
|
|
83
|
+
/**
|
|
84
|
+
* environment flags
|
|
85
|
+
*/
|
|
86
|
+
...environmentPrototype,
|
|
87
|
+
/**
|
|
88
|
+
* unmodified WebdriverIO commands
|
|
89
|
+
*/
|
|
90
|
+
...userPrototype,
|
|
91
|
+
/**
|
|
92
|
+
* custom browser specific commands
|
|
93
|
+
*/
|
|
94
|
+
...browserCommands
|
|
95
|
+
};
|
|
96
|
+
prototype.emit = { writable: true, value: () => { } };
|
|
97
|
+
prototype.on = { writable: true, value: () => { } };
|
|
98
|
+
const monad = webdriverMonad(params, modifier, prototype);
|
|
99
|
+
return monad(window.__wdioEnv__.sessionId, commandWrapper);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* this file content is assigned to modules we mock out for browser compatibility
|
|
3
|
+
*/
|
|
4
|
+
export declare const createRequire: () => {
|
|
5
|
+
(): void;
|
|
6
|
+
resolve(): void;
|
|
7
|
+
};
|
|
8
|
+
export declare const SUPPORTED_BROWSER: never[];
|
|
9
|
+
export declare const locatorStrategy: {};
|
|
10
|
+
export declare class EventEmitter {
|
|
11
|
+
}
|
|
12
|
+
export declare const URL: {
|
|
13
|
+
new (url: string | URL, base?: string | URL | undefined): URL;
|
|
14
|
+
prototype: URL;
|
|
15
|
+
createObjectURL(obj: Blob | MediaSource): string;
|
|
16
|
+
revokeObjectURL(url: string): void;
|
|
17
|
+
};
|
|
18
|
+
export declare const pathToFileURL: () => string;
|
|
19
|
+
export declare const fileURLToPath: () => string;
|
|
20
|
+
export declare const dirname: () => string;
|
|
21
|
+
export declare const resolve: () => string;
|
|
22
|
+
declare const _default: () => void;
|
|
23
|
+
export default _default;
|
|
24
|
+
//# sourceMappingURL=mock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/browser/mock.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,aAAa;;;CAIzB,CAAA;AAED,eAAO,MAAM,iBAAiB,SAAK,CAAA;AACnC,eAAO,MAAM,eAAe,IAAK,CAAA;AACjC,qBAAa,YAAY;CAAG;AAC5B,eAAO,MAAM,GAAG;;;;;CAAa,CAAA;AAC7B,eAAO,MAAM,aAAa,cAAW,CAAA;AACrC,eAAO,MAAM,aAAa,cAAW,CAAA;AACrC,eAAO,MAAM,OAAO,cAAW,CAAA;AAC/B,eAAO,MAAM,OAAO,cAAW,CAAA;;AAC/B,wBAAuB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* this file content is assigned to modules we mock out for browser compatibility
|
|
3
|
+
*/
|
|
4
|
+
export const createRequire = () => {
|
|
5
|
+
const require = () => { };
|
|
6
|
+
require.resolve = () => { };
|
|
7
|
+
return require;
|
|
8
|
+
};
|
|
9
|
+
export const SUPPORTED_BROWSER = [];
|
|
10
|
+
export const locatorStrategy = {};
|
|
11
|
+
export class EventEmitter {
|
|
12
|
+
}
|
|
13
|
+
export const URL = window.URL;
|
|
14
|
+
export const pathToFileURL = () => '';
|
|
15
|
+
export const fileURLToPath = () => '';
|
|
16
|
+
export const dirname = () => '';
|
|
17
|
+
export const resolve = () => '';
|
|
18
|
+
export default () => { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../src/browser/reporter.ts"],"names":[],"mappings":"AACA,QAAA,MAAM,YAAY,KAAuB,CAAA;AAEzC,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,YAAY;gBACrC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG;IAItC,aAAa;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/browser/setup.ts"],"names":[],"mappings":"AAKA,aAAK,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC,CAAA;AAE9D,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,cAAc,EAAE,cAAc,EAAE,CAAA;KACnC;CACJ;AAQD,wBAAsB,QAAQ,kBAW7B"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { automationProtocolPath } from 'virtual:wdio';
|
|
2
|
+
import { expect } from 'expect-webdriverio';
|
|
3
|
+
import { remote } from 'webdriverio';
|
|
4
|
+
import { _setGlobal } from '@wdio/globals';
|
|
5
|
+
window.__wdioErrors__ = [];
|
|
6
|
+
addEventListener('error', (ev) => window.__wdioErrors__.push({
|
|
7
|
+
filename: ev.filename,
|
|
8
|
+
message: ev.message
|
|
9
|
+
}));
|
|
10
|
+
export async function setupEnv() {
|
|
11
|
+
const injectGlobals = window.__wdioEnv__.injectGlobals;
|
|
12
|
+
const browser = await remote({
|
|
13
|
+
automationProtocol: automationProtocolPath,
|
|
14
|
+
capabilities: window.__wdioEnv__.capabilities
|
|
15
|
+
});
|
|
16
|
+
_setGlobal('browser', browser, injectGlobals);
|
|
17
|
+
_setGlobal('driver', browser, injectGlobals);
|
|
18
|
+
_setGlobal('expect', expect, injectGlobals);
|
|
19
|
+
_setGlobal('$', browser.$.bind(browser), injectGlobals);
|
|
20
|
+
_setGlobal('$$', browser.$.bind(browser), injectGlobals);
|
|
21
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Browser } from 'webdriverio';
|
|
2
|
+
import type { Environment, FrameworkPreset } from './types';
|
|
3
|
+
export declare const SESSIONS: Map<string, Environment>;
|
|
4
|
+
export declare const BROWSER_POOL: Map<string, Browser<'async'>>;
|
|
5
|
+
export declare const EVENTS: {
|
|
6
|
+
readonly suite: "suite:start";
|
|
7
|
+
readonly 'suite end': "suite:end";
|
|
8
|
+
readonly test: "test:start";
|
|
9
|
+
readonly 'test end': "test:end";
|
|
10
|
+
readonly hook: "hook:start";
|
|
11
|
+
readonly 'hook end': "hook:end";
|
|
12
|
+
readonly pass: "test:pass";
|
|
13
|
+
readonly fail: "test:fail";
|
|
14
|
+
readonly retry: "test:retry";
|
|
15
|
+
readonly pending: "test:pending";
|
|
16
|
+
};
|
|
17
|
+
export declare const PRESET_DEPENDENCIES: Record<FrameworkPreset, [string, string, any] | undefined>;
|
|
18
|
+
export declare const FRAMEWORK_SUPPORT_ERROR = "Currently only \"mocha\" is supported as framework when using @wdio/browser-runner.";
|
|
19
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE3D,eAAO,MAAM,QAAQ,0BAAiC,CAAA;AACtD,eAAO,MAAM,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAa,CAAA;AAEpE,eAAO,MAAM,MAAM;;;;;;;;;;;CAWT,CAAA;AAEV,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAe1F,CAAA;AAED,eAAO,MAAM,uBAAuB,wFAAsF,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const SESSIONS = new Map();
|
|
2
|
+
export const BROWSER_POOL = new Map();
|
|
3
|
+
export const EVENTS = {
|
|
4
|
+
'suite': 'suite:start',
|
|
5
|
+
'suite end': 'suite:end',
|
|
6
|
+
'test': 'test:start',
|
|
7
|
+
'test end': 'test:end',
|
|
8
|
+
'hook': 'hook:start',
|
|
9
|
+
'hook end': 'hook:end',
|
|
10
|
+
'pass': 'test:pass',
|
|
11
|
+
'fail': 'test:fail',
|
|
12
|
+
'retry': 'test:retry',
|
|
13
|
+
'pending': 'test:pending'
|
|
14
|
+
};
|
|
15
|
+
export const PRESET_DEPENDENCIES = {
|
|
16
|
+
react: ['@vitejs/plugin-react', 'default', {
|
|
17
|
+
babel: {
|
|
18
|
+
assumptions: {
|
|
19
|
+
setPublicClassFields: true
|
|
20
|
+
},
|
|
21
|
+
parserOpts: {
|
|
22
|
+
plugins: ['decorators-legacy', 'classProperties']
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}],
|
|
26
|
+
preact: ['@preact/preset-vite', 'default', undefined],
|
|
27
|
+
vue: ['@vitejs/plugin-vue', 'default', undefined],
|
|
28
|
+
svelte: ['@sveltejs/vite-plugin-svelte', 'svelte', undefined],
|
|
29
|
+
lit: undefined
|
|
30
|
+
};
|
|
31
|
+
export const FRAMEWORK_SUPPORT_ERROR = 'Currently only "mocha" is supported as framework when using @wdio/browser-runner.';
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import LocalRunner, { RunArgs } from '@wdio/local-runner';
|
|
2
|
+
import type { Options } from '@wdio/types';
|
|
3
|
+
import type { BrowserRunnerOptions as BrowserRunnerOptionsImport } from './types';
|
|
4
|
+
export default class BrowserRunner extends LocalRunner {
|
|
5
|
+
#private;
|
|
6
|
+
private options;
|
|
7
|
+
private config;
|
|
8
|
+
constructor(options: BrowserRunnerOptionsImport, config: Options.Testrunner);
|
|
9
|
+
/**
|
|
10
|
+
* nothing to initialise when running locally
|
|
11
|
+
*/
|
|
12
|
+
initialise(): Promise<void>;
|
|
13
|
+
run(runArgs: RunArgs): import("@wdio/local-runner/build/worker.js").default;
|
|
14
|
+
/**
|
|
15
|
+
* shutdown vite server
|
|
16
|
+
*
|
|
17
|
+
* @return {Promise} resolves when vite server has been shutdown
|
|
18
|
+
*/
|
|
19
|
+
shutdown(): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
declare global {
|
|
22
|
+
namespace WebdriverIO {
|
|
23
|
+
interface BrowserRunnerOptions extends BrowserRunnerOptionsImport {
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,EAAE,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAKzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAI1C,OAAO,KAAK,EAAE,oBAAoB,IAAI,0BAA0B,EAAgB,MAAM,SAAS,CAAA;AAI/F,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;;IAMtC,OAAO,CAAC,OAAO;IAA8B,OAAO,CAAC,MAAM;gBAAnD,OAAO,EAAE,0BAA0B,EAAU,MAAM,EAAE,OAAO,CAAC,UAAU;IAW3F;;OAEG;IACG,UAAU;IAgChB,GAAG,CAAE,OAAO,EAAE,OAAO;IA8BrB;;;;OAIG;IACG,QAAQ;CAOjB;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,WAAW,CAAC;QAClB,UAAU,oBAAqB,SAAQ,0BAA0B;SAAG;KACvE;CACJ"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import logger from '@wdio/logger';
|
|
2
|
+
import getPort from 'get-port';
|
|
3
|
+
import LocalRunner from '@wdio/local-runner';
|
|
4
|
+
import { attach } from 'webdriverio';
|
|
5
|
+
import { createServer } from 'vite';
|
|
6
|
+
import { FRAMEWORK_SUPPORT_ERROR, SESSIONS, BROWSER_POOL } from './constants.js';
|
|
7
|
+
import { getViteConfig } from './utils.js';
|
|
8
|
+
const log = logger('@wdio/browser-runner');
|
|
9
|
+
export default class BrowserRunner extends LocalRunner {
|
|
10
|
+
options;
|
|
11
|
+
config;
|
|
12
|
+
#options;
|
|
13
|
+
#config;
|
|
14
|
+
#server;
|
|
15
|
+
#wss;
|
|
16
|
+
constructor(options, config) {
|
|
17
|
+
super(options, config);
|
|
18
|
+
this.options = options;
|
|
19
|
+
this.config = config;
|
|
20
|
+
if (config.framework !== 'mocha') {
|
|
21
|
+
throw new Error(FRAMEWORK_SUPPORT_ERROR);
|
|
22
|
+
}
|
|
23
|
+
this.#options = options;
|
|
24
|
+
this.#config = config;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* nothing to initialise when running locally
|
|
28
|
+
*/
|
|
29
|
+
async initialise() {
|
|
30
|
+
const rootDir = this.#options.rootDir || process.cwd();
|
|
31
|
+
log.info('Initiate browser environment');
|
|
32
|
+
try {
|
|
33
|
+
const port = await getPort();
|
|
34
|
+
const [viteConfig, wss] = await getViteConfig(this.#options, rootDir, port);
|
|
35
|
+
this.#server = await createServer(viteConfig);
|
|
36
|
+
await this.#server.listen();
|
|
37
|
+
log.info(`Vite server started successfully on port ${port}, root directory: ${rootDir}`);
|
|
38
|
+
/**
|
|
39
|
+
* propagate console events
|
|
40
|
+
*/
|
|
41
|
+
wss.on('connection', (ws) => ws.on('message', (payload) => {
|
|
42
|
+
try {
|
|
43
|
+
const message = JSON.parse(payload);
|
|
44
|
+
const isWDIOLog = Boolean(typeof message.args[0] === 'string' && message.args[0].startsWith('[WDIO]'));
|
|
45
|
+
if (message.name !== 'consoleEvent' || isWDIOLog) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
console[message.type](`[${message.cid}]`, ...(message.args || []));
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
throw new Error(`Vite server failed to start: ${err.stack}`);
|
|
57
|
+
}
|
|
58
|
+
await super.initialise();
|
|
59
|
+
}
|
|
60
|
+
run(runArgs) {
|
|
61
|
+
if (runArgs.command === 'run') {
|
|
62
|
+
runArgs.args.baseUrl = `http://localhost:${this.#server?.config.server.port}`;
|
|
63
|
+
}
|
|
64
|
+
const worker = super.run(runArgs);
|
|
65
|
+
worker.on('message', async (payload) => {
|
|
66
|
+
if (payload.name === 'sessionStarted') {
|
|
67
|
+
SESSIONS.set(payload.cid, {
|
|
68
|
+
args: this.#config.mochaOpts || {},
|
|
69
|
+
capabilities: payload.content.capabilities,
|
|
70
|
+
sessionId: payload.content.sessionId,
|
|
71
|
+
injectGlobals: payload.content.injectGlobals
|
|
72
|
+
});
|
|
73
|
+
BROWSER_POOL.set(payload.cid, await attach({
|
|
74
|
+
sessionId: payload.content.sessionId,
|
|
75
|
+
options: this.#config,
|
|
76
|
+
capabilities: payload.content.capabilities
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
if (payload.name === 'sessionEnded') {
|
|
80
|
+
SESSIONS.delete(payload.cid);
|
|
81
|
+
BROWSER_POOL.delete(payload.cid);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return worker;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* shutdown vite server
|
|
88
|
+
*
|
|
89
|
+
* @return {Promise} resolves when vite server has been shutdown
|
|
90
|
+
*/
|
|
91
|
+
async shutdown() {
|
|
92
|
+
await super.shutdown();
|
|
93
|
+
if (this.#server) {
|
|
94
|
+
log.info('Shutting down Vite server');
|
|
95
|
+
await this.#server.close();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testrunner.d.ts","sourceRoot":"","sources":["../../src/plugins/testrunner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAyClC,wBAAgB,UAAU,CAAE,OAAO,EAAE,WAAW,CAAC,oBAAoB,GAAG,MAAM,CA0G7E"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import url from 'node:url';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import logger from '@wdio/logger';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { WebDriverProtocol, MJsonWProtocol, JsonWProtocol, AppiumProtocol, ChromiumProtocol, SauceLabsProtocol, SeleniumProtocol, GeckoProtocol, WebDriverBidiProtocol } from '@wdio/protocols';
|
|
6
|
+
import { SESSIONS } from '../constants.js';
|
|
7
|
+
import { getTemplate, getErrorTemplate } from '../utils.js';
|
|
8
|
+
const log = logger('@wdio/browser-runner:plugin');
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
|
11
|
+
const commands = {
|
|
12
|
+
...WebDriverProtocol,
|
|
13
|
+
...MJsonWProtocol,
|
|
14
|
+
...JsonWProtocol,
|
|
15
|
+
...AppiumProtocol,
|
|
16
|
+
...ChromiumProtocol,
|
|
17
|
+
...SauceLabsProtocol,
|
|
18
|
+
...SeleniumProtocol,
|
|
19
|
+
...GeckoProtocol,
|
|
20
|
+
...WebDriverBidiProtocol
|
|
21
|
+
};
|
|
22
|
+
const protocolCommandList = Object.values(commands).map((endpoint) => Object.values(endpoint).map(({ command }) => command)).flat();
|
|
23
|
+
const WDIO_PACKAGES = ['webdriverio', 'expect-webdriverio'];
|
|
24
|
+
const virtualModuleId = 'virtual:wdio';
|
|
25
|
+
const resolvedVirtualModuleId = '\0' + virtualModuleId;
|
|
26
|
+
const MODULES_TO_MOCK = [
|
|
27
|
+
'node:module', 'node:events', 'node:path', 'node:url', 'puppeteer-core', 'archiver',
|
|
28
|
+
'query-selector-shadow-dom/plugins/puppeteer/index.js',
|
|
29
|
+
'query-selector-shadow-dom/plugins/webdriverio/index.js',
|
|
30
|
+
'glob', 'devtools'
|
|
31
|
+
];
|
|
32
|
+
export function testrunner(options) {
|
|
33
|
+
const automationProtocolPath = path.resolve(__dirname, '..', 'browser', 'driver.js');
|
|
34
|
+
const mockModulePath = path.resolve(__dirname, '..', 'browser', 'mock.js');
|
|
35
|
+
const setupModulePath = path.resolve(__dirname, '..', 'browser', 'setup.js');
|
|
36
|
+
const reporterPath = path.resolve(__dirname, '..', 'browser', 'reporter.js');
|
|
37
|
+
return {
|
|
38
|
+
name: 'wdio:testrunner',
|
|
39
|
+
enforce: 'pre',
|
|
40
|
+
resolveId: (id) => {
|
|
41
|
+
if (id === virtualModuleId) {
|
|
42
|
+
return resolvedVirtualModuleId;
|
|
43
|
+
}
|
|
44
|
+
if (id === '@wdio/browser-runner/setup') {
|
|
45
|
+
return setupModulePath;
|
|
46
|
+
}
|
|
47
|
+
if (id === '@wdio/browser-runner/reporter') {
|
|
48
|
+
return reporterPath;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* make sure WDIO imports are resolved properly as ESM module
|
|
52
|
+
*/
|
|
53
|
+
if (id.startsWith('@wdio') || WDIO_PACKAGES.includes(id)) {
|
|
54
|
+
return require.resolve(id).replace('/cjs', '');
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* mock out imports that we can't transpile into browser land
|
|
58
|
+
*/
|
|
59
|
+
if (MODULES_TO_MOCK.includes(id)) {
|
|
60
|
+
return mockModulePath;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
load(id) {
|
|
64
|
+
/**
|
|
65
|
+
* provide a list of protocol commands to generate the prototype in the browser
|
|
66
|
+
*/
|
|
67
|
+
if (id === resolvedVirtualModuleId) {
|
|
68
|
+
return /*js*/ `
|
|
69
|
+
export const commands = ${JSON.stringify(protocolCommandList)}
|
|
70
|
+
export const automationProtocolPath = ${JSON.stringify(automationProtocolPath)}
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
transform(code, id) {
|
|
75
|
+
if (id.includes('.vite/deps/expect.js')) {
|
|
76
|
+
return {
|
|
77
|
+
code: code.replace('var fs = _interopRequireWildcard(require_graceful_fs());', 'var fs = {};').replace('var expect_default = require_build11();', 'var expect_default = require_build11();\nwindow.expect = expect_default.default;').replace('process.stdout.isTTY', 'false')
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return { code };
|
|
81
|
+
},
|
|
82
|
+
configureServer(server) {
|
|
83
|
+
return () => {
|
|
84
|
+
server.middlewares.use('/', async (req, res, next) => {
|
|
85
|
+
log.info(`Received request for: ${req.url}`);
|
|
86
|
+
if (!req.url) {
|
|
87
|
+
return next();
|
|
88
|
+
}
|
|
89
|
+
const urlParsed = url.parse(req.url);
|
|
90
|
+
// if request is not html , directly return next()
|
|
91
|
+
if (!urlParsed.pathname || !urlParsed.path || !urlParsed.pathname.endsWith('test.html')) {
|
|
92
|
+
return next();
|
|
93
|
+
}
|
|
94
|
+
const urlParamString = new URLSearchParams(urlParsed.query || '');
|
|
95
|
+
const [cid] = urlParsed.pathname.slice(1).split('/');
|
|
96
|
+
const spec = urlParamString.get('spec');
|
|
97
|
+
if (!cid || !SESSIONS.has(cid)) {
|
|
98
|
+
log.error(`No environment found for ${cid || 'non determined environment'}`);
|
|
99
|
+
return next();
|
|
100
|
+
}
|
|
101
|
+
if (!spec) {
|
|
102
|
+
log.error('No spec file was defined to run for this environment');
|
|
103
|
+
return next();
|
|
104
|
+
}
|
|
105
|
+
const env = SESSIONS.get(cid);
|
|
106
|
+
try {
|
|
107
|
+
const template = await getTemplate(options, env, spec);
|
|
108
|
+
log.debug(`Render template for ${req.url}`);
|
|
109
|
+
res.end(await server.transformIndexHtml(`${req.url}`, template));
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
const template = await getErrorTemplate(req.url, err);
|
|
113
|
+
log.error(`Failed to render template: ${err.message}`);
|
|
114
|
+
res.end(await server.transformIndexHtml(`${req.url}`, template));
|
|
115
|
+
}
|
|
116
|
+
return next();
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
package/build/types.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { InlineConfig } from 'vite';
|
|
2
|
+
import type { Workers, Capabilities } from '@wdio/types';
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
__wdioEnv__: Environment;
|
|
6
|
+
wdioDebugContinue: (value: unknown) => void;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare type FrameworkPreset = 'react' | 'preact' | 'vue' | 'svelte' | 'lit';
|
|
10
|
+
export interface BrowserRunnerOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Project root directory
|
|
13
|
+
* @default process.cwd()
|
|
14
|
+
*/
|
|
15
|
+
rootDir?: string;
|
|
16
|
+
/**
|
|
17
|
+
* WebdriverIOs browser runner supports a set of presets to test for a specific framework.
|
|
18
|
+
*/
|
|
19
|
+
preset?: FrameworkPreset;
|
|
20
|
+
/**
|
|
21
|
+
* Vite configuration to overwrite the preset
|
|
22
|
+
*/
|
|
23
|
+
viteConfig?: InlineConfig;
|
|
24
|
+
}
|
|
25
|
+
export interface RunArgs extends Workers.WorkerRunPayload {
|
|
26
|
+
command: string;
|
|
27
|
+
args: any;
|
|
28
|
+
cid: string;
|
|
29
|
+
}
|
|
30
|
+
export interface Environment {
|
|
31
|
+
args: any;
|
|
32
|
+
capabilities: Capabilities.RemoteCapability;
|
|
33
|
+
sessionId: string;
|
|
34
|
+
injectGlobals: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface ConsoleEvent {
|
|
37
|
+
name: 'consoleEvent';
|
|
38
|
+
type: 'log' | 'info' | 'warn' | 'debug' | 'error';
|
|
39
|
+
args: unknown[];
|
|
40
|
+
cid: string;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AACxC,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAExD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,WAAW,EAAE,WAAW,CAAA;QACxB,iBAAiB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;KAC9C;CACJ;AAED,oBAAY,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAA;AAE3E,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB;;OAEG;IACH,UAAU,CAAC,EAAE,YAAY,CAAA;CAC5B;AAED,MAAM,WAAW,OAAQ,SAAQ,OAAO,CAAC,gBAAgB;IACrD,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,GAAG,CAAA;IACT,GAAG,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,GAAG,CAAA;IACT,YAAY,EAAE,YAAY,CAAC,gBAAgB,CAAA;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,cAAc,CAAA;IACpB,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;IACjD,IAAI,EAAE,OAAO,EAAE,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;CACd"}
|
package/build/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/build/utils.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { WebSocketServer } from 'ws';
|
|
2
|
+
import type { InlineConfig } from 'vite';
|
|
3
|
+
import type { Environment } from './types';
|
|
4
|
+
export declare function getTemplate(options: WebdriverIO.BrowserRunnerOptions, env: Environment, spec: string): Promise<string>;
|
|
5
|
+
export declare function getErrorTemplate(filename: string, error: Error): Promise<string>;
|
|
6
|
+
export declare function getViteConfig(options: WebdriverIO.BrowserRunnerOptions, root: string, port: number): Promise<[Partial<InlineConfig>, WebSocketServer]>;
|
|
7
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,eAAe,EAAa,MAAM,IAAI,CAAA;AAI/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAKxC,OAAO,KAAK,EAAE,WAAW,EAAmB,MAAM,SAAS,CAAA;AAI3D,wBAAsB,WAAW,CAAE,OAAO,EAAE,WAAW,CAAC,oBAAoB,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,mBA2E3G;AAED,wBAAsB,gBAAgB,CAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,mBAUrE;AAiBD,wBAAsB,aAAa,CAC/B,OAAO,EAAE,WAAW,CAAC,oBAAoB,EACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,eAAe,CAAC,CAAC,CAyEnD"}
|
package/build/utils.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import getPort from 'get-port';
|
|
5
|
+
import topLevelAwait from 'vite-plugin-top-level-await';
|
|
6
|
+
import { WebSocketServer } from 'ws';
|
|
7
|
+
import { esbuildCommonjs } from '@originjs/vite-plugin-commonjs';
|
|
8
|
+
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill';
|
|
9
|
+
import logger from '@wdio/logger';
|
|
10
|
+
import { testrunner } from './plugins/testrunner.js';
|
|
11
|
+
import { EVENTS, PRESET_DEPENDENCIES, BROWSER_POOL } from './constants.js';
|
|
12
|
+
const log = logger('@wdio/browser-runner');
|
|
13
|
+
export async function getTemplate(options, env, spec) {
|
|
14
|
+
const root = options.rootDir || process.cwd();
|
|
15
|
+
const require = createRequire(path.join(root, 'node_modules'));
|
|
16
|
+
const listeners = Object.entries(EVENTS).map(([mochaEvent, wdioEvent]) => (
|
|
17
|
+
/*js*/ `runner.on('${mochaEvent}', (payload) => {
|
|
18
|
+
window.__wdioEvents__.push(formatMessage({ type: '${wdioEvent}', payload, err: payload.err }))
|
|
19
|
+
})`)).join('\n');
|
|
20
|
+
let vueDeps = '';
|
|
21
|
+
if (options.preset === 'vue') {
|
|
22
|
+
try {
|
|
23
|
+
const vueDir = path.dirname(require.resolve('vue'));
|
|
24
|
+
const vueScript = (await fs.readFile(path.join(vueDir, 'dist', 'vue.global.prod.js'), 'utf-8')).toString();
|
|
25
|
+
vueDeps += /*html*/ `
|
|
26
|
+
<script type="module">
|
|
27
|
+
${vueScript}
|
|
28
|
+
window.Vue = Vue
|
|
29
|
+
</script>`;
|
|
30
|
+
const vueCompilerDir = path.dirname(require.resolve('@vue/compiler-dom'));
|
|
31
|
+
const vueCompilerScript = (await fs.readFile(path.join(vueCompilerDir, 'dist', 'compiler-dom.global.prod.js'), 'utf-8')).toString();
|
|
32
|
+
vueDeps += /*html*/ `
|
|
33
|
+
<script type="module">
|
|
34
|
+
${vueCompilerScript}
|
|
35
|
+
window.VueCompilerDOM = VueCompilerDOM
|
|
36
|
+
</script>`;
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
throw new Error(`Fail to set-up Vue environment: ${err.message}\n\n` +
|
|
40
|
+
'Make sure you have "vue" and "@vue/compiler-dom" installed as dependencies!');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return /* html */ `
|
|
44
|
+
<!doctype html>
|
|
45
|
+
<html>
|
|
46
|
+
<head>
|
|
47
|
+
<title>WebdriverIO Browser Test</title>
|
|
48
|
+
<link rel="stylesheet" href="https://unpkg.com/mocha@10.0.0/mocha.css">
|
|
49
|
+
<script type="module">
|
|
50
|
+
/**
|
|
51
|
+
* Inject environment variables
|
|
52
|
+
*/
|
|
53
|
+
window.__wdioEnv__ = ${JSON.stringify(env)}
|
|
54
|
+
</script>
|
|
55
|
+
${vueDeps}
|
|
56
|
+
<script type="module">
|
|
57
|
+
import Mocha from 'https://esm.sh/mocha@10.0.0'
|
|
58
|
+
import HTMLReporter from '@wdio/browser-runner/reporter'
|
|
59
|
+
const mochaOpts = ${JSON.stringify(env.args || {})}
|
|
60
|
+
const mocha = Mocha.setup({
|
|
61
|
+
...mochaOpts,
|
|
62
|
+
reporter: HTMLReporter
|
|
63
|
+
})
|
|
64
|
+
</script>
|
|
65
|
+
</head>
|
|
66
|
+
<body>
|
|
67
|
+
<div id="mocha"></div>
|
|
68
|
+
<script async type="module">
|
|
69
|
+
import { setupEnv } from '@wdio/browser-runner/setup'
|
|
70
|
+
import { formatMessage } from '@wdio/mocha-framework/common'
|
|
71
|
+
|
|
72
|
+
await setupEnv()
|
|
73
|
+
await import('${spec}')
|
|
74
|
+
|
|
75
|
+
window.__wdioEvents__ = []
|
|
76
|
+
console.log('[WDIO] Start Mocha testsuite')
|
|
77
|
+
const runner = mocha.run((failures) => {
|
|
78
|
+
window.__wdioFailures__ = failures
|
|
79
|
+
})
|
|
80
|
+
${listeners}
|
|
81
|
+
</script>
|
|
82
|
+
</body>
|
|
83
|
+
</html>`;
|
|
84
|
+
}
|
|
85
|
+
export async function getErrorTemplate(filename, error) {
|
|
86
|
+
return /*html*/ `
|
|
87
|
+
<pre>${error.stack}</pre>
|
|
88
|
+
<script type="module">
|
|
89
|
+
window.__wdioErrors__ = [{
|
|
90
|
+
filename: "${filename}",
|
|
91
|
+
message: \`${error.message}\`
|
|
92
|
+
}]
|
|
93
|
+
</script>
|
|
94
|
+
`;
|
|
95
|
+
}
|
|
96
|
+
async function userfriendlyImport(preset, pkg) {
|
|
97
|
+
if (!pkg) {
|
|
98
|
+
return {};
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
return await import(pkg);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
throw new Error(`Couldn't load preset "${preset}" given important dependency ("${pkg}") is not installed.\n` +
|
|
105
|
+
`Please run:\n\n\tnpm install ${pkg}\n\tor\n\tyarn add --dev ${pkg}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export async function getViteConfig(options, root, port) {
|
|
109
|
+
const wsPort = await getPort();
|
|
110
|
+
const wss = new WebSocketServer({ port: wsPort });
|
|
111
|
+
wss.on('connection', (ws) => ws.on('message', handleBrowserCommand(ws)));
|
|
112
|
+
/**
|
|
113
|
+
* user provided vite config
|
|
114
|
+
*/
|
|
115
|
+
if (options.viteConfig) {
|
|
116
|
+
options.viteConfig.plugins = [
|
|
117
|
+
...(options.viteConfig.plugins || []),
|
|
118
|
+
testrunner(options)
|
|
119
|
+
];
|
|
120
|
+
options.viteConfig.server = {
|
|
121
|
+
...(options.viteConfig.server || {}),
|
|
122
|
+
proxy: {
|
|
123
|
+
...(options.viteConfig.server?.proxy || {}),
|
|
124
|
+
'/ws': {
|
|
125
|
+
target: `ws://localhost:${wsPort}`,
|
|
126
|
+
ws: true
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
return [options.viteConfig, wss];
|
|
131
|
+
}
|
|
132
|
+
const config = {
|
|
133
|
+
configFile: false,
|
|
134
|
+
root,
|
|
135
|
+
server: {
|
|
136
|
+
port,
|
|
137
|
+
host: 'localhost',
|
|
138
|
+
proxy: {
|
|
139
|
+
'/ws': {
|
|
140
|
+
target: `ws://localhost:${wsPort}`,
|
|
141
|
+
ws: true
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
logLevel: 'silent',
|
|
146
|
+
plugins: [
|
|
147
|
+
testrunner(options),
|
|
148
|
+
topLevelAwait()
|
|
149
|
+
],
|
|
150
|
+
optimizeDeps: {
|
|
151
|
+
include: ['expect', 'jest-matcher-utils'],
|
|
152
|
+
esbuildOptions: {
|
|
153
|
+
logLevel: 'silent',
|
|
154
|
+
// Node.js global to browser globalThis
|
|
155
|
+
define: {
|
|
156
|
+
global: 'globalThis',
|
|
157
|
+
},
|
|
158
|
+
// Enable esbuild polyfill plugins
|
|
159
|
+
plugins: [
|
|
160
|
+
NodeGlobalsPolyfillPlugin({
|
|
161
|
+
process: true,
|
|
162
|
+
buffer: true
|
|
163
|
+
}),
|
|
164
|
+
esbuildCommonjs(['@testing-library/vue'])
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
if (options.preset) {
|
|
170
|
+
const [pkg, importProp, opts] = PRESET_DEPENDENCIES[options.preset] || [];
|
|
171
|
+
const plugin = (await userfriendlyImport(options.preset, pkg))[importProp || 'default'];
|
|
172
|
+
if (plugin) {
|
|
173
|
+
config.plugins.push(plugin(opts));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return [config, wss];
|
|
177
|
+
}
|
|
178
|
+
function handleBrowserCommand(ws) {
|
|
179
|
+
return async (data) => {
|
|
180
|
+
try {
|
|
181
|
+
const payload = JSON.parse(data.toString());
|
|
182
|
+
if (!payload.commandName) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
log.info(`Received browser message: ${data}`);
|
|
186
|
+
const cid = payload.cid;
|
|
187
|
+
if (typeof cid !== 'string') {
|
|
188
|
+
return ws.send(JSON.stringify({
|
|
189
|
+
id: payload.id,
|
|
190
|
+
error: `No "cid" property passed into command message with id "${payload.id}"`
|
|
191
|
+
}));
|
|
192
|
+
}
|
|
193
|
+
const browser = await BROWSER_POOL.get(payload.cid);
|
|
194
|
+
if (!browser) {
|
|
195
|
+
return ws.send(JSON.stringify({
|
|
196
|
+
id: payload.id,
|
|
197
|
+
error: `Couldn't find browser with cid "${payload.cid}"`
|
|
198
|
+
}));
|
|
199
|
+
}
|
|
200
|
+
const result = await browser[payload.commandName](...payload.args);
|
|
201
|
+
const resultMsg = JSON.stringify({ id: payload.id, result });
|
|
202
|
+
log.info(`Return command result: ${resultMsg}`);
|
|
203
|
+
return ws.send(resultMsg);
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
log.error(`Failed handling command: ${err.message}`);
|
|
207
|
+
return ws.send(JSON.stringify({ error: `Failed handling command message: ${err.message}` }));
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wdio/browser-runner",
|
|
3
|
+
"version": "7.20.8-alpha.504+428a9d729",
|
|
4
|
+
"description": "A WebdriverIO runner to run unit tests tests in the browser.",
|
|
5
|
+
"author": "Christian Bromann <mail@bromann.dev>",
|
|
6
|
+
"homepage": "https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-browser-runner",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": "^16.13 || >=18"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git://github.com/webdriverio/webdriverio.git",
|
|
14
|
+
"directory": "packages/wdio-browser-runner"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"webdriver",
|
|
18
|
+
"webdriverio",
|
|
19
|
+
"wdio",
|
|
20
|
+
"wdio-runner"
|
|
21
|
+
],
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/webdriverio/webdriverio/issues"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": "./build/index.js",
|
|
27
|
+
"types": "./build/index.d.ts",
|
|
28
|
+
"typeScriptVersion": "3.8.3",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
31
|
+
"@esbuild-plugins/node-globals-polyfill": "^0.1.1",
|
|
32
|
+
"@originjs/vite-plugin-commonjs": "^1.0.3",
|
|
33
|
+
"@wdio/globals": "7.20.8-alpha.504+428a9d729",
|
|
34
|
+
"@wdio/local-runner": "7.20.8-alpha.504+428a9d729",
|
|
35
|
+
"@wdio/logger": "7.20.8-alpha.504+428a9d729",
|
|
36
|
+
"@wdio/mocha-framework": "7.20.8-alpha.504+428a9d729",
|
|
37
|
+
"@wdio/protocols": "7.20.8-alpha.504+428a9d729",
|
|
38
|
+
"@wdio/runner": "7.20.8-alpha.504+428a9d729",
|
|
39
|
+
"@wdio/types": "7.20.8-alpha.504+428a9d729",
|
|
40
|
+
"expect-webdriverio": "^4.0.0-alpha.4",
|
|
41
|
+
"get-port": "^6.1.2",
|
|
42
|
+
"vite": "^3.1.7",
|
|
43
|
+
"vite-plugin-top-level-await": "^1.2.1",
|
|
44
|
+
"webdriver": "7.20.8-alpha.504+428a9d729",
|
|
45
|
+
"webdriverio": "7.20.8-alpha.504+428a9d729",
|
|
46
|
+
"ws": "^8.10.0"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/ws": "^8.5.3"
|
|
53
|
+
},
|
|
54
|
+
"gitHead": "428a9d729ae6231968a60908732fa3f607d195e9"
|
|
55
|
+
}
|