UNPKG

@moyal/js-test

Version:

A lightweight, dependency-free JavaScript testing utility. This project is framework-agnostic and usable in both browser and Node.js environments.

7 lines (6 loc) 13.5 kB
/*! * @moyal/js-test v2.1.7 * (c) 2000–present Ilan Moyal * Released under the MIT License */ let t,e,r;class s{static#t=null;static __setup(s,n,i){t=s,e=n,r=i}static getDefaultLogger(){if(null===this.#t)try{"undefined"!=typeof window&&void 0!==window.document||"function"==typeof importScripts&&"undefined"!=typeof self?this.#t=new e:"undefined"!=typeof process&&process.versions?.node?this.#t=new r:this.#t=new t}catch{this.#t=new t}return this.#t}static isLogger(t){return t instanceof s&&Object.getPrototypeOf(t.constructor)===s}#e=new Set(["black","red","green","yellow","blue","magenta","cyan","white","gray","lightred","lightgreen","lightyellow","lightblue","lightmagenta","lightcyan","lightgray"]);isSupportedColor(t){return this.#e.has(t)}normalizeColor(t){return"string"==typeof t?t.toLowerCase():""}log(t,e,...r){}info(t,e,...r){}warn(t,e,...r){}error(t,e,...r){}group(t,e){}groupCollapsed(t,e){}groupEnd(){}}class n{static#r;static{this.#r="undefined"!=typeof performance&&"function"==typeof performance.now?()=>performance.now():()=>Date.now()}static now(){return this.#r()}static isString(t){return"string"==typeof t||"[object String]"===Object.prototype.toString.call(t)}static isIterable(t){return n.isFunctionOrGeneratorFunction(t?.[Symbol.iterator])}static isFunction(t){let e=typeof t;return("object"===e||"function"===e)&&"[object Function]"===Object.prototype.toString.call(t)}static isFunctionOrGeneratorFunction(t){const e=typeof t;if("function"!==e&&"object"!==e)return!1;const r=Object.prototype.toString.call(t);return"[object Function]"===r||"[object GeneratorFunction]"===r}}class i{static*#s(t,e){for(;;)yield t.replace("{0}",e++)}#n=null;#i=null;#o=null;constructor(t,e){if(null!=e&&(!Number.isInteger(e)||e<1))throw new Error("startValue must be a positive integer");this.#n=t??"{0}",this.#i=e??1}reset(){this.#o=i.#s(this.#n,this.#i)}next(){return null==this.#o&&this.reset(),this.#o.next().value}close(){this.#o?.return&&this.#o.return(),this.#o=null}*[Symbol.iterator](){let t=i.#s(this.#n,this.#i);for(let e of t)yield e}}class o extends i{constructor(t=1,e="{0}. "){if(e??="{0}. ",!n.isString(e)||e.indexOf("{0}")<0)throw new Error("Automatic numbering format must include {0}");super(e,t??1)}next(t){return super.next()+(t??"")}}class l{#l="";#u=[];#i=1;constructor(t){this.#i=t??1,this.reset()}reset(){this.#l="",this.#u.length=0,this.#u.push(new o(this.#i,null))}get level(){return this.#u.length}next(t){return this.#l=this.#u[this.#u.length-1].next(),this.#l+(t??"")}nest(t){let e=this.#l.trim();return e+="{0}. ",this.#u.push(new o(t??1,e)),this}unnest(){return this.#u.length>1&&this.#u.pop(),this}}class u{_result=null;_additionalData=null;constructor(t,e){this._result=t,this._additionalData=e}}class a{#a=null;#c=!0;#h=null;#d=null;#g=null;#_=[];#p=0;static#f=null;static __setup(t){this.#f=t}constructor(t,e,r,s){if(!n.isString(t))throw new Error("testName must be string");if(null!=e&&!n.isString(e))throw new Error("successMessage must be string, null or undefined");if(null!=r&&!n.isString(r))throw new Error("failureMessage must be string, null or undefined");this.#a=t,this.#h=e??"success",this.#d=r??"failure",this.#g=s}get name(){return this.#a}get successMessage(){return this.#h}get failureMessage(){return this.#d}get elapsed(){return this.#p}set elapsed(t){this.#p=t}get succeeded(){return this.#c}set succeeded(t){this.#c=!0===t}get failed(){return!0!==this.succeeded}get errors(){return this.#_}get errorCount(){return this.errors.length}get additionalData(){return this.#g}set additionalData(t){this.#g=t}get logger(){return a.#f.logger}run(t,e){return this.runImpl(),(!0===t||!1!==t&&!this.succeeded)&&this.write(e),this.succeeded}runImpl(){throw new Error("Method 'runImpl()' must be implemented by subclass")}_push_error(t){this.#_.push(t)}write(t){null!=t&&t instanceof l||(t=null);const e=this.name?.trim()||"(unnamed test)";let r=`${t?.next()??""}${e}: ${this.succeeded?this.successMessage:this.failureMessage} (${this.elapsed} ms`,s=this.succeeded?"green":"red";if(0===this.errorCount)r+=")";else{let t=(this.succeeded?"":"un")+"expected "+(this.errorCount>1?"errors":"error");r+=`, ${this.errorCount} ${t})`}if(0!=this.errorCount||null!=this.additionalData){if(this.logger.groupCollapsed(r,s),this.errorCount>0){null!=this.additionalData&&this.logger.groupCollapsed("errors");for(let t of this.errors)this.succeeded?this.logger.error(t,"black"):this.logger.error(t);null!=this.additionalData&&this.logger.groupEnd()}null!=this.additionalData&&(this.errorCount>0&&this.logger.groupCollapsed("additional data"),this.logger.log(JSON.stringify(this.additionalData)),this.errorCount>0&&this.logger.groupEnd()),this.logger.groupEnd()}else this.logger.log(r,s)}}class c extends a{#f=null;#w=null;constructor(t,e,r,s,n,i){super(t,r,s,n),this.#f=e,this.#w=i??globalThis}runImpl(){if(!0===this.#f)this.succeeded=!0;else if(n.isFunction(this.#f)){let t;const e=n.now();try{let e=this.#f.call(this.#w);e instanceof u?(this.additionalData=e._additionalData,t=!0===e._result):t=e}catch(e){this._push_error(e),t=!1}const r=n.now();this.elapsed=r-e,this.succeeded=t}else this.succeeded=!1;return this.succeeded}}class h extends c{#m=null;#w=null;#x=!0;constructor(t,e,r,s,i){if(super(t,r,(e=!0===e)?"An error was thrown (as expected)!":"An error was NOT thrown (as expected).",e?"Expected an error, but none was thrown or it did not satisfy the predicate.":"An error was not thrown (unexpectedly).",i),!n.isFunction(r))throw new Error("fn parameter must be a function");if(e&&null!=s&&!n.isFunction(s))throw new Error("checkErrorFn parameter must be a function, null or undefined");this.#x=e,this.#w=i,this.#m=s}runImpl(){super.runImpl();super.succeeded||1!==this.errors.length?this.succeeded=!this.#x:this.succeeded=this.#x&&(null==this.#m||!0===this.#m.call(this.#w,this.errors[0]))}}class d extends c{constructor(t,e,r,s,i){let o,l=null;n.isFunction(e)||n.isFunction(r)||n.isFunction(s)?o=()=>{let t=n.isFunction(e)?e.call(i??globalThis):e,o=n.isFunction(r)?r.call(i??globalThis):r;return new u(n.isFunction(s)?s.call(i??globalThis,t,o):t===o,{expected:t,actual:o})}:(o=e===r,l={expected:e,actual:r}),super(t,o,"Expected and actual values matched","Expected and actual values did not match",l,i)}}class g extends c{constructor(t,e,r,s,i){let o,l=null;n.isFunction(e)||n.isFunction(r)||n.isFunction(s)?o=()=>{let t=n.isFunction(e)?e.call(i??globalThis):e,o=n.isFunction(r)?r.call(i??globalThis):r;return new u(n.isFunction(s)?!s.call(i??globalThis,t,o):t!==o,{not_expected:t,actual:o})}:(o=e!==r,l={not_expected:e,actual:r}),super(t,o,"Actual value did not match the disallowed value (as expected!)","Actual value matched the disallowed value (not as expected!)",l,i)}}class _ extends g{constructor(t,e,r){super(t,void 0,e,null,r)}}class p extends d{constructor(t,e,r){super(t,!1,e,null,r)}}class f extends g{constructor(t,e,r){super(t,null,e,null,r)}}class w extends d{constructor(t,e,r){super(t,null,e,null,r)}}class m extends d{constructor(t,e,r){super(t,!0,e,null,r)}}class x extends d{constructor(t,e,r){super(t,void 0,e,null,r)}}class C extends h{constructor(t,e,r){super(t,!1,e,null,r)}}class F extends a{#x=null;#C=null;#F=null;#b=!0;#w=null;constructor(t,e,r,s,i){super(t,"Actual sequence equals to the expected sequence","Actual sequence does not equal to the expected sequence)",null,i),this.additionalData={},this.#x=e,this.#C=r,this.#F=s,this.#w=i,n.isIterable(e)||(this.additionalData.expected="ERROR: 'expected' argument is not iterable!",this.#b=!1),n.isIterable(r)||(this.additionalData.actual="ERROR: 'actual' argument is not iterable!",this.#b=!1)}runImpl(){if(this.#b){const e=n.now();let r,s=this.additionalData.expected=Array.from(this.#x),i=this.additionalData.actual=Array.from(this.#C);if(s.length===i.length){let e=[];for(var t=0;t<s.length;t++){!0!==(null!=this.#F?this.#F.call(this.#w??void 0,s[t],i[t]):s[t]===i[t])&&e.push(t)}e.length>0&&(this.additionalData["Mismatch at indices"]="Different element indices are: {"+e.join(", ")+"}"),r=0===e.length}else this.additionalData["Mismatch at indices"]="expected.length !== actual.length",r=!1;const o=n.now();this.elapsed=o-e,this.succeeded=r}else this.succeeded=!1}}class b extends h{constructor(t,e,r,s){super(t,!0,e,r,s)}}class y extends a{#y=[];#E=0;#v=0;#D=0;#$=0;#S=null;#A=null;constructor(t,...e){super(t),this.add(...e)}clear(){this.#y.length=0,this.#E=0,this.#v=0,this.#D=0,this.#$=0}get errorCount(){return this.#D}run(t,e){return this.#A=t,super.run(t,e)}runImpl(){this.#E=0,this.#D=0,this.#$=0;const t=n.now();for(let t of this.#y)t.runImpl(),t instanceof y?(this.#v+=t.totalFailureCount,this.#$+=t.unexpectedErrorCount):(this.#E+=t.succeeded?0:1,this.#$+=t.succeeded?0:t.errorCount,this.#v+=t.succeeded?0:1),this.#D+=t.errorCount;const e=n.now();return this.elapsed=e-t,0===this.#E}write(t,e){null!=t&&t instanceof l||(t=null);const r=null==e?this.#A:e;let s,n=`${t?.next()??""}${this.name}: (${this.elapsed}ms, `;if(this.succeeded?(s="green",n+="all passed"):(s="red",n+=`${0==this.#E?"no":this.#E.toString()} direct failure${1===this.#E?"":"s"}, ${this.#v} total failure${1===this.#v?"":"s"}`),this.#$>0&&(n+=`, ${this.#$} unexpected error${this.#$>1?"s":""}`),n+=")",this.succeeded?this.logger.groupCollapsed(n,s):this.logger.group(n,s),this.#y?.length>0){t?.nest();for(let e of this.#y)(!0===r||null==r&&!e.succeeded)&&e.write(t,this.#A);t?.unnest()}this.logger.groupEnd()}get unexpectedErrorCount(){return this.#$}get directFailureCount(){return this.#E}get totalFailureCount(){return this.#v}get succeeded(){return 0===this.#v}add(...t){this.#y.push(...t);for(let e of t)e instanceof y&&(e.#S=this)}groupStart(t){let e=new y(t);return this.add(e),e}groupClose(){return this.#S??this}areEqual(t,e,r,s,n){return this.add(new d(t,e,r,s,n)),this}areNotEqual(t,e,r,s,n){return this.add(new g(t,e,r,s,n)),this}isTrue(t,e,r=null){return this.add(new m(t,e,r)),this}isFalse(t,e,r){return this.add(new p(t,e,r)),this}isNull(t,e,r){return this.add(new w(t,e,r)),this}isNotNull(t,e,r=null){return this.add(new f(t,e,r)),this}isDefined(t,e,r=null){return this.add(new _(t,e,r)),this}isUndefined(t,e,r=null){return this.add(new x(t,e,r)),this}throws(t,e,r,s=null){return this.add(new b(t,e,r,s)),this}noThrows(t,e,r=null){return this.add(new C(t,e,r)),this}sequencesAreEqual(t,e,r,s){return this.add(new F(t,e,r,s)),this}}class E extends s{#M=0;#L="";#q(){this.#M++,this.#L=" ".repeat(this.#M)}#I(){this.#M--,this.#M<0&&(this.#M=0),this.#L=" ".repeat(this.#M)}prefixMessage(t){return this.#L+t}colorfy(t,e,r){return t}log(t,e,...r){return t??="",console.log(this.colorfy(this.prefixMessage(t),e,"white"),...r),this}info(t,e,...r){return t??="",console.info(this.colorfy(this.prefixMessage(t),e,"cyan"),...r),this}warn(t,e,...r){return t??="",console.warn(this.colorfy(this.prefixMessage(t),e,"yellow"),...r),this}error(t,e,...r){return t??="",console.error(this.colorfy(this.prefixMessage(t),e,"red"),...r),this}#N(t,e){t??="",console.log(this.colorfy(this.prefixMessage(`▼ ${t}`),e,"gray")),this.#q()}group(t,e){return this.#N(t,e),this}groupCollapsed(t,e){return this.#N(t,e),this}groupEnd(){return this.#I(),this}}class v extends s{#T(t){return t=this.normalizeColor(t),this.isSupportedColor(t)?t:void 0}log(t,e,...r){return t??="",console.log(`%c${t}`,`color:${this.#T(e)??"inherit"}`,...r),this}info(t,e,...r){return t??="",console.info(`%c${t}`,`color:${this.#T(e)??"blue"}`,...r),this}warn(t,e,...r){return t??="",console.warn(`%c${t}`,`color:${this.#T(e)??"orange"}`,...r),this}error(t,e,...r){return t??="",console.error(`%c${t}`,`color:${this.#T(e)??"red"}`,...r),this}group(t,e){return console.group(`%c${t}`,`color:${this.#T(e)??"inherit"}`),this}groupCollapsed(t,e){return console.groupCollapsed(`%c${t}`,`color:${this.#T(e)??"inherit"}`),this}groupEnd(){return console.groupEnd(),this}}class D extends E{#z(t,e){return({black:"",red:"",green:"",yellow:"",blue:"",magenta:"",cyan:"",white:"",gray:"",lightred:"",lightgreen:"",lightyellow:"",lightblue:"",lightmagenta:"",lightcyan:"",lightgray:""}[t=this.normalizeColor(t)]??"")+e+""}colorfy(t,e,r){return this.#z(e?.toLowerCase()??r,t)}}s.__setup(E,v,D);class ${static version="2.1.7"}class S{static#O=null;static get Version(){return $.version}static get logger(){return null==this.#O&&(this.#O=s.getDefaultLogger()),this.#O}static set logger(t){null==t?this.#O=s.getDefaultLogger():s.isLogger(t)&&(this.#O=t)}static areEqual(t,e,r,s,n){return new d(t,e,r,s).run(n)}static areNotEqual(t,e,r,s,n){return new g(t,e,r,s).run(n)}static isTrue(t,e,r){return new m(t,e).run(r)}static isFalse(t,e,r){return new p(t,e).run(r)}static isNull(t,e,r){return new w(t,e).run(r)}static isNotNull(t,e,r){return new f(t,e).run(r)}static isDefined(t,e,r){return new _(t,e).run(r)}static isUndefined(t,e,r){return new x(t,e).run(r)}static throws(t,e,r,s,n){return new b(t,e,r,s).run(n)}static noThrows(t,e,r,s){return new C(t,e,r).run(s)}static sequencesAreEqual(t,e,r,s,n){return new F(t,e,r,s).run(n)}}a.__setup(S);export{d as AreEqual,g as AreNotEqual,c as Assert,o as AutoNumbering,v as BrowserLogger,_ as IsDefined,p as IsFalse,f as IsNotNull,w as IsNull,m as IsTrue,x as IsUndefined,s as LoggerBase,l as MultiLevelAutoNumbering,C as NoThrows,D as NodeLogger,F as SequencesAreEqual,i as SequentialText,E as SimpleLogger,S as Test,a as TestBase,y as TestGroup,b as Throws,h as ThrowsBase};