@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.
- package/dist/ChromeCleanupService.d.ts +18 -2
- package/dist/createChromeCapability.d.ts +1 -1
- package/dist/index.js +98 -7
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
- package/src/ChromeCleanupService.ts +138 -4
- package/src/createChromeCapability.ts +2 -3
- package/tsconfig.json +14 -16
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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(
|
|
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.
|
|
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
|
-
|
|
11
|
+
|
|
13
12
|
...extraArgs,
|
|
14
13
|
];
|
|
15
14
|
|
package/tsconfig.json
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"src
|
|
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
|
}
|