@ainias42/wdio-utils 0.0.1 → 0.0.3

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,9 +1,25 @@
1
- export declare class ChromeCleanupService {
1
+ import type { Awaitable } from '@ainias42/js-helper';
2
+ import type { Services } from '@wdio/types';
3
+ export declare class ChromeCleanupService implements Services.ServiceInstance {
2
4
  private cacheDir;
3
- constructor(_1: any, _browser: any, config: {
5
+ private newSessionPerTest;
6
+ private afterBeforeTest;
7
+ private myCapabilities;
8
+ constructor(pluginConfig: {
9
+ newSessionPerTest?: boolean;
10
+ afterBeforeTest?: () => Awaitable<void>;
11
+ } | undefined, _browser: any, config: {
4
12
  cacheDir: string;
5
13
  });
14
+ private getCacheDir;
6
15
  private sortByVersion;
7
16
  private cleanCache;
17
+ private updateCapabilities;
18
+ onPrepare(): Promise<void>;
8
19
  onComplete(): Promise<void>;
20
+ beforeTest(): Promise<void>;
21
+ beforeSession(config: any, capabilities: WebdriverIO.Capabilities | Record<string, {
22
+ capabilities: WebdriverIO.Capabilities;
23
+ }>): Promise<void>;
24
+ afterSession(config: any, capabilities: WebdriverIO.Capabilities | Record<string, undefined | WebdriverIO.Capabilities>): Promise<void>;
9
25
  }
@@ -1,4 +1,4 @@
1
- export declare function createChromeCapability(cacheDir: string, headless: boolean, extraArgs?: string[]): {
1
+ export declare function createChromeCapability(cacheDir: string, headless: boolean, extraArgs?: string[], id?: string): {
2
2
  browserName: string;
3
3
  browserVersion: string;
4
4
  'goog:chromeOptions': {
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { ObjectHelper, Random } from "@ainias42/js-helper";
2
+ import { driver } from "@wdio/globals";
1
3
  import { default as default_0 } from "fs/promises";
2
4
  import { default as default_1 } from "path";
3
5
  /******/ // The require scope
@@ -24,6 +26,10 @@ import { default as default_1 } from "path";
24
26
  /************************************************************************/
25
27
  var __webpack_exports__ = {};
26
28
 
29
+ ;// external "@ainias42/js-helper"
30
+
31
+ ;// external "@wdio/globals"
32
+
27
33
  ;// external "fs/promises"
28
34
 
29
35
  ;// external "path"
@@ -31,9 +37,25 @@ var __webpack_exports__ = {};
31
37
  ;// ./src/ChromeCleanupService.ts
32
38
 
33
39
 
40
+
41
+
42
+ const browser = driver;
43
+ function isMultiBrowser(browserInstance) {
44
+ return Array.isArray(browserInstance.instances);
45
+ }
34
46
  class ChromeCleanupService {
35
- constructor(_1, _browser, config) {
47
+ constructor(pluginConfig, _browser, config) {
48
+ var _a;
49
+ this.newSessionPerTest = true;
50
+ // TODO handle single capability
51
+ this.myCapabilities = {};
36
52
  this.cacheDir = config.cacheDir;
53
+ this.newSessionPerTest = (_a = pluginConfig === null || pluginConfig === void 0 ? void 0 : pluginConfig.newSessionPerTest) !== null && _a !== void 0 ? _a : this.newSessionPerTest;
54
+ this.afterBeforeTest = pluginConfig === null || pluginConfig === void 0 ? void 0 : pluginConfig.afterBeforeTest;
55
+ }
56
+ getCacheDir() {
57
+ var _a;
58
+ return (_a = this.cacheDir) !== null && _a !== void 0 ? _a : 'test/tmp';
37
59
  }
38
60
  // eslint-disable-next-line class-methods-use-this
39
61
  sortByVersion(items) {
@@ -78,21 +100,90 @@ class ChromeCleanupService {
78
100
  console.error(`[WDIO Cleanup] Error cleaning cache at ${cachePath}:`, error);
79
101
  }
80
102
  }
103
+ updateCapabilities(capabilities) {
104
+ var _a, _b;
105
+ const cacheDir = this.getCacheDir();
106
+ for (const cap of capabilities) {
107
+ const options = (_a = cap['goog:chromeOptions']) !== null && _a !== void 0 ? _a : {};
108
+ const args = (_b = options.args) !== null && _b !== void 0 ? _b : [];
109
+ if (args.every(arg => !arg.startsWith('--user-data-dir='))) {
110
+ args.push(`--user-data-dir=${default_1.join(cacheDir, 'profiles', Random.getStringRandom(12))}`);
111
+ }
112
+ options.args = args;
113
+ cap['goog:chromeOptions'] = options;
114
+ }
115
+ }
116
+ async onPrepare() {
117
+ const cacheDir = this.getCacheDir();
118
+ await default_0.rm(`${cacheDir}/profiles`, {
119
+ recursive: true,
120
+ force: true
121
+ }).catch();
122
+ }
81
123
  async onComplete() {
82
- var _a;
83
- const cacheDir = (_a = this.cacheDir) !== null && _a !== void 0 ? _a : 'test/tmp';
124
+ const cacheDir = this.getCacheDir();
84
125
  await this.cleanCache(`${cacheDir}/chrome`);
85
126
  await this.cleanCache(`${cacheDir}/chromedriver`);
86
127
  await default_0.rm(`${cacheDir}/profiles`, {
87
128
  recursive: true,
88
129
  force: true
89
- });
130
+ }).catch();
131
+ }
132
+ async beforeTest() {
133
+ var _a, _b, _c;
134
+ if (!this.newSessionPerTest) {
135
+ return;
136
+ }
137
+ this.updateCapabilities(ObjectHelper.values(this.myCapabilities));
138
+ for (const cap of ObjectHelper.values(this.myCapabilities)) {
139
+ const options = (_a = cap['goog:chromeOptions']) !== null && _a !== void 0 ? _a : {};
140
+ const args = ((_b = options.args) !== null && _b !== void 0 ? _b : []).filter(value => !value.startsWith('--user-data-dir='));
141
+ args.push(`--profile-dir=profile_${Random.getStringRandom(12)}`);
142
+ options.args = args;
143
+ cap['goog:chromeOptions'] = options;
144
+ }
145
+ if (isMultiBrowser(browser)) {
146
+ const promises = browser.instances.map(instanceName =>
147
+ // @ts-expect-error there are typing errors here
148
+ browser[instanceName].reloadSession(this.myCapabilities[instanceName]));
149
+ await Promise.all(promises);
150
+ }
151
+ (_c = this.afterBeforeTest) === null || _c === void 0 ? void 0 : _c.call(this);
152
+ }
153
+ async beforeSession(config, capabilities) {
154
+ const resolvedCapabilities = [];
155
+ if ('browserName' in capabilities) {
156
+ resolvedCapabilities.push(capabilities);
157
+ } else {
158
+ resolvedCapabilities.push(...Object.values(capabilities).filter(obj => !!obj).map(cap => cap.capabilities));
159
+ this.myCapabilities = Object.entries(capabilities).filter(([name, obj]) => !!obj).reduce((acc, [name, cap]) => {
160
+ acc[name] = cap.capabilities;
161
+ return acc;
162
+ }, {});
163
+ }
164
+ this.updateCapabilities(resolvedCapabilities);
165
+ }
166
+ async afterSession(config, capabilities) {
167
+ const resolvedCapabilities = [];
168
+ if ('browserName' in capabilities) {
169
+ resolvedCapabilities.push(capabilities);
170
+ } else {
171
+ resolvedCapabilities.push(...Object.values(capabilities).filter(obj => !!obj));
172
+ }
173
+ const profileDirs = resolvedCapabilities.filter(cap => {
174
+ var _a;
175
+ return 'chrome' in cap && typeof cap.chrome === 'object' && cap.chrome !== null && 'userDataDir' in cap.chrome && !!((_a = cap === null || cap === void 0 ? void 0 : cap.chrome) === null || _a === void 0 ? void 0 : _a.userDataDir);
176
+ }).map(cap => cap.chrome.userDataDir);
177
+ const deletionPromises = profileDirs.map(profileDir => default_0.rm(`${profileDir}`, {
178
+ recursive: true,
179
+ force: true
180
+ }).catch());
181
+ await Promise.all(deletionPromises);
90
182
  }
91
183
  }
92
184
  ;// ./src/createChromeCapability.ts
93
-
94
- function createChromeCapability(cacheDir, headless, extraArgs = []) {
95
- const args = ['--disable-infobars', '--enable-automation', '--disable-web-security', '--disable-popup-blocking', '--disable-notifications', '--disable-features=MacAppCodeSignClone', '--disable-blink-features=AutomationControlled', `--user-data-dir=${default_1.join(cacheDir, 'profiles')}`, ...extraArgs];
185
+ function createChromeCapability(cacheDir, headless, extraArgs = [], id = 'default') {
186
+ const args = ['--disable-infobars', '--enable-automation', '--disable-web-security', '--disable-popup-blocking', '--disable-notifications', '--disable-features=MacAppCodeSignClone', '--disable-blink-features=AutomationControlled', ...extraArgs];
96
187
  if (headless) {
97
188
  args.push('--headless=new');
98
189
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","mappings":"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","sources":["webpack://@ainias42/wdio-utils/webpack/bootstrap","webpack://@ainias42/wdio-utils/webpack/runtime/define property getters","webpack://@ainias42/wdio-utils/webpack/runtime/hasOwnProperty shorthand","webpack://@ainias42/wdio-utils/external module \"fs/promises\"","webpack://@ainias42/wdio-utils/external module \"path\"","webpack://@ainias42/wdio-utils/./src/ChromeCleanupService.ts","webpack://@ainias42/wdio-utils/./src/createChromeCapability.ts","webpack://@ainias42/wdio-utils/./src/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","","","import fs from 'fs/promises';\nimport path from 'path';\n\nexport class ChromeCleanupService {\n private cacheDir: string;\n\n constructor(_1: any, _browser: any, config: { cacheDir: string }) {\n this.cacheDir = config.cacheDir;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private sortByVersion(items: string[]) {\n return items.sort((a, b) => {\n const aVerMatch = a.match(/((?:\\d+\\.){3}\\d+)/);\n const bVerMatch = b.match(/((?:\\d+\\.){3}\\d+)/);\n\n const aVer = aVerMatch ? aVerMatch[0] : '0.0.0.0';\n const bVer = bVerMatch ? bVerMatch[0] : '0.0.0.0';\n\n return bVer.localeCompare(aVer, undefined, { numeric: true });\n });\n }\n\n private async cleanCache(cachePath: string) {\n try {\n const exists = await fs\n .stat(cachePath)\n .then(() => true)\n .catch(() => false);\n if (!exists) {\n return;\n }\n\n const entries = await fs.readdir(cachePath);\n const items: string[] = [];\n\n const itemPromises = entries.map(async (entry) => {\n const fullPath = path.join(cachePath, entry);\n const stat = await fs.stat(fullPath);\n if (stat.isDirectory()) {\n items.push(fullPath);\n }\n });\n await Promise.all(itemPromises);\n\n if (items.length <= 1) {\n return;\n }\n\n const sortedItems = this.sortByVersion(items);\n const [latest, ...oldItems] = sortedItems;\n\n const deletePromises = oldItems.map((oldItem) => fs.rm(oldItem, { recursive: true, force: true }));\n await Promise.all(deletePromises);\n\n console.log(`[WDIO Cleanup] Deleted old drivers/binaries, kept: ${latest}`);\n } catch (error) {\n console.error(`[WDIO Cleanup] Error cleaning cache at ${cachePath}:`, error);\n }\n }\n\n async onComplete() {\n const cacheDir = this.cacheDir ?? 'test/tmp';\n await this.cleanCache(`${cacheDir}/chrome`);\n await this.cleanCache(`${cacheDir}/chromedriver`);\n await fs.rm(`${cacheDir}/profiles`, { recursive: true, force: true });\n }\n}\n","import path from 'path';\n\nexport function createChromeCapability(cacheDir: string, headless: boolean, extraArgs: string[] = []) {\n const args = [\n '--disable-infobars',\n '--enable-automation',\n '--disable-web-security',\n '--disable-popup-blocking',\n '--disable-notifications',\n '--disable-features=MacAppCodeSignClone',\n '--disable-blink-features=AutomationControlled',\n `--user-data-dir=${path.join(cacheDir, 'profiles')}`,\n ...extraArgs,\n ];\n\n if (headless) {\n args.push('--headless=new');\n }\n\n return {\n browserName: 'chrome',\n browserVersion: 'stable',\n 'goog:chromeOptions': {\n excludeSwitches: ['enable-automation'],\n args,\n prefs: {\n 'intl.accept_languages': 'en',\n credentials_enable_service: false,\n 'profile.password_manager_enabled': false,\n },\n },\n };\n}\n","export * from './ChromeCleanupService';\nexport * from './createChromeCapability';\n"],"names":["fs","path","ChromeCleanupService","constructor","_1","_browser","config","cacheDir","sortByVersion","items","sort","a","b","aVerMatch","match","bVerMatch","aVer","bVer","localeCompare","undefined","numeric","cleanCache","cachePath","exists","stat","then","catch","entries","readdir","itemPromises","map","entry","fullPath","join","isDirectory","push","Promise","all","length","sortedItems","latest","oldItems","deletePromises","oldItem","rm","recursive","force","console","log","error","onComplete","_a","createChromeCapability","headless","extraArgs","args","browserName","browserVersion","excludeSwitches","prefs","credentials_enable_service"],"sourceRoot":""}
1
+ {"version":3,"file":"index.js","mappings":"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","sources":["webpack://@ainias42/wdio-utils/webpack/bootstrap","webpack://@ainias42/wdio-utils/webpack/runtime/define property getters","webpack://@ainias42/wdio-utils/webpack/runtime/hasOwnProperty shorthand","webpack://@ainias42/wdio-utils/external module \"@ainias42/js-helper\"","webpack://@ainias42/wdio-utils/external module \"@wdio/globals\"","webpack://@ainias42/wdio-utils/external module \"fs/promises\"","webpack://@ainias42/wdio-utils/external module \"path\"","webpack://@ainias42/wdio-utils/./src/ChromeCleanupService.ts","webpack://@ainias42/wdio-utils/./src/createChromeCapability.ts","webpack://@ainias42/wdio-utils/./src/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","","","","","import { ObjectHelper, Random } from '@ainias42/js-helper';\nimport { driver } from '@wdio/globals';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { Awaitable, URecord } from '@ainias42/js-helper';\nimport type { Services } from '@wdio/types';\n\ntype SingleBrowser = {\n capabilities: WebdriverIO.Capabilities;\n instances?: undefined;\n};\n\ntype MultiBrowser<Names extends string = string> = Record<Names, SingleBrowser> & { instances: Names[] };\ntype Browser = MultiBrowser | SingleBrowser;\n\nconst browser = driver as Browser;\n\nfunction isMultiBrowser(browserInstance: Browser): browserInstance is MultiBrowser {\n return Array.isArray(browserInstance.instances);\n}\n\nexport class ChromeCleanupService implements Services.ServiceInstance {\n private cacheDir: string;\n private newSessionPerTest: boolean = true;\n private afterBeforeTest: (() => Awaitable<void>) | undefined;\n // TODO handle single capability\n private myCapabilities: URecord<string, WebdriverIO.Capabilities> = {};\n\n constructor(\n pluginConfig: { newSessionPerTest?: boolean; afterBeforeTest?: () => Awaitable<void> } | undefined,\n _browser: any,\n config: { cacheDir: string },\n ) {\n this.cacheDir = config.cacheDir;\n this.newSessionPerTest = pluginConfig?.newSessionPerTest ?? this.newSessionPerTest;\n this.afterBeforeTest = pluginConfig?.afterBeforeTest;\n }\n\n private getCacheDir() {\n return this.cacheDir ?? 'test/tmp';\n }\n\n // eslint-disable-next-line class-methods-use-this\n private sortByVersion(items: string[]) {\n return items.sort((a, b) => {\n const aVerMatch = a.match(/((?:\\d+\\.){3}\\d+)/);\n const bVerMatch = b.match(/((?:\\d+\\.){3}\\d+)/);\n\n const aVer = aVerMatch ? aVerMatch[0] : '0.0.0.0';\n const bVer = bVerMatch ? bVerMatch[0] : '0.0.0.0';\n\n return bVer.localeCompare(aVer, undefined, { numeric: true });\n });\n }\n\n private async cleanCache(cachePath: string) {\n try {\n const exists = await fs\n .stat(cachePath)\n .then(() => true)\n .catch(() => false);\n if (!exists) {\n return;\n }\n\n const entries = await fs.readdir(cachePath);\n const items: string[] = [];\n\n const itemPromises = entries.map(async (entry) => {\n const fullPath = path.join(cachePath, entry);\n const stat = await fs.stat(fullPath);\n if (stat.isDirectory()) {\n items.push(fullPath);\n }\n });\n await Promise.all(itemPromises);\n\n if (items.length <= 1) {\n return;\n }\n\n const sortedItems = this.sortByVersion(items);\n const [latest, ...oldItems] = sortedItems;\n\n const deletePromises = oldItems.map((oldItem) => fs.rm(oldItem, { recursive: true, force: true }));\n await Promise.all(deletePromises);\n\n console.log(`[WDIO Cleanup] Deleted old drivers/binaries, kept: ${latest}`);\n } catch (error) {\n console.error(`[WDIO Cleanup] Error cleaning cache at ${cachePath}:`, error);\n }\n }\n\n private updateCapabilities(capabilities: WebdriverIO.Capabilities[]) {\n const cacheDir = this.getCacheDir();\n\n for (const cap of capabilities) {\n const options = cap['goog:chromeOptions'] ?? {};\n const args = options.args ?? [];\n if (args.every((arg) => !arg.startsWith('--user-data-dir='))) {\n args.push(`--user-data-dir=${path.join(cacheDir, 'profiles', Random.getStringRandom(12))}`);\n }\n options.args = args;\n cap['goog:chromeOptions'] = options;\n }\n }\n\n async onPrepare() {\n const cacheDir = this.getCacheDir();\n await fs.rm(`${cacheDir}/profiles`, { recursive: true, force: true }).catch();\n }\n\n async onComplete() {\n const cacheDir = this.getCacheDir();\n await this.cleanCache(`${cacheDir}/chrome`);\n await this.cleanCache(`${cacheDir}/chromedriver`);\n await fs.rm(`${cacheDir}/profiles`, { recursive: true, force: true }).catch();\n }\n\n async beforeTest() {\n if (!this.newSessionPerTest) {\n return;\n }\n this.updateCapabilities(ObjectHelper.values(this.myCapabilities));\n\n for (const cap of ObjectHelper.values(this.myCapabilities)) {\n const options = cap['goog:chromeOptions'] ?? {};\n const args = (options.args ?? []).filter((value) => !value.startsWith('--user-data-dir='));\n args.push(`--profile-dir=profile_${Random.getStringRandom(12)}`);\n options.args = args;\n cap['goog:chromeOptions'] = options;\n }\n\n if (isMultiBrowser(browser)) {\n const promises = browser.instances.map((instanceName) =>\n // @ts-expect-error there are typing errors here\n browser[instanceName].reloadSession(this.myCapabilities[instanceName]),\n );\n await Promise.all(promises);\n }\n\n this.afterBeforeTest?.();\n }\n\n async beforeSession(\n config: any,\n capabilities: WebdriverIO.Capabilities | Record<string, { capabilities: WebdriverIO.Capabilities }>,\n ) {\n const resolvedCapabilities: WebdriverIO.Capabilities[] = [];\n if ('browserName' in capabilities) {\n resolvedCapabilities.push(capabilities);\n } else {\n resolvedCapabilities.push(\n ...Object.values(capabilities)\n .filter((obj): obj is { capabilities: WebdriverIO.Capabilities } => !!obj)\n .map((cap) => cap.capabilities),\n );\n\n this.myCapabilities = Object.entries(capabilities)\n .filter(([name, obj]) => !!obj)\n .reduce(\n (acc, [name, cap]) => {\n acc[name] = cap.capabilities;\n return acc;\n },\n {} as URecord<string, WebdriverIO.Capabilities>,\n );\n }\n\n this.updateCapabilities(resolvedCapabilities);\n }\n\n async afterSession(\n config: any,\n capabilities: WebdriverIO.Capabilities | Record<string, undefined | WebdriverIO.Capabilities>,\n ) {\n const resolvedCapabilities: WebdriverIO.Capabilities[] = [];\n if ('browserName' in capabilities) {\n resolvedCapabilities.push(capabilities);\n } else {\n resolvedCapabilities.push(\n ...Object.values(capabilities).filter((obj): obj is WebdriverIO.Capabilities => !!obj),\n );\n }\n\n const profileDirs = resolvedCapabilities\n .filter(\n (cap): cap is WebdriverIO.Capabilities & { chrome: { userDataDir: string } } =>\n 'chrome' in cap &&\n typeof cap.chrome === 'object' &&\n cap.chrome !== null &&\n 'userDataDir' in cap.chrome &&\n !!cap?.chrome?.userDataDir,\n )\n .map((cap) => cap.chrome.userDataDir);\n\n const deletionPromises = profileDirs.map((profileDir) =>\n fs.rm(`${profileDir}`, { recursive: true, force: true }).catch(),\n );\n await Promise.all(deletionPromises);\n }\n}\n","\nexport function createChromeCapability(cacheDir: string, headless: boolean, extraArgs: string[] = [], id = 'default') {\n const args = [\n '--disable-infobars',\n '--enable-automation',\n '--disable-web-security',\n '--disable-popup-blocking',\n '--disable-notifications',\n '--disable-features=MacAppCodeSignClone',\n '--disable-blink-features=AutomationControlled',\n\n ...extraArgs,\n ];\n\n if (headless) {\n args.push('--headless=new');\n }\n\n return {\n browserName: 'chrome',\n browserVersion: 'stable',\n 'goog:chromeOptions': {\n excludeSwitches: ['enable-automation'],\n args,\n prefs: {\n 'intl.accept_languages': 'en',\n credentials_enable_service: false,\n 'profile.password_manager_enabled': false,\n },\n },\n };\n}\n","export * from './ChromeCleanupService';\nexport * from './createChromeCapability';\n"],"names":["ObjectHelper","Random","driver","fs","path","browser","isMultiBrowser","browserInstance","Array","isArray","instances","ChromeCleanupService","constructor","pluginConfig","_browser","config","newSessionPerTest","myCapabilities","cacheDir","_a","afterBeforeTest","getCacheDir","sortByVersion","items","sort","a","b","aVerMatch","match","bVerMatch","aVer","bVer","localeCompare","undefined","numeric","cleanCache","cachePath","exists","stat","then","catch","entries","readdir","itemPromises","map","entry","fullPath","join","isDirectory","push","Promise","all","length","sortedItems","latest","oldItems","deletePromises","oldItem","rm","recursive","force","console","log","error","updateCapabilities","capabilities","cap","options","args","_b","every","arg","startsWith","getStringRandom","onPrepare","onComplete","beforeTest","values","filter","value","promises","instanceName","reloadSession","_c","call","beforeSession","resolvedCapabilities","Object","obj","name","reduce","acc","afterSession","profileDirs","chrome","userDataDir","deletionPromises","profileDir","createChromeCapability","headless","extraArgs","id","browserName","browserVersion","excludeSwitches","prefs","credentials_enable_service"],"sourceRoot":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainias42/wdio-utils",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Utils for WDIO",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -26,9 +26,12 @@
26
26
  },
27
27
  "peerDependencies": {},
28
28
  "dependencies": {
29
- "@ainias42/config": "*"
29
+ "@ainias42/config": "*",
30
+ "@wdio/globals": "^9.23.0",
31
+ "@ainias42/js-helper": ">=0.8.19"
30
32
  },
31
33
  "devDependencies": {
32
- "@ainias42/webpack-config": "*"
34
+ "@ainias42/webpack-config": "*",
35
+ "@wdio/types": "^9.24.0"
33
36
  }
34
37
  }
@@ -1,11 +1,43 @@
1
+ import { ObjectHelper, Random } from '@ainias42/js-helper';
2
+ import { driver } from '@wdio/globals';
1
3
  import fs from 'fs/promises';
2
4
  import path from 'path';
5
+ import type { Awaitable, URecord } from '@ainias42/js-helper';
6
+ import type { Services } from '@wdio/types';
3
7
 
4
- export class ChromeCleanupService {
8
+ type SingleBrowser = {
9
+ capabilities: WebdriverIO.Capabilities;
10
+ instances?: undefined;
11
+ };
12
+
13
+ type MultiBrowser<Names extends string = string> = Record<Names, SingleBrowser> & { instances: Names[] };
14
+ type Browser = MultiBrowser | SingleBrowser;
15
+
16
+ const browser = driver as Browser;
17
+
18
+ function isMultiBrowser(browserInstance: Browser): browserInstance is MultiBrowser {
19
+ return Array.isArray(browserInstance.instances);
20
+ }
21
+
22
+ export class ChromeCleanupService implements Services.ServiceInstance {
5
23
  private cacheDir: string;
24
+ private newSessionPerTest: boolean = true;
25
+ private afterBeforeTest: (() => Awaitable<void>) | undefined;
26
+ // TODO handle single capability
27
+ private myCapabilities: URecord<string, WebdriverIO.Capabilities> = {};
6
28
 
7
- constructor(_1: any, _browser: any, config: { cacheDir: string }) {
29
+ constructor(
30
+ pluginConfig: { newSessionPerTest?: boolean; afterBeforeTest?: () => Awaitable<void> } | undefined,
31
+ _browser: any,
32
+ config: { cacheDir: string },
33
+ ) {
8
34
  this.cacheDir = config.cacheDir;
35
+ this.newSessionPerTest = pluginConfig?.newSessionPerTest ?? this.newSessionPerTest;
36
+ this.afterBeforeTest = pluginConfig?.afterBeforeTest;
37
+ }
38
+
39
+ private getCacheDir() {
40
+ return this.cacheDir ?? 'test/tmp';
9
41
  }
10
42
 
11
43
  // eslint-disable-next-line class-methods-use-this
@@ -59,10 +91,112 @@ export class ChromeCleanupService {
59
91
  }
60
92
  }
61
93
 
94
+ private updateCapabilities(capabilities: WebdriverIO.Capabilities[]) {
95
+ const cacheDir = this.getCacheDir();
96
+
97
+ for (const cap of capabilities) {
98
+ const options = cap['goog:chromeOptions'] ?? {};
99
+ const args = options.args ?? [];
100
+ if (args.every((arg) => !arg.startsWith('--user-data-dir='))) {
101
+ args.push(`--user-data-dir=${path.join(cacheDir, 'profiles', Random.getStringRandom(12))}`);
102
+ }
103
+ options.args = args;
104
+ cap['goog:chromeOptions'] = options;
105
+ }
106
+ }
107
+
108
+ async onPrepare() {
109
+ const cacheDir = this.getCacheDir();
110
+ await fs.rm(`${cacheDir}/profiles`, { recursive: true, force: true }).catch();
111
+ }
112
+
62
113
  async onComplete() {
63
- const cacheDir = this.cacheDir ?? 'test/tmp';
114
+ const cacheDir = this.getCacheDir();
64
115
  await this.cleanCache(`${cacheDir}/chrome`);
65
116
  await this.cleanCache(`${cacheDir}/chromedriver`);
66
- await fs.rm(`${cacheDir}/profiles`, { recursive: true, force: true });
117
+ await fs.rm(`${cacheDir}/profiles`, { recursive: true, force: true }).catch();
118
+ }
119
+
120
+ async beforeTest() {
121
+ if (!this.newSessionPerTest) {
122
+ return;
123
+ }
124
+ this.updateCapabilities(ObjectHelper.values(this.myCapabilities));
125
+
126
+ for (const cap of ObjectHelper.values(this.myCapabilities)) {
127
+ const options = cap['goog:chromeOptions'] ?? {};
128
+ const args = (options.args ?? []).filter((value) => !value.startsWith('--user-data-dir='));
129
+ args.push(`--profile-dir=profile_${Random.getStringRandom(12)}`);
130
+ options.args = args;
131
+ cap['goog:chromeOptions'] = options;
132
+ }
133
+
134
+ if (isMultiBrowser(browser)) {
135
+ const promises = browser.instances.map((instanceName) =>
136
+ // @ts-expect-error there are typing errors here
137
+ browser[instanceName].reloadSession(this.myCapabilities[instanceName]),
138
+ );
139
+ await Promise.all(promises);
140
+ }
141
+
142
+ this.afterBeforeTest?.();
143
+ }
144
+
145
+ async beforeSession(
146
+ config: any,
147
+ capabilities: WebdriverIO.Capabilities | Record<string, { capabilities: WebdriverIO.Capabilities }>,
148
+ ) {
149
+ const resolvedCapabilities: WebdriverIO.Capabilities[] = [];
150
+ if ('browserName' in capabilities) {
151
+ resolvedCapabilities.push(capabilities);
152
+ } else {
153
+ resolvedCapabilities.push(
154
+ ...Object.values(capabilities)
155
+ .filter((obj): obj is { capabilities: WebdriverIO.Capabilities } => !!obj)
156
+ .map((cap) => cap.capabilities),
157
+ );
158
+
159
+ this.myCapabilities = Object.entries(capabilities)
160
+ .filter(([name, obj]) => !!obj)
161
+ .reduce(
162
+ (acc, [name, cap]) => {
163
+ acc[name] = cap.capabilities;
164
+ return acc;
165
+ },
166
+ {} as URecord<string, WebdriverIO.Capabilities>,
167
+ );
168
+ }
169
+
170
+ this.updateCapabilities(resolvedCapabilities);
171
+ }
172
+
173
+ async afterSession(
174
+ config: any,
175
+ capabilities: WebdriverIO.Capabilities | Record<string, undefined | WebdriverIO.Capabilities>,
176
+ ) {
177
+ const resolvedCapabilities: WebdriverIO.Capabilities[] = [];
178
+ if ('browserName' in capabilities) {
179
+ resolvedCapabilities.push(capabilities);
180
+ } else {
181
+ resolvedCapabilities.push(
182
+ ...Object.values(capabilities).filter((obj): obj is WebdriverIO.Capabilities => !!obj),
183
+ );
184
+ }
185
+
186
+ const profileDirs = resolvedCapabilities
187
+ .filter(
188
+ (cap): cap is WebdriverIO.Capabilities & { chrome: { userDataDir: string } } =>
189
+ 'chrome' in cap &&
190
+ typeof cap.chrome === 'object' &&
191
+ cap.chrome !== null &&
192
+ 'userDataDir' in cap.chrome &&
193
+ !!cap?.chrome?.userDataDir,
194
+ )
195
+ .map((cap) => cap.chrome.userDataDir);
196
+
197
+ const deletionPromises = profileDirs.map((profileDir) =>
198
+ fs.rm(`${profileDir}`, { recursive: true, force: true }).catch(),
199
+ );
200
+ await Promise.all(deletionPromises);
67
201
  }
68
202
  }
@@ -1,6 +1,5 @@
1
- import path from 'path';
2
1
 
3
- export function createChromeCapability(cacheDir: string, headless: boolean, extraArgs: string[] = []) {
2
+ export function createChromeCapability(cacheDir: string, headless: boolean, extraArgs: string[] = [], id = 'default') {
4
3
  const args = [
5
4
  '--disable-infobars',
6
5
  '--enable-automation',
@@ -9,7 +8,7 @@ export function createChromeCapability(cacheDir: string, headless: boolean, extr
9
8
  '--disable-notifications',
10
9
  '--disable-features=MacAppCodeSignClone',
11
10
  '--disable-blink-features=AutomationControlled',
12
- `--user-data-dir=${path.join(cacheDir, 'profiles')}`,
11
+
13
12
  ...extraArgs,
14
13
  ];
15
14
 
package/tsconfig.json CHANGED
@@ -1,18 +1,16 @@
1
1
  {
2
- "extends": "@ainias42/config/tsconfig.json",
3
- "compilerOptions": {
4
- "jsx": "react",
5
- "outDir": "./dist",
6
- "declaration": true
7
- },
8
- "exclude": [
9
- "../../node_modules",
10
- "dist/**/*",
11
- "dist/src/**/*"
12
- ],
13
- "include": [
14
- "src/**/*.tsx",
15
- "src/**/*.ts",
16
- "src/**/*.d.ts",
17
- ]
2
+ "extends": "@ainias42/config/tsconfig.json",
3
+ "compilerOptions": {
4
+ "jsx": "react",
5
+ "outDir": "./dist",
6
+ "declaration": true,
7
+ "typeRoots": [
8
+ "node_modules/@types",
9
+ "../../node_modules/@types",
10
+ "../../node_modules/@wdio/globals",
11
+ "../../node_modules/webdriverio/build/@types"
12
+ ]
13
+ },
14
+ "exclude": ["../../node_modules", "dist/**/*", "dist/src/**/*"],
15
+ "include": ["src/**/*.tsx", "src/**/*.ts", "src/**/*.d.ts"]
18
16
  }