UNPKG

loadmill

Version:

A node.js module for running load tests and functional tests on loadmill.com

214 lines (184 loc) 6.88 kB
import * as fs from "fs"; import isEmpty = require('lodash/isEmpty'); import isAString = require('lodash/isString'); import * as util from 'util'; const CLI_COLORS = { RED: '\x1b[31m', GREEN: '\x1b[32m', YELLOW: '\x1b[33m', GREY: '\x1b[90m', DEFAULT: '\x1b[0m' } const STATUSES = { PASSED: "PASSED", FAILED: "FAILED", STOPPED: "STOPPED", FLAKY: "FLAKY", }; export enum FLOW_STATUS { DISABLED = 'Disabled', DRAFT = 'Draft', EVALUATING = 'Evaluating', ACTIVE = 'Active', }; const HALF_TAB = " "; function failedFlowLine(f: any, colors: any): string { return `${HALF_TAB}${HALF_TAB}Flow ${f.description} - ${coloredFlowLine(f.status, colors)}`; } const FAILED_STATUS_LINE = `status: '${CLI_COLORS.RED}FAILED${CLI_COLORS.DEFAULT}'`; const PASSED_STATUS_LINE = `status: '${CLI_COLORS.GREEN}PASSED${CLI_COLORS.DEFAULT}'`; export const getObjectAsString = (obj, colors) => { // trim response body to length of 255 if (obj.response && obj.response.text && obj.response.text.length > 1024) { obj.response.text = obj.response.text.substring(0, 1024) + ' [trimmed]' } let str = util.inspect(obj, { showHidden: false, depth: null, compact: false } as any); if (colors) { str = str .replace(/status:\s*'FAILED'/g, FAILED_STATUS_LINE) .replace(/status:\s*'PASSED'/g, PASSED_STATUS_LINE); } return str; } const coloredFlowLine = (status, colors) => { if (!colors) { return status; } return `${getStatusColor(status)}${status}${CLI_COLORS.DEFAULT}`; } export const printOnlyFailedFlowRunsReport = (testSuitesRuns, logger, colors) => { if (Array.isArray(testSuitesRuns) && testSuitesRuns.length > 0) { let total = 0; let totalFailed = 0; let lines: Array<string> =[] testSuitesRuns.forEach(suiteRun => { const { flowRuns } = suiteRun; if (flowRuns && Array.isArray(flowRuns)) { total += flowRuns.length; const suiteLines: Array<string> =[] flowRuns.forEach((f) => { if (f.status === STATUSES.FAILED && f.flowStatus === FLOW_STATUS.ACTIVE) { suiteLines.push(failedFlowLine(f, colors)) } }); if (suiteLines.length > 0) { lines.push(""); lines.push(`${HALF_TAB}Test Suite ${suiteRun.description} has failed flow:`); lines = lines.concat(suiteLines); lines.push(`${HALF_TAB}More info can be found at ${suiteRun.url}`); totalFailed += suiteLines.length; } } }); if (lines.length >0) { logger.log(""); logger.log(`Test Plan errors report - ${CLI_COLORS.RED}${totalFailed} flows have failed ${CLI_COLORS.DEFAULT} (out of ${total} total).`) lines.forEach(l=> logger.log(l)); } } } export const printTestSuitesRunsReport = (testPlanDescription, testSuitesRuns, logger, colors) => { if (Array.isArray(testSuitesRuns) && testSuitesRuns.length > 0) { logger.log(""); logger.log(`Test Plan [${testPlanDescription}] Suites Runs report:`); testSuitesRuns.map( ts => logger.log(`Test Suite ${ts.description} - ${coloredFlowLine(ts.status, colors)}`)); } } export const convertStrToArr = (strWithCommas) => { return typeof strWithCommas !== "string" ? null : strWithCommas.split(","); } export const convertArrToLabelQueryParams = (arr: Array<string | number>): string => { return '&label=' + arr.join('&label='); } export const filterLabels = (labels: Array<number | string>) => { if (!Array.isArray(labels)) { throw new Error(`lables need be in array format i.e. ['my label', 'another label']. Got ${labels}`); } if (labels.every(l => l == '')) { return null; } return labels.filter(l => (typeof l === 'string' || typeof l === 'number') && l !== ''); } export const filterTags = (tags: Array<string>) => { if (!Array.isArray(tags)) { throw new Error(`Tags need be in array format i.e. ['tag1', 'another tag']. Got ${tags}`); } if (tags.every(l => l == '')) { return null; } return tags.filter(l => (typeof l === 'string') && l !== ''); } export const isEmptyObj = (obj) => isEmpty(obj); export const isString = (obj) => isAString(obj); export const isUUID = s => /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(s); export const toLoadmillParams = (rawParams: string[]) => { const parameters = {}; rawParams.forEach(pair => { if (!pair) { return; } const pivot = pair.indexOf('='); if (pivot <= 0) { throw new Error(`Invalid parameter assignment: ${pair}`); } const name = pair.slice(0, pivot); parameters[name] = pair.slice(pivot + 1, pair.length); }); return parameters; } export const readRawParams = (filePath: string): string[] => { try { return fs.readFileSync(filePath, 'utf-8').split(/\r?\n/); } catch (err) { throw new Error(`Couldn't find file '${filePath}'. Please check file path and permissions.`); } }; export const sleep = async (ms: number) => { await new Promise(r => setTimeout(r, ms)); }; export class Logger { private readonly verb: boolean = false; private readonly colors: boolean = false; constructor(verbose: boolean, colors: boolean) { this.verb = verbose; this.colors = colors; } log = (msg, ...args) => console.log(msg, ...args); error = (err) => { if (this.colors) { console.log(CLI_COLORS.RED, err, CLI_COLORS.DEFAULT); } else { console.log(err); } }; warn = (wrn) => { if (this.colors) { console.log(CLI_COLORS.YELLOW, wrn, CLI_COLORS.DEFAULT); } else { console.log(wrn); } }; verbose = (msg, ...args) => this.verb ? console.log(msg, ...args) : void (0); } export const getLogger = (testArgs) => { const verbose = testArgs && testArgs.verbose ? testArgs.verbose : false; const colors = testArgs && testArgs.colors ? testArgs.colors : false; return new Logger(verbose, colors); } const getStatusColor = (status) => { switch (status) { case STATUSES.PASSED: return CLI_COLORS.GREEN; case STATUSES.FAILED: return CLI_COLORS.RED; case STATUSES.STOPPED: return CLI_COLORS.GREY; case STATUSES.FLAKY: return CLI_COLORS.YELLOW; default: return CLI_COLORS.DEFAULT; } } export const TESTING_ORIGIN = process.env.LOADMILL_ORIGIN || "https://app.loadmill.com";