UNPKG

@push-based/node-cli-testing

Version:

### A e2e-testing library for node CLI and processes including sandbox generation on the fly

260 lines (259 loc) 10.6 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; exports.__esModule = true; exports.CliProject = exports.getCliProcess = void 0; var fs_1 = require("fs"); var path_1 = require("path"); var index_1 = require("../../../process/src/index"); var utils_1 = require("./utils"); /** * A closure for the testProcessE2e function to seperate process configuration and testing config from test data. * * @param processOptions: passed directly to execa as options */ function getCliProcess(processOptions, promptTestOptions) { return { exec: function (processParams, userInput) { if (processParams === void 0) { processParams = {}; } if (userInput === void 0) { userInput = []; } var processOpts = __spreadArray([promptTestOptions.bin], (0, utils_1.processParamsToParamsArray)(processParams), true); return (0, index_1.testProcessE2e)(processOpts, userInput, processOptions, promptTestOptions); } }; } exports.getCliProcess = getCliProcess; /** * A helper class to manage an project structure for a yargs based CLI */ var CliProject = /** @class */ (function () { function CliProject() { /** * A flag to add more detailed information as logs */ this.verbose = false; /** * The folder in which to execute the process */ this.root = ''; /** * The the binary to execute */ this.bin = ''; /** * The process executing the CLI bin */ this.process = undefined; /** * Filenames to delete e.g. in project teardown * All files are located from root */ this.deleteFiles = []; /** * Filenames to create e.g. in project setup * All files are located from root */ this.createFiles = {}; /** * Filenames to create e.g. in project setup */ this.rcFile = {}; } /** * freezes jest so we can read logs :) * @param ms */ CliProject.prototype.wait = function (ms) { if (ms === void 0) { ms = 30000; } return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, new Promise(function (r) { return setTimeout(r, ms); })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; CliProject.prototype.logVerbose = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } this.verbose && console.log.apply(console, args); }; CliProject.prototype.tableVerbose = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } this.verbose && console.table.apply(console, args); }; CliProject.prototype._setup = function (cfg) { return __awaiter(this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { // global settings this.verbose = Boolean(cfg.verbose); // use configurations this.root = cfg.root; this.bin = cfg.bin; cfg["delete"] && (this.deleteFiles = cfg["delete"]); cfg.create && (this.createFiles = cfg.create); cfg.rcFile && (this.rcFile = cfg.rcFile); // handle default rcPath if (Object.keys(this.rcFile).length > 0) { Object.entries(this.rcFile).forEach(function (_a) { var rcName = _a[0], rcContent = _a[1]; _this.deleteFiles.push(rcName); _this.createFiles[rcName] = rcContent; }); } // remove duplicated paths this.deleteFiles = Array.from(new Set(this.deleteFiles)); this.process = getCliProcess({ cwd: this.root, env: cfg.env }, { bin: this.bin }); return [2 /*return*/]; }); }); }; /** * @internal * @protected * * Method to delete files generated during the CLI run * Notice all files will get located from the project root */ CliProject.prototype.deleteGeneratedFiles = function () { var _this = this; (0, utils_1.deleteFileOrFolder)((this.deleteFiles || []) .map(function (file) { return (0, path_1.join)(_this.root, file); })); }; /** * @internal * @protected * * Method to create files needed during the CLI run * Notice all files will get located from the project root */ CliProject.prototype.createInitialFiles = function () { var _this = this; var preparedPaths = Object.entries((this === null || this === void 0 ? void 0 : this.createFiles) || {}) .map(function (entry) { entry[0] = (0, path_1.join)(_this.root, entry[0]); return entry; }); preparedPaths .forEach(function (_a) { var file = _a[0], content = _a[1]; var exists = (0, fs_1.existsSync)(file); if (exists) { if (content !== undefined) { (0, fs_1.rmSync)(file); _this.logVerbose("File ".concat(file, " got deleted as it already exists")); } } if (content === undefined) { !exists && (0, fs_1.mkdirSync)(file, { recursive: true }); } else { var dir = (0, path_1.dirname)(file); if (!(0, fs_1.existsSync)(dir)) { _this.logVerbose("Created dir ".concat(dir, " to save ").concat(file)); (0, fs_1.mkdirSync)(dir); } switch (true) { case file.endsWith('.png'): case file.endsWith('.ico'): content = Buffer.from(content + '', 'base64'); break; case file.endsWith('.json'): content = JSON.stringify(content); break; } (0, fs_1.writeFileSync)(file, content, 'utf8'); } _this.logVerbose("File ".concat(file, " created")); }); }; /** * Set up the project. e.g. create files, start processes */ CliProject.prototype.setup = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { this.createInitialFiles(); return [2 /*return*/]; }); }); }; /** * Teardown the project. e.g delete files, stop processes */ CliProject.prototype.teardown = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { this.deleteGeneratedFiles(); return [2 /*return*/]; }); }); }; /** * Executes the CLI with given parameters and user input. * See getCliProcess for details * * @param processParams * @param userInput */ CliProject.prototype.exec = function (processParams, userInput) { return this.process.exec(processParams, userInput); }; return CliProject; }()); exports.CliProject = CliProject;