UNPKG

@puppedo/core

Version:

PuppeDo is a runner for tests E2E in YAML style. With power of Playwright or Puppeteer.

180 lines (157 loc) 4.84 kB
/* eslint-disable implicit-arrow-linebreak */ import fs from 'fs'; import path from 'path'; import crypto from 'crypto'; import deepmergeJs from 'deepmerge'; // import { deepmerge } from 'deepmerge-ts'; import dayjs from 'dayjs'; import { ColorsType, SocketType, TestFunctionsBlockNames } from './global.d'; /* https://stackoverflow.com/questions/23975735/what-is-this-u001b9-syntax-of-choosing-what-color-text-appears-on-console SANE = "\u001B[0m" HIGH_INTENSITY = "\u001B[1m" LOW_INTENSITY = "\u001B[2m" ITALIC = "\u001B[3m" UNDERLINE = "\u001B[4m" BLINK = "\u001B[5m" RAPID_BLINK = "\u001B[6m" REVERSE_VIDEO = "\u001B[7m" INVISIBLE_TEXT = "\u001B[8m" BACKGROUND_BLACK = "\u001B[40m" BACKGROUND_RED = "\u001B[41m" BACKGROUND_GREEN = "\u001B[42m" BACKGROUND_YELLOW = "\u001B[43m" BACKGROUND_BLUE = "\u001B[44m" BACKGROUND_MAGENTA = "\u001B[45m" BACKGROUND_CYAN = "\u001B[46m" BACKGROUND_WHITE = "\u001B[47m" */ export enum colors { sane = 0, black = 30, red = 31, green = 32, yellow = 33, blue = 34, magenta = 35, cyan = 36, white = 37, blackBackground = 40, redBackground = 41, greenBackground = 42, yellowBackground = 43, blueBackground = 44, magentaBackground = 45, cyanBackground = 46, whiteBackground = 47, raw = colors.sane, timer = colors.sane, debug = colors.sane, info = colors.cyan, test = colors.green, warn = colors.yellow, error = colors.red, trace = colors.cyan, env = colors.blue, } export function sleep(ms: number): Promise<void> { return new Promise((resolve) => { setTimeout(resolve, ms); }); } export function merge<T>(...objects: T[]): T { // return deepmerge(...objects) as T; return deepmergeJs.all(objects, { arrayMerge: (_, source) => source }); } export const deepMergeField = <T extends Record<string, unknown>>( obj1: T, obj2: Partial<T>, fieldsMerge: Array<keyof T>, ): T => { const mergedFields = fieldsMerge.reduce((acc: Partial<T>, v) => { acc[v] = { ...(obj1[v] ?? {}), ...(obj2[v] ?? {}) } as T[keyof T]; return acc; }, {}); const result = { ...obj1, ...obj2, ...mergedFields }; return result; }; export const paintString = (str: string, color: ColorsType = 'sane'): string => { if (['sane', 'raw', 'timer', 'debug'].includes(color)) { return str; } return `\u001b[${colors[color] || 0}m${str}\u001b[0m`; }; export const blankSocket: SocketType = { send: () => { // Do nothing }, sendYAML: () => { // Do nothing }, }; export const getTimer = ({ timeStartBigInt, timeEndBigInt, timeStart, timeEnd, }: { timeStartBigInt?: bigint; timeEndBigInt?: bigint; timeStart?: Date; timeEnd?: Date; } = {}): { timeStart: Date; timeEnd: Date; timeStartBigInt: bigint; timeEndBigInt: bigint; deltaStr: string; delta: number; } => { const timeStartBigIntResolved = timeStartBigInt ?? process.hrtime.bigint(); const timeEndBigIntResolved = timeEndBigInt ?? process.hrtime.bigint(); const timeStartResolved = timeStart ?? new Date(); const timeEndResolved = timeEnd ?? new Date(); const delta = Number(timeEndBigIntResolved - timeStartBigIntResolved) / 1e9; let deltaStr = `${delta.toFixed(3)} s.`; if (delta > 60) { deltaStr = `${Math.floor(delta / 60)} min. ${(delta % 60).toFixed(3)} s.`; } return { timeStart: timeStartResolved, timeEnd: timeEndResolved, timeStartBigInt: timeStartBigIntResolved, timeEndBigInt: timeEndBigIntResolved, deltaStr, delta, }; }; export const pick = (obj: Record<string, unknown>, fields: string[]): Record<string, unknown> => Object.fromEntries(Object.entries(obj).filter(([key]) => fields.includes(key))); export const omit = (obj: Record<string, unknown>, fields: string[]): Record<string, unknown> => Object.fromEntries(Object.entries(obj).filter(([key]) => !fields.includes(key))); export const getNowDateTime = (now: Date = new Date(), format = 'YYYY-MM-DD_HH-mm-ss.SSS'): string => dayjs(now).format(format); export const walkSync = ( dir: string, options: { ignoreFolders: string[]; extensions?: string[]; ignoreFiles: string[] } = { ignoreFolders: [], ignoreFiles: [], }, ): string[] => { const baseDir = path.basename(dir); if (!fs.existsSync(dir) || options.ignoreFolders.includes(baseDir)) { return []; } if (!fs.statSync(dir).isDirectory()) { return [dir]; } const dirs = fs .readdirSync(dir) .map((f) => walkSync(path.join(dir, f), options)) .flat() .filter((v) => !options.ignoreFiles.includes(v)) .filter((v) => (options.extensions ? options.extensions.includes(path.parse(v).ext) : true)); return dirs; }; export const RUNNER_BLOCK_NAMES: TestFunctionsBlockNames[] = ['beforeTest', 'runTest', 'afterTest']; export const generateId = (length = 6): string => crypto.randomBytes(length).toString('hex');