UNPKG

cypress-load-balancer

Version:

A simple load balancer for Cypress tests.

93 lines (92 loc) 4 kB
import path from "path"; import fs from "node:fs"; class Utils { getPath(...pathNames) { return path.join(process.cwd(), ".cypress_load_balancer", ...pathNames); } //eslint-disable-next-line @typescript-eslint/no-explicit-any DEBUG(...args) { if (process.env.CYPRESS_LOAD_BALANCER_DEBUG == "true") { console.debug("cypress-load-balancer", ...args); } } get CLB_DIRECTORY() { return this.getPath(); } get MAIN_LOAD_BALANCING_MAP_FILE_PATH() { return this.getPath("spec-map.json"); } get MAX_DURATIONS_ALLOWED() { return Number(Number(process.env.CYPRESS_LOAD_BALANCER_MAX_DURATIONS_ALLOWED || 10)); } get TESTING_TYPES() { return ["e2e", "component"]; } /** * Adds a new filepath entry to the load balancing map * @param loadBalancingMap {LoadBalancingMap} * @param testingType {TestingType} * @param filePath {FilePath} * @param [opts={}] * @param [opts.force=] {boolean} If true, will re-create the entry even if one already exists */ createNewEntry(loadBalancingMap, testingType, filePath, opts = {}) { if (loadBalancingMap[testingType][filePath] == null || opts.force === true) { loadBalancingMap[testingType][filePath] = { stats: { durations: [], average: 0 } }; this.DEBUG(`Added new entry for file in load balancer object for "${testingType}" type tests:`, filePath); } else { this.DEBUG(`File already exists in load balancer for "${testingType}" type tests:`, filePath); } } calculateAverageDuration(durations) { return Math.ceil(durations.reduce((acc, t) => acc + Math.abs(t), 0) / (durations.length || 1)); } saveMapFile(loadBalancingMap, fileName) { const file = fileName != null ? this.getPath(fileName.replace(/.json/g, ``) + ".json") : this.MAIN_LOAD_BALANCING_MAP_FILE_PATH; fs.writeFileSync(file, JSON.stringify(loadBalancingMap)); this.DEBUG("Saved load balancing map file"); } shrinkToFit(arr) { if (arr.length > this.MAX_DURATIONS_ALLOWED) { arr.splice(0, arr.length - this.MAX_DURATIONS_ALLOWED); } return arr; } initializeLoadBalancingFiles(opts = {}) { let [isDirectoryCreated, isFileCreated] = [false, false]; const dir = this.CLB_DIRECTORY; if (!fs.existsSync(dir) || opts.forceCreateMainDirectory === true) { fs.mkdirSync(dir); this.DEBUG("Created directory for `/.cypress_load_balancer", `Force initialization?`, opts.forceCreateMainDirectory); isDirectoryCreated = true; } if (!fs.existsSync(this.MAIN_LOAD_BALANCING_MAP_FILE_PATH) || opts.forceCreateMainLoadBalancingMap === true) { this.saveMapFile({ e2e: {}, component: {} }); this.DEBUG("Cypress load balancing file initialized", `Force initialization?`, opts.forceCreateMainLoadBalancingMap); isFileCreated = true; } return [isDirectoryCreated, isFileCreated]; } /** * Updates file status: * Optional: * adds a new duration; * Always: * Removes oldest durations if maximum length has been reached; * Calculates the average duration. * @param loadBalancingMap {LoadBalancingMap} * @param testingType {TestingType} * @param fileName {string} * @param [duration=] {number} Only adds new duration if provided */ updateFileStats(loadBalancingMap, testingType, fileName, duration) { if (duration != null) loadBalancingMap[testingType][fileName].stats.durations.push(duration); this.shrinkToFit(loadBalancingMap[testingType][fileName].stats.durations); loadBalancingMap[testingType][fileName].stats.average = this.calculateAverageDuration(loadBalancingMap[testingType][fileName].stats.durations); } } export default new Utils();