UNPKG

fluentrest-ts

Version:

A lightweight, fluent TypeScript API testing library inspired by Java's RestAssured. Built on top of Axios, JSONPath, and Joi for powerful request handling and response validation.

168 lines (167 loc) 6.38 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.writeLogFile = writeLogFile; exports.log = log; exports.logRequest = logRequest; exports.logResponse = logResponse; exports.logError = logError; exports.formatError = formatError; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const chalk_1 = __importDefault(require("chalk")); const config_1 = require("./config"); function resolveLogFilePath() { return path.resolve(process.cwd(), (0, config_1.getCurrentDefaults)().logFilePath); } function writeLogFile(label, data) { const logPath = resolveLogFilePath(); if (!fs.existsSync(path.dirname(logPath))) { fs.mkdirSync(path.dirname(logPath), { recursive: true }); } const logEntry = `\n--- ${label} ---\n${JSON.stringify(data, null, 2)}\n`; fs.appendFileSync(logPath, logEntry); } /** * Determines if a message should be logged based on the current and required log levels. * @param current - The current log level set for the system. * @param required - The minimum log level required to perform the log. * @returns boolean indicating whether the log should be executed. */ function shouldLog(current, required) { const levels = { none: 0, info: 1, debug: 2 }; return levels[current] >= levels[required]; } /** * Returns a colorized chalk function based on the provided log level. * Used to visually differentiate log messages in the terminal. * @param level - The log level. * @returns chalk color function for the given level. */ function getColor(level) { return level === "debug" ? chalk_1.default.gray : level === "info" ? chalk_1.default.cyan : chalk_1.default.white; // fallback, should never happen } /** * Logs a labeled data message to the console and optionally to a file. * Logging respects the current log level and configured verbosity. * @param label - Descriptive label for the log entry. * @param data - Any payload to log (object, string, etc). * @param logLevel - Current configured log level. * @param logToFile - Flag indicating whether to write logs to a file. * @param level - Log level required to execute the log (defaults to 'info'). */ function log(label, data, logLevel, logToFile, level = "info") { if (!shouldLog(logLevel, level)) return; const color = getColor(level); console.log(color(`\n--- ${label} ---`)); console.dir(data, { depth: null, colors: true }); if (logToFile) { writeLogFile(label, data); } } /** * Logs request details including method, URL, headers, params, and body. * Respects the log level (skips if below 'info'). */ function logRequest(config, logLevel, logToFile) { if (!shouldLog(logLevel, "info")) return; let requestLog = { method: config.method, baseURL: config.baseURL, endpoint: config.url, data: config.data, }; if (shouldLog(logLevel, "debug")) { requestLog = { ...requestLog, headers: config.headers, params: config.params, data: config.data, timeout: config.timeout, baseURL: config.baseURL }; } log("Request", requestLog, logLevel, logToFile, "info"); } /** * Logs the full HTTP response: status, headers, and body. * Skips logging unless log level is 'info' or 'debug'. */ function logResponse(response, logLevel, logToFile) { if (!shouldLog(logLevel, "info")) return; let responseLog = { status: response.status, data: response.data, }; if (shouldLog(logLevel, "debug")) { responseLog = { ...responseLog, headers: response.headers, data: response.data, statusText: response.statusText }; } log("Response", responseLog, logLevel, logToFile, "info"); } /** * Logs errors that occur during request execution or assertions. * This always logs if log level is 'error' or higher. * Optionally writes error details to file if `toFile` is enabled. */ function logError(error, label, logLevel, logToFile, responseBody, errorCode) { const formatted = formatError(label, error, responseBody, errorCode); // Always log errors regardless of logLevel — this is a test failure log(label, { message: formatted }, logLevel, logToFile, "debug"); } /** * Helper to format error messages consistently for throwing or logging. * Includes optional context like payload and custom error code. */ function formatError(message, error, responseBody, errorCode) { const stack = error?.stack ?? "No stack trace"; const bodySnippet = responseBody ? `\nResponse Body:\n${JSON.stringify(responseBody, null, 2)}` : ""; const codePrefix = errorCode ? `[${errorCode}] ` : ""; return `${codePrefix}${message}\n${stack}${bodySnippet}`; }