UNPKG

@ply-ct/ply

Version:

REST API Automated Testing

260 lines 9.41 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 (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __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.DefaultRowConverter = exports.fromXlsx = exports.fromCsv = exports.ValuesBuilder = exports.isExpression = void 0; const process = __importStar(require("process")); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const stream = __importStar(require("stream")); const ply_values_1 = require("@ply-ct/ply-values"); const merge_anything_1 = require("merge-anything"); const csv_parse_1 = require("csv-parse"); const stream_transform_1 = require("stream-transform"); const node_1 = __importDefault(require("read-excel-file/node")); const retrieval_1 = require("./retrieval"); const json_1 = require("./json"); const isExpression = (input) => { return input.startsWith('${') && input.endsWith('}'); }; exports.isExpression = isExpression; class ValuesBuilder { constructor(valuesFiles, logger) { this.logger = logger; this.values = {}; this.enabledLocs = Object.keys(valuesFiles).filter((vf) => valuesFiles[vf]); for (const loc of this.enabledLocs) { if (loc.endsWith('.csv') || loc.endsWith('.xlsx')) { if (this.rowsLoc) { throw new Error('Only one values file may be .csv or .xlsx'); } this.rowsLoc = loc; } } } get isRows() { return !!this.rowsLoc; } async read() { if (process.env['PLY_VALUES']) { this.logger.error('PLY_VALUES environment variable is no longer supported'); } this.values = {}; const valuesHolders = []; for (const location of this.enabledLocs) { if (location.endsWith('.csv') || location.endsWith('.xlsx')) { this.logger.debug(`Delayed load rowwise values file" ${location}`); } else { const contents = await new retrieval_1.Retrieval(location).read(); if (contents) { try { valuesHolders.push({ values: (0, json_1.parseJsonc)(location, contents), location: { path: location } }); } catch (err) { throw new Error(`Cannot parse values file: ${location} (${err.message})`); } } else { this.logger.error(`Values file not found: ${path.normalize(path.resolve(location))}`); } } } this.values = new ply_values_1.ValuesAccess(valuesHolders, { env: process.env }).getValues(); return this.values; } async getRowStream() { if (!this.rowsLoc) { throw new Error('Rowwise values required for row converter'); } const baseVals = (await this.read()) || {}; if (this.rowsLoc.endsWith('.xlsx')) { const readable = new stream.Readable({ objectMode: true }); for (const row of await (0, exports.fromXlsx)(this.rowsLoc)) { this.logger.debug('Row values', row); readable.push((0, merge_anything_1.merge)(baseVals, row)); } readable.push(null); return readable; } else { // stream csv records const parser = fs.createReadStream(this.rowsLoc).pipe((0, csv_parse_1.parse)({ to_line: 1 })); // header row let converter; for await (const row of parser) { converter = new DefaultRowConverter(row); } const transformer = (0, stream_transform_1.transform)(async (row, cb) => { const converted = converter.convert(row); this.logger.debug('Row values', converted); cb(null, (0, merge_anything_1.merge)(baseVals, converted)); }); return fs .createReadStream(this.rowsLoc) .pipe((0, csv_parse_1.parse)({ from_line: 2 })) .pipe(transformer); } } } exports.ValuesBuilder = ValuesBuilder; /** * Reads entire csv file into rows in memory */ const fromCsv = async (file) => { const valueObjs = []; const parser = fs.createReadStream(file).pipe((0, csv_parse_1.parse)({ // CSV options if any })); let converter; for await (const row of parser) { if (converter) { valueObjs.push(converter.convert(row)); } else { converter = new DefaultRowConverter(row); } } return valueObjs; }; exports.fromCsv = fromCsv; /** * Reads entire xlsx file into rows in memory */ const fromXlsx = async (file) => { const valueObjs = []; const rows = await (0, node_1.default)(file); let converter; for await (const row of rows) { if (converter) { valueObjs.push(converter.convert(row)); } else { converter = new DefaultRowConverter(row, { inferPrimitiveTypes: false }); } } return valueObjs; }; exports.fromXlsx = fromXlsx; const defaultOptions = { trimValues: true, trimLabels: true, inferPrimitiveTypes: true, blankIsNull: true }; class DefaultRowConverter { constructor(names, options) { this.options = (0, merge_anything_1.merge)(defaultOptions, options || {}); this.names = names.map((name) => { if (this.options.trimLabels) { return ('' + name).trim(); } else { return '' + name; } }); } splitName(name) { return name.split('.'); } convert(row) { const obj = {}; for (let i = 0; i < row.length; i++) { const segs = this.splitName(this.names[i]); let cur = obj; for (let j = 0; j < segs.length; j++) { const seg = segs[j]; let key = seg; let arrIdx; if (seg.endsWith(']')) { const sq1 = seg.indexOf('['); if (sq1 !== -1) { key = seg.substring(0, sq1); arrIdx = parseInt(seg.substring(sq1 + 1, seg.length - 1)); } } if (j === segs.length - 1) { if (typeof arrIdx === 'number') { if (typeof cur[key] === 'undefined') { cur[key] = []; } cur[key][arrIdx] = this.getValue(row[i]); } else { cur[key] = this.getValue(row[i]); } } else if (typeof arrIdx === 'number') { if (typeof cur[key] === 'undefined') { cur[key] = []; } if (typeof cur[key][arrIdx] === 'undefined') { cur[key][arrIdx] = {}; } cur = cur[key][arrIdx]; } else { if (typeof cur[key] === 'undefined') { cur[key] = {}; } cur = cur[key]; } } } return obj; } /** * TODO: Date */ getValue(str) { let val = str; if (typeof val === 'string') { if (this.options.trimValues) { val = val.trim(); } if (this.options.inferPrimitiveTypes) { const num = parseFloat(val); if (!isNaN(num)) return num; if (val.toLowerCase() === 'true') return true; else if (val.toLowerCase() === 'false') return false; } if (this.options.blankIsNull && val === '') return null; if (val === "''") return ''; } return val; } } exports.DefaultRowConverter = DefaultRowConverter; //# sourceMappingURL=values.js.map