@ainias42/wdio-utils 0.0.1 → 0.0.2

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.
@@ -6,4 +6,5 @@ export declare class ChromeCleanupService {
6
6
  private sortByVersion;
7
7
  private cleanCache;
8
8
  onComplete(): Promise<void>;
9
+ afterSession(): Promise<void>;
9
10
  }
package/dist/index.js CHANGED
@@ -88,6 +88,14 @@ class ChromeCleanupService {
88
88
  force: true
89
89
  });
90
90
  }
91
+ async afterSession() {
92
+ var _a;
93
+ const cacheDir = (_a = this.cacheDir) !== null && _a !== void 0 ? _a : 'test/tmp';
94
+ await default_0.rm(`${cacheDir}/profiles`, {
95
+ recursive: true,
96
+ force: true
97
+ });
98
+ }
91
99
  }
92
100
  ;// ./src/createChromeCapability.ts
93
101
 
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 \"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 async afterSession() {\n const cacheDir = this.cacheDir ?? 'test/tmp';\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","afterSession","createChromeCapability","headless","extraArgs","args","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.2",
4
4
  "description": "Utils for WDIO",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -65,4 +65,9 @@ export class ChromeCleanupService {
65
65
  await this.cleanCache(`${cacheDir}/chromedriver`);
66
66
  await fs.rm(`${cacheDir}/profiles`, { recursive: true, force: true });
67
67
  }
68
+
69
+ async afterSession() {
70
+ const cacheDir = this.cacheDir ?? 'test/tmp';
71
+ await fs.rm(`${cacheDir}/profiles`, { recursive: true, force: true });
72
+ }
68
73
  }