testeranto
Version:
the AI powered BDD test framework for typescript projects
204 lines (203 loc) • 7.51 kB
JavaScript
/* eslint-disable @typescript-eslint/no-unused-vars */
import ansiC from "ansi-colors";
import path from "path";
import fs from "fs";
import crypto from "node:crypto";
export function runtimeLogs(runtime, reportDest) {
const safeDest = reportDest || `testeranto/reports/default_${Date.now()}`;
try {
if (!fs.existsSync(safeDest)) {
fs.mkdirSync(safeDest, { recursive: true });
}
if (runtime === "node") {
return {
stdout: fs.createWriteStream(`${safeDest}/stdout.log`),
stderr: fs.createWriteStream(`${safeDest}/stderr.log`),
exit: fs.createWriteStream(`${safeDest}/exit.log`),
};
}
else if (runtime === "web") {
return {
info: fs.createWriteStream(`${safeDest}/info.log`),
warn: fs.createWriteStream(`${safeDest}/warn.log`),
error: fs.createWriteStream(`${safeDest}/error.log`),
debug: fs.createWriteStream(`${safeDest}/debug.log`),
exit: fs.createWriteStream(`${safeDest}/exit.log`),
};
}
else if (runtime === "pure") {
return {
exit: fs.createWriteStream(`${safeDest}/exit.log`),
};
}
else if (runtime === "python") {
return {
stdout: fs.createWriteStream(`${safeDest}/stdout.log`),
stderr: fs.createWriteStream(`${safeDest}/stderr.log`),
exit: fs.createWriteStream(`${safeDest}/exit.log`),
};
}
else if (runtime === "golang") {
return {
stdout: fs.createWriteStream(`${safeDest}/stdout.log`),
stderr: fs.createWriteStream(`${safeDest}/stderr.log`),
exit: fs.createWriteStream(`${safeDest}/exit.log`),
};
}
else {
throw `unknown runtime: ${runtime}`;
}
}
catch (e) {
console.error(`Failed to create log streams in ${safeDest}:`, e);
throw e;
}
}
export function createLogStreams(reportDest, runtime) {
// Create directory if it doesn't exist
if (!fs.existsSync(reportDest)) {
fs.mkdirSync(reportDest, { recursive: true });
}
// const streams = {
// exit: fs.createWriteStream(`${reportDest}/exit.log`),
const safeDest = reportDest || `testeranto/reports/default_${Date.now()}`;
try {
if (!fs.existsSync(safeDest)) {
fs.mkdirSync(safeDest, { recursive: true });
}
const streams = runtimeLogs(runtime, safeDest);
// const streams = {
// exit: fs.createWriteStream(`${safeDest}/exit.log`),
// ...(runtime === "node" || runtime === "pure"
// ? {
// stdout: fs.createWriteStream(`${safeDest}/stdout.log`),
// stderr: fs.createWriteStream(`${safeDest}/stderr.log`),
// }
// : {
// info: fs.createWriteStream(`${safeDest}/info.log`),
// warn: fs.createWriteStream(`${safeDest}/warn.log`),
// error: fs.createWriteStream(`${safeDest}/error.log`),
// debug: fs.createWriteStream(`${safeDest}/debug.log`),
// }),
// };
return Object.assign(Object.assign({}, streams), { closeAll: () => {
Object.values(streams).forEach((stream) => !stream.closed && stream.close());
}, writeExitCode: (code, error) => {
if (error) {
streams.exit.write(`Error: ${error.message}\n`);
if (error.stack) {
streams.exit.write(`Stack Trace:\n${error.stack}\n`);
}
}
streams.exit.write(`${code}\n`);
}, exit: streams.exit });
}
catch (e) {
console.error(`Failed to create log streams in ${safeDest}:`, e);
throw e;
}
}
export async function fileHash(filePath, algorithm = "md5") {
return new Promise((resolve, reject) => {
const hash = crypto.createHash(algorithm);
const fileStream = fs.createReadStream(filePath);
fileStream.on("data", (data) => {
hash.update(data);
});
fileStream.on("end", () => {
const fileHash = hash.digest("hex");
resolve(fileHash);
});
fileStream.on("error", (error) => {
reject(`Error reading file: ${error.message}`);
});
});
}
export const statusMessagePretty = (failures, test, runtime) => {
if (failures === 0) {
console.log(ansiC.green(ansiC.inverse(`${runtime} > ${test}`)));
}
else if (failures > 0) {
console.log(ansiC.red(ansiC.inverse(`${runtime} > ${test} failed ${failures} times (exit code: ${failures})`)));
}
else {
console.log(ansiC.red(ansiC.inverse(`${runtime} > ${test} crashed (exit code: -1)`)));
}
};
export async function writeFileAndCreateDir(filePath, data) {
const dirPath = path.dirname(filePath);
try {
await fs.promises.mkdir(dirPath, { recursive: true });
await fs.writeFileSync(filePath, data);
}
catch (error) {
console.error(`Error writing file: ${error}`);
}
}
export const filesHash = async (files, algorithm = "md5") => {
return new Promise((resolve, reject) => {
resolve(files.reduce(async (mm, f) => {
return (await mm) + (await fileHash(f));
}, Promise.resolve("")));
});
};
export function isValidUrl(string) {
try {
new URL(string);
return true;
}
catch (err) {
return false;
}
}
// Wait for file to exist, checks every 2 seconds by default
export async function pollForFile(path, timeout = 2000) {
const intervalObj = setInterval(function () {
const file = path;
const fileExists = fs.existsSync(file);
if (fileExists) {
clearInterval(intervalObj);
}
}, timeout);
}
const executablePath = "/opt/homebrew/bin/chromium";
export const puppeteerConfigs = {
slowMo: 1,
waitForInitialPage: false,
executablePath,
headless: true,
defaultViewport: null, // Disable default 800x600 viewport
dumpio: false,
devtools: false,
args: [
"--allow-file-access-from-files",
"--allow-insecure-localhost",
"--allow-running-insecure-content",
"--auto-open-devtools-for-tabs",
"--disable-dev-shm-usage",
"--disable-extensions",
"--disable-features=site-per-process",
"--disable-gpu",
"--disable-setuid-sandbox",
"--disable-site-isolation-trials",
"--disable-web-security",
"--no-first-run",
"--no-sandbox",
"--no-startup-window",
"--reduce-security-for-testing",
"--remote-allow-origins=*",
"--start-maximized",
"--unsafely-treat-insecure-origin-as-secure=*",
`--remote-debugging-port=3234`,
// "--disable-features=IsolateOrigins,site-per-process",
// "--disable-features=IsolateOrigins",
// "--disk-cache-dir=/dev/null",
// "--disk-cache-size=1",
// "--no-zygote",
// "--remote-allow-origins=ws://localhost:3234",
// "--single-process",
// "--start-maximized",
// "--unsafely-treat-insecure-origin-as-secure",
// "--unsafely-treat-insecure-origin-as-secure=ws://192.168.0.101:3234",
],
};