@wdio/browser-runner 8.27.0 → 8.28.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/browser/driver.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,OAAO,OAAO,WAAW;;IAG5B,MAAM,CAAC,UAAU,CACb,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,KAAK,EACf,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACjD,cAAc,EAAE,GAAG;CA+J1B"}
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/browser/driver.ts"],"names":[],"mappings":"AAqBA,MAAM,CAAC,OAAO,OAAO,WAAW;;IAG5B,MAAM,CAAC,UAAU,CACb,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,KAAK,EACf,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACjD,cAAc,EAAE,GAAG;CAoL1B"}
@@ -1,13 +1,15 @@
1
- import stringify from 'fast-safe-stringify';
2
1
  import { commands } from 'virtual:wdio';
3
2
  import { webdriverMonad, sessionEnvironmentDetector } from '@wdio/utils';
4
3
  import { getEnvironmentVars } from 'webdriver';
4
+ import { MESSAGE_TYPES } from '@wdio/types';
5
+ import { browser } from '@wdio/globals';
5
6
  import { getCID } from './utils.js';
6
- import { MESSAGE_TYPES } from '../constants.js';
7
+ import { WDIO_EVENT_NAME } from '../constants.js';
7
8
  const COMMAND_TIMEOUT = 30 * 1000; // 30s
8
9
  const CONSOLE_METHODS = ['log', 'info', 'warn', 'error', 'debug'];
9
10
  const HIDE_REPORTER_FOR_COMMANDS = ['saveScreenshot', 'savePDF'];
10
11
  const mochaFramework = document.querySelector('mocha-framework');
12
+ let id = 0;
11
13
  export default class ProxyDriver {
12
14
  static #commandMessages = new Map();
13
15
  static newSession(params, modifier, userPrototype, commandWrapper) {
@@ -18,49 +20,22 @@ export default class ProxyDriver {
18
20
  /**
19
21
  * log all console events once connected
20
22
  */
21
- const connectPromise = window.__wdioConnectPromise__;
22
- connectPromise.then(this.#wrapConsolePrototype.bind(this, cid));
23
+ this.#wrapConsolePrototype(cid);
23
24
  /**
24
- * handle Vite server socket messages
25
+ * listen on socket events from testrunner
25
26
  */
26
- const socket = window.__wdioSocket__;
27
- socket.addEventListener('message', this.#handleServerMessage.bind(this));
28
- let commandId = 0;
27
+ import.meta.hot?.on(WDIO_EVENT_NAME, this.#handleServerMessage.bind(this));
28
+ import.meta.hot?.send(WDIO_EVENT_NAME, {
29
+ type: MESSAGE_TYPES.initiateBrowserStateRequest,
30
+ value: { cid }
31
+ });
29
32
  const environment = sessionEnvironmentDetector({ capabilities: params.capabilities, requestedCapabilities: {} });
30
33
  const environmentPrototype = getEnvironmentVars(environment);
31
34
  // have debug command
32
35
  const commandsProcessedInNodeWorld = [...commands, 'debug', 'saveScreenshot', 'savePDF'];
33
36
  const protocolCommands = commandsProcessedInNodeWorld.reduce((prev, commandName) => {
34
- const isDebugCommand = commandName === 'debug';
35
37
  prev[commandName] = {
36
- value: async (...args) => {
37
- if (socket.readyState !== 1) {
38
- await connectPromise;
39
- }
40
- commandId++;
41
- /**
42
- * print information which command is executed (except for debug commands)
43
- */
44
- console.log(...(isDebugCommand
45
- ? ['[WDIO] %cDebug Mode Enabled', 'background: #ea5906; color: #fff; padding: 3px; border-radius: 5px;']
46
- : [`[WDIO] ${(new Date()).toISOString()} - id: ${commandId} - COMMAND: ${commandName}(${args.join(', ')})`]));
47
- if (HIDE_REPORTER_FOR_COMMANDS.includes(commandName) && mochaFramework) {
48
- mochaFramework.setAttribute('style', 'display: none');
49
- }
50
- socket.send(JSON.stringify(this.#commandRequest({
51
- commandName,
52
- cid,
53
- id: commandId.toString(),
54
- args
55
- })));
56
- return new Promise((resolve, reject) => {
57
- let commandTimeout;
58
- if (!isDebugCommand) {
59
- commandTimeout = setTimeout(() => reject(new Error(`Command "${commandName}" timed out`)), COMMAND_TIMEOUT);
60
- }
61
- this.#commandMessages.set(commandId.toString(), { resolve, reject, commandTimeout, commandName });
62
- });
63
- }
38
+ value: this.#getMockedCommand(cid, commandName)
64
39
  };
65
40
  return prev;
66
41
  }, {});
@@ -89,48 +64,92 @@ export default class ProxyDriver {
89
64
  const monad = webdriverMonad(params, modifier, prototype);
90
65
  return monad(window.__wdioEnv__.sessionId, commandWrapper);
91
66
  }
92
- static #handleServerMessage(ev) {
93
- try {
94
- const { type, value } = JSON.parse(ev.data);
95
- if (type !== MESSAGE_TYPES.commandResponseMessage) {
96
- return;
97
- }
98
- if (!value.id) {
99
- return console.error(`Message without id: ${JSON.stringify(ev.data)}`);
100
- }
101
- const commandMessage = this.#commandMessages.get(value.id);
102
- if (!commandMessage) {
103
- return console.error(`Unknown command id "${value.id}"`);
67
+ static #getMockedCommand(cid, commandName) {
68
+ const isDebugCommand = commandName === 'debug';
69
+ return async (...args) => {
70
+ if (!import.meta.hot) {
71
+ throw new Error('Could not connect to testrunner');
104
72
  }
105
- if (HIDE_REPORTER_FOR_COMMANDS.includes(commandMessage.commandName) && mochaFramework) {
106
- mochaFramework.removeAttribute('style');
107
- }
108
- if (value.error) {
109
- console.log(`[WDIO] ${(new Date()).toISOString()} - id: ${value.id} - ERROR: ${JSON.stringify(value.error.message)}`);
110
- return commandMessage.reject(new Error(value.error.message || 'unknown error'));
111
- }
112
- if (commandMessage.commandTimeout) {
113
- clearTimeout(commandMessage.commandTimeout);
73
+ id++;
74
+ /**
75
+ * print information which command is executed (except for debug commands)
76
+ */
77
+ console.log(...(isDebugCommand
78
+ ? ['[WDIO] %cDebug Mode Enabled', 'background: #ea5906; color: #fff; padding: 3px; border-radius: 5px;']
79
+ : [`[WDIO] ${(new Date()).toISOString()} - id: ${id} - COMMAND: ${commandName}(${args.join(', ')})`]));
80
+ if (HIDE_REPORTER_FOR_COMMANDS.includes(commandName) && mochaFramework) {
81
+ mochaFramework.setAttribute('style', 'display: none');
114
82
  }
115
- console.log(`[WDIO] ${(new Date()).toISOString()} - id: ${value.id} - RESULT: ${JSON.stringify(value.result)}`);
116
- commandMessage.resolve(value.result);
117
- this.#commandMessages.delete(value.id);
83
+ import.meta.hot.send(WDIO_EVENT_NAME, this.#commandRequest({
84
+ commandName,
85
+ cid,
86
+ id,
87
+ args
88
+ }));
89
+ return new Promise((resolve, reject) => {
90
+ let commandTimeout;
91
+ if (!isDebugCommand) {
92
+ commandTimeout = setTimeout(() => reject(new Error(`Command "${commandName}" timed out`)), COMMAND_TIMEOUT);
93
+ }
94
+ this.#commandMessages.set(id, { resolve, reject, commandTimeout, commandName });
95
+ });
96
+ };
97
+ }
98
+ static #handleServerMessage(payload) {
99
+ if (payload.type === MESSAGE_TYPES.commandResponseMessage) {
100
+ return this.#handleCommandResponse(payload.value);
101
+ }
102
+ if (payload.type === MESSAGE_TYPES.initiateBrowserStateResponse) {
103
+ return this.#handleBrowserInitiation(payload.value);
104
+ }
105
+ }
106
+ static #handleCommandResponse(value) {
107
+ if (!value.id) {
108
+ return console.error(`Message without id: ${JSON.stringify(value)}`);
109
+ }
110
+ const commandMessage = this.#commandMessages.get(value.id);
111
+ if (!commandMessage) {
112
+ return console.error(`Unknown command id "${value.id}"`);
113
+ }
114
+ if (HIDE_REPORTER_FOR_COMMANDS.includes(commandMessage.commandName) && mochaFramework) {
115
+ mochaFramework.removeAttribute('style');
116
+ }
117
+ if (value.error) {
118
+ console.log(`[WDIO] ${(new Date()).toISOString()} - id: ${value.id} - ERROR: ${JSON.stringify(value.error.message)}`);
119
+ return commandMessage.reject(new Error(value.error.message || 'unknown error'));
120
+ }
121
+ if (commandMessage.commandTimeout) {
122
+ clearTimeout(commandMessage.commandTimeout);
123
+ }
124
+ console.log(`[WDIO] ${(new Date()).toISOString()} - id: ${value.id} - RESULT: ${JSON.stringify(value.result)}`);
125
+ commandMessage.resolve(value.result);
126
+ this.#commandMessages.delete(value.id);
127
+ }
128
+ /**
129
+ * Initiate browser states even in case page loads happen. This is necessary so we can
130
+ * add a custom command that was added in the Node.js environment to the browser scope
131
+ * within the browser so the instance is aware of it and can translate the command
132
+ * request back to the worker process
133
+ */
134
+ static #handleBrowserInitiation(value) {
135
+ const cid = getCID();
136
+ if (!cid) {
137
+ return;
118
138
  }
119
- catch (err) {
120
- console.error(`Failed handling command socket message "${err.message}"`);
139
+ for (const commandName of value.customCommands) {
140
+ browser.addCommand(commandName, this.#getMockedCommand(cid, commandName));
121
141
  }
122
142
  }
123
143
  static #wrapConsolePrototype(cid) {
124
- const socket = window.__wdioSocket__;
125
144
  for (const method of CONSOLE_METHODS) {
126
145
  const origCommand = console[method].bind(console);
127
146
  console[method] = (...args) => {
128
- socket.send(stringify.default(this.#consoleMessage({
147
+ import.meta.hot?.send(WDIO_EVENT_NAME, this.#consoleMessage({
129
148
  name: 'consoleEvent',
130
149
  type: method,
131
150
  args,
132
151
  cid
133
- })));
152
+ }));
134
153
  origCommand(...args);
135
154
  };
136
155
  }
@@ -0,0 +1,3 @@
1
+ import { expect } from 'expect';
2
+ export { expect };
3
+ //# sourceMappingURL=expect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect.d.ts","sourceRoot":"","sources":["../../src/browser/expect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA2E,MAAM,QAAQ,CAAA;AAkHxG,OAAO,EAAE,MAAM,EAAE,CAAA"}
@@ -0,0 +1,88 @@
1
+ import { expect } from 'expect';
2
+ import { MESSAGE_TYPES } from '@wdio/types';
3
+ import { matchers } from 'virtual:wdio';
4
+ import { $ } from '@wdio/globals';
5
+ import { getCID } from './utils.js';
6
+ import { WDIO_EVENT_NAME } from '../constants.js';
7
+ const asymmetricMatcher = typeof Symbol === 'function' && Symbol.for
8
+ ? Symbol.for('jest.asymmetricMatcher')
9
+ : 1267621;
10
+ let matcherRequestCount = 0;
11
+ const matcherRequests = new Map();
12
+ const COMMAND_TIMEOUT = 30 * 1000; // 30s
13
+ /**
14
+ * Set up expect-webdriverio matchers for the browser environment.
15
+ * Every assertion is send to the testrunner via a websocket connection
16
+ * and is executed in the Node.js environment. This allows us to enable
17
+ * matchers that require Node.js specific modules like `fs` or `child_process`,
18
+ * for visual regression or snapshot testing for example.
19
+ */
20
+ expect.extend(matchers.reduce((acc, matcherName) => {
21
+ acc[matcherName] = async function (context, ...args) {
22
+ const cid = getCID();
23
+ if (!import.meta.hot || !cid) {
24
+ return {
25
+ pass: false,
26
+ message: () => 'Could not connect to testrunner'
27
+ };
28
+ }
29
+ if (typeof args[0] === 'object' && '$$typeof' in args[0] && args[0].$$typeof === asymmetricMatcher && args[0].asymmetricMatch) {
30
+ args[0] = {
31
+ $$typeof: args[0].toString(),
32
+ sample: args[0].sample,
33
+ inverse: args[0].inverse
34
+ };
35
+ }
36
+ const expectRequest = {
37
+ id: matcherRequestCount++,
38
+ cid,
39
+ scope: this,
40
+ matcherName,
41
+ args: args
42
+ };
43
+ /**
44
+ * Check if context is an WebdriverIO.Element
45
+ */
46
+ if ('elementId' in context && typeof context.elementId === 'string') {
47
+ expectRequest.element = context;
48
+ }
49
+ /**
50
+ * Check if context is ChainablePromiseElement
51
+ */
52
+ if ('then' in context && typeof context.selector === 'object') {
53
+ expectRequest.element = await context;
54
+ }
55
+ /**
56
+ * Check if context is a `Element` and transtform it into a WebdriverIO.Element
57
+ */
58
+ if (context instanceof Element) {
59
+ expectRequest.element = await $(context);
60
+ }
61
+ import.meta.hot.send(WDIO_EVENT_NAME, { type: MESSAGE_TYPES.expectRequestMessage, value: expectRequest });
62
+ const contextString = 'elementId' in context ? 'WebdriverIO.Element' : 'WebdriverIO.Browser';
63
+ return new Promise((resolve, reject) => {
64
+ const commandTimeout = setTimeout(() => reject(new Error(`Assertion expect(${contextString}).${matcherName}(...) timed out`)), COMMAND_TIMEOUT);
65
+ matcherRequests.set(expectRequest.id, { resolve, commandTimeout });
66
+ });
67
+ };
68
+ return acc;
69
+ }, {}));
70
+ /**
71
+ * listen on assertion results from testrunner
72
+ */
73
+ import.meta.hot?.on(WDIO_EVENT_NAME, (message) => {
74
+ if (message.type !== MESSAGE_TYPES.expectResponseMessage) {
75
+ return;
76
+ }
77
+ const payload = matcherRequests.get(message.value.id);
78
+ if (!payload) {
79
+ return console.warn(`Couldn't find payload for assertion result with id ${message.value.id}`);
80
+ }
81
+ clearTimeout(payload.commandTimeout);
82
+ matcherRequests.delete(message.value.id);
83
+ payload.resolve({
84
+ pass: message.value.pass,
85
+ message: () => message.value.message
86
+ });
87
+ });
88
+ export { expect };
@@ -5,6 +5,6 @@ export declare class MochaFramework extends HTMLElement {
5
5
  get spec(): string;
6
6
  connectedCallback(): void;
7
7
  attributeChangedCallback(name: string, oldValue: unknown, newValue: unknown): void;
8
- run(socket: WebSocket): Promise<void>;
8
+ run(): Promise<void>;
9
9
  }
10
10
  //# sourceMappingURL=mocha.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mocha.d.ts","sourceRoot":"","sources":["../../../src/browser/frameworks/mocha.ts"],"names":[],"mappings":"AA8BA,qBAAa,cAAe,SAAQ,WAAW;;;IA0B3C,MAAM,KAAK,kBAAkB,aAE5B;IAED,IAAI,IAAI,WAEP;IAED,iBAAiB;IAWjB,wBAAwB,CAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO;IAatE,GAAG,CAAE,MAAM,EAAE,SAAS;CAoI/B"}
1
+ {"version":3,"file":"mocha.d.ts","sourceRoot":"","sources":["../../../src/browser/frameworks/mocha.ts"],"names":[],"mappings":"AA6BA,qBAAa,cAAe,SAAQ,WAAW;;;IAyB3C,MAAM,KAAK,kBAAkB,aAE5B;IAED,IAAI,IAAI,WAEP;IAED,iBAAiB;IAWjB,wBAAwB,CAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO;IAatE,GAAG;CAgIZ"}
@@ -1,7 +1,8 @@
1
- import stringify from 'fast-safe-stringify';
1
+ import safeStringify from 'safe-stringify';
2
2
  import { setupEnv, formatMessage } from '@wdio/mocha-framework/common';
3
+ import { MESSAGE_TYPES } from '@wdio/types';
3
4
  import { getCID } from '../utils.js';
4
- import { MESSAGE_TYPES, EVENTS } from '../../constants.js';
5
+ import { EVENTS, WDIO_EVENT_NAME } from '../../constants.js';
5
6
  const startTime = Date.now();
6
7
  if (!window.Mocha) {
7
8
  throw new Error('Can\'t find Mocha attached to the `window` scope, was it installed? Run `npm install mocha` and run again!');
@@ -23,7 +24,6 @@ class HTMLReporter extends BaseReporter {
23
24
  export class MochaFramework extends HTMLElement {
24
25
  #root;
25
26
  #spec;
26
- #socket;
27
27
  #require;
28
28
  #hookResolver = new Map();
29
29
  #runnerEvents = [];
@@ -69,7 +69,7 @@ export class MochaFramework extends HTMLElement {
69
69
  document.body.style.width = `calc(100% - ${this.#isMinified ? '65px' : '500px'})`;
70
70
  }
71
71
  }
72
- async run(socket) {
72
+ async run() {
73
73
  const globalTeardownScripts = [];
74
74
  const globalSetupScripts = [];
75
75
  for (const r of this.#require) {
@@ -92,8 +92,10 @@ export class MochaFramework extends HTMLElement {
92
92
  for (const setupScript of globalSetupScripts) {
93
93
  await setupScript();
94
94
  }
95
- this.#socket = socket;
96
- socket.addEventListener('message', this.#handleSocketMessage.bind(this));
95
+ /**
96
+ * listen on socket events from testrunner
97
+ */
98
+ import.meta.hot?.on(WDIO_EVENT_NAME, this.#handleSocketMessage.bind(this));
97
99
  const cid = getCID();
98
100
  if (!cid) {
99
101
  throw new Error('"cid" query parameter is missing');
@@ -145,16 +147,9 @@ export class MochaFramework extends HTMLElement {
145
147
  window.__wdioFailures__ = failures;
146
148
  console.log(`[WDIO] Finished test suite in ${Date.now() - startTime}ms`);
147
149
  }
148
- #handleSocketMessage(payload) {
149
- try {
150
- const message = JSON.parse(payload.data);
151
- if (message.type === MESSAGE_TYPES.hookResultMessage) {
152
- return this.#handleHookResult(message.value);
153
- }
154
- // no-op
155
- }
156
- catch (err) {
157
- console.error(`Failed handling message from Vite server: ${err.stack}`);
150
+ #handleSocketMessage(message) {
151
+ if (message.type === MESSAGE_TYPES.hookResultMessage) {
152
+ return this.#handleHookResult(message.value);
158
153
  }
159
154
  }
160
155
  #handleHookResult(result) {
@@ -170,19 +165,19 @@ export class MochaFramework extends HTMLElement {
170
165
  }
171
166
  #getHook(name) {
172
167
  return (...args) => new Promise((resolve, reject) => {
173
- const id = (this.#hookResolver.size + 1).toString();
168
+ const id = this.#hookResolver.size + 1;
174
169
  const cid = getCID();
175
170
  if (!cid) {
176
171
  return reject(new Error('"cid" query parameter is missing'));
177
172
  }
178
- this.#hookResolver.set(id.toString(), { resolve, reject });
179
- this.#socket?.send(stringify.default(this.#hookTrigger({ name, id, cid, args })));
173
+ this.#hookResolver.set(id, { resolve, reject });
174
+ import.meta.hot?.send(WDIO_EVENT_NAME, this.#hookTrigger({ name, id, cid, args }));
180
175
  });
181
176
  }
182
177
  #hookTrigger(value) {
183
178
  return {
184
179
  type: MESSAGE_TYPES.hookTriggerMessage,
185
- value
180
+ value: JSON.parse(safeStringify(value))
186
181
  };
187
182
  }
188
183
  }
@@ -3,16 +3,14 @@ type WDIOErrorEvent = Pick<ErrorEvent, 'filename' | 'message'>;
3
3
  declare global {
4
4
  interface Window {
5
5
  Mocha?: any;
6
+ WDIO_EVENT_NAME: string;
6
7
  __wdioErrors__: WDIOErrorEvent[];
7
8
  __wdioSpec__: string;
8
9
  __wdioFailures__: number;
9
10
  __wdioEvents__: any[];
10
- __wdioSocket__: WebSocket;
11
11
  __wdioConnectPromise__: Promise<WebSocket>;
12
12
  __wdioMockCache__: Map<string, any>;
13
13
  }
14
14
  }
15
- export declare const socket: WebSocket;
16
- export declare const connectPromise: Promise<WebSocket>;
17
15
  export {};
18
16
  //# sourceMappingURL=setup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/browser/setup.ts"],"names":[],"mappings":"AAMA,OAAO,uBAAuB,CAAA;AAI9B,KAAK,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC,CAAA;AAC9D,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,KAAK,CAAC,EAAE,GAAG,CAAA;QACX,cAAc,EAAE,cAAc,EAAE,CAAA;QAChC,YAAY,EAAE,MAAM,CAAA;QACpB,gBAAgB,EAAE,MAAM,CAAA;QACxB,cAAc,EAAE,GAAG,EAAE,CAAA;QACrB,cAAc,EAAE,SAAS,CAAA;QACzB,sBAAsB,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;QAC1C,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KACtC;CACJ;AAWD,eAAO,MAAM,MAAM,WAA+C,CAAA;AAClE,eAAO,MAAM,cAAc,oBAGzB,CAAA"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/browser/setup.ts"],"names":[],"mappings":"AAOA,OAAO,uBAAuB,CAAA;AAI9B,KAAK,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC,CAAA;AAC9D,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,KAAK,CAAC,EAAE,GAAG,CAAA;QACX,eAAe,EAAE,MAAM,CAAA;QACvB,cAAc,EAAE,cAAc,EAAE,CAAA;QAChC,YAAY,EAAE,MAAM,CAAA;QACpB,gBAAgB,EAAE,MAAM,CAAA;QACxB,cAAc,EAAE,GAAG,EAAE,CAAA;QACrB,sBAAsB,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;QAC1C,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KACtC;CACJ"}
@@ -1,3 +1,4 @@
1
+ /// <reference types="vite/client" />
1
2
  import { automationProtocolPath } from 'virtual:wdio';
2
3
  import { expect } from 'expect-webdriverio';
3
4
  import { remote } from 'webdriverio';
@@ -7,16 +8,6 @@ import { showPopupWarning } from './utils.js';
7
8
  globalThis.alert = showPopupWarning('alert', undefined);
8
9
  globalThis.confirm = showPopupWarning('confirm', false, true);
9
10
  globalThis.prompt = showPopupWarning('prompt', null, 'your value');
10
- /**
11
- * create connection to Vite server
12
- */
13
- const wsUrl = 'ws://' + window.location.host + '/ws';
14
- console.log(`[WDIO] Connect to testrunner: ${wsUrl}`);
15
- export const socket = window.__wdioSocket__ = new WebSocket(wsUrl);
16
- export const connectPromise = window.__wdioConnectPromise__ = new Promise((resolve) => {
17
- console.log('[WDIO] Connected to testrunner');
18
- socket.addEventListener('open', () => resolve(socket));
19
- });
20
11
  /**
21
12
  * Setup fake browser instance and attach to global scope if necessary
22
13
  */
@@ -30,12 +21,11 @@ _setGlobal('expect', expect, window.__wdioEnv__.injectGlobals);
30
21
  _setGlobal('$', browser.$.bind(browser), window.__wdioEnv__.injectGlobals);
31
22
  _setGlobal('$$', browser.$$.bind(browser), window.__wdioEnv__.injectGlobals);
32
23
  /**
33
- * run framework immediatelly on page load
24
+ * run framework immediately on page load
34
25
  */
35
26
  const mochaFramework = document.querySelector('mocha-framework');
36
27
  if (mochaFramework) {
37
- const socket = await connectPromise;
38
- mochaFramework.run(socket).catch((err) => {
28
+ mochaFramework.run().catch((err) => {
39
29
  /**
40
30
  * On MacOS importing the spec file might fail with a null error object.
41
31
  * This is Vite doing a hot reload and the error is not relevant for us.
@@ -0,0 +1,11 @@
1
+ import { type CoverageMap } from 'istanbul-lib-coverage';
2
+ import type { WorkerInstance } from '@wdio/local-runner';
3
+ import { type Options } from '@wdio/types';
4
+ import type { ViteServer } from './vite/server.js';
5
+ export declare class ServerWorkerCommunicator {
6
+ #private;
7
+ coverageMaps: CoverageMap[];
8
+ constructor(config: Options.Testrunner);
9
+ register(server: ViteServer, worker: WorkerInstance): void;
10
+ }
11
+ //# sourceMappingURL=communicator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"communicator.d.ts","sourceRoot":"","sources":["../src/communicator.ts"],"names":[],"mappings":"AACA,OAAoB,EAAE,KAAK,WAAW,EAAwB,MAAM,uBAAuB,CAAA;AAI3F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAiB,KAAK,OAAO,EAAgB,MAAM,aAAa,CAAA;AAKvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAWlD,qBAAa,wBAAwB;;IAe1B,YAAY,EAAE,WAAW,EAAE,CAAK;gBAE1B,MAAM,EAAE,OAAO,CAAC,UAAU;IAIvC,QAAQ,CAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc;CAmEvD"}
@@ -0,0 +1,82 @@
1
+ import libSourceMap from 'istanbul-lib-source-maps';
2
+ import libCoverage from 'istanbul-lib-coverage';
3
+ import logger from '@wdio/logger';
4
+ import { MESSAGE_TYPES } from '@wdio/types';
5
+ import { SESSIONS } from './constants.js';
6
+ import { WDIO_EVENT_NAME } from './constants.js';
7
+ const log = logger('@wdio/browser-runner');
8
+ export class ServerWorkerCommunicator {
9
+ #mapStore = libSourceMap.createSourceMapStore();
10
+ #config;
11
+ #msgId = 0;
12
+ /**
13
+ * keep track of custom commands per session
14
+ */
15
+ #customCommands = new Map();
16
+ /**
17
+ * keep track of request/response messages on browser/worker level
18
+ */
19
+ #pendingMessages = new Map();
20
+ coverageMaps = [];
21
+ constructor(config) {
22
+ this.#config = config;
23
+ }
24
+ register(server, worker) {
25
+ server.onBrowserEvent((data, client) => this.#onBrowserEvent(data, client, worker));
26
+ worker.on('message', this.#onWorkerMessage.bind(this));
27
+ }
28
+ async #onWorkerMessage(payload) {
29
+ if (payload.name === 'sessionStarted' && !SESSIONS.has(payload.cid)) {
30
+ SESSIONS.set(payload.cid, {
31
+ args: this.#config.mochaOpts || {},
32
+ config: this.#config,
33
+ capabilities: payload.content.capabilities,
34
+ sessionId: payload.content.sessionId,
35
+ injectGlobals: payload.content.injectGlobals
36
+ });
37
+ }
38
+ if (payload.name === 'sessionEnded') {
39
+ SESSIONS.delete(payload.cid);
40
+ }
41
+ if (payload.name === 'workerEvent' && payload.args.type === MESSAGE_TYPES.coverageMap) {
42
+ const coverageMapData = payload.args.value;
43
+ this.coverageMaps.push(await this.#mapStore.transformCoverage(libCoverage.createCoverageMap(coverageMapData)));
44
+ }
45
+ if (payload.name === 'workerEvent' && payload.args.type === MESSAGE_TYPES.customCommand) {
46
+ const { commandName, cid } = payload.args.value;
47
+ if (!this.#customCommands.has(cid)) {
48
+ this.#customCommands.set(cid, new Set());
49
+ }
50
+ const customCommands = this.#customCommands.get(cid) || new Set();
51
+ customCommands.add(commandName);
52
+ return;
53
+ }
54
+ if (payload.name === 'workerResponse') {
55
+ const msg = this.#pendingMessages.get(payload.args.id);
56
+ if (!msg) {
57
+ return log.error(`Couldn't find message with id ${payload.args.id} from type ${payload.args.message.type}`);
58
+ }
59
+ this.#pendingMessages.delete(payload.args.id);
60
+ return msg.client.send(WDIO_EVENT_NAME, payload.args.message);
61
+ }
62
+ }
63
+ #onBrowserEvent(message, client, worker) {
64
+ /**
65
+ * some browser events don't need to go through the worker process
66
+ */
67
+ if (message.type === MESSAGE_TYPES.initiateBrowserStateRequest) {
68
+ const result = {
69
+ type: MESSAGE_TYPES.initiateBrowserStateResponse,
70
+ value: {
71
+ customCommands: [...(this.#customCommands.get(message.value.cid) || [])]
72
+ }
73
+ };
74
+ return client.send(WDIO_EVENT_NAME, result);
75
+ }
76
+ const id = this.#msgId++;
77
+ const msg = { id, client };
78
+ this.#pendingMessages.set(id, msg);
79
+ const args = { id, message };
80
+ return worker.postMessage('workerRequest', args, true);
81
+ }
82
+ }
@@ -1,7 +1,7 @@
1
1
  import type { Environment } from './types.js';
2
2
  import type { ReportOptions } from 'istanbul-reports';
3
3
  export declare const SESSIONS: Map<string, Environment>;
4
- export declare const BROWSER_POOL: Map<string, WebdriverIO.Browser>;
4
+ export declare const WDIO_EVENT_NAME = "wdio:workerMessage";
5
5
  export declare const EVENTS: {
6
6
  readonly suite: "suite:start";
7
7
  readonly 'suite end': "suite:end";
@@ -15,13 +15,6 @@ export declare const EVENTS: {
15
15
  readonly pending: "test:pending";
16
16
  };
17
17
  export declare const FRAMEWORK_SUPPORT_ERROR = "Currently only \"mocha\" is supported as framework when using @wdio/browser-runner.";
18
- export declare enum MESSAGE_TYPES {
19
- consoleMessage = 0,
20
- commandRequestMessage = 1,
21
- commandResponseMessage = 2,
22
- hookTriggerMessage = 3,
23
- hookResultMessage = 4
24
- }
25
18
  export declare const DEFAULT_INCLUDE: string[];
26
19
  export declare const DEFAULT_FILE_EXTENSIONS: string[];
27
20
  export declare const DEFAULT_REPORTS_DIRECTORY = "coverage";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAErD,eAAO,MAAM,QAAQ,0BAAiC,CAAA;AACtD,eAAO,MAAM,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAa,CAAA;AAEvE,eAAO,MAAM,MAAM;;;;;;;;;;;CAWT,CAAA;AAEV,eAAO,MAAM,uBAAuB,wFAAsF,CAAA;AAE1H,oBAAY,aAAa;IACrB,cAAc,IAAI;IAClB,qBAAqB,IAAA;IACrB,sBAAsB,IAAA;IACtB,kBAAkB,IAAA;IAClB,iBAAiB,IAAA;CACpB;AAED,eAAO,MAAM,eAAe,UAAS,CAAA;AACrC,eAAO,MAAM,uBAAuB,UAAoF,CAAA;AACxH,eAAO,MAAM,yBAAyB,aAAa,CAAA;AACnD,eAAO,MAAM,gBAAgB,OAAO,CAAA;AACpC,eAAO,MAAM,sBAAsB,cAAc,CAAA;AACjD,eAAO,MAAM,gBAAgB,iBAAiB,CAAA;AAC9C,eAAO,MAAM,gBAAgB,2DAA4D,CAAA;AACzF,eAAO,MAAM,wBAAwB,EAAE,CAAC,MAAM,aAAa,CAAC,EAAiD,CAAA;AAC7G,eAAO,MAAM,yBAAyB,sEAAsE,CAAA;AAC5G,eAAO,MAAM,uBAAuB,sEAAsE,CAAA;AAE1G,eAAO,MAAM,eAAe,irEA+D3B,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAErD,eAAO,MAAM,QAAQ,0BAAiC,CAAA;AACtD,eAAO,MAAM,eAAe,uBAAuB,CAAA;AAEnD,eAAO,MAAM,MAAM;;;;;;;;;;;CAWT,CAAA;AAEV,eAAO,MAAM,uBAAuB,wFAAsF,CAAA;AAE1H,eAAO,MAAM,eAAe,UAAS,CAAA;AACrC,eAAO,MAAM,uBAAuB,UAAoF,CAAA;AACxH,eAAO,MAAM,yBAAyB,aAAa,CAAA;AACnD,eAAO,MAAM,gBAAgB,OAAO,CAAA;AACpC,eAAO,MAAM,sBAAsB,cAAc,CAAA;AACjD,eAAO,MAAM,gBAAgB,iBAAiB,CAAA;AAC9C,eAAO,MAAM,gBAAgB,2DAA4D,CAAA;AACzF,eAAO,MAAM,wBAAwB,EAAE,CAAC,MAAM,aAAa,CAAC,EAAiD,CAAA;AAC7G,eAAO,MAAM,yBAAyB,sEAAsE,CAAA;AAC5G,eAAO,MAAM,uBAAuB,sEAAsE,CAAA;AAE1G,eAAO,MAAM,eAAe,irEA+D3B,CAAA"}
@@ -1,5 +1,5 @@
1
1
  export const SESSIONS = new Map();
2
- export const BROWSER_POOL = new Map();
2
+ export const WDIO_EVENT_NAME = 'wdio:workerMessage';
3
3
  export const EVENTS = {
4
4
  'suite': 'suite:start',
5
5
  'suite end': 'suite:end',
@@ -13,14 +13,6 @@ export const EVENTS = {
13
13
  'pending': 'test:pending'
14
14
  };
15
15
  export const FRAMEWORK_SUPPORT_ERROR = 'Currently only "mocha" is supported as framework when using @wdio/browser-runner.';
16
- export var MESSAGE_TYPES;
17
- (function (MESSAGE_TYPES) {
18
- MESSAGE_TYPES[MESSAGE_TYPES["consoleMessage"] = 0] = "consoleMessage";
19
- MESSAGE_TYPES[MESSAGE_TYPES["commandRequestMessage"] = 1] = "commandRequestMessage";
20
- MESSAGE_TYPES[MESSAGE_TYPES["commandResponseMessage"] = 2] = "commandResponseMessage";
21
- MESSAGE_TYPES[MESSAGE_TYPES["hookTriggerMessage"] = 3] = "hookTriggerMessage";
22
- MESSAGE_TYPES[MESSAGE_TYPES["hookResultMessage"] = 4] = "hookResultMessage";
23
- })(MESSAGE_TYPES || (MESSAGE_TYPES = {}));
24
16
  export const DEFAULT_INCLUDE = ['**'];
25
17
  export const DEFAULT_FILE_EXTENSIONS = ['.js', '.cjs', '.mjs', '.ts', '.mts', '.cts', '.tsx', '.jsx', '.vue', '.svelte'];
26
18
  export const DEFAULT_REPORTS_DIRECTORY = 'coverage';
package/build/index.d.ts CHANGED
@@ -7,8 +7,11 @@ export default class BrowserRunner extends LocalRunner {
7
7
  #private;
8
8
  private options;
9
9
  protected _config: Options.Testrunner;
10
- private _coverageMaps;
11
10
  constructor(options: BrowserRunnerOptionsImport, _config: Options.Testrunner);
11
+ /**
12
+ * for testing purposes
13
+ */
14
+ private _servers;
12
15
  /**
13
16
  * nothing to initialize when running locally
14
17
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAO5C,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAW/G,OAAO,KAAK,EAAE,oBAAoB,IAAI,0BAA0B,EAAmB,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAK5H,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;;IAY9C,OAAO,CAAC,OAAO;IACf,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU;IAJzC,OAAO,CAAC,aAAa,CAAoB;gBAG7B,OAAO,EAAE,0BAA0B,EACjC,OAAO,EAAE,OAAO,CAAC,UAAU;IAuBzC;;OAEG;IACG,UAAU;IAsBV,GAAG,CAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAkCrD;;;;OAIG;IACG,QAAQ;YAgDA,wBAAwB;CA2DzC;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,WAAW,CAAC;QAClB,UAAU,oBAAqB,SAAQ,0BAA0B;SAAG;KACvE;CACJ;AAED;;GAEG;AACH,cAAc,aAAa,CAAA;AAE3B;;;GAGG;AAEH;;;;;;;;;;;;GAYG;AAEH,wBAAgB,IAAI,CAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,QAAI;AAEvE;;;;GAIG;AAEH,wBAAgB,MAAM,CAAC,UAAU,EAAE,MAAM,QAAI;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AACnE,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AACpE,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;IACxC,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;CAChB,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AACnB,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;IACxC,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;CACd,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;AACvB,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC;CAChB,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAC5B,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,IAAI,CAAC;CACd,GAAG,wBAAwB,CAAC,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAK5C,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAU/G,OAAO,KAAK,EAAE,oBAAoB,IAAI,0BAA0B,EAAmB,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAI5H,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;;IAU9C,OAAO,CAAC,OAAO;IACf,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU;gBAD7B,OAAO,EAAE,0BAA0B,EACjC,OAAO,EAAE,OAAO,CAAC,UAAU;IAwBzC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAgB;IAEhC;;OAEG;IACG,UAAU;IAsBV,GAAG,CAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAuBrD;;;;OAIG;IACG,QAAQ;YAQA,wBAAwB;CA4DzC;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,WAAW,CAAC;QAClB,UAAU,oBAAqB,SAAQ,0BAA0B;SAAG;KACvE;CACJ;AAED;;GAEG;AACH,cAAc,aAAa,CAAA;AAE3B;;;GAGG;AAEH;;;;;;;;;;;;GAYG;AAEH,wBAAgB,IAAI,CAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,QAAI;AAEvE;;;;GAIG;AAEH,wBAAgB,MAAM,CAAC,UAAU,EAAE,MAAM,QAAI;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AACnE,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AACpE,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;IACxC,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;CAChB,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AACnB,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;IACxC,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;CACd,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;AACvB,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC;CAChB,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAC5B,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,IAAI,CAAC;CACd,GAAG,wBAAwB,CAAC,CAAC,CAAC,CAAA"}