@ply-ct/ply
Version:
REST API Automated Testing
260 lines • 9.41 kB
JavaScript
;
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