Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

aft-core

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

aft-core - npm Package Compare versions

Comparing version 8.4.2 to 9.0.0

dist/src/helpers/retry.d.ts

81

dist/src/helpers/convert.d.ts
import { JsonObject } from "./custom-types";
/**
* type containing an `exclude` field having either a `string` or `RegExp`
* used to identify characters or strings to be excluded and a `replaceWith`
* field containing a `string` to use as a replacement for each excluded value
*
* Ex:
* ```
* const opts = [{exclude: /[\s]+/g, replaceWith: '_'}];
* convert.toSafeString('I am an example', opts); // returns 'I_am_an_example'
* ```
*/
export declare type SafeStringOption = {

@@ -6,3 +17,13 @@ exclude: string | RegExp;

};
/**
* module providing a default set of string replacement values via the
* `SafeStringOptions.defaults` const
*/
export declare module SafeStringOption {
/**
* a default set of characters to exclude and their replacement values that prevents
* any curly or square brackets, forward or backslashes, commas, dashes, fullstops,
* empty spaces and special characters where special characters are replaced with empty
* string and the rest with underscore
*/
const defaults: SafeStringOption[];

@@ -23,4 +44,11 @@ }

* function will return the number of milliseconds elapsed since the
* passed in timestamp
* @param startTime the value from calling 'new Date().getTime()' at the
* passed in `startTime`
*
* Ex:
* ```
* const start = Date.now();
* // perform some actions...
* convert.toElapsedMs(start); // returns Date.now() - start
* ```
* @param startTime the value from calling 'Date.now()' at the
* point in time when some event has started.

@@ -32,2 +60,7 @@ */

* the value of the passed in 'replaceWith' string
*
* Ex:
* ```
* convert.toSafeString('I am an Example!'); // returns 'I_am_an_Example'
* ```
* @param input the original string to process

@@ -40,2 +73,8 @@ * @param options an array of {exclude: string | RegExp, replaceWith: string} objects to

* converts the passed in `Map` to a JSON string
*
* Ex:
* ```
* const m = new Map<number, string>([[2, "foo"],[5, "bar"]]);
* convert.mapToString(m); // returns '[[2, "foo"],[5, "bar"]]'
* ```
* @param mapObj the `Map` to be converted to a string

@@ -47,2 +86,7 @@ * @returns a JSON string of the format `[["key", "val"],["key", "val"]]`

* converts the passed in string to a valid `Map` object
*
* Ex:
* ```
* convert.stringToMap('[[2, "foo"],[5, "bar"]]'); // returns new Map<number, string>([[2, "foo"],[5, "bar"]])
* ```
* @param mapStr a JSON string representation of a `Map` as an array

@@ -57,2 +101,11 @@ * containing arrays of key-value pairs like `[["key", "val"],["key", "val"]]`

* to a simple JSON object
*
* Ex:
* ```
* const foo = {
* bar: () => 'bar',
* baz: 'baz'
* };
* convert.toJsonObject(foo); // returns {'baz': 'baz'}
* ```
* @param obj an input object to be converted

@@ -69,4 +122,28 @@ * @returns a valid `JsonObject` typed object

toHoursMinutesSeconds(milliseconds: number): string;
/**
* converts the passed in seconds to milliseconds
* @param seconds the number of seconds
* @returns the number of milliseconds in the passed
* in `seconds`
*/
secToMillisec(seconds: number): number;
/**
* converts the passed in minutes to milliseconds
* @param minutes the number of minutes
* @returns the number of milliseconds in the passed in
* `minutes`
*/
minToMillisec(minutes: number): number;
}
/**
* constant helper class for converting values to other values
* such as:
* ```
* convert.toBase64Encoded('foo'); // returns 'Zm9v'
* convert.fromBase64Encoded('Zm9v'); // returns 'foo'
* convert.toSafeString('I am an Example!'); // returns 'I_am_an_Example'
* convert.toHoursMinutesSeconds(3666600); // returns '01:01:06.600'
* ```
*/
export declare const convert: Convert;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convert = exports.SafeStringOption = void 0;
/**
* module providing a default set of string replacement values via the
* `SafeStringOptions.defaults` const
*/
var SafeStringOption;
(function (SafeStringOption) {
/**
* a default set of characters to exclude and their replacement values that prevents
* any curly or square brackets, forward or backslashes, commas, dashes, fullstops,
* empty spaces and special characters where special characters are replaced with empty
* string and the rest with underscore
*/
SafeStringOption.defaults = [

@@ -29,8 +39,15 @@ { exclude: /[\/\\\{\}\(\)\,\.\-]/g, replaceWith: '_' },

* function will return the number of milliseconds elapsed since the
* passed in timestamp
* @param startTime the value from calling 'new Date().getTime()' at the
* passed in `startTime`
*
* Ex:
* ```
* const start = Date.now();
* // perform some actions...
* convert.toElapsedMs(start); // returns Date.now() - start
* ```
* @param startTime the value from calling 'Date.now()' at the
* point in time when some event has started.
*/
toElapsedMs(startTime) {
return new Date().getTime() - startTime;
return Date.now() - startTime;
}

@@ -40,2 +57,7 @@ /**

* the value of the passed in 'replaceWith' string
*
* Ex:
* ```
* convert.toSafeString('I am an Example!'); // returns 'I_am_an_Example'
* ```
* @param input the original string to process

@@ -57,2 +79,8 @@ * @param options an array of {exclude: string | RegExp, replaceWith: string} objects to

* converts the passed in `Map` to a JSON string
*
* Ex:
* ```
* const m = new Map<number, string>([[2, "foo"],[5, "bar"]]);
* convert.mapToString(m); // returns '[[2, "foo"],[5, "bar"]]'
* ```
* @param mapObj the `Map` to be converted to a string

@@ -66,2 +94,7 @@ * @returns a JSON string of the format `[["key", "val"],["key", "val"]]`

* converts the passed in string to a valid `Map` object
*
* Ex:
* ```
* convert.stringToMap('[[2, "foo"],[5, "bar"]]'); // returns new Map<number, string>([[2, "foo"],[5, "bar"]])
* ```
* @param mapStr a JSON string representation of a `Map` as an array

@@ -78,2 +111,11 @@ * containing arrays of key-value pairs like `[["key", "val"],["key", "val"]]`

* to a simple JSON object
*
* Ex:
* ```
* const foo = {
* bar: () => 'bar',
* baz: 'baz'
* };
* convert.toJsonObject(foo); // returns {'baz': 'baz'}
* ```
* @param obj an input object to be converted

@@ -106,4 +148,32 @@ * @returns a valid `JsonObject` typed object

}
/**
* converts the passed in seconds to milliseconds
* @param seconds the number of seconds
* @returns the number of milliseconds in the passed
* in `seconds`
*/
secToMillisec(seconds) {
return seconds * 1000;
}
/**
* converts the passed in minutes to milliseconds
* @param minutes the number of minutes
* @returns the number of milliseconds in the passed in
* `minutes`
*/
minToMillisec(minutes) {
return this.secToMillisec(minutes * 60);
}
}
/**
* constant helper class for converting values to other values
* such as:
* ```
* convert.toBase64Encoded('foo'); // returns 'Zm9v'
* convert.fromBase64Encoded('Zm9v'); // returns 'foo'
* convert.toSafeString('I am an Example!'); // returns 'I_am_an_Example'
* convert.toHoursMinutesSeconds(3666600); // returns '01:01:06.600'
* ```
*/
exports.convert = new Convert();
//# sourceMappingURL=convert.js.map

@@ -93,1 +93,7 @@ /**

export declare type Merge<T1, T2, T3 = {}, T4 = {}, T5 = {}, T6 = {}> = T1 & T2 & T3 & T4 & T5 & T6;
/**
* a retry back-off delay type where `constant` uses the same
* delay each time, `linear` adds the start delay to the previous
* on each iteration and `exponential` doubles the previous delay
*/
export declare type RetryBackOffType = 'constant' | 'linear' | 'exponential';

70

dist/src/helpers/err.d.ts

@@ -0,3 +1,22 @@

import { LogLevel } from '../plugins/logging/log-level';
import { LogManager } from '../plugins/logging/log-manager';
import { Func } from './custom-types';
export declare type ErrVerbosity = 'full' | 'short';
export declare type ErrOptions = {
/**
* an optional `LogManager` instance to use in logging the error message
* and stack
*/
logMgr?: LogManager;
/**
* the `LogLevel` to use when logging any caught `Error`. defaults to
* `warn`
*/
errLevel?: LogLevel;
/**
* the amount of detail to include in the output message. defaults to
* `full`
*/
verbosity?: ErrVerbosity;
};
/**

@@ -8,7 +27,11 @@ * provides a standardised way of generating log-friendly exception details

* const logMgr = new LogManager({logName: 'foo'});
* Err.handle(() => functionThatThrowsTypeError(), logMgr);
* const result = await Err.handle(functionThatThrowsTypeError, {
* logMgr: logMgr,
* errLevel: 'debug',
* verbosity: 'short'
* });
* ```
* which would output:
* ```text
* YYYYMMDD - [foo] - WARN - TypeError: [100 characters of description] --- [300 characters of the stack trace]
* YYYYMMDD - [foo] - DEBUG - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace]
* ```

@@ -22,3 +45,3 @@ * and:

* await logMgr.warn(Err.short(e));
* await logMgr.warn(Err.full(e));
* await logMgr.debug(Err.full(e));
* }

@@ -28,4 +51,5 @@ * ```

* ```text
* YYYYMMDD - [AFT] - WARN - TypeError: [100 characters of description] --- [300 characters of the stack trace]
* YYYYMMDD - [AFT] - WARN - TypeError: [full type error description message] --- [full stack trace of as much as the Error contained]
* YYYYMMDD - [AFT] - WARN - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace]
* YYYYMMDD - [AFT] - DEBUG - TypeError: [full type error description message]
* [full stack trace of as much as the Error contained]
* ```

@@ -35,12 +59,15 @@ */

readonly err: Error;
private readonly _type;
private readonly _message;
private readonly _stack;
constructor(err: any);
short(): string;
full(): string;
private _verbosity;
constructor(error: any);
get verbosity(): ErrVerbosity;
setVerbosity(v: ErrVerbosity): this;
get type(): string;
get message(): string;
get stack(): string;
toString(): string;
private _isError;
private _processMessage;
private _processStack;
private _removeInternalStackLines;
private _removeBadCharacters;
private _formatOutput;
private _removeNewlinesAndExtraWhitespace;
}

@@ -51,3 +78,3 @@ export declare module Err {

* @returns a shortened string formatted as `Error.name: Error.message (max 100 chars) --- Error.stack (max 300 chars)`
* where any single quotes, newlines and extra spaces are removed
* where any newlines, tabs and extra spaces are removed
*/

@@ -57,4 +84,8 @@ function short(err: any): string;

* @param err the `Error` to parse
* @returns a full length string formatted as `Error.name: Error.message --- Error.stack`
* where any single quotes, newlines and extra spaces are removed
* @returns a full length string formatted as
* ```
* Error.name: Error.message
* Error.stack
* ```
* where the full Error details are preserved
*/

@@ -65,6 +96,9 @@ function full(err: any): string;

* @param func a function to be run inside a try-catch
* @param logMgr an optional `LogManager` that will log any error
* @param optsOrLogMgr an `ErrOptions` object containing options for this handler or a
* `LogManager` used to log any captured `Error` _(defaults to `undefined`)_
* > **WARNING** passing a `LogManager` is deprecated and you should instead add the
* `LogManager` using the `logMgr` field in the `ErrOptions` instance)
* @returns the result of the passed in `func` or `null` if an error is thrown
*/
function handle<T extends any>(func: Func<void, T | PromiseLike<T>>, logMgr?: LogManager): Promise<T>;
function handle<T extends any>(func: Func<void, T | PromiseLike<T>>, optsOrLogMgr?: LogManager | ErrOptions): Promise<T>;
}

@@ -20,7 +20,11 @@ "use strict";

* const logMgr = new LogManager({logName: 'foo'});
* Err.handle(() => functionThatThrowsTypeError(), logMgr);
* const result = await Err.handle(functionThatThrowsTypeError, {
* logMgr: logMgr,
* errLevel: 'debug',
* verbosity: 'short'
* });
* ```
* which would output:
* ```text
* YYYYMMDD - [foo] - WARN - TypeError: [100 characters of description] --- [300 characters of the stack trace]
* YYYYMMDD - [foo] - DEBUG - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace]
* ```

@@ -34,3 +38,3 @@ * and:

* await logMgr.warn(Err.short(e));
* await logMgr.warn(Err.full(e));
* await logMgr.debug(Err.full(e));
* }

@@ -40,35 +44,76 @@ * ```

* ```text
* YYYYMMDD - [AFT] - WARN - TypeError: [100 characters of description] --- [300 characters of the stack trace]
* YYYYMMDD - [AFT] - WARN - TypeError: [full type error description message] --- [full stack trace of as much as the Error contained]
* YYYYMMDD - [AFT] - WARN - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace]
* YYYYMMDD - [AFT] - DEBUG - TypeError: [full type error description message]
* [full stack trace of as much as the Error contained]
* ```
*/
class Err {
constructor(err) {
if (err) {
if (!this._isError(err)) {
this.err = new Error(String(err));
}
else {
this.err = err;
}
if (this.err) {
this._type = this.err.name || 'Error';
this._message = this._removeBadCharacters(this.err.message);
this._stack = this._removeBadCharacters(this._removeInternalStackLines(this.err.stack));
}
constructor(error) {
if (this._isError(error)) {
this.err = error;
}
else {
this.err = new Error(String(error || 'unknown'));
}
}
short() {
return this._formatOutput(false);
get verbosity() {
if (!this._verbosity) {
this._verbosity = 'full';
}
return this._verbosity;
}
full() {
return this._formatOutput(true);
setVerbosity(v) {
this._verbosity = (['full', 'short'].includes(v)) ? v : 'full';
return this;
}
get type() {
var _a;
return ((_a = this.err) === null || _a === void 0 ? void 0 : _a.name) || 'Error';
}
get message() {
var _a;
return ((_a = this.err) === null || _a === void 0 ? void 0 : _a.message) || 'unknown';
}
get stack() {
var _a;
return ((_a = this.err) === null || _a === void 0 ? void 0 : _a.stack) || 'unknown';
}
toString() {
const message = this._processMessage(this.message);
const stack = this._processStack(this.stack);
let output;
if (this.verbosity === 'short') {
output = `${this.type}: ${message} --- ${stack}`;
}
else {
output = `${this.type}: ${message}\n${stack}`;
}
return output;
}
_isError(obj) {
return (obj === null || obj === void 0 ? void 0 : obj.name) && (obj === null || obj === void 0 ? void 0 : obj.message) && (obj === null || obj === void 0 ? void 0 : obj.stack);
}
_processMessage(message) {
let msg = message;
if (this.verbosity === 'short') {
msg = (0, ellide_1.ellide)(msg, 100);
msg = this._removeNewlinesAndExtraWhitespace(msg);
}
return msg;
}
_processStack(stack) {
let stk = this._removeInternalStackLines(stack);
if (this.verbosity === 'short') {
const stackLines = stk.split('\n');
if (stackLines.length > 0) {
stk = (0, ellide_1.ellide)(stackLines[0], 300, 'middle');
}
stk = this._removeNewlinesAndExtraWhitespace(stk);
}
return stk;
}
_removeInternalStackLines(stack) {
const resultStackLines = new Array();
const stackLines = stack.split('\n');
for (var i = 0; i < stackLines.length; i++) {
const stackLines = (stack === null || stack === void 0 ? void 0 : stack.split('\n')) || [];
for (var i = 1; i < stackLines.length; i++) {
let line = stackLines[i];

@@ -79,16 +124,11 @@ if (line.match(/.*(err).(ts|js)/gi) == null) {

}
return resultStackLines.join('\n').replace(`${this._type}: ${this._message}`, '');
return resultStackLines.join('\n').replace(`${this.type}: ${this.message}`, '');
}
_removeBadCharacters(input) {
_removeNewlinesAndExtraWhitespace(input) {
return (input) ? convert_1.convert.toSafeString(input, [
{ exclude: /\`/g, replaceWith: '' },
{ exclude: /[\n\t]/g, replaceWith: '' },
{ exclude: /[\n\r]/g, replaceWith: '' },
{ exclude: /[\t]/g, replaceWith: ' ' },
{ exclude: /[ ]{2,}/g, replaceWith: ' ' }
]) : '';
}
_formatOutput(full) {
let msg = (full) ? this._message : (0, ellide_1.ellide)(this._message, 100);
let stk = (full) ? this._stack : (0, ellide_1.ellide)(this._stack, 300);
return `${this._type}: ${msg} --- ${stk}`;
}
}

@@ -100,6 +140,8 @@ exports.Err = Err;

* @returns a shortened string formatted as `Error.name: Error.message (max 100 chars) --- Error.stack (max 300 chars)`
* where any single quotes, newlines and extra spaces are removed
* where any newlines, tabs and extra spaces are removed
*/
function short(err) {
return new Err(err).short();
return new Err(err)
.setVerbosity('short')
.toString();
}

@@ -109,7 +151,13 @@ Err.short = short;

* @param err the `Error` to parse
* @returns a full length string formatted as `Error.name: Error.message --- Error.stack`
* where any single quotes, newlines and extra spaces are removed
* @returns a full length string formatted as
* ```
* Error.name: Error.message
* Error.stack
* ```
* where the full Error details are preserved
*/
function full(err) {
return new Err(err).full();
return new Err(err)
.setVerbosity('full')
.toString();
}

@@ -120,11 +168,25 @@ Err.full = full;

* @param func a function to be run inside a try-catch
* @param logMgr an optional `LogManager` that will log any error
* @param optsOrLogMgr an `ErrOptions` object containing options for this handler or a
* `LogManager` used to log any captured `Error` _(defaults to `undefined`)_
* > **WARNING** passing a `LogManager` is deprecated and you should instead add the
* `LogManager` using the `logMgr` field in the `ErrOptions` instance)
* @returns the result of the passed in `func` or `null` if an error is thrown
*/
function handle(func, logMgr) {
function handle(func, optsOrLogMgr) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
let opts;
if (_isLogManager(optsOrLogMgr)) { // TODO: remove this in next major release
opts = { logMgr: optsOrLogMgr };
yield ((_a = opts.logMgr) === null || _a === void 0 ? void 0 : _a.warn(`passing a 'LogManager' is DEPRECATED! pass a 'ErrOptions' object containing your 'LogManager' instead`));
}
else {
opts = optsOrLogMgr || {};
}
return yield Promise.resolve()
.then(func)
.catch((err) => __awaiter(this, void 0, void 0, function* () {
yield (logMgr === null || logMgr === void 0 ? void 0 : logMgr.warn(Err.short(err)));
var _b;
const e = new Err(err).setVerbosity(opts === null || opts === void 0 ? void 0 : opts.verbosity);
yield ((_b = opts === null || opts === void 0 ? void 0 : opts.logMgr) === null || _b === void 0 ? void 0 : _b[(opts === null || opts === void 0 ? void 0 : opts.errLevel) || 'warn'](e.toString()));
return null;

@@ -135,3 +197,9 @@ }));

Err.handle = handle;
function _isLogManager(obj) {
if ((obj === null || obj === void 0 ? void 0 : obj.logName) && (obj === null || obj === void 0 ? void 0 : obj.trace) && (obj === null || obj === void 0 ? void 0 : obj.debug) && (obj === null || obj === void 0 ? void 0 : obj.info)) {
return true;
}
return false;
}
})(Err = exports.Err || (exports.Err = {}));
//# sourceMappingURL=err.js.map

@@ -8,2 +8,16 @@ /**

* throwing an exception
*
* Ex:
* ```
* const maxWait = 10000; // 10 seconds
* const maxHold = 5000; // 5 seconds
* // wait a maximum of 10 seconds to aquire lock and then hold
* // lock for maximum of 5 seconds or until `unlock` is called
* const lock = new ExpiringFileLock('unique_name', maxWait, maxHold);
* try {
* // perform action on shared resource...
* } finally {
* lock?.unlock();
* }
* ```
*/

@@ -10,0 +24,0 @@ export declare class ExpiringFileLock {

@@ -17,2 +17,16 @@ "use strict";

* throwing an exception
*
* Ex:
* ```
* const maxWait = 10000; // 10 seconds
* const maxHold = 5000; // 5 seconds
* // wait a maximum of 10 seconds to aquire lock and then hold
* // lock for maximum of 5 seconds or until `unlock` is called
* const lock = new ExpiringFileLock('unique_name', maxWait, maxHold);
* try {
* // perform action on shared resource...
* } finally {
* lock?.unlock();
* }
* ```
*/

@@ -19,0 +33,0 @@ class ExpiringFileLock {

@@ -87,3 +87,3 @@ "use strict";

_writeToFile() {
let lock = file_io_1.fileio.getExpiringFileLock(this.filename, 10000, 5000);
const lock = file_io_1.fileio.getExpiringFileLock(this.filename, 10000, 5000);
try {

@@ -98,3 +98,3 @@ file_io_1.fileio.write(this.filename, convert_1.convert.mapToString(this._memoryMap));

let fileMapData;
let lock = file_io_1.fileio.getExpiringFileLock(this.filename, 10000, 5000);
const lock = file_io_1.fileio.getExpiringFileLock(this.filename, 10000, 5000);
try {

@@ -101,0 +101,0 @@ fileMapData = file_io_1.fileio.readAs(this.filename, convert_1.convert.stringToMap);

@@ -36,3 +36,3 @@ "use strict";

}) // and then dispose with any Error
.finally(() => disposable.dispose(err));
.finally(() => disposable === null || disposable === void 0 ? void 0 : disposable.dispose(err));
});

@@ -39,0 +39,0 @@ }

@@ -18,4 +18,10 @@ export interface VerifierMatcher {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(equaling(5)); // succeeds
* await verifier(() => undefined).returns(equaling(null)); // succeeds
* await verifier(() => true).returns(equaling(false)); // fails
* ```
* @param expected the expected value
* @returns a new {Equaling} instance
* @returns a new `Equaling` instance
*/

@@ -34,4 +40,10 @@ export declare const equaling: (expected: any) => Equaling;

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(exactly(5)); // succeeds
* await verifier(() => undefined).returns(exactly(null)); // fails
* await verifier(() => true).returns(exactly(false)); // fails
* ```
* @param expected the expected value
* @returns a new {Exactly} instance
* @returns a new `Exactly` instance
*/

@@ -52,5 +64,14 @@ export declare const exactly: (expected: any) => Exactly;

* between the `minimum`, `maximum` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(between(5, 6)); // succeeds
* await verifier(() => 5).returns(between(4, 5)); // succeeds
* await verifier(() => 5).returns(between(-5, 10)); // succeeds
* await verifier(() => 5).returns(between(0, 4)); // fails
* await verifier(() => 5).returns(between(6, 10)); // fails
* await verifier(() => null).returns(between(6, 10)); // fails
* ```
* @param minimum the minimum value the `actual` result can be
* @param maximum the maximum value the `actual` result can be
* @returns a new {NumberBetween} instance
* @returns a new `NumberBetween` instance
*/

@@ -70,4 +91,13 @@ export declare const between: (minimum: number, maximum: number) => NumberBetween;

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 'foobarbaz').returns(containing('bar')); // succeeds
* await verifier(() => [1, 2, 3, 4, 5, 6]).returns(containing(5)); // succeeds
* await verifier(() => new Set([1, 2, 3, 4, 5, 6]).returns(containing(5)); // succeeds
* await verifier(() => new Map([[5, 'five'], [6, 'six']])).returns(containing(5)); // succeeds
* await verifier(() => 'foo').returns(containing('oof')); // fails
* await verifier(() => new Map([[5, 'five'], [6, 'six']])).returns(containing('five')); // fails
* ```
* @param expected the expected value
* @returns a new {ValueContaining} instance
* @returns a new `ValueContaining` instance
*/

@@ -85,3 +115,11 @@ export declare const containing: (expected: any) => ValueContaining;

* between the where `a` is the `actual` result
* @returns a new {HavingValue} instance
* like:
* ```
* await verifier(() => 'foobarbaz').returns(havingValue()); // succeeds
* await verifier(() => false).returns(havingValue()); // succeeds
* await verifier(() => 0).returns(havingValue()); // succeeds
* await verifier(() => null).returns(havingValue()); // fails
* await verifier(() => undefined).returns(havingValue()); // fails
* ```
* @returns a new `HavingValue` instance
*/

@@ -100,4 +138,11 @@ export declare const havingValue: () => HavingValue;

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(greaterThan(0)); // succeeds
* await verifier(() => 5).returns(greaterThan(4.999)); // succeeds
* await verifier(() => 5).returns(greaterThan(5)); // fails
* await verifier(() => null).returns(greaterThan(0)); // fails
* ```
* @param expected the expected value
* @returns a new {GreaterThan} instance
* @returns a new `GreaterThan` instance
*/

@@ -116,4 +161,11 @@ export declare const greaterThan: (expected: number) => GreaterThan;

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(lessThan(10)); // succeeds
* await verifier(() => 5).returns(lessThan(5.0001)); // succeeds
* await verifier(() => 5).returns(lessThan(5)); // fails
* await verifier(() => null).returns(lessThan(10)); // fails
* ```
* @param expected the expected value
* @returns a new {LessThan} instance
* @returns a new `LessThan` instance
*/

@@ -131,6 +183,13 @@ export declare const lessThan: (expected: number) => LessThan;

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(not(equaling(10))); // succeeds
* await verifier(() => null).returns(not(exactly(undefined))); // succeeds
* await verifier(() => [1, 2, 3]).returns(not(containing(5))); // succeeds
* await verifier(() => null).returns(not(havingValue())); // succeeds
* ```
* @param expected a {VerifierMatcher} to negate
* @returns a new {Negate} instance
* @returns a new `Negate` instance
*/
export declare const not: (expected: VerifierMatcher) => Negate;
export {};

@@ -22,4 +22,10 @@ "use strict";

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(equaling(5)); // succeeds
* await verifier(() => undefined).returns(equaling(null)); // succeeds
* await verifier(() => true).returns(equaling(false)); // fails
* ```
* @param expected the expected value
* @returns a new {Equaling} instance
* @returns a new `Equaling` instance
*/

@@ -48,4 +54,10 @@ const equaling = (expected) => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(exactly(5)); // succeeds
* await verifier(() => undefined).returns(exactly(null)); // fails
* await verifier(() => true).returns(exactly(false)); // fails
* ```
* @param expected the expected value
* @returns a new {Exactly} instance
* @returns a new `Exactly` instance
*/

@@ -79,5 +91,14 @@ const exactly = (expected) => {

* between the `minimum`, `maximum` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(between(5, 6)); // succeeds
* await verifier(() => 5).returns(between(4, 5)); // succeeds
* await verifier(() => 5).returns(between(-5, 10)); // succeeds
* await verifier(() => 5).returns(between(0, 4)); // fails
* await verifier(() => 5).returns(between(6, 10)); // fails
* await verifier(() => null).returns(between(6, 10)); // fails
* ```
* @param minimum the minimum value the `actual` result can be
* @param maximum the maximum value the `actual` result can be
* @returns a new {NumberBetween} instance
* @returns a new `NumberBetween` instance
*/

@@ -125,4 +146,13 @@ const between = (minimum, maximum) => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 'foobarbaz').returns(containing('bar')); // succeeds
* await verifier(() => [1, 2, 3, 4, 5, 6]).returns(containing(5)); // succeeds
* await verifier(() => new Set([1, 2, 3, 4, 5, 6]).returns(containing(5)); // succeeds
* await verifier(() => new Map([[5, 'five'], [6, 'six']])).returns(containing(5)); // succeeds
* await verifier(() => 'foo').returns(containing('oof')); // fails
* await verifier(() => new Map([[5, 'five'], [6, 'six']])).returns(containing('five')); // fails
* ```
* @param expected the expected value
* @returns a new {ValueContaining} instance
* @returns a new `ValueContaining` instance
*/

@@ -151,3 +181,11 @@ const containing = (expected) => {

* between the where `a` is the `actual` result
* @returns a new {HavingValue} instance
* like:
* ```
* await verifier(() => 'foobarbaz').returns(havingValue()); // succeeds
* await verifier(() => false).returns(havingValue()); // succeeds
* await verifier(() => 0).returns(havingValue()); // succeeds
* await verifier(() => null).returns(havingValue()); // fails
* await verifier(() => undefined).returns(havingValue()); // fails
* ```
* @returns a new `HavingValue` instance
*/

@@ -176,4 +214,11 @@ const havingValue = () => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(greaterThan(0)); // succeeds
* await verifier(() => 5).returns(greaterThan(4.999)); // succeeds
* await verifier(() => 5).returns(greaterThan(5)); // fails
* await verifier(() => null).returns(greaterThan(0)); // fails
* ```
* @param expected the expected value
* @returns a new {GreaterThan} instance
* @returns a new `GreaterThan` instance
*/

@@ -202,4 +247,11 @@ const greaterThan = (expected) => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(lessThan(10)); // succeeds
* await verifier(() => 5).returns(lessThan(5.0001)); // succeeds
* await verifier(() => 5).returns(lessThan(5)); // fails
* await verifier(() => null).returns(lessThan(10)); // fails
* ```
* @param expected the expected value
* @returns a new {LessThan} instance
* @returns a new `LessThan` instance
*/

@@ -228,4 +280,11 @@ const lessThan = (expected) => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(not(equaling(10))); // succeeds
* await verifier(() => null).returns(not(exactly(undefined))); // succeeds
* await verifier(() => [1, 2, 3]).returns(not(containing(5))); // succeeds
* await verifier(() => null).returns(not(havingValue())); // succeeds
* ```
* @param expected a {VerifierMatcher} to negate
* @returns a new {Negate} instance
* @returns a new `Negate` instance
*/

@@ -232,0 +291,0 @@ const not = (expected) => {

@@ -9,2 +9,21 @@ import { BuildInfoManager } from "../plugins/build-info/build-info-manager";

import { VerifierMatcher } from "./verifier-matcher";
/**
* class to be used for executing some Functional Test Assertion after checking with any
* `TestCasePlugin` and `DefectPlugin` instances that have been loaded to confirm that the
* assertion should be executed based on referenced Test ID(s) or Defect ID(s)
*
* Ex:
* ```
* await verify(async (v: Verifier) => {
* await v.logMgr.info('doing some testing...');
* let feature = new FeatureObj();
* return await feature.returnExpectedValue();
* }).withDescription('example usage for Verifier')
* .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run
* .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run
* .returns('expected value');
* ```
* @param assertion the `Func<Verifier, any>` function to be executed by this `Verifier`
* @returns a new `Verifier` instance
*/
export declare class Verifier implements PromiseLike<void> {

@@ -24,5 +43,6 @@ protected _assertion: Func<Verifier, any>;

/**
* a `LogManager` that uses either the `withDescription`
* or a list of `withTestId` or a uuid as the `logName` depending
* on which is available and where `description` is preferred most
* a `LogManager` that uses either the Description
* or a list of Test Ids or a `uuid` as the `logName` depending
* on which is available (NOTE: description is preferred most and
* will be used if other values are also present)
*/

@@ -68,6 +88,6 @@ get logMgr(): LogManager;

* your test case management system. if all the referenced `testId` values should not be
* run (as returned by your {AbstractTestCasePlugin.shouldRun(testId)}) then
* run (as returned by your `AbstractTestCasePlugin.shouldRun(testId)`) then
* the `assertion` will not be run.
* NOTE: multiple `testId` values can be chained together
* @param testIds a test identifier for your connected {AbstractTestCasePlugin}
* @param testIds a test identifier for your connected `AbstractTestCasePlugin`
* @returns this `Verifier` instance

@@ -100,5 +120,5 @@ */

/**
* allows for using a specific {TestCaseManager} instance. if not
* set then the global {TestCaseManager.instance()} will be used
* @param testMgr a {TestCaseManager} instance
* allows for using a specific `TestCaseManager` instance. if not
* set then the global `TestCaseManager.instance()` will be used
* @param testMgr a `TestCaseManager` instance
* @returns this `Verifier` instance

@@ -108,5 +128,5 @@ */

/**
* allows for using a specific {DefectManager} instance. if not
* set then the global {DefectManager.instance()} will be used
* @param defectMgr a {DefectManager} instance
* allows for using a specific `DefectManager` instance. if not
* set then the global `DefectManager.instance()` will be used
* @param defectMgr a `DefectManager` instance
* @returns this `Verifier` instance

@@ -116,5 +136,5 @@ */

/**
* allows for using a specific {BuildInfoManager} instance. if not
* set then the global {BuildInfoManager.instance()} will be used
* @param buildMgr a {BuildInfoManager} instance
* allows for using a specific `BuildInfoManager` instance. if not
* set then the global `BuildInfoManager.instance()` will be used
* @param buildMgr a `BuildInfoManager` instance
* @returns this `Verifier` instance

@@ -126,6 +146,4 @@ */

/**
* creates `ITestResult` objects for each `testId` and sends these
* creates `TestResult` objects for each `testId` and sends these
* to the `LogManager.logResult` function
* @param result an `IProcessingResult` returned from executing the
* expectation
*/

@@ -140,3 +158,4 @@ protected _logResult(status: TestStatus, message?: string): Promise<void>;

* Test Assertion.
* ex:
*
* Ex:
* ```

@@ -148,8 +167,9 @@ * await verify(async (v: Verifier) => {

* }).withDescription('example usage for Verifier')
* .and.withTestId('C1234')
* .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run
* .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run
* .returns('expected value');
* ```
* @param assertion the {Func<Verifier, any>} function to be executed by this `Verifier`
* @param assertion the `Func<Verifier, any>` function to be executed by this `Verifier`
* @returns a new `Verifier` instance
*/
export declare const verify: (assertion: Func<Verifier, any>) => Verifier;

@@ -20,2 +20,21 @@ "use strict";

const verifier_matcher_1 = require("./verifier-matcher");
/**
* class to be used for executing some Functional Test Assertion after checking with any
* `TestCasePlugin` and `DefectPlugin` instances that have been loaded to confirm that the
* assertion should be executed based on referenced Test ID(s) or Defect ID(s)
*
* Ex:
* ```
* await verify(async (v: Verifier) => {
* await v.logMgr.info('doing some testing...');
* let feature = new FeatureObj();
* return await feature.returnExpectedValue();
* }).withDescription('example usage for Verifier')
* .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run
* .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run
* .returns('expected value');
* ```
* @param assertion the `Func<Verifier, any>` function to be executed by this `Verifier`
* @returns a new `Verifier` instance
*/
class Verifier {

@@ -28,5 +47,6 @@ constructor() {

/**
* a `LogManager` that uses either the `withDescription`
* or a list of `withTestId` or a uuid as the `logName` depending
* on which is available and where `description` is preferred most
* a `LogManager` that uses either the Description
* or a list of Test Ids or a `uuid` as the `logName` depending
* on which is available (NOTE: description is preferred most and
* will be used if other values are also present)
*/

@@ -150,6 +170,6 @@ get logMgr() {

* your test case management system. if all the referenced `testId` values should not be
* run (as returned by your {AbstractTestCasePlugin.shouldRun(testId)}) then
* run (as returned by your `AbstractTestCasePlugin.shouldRun(testId)`) then
* the `assertion` will not be run.
* NOTE: multiple `testId` values can be chained together
* @param testIds a test identifier for your connected {AbstractTestCasePlugin}
* @param testIds a test identifier for your connected `AbstractTestCasePlugin`
* @returns this `Verifier` instance

@@ -207,5 +227,5 @@ */

/**
* allows for using a specific {TestCaseManager} instance. if not
* set then the global {TestCaseManager.instance()} will be used
* @param testMgr a {TestCaseManager} instance
* allows for using a specific `TestCaseManager` instance. if not
* set then the global `TestCaseManager.instance()` will be used
* @param testMgr a `TestCaseManager` instance
* @returns this `Verifier` instance

@@ -218,5 +238,5 @@ */

/**
* allows for using a specific {DefectManager} instance. if not
* set then the global {DefectManager.instance()} will be used
* @param defectMgr a {DefectManager} instance
* allows for using a specific `DefectManager` instance. if not
* set then the global `DefectManager.instance()` will be used
* @param defectMgr a `DefectManager` instance
* @returns this `Verifier` instance

@@ -229,5 +249,5 @@ */

/**
* allows for using a specific {BuildInfoManager} instance. if not
* set then the global {BuildInfoManager.instance()} will be used
* @param buildMgr a {BuildInfoManager} instance
* allows for using a specific `BuildInfoManager` instance. if not
* set then the global `BuildInfoManager.instance()` will be used
* @param buildMgr a `BuildInfoManager` instance
* @returns this `Verifier` instance

@@ -292,6 +312,4 @@ */

/**
* creates `ITestResult` objects for each `testId` and sends these
* creates `TestResult` objects for each `testId` and sends these
* to the `LogManager.logResult` function
* @param result an `IProcessingResult` returned from executing the
* expectation
*/

@@ -390,3 +408,4 @@ _logResult(status, message) {

* Test Assertion.
* ex:
*
* Ex:
* ```

@@ -398,6 +417,7 @@ * await verify(async (v: Verifier) => {

* }).withDescription('example usage for Verifier')
* .and.withTestId('C1234')
* .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run
* .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run
* .returns('expected value');
* ```
* @param assertion the {Func<Verifier, any>} function to be executed by this `Verifier`
* @param assertion the `Func<Verifier, any>` function to be executed by this `Verifier`
* @returns a new `Verifier` instance

@@ -404,0 +424,0 @@ */

import { Func } from "./custom-types";
declare class Wait {
/**
* function will execute an asynchronous action and await a result repeating execution every 1 millisecond until a
* result of 'true' is returned or the 'msDuration' specified has elapsed. If the action never returns 'true' and
* the 'msDuration' elapses, an Error will be thrown by way of a Promise.reject
* @param condition an asynchronous action that should be executed until it returns 'true' or the 'msDuration' has expired
* @param msDuration the maximum amount of time to wait for the 'condition' to return 'true'
* @param onFailAction an action to perform on each attempt resulting in failure ('Error' or 'false') of the 'condition'
* function will wait for the specified amount of time
* @param durationMs the amount of time to wait before resuming
*/
untilTrue(condition: Func<void, boolean | PromiseLike<boolean>>, msDuration: number, onFailAction?: Func<void, any>): Promise<void>;
forDuration(durationMs: number): Promise<void>;
/**
* function will wait for the specified amount of time
* @param msDuration the amount of time to wait before resuming
* waits up to the specified `maxDurationMs` for a result from the passed in `func`
* @param func a synchronous or async function returning a result of type `T`
* @param maxDurationMs the maximum amount of time to wait (defaults to 30 seconds)
* @returns the result of the passed in `func` or `undefined` if the `maxDurationMs` elapses before `func`
* returns a result
*/
forDuration(msDuration: number): Promise<void>;
forResult<T>(func: Func<void, T | PromiseLike<T>>, maxDurationMs?: number): Promise<T>;
/**
* will wait until the specified time
* @param time either the time in milliseconds past the epoch or a `Date` object
* representing the desired time to wait until
*/
until(time: number | Date): Promise<void>;
}
export declare const wait: Wait;
export {};

@@ -13,57 +13,53 @@ "use strict";

exports.wait = void 0;
const err_1 = require("./err");
const convert_1 = require("./convert");
class Wait {
/**
* function will execute an asynchronous action and await a result repeating execution every 1 millisecond until a
* result of 'true' is returned or the 'msDuration' specified has elapsed. If the action never returns 'true' and
* the 'msDuration' elapses, an Error will be thrown by way of a Promise.reject
* @param condition an asynchronous action that should be executed until it returns 'true' or the 'msDuration' has expired
* @param msDuration the maximum amount of time to wait for the 'condition' to return 'true'
* @param onFailAction an action to perform on each attempt resulting in failure ('Error' or 'false') of the 'condition'
* function will wait for the specified amount of time
* @param durationMs the amount of time to wait before resuming
*/
untilTrue(condition, msDuration, onFailAction) {
forDuration(durationMs) {
return __awaiter(this, void 0, void 0, function* () {
let result = false;
let attempts = 0;
const startTime = new Date().getTime();
let err;
do {
attempts++;
result = yield Promise.resolve()
.then(condition)
.catch((e) => {
err = e;
return false;
});
if (!result) {
if (onFailAction) {
yield Promise.resolve()
.then(onFailAction)
.catch((err) => {
/* ignore */
});
}
}
yield this.forDuration(1);
} while (result !== true && convert_1.convert.toElapsedMs(startTime) < msDuration);
if (result) {
return Promise.resolve();
}
return Promise.reject(`wait.untilTrue(...) exceeded [${convert_1.convert.toHoursMinutesSeconds(msDuration)}] over '${attempts}' attempts without returning 'true'${(err) ? ` due to: ${err_1.Err.short(err)}` : ''}`);
return new Promise((resolve) => {
setTimeout(resolve, durationMs);
});
});
}
/**
* function will wait for the specified amount of time
* @param msDuration the amount of time to wait before resuming
* waits up to the specified `maxDurationMs` for a result from the passed in `func`
* @param func a synchronous or async function returning a result of type `T`
* @param maxDurationMs the maximum amount of time to wait (defaults to 30 seconds)
* @returns the result of the passed in `func` or `undefined` if the `maxDurationMs` elapses before `func`
* returns a result
*/
forDuration(msDuration) {
forResult(func, maxDurationMs = 30000) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve) => {
setTimeout(resolve, msDuration);
});
return yield Promise.race([
Promise.resolve().then(func).catch((err) => Promise.reject(err)),
new Promise((resolve) => setTimeout(resolve, maxDurationMs, undefined))
]);
});
}
/**
* will wait until the specified time
* @param time either the time in milliseconds past the epoch or a `Date` object
* representing the desired time to wait until
*/
until(time) {
return __awaiter(this, void 0, void 0, function* () {
let t;
if (typeof time === "number") {
t = time;
}
else {
t = time.getTime();
}
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
while (Date.now() < t) {
yield exports.wait.forDuration(1);
}
resolve();
}));
});
}
}
exports.wait = new Wait();
//# sourceMappingURL=wait.js.map

@@ -23,2 +23,3 @@ /** configuration */

export * from './helpers/rand';
export * from './helpers/retry';
export * from './helpers/using';

@@ -25,0 +26,0 @@ export * from './helpers/verifier';

@@ -39,2 +39,3 @@ "use strict";

__exportStar(require("./helpers/rand"), exports);
__exportStar(require("./helpers/retry"), exports);
__exportStar(require("./helpers/using"), exports);

@@ -41,0 +42,0 @@ __exportStar(require("./helpers/verifier"), exports);

@@ -0,1 +1,5 @@

/**
* type representing if a Defect is still open or if it has
* been resolved (closed)
*/
export declare type DefectStatus = 'open' | 'closed';

@@ -26,3 +26,3 @@ import { LoggingPlugin, LoggingPluginOptions } from "./logging-plugin";

* "plugins": [
* "logging-plugin1",
* {"name": "logging-plugin1", "enabled": true, "searchDirectory": "./dist/", "options": {"foo": "bar"}},
* {"name": "logging-plugin2", "enabled": false, "options": {"foo": "bar"}}

@@ -29,0 +29,0 @@ * ]

@@ -32,3 +32,3 @@ "use strict";

* "plugins": [
* "logging-plugin1",
* {"name": "logging-plugin1", "enabled": true, "searchDirectory": "./dist/", "options": {"foo": "bar"}},
* {"name": "logging-plugin2", "enabled": false, "options": {"foo": "bar"}}

@@ -35,0 +35,0 @@ * ]

@@ -14,3 +14,3 @@ import { Plugin } from './plugin';

* ```typescript
* let plugins: CustomPlugin[] = pluginloader.load<CustomPlugin>([{
* const plugins: CustomPlugin[] = pluginloader.load<CustomPlugin>([{
* name: 'custom-plugin',

@@ -51,18 +51,25 @@ * searchDirectory: '../../plugins',

* responsible for finding and loading plugins based on a passed in
* {pluginName} and optional {options}. any plugin loaded by this
* class must extend from {AbstractPlugin<any>} and would be expected
* to accept an {options} object in its constructor.
* `PluginConfig`. any plugin loaded by this class must extend from
* `Plugin<T extends PluginOptions>` and would be expected to accept an object extending
* `PluginOptions` object in its constructor.
*
* ```typescript
* let plugin: CustomPlugin = await pluginloader.load<CustomPlugin>('custom-plugin', {foo: 'bar'});
* const plugins: CustomPlugin[] = pluginloader.load<CustomPlugin>([{
* name: 'custom-plugin',
* searchDirectory: '../../plugins',
* enabled: false,
* options: {
* storagePath: './'
* }
* }, 'custom-plugin-2']);
* ```
* NOTE: the above will attempt to load `custom-plugin` package
* passing in the specified options to its constructor. if loading
*
* **NOTE:** the above attempts to load a `custom-plugin` class. if loading
* fails then it will search the filesystem, starting at the current
* execution directory and searching all subdirectories, for a file
* named `custom-plugin.js` which, if found, will be imported and a
* new instance will be created passing in the specified options to
* its constructor. following instantiation the {onLoad} function is
* awaited and then the new plugin instance is returned
* new instance will be created and added to the internal cache and the
* array to be returned
*/
export declare const pluginloader: PluginLoader;
export {};

@@ -25,3 +25,3 @@ "use strict";

* ```typescript
* let plugins: CustomPlugin[] = pluginloader.load<CustomPlugin>([{
* const plugins: CustomPlugin[] = pluginloader.load<CustomPlugin>([{
* name: 'custom-plugin',

@@ -177,18 +177,25 @@ * searchDirectory: '../../plugins',

* responsible for finding and loading plugins based on a passed in
* {pluginName} and optional {options}. any plugin loaded by this
* class must extend from {AbstractPlugin<any>} and would be expected
* to accept an {options} object in its constructor.
* `PluginConfig`. any plugin loaded by this class must extend from
* `Plugin<T extends PluginOptions>` and would be expected to accept an object extending
* `PluginOptions` object in its constructor.
*
* ```typescript
* let plugin: CustomPlugin = await pluginloader.load<CustomPlugin>('custom-plugin', {foo: 'bar'});
* const plugins: CustomPlugin[] = pluginloader.load<CustomPlugin>([{
* name: 'custom-plugin',
* searchDirectory: '../../plugins',
* enabled: false,
* options: {
* storagePath: './'
* }
* }, 'custom-plugin-2']);
* ```
* NOTE: the above will attempt to load `custom-plugin` package
* passing in the specified options to its constructor. if loading
*
* **NOTE:** the above attempts to load a `custom-plugin` class. if loading
* fails then it will search the filesystem, starting at the current
* execution directory and searching all subdirectories, for a file
* named `custom-plugin.js` which, if found, will be imported and a
* new instance will be created passing in the specified options to
* its constructor. following instantiation the {onLoad} function is
* awaited and then the new plugin instance is returned
* new instance will be created and added to the internal cache and the
* array to be returned
*/
exports.pluginloader = new PluginLoader();
//# sourceMappingURL=plugin-loader.js.map

@@ -40,5 +40,4 @@ import { Plugin } from "./plugin";

* "plugins": [
* {name: "some-custom-plugin", enabled: false, searchDirectory: "/full/path/to/search"},
* "some-other-plugin",
* {name: "a-third-plugin", searchDirectory: "../../relative-path-to-search", options: {"foo": "option used by plugin instance"}}
* {"name": "some-custom-plugin", "enabled": false, "searchDirectory": "/full/path/to/search"},
* {"name": "a-second-plugin", "searchDirectory": "../../relative-path-to-search", "options": {"foo": "option used by plugin instance"}}
* ],

@@ -45,0 +44,0 @@ * "bar": "configurataion used by PluginManagerInstance"

@@ -47,5 +47,4 @@ "use strict";

* "plugins": [
* {name: "some-custom-plugin", enabled: false, searchDirectory: "/full/path/to/search"},
* "some-other-plugin",
* {name: "a-third-plugin", searchDirectory: "../../relative-path-to-search", options: {"foo": "option used by plugin instance"}}
* {"name": "some-custom-plugin", "enabled": false, "searchDirectory": "/full/path/to/search"},
* {"name": "a-second-plugin", "searchDirectory": "../../relative-path-to-search", "options": {"foo": "option used by plugin instance"}}
* ],

@@ -52,0 +51,0 @@ * "bar": "configurataion used by PluginManagerInstance"

@@ -6,3 +6,3 @@ import { TestCase } from "./test-case";

/**
* loads and provides an interface between any `ITestCasePlugin`
* loads and provides access to a `TestCasePlugin` for use in conditional test execution and filtering.
* to specify a plugin use the following `aftconfig.json` key:

@@ -12,4 +12,6 @@ * ```

* ...
* "testcasemanager": {
* "pluginNames": ["plugin-name"]
* "TestCaseManager": {
* "plugins": [
* {"name": "test-case-plugin", "options": {"username": "foo@bar.com", "accesskey": "SuperSecretKey"}}
* ]
* }

@@ -16,0 +18,0 @@ * ...

@@ -15,3 +15,3 @@ "use strict";

/**
* loads and provides an interface between any `ITestCasePlugin`
* loads and provides access to a `TestCasePlugin` for use in conditional test execution and filtering.
* to specify a plugin use the following `aftconfig.json` key:

@@ -21,4 +21,6 @@ * ```

* ...
* "testcasemanager": {
* "pluginNames": ["plugin-name"]
* "TestCaseManager": {
* "plugins": [
* {"name": "test-case-plugin", "options": {"username": "foo@bar.com", "accesskey": "SuperSecretKey"}}
* ]
* }

@@ -25,0 +27,0 @@ * ...

@@ -31,3 +31,26 @@ "use strict";

});
describe('secToMillisec', () => {
const testData = [0.5, 1, 10, 60];
for (var i = 0; i < testData.length; i++) {
const data = testData[i];
it(`can calculate the milliseconds in '${data}' seconds`, () => {
expect(src_1.convert.secToMillisec(data)).toEqual(data * 1000);
});
}
});
describe('minToMillisec', () => {
const testData = [
{ min: 0.5, exp: 30000 },
{ min: 1, exp: 60000 },
{ min: 2, exp: 120000 },
{ min: 60, exp: 3600000 }
];
for (var i = 0; i < testData.length; i++) {
const data = testData[i];
it(`can convert minutes to milliseconds for ${JSON.stringify(data)}`, () => {
expect(src_1.convert.minToMillisec(data.min)).toEqual(data.exp);
});
}
});
});
//# sourceMappingURL=convert-spec.js.map

@@ -19,46 +19,83 @@ "use strict";

expect(actual.err.message).toEqual(err.message);
expect(actual.verbosity).toEqual('full');
});
it('can generate a shortened string', () => {
const err = new Error(src_1.rand.getString(1000, true, true, true, true));
const actual = src_1.Err.short(err);
expect(actual.length).toBeLessThan(450);
it('verbosity can be set', () => {
const err = new Error(src_1.rand.getString(25));
const actual = new src_1.Err(err).setVerbosity('short');
expect(actual.err).toBeDefined();
expect(actual.err.message).toEqual(err.message);
expect(actual.verbosity).toEqual('short');
});
it('can generate a full Error string', () => {
const err = new Error(src_1.rand.getString(500, true, true, true, true));
const actual = src_1.Err.full(err);
expect(actual.length).toBeGreaterThan(500);
describe('short', () => {
it('can generate a shortened string', () => {
const err = new Error(src_1.rand.getString(1000, true, true, true, true));
const actual = src_1.Err.short(err);
expect(actual.length).toBeLessThan(450);
});
it('can handle null argument to contstuctor', () => {
const actual = src_1.Err.short(null);
expect(actual).toMatch(/^(Error: unknown --- )[ \w\d]+/gi);
});
});
it('can handle null argument to contstuctor', () => {
const actual = src_1.Err.full(null);
expect(actual).toEqual('undefined: undefined --- undefined');
describe('full', () => {
it('can generate a full Error string', () => {
const err = new Error(src_1.rand.getString(500, true, true, true, true));
const actual = src_1.Err.full(err);
expect(actual.length).toBeGreaterThan(500);
});
it('can handle null argument to contstuctor', () => {
const actual = src_1.Err.full(null);
expect(actual).toMatch(/^(Error: unknown\n)[\s\w\d]+/gi);
});
});
it('can handle try-catch for a Func<void, any> that does not throw', () => __awaiter(void 0, void 0, void 0, function* () {
const func = function () { return 'foo'; };
const val = yield src_1.Err.handle(func);
expect(val).toEqual('foo');
}));
it('can handle try-catch for a Func<void, any> that throws', () => __awaiter(void 0, void 0, void 0, function* () {
const func = function () { throw 'foo'; };
const val = yield src_1.Err.handle(func);
expect(val).toBeNull();
}));
it('can handle try-catch for a Func<void, any> that rejects a Promise', () => __awaiter(void 0, void 0, void 0, function* () {
const func = () => Promise.reject('foo');
const val = yield src_1.Err.handle(func);
expect(val).toBeNull();
}));
it('will log a warning if a LogManager is supplied and the Func throws', () => __awaiter(void 0, void 0, void 0, function* () {
const logMgr = new src_1.LogManager({ logName: 'will log a warning if a LogManager is supplied and the Func throws', plugins: [] });
let logMessage;
spyOn(logMgr, 'warn').and.callFake((message) => {
logMessage = message;
return Promise.resolve();
});
const func = function () { throw 'foo'; };
const val = yield src_1.Err.handle(func, logMgr);
expect(val).toBeNull();
expect(logMgr.warn).toHaveBeenCalledTimes(1);
expect(logMessage).toContain('Error: foo ');
}));
describe('handle', () => {
it('can handle try-catch for a Func<void, any> that does not throw', () => __awaiter(void 0, void 0, void 0, function* () {
const func = function () { return 'foo'; };
const val = yield src_1.Err.handle(func);
expect(val).toEqual('foo');
}));
it('can handle try-catch for a Func<void, any> that throws', () => __awaiter(void 0, void 0, void 0, function* () {
const func = function () { throw 'foo'; };
const val = yield src_1.Err.handle(func);
expect(val).toBeNull();
}));
it('can handle try-catch for a Func<void, any> that rejects a Promise', () => __awaiter(void 0, void 0, void 0, function* () {
const func = () => Promise.reject('foo');
const val = yield src_1.Err.handle(func);
expect(val).toBeNull();
}));
it('will log a warning if a LogManager is supplied and the Func throws', () => __awaiter(void 0, void 0, void 0, function* () {
const logMgr = new src_1.LogManager({ logName: 'will log a warning if a LogManager is supplied and the Func throws', plugins: [] });
let logMessage;
spyOn(logMgr, 'warn').and.callFake((message) => {
logMessage = message;
return Promise.resolve();
});
const func = function () { throw 'foo'; };
const val = yield src_1.Err.handle(func, logMgr);
expect(val).toBeNull();
expect(logMgr.warn).toHaveBeenCalledTimes(2); // 1 time for logging and 1 time to output deprecation warning for passing LogMgr instead of ErrOptions
expect(logMessage).toContain('Error: foo');
}));
it('accepts ErrOptions as a second argument', () => __awaiter(void 0, void 0, void 0, function* () {
const func = function () { throw 'foo'; };
const logger = new src_1.LogManager({ logName: 'accepts ErrOptions as a second argument' });
let actualLevel;
let actualMessage;
spyOn(logger, 'log').and.callFake((level, message) => {
actualLevel = level;
actualMessage = message;
return Promise.resolve();
});
const val = yield src_1.Err.handle(func, {
verbosity: 'short',
errLevel: 'info',
logMgr: logger
});
expect(val).toBeNull();
expect(actualLevel).toEqual('info');
expect(actualMessage).not.toContain('\n');
}));
});
});
//# sourceMappingURL=err-spec.js.map

@@ -15,67 +15,42 @@ "use strict";

describe('Wait', () => {
beforeEach(() => {
TestHelper.reset();
});
it('can wait for a less than the maximum duration if action returns true', () => __awaiter(void 0, void 0, void 0, function* () {
let now = new Date().getTime();
yield wait_1.wait.untilTrue(() => __awaiter(void 0, void 0, void 0, function* () {
// wait 1 ms and return false 2 times, then true
yield new Promise((resolve) => {
setTimeout(resolve, 1);
it('can wait for a less than the maximum duration', () => __awaiter(void 0, void 0, void 0, function* () {
let start = new Date().getTime();
const result = yield wait_1.wait.forResult(() => 12, 500);
let elapsed = convert_1.convert.toElapsedMs(start);
expect(result).toEqual(12);
expect(elapsed).toBeLessThan(500);
}));
it('will return null on timeout', () => __awaiter(void 0, void 0, void 0, function* () {
const start = new Date().getTime();
const result = yield wait_1.wait.forResult(() => {
return new Promise((resolve) => {
// called after `wait` duration times out
setTimeout(() => resolve(12), 2000);
});
TestHelper.count += 1;
return TestHelper.count > 2;
}), 2000);
let elapsed = convert_1.convert.toElapsedMs(now);
expect(elapsed).toBeGreaterThan(3);
expect(elapsed).toBeLessThan(2000);
expect(TestHelper.count).toEqual(3);
}, 500);
const elapsed = convert_1.convert.toElapsedMs(start);
expect(result).toBeUndefined();
expect(elapsed).toBeLessThan(1000);
}));
it('will emit a rejected promise if duration is exceeded without returning true', () => __awaiter(void 0, void 0, void 0, function* () {
const now = new Date().getTime();
it('allows exceptions in func through', () => __awaiter(void 0, void 0, void 0, function* () {
let actualErr;
yield wait_1.wait.untilTrue(() => __awaiter(void 0, void 0, void 0, function* () {
TestHelper.count += 1;
return false;
}), 200).catch((err) => {
const result = yield wait_1.wait.forResult(() => { throw 'fake error'; }, 200)
.catch((err) => {
actualErr = err;
return -1;
});
const elapsed = convert_1.convert.toElapsedMs(now);
expect(elapsed).toBeGreaterThanOrEqual(200);
expect(elapsed).toBeLessThan(1000);
expect(TestHelper.count).toBeGreaterThan(10);
expect(actualErr).toEqual(`wait.untilTrue(...) exceeded [${convert_1.convert.toHoursMinutesSeconds(200)}] over '${TestHelper.count}' attempts without returning 'true'`);
}));
it('can execute a failure action on each failed attempt', () => __awaiter(void 0, void 0, void 0, function* () {
let actual = 0;
yield wait_1.wait.untilTrue(() => { throw new Error('fake error'); }, 200, () => __awaiter(void 0, void 0, void 0, function* () {
actual++;
yield wait_1.wait.forDuration(50);
})).catch((err) => { });
expect(actual).toBeGreaterThan(1);
}));
it('can handle a rejected promise in the passed in func', () => __awaiter(void 0, void 0, void 0, function* () {
let actualErr;
yield wait_1.wait.untilTrue(() => Promise.reject('fake error'), 200)
.catch((err) => actualErr = err);
expect(result).toEqual(-1);
expect(actualErr).toContain('fake error');
}));
it('can handle exceptions in the failure action on each failed attempt', () => __awaiter(void 0, void 0, void 0, function* () {
let actual = 0;
yield wait_1.wait.untilTrue(() => { throw new Error('fake error'); }, 200, () => __awaiter(void 0, void 0, void 0, function* () {
actual++;
yield wait_1.wait.forDuration(50);
throw new Error('onFailureAction error');
})).catch((err) => { });
expect(actual).toBeGreaterThan(1);
it('allows rejected promises through', () => __awaiter(void 0, void 0, void 0, function* () {
let error;
const result = yield wait_1.wait.forResult(() => Promise.reject('fake rejection'), 200)
.catch((err) => {
error = err;
return -1;
});
expect(result).toEqual(-1);
expect(error).toContain('fake rejection');
}));
});
var TestHelper;
(function (TestHelper) {
TestHelper.count = 0;
function reset() {
TestHelper.count = 0;
}
TestHelper.reset = reset;
})(TestHelper || (TestHelper = {}));
//# sourceMappingURL=wait-spec.js.map

@@ -1,1 +0,1 @@

[["DSG194SXJ10X","UK0Z1MV8AY475IYOG5"],["IDP81GMY8NXC","HWWODIBCUAYDGZQENSVFIMORSFLYSFMINGLIHOYQAQLZXHHNOIKDWFPTIUFNMUALYGGBCGWHPDJZSOVNDJIXIGBOFCYWWYBXSIBFIKRIZSYMAQWYHTWCTPKLIORJWGEFGYHIPAWLOP"],["FD5H5UYB2KUB6733CQH","9R3V6368JKF2QXSUJR6HH4I"],["7KYBL8MHWV","HEWXTEWHZVVXMYXZQBKTYXMHCROXAWAJPKNHIBNFATIWWTTEWFCTHAVZWSBAMPLFLIRWSLCBYWNPOZZKJIDYOGRWMYAOMMBFVYLNOXOATFZMKHMSDALCWIAXNPHTKSDFBLWXWIHKAFZESGKODGAZAGOXOQFNFIMYENU"],["CGM99PI1M8","1E8USIQS2YRHKP3LS4ANSBRI"],["HNZCAJ8V63SK","NCRLYCANRVESTNOGKHGPPCSJWTBUXKLRXTJTRGCQEDWLBKBEJBJULRYMDWNKMQHEUSXVMZOJJRASWKUKZYONDBFTXLFNJVOVWVRZAYQATEHTYULXRGGUAYWDBZG"],["LQZS2ERJKA52","XQ2U1F6D1P6F9RE0"],["O7F8S6P22K74591","XCHGNJUPNDOCBYPFAMNCGEJWDBSIFLNZRYXVSFNMMXVAWFKJQXEKWFKBVOLNCTHKCTVUPBQNMMJHAEEOMYVWPEASNTDNOSMXHTUQVDSQZWLEHDDLGCNZ"],["8FKOQRUHDEMFBA","UR71XH4DJ9VPY9BM86PHBVOTZ"],["PVZZQSGEGPU0","BQ6F4SN9V8ZSC81KJVI816ISED"],["6OISJAXZL6PZH7VB1","28VVDEQO4ZSWMT1FNK7RYBYPRMAD"],["Y8FYRGCA7K4","P6SZ0DQGBG71OIUF4K4A7YE"],["WT213LFWGMH9QBDN3NJ","NROOWM5TEG7WZ50ZV"],["U2007RHGVRL11VD","RQRVOFQSDKUZKOZBDJADNHZNEDHKXIIQGVVEFHSOZAHLLBJZWSCSRDVKDHGMPVPUGKHJFGXCMYFKEEJTRWBHOYMAVFHOAOUTHMXXKLDQOROZRUJEBVCGIFYNSMGVIFW"],["MNBOPFL86WO3AP3GR","75IPN8RL02VZSG3"],["8M26ETIBYSK","587ZQQIQ1TZQMJEJZEROV9U3IVPGI"],["BM7YH4ZL439NW","G9PB8OZX7US30CRTQ0GQE"],["V64KY4D644MHME","PYE7G3RQ8FTUGE27GE5LU2"],["003EM6NG43RIE6AAO3","9TO1X1123Q38RGH1MS697"],["63JX0ME1AKBC0NL","K7EZMDFIVRBDSZKFXUAFN5BKQN9TN"],["OBEV17ABNPPE767","P9E7KWW9BGCQAI6OUX"],["UCL2XCK8KHT7O5U9","1NCTRWX2OBAVRQS5IP"],["Y9O6ZM73P3AX49TG","J5Y6965ET2L73UKDP26B5UGW"],["NES2MCZM0MPV9YLTBH","4CWRQHLT3G4I6NMIA"]]
[["EMEZ3RS3M1M","3WH5BE6H46X3ZWYV8ZVT8PD94I"],["9ILQ9Z8B8E44JHZD5I","3CERVOOTHCXS4JF5NG9T0DGV9GS9"],["V90QGSDUGIJES53PL0","64RS5JT0GR4GB4XDGVMIEULYYWX"],["RJOVF0DTCCRLBM","Q93VJC6PJQ8N63NAVXOA16LLA"],["E165HLUFGY3Y","5GAOZVS9IQOLVKMFFK4O"],["0HWOVLUG4VEYM10ZYKC","ZXJUNMBLWQTPCZUEDWBWFNIGDZTNPTRWYWJXSQPMORDTGYLDCMQSPPPUELUYZVSLQTTPOKNAIBSMWVAZVLWFNQXZKDGDQJQDABJETFKHMO"],["0AM0UTOI4KM0CK6","OKYK3Y59KMNE4ROEM"],["ZD5NLES60WN23GEV","XQUUTERRCRYQGLMOSGNWTLBYXQDRXPMBBNSKIPJYVGENYDPPXYRXATRUETTIPCFIIIPSWNUZTTPDCUTRVEPXEUUCKCMDBIKTMRCHXNBUHNOTTHNOOZPMPMVLOWDGEVIIPQJQI"],["J27U7940YT6XJRSU1","TWC96VP3D28MXC06F4T1ZY1"],["T4FQ48PN2GY4","HHUETHJXT961NTO0JQBJY7A2V4J0"],["ET0U7H7CR6GBN4","3ZBX4ACHC67FG98KFGD86"],["WM5TT7WOATXA","HQVNPICAYBRCJZMHCXMPITVSILONTKZBAIWSWZHYBOUGVBDZAOCSJKEAUARGVCYJPMFTNWEIUMLKQSVYKVYMFQXKLUOFYSHEPMFUMDUPWSJFDEZHHBRNRVNMEEVCNORTNQATGVURRAXYJJBMMFWMHURMGVYSTMBFVLOBQXQTIIKFXMFIFVUKHOYAGG"],["68E5S3VGZT84","P8FL157XX3ZDD69JR0O"],["YAV2L8ZA32","FFHKJLZQJMQC73P"],["MWT4E1UO6FIXS5ENN","SIZHPBR6IO58SECMT9W3LQXGK"],["9B43U2950ZIZP7J62Q","6J6L6948Q1LAAOZ5DE1XENT3N2AL"],["X57VI6TMJZH4C8SE","E02IN72T3KYSEGOCIQ"],["VCWCOZWJ8SN1IFWFT","OFCAJYHFSOTNAXCVCLQHBHIPDWJQSHWRBBGZEMQNYORKBVODUVVSGGTEGBMVRVAQGHJJVYGKHHLDHXKIWRHKEWEIAGTHMMCQMIZEHRIBGKTYJUITVUQSBGMALOLVDEGYWUXSUDZPKQABRPCYBDNHNJCUBIJTYFWTTNKIXJCLGSDHVCAGTDMIVZJOANZAXYOD"],["1B9LJ6BJW20KTS9GM","T6K25NHBNIMMM3ZIGVELAB"],["0BKN8ZY8YA28GXKC63X","IU7DJIOCD8BELNXJN"],["CXNAS36FEWJE00Q7GTV","OXZ26UKLVC0CDFZ39HE0EXE"],["7O3VSCG6FYGKZQEX","RZOJO3KHGWQOOEZ"],["GVP08TWET2","EYZD7CLCFEVTHTQLL"],["MUAAVT3ED8","H4UNQTWPMBSWF7O"],["MRX0MJN6G3","YTQVSOVXQVBLWJVTOJIUYDZYPZYJHHQFURSALYCCVXPAERXQBSWHBLRCSCTSTBOCYFNULMMRWNEBGGRUBPSPSOTBOMGPHIJLMVJUBBBTNEWGDIM"],["K115K8RI0U","R36LRZ896DUUM4V414"],["1PHS8W3DNG0MHRORL","Q3CC6OGKA24WBHE4HR4J"],["04QZ97ZY3HEU3F6090","T434TQNA2NZF3V96"],["GXP2FWQALEWS","F4J0INFWBRXFAXO1NXUN"],["V3J0FC5V4CCWV1","3T701TI4ZO1YQ0V0DJ8MEK"]]
{
"name": "aft-core",
"version": "8.4.2",
"version": "9.0.0",
"description": "Automation Framework for Testing (AFT) package supporting JavaScript unit, integration and functional testing",

@@ -13,5 +13,5 @@ "repository": {

"clean": "rimraf ./dist && rimraf ./.nyc_output && rimraf ./coverage",
"build": "yarn clean && tsc --build",
"build": "npm run clean && tsc --build",
"test": "jasmine-ts ./test/**/*-spec.ts",
"coverage": "nyc yarn test"
"coverage": "nyc npm run test"
},

@@ -50,3 +50,3 @@ "keywords": [

},
"gitHead": "3e979bba2871af6092a3edb91b24b94446311acf"
"gitHead": "3f91ae334e55378b543cfb0a24a28b224c25e2a9"
}

@@ -56,3 +56,4 @@ # AFT-Core

- **fileio** - a constant class providing file system `write`, `readAs<T>` and `getExpiringFileLock` functions to simplify file operations
- **wait** - constant class providing `wait.untilTrue(...)` and `wait.forDuration(number)` functions to allow for non-thread-locking waits
- **wait** - constant class providing `wait.forResult<T>(...): Promise<T>`, `wait.forDuration(number)`, and `wait.until(number | Date): Promise<void>` functions to allow for non-thread-locking waits
- **retry** - constant class providing `retry(retryable): Promise<T>` async function
- **verifier** - see: [Testing with the Verifier](#testing-with-the-verifier) section below

@@ -59,0 +60,0 @@

import { JsonObject } from "./custom-types";
/**
* type containing an `exclude` field having either a `string` or `RegExp`
* used to identify characters or strings to be excluded and a `replaceWith`
* field containing a `string` to use as a replacement for each excluded value
*
* Ex:
* ```
* const opts = [{exclude: /[\s]+/g, replaceWith: '_'}];
* convert.toSafeString('I am an example', opts); // returns 'I_am_an_example'
* ```
*/
export type SafeStringOption = {

@@ -8,3 +19,13 @@ exclude: string | RegExp;

/**
* module providing a default set of string replacement values via the
* `SafeStringOptions.defaults` const
*/
export module SafeStringOption {
/**
* a default set of characters to exclude and their replacement values that prevents
* any curly or square brackets, forward or backslashes, commas, dashes, fullstops,
* empty spaces and special characters where special characters are replaced with empty
* string and the rest with underscore
*/
export const defaults: SafeStringOption[] = [

@@ -36,8 +57,15 @@ {exclude: /[\/\\\{\}\(\)\,\.\-]/g, replaceWith: '_'},

* function will return the number of milliseconds elapsed since the
* passed in timestamp
* @param startTime the value from calling 'new Date().getTime()' at the
* passed in `startTime`
*
* Ex:
* ```
* const start = Date.now();
* // perform some actions...
* convert.toElapsedMs(start); // returns Date.now() - start
* ```
* @param startTime the value from calling 'Date.now()' at the
* point in time when some event has started.
*/
toElapsedMs(startTime: number): number {
return new Date().getTime() - startTime;
return Date.now() - startTime;
}

@@ -48,2 +76,7 @@

* the value of the passed in 'replaceWith' string
*
* Ex:
* ```
* convert.toSafeString('I am an Example!'); // returns 'I_am_an_Example'
* ```
* @param input the original string to process

@@ -66,2 +99,8 @@ * @param options an array of {exclude: string | RegExp, replaceWith: string} objects to

* converts the passed in `Map` to a JSON string
*
* Ex:
* ```
* const m = new Map<number, string>([[2, "foo"],[5, "bar"]]);
* convert.mapToString(m); // returns '[[2, "foo"],[5, "bar"]]'
* ```
* @param mapObj the `Map` to be converted to a string

@@ -76,2 +115,7 @@ * @returns a JSON string of the format `[["key", "val"],["key", "val"]]`

* converts the passed in string to a valid `Map` object
*
* Ex:
* ```
* convert.stringToMap('[[2, "foo"],[5, "bar"]]'); // returns new Map<number, string>([[2, "foo"],[5, "bar"]])
* ```
* @param mapStr a JSON string representation of a `Map` as an array

@@ -89,2 +133,11 @@ * containing arrays of key-value pairs like `[["key", "val"],["key", "val"]]`

* to a simple JSON object
*
* Ex:
* ```
* const foo = {
* bar: () => 'bar',
* baz: 'baz'
* };
* convert.toJsonObject(foo); // returns {'baz': 'baz'}
* ```
* @param obj an input object to be converted

@@ -119,4 +172,34 @@ * @returns a valid `JsonObject` typed object

}
/**
* converts the passed in seconds to milliseconds
* @param seconds the number of seconds
* @returns the number of milliseconds in the passed
* in `seconds`
*/
secToMillisec(seconds: number): number {
return seconds * 1000;
}
/**
* converts the passed in minutes to milliseconds
* @param minutes the number of minutes
* @returns the number of milliseconds in the passed in
* `minutes`
*/
minToMillisec(minutes: number): number {
return this.secToMillisec(minutes * 60);
}
}
/**
* constant helper class for converting values to other values
* such as:
* ```
* convert.toBase64Encoded('foo'); // returns 'Zm9v'
* convert.fromBase64Encoded('Zm9v'); // returns 'foo'
* convert.toSafeString('I am an Example!'); // returns 'I_am_an_Example'
* convert.toHoursMinutesSeconds(3666600); // returns '01:01:06.600'
* ```
*/
export const convert = new Convert();

@@ -98,2 +98,9 @@ /**

*/
export type Merge<T1, T2, T3 = {}, T4 = {}, T5 = {}, T6 = {}> = T1 & T2 & T3 & T4 & T5 & T6;
export type Merge<T1, T2, T3 = {}, T4 = {}, T5 = {}, T6 = {}> = T1 & T2 & T3 & T4 & T5 & T6;
/**
* a retry back-off delay type where `constant` uses the same
* delay each time, `linear` adds the start delay to the previous
* on each iteration and `exponential` doubles the previous delay
*/
export type RetryBackOffType = 'constant' | 'linear' | 'exponential';

@@ -0,1 +1,2 @@

import { LogLevel } from '../plugins/logging/log-level';
import { LogManager } from '../plugins/logging/log-manager';

@@ -6,2 +7,22 @@ import { convert } from './convert';

export type ErrVerbosity = 'full' | 'short';
export type ErrOptions = {
/**
* an optional `LogManager` instance to use in logging the error message
* and stack
*/
logMgr?: LogManager;
/**
* the `LogLevel` to use when logging any caught `Error`. defaults to
* `warn`
*/
errLevel?: LogLevel;
/**
* the amount of detail to include in the output message. defaults to
* `full`
*/
verbosity?: ErrVerbosity;
}
/**

@@ -12,7 +33,11 @@ * provides a standardised way of generating log-friendly exception details

* const logMgr = new LogManager({logName: 'foo'});
* Err.handle(() => functionThatThrowsTypeError(), logMgr);
* const result = await Err.handle(functionThatThrowsTypeError, {
* logMgr: logMgr,
* errLevel: 'debug',
* verbosity: 'short'
* });
* ```
* which would output:
* ```text
* YYYYMMDD - [foo] - WARN - TypeError: [100 characters of description] --- [300 characters of the stack trace]
* YYYYMMDD - [foo] - DEBUG - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace]
* ```

@@ -26,3 +51,3 @@ * and:

* await logMgr.warn(Err.short(e));
* await logMgr.warn(Err.full(e));
* await logMgr.debug(Err.full(e));
* }

@@ -32,4 +57,5 @@ * ```

* ```text
* YYYYMMDD - [AFT] - WARN - TypeError: [100 characters of description] --- [300 characters of the stack trace]
* YYYYMMDD - [AFT] - WARN - TypeError: [full type error description message] --- [full stack trace of as much as the Error contained]
* YYYYMMDD - [AFT] - WARN - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace]
* YYYYMMDD - [AFT] - DEBUG - TypeError: [full type error description message]
* [full stack trace of as much as the Error contained]
* ```

@@ -39,30 +65,48 @@ */

readonly err: Error;
private _verbosity: ErrVerbosity;
private readonly _type: string;
private readonly _message: string;
private readonly _stack: string;
constructor(error: any) {
if (this._isError(error)) {
this.err = error;
} else {
this.err = new Error(String(error || 'unknown'));
}
}
constructor(err: any) {
if (err) {
if (!this._isError(err)) {
this.err = new Error(String(err));
} else {
this.err = err;
}
if (this.err) {
this._type = this.err.name || 'Error';
this._message = this._removeBadCharacters(this.err.message);
this._stack = this._removeBadCharacters(this._removeInternalStackLines(this.err.stack));
}
get verbosity(): ErrVerbosity {
if (!this._verbosity) {
this._verbosity = 'full';
}
return this._verbosity;
}
short(): string {
return this._formatOutput(false);
setVerbosity(v: ErrVerbosity): this {
this._verbosity = (['full', 'short'].includes(v)) ? v : 'full';
return this;
}
full(): string {
return this._formatOutput(true);
get type(): string {
return this.err?.name || 'Error';
}
get message(): string {
return this.err?.message || 'unknown';
}
get stack(): string {
return this.err?.stack || 'unknown';
}
toString(): string {
const message = this._processMessage(this.message);
const stack = this._processStack(this.stack);
let output: string;
if (this.verbosity === 'short') {
output = `${this.type}: ${message} --- ${stack}`;
} else {
output = `${this.type}: ${message}\n${stack}`;
}
return output;
}
private _isError(obj: any): boolean {

@@ -72,6 +116,27 @@ return obj?.name && obj?.message && obj?.stack;

private _processMessage(message: string): string {
let msg = message;
if (this.verbosity === 'short') {
msg = ellide(msg, 100);
msg = this._removeNewlinesAndExtraWhitespace(msg);
}
return msg;
}
private _processStack(stack: string): string {
let stk = this._removeInternalStackLines(stack);
if (this.verbosity === 'short') {
const stackLines = stk.split('\n');
if (stackLines.length > 0) {
stk = ellide(stackLines[0], 300, 'middle');
}
stk = this._removeNewlinesAndExtraWhitespace(stk);
}
return stk;
}
private _removeInternalStackLines(stack: string): string {
const resultStackLines = new Array<string>();
const stackLines: Array<string> = stack.split('\n');
for (var i=0; i<stackLines.length; i++) {
const stackLines: Array<string> = stack?.split('\n') || [];
for (var i=1; i<stackLines.length; i++) {
let line = stackLines[i];

@@ -82,18 +147,12 @@ if (line.match(/.*(err).(ts|js)/gi) == null) {

}
return resultStackLines.join('\n').replace(`${this._type}: ${this._message}`, '');
return resultStackLines.join('\n').replace(`${this.type}: ${this.message}`, '');
}
private _removeBadCharacters(input: string): string {
private _removeNewlinesAndExtraWhitespace(input: string): string {
return (input) ? convert.toSafeString(input, [
{exclude: /\`/g, replaceWith: ''},
{exclude: /[\n\t]/g, replaceWith: ''},
{exclude: /[\n\r]/g, replaceWith: ''},
{exclude: /[\t]/g, replaceWith: ' '},
{exclude: /[ ]{2,}/g, replaceWith: ' '}
]) : '';
}
private _formatOutput(full: boolean): string {
let msg = (full) ? this._message : ellide(this._message, 100);
let stk = (full) ? this._stack : ellide(this._stack, 300);
return `${this._type}: ${msg} --- ${stk}`;
}
}

@@ -105,6 +164,8 @@

* @returns a shortened string formatted as `Error.name: Error.message (max 100 chars) --- Error.stack (max 300 chars)`
* where any single quotes, newlines and extra spaces are removed
* where any newlines, tabs and extra spaces are removed
*/
export function short(err: any): string {
return new Err(err).short();
return new Err(err)
.setVerbosity('short')
.toString();
}

@@ -114,7 +175,13 @@

* @param err the `Error` to parse
* @returns a full length string formatted as `Error.name: Error.message --- Error.stack`
* where any single quotes, newlines and extra spaces are removed
* @returns a full length string formatted as
* ```
* Error.name: Error.message
* Error.stack
* ```
* where the full Error details are preserved
*/
export function full(err: any): string {
return new Err(err).full();
return new Err(err)
.setVerbosity('full')
.toString();
}

@@ -125,13 +192,31 @@

* @param func a function to be run inside a try-catch
* @param logMgr an optional `LogManager` that will log any error
* @param optsOrLogMgr an `ErrOptions` object containing options for this handler or a
* `LogManager` used to log any captured `Error` _(defaults to `undefined`)_
* > **WARNING** passing a `LogManager` is deprecated and you should instead add the
* `LogManager` using the `logMgr` field in the `ErrOptions` instance)
* @returns the result of the passed in `func` or `null` if an error is thrown
*/
export async function handle<T extends any>(func: Func<void, T | PromiseLike<T>>, logMgr?: LogManager): Promise<T> {
export async function handle<T extends any>(func: Func<void, T | PromiseLike<T>>, optsOrLogMgr?: LogManager | ErrOptions): Promise<T> {
let opts: ErrOptions;
if (_isLogManager(optsOrLogMgr)) { // TODO: remove this in next major release
opts = {logMgr: optsOrLogMgr} as ErrOptions;
await opts.logMgr?.warn(`passing a 'LogManager' is DEPRECATED! pass a 'ErrOptions' object containing your 'LogManager' instead`);
} else {
opts = optsOrLogMgr as ErrOptions || {};
}
return await Promise.resolve()
.then(func)
.catch(async (err) => {
await logMgr?.warn(Err.short(err));
return null;
});
.then(func)
.catch(async (err) => {
const e = new Err(err).setVerbosity(opts?.verbosity);
await opts?.logMgr?.[opts?.errLevel || 'warn'](e.toString());
return null;
});
}
function _isLogManager(obj: any): boolean {
if (obj?.logName && obj?.trace && obj?.debug && obj?.info) {
return true;
}
return false;
}
}

@@ -15,2 +15,16 @@ import * as fs from "fs";

* throwing an exception
*
* Ex:
* ```
* const maxWait = 10000; // 10 seconds
* const maxHold = 5000; // 5 seconds
* // wait a maximum of 10 seconds to aquire lock and then hold
* // lock for maximum of 5 seconds or until `unlock` is called
* const lock = new ExpiringFileLock('unique_name', maxWait, maxHold);
* try {
* // perform action on shared resource...
* } finally {
* lock?.unlock();
* }
* ```
*/

@@ -17,0 +31,0 @@ export class ExpiringFileLock {

@@ -94,3 +94,3 @@ import * as path from "path";

private _writeToFile(): void {
let lock: ExpiringFileLock = fileio.getExpiringFileLock(this.filename, 10000, 5000);
const lock: ExpiringFileLock = fileio.getExpiringFileLock(this.filename, 10000, 5000);
try {

@@ -105,3 +105,3 @@ fileio.write(this.filename, convert.mapToString(this._memoryMap));

let fileMapData: Map<Tkey, Tval>;
let lock: ExpiringFileLock = fileio.getExpiringFileLock(this.filename, 10000, 5000);
const lock: ExpiringFileLock = fileio.getExpiringFileLock(this.filename, 10000, 5000);
try {

@@ -108,0 +108,0 @@ fileMapData = fileio.readAs<Map<Tkey, Tval>>(this.filename, convert.stringToMap);

@@ -26,3 +26,3 @@ import { Func } from "./custom-types";

}) // and then dispose with any Error
.finally(() => disposable.dispose(err));
.finally(() => disposable?.dispose(err));
}

@@ -28,4 +28,10 @@ export interface VerifierMatcher {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(equaling(5)); // succeeds
* await verifier(() => undefined).returns(equaling(null)); // succeeds
* await verifier(() => true).returns(equaling(false)); // fails
* ```
* @param expected the expected value
* @returns a new {Equaling} instance
* @returns a new `Equaling` instance
*/

@@ -56,4 +62,10 @@ export const equaling = (expected: any): Equaling => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(exactly(5)); // succeeds
* await verifier(() => undefined).returns(exactly(null)); // fails
* await verifier(() => true).returns(exactly(false)); // fails
* ```
* @param expected the expected value
* @returns a new {Exactly} instance
* @returns a new `Exactly` instance
*/

@@ -92,5 +104,14 @@ export const exactly = (expected: any): Exactly => {

* between the `minimum`, `maximum` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(between(5, 6)); // succeeds
* await verifier(() => 5).returns(between(4, 5)); // succeeds
* await verifier(() => 5).returns(between(-5, 10)); // succeeds
* await verifier(() => 5).returns(between(0, 4)); // fails
* await verifier(() => 5).returns(between(6, 10)); // fails
* await verifier(() => null).returns(between(6, 10)); // fails
* ```
* @param minimum the minimum value the `actual` result can be
* @param maximum the maximum value the `actual` result can be
* @returns a new {NumberBetween} instance
* @returns a new `NumberBetween` instance
*/

@@ -140,4 +161,13 @@ export const between = (minimum: number, maximum: number): NumberBetween => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 'foobarbaz').returns(containing('bar')); // succeeds
* await verifier(() => [1, 2, 3, 4, 5, 6]).returns(containing(5)); // succeeds
* await verifier(() => new Set([1, 2, 3, 4, 5, 6]).returns(containing(5)); // succeeds
* await verifier(() => new Map([[5, 'five'], [6, 'six']])).returns(containing(5)); // succeeds
* await verifier(() => 'foo').returns(containing('oof')); // fails
* await verifier(() => new Map([[5, 'five'], [6, 'six']])).returns(containing('five')); // fails
* ```
* @param expected the expected value
* @returns a new {ValueContaining} instance
* @returns a new `ValueContaining` instance
*/

@@ -165,3 +195,11 @@ export const containing = (expected: any): ValueContaining => {

* between the where `a` is the `actual` result
* @returns a new {HavingValue} instance
* like:
* ```
* await verifier(() => 'foobarbaz').returns(havingValue()); // succeeds
* await verifier(() => false).returns(havingValue()); // succeeds
* await verifier(() => 0).returns(havingValue()); // succeeds
* await verifier(() => null).returns(havingValue()); // fails
* await verifier(() => undefined).returns(havingValue()); // fails
* ```
* @returns a new `HavingValue` instance
*/

@@ -192,4 +230,11 @@ export const havingValue = (): HavingValue => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(greaterThan(0)); // succeeds
* await verifier(() => 5).returns(greaterThan(4.999)); // succeeds
* await verifier(() => 5).returns(greaterThan(5)); // fails
* await verifier(() => null).returns(greaterThan(0)); // fails
* ```
* @param expected the expected value
* @returns a new {GreaterThan} instance
* @returns a new `GreaterThan` instance
*/

@@ -220,4 +265,11 @@ export const greaterThan = (expected: number): GreaterThan => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(lessThan(10)); // succeeds
* await verifier(() => 5).returns(lessThan(5.0001)); // succeeds
* await verifier(() => 5).returns(lessThan(5)); // fails
* await verifier(() => null).returns(lessThan(10)); // fails
* ```
* @param expected the expected value
* @returns a new {LessThan} instance
* @returns a new `LessThan` instance
*/

@@ -247,4 +299,11 @@ export const lessThan = (expected: number): LessThan => {

* between the `expected` and `actual` result
* like:
* ```
* await verifier(() => 5).returns(not(equaling(10))); // succeeds
* await verifier(() => null).returns(not(exactly(undefined))); // succeeds
* await verifier(() => [1, 2, 3]).returns(not(containing(5))); // succeeds
* await verifier(() => null).returns(not(havingValue())); // succeeds
* ```
* @param expected a {VerifierMatcher} to negate
* @returns a new {Negate} instance
* @returns a new `Negate` instance
*/

@@ -251,0 +310,0 @@ export const not = (expected: VerifierMatcher): Negate => {

@@ -13,2 +13,21 @@ import { buildinfo, BuildInfoManager } from "../plugins/build-info/build-info-manager";

/**
* class to be used for executing some Functional Test Assertion after checking with any
* `TestCasePlugin` and `DefectPlugin` instances that have been loaded to confirm that the
* assertion should be executed based on referenced Test ID(s) or Defect ID(s)
*
* Ex:
* ```
* await verify(async (v: Verifier) => {
* await v.logMgr.info('doing some testing...');
* let feature = new FeatureObj();
* return await feature.returnExpectedValue();
* }).withDescription('example usage for Verifier')
* .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run
* .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run
* .returns('expected value');
* ```
* @param assertion the `Func<Verifier, any>` function to be executed by this `Verifier`
* @returns a new `Verifier` instance
*/
export class Verifier implements PromiseLike<void> {

@@ -34,5 +53,6 @@ protected _assertion: Func<Verifier, any>;

/**
* a `LogManager` that uses either the `withDescription`
* or a list of `withTestId` or a uuid as the `logName` depending
* on which is available and where `description` is preferred most
* a `LogManager` that uses either the Description
* or a list of Test Ids or a `uuid` as the `logName` depending
* on which is available (NOTE: description is preferred most and
* will be used if other values are also present)
*/

@@ -156,6 +176,6 @@ get logMgr(): LogManager {

* your test case management system. if all the referenced `testId` values should not be
* run (as returned by your {AbstractTestCasePlugin.shouldRun(testId)}) then
* run (as returned by your `AbstractTestCasePlugin.shouldRun(testId)`) then
* the `assertion` will not be run.
* NOTE: multiple `testId` values can be chained together
* @param testIds a test identifier for your connected {AbstractTestCasePlugin}
* @param testIds a test identifier for your connected `AbstractTestCasePlugin`
* @returns this `Verifier` instance

@@ -216,5 +236,5 @@ */

/**
* allows for using a specific {TestCaseManager} instance. if not
* set then the global {TestCaseManager.instance()} will be used
* @param testMgr a {TestCaseManager} instance
* allows for using a specific `TestCaseManager` instance. if not
* set then the global `TestCaseManager.instance()` will be used
* @param testMgr a `TestCaseManager` instance
* @returns this `Verifier` instance

@@ -228,5 +248,5 @@ */

/**
* allows for using a specific {DefectManager} instance. if not
* set then the global {DefectManager.instance()} will be used
* @param defectMgr a {DefectManager} instance
* allows for using a specific `DefectManager` instance. if not
* set then the global `DefectManager.instance()` will be used
* @param defectMgr a `DefectManager` instance
* @returns this `Verifier` instance

@@ -240,5 +260,5 @@ */

/**
* allows for using a specific {BuildInfoManager} instance. if not
* set then the global {BuildInfoManager.instance()} will be used
* @param buildMgr a {BuildInfoManager} instance
* allows for using a specific `BuildInfoManager` instance. if not
* set then the global `BuildInfoManager.instance()` will be used
* @param buildMgr a `BuildInfoManager` instance
* @returns this `Verifier` instance

@@ -300,6 +320,4 @@ */

/**
* creates `ITestResult` objects for each `testId` and sends these
* creates `TestResult` objects for each `testId` and sends these
* to the `LogManager.logResult` function
* @param result an `IProcessingResult` returned from executing the
* expectation
*/

@@ -389,3 +407,4 @@ protected async _logResult(status: TestStatus, message?: string): Promise<void> {

* Test Assertion.
* ex:
*
* Ex:
* ```

@@ -397,6 +416,7 @@ * await verify(async (v: Verifier) => {

* }).withDescription('example usage for Verifier')
* .and.withTestId('C1234')
* .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run
* .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run
* .returns('expected value');
* ```
* @param assertion the {Func<Verifier, any>} function to be executed by this `Verifier`
* @param assertion the `Func<Verifier, any>` function to be executed by this `Verifier`
* @returns a new `Verifier` instance

@@ -403,0 +423,0 @@ */

@@ -1,3 +0,1 @@

import { Err } from "./err";
import { convert } from "./convert";
import { Func } from "./custom-types";

@@ -7,50 +5,42 @@

/**
* function will execute an asynchronous action and await a result repeating execution every 1 millisecond until a
* result of 'true' is returned or the 'msDuration' specified has elapsed. If the action never returns 'true' and
* the 'msDuration' elapses, an Error will be thrown by way of a Promise.reject
* @param condition an asynchronous action that should be executed until it returns 'true' or the 'msDuration' has expired
* @param msDuration the maximum amount of time to wait for the 'condition' to return 'true'
* @param onFailAction an action to perform on each attempt resulting in failure ('Error' or 'false') of the 'condition'
* function will wait for the specified amount of time
* @param durationMs the amount of time to wait before resuming
*/
async untilTrue(condition: Func<void, boolean | PromiseLike<boolean>>, msDuration: number, onFailAction?: Func<void, any>) : Promise<void> {
let result: boolean = false;
let attempts: number = 0;
const startTime: number = new Date().getTime();
let err: Error;
async forDuration(durationMs: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, durationMs);
});
}
do {
attempts++;
result = await Promise.resolve()
.then(condition)
.catch((e) => {
err = e;
return false;
});
if (!result) {
if (onFailAction) {
await Promise.resolve()
.then(onFailAction)
.catch((err) => {
/* ignore */
});
}
}
await this.forDuration(1);
} while (result !== true && convert.toElapsedMs(startTime) < msDuration);
if (result) {
return Promise.resolve();
}
return Promise.reject(`wait.untilTrue(...) exceeded [${convert.toHoursMinutesSeconds(msDuration)}] over '${attempts}' attempts without returning 'true'${(err) ? ` due to: ${Err.short(err)}` : ''}`);
/**
* waits up to the specified `maxDurationMs` for a result from the passed in `func`
* @param func a synchronous or async function returning a result of type `T`
* @param maxDurationMs the maximum amount of time to wait (defaults to 30 seconds)
* @returns the result of the passed in `func` or `undefined` if the `maxDurationMs` elapses before `func`
* returns a result
*/
async forResult<T>(func: Func<void, T | PromiseLike<T>>, maxDurationMs: number = 30000): Promise<T> {
return await Promise.race([
Promise.resolve().then(func).catch((err) => Promise.reject(err)),
new Promise<T>((resolve) => setTimeout(resolve, maxDurationMs, undefined))
]);
}
/**
* function will wait for the specified amount of time
* @param msDuration the amount of time to wait before resuming
* will wait until the specified time
* @param time either the time in milliseconds past the epoch or a `Date` object
* representing the desired time to wait until
*/
async forDuration(msDuration: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, msDuration);
async until(time: number | Date): Promise<void> {
let t: number;
if (typeof time === "number") {
t = time;
} else {
t = time.getTime();
}
return new Promise(async (resolve) => {
while (Date.now() < t) {
await wait.forDuration(1);
}
resolve();
});

@@ -57,0 +47,0 @@ }

@@ -23,2 +23,3 @@ /** configuration */

export * from './helpers/rand';
export * from './helpers/retry';
export * from './helpers/using';

@@ -25,0 +26,0 @@ export * from './helpers/verifier';

@@ -0,1 +1,5 @@

/**
* type representing if a Defect is still open or if it has
* been resolved (closed)
*/
export type DefectStatus = 'open' | 'closed';

@@ -31,3 +31,3 @@ import { cloneDeep } from "lodash";

* "plugins": [
* "logging-plugin1",
* {"name": "logging-plugin1", "enabled": true, "searchDirectory": "./dist/", "options": {"foo": "bar"}},
* {"name": "logging-plugin2", "enabled": false, "options": {"foo": "bar"}}

@@ -34,0 +34,0 @@ * ]

@@ -24,3 +24,3 @@ import * as fs from 'fs';

* ```typescript
* let plugins: CustomPlugin[] = pluginloader.load<CustomPlugin>([{
* const plugins: CustomPlugin[] = pluginloader.load<CustomPlugin>([{
* name: 'custom-plugin',

@@ -173,17 +173,24 @@ * searchDirectory: '../../plugins',

* responsible for finding and loading plugins based on a passed in
* {pluginName} and optional {options}. any plugin loaded by this
* class must extend from {AbstractPlugin<any>} and would be expected
* to accept an {options} object in its constructor.
* `PluginConfig`. any plugin loaded by this class must extend from
* `Plugin<T extends PluginOptions>` and would be expected to accept an object extending
* `PluginOptions` object in its constructor.
*
* ```typescript
* let plugin: CustomPlugin = await pluginloader.load<CustomPlugin>('custom-plugin', {foo: 'bar'});
* const plugins: CustomPlugin[] = pluginloader.load<CustomPlugin>([{
* name: 'custom-plugin',
* searchDirectory: '../../plugins',
* enabled: false,
* options: {
* storagePath: './'
* }
* }, 'custom-plugin-2']);
* ```
* NOTE: the above will attempt to load `custom-plugin` package
* passing in the specified options to its constructor. if loading
*
* **NOTE:** the above attempts to load a `custom-plugin` class. if loading
* fails then it will search the filesystem, starting at the current
* execution directory and searching all subdirectories, for a file
* named `custom-plugin.js` which, if found, will be imported and a
* new instance will be created passing in the specified options to
* its constructor. following instantiation the {onLoad} function is
* awaited and then the new plugin instance is returned
* new instance will be created and added to the internal cache and the
* array to be returned
*/
export const pluginloader = new PluginLoader();

@@ -44,5 +44,4 @@ import { Plugin } from "./plugin";

* "plugins": [
* {name: "some-custom-plugin", enabled: false, searchDirectory: "/full/path/to/search"},
* "some-other-plugin",
* {name: "a-third-plugin", searchDirectory: "../../relative-path-to-search", options: {"foo": "option used by plugin instance"}}
* {"name": "some-custom-plugin", "enabled": false, "searchDirectory": "/full/path/to/search"},
* {"name": "a-second-plugin", "searchDirectory": "../../relative-path-to-search", "options": {"foo": "option used by plugin instance"}}
* ],

@@ -49,0 +48,0 @@ * "bar": "configurataion used by PluginManagerInstance"

@@ -9,3 +9,3 @@ import { LogManager } from "../logging/log-manager";

/**
* loads and provides an interface between any `ITestCasePlugin`
* loads and provides access to a `TestCasePlugin` for use in conditional test execution and filtering.
* to specify a plugin use the following `aftconfig.json` key:

@@ -15,4 +15,6 @@ * ```

* ...
* "testcasemanager": {
* "pluginNames": ["plugin-name"]
* "TestCaseManager": {
* "plugins": [
* {"name": "test-case-plugin", "options": {"username": "foo@bar.com", "accesskey": "SuperSecretKey"}}
* ]
* }

@@ -19,0 +21,0 @@ * ...

@@ -33,2 +33,27 @@ import { convert, rand } from "../../src";

});
describe('secToMillisec', () => {
const testData = [0.5, 1, 10, 60];
for(var i=0; i<testData.length; i++) {
const data = testData[i];
it(`can calculate the milliseconds in '${data}' seconds`, () => {
expect(convert.secToMillisec(data)).toEqual(data * 1000);
});
}
});
describe('minToMillisec', () => {
const testData: Array<{min: number, exp: number}> = [
{min: 0.5, exp: 30000},
{min: 1, exp: 60000},
{min: 2, exp: 120000},
{min: 60, exp: 3600000}
];
for(var i=0; i<testData.length; i++) {
const data = testData[i];
it(`can convert minutes to milliseconds for ${JSON.stringify(data)}`, () => {
expect(convert.minToMillisec(data.min)).toEqual(data.exp);
});
}
});
});

@@ -1,2 +0,2 @@

import { rand, Err, LogManager } from "../../src";
import { rand, Err, LogManager, LogLevel } from "../../src";

@@ -11,61 +11,105 @@ describe('Err', () => {

expect(actual.err.message).toEqual(err.message);
expect(actual.verbosity).toEqual('full');
});
it('can generate a shortened string', () => {
const err: Error = new Error(rand.getString(1000, true, true, true, true));
const actual: string = Err.short(err);
it('verbosity can be set', () => {
const err: Error = new Error(rand.getString(25));
expect(actual.length).toBeLessThan(450);
const actual = new Err(err).setVerbosity('short');
expect(actual.err).toBeDefined();
expect(actual.err.message).toEqual(err.message);
expect(actual.verbosity).toEqual('short');
});
it('can generate a full Error string', () => {
const err: Error = new Error(rand.getString(500, true, true, true, true));
describe('short', () => {
it('can generate a shortened string', () => {
const err: Error = new Error(rand.getString(1000, true, true, true, true));
const actual: string = Err.full(err);
const actual: string = Err.short(err);
expect(actual.length).toBeGreaterThan(500);
expect(actual.length).toBeLessThan(450);
});
it('can handle null argument to contstuctor', () => {
const actual: string = Err.short(null);
expect(actual).toMatch(/^(Error: unknown --- )[ \w\d]+/gi);
});
});
it('can handle null argument to contstuctor', () => {
const actual: string = Err.full(null);
describe('full', () => {
it('can generate a full Error string', () => {
const err: Error = new Error(rand.getString(500, true, true, true, true));
expect(actual).toEqual('undefined: undefined --- undefined');
});
const actual: string = Err.full(err);
it('can handle try-catch for a Func<void, any> that does not throw', async () => {
const func = function () { return 'foo'; };
const val = await Err.handle(func);
expect(actual.length).toBeGreaterThan(500);
});
expect(val).toEqual('foo');
it('can handle null argument to contstuctor', () => {
const actual: string = Err.full(null);
expect(actual).toMatch(/^(Error: unknown\n)[\s\w\d]+/gi);
});
});
it('can handle try-catch for a Func<void, any> that throws', async () => {
const func = function () { throw 'foo'; };
const val = await Err.handle(func);
describe('handle', () => {
it('can handle try-catch for a Func<void, any> that does not throw', async () => {
const func = function () { return 'foo'; };
const val = await Err.handle(func);
expect(val).toBeNull();
});
expect(val).toEqual('foo');
});
it('can handle try-catch for a Func<void, any> that rejects a Promise', async () => {
const func = () => Promise.reject('foo');
const val = await Err.handle(func);
it('can handle try-catch for a Func<void, any> that throws', async () => {
const func = function () { throw 'foo'; };
const val = await Err.handle(func);
expect(val).toBeNull();
});
expect(val).toBeNull();
});
it('will log a warning if a LogManager is supplied and the Func throws', async () => {
const logMgr = new LogManager({logName: 'will log a warning if a LogManager is supplied and the Func throws', plugins: []});
let logMessage: string;
spyOn(logMgr, 'warn').and.callFake((message: string) => {
logMessage = message;
return Promise.resolve();
it('can handle try-catch for a Func<void, any> that rejects a Promise', async () => {
const func = () => Promise.reject('foo');
const val = await Err.handle(func);
expect(val).toBeNull();
});
const func = function () { throw 'foo'; };
const val = await Err.handle(func, logMgr);
expect(val).toBeNull();
expect(logMgr.warn).toHaveBeenCalledTimes(1);
expect(logMessage).toContain('Error: foo ');
it('will log a warning if a LogManager is supplied and the Func throws', async () => {
const logMgr = new LogManager({logName: 'will log a warning if a LogManager is supplied and the Func throws', plugins: []});
let logMessage: string;
spyOn(logMgr, 'warn').and.callFake((message: string) => {
logMessage = message;
return Promise.resolve();
});
const func = function () { throw 'foo'; };
const val = await Err.handle(func, logMgr);
expect(val).toBeNull();
expect(logMgr.warn).toHaveBeenCalledTimes(2); // 1 time for logging and 1 time to output deprecation warning for passing LogMgr instead of ErrOptions
expect(logMessage).toContain('Error: foo');
});
it('accepts ErrOptions as a second argument', async () => {
const func = function () { throw 'foo'; };
const logger = new LogManager({logName: 'accepts ErrOptions as a second argument'});
let actualLevel: LogLevel;
let actualMessage: string;
spyOn(logger, 'log').and.callFake((level: LogLevel, message: string) => {
actualLevel = level;
actualMessage = message;
return Promise.resolve();
});
const val = await Err.handle(func, {
verbosity: 'short',
errLevel: 'info',
logMgr: logger
});
expect(val).toBeNull();
expect(actualLevel).toEqual('info');
expect(actualMessage).not.toContain('\n');
});
});
});

@@ -5,77 +5,49 @@ import { convert } from "../../src/helpers/convert";

describe('Wait', () => {
beforeEach(() => {
TestHelper.reset();
});
it('can wait for a less than the maximum duration if action returns true', async () => {
let now: number = new Date().getTime();
it('can wait for a less than the maximum duration', async () => {
let start: number = new Date().getTime();
await wait.untilTrue(async () => {
// wait 1 ms and return false 2 times, then true
await new Promise<void>((resolve) => {
setTimeout(resolve, 1);
});
TestHelper.count += 1;
return TestHelper.count > 2;
}, 2000);
const result: number = await wait.forResult(() => 12, 500);
let elapsed: number = convert.toElapsedMs(now);
expect(elapsed).toBeGreaterThan(3);
expect(elapsed).toBeLessThan(2000);
expect(TestHelper.count).toEqual(3);
let elapsed: number = convert.toElapsedMs(start);
expect(result).toEqual(12);
expect(elapsed).toBeLessThan(500);
});
it('will emit a rejected promise if duration is exceeded without returning true', async () => {
const now: number = new Date().getTime();
let actualErr: any;
await wait.untilTrue(async () => {
TestHelper.count += 1;
return false;
}, 200).catch((err) => {
actualErr = err;
});
it('will return null on timeout', async () => {
const start: number = new Date().getTime();
const result: number = await wait.forResult(() => {
return new Promise((resolve) => {
// called after `wait` duration times out
setTimeout(() => resolve(12), 2000);
});
}, 500);
const elapsed: number = convert.toElapsedMs(now);
expect(elapsed).toBeGreaterThanOrEqual(200);
const elapsed: number = convert.toElapsedMs(start);
expect(result).toBeUndefined();
expect(elapsed).toBeLessThan(1000);
expect(TestHelper.count).toBeGreaterThan(10);
expect(actualErr).toEqual(`wait.untilTrue(...) exceeded [${convert.toHoursMinutesSeconds(200)}] over '${TestHelper.count}' attempts without returning 'true'`);
});
it('can execute a failure action on each failed attempt', async () => {
let actual: number = 0;
await wait.untilTrue(() => {throw new Error('fake error');}, 200, async () => {
actual++;
await wait.forDuration(50);
}).catch((err) => {/* do nothing */});
expect(actual).toBeGreaterThan(1);
});
it('can handle a rejected promise in the passed in func', async () => {
it('allows exceptions in func through', async () => {
let actualErr: any;
await wait.untilTrue(() => Promise.reject('fake error'), 200)
.catch((err) => actualErr = err);
const result: number = await wait.forResult(() => {throw 'fake error';}, 200)
.catch((err) => {
actualErr = err;
return -1;
});
expect(result).toEqual(-1);
expect(actualErr).toContain('fake error');
});
it('can handle exceptions in the failure action on each failed attempt', async () => {
let actual: number = 0;
await wait.untilTrue(() => {throw new Error('fake error');}, 200, async () => {
actual++;
await wait.forDuration(50);
throw new Error('onFailureAction error');
}).catch((err) => {/* do nothing */});
it('allows rejected promises through', async () => {
let error: string;
const result: number = await wait.forResult(() => Promise.reject('fake rejection'), 200)
.catch((err) => {
error = err;
return -1;
});
expect(actual).toBeGreaterThan(1);
expect(result).toEqual(-1);
expect(error).toContain('fake rejection');
});
});
module TestHelper {
export var count: number = 0;
export function reset(): void {
count = 0;
}
}
});
{
"extends": "../../tsconfig-settings.json",
"extends": "../../tsconfig.settings.json",
"compilerOptions": {

@@ -4,0 +4,0 @@ "outDir": "dist",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc