vest 4.0.0-dev-cc5cf5 → 4.0.0-dev-31f012
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -44
- package/README.md +7 -1
- package/dist/cjs/classnames.development.js +3 -3
- package/dist/cjs/classnames.production.js +1 -1
- package/dist/cjs/promisify.development.js +1 -1
- package/dist/cjs/promisify.production.js +1 -1
- package/dist/cjs/vest.development.js +394 -180
- package/dist/cjs/vest.production.js +1 -1
- package/dist/es/classnames.development.js +3 -3
- package/dist/es/classnames.production.js +1 -1
- package/dist/es/promisify.development.js +1 -1
- package/dist/es/promisify.production.js +1 -1
- package/dist/es/vest.development.js +394 -180
- package/dist/es/vest.production.js +1 -1
- package/dist/umd/classnames.development.js +3 -3
- package/dist/umd/classnames.production.js +1 -1
- package/dist/umd/promisify.development.js +1 -1
- package/dist/umd/promisify.production.js +1 -1
- package/dist/umd/vest.development.js +394 -180
- package/dist/umd/vest.production.js +1 -1
- package/package.json +1 -1
- package/testUtils/testObjects.ts +11 -2
- package/types/classnames.d.ts +2 -2
- package/types/vest.d.ts +10 -3
- package/docs/.nojekyll +0 -0
- package/docs/README.md +0 -107
- package/docs/_assets/favicon.ico +0 -0
- package/docs/_assets/vest-logo.png +0 -0
- package/docs/_sidebar.md +0 -14
- package/docs/cross_field_validations.md +0 -34
- package/docs/enforce.md +0 -11
- package/docs/exclusion.md +0 -129
- package/docs/getting_started.md +0 -72
- package/docs/group.md +0 -142
- package/docs/index.html +0 -41
- package/docs/migration.md +0 -202
- package/docs/n4s/rules.md +0 -1282
- package/docs/node.md +0 -36
- package/docs/optional.md +0 -103
- package/docs/result.md +0 -249
- package/docs/state.md +0 -102
- package/docs/test.md +0 -172
- package/docs/utilities.md +0 -109
- package/docs/warn.md +0 -82
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((n="undefined"!=typeof globalThis?globalThis:n||self).vest={})}(this,(function(n){function t(n,t,r){if(r||2===arguments.length)for(var e,u=0,i=t.length;u<i;u++)!e&&u in t||(e||(e=Array.prototype.slice.call(t,0,u)),e[u]=t[u]);return n.concat(e||t)}function r(n){return"function"==typeof n}function e(n,t){function r(n){e=!0,u=n}for(var e=!1,u=null,i=0;i<n.length;i++)if(t(n[i],r,i),e)return u}function u(n){for(var t=[],e=1;e<arguments.length;e++)t[e-1]=arguments[e];return r(n)?n.apply(void 0,t):n}function i(n,t){var r;return null!==(r=u(n))&&void 0!==r?r:t}function o(n,t){return n={pass:n},t&&(n.message=t),n}function s(n,t){try{return n.run(t)}catch(n){return o(!1)}}function a(n){return function(){for(var t=[],r=0;r<arguments.length;r++)t[r]=arguments[r];return!n.apply(void 0,t)}}function f(n,t){return n.length===Number(t)}function c(n,t){return n.length>Number(t)}function l(n){return null===n}function p(n){return void 0===n}function d(n){return String(n)===n}function v(n,t){return d(n)&&d(t)&&n.endsWith(t)}function h(n,t){return n===t}function g(n){var t=Number(n);return!(isNaN(parseFloat(String(n)))||isNaN(Number(n))||!isFinite(t))}function y(n,t){return g(n)&&g(t)&&Number(n)>Number(t)}function m(n,t){return g(n)&&g(t)&&Number(n)>=Number(t)}function N(n,t){return!!(Array.isArray(t)||d(t)&&d(n))&&-1!==t.indexOf(n)}function b(n){return!!Array.isArray(n)}function E(n,t){return g(n)&&g(t)&&Number(n)<=Number(t)}function O(n,t,r){return m(n,t)&&E(n,r)}function C(n){return d(n)&&!n.trim()}function T(n){return!!n===n}function w(n){return"number"==typeof n}function S(n){if(n){if(w(n))return 0===n;if(Object.prototype.hasOwnProperty.call(n,"length"))return f(n,0);if("object"==typeof n)return f(Object.keys(n),0)}return!0}function k(n){return Number.isNaN(n)}function x(n){return!!g(n)&&0>Number(n)}function P(n){return!!n}function F(n,t){return g(n)&&g(t)&&Number(n)<Number(t)}function j(n,t){return t instanceof RegExp?t.test(n):!!d(t)&&new RegExp(t).test(n)}function W(n,t){return g(n)&&g(t)&&Number(n)===Number(t)}function A(n,t){return d(n)&&d(t)&&n.startsWith(t)}function I(n,t){throw Error(i(t,n))}function R(n){function t(t,u){var i,o,s=r();return t=An({},s||{},null!==(i=null==n?void 0:n(t,s))&&void 0!==i?i:t),i=e.ctx=Object.freeze(t),e.ancestry.unshift(i),u=u(i),e.ancestry.shift(),e.ctx=null!==(o=e.ancestry[0])&&void 0!==o?o:null,u}function r(){return e.ctx}var e={ancestry:[]};return{bind:function(n,r){return function(){for(var e=[],u=0;u<arguments.length;u++)e[u]=arguments[u];return t(n,(function(){return r.apply(void 0,e)}))}},run:t,use:r,useX:function(n){var t;return null!==(t=e.ctx)&&void 0!==t?t:I(i(n,"Context was used after it was closed"))}}}function q(){return null}function B(n,t){var r,e=function(r){var e=n[r],u=t[r];if(!(r=nt.run({value:e,set:!0,meta:{key:r}},(function(){return s(u,e)}))).pass)return{value:r}};for(r in t){var u=e(r);if("object"==typeof u)return u.value}return o(!0)}function D(n){for(var t in tt){var e=tt[t];r(e)&&n(t,e)}}function G(){return"function"==typeof Proxy}function X(n,r,e){for(var i=[],s=3;s<arguments.length;s++)i[s-3]=arguments[s];return T(n)||n&&T(n.pass)||I("Incorrect return value for rule: "+JSON.stringify(n)),T(n)?o(n):o(n.pass,u.apply(void 0,t([n.message,r,e],i,!1)))}function K(n){function r(r,e,u){return function(){for(var i=[],o=0;o<arguments.length;o++)i[o]=arguments[o];if(!(o=X.apply(void 0,t([nt.run({value:n},(function(){return e.apply(void 0,t([n],i,!1))})),u,n],i,!1))).pass){if(!S(o.message))throw o.message;I("enforce/"+u+" failed with "+JSON.stringify(n))}return r}}var e={};if(!G())return D((function(n,t){e[n]=r(e,t,n)})),e;var u=new Proxy(e,{get:function(n,t){if(n=tt[t])return r(u,n,t)}});return u}function M(n){var r,s=[];return function n(a){return function(){for(var f=[],c=0;c<arguments.length;c++)f[c]=arguments[c];var l=tt[a];s.push((function(n){return X.apply(void 0,t([l.apply(void 0,t([n],f,!1)),a,n],f,!1))}));var p={run:function(n){return i(e(s,(function(t,e){var i,s=nt.run({value:n},(function(){return t(n)}));s.pass||e(o(!!s.pass,null!==(i=u(r,n,s.message))&&void 0!==i?i:s.message))})),o(!0))},test:function(n){return p.run(n).pass},message:function(n){return n&&(r=n),p}};return G()?p=new Proxy(p,{get:function(t,r){return tt[r]?n(r):t[r]}}):(D((function(t){p[t]=n(t)})),p)}}(n)}function _(n){var t,r={};for(t in n)r[t]=rt.optional(n[t]);return r}function L(n,t){return!(!t||n.fieldName!==t)}function U(n){void 0===n&&(n=1);var t=[],r=function(e,u){var i=r.get(e);return i?i[1]:(u=u(),t.unshift([e.concat(),u]),c(t,n)&&(t.length=n),u)};return r.invalidate=function(n){var r=t.findIndex((function(t){var r=t[0];return f(n,r.length)&&n.every((function(n,t){return n===r[t]}))}));-1<r&&t.splice(r,1)},r.get=function(n){return t[t.findIndex((function(t){var r=t[0];return f(n,r.length)&&n.every((function(n,t){return n===r[t]}))}))]||null},r}function J(){return ut.useX().stateRef}function V(){return J().testObjects()}function z(){(0,J().testObjectsCursor()[1])((function(n){return n+1}))}function Y(n){var t=J().testObjectsCursor()[0],r=V();n!==r[0][t]&&(0,r[1])((function(r){return(r=r.slice(0))[t]=n,r}))}function H(){var n=V()[0];return ot([n],(function(){return n.filter((function(n){return n.isPending()}))}))}function Q(){var n=V()[1],t=J().optionalFields()[0];if(!S(t)){var e={};n((function(n){return n.map((function(n){var u=n.fieldName;if(e.hasOwnProperty(u))e[n.fieldName]&&n.omit();else{var i=t[u];r(i)&&(e[u]=i(),e[n.fieldName]&&n.omit())}return n}))}))}}function Z(n){var t=H();return!S(t)&&(n?t.some((function(t){return L(t,n)})):Jn(t))}function $(n,t){function r(n,t){i[n]++,u&&(i[t]=(i[t]||[]).concat(u))}var e=t.fieldName,u=t.message;n[e]=n[e]||{errorCount:0,warnCount:0,testCount:0};var i=n[e];return t.isSkipped()||(n[e].testCount++,t.isFailing()?r("errorCount","errors"):t.isWarning()&&r("warnCount","warnings")),i}function nn(n,t,r){var e;void 0===r&&(r={});var u=(r=r||{}).group,i=r.fieldName;return t.reduce((function(t,r){return u&&r.groupName!==u||i&&!L(r,i)||"warnings"===n!=!!r.warns||!r.hasFailures()||(t[r.fieldName]=(t[r.fieldName]||[]).concat(r.message||[])),t}),Wn({},i&&((e={})[i]=[],e)))}function tn(n){return en("errors",n)}function rn(n){return en("warnings",n)}function en(n,t){return n=nn(n,V()[0],{fieldName:t}),t?n[t]:n}function un(n,t){return n=sn("errors",n,t),t?n[t]:n}function on(n,t){return n=sn("warnings",n,t),t?n[t]:n}function sn(n,t,r){return t||I("get"+n[0].toUpperCase()+n.slice(1)+"ByGroup requires a group name. Received `"+t+"` instead."),nn(n,V()[0],{group:t,fieldName:r})}function an(n,t,r){return!(!n.hasFailures()||r&&!L(n,r)||"warnings"===t!=!!n.warns)}function fn(n){return ln("errors",n)}function cn(n){return ln("warnings",n)}function ln(n,t){return V()[0].some((function(r){return an(r,n,t)}))}function pn(n,t){return vn("errors",n,t)}function dn(n,t){return vn("warnings",n,t)}function vn(n,t,r){return V()[0].some((function(e){return t===e.groupName&&an(e,n,r)}))}function hn(){var n=V()[0],t={stateRef:J()};return st([n],ut.bind(t,(function(){return An(function(){var n={errorCount:0,groups:{},testCount:0,tests:{},warnCount:0};return V()[0].forEach((function(t){var r=t.fieldName,e=t.groupName;n.tests[r]=$(n.tests,t),e&&(n.groups[e]=n.groups[e]||{},n.groups[e][r]=$(n.groups[e],t))})),function(n){for(var t in n.tests)n.errorCount+=n.tests[t].errorCount,n.warnCount+=n.tests[t].warnCount,n.testCount+=n.tests[t].testCount;return n}(n)}(),{getErrors:ut.bind(t,tn),getErrorsByGroup:ut.bind(t,un),getWarnings:ut.bind(t,rn),getWarningsByGroup:ut.bind(t,on),hasErrors:ut.bind(t,fn),hasErrorsByGroup:ut.bind(t,pn),hasWarnings:ut.bind(t,cn),hasWarningsByGroup:ut.bind(t,dn),isValid:ut.bind(t,(function(n){var t=hn(),r=function(){var n=V()[0];return it([n],(function(){return n.reduce((function(n,t){return n[t.fieldName]||t.isOmitted()&&(n[t.fieldName]=!0),n}),{})}))}();return(r=!!n&&!!r[n])?n=!0:t.hasErrors(n)?n=!1:n=!(S(r=V()[0])||n&&S(t.tests[n])||function(n){var t=J().optionalFields()[0];return Jn(H().filter((function(r){return!(n&&!L(r,n))&&!0!==t[r.fieldName]})))}(n))&&function(n){var t=V()[0],r=J().optionalFields()[0];return t.every((function(t){return!(!n||L(t,n))||!0===r[t.fieldName]||t.isTested()||t.isOmitted()}))}(n),n}))})})))}function gn(){var n=V()[0],t={stateRef:J()};return at([n],ut.bind(t,(function(){return An({},hn(),{done:ut.bind(t,ft)})})))}function yn(n,t,e){return!(r(n)&&(!t||e.tests[t]&&0!==e.tests[t].testCount))}function mn(n){return!(Z()&&(!n||Z(n)))}function Nn(n,t){var r=ut.bind({},n);(0,J().testCallbacks()[1])((function(n){return t?n.fieldCallbacks[t]=(n.fieldCallbacks[t]||[]).concat(r):n.doneCallbacks.push(r),n}))}function bn(n){return n.forEach((function(n){return n()}))}function En(){var n=ut.useX();return n.bus||I(),n.bus}function On(n){return Tn("only","tests",n)}function Cn(n){return Tn("skip","tests",n)}function Tn(n,t,r){var e=ut.useX("hook called outside of a running suite.");r&&[].concat(r).forEach((function(r){d(r)&&(e.exclusion[t][r]="only"===n)}))}function wn(n){for(var t in n)if(!0===n[t])return!0;return!1}function Sn(n){I("Wrong arguments passed to group. Group "+n+".")}function kn(n){var t=n.asyncTest,e=n.message;if(t&&r(t.then)){var u=En().emit,i=J(),o=ut.bind({stateRef:i},(function(){(0,V()[1])((function(n){return n.slice(0)})),u(Fn.TEST_COMPLETED,n)}));i=ut.bind({stateRef:i},(function(t){n.isCanceled()||(n.message=d(t)?t:e,n.fail(),o())}));try{t.then(o,i)}catch(n){i()}}}function xn(n){var t,e=J().testObjectsCursor()[0],u=J().prevTestObjects()[0];if((t=Jn(u[e]))&&(t=!((t=u[e]).fieldName===n.fieldName&&t.groupName===n.groupName)),t&&function(n,t){setTimeout((function(){I(n,t)}),0)}("Vest Critical Error: Tests called in different order than previous run.\n The test at cursor "+e+" was not the same profile as the previous test.\n expected: "+JSON.stringify(u[e])+"\n actual: "+JSON.stringify(n)+"\n This usually happens when you conditionally call your tests using if/else.\n This might lead to unexpected behavior in your test results.\n Replacing if/else with skipWhen solves these issues."),Y(e=i(u[e],n)),function(n){var t=n.fieldName;n=n.groupName;var r=ut.useX();if(r.skipped)return!0;var e=(r=r.exclusion).tests,u=e[t];if(!1===u)return!0;if(u=!0===u,n){n:{var i=ut.useX().exclusion.groups;if(Object.prototype.hasOwnProperty.call(i,n))var o=!1===i[n];else{for(o in i)if(!0===i[o]){o=!0;break n}o=!1}}if(o)return!0;if(!0===r.groups[n])return!(u||!wn(e)&&!1!==e[t])}return!u&&wn(e)}(n))return n.skip(),z(),e;if(n!==e&&e.fieldName===n.fieldName&&e.groupName===n.groupName&&e.isPending()&&e.cancel(),Y(n),z(),n.isUntested()){e=En().emit,u=function(n){return ut.run({currentTest:n},(function(){try{var t=n.testFn()}catch(r){t=r,p(n.message)&&d(t)&&(n.message=r),t=!1}return!1===t&&n.fail(),t}))}(n);try{u&&r(u.then)?(n.asyncTest=u,n.setPending(),kn(n)):e(Fn.TEST_COMPLETED,n)}catch(t){I("Your test function "+n.fieldName+" returned "+JSON.stringify(u)+'. Only "false" or a Promise are supported. Return values may cause unexpected behavior.')}}else(e=n.asyncTest)&&r(e.then)&&(n.setPending(),kn(n));return n}function Pn(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];r=t.reverse(),t=r[0],r=r[1];var e=ut.useX();return xn(t=new ct(n,t,{message:r,groupName:null==e?void 0:e.groupName}))}var Fn,jn,Wn=function(){return Wn=Object.assign||function(n){for(var t,r=1,e=arguments.length;r<e;r++)for(var u in t=arguments[r])Object.prototype.hasOwnProperty.call(t,u)&&(n[u]=t[u]);return n},Wn.apply(this,arguments)},An=Object.assign,In=a(f),Rn=a(l),qn=a(p),Bn=a(v),Dn=a(h),Gn=a(g),Xn=a(N),Kn=a(b),Mn=a(O),_n=a(C),Ln=a(T),Un=a(w),Jn=a(S),Vn=a(k),zn=a(x),Yn=a(d),Hn=a(P),Qn=a(j),Zn=a(W),$n=a(A),nt=R((function(n,t){var r={value:n.value,meta:n.meta||{}};return t?n.set?An(r,{parent:function(){return t?{value:t.value,meta:t.meta,parent:t.parent}:t}}):t:An(r,{parent:q})})),tt=An({condition:function(n,t){try{return t(n)}catch(n){return!1}},doesNotEndWith:Bn,doesNotStartWith:$n,endsWith:v,equals:h,greaterThan:y,greaterThanOrEquals:m,gt:y,gte:m,inside:N,isArray:b,isBetween:O,isBlank:C,isBoolean:T,isEmpty:S,isEven:function(n){return!!g(n)&&0==n%2},isFalsy:Hn,isNaN:k,isNegative:x,isNotArray:Kn,isNotBetween:Mn,isNotBlank:_n,isNotBoolean:Ln,isNotEmpty:Jn,isNotNaN:Vn,isNotNull:Rn,isNotNumber:Un,isNotNumeric:Gn,isNotString:Yn,isNotUndefined:qn,isNull:l,isNumber:w,isNumeric:g,isOdd:function(n){return!!g(n)&&0!=n%2},isPositive:zn,isString:d,isTruthy:P,isUndefined:p,lengthEquals:f,lengthNotEquals:In,lessThan:F,lessThanOrEquals:E,longerThan:c,longerThanOrEquals:function(n,t){return n.length>=Number(t)},lt:F,lte:E,matches:j,notEquals:Dn,notInside:Xn,notMatches:Qn,numberEquals:W,numberNotEquals:Zn,shorterThan:function(n,t){return n.length<Number(t)},shorterThanOrEquals:function(n,t){return n.length<=Number(t)},startsWith:A},{allOf:function(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];return i(e(t,(function(t,r){(t=s(t,n)).pass||r(t)})),o(!0))},anyOf:function(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];return i(e(t,(function(t,r){(t=s(t,n)).pass&&r(t)})),o(!1))},noneOf:function(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];return i(e(t,(function(t,r){s(t,n).pass&&r(o(!1))})),o(!0))},oneOf:function(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];var e=[];return t.some((function(t){if(c(e,1))return!1;(t=s(t,n)).pass&&e.push(t)})),o(f(e,1))},optional:function(n,t){return p(n)||null===n?o(!0):s(t,n)}},{shape:function(n,t){var r=B(n,t);if(!r.pass)return r;for(var e in n)if(!Object.prototype.hasOwnProperty.call(t,e))return o(!1);return o(!0)},loose:B,isArrayOf:function(n,t){return i(e(n,(function(n,r,e){(e=nt.run({value:n,set:!0,meta:{index:e}},(function(){return s(t,n)}))).pass||r(e)})),o(!0))}}),rt=(jn=Wn({context:function(){return nt.useX()},extend:function(n){An(tt,n)}},{partial:_}),G()?new Proxy(An(K,jn),{get:function(n,t){return t in n?n[t]:tt[t]?M(t):void 0}}):(D((function(n){jn[n]=M(n)})),jn)),et=function(n){return function(){return""+n++}}(0),ut=R((function(n,t){return t?null:An({},{exclusion:{tests:{},groups:{}}},n)})),it=U(),ot=U(),st=U(20),at=U(20),ft=function(){for(var n=[],t=0;t<arguments.length;t++)n[t]=arguments[t];var r=(n=n.reverse())[0];if(n=n[1],t=gn(),yn(r,n,t))return t;var e=function(){return r(hn())};return mn(n)?(e(),t):(Nn(e,n),t)};(Fn||(Fn={})).TEST_COMPLETED="test_completed",On.group=function(n){return Tn("only","groups",n)},Cn.group=function(n){return Tn("skip","groups",n)};var ct=function(){function n(n,t,r){var e=void 0===r?{}:r;r=e.message,e=e.groupName,this.id=et(),this.warns=!1,this.status=lt,this.fieldName=n,this.testFn=t,e&&(this.groupName=e),r&&(this.message=r)}return n.prototype.run=function(){try{var n=this.testFn()}catch(t){n=t,p(this.message)&&d(n)&&(this.message=t),n=!1}return!1===n&&this.fail(),n},n.prototype.setStatus=function(n){this.isFinalStatus()&&n!==mt||(this.status=n)},n.prototype.setPending=function(){this.setStatus(gt)},n.prototype.fail=function(){this.setStatus(this.warns?vt:dt)},n.prototype.done=function(){this.isFinalStatus()||this.setStatus(ht)},n.prototype.warn=function(){this.warns=!0},n.prototype.isFinalStatus=function(){return this.hasFailures()||this.isCanceled()||this.isPassing()},n.prototype.skip=function(){this.setStatus(pt)},n.prototype.cancel=function(){this.setStatus(yt),function(n){(0,V()[1])((function(t){var r=t.indexOf(n);return-1!==r&&t.splice(r,1),[].concat(t)}))}(this)},n.prototype.omit=function(){this.setStatus(mt)},n.prototype.valueOf=function(){return!this.isFailing()},n.prototype.hasFailures=function(){return this.isFailing()||this.isWarning()},n.prototype.isPending=function(){return this.status===gt},n.prototype.isTested=function(){return this.hasFailures()||this.isPassing()},n.prototype.isOmitted=function(){return this.status===mt},n.prototype.isUntested=function(){return this.status===lt},n.prototype.isFailing=function(){return this.status===dt},n.prototype.isCanceled=function(){return this.status===yt},n.prototype.isSkipped=function(){return this.status===pt},n.prototype.isPassing=function(){return this.status===ht},n.prototype.isWarning=function(){return this.status===vt},n}(),lt="UNTESTED",pt="SKIPPED",dt="FAILED",vt="WARNING",ht="PASSING",gt="PENDING",yt="CANCELED",mt="OMITTED",Nt=An(Pn,{each:function(n){return function(r){return Array.isArray(r)||I("test.each: Expected table to be an array."),function(e){for(var i=[],o=1;o<arguments.length;o++)i[o-1]=arguments[o];var s=(i=i.reverse())[0],a=i[1];return r.map((function(r){return r=[].concat(r),n(u.apply(void 0,t([e],r,!1)),u.apply(void 0,t([a],r,!1)),(function(){return s.apply(void 0,r)}))}))}}}(Pn),memo:function(n){var t=U(100);return function(r){for(var e=[],u=1;u<arguments.length;u++)e[u-1]=arguments[u];u=J().suiteId()[0];var i=J().testObjectsCursor()[0],o=(e=e.reverse())[1],s=e[2];return e=[u,r,i].concat(e[0]),null===(u=t.get(e))?t(e,(function(){return n(r,s,o)})):u[1].isCanceled()?(t.invalidate(e),t(e,(function(){return n(r,s,o)}))):xn(u[1])}}(Pn)});n.VERSION="4.0.0-dev-cc5cf5",n.create=function(n){r(n)||I("Suite initialization error. Expected `tests` to be a function.");var t=function(){var n=function(){var n={};return{emit:function(t,r){n[t]&&n[t].forEach((function(n){n(r)}))},on:function(t,r){return n[t]||(n[t]=[]),n[t].push(r),{off:function(){n[t]=n[t].filter((function(n){return n!==r}))}}}}}();return n.on(Fn.TEST_COMPLETED,(function(n){if(!n.isCanceled()){n.done(),n=n.fieldName;var t=J().testCallbacks()[0].fieldCallbacks;n&&!Z(n)&&Array.isArray(t[n])&&bn(t[n]),n=J().testCallbacks()[0].doneCallbacks,Z()||bn(n)}})),n}(),e=function(n){function t(n,t){return i.references.push(),e(n,u(t)),function(){return[i.references[n],function(t){return e(n,u(t,i.references[n]))}]}}function e(t,e){var u=i.references[t];i.references[t]=e,r(t=o[t][1])&&t(e,u),r(n)&&n()}var i={references:[]},o=[];return{registerStateKey:function(n,r){var e=o.length;return o.push([n,r]),t(e,n)},reset:function(){i.references=[],o.forEach((function(n,r){return t(r,n[0])}))}}}(),i=function(n,t){var r=t.suiteId;return{optionalFields:n.registerStateKey((function(){return{}})),prevTestObjects:n.registerStateKey((function(){return[]})),suiteId:n.registerStateKey((function(){return r})),testCallbacks:n.registerStateKey((function(){return{fieldCallbacks:{},doneCallbacks:[]}})),testObjects:n.registerStateKey((function(){return[]})),testObjectsCursor:n.registerStateKey((function(){return 0}))}}(e,{suiteId:et()});return An(ut.bind({stateRef:i,bus:t},(function(){for(var t=[],r=0;r<arguments.length;r++)t[r]=arguments[r];var u=V()[0];return r=J().prevTestObjects()[1],e.reset(),r((function(){return u})),n.apply(void 0,t),Q(),gn()})),{get:ut.bind({stateRef:i},hn),remove:ut.bind({stateRef:i},(function(n){var t=V()[0];[].concat(t).forEach((function(t){L(t,n)&&t.cancel()}))})),reset:e.reset})},n.enforce=rt,n.group=function(n,t){d(n)||Sn("name must be a string"),r(t)||Sn("callback must be a function"),ut.run({groupName:n},t)},n.only=On,n.optional=function(n){(0,J().optionalFields()[1])((function(t){if(b(n)||d(n))[].concat(n).forEach((function(n){t[n]=!0}));else for(var r in n)t[r]=n[r];return t}))},n.skip=Cn,n.skipWhen=function(n,t){ut.run({skipped:u(n)},(function(){return t()}))},n.test=Nt,n.warn=function(){var n=ut.useX("warn hook called outside of a running suite.");n.currentTest||I("warn called outside of a test."),n.currentTest.warn()},Object.defineProperty(n,"__esModule",{value:!0})}));
|
|
1
|
+
"use strict";!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((n="undefined"!=typeof globalThis?globalThis:n||self).vest={})}(this,(function(n){function t(n,t,r){if(r||2===arguments.length)for(var e,u=0,i=t.length;u<i;u++)!e&&u in t||(e||(e=Array.prototype.slice.call(t,0,u)),e[u]=t[u]);return n.concat(e||t)}function r(n){return"function"==typeof n}function e(n,t){function r(n){e=!0,u=n}for(var e=!1,u=null,i=0;i<n.length;i++)if(t(n[i],r,i),e)return u}function u(n){for(var t=[],e=1;e<arguments.length;e++)t[e-1]=arguments[e];return r(n)?n.apply(void 0,t):n}function i(n,t){var r;return null!==(r=u(n))&&void 0!==r?r:t}function o(n,t){return n={pass:n},t&&(n.message=t),n}function s(n,t){try{return n.run(t)}catch(n){return o(!1)}}function a(n){return function(){for(var t=[],r=0;r<arguments.length;r++)t[r]=arguments[r];return!n.apply(void 0,t)}}function c(n,t){return n.length===Number(t)}function f(n,t){return n.length>Number(t)}function l(n){return null===n}function p(n){return void 0===n}function v(n){return String(n)===n}function d(n,t){return v(n)&&v(t)&&n.endsWith(t)}function h(n,t){return n===t}function g(n){var t=Number(n);return!(isNaN(parseFloat(String(n)))||isNaN(Number(n))||!isFinite(t))}function m(n,t){return g(n)&&g(t)&&Number(n)>Number(t)}function y(n,t){return g(n)&&g(t)&&Number(n)>=Number(t)}function N(n){return!!Array.isArray(n)}function b(n,t){return!!(N(t)||v(t)&&v(n))&&-1!==t.indexOf(n)}function E(n,t){return g(n)&&g(t)&&Number(n)<=Number(t)}function C(n,t,r){return y(n,t)&&E(n,r)}function O(n){return v(n)&&!n.trim()}function T(n){return!!n===n}function S(n){return"number"==typeof n}function w(n){if(n){if(S(n))return 0===n;if(Object.prototype.hasOwnProperty.call(n,"length"))return c(n,0);if("object"==typeof n)return c(Object.keys(n),0)}return!0}function P(n){return Number.isNaN(n)}function x(n){return!!g(n)&&0>Number(n)}function F(n){return!!n}function k(n,t){return g(n)&&g(t)&&Number(n)<Number(t)}function I(n,t){return t instanceof RegExp?t.test(n):!!v(t)&&new RegExp(t).test(n)}function A(n,t){return g(n)&&g(t)&&Number(n)===Number(t)}function D(n,t){return v(n)&&v(t)&&n.startsWith(t)}function L(n,t){throw Error(i(t,n))}function W(n){function t(t,u){var i,o,s=r();return t=qn({},s||{},null!==(i=null==n?void 0:n(t,s))&&void 0!==i?i:t),i=e.ctx=Object.freeze(t),e.ancestry.unshift(i),u=u(i),e.ancestry.shift(),e.ctx=null!==(o=e.ancestry[0])&&void 0!==o?o:null,u}function r(){return e.ctx}var e={ancestry:[]};return{bind:function(n,r){return function(){for(var e=[],u=0;u<arguments.length;u++)e[u]=arguments[u];return t(n,(function(){return r.apply(void 0,e)}))}},run:t,use:r,useX:function(n){var t;return null!==(t=e.ctx)&&void 0!==t?t:L(i(n,"Context was used after it was closed"))}}}function U(){return null}function j(n,t){var r,e=function(r){var e=n[r],u=t[r];if(!(r=ft.run({value:e,set:!0,meta:{key:r}},(function(){return s(u,e)}))).pass)return{value:r}};for(r in t){var u=e(r);if("object"==typeof u)return u.value}return o(!0)}function R(n){for(var t in lt){var e=lt[t];r(e)&&n(t,e)}}function X(){try{return r(Proxy)}catch(n){return!1}}function _(n,r,e){for(var i=[],s=3;s<arguments.length;s++)i[s-3]=arguments[s];return T(n)||n&&T(n.pass)||L("Incorrect return value for rule: "+JSON.stringify(n)),T(n)?o(n):o(n.pass,u.apply(void 0,t([n.message,r,e],i)))}function M(n){function r(r,e,u){return function(){for(var i=[],o=0;o<arguments.length;o++)i[o]=arguments[o];if(!(o=_.apply(void 0,t([ft.run({value:n},(function(){return e.apply(void 0,t([n],i))})),u,n],i))).pass){if(!w(o.message))throw o.message;L("enforce/"+u+" failed with "+JSON.stringify(n))}return r}}var e={};if(!X())return R((function(n,t){e[n]=r(e,t,n)})),e;var u=new Proxy(e,{get:function(n,t){if(n=lt[t])return r(u,n,t)}});return u}function G(n){var r,s=[];return function n(a){return function(){for(var c=[],f=0;f<arguments.length;f++)c[f]=arguments[f];var l=lt[a];s.push((function(n){return _.apply(void 0,t([l.apply(void 0,t([n],c)),a,n],c))}));var p={run:function(n){return i(e(s,(function(t,e){var i,s=ft.run({value:n},(function(){return t(n)}));s.pass||e(o(!!s.pass,null!==(i=u(r,n,s.message))&&void 0!==i?i:s.message))})),o(!0))},test:function(n){return p.run(n).pass},message:function(n){return n&&(r=n),p}};return X()?p=new Proxy(p,{get:function(t,r){return lt[r]?n(r):t[r]}}):(R((function(t){p[t]=n(t)})),p)}}(n)}function q(n){var t,r={};for(t in n)r[t]=pt.optional(n[t]);return r}function B(n,t){return t=t.suiteId,{optionalFields:n.registerStateKey((function(){return{}})),suiteId:n.registerStateKey(t),testCallbacks:n.registerStateKey((function(){return{fieldCallbacks:{},doneCallbacks:[]}})),testObjects:n.registerStateKey((function(n){return{prev:n?n.current:[],current:[]}}))}}function K(n){return(n=[].concat(n))[n.length-1]}function H(){function n(){t=[0]}var t=[];return n(),{addLevel:function(){t.push(0)},cursorAt:function(){return K(t)},getCursor:function(){return[].concat(t)},next:function(){return t[t.length-1]++,K(t)},removeLevel:function(){t.pop()},reset:n}}function V(n,t){for(var r=[],e=0;e<n.length;e++){var u=n[e];N(u)?r.push(V(u,t)):(u=t(u),Kn(u)&&r.push(u))}return r}function J(n){return[].concat(n).reduce((function(n,t){return N(t)?n.concat(J(t)):[].concat(n).concat(t)}),[])}function z(n,t){var r=0;for(t=t.slice(0,-1);r<t.length;r++){var e=t[r];n[e]=i(n[e],[]),n=n[e]}return n}function Y(n){void 0===n&&(n=1);var t=[],r=function(e,u){var i=r.get(e);return i?i[1]:(u=u(),t.unshift([e.concat(),u]),f(t,n)&&(t.length=n),u)};return r.invalidate=function(n){var r=t.findIndex((function(t){var r=t[0];return c(n,r.length)&&n.every((function(n,t){return n===r[t]}))}));-1<r&&t.splice(r,1)},r.get=function(n){return t[t.findIndex((function(t){var r=t[0];return c(n,r.length)&&n.every((function(n,t){return n===r[t]}))}))]||null},r}function Q(){return ht.useX().stateRef}function Z(){(0,Q().testObjects()[1])((function(n){return{prev:n.prev,current:[].concat(n.current)}}))}function $(n){(0,Q().testObjects()[1])((function(t){return{prev:t.prev,current:[].concat(n(t.current))}}))}function nn(){return J(V(Q().testObjects()[0].current,(function(n){return n.isPending()?n:null})))}function tn(){var n=Q().testObjects()[0].current;return gt([n],(function(){return J(n)}))}function rn(){return ht.useX().testCursor.getCursor()}function en(n,t){if(n=void 0===(n=n.type)?_n.DEFAULT:n,r(t)){var e=rn();return ht.run({isolate:{type:n}},(function(){ht.useX().testCursor.addLevel(),$((function(n){return z(n,e)[K(e)]=[],n}));var n=t();return ht.useX().testCursor.removeLevel(),ht.useX().testCursor.next(),n}))}}function un(n,t){return!(!t||n.fieldName!==t)}function on(n){var t=nn();return!w(t)&&(n?t.some((function(t){return un(t,n)})):rt(t))}function sn(n,t){function r(n,t){i[n]++,u&&(i[t]=(i[t]||[]).concat(u))}var e=t.fieldName,u=t.message;n[e]=n[e]||{errorCount:0,warnCount:0,testCount:0};var i=n[e];return t.isSkipped()||(n[e].testCount++,t.isFailing()?r("errorCount","errors"):t.isWarning()&&r("warnCount","warnings")),i}function an(n,t,r){var e;void 0===r&&(r={});var u=(r=r||{}).group,i=r.fieldName;return t.reduce((function(t,r){return u&&r.groupName!==u||i&&!un(r,i)||"warnings"===n!=!!r.warns||!r.hasFailures()||(t[r.fieldName]=(t[r.fieldName]||[]).concat(r.message||[])),t}),Gn({},i&&((e={})[i]=[],e)))}function cn(n){return ln("errors",n)}function fn(n){return ln("warnings",n)}function ln(n,t){return n=an(n,tn(),{fieldName:t}),t?n[t]:n}function pn(n,t){return n=dn("errors",n,t),t?n[t]:n}function vn(n,t){return n=dn("warnings",n,t),t?n[t]:n}function dn(n,t,r){return t||L("get"+n[0].toUpperCase()+n.slice(1)+"ByGroup requires a group name. Received `"+t+"` instead."),an(n,tn(),{group:t,fieldName:r})}function hn(n,t,r){return!(!n.hasFailures()||r&&!un(n,r)||"warnings"===t!=!!n.warns)}function gn(n){return yn("errors",n)}function mn(n){return yn("warnings",n)}function yn(n,t){return tn().some((function(r){return hn(r,n,t)}))}function Nn(n,t){return En("errors",n,t)}function bn(n,t){return En("warnings",n,t)}function En(n,t,r){return tn().some((function(e){return t===e.groupName&&hn(e,n,r)}))}function Cn(){var n=tn(),t={stateRef:Q()};return mt([n],ht.bind(t,(function(){return qn(function(){var n={errorCount:0,groups:{},testCount:0,tests:{},warnCount:0};return tn().forEach((function(t){var r=t.fieldName,e=t.groupName;n.tests[r]=sn(n.tests,t),e&&(n.groups[e]=n.groups[e]||{},n.groups[e][r]=sn(n.groups[e],t))})),function(n){for(var t in n.tests)n.errorCount+=n.tests[t].errorCount,n.warnCount+=n.tests[t].warnCount,n.testCount+=n.tests[t].testCount;return n}(n)}(),{getErrors:ht.bind(t,cn),getErrorsByGroup:ht.bind(t,pn),getWarnings:ht.bind(t,fn),getWarningsByGroup:ht.bind(t,vn),hasErrors:ht.bind(t,gn),hasErrorsByGroup:ht.bind(t,Nn),hasWarnings:ht.bind(t,mn),hasWarningsByGroup:ht.bind(t,bn),isValid:ht.bind(t,(function(n){var t=Cn(),r=tn().reduce((function(n,t){return n[t.fieldName]||t.isOmitted()&&(n[t.fieldName]=!0),n}),{});return(r=!!n&&!!r[n])?n=!0:t.hasErrors(n)?n=!1:n=!(w(r=tn())||n&&w(t.tests[n])||function(n){var t=Q().optionalFields()[0];return rt(nn().filter((function(r){return!(n&&!un(r,n))&&!0!==t[r.fieldName]})))}(n))&&function(n){var t=tn(),r=Q().optionalFields()[0];return t.every((function(t){return!(!n||un(t,n))||!0===r[t.fieldName]||t.isTested()||t.isOmitted()}))}(n),n}))})})))}function On(){var n=tn(),t={stateRef:Q()};return yt([n],ht.bind(t,(function(){return qn({},Cn(),{done:ht.bind(t,Nt)})})))}function Tn(n,t,e){return!(r(n)&&(!t||e.tests[t]&&0!==e.tests[t].testCount))}function Sn(n){return!(on()&&(!n||on(n)))}function wn(n,t){var r=ht.bind({},n);(0,Q().testCallbacks()[1])((function(n){return t?n.fieldCallbacks[t]=(n.fieldCallbacks[t]||[]).concat(r):n.doneCallbacks.push(r),n}))}function Pn(n){return n.forEach((function(n){return n()}))}function xn(){var n=function(){var n={};return{emit:function(t,r){n[t]&&n[t].forEach((function(n){n(r)}))},on:function(t,r){return n[t]||(n[t]=[]),n[t].push(r),{off:function(){n[t]=n[t].filter((function(n){return n!==r}))}}}}}();return n.on(dt.TEST_COMPLETED,(function(n){if(!n.isCanceled()){n.done(),n=n.fieldName;var t=Q().testCallbacks()[0].fieldCallbacks;n&&!on(n)&&N(t[n])&&Pn(t[n]),n=Q().testCallbacks()[0].doneCallbacks,on()||Pn(n)}})),n.on(dt.SUITE_COMPLETED,(function(){!function(){var n=Q().optionalFields()[0];if(!w(n)){var t={};$((function(e){return V(e,(function(e){var u=e.fieldName;if(t.hasOwnProperty(u))t[e.fieldName]&&e.omit();else{var i=n[u];r(i)&&(t[u]=i(),t[e.fieldName]&&e.omit())}return e}))}))}}()})),n.on(dt.REMOVE_FIELD,(function(n){tn().forEach((function(t){un(t,n)&&(t.cancel(),function(n){$((function(t){return V(t,(function(t){return n!==t?t:null}))}))}(t))}))})),n}function Fn(){var n=ht.useX();return n.bus||L(),n.bus}function kn(n){return An(0,"tests",n)}function In(n){return An(1,"tests",n)}function An(n,t,r){var e=ht.useX("hook called outside of a running suite.");r&&[].concat(r).forEach((function(r){v(r)&&(e.exclusion[t][r]=0===n)}))}function Dn(n){for(var t in n)if(!0===n[t])return!0;return!1}function Ln(n){L("Wrong arguments passed to group. Group "+n+".")}function Wn(n){var t=n.asyncTest,e=n.message;if(t&&r(t.then)){var u=Fn().emit,i=Q(),o=ht.bind({stateRef:i},(function(){Z(),u(dt.TEST_COMPLETED,n)}));i=ht.bind({stateRef:i},(function(t){n.isCanceled()||(n.message=v(t)?t:e,n.fail(),o())}));try{t.then(o,i)}catch(n){i()}}}function Un(n){var t=Q().testObjects(),r=t[1],e=t[0].prev;if(w(e))return jn(n),n;if(function(n,t){return rt(n)&&!(n.fieldName===t.fieldName&&n.groupName===t.groupName)}(t=function(n){var t=rn();return z(n,t)[K(t)]}(e),n)){!function(n,t){ht.useX().isolate.type!==_n.EACH&&function(n,t){setTimeout((function(){L(n,t)}),0)}("Vest Critical Error: Tests called in different order than previous run.\n expected: "+n.fieldName+"\n received: "+t.fieldName+"\n This happens when you conditionally call your tests using if/else.\n This might lead to incorrect validation results.\n Replacing if/else with skipWhen solves these issues.")}(t,n),t=z(e,rn());var u=ht.useX().testCursor.cursorAt();t.splice(u),r((function(n){return{prev:e,current:n.current}})),t=null}return jn(n=i(t,n)),n}function jn(n){var t=rn();$((function(r){return z(r,t)[K(t)]=n,r}))}function Rn(n){var t=Un(n);if(function(n){var t=n.fieldName;n=n.groupName;var r=ht.useX();if(r.skipped)return!0;var e=(r=r.exclusion).tests,u=e[t];if(!1===u)return!0;if(u=!0===u,n){n:{var i=ht.useX().exclusion.groups;if(Object.prototype.hasOwnProperty.call(i,n))var o=!1===i[n];else{for(o in i)if(!0===i[o]){o=!0;break n}o=!1}}if(o)return!0;if(!0===r.groups[n])return!(u||!Dn(e)&&!1!==e[t])}return!u&&Dn(e)}(n))return n.skip(),ht.useX().testCursor.next(),t;if(n!==t&&t.fieldName===n.fieldName&&t.groupName===n.groupName&&t.isPending()&&t.cancel(),jn(n),ht.useX().testCursor.next(),n.isUntested()){t=Fn();var e=function(n){return ht.run({currentTest:n},(function(){try{var t=n.testFn()}catch(r){t=r,p(n.message)&&v(t)&&(n.message=r),t=!1}return!1===t&&n.fail(),t}))}(n);try{e&&r(e.then)?(n.asyncTest=e,n.setPending(),Wn(n)):t.emit(dt.TEST_COMPLETED,n)}catch(t){L("Your test function "+n.fieldName+' returned a value. Only "false" or Promise returns are supported.')}}else(t=n.asyncTest)&&r(t.then)&&(n.setPending(),Wn(n));return n}function Xn(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];r=t.reverse(),t=r[0],r=r[1];var e=ht.useX();return Rn(t=new bt(n,t,{message:r,groupName:null==e?void 0:e.groupName}))}var _n,Mn,Gn=function(){return(Gn=Object.assign||function(n){for(var t,r=1,e=arguments.length;r<e;r++)for(var u in t=arguments[r])Object.prototype.hasOwnProperty.call(t,u)&&(n[u]=t[u]);return n}).apply(this,arguments)},qn=Object.assign,Bn=a(c),Kn=a(l),Hn=a(p),Vn=a(d),Jn=a(h),zn=a(g),Yn=a(N),Qn=a(b),Zn=a(C),$n=a(O),nt=a(T),tt=a(S),rt=a(w),et=a(P),ut=a(x),it=a(v),ot=a(F),st=a(I),at=a(A),ct=a(D),ft=W((function(n,t){var r={value:n.value,meta:n.meta||{}};return t?n.set?qn(r,{parent:function(){return t?{value:t.value,meta:t.meta,parent:t.parent}:t}}):t:qn(r,{parent:U})})),lt=qn({condition:function(n,t){try{return t(n)}catch(n){return!1}},doesNotEndWith:Vn,doesNotStartWith:ct,endsWith:d,equals:h,greaterThan:m,greaterThanOrEquals:y,gt:m,gte:y,inside:b,isArray:N,isBetween:C,isBlank:O,isBoolean:T,isEmpty:w,isEven:function(n){return!!g(n)&&0==n%2},isFalsy:ot,isNaN:P,isNegative:x,isNotArray:Yn,isNotBetween:Zn,isNotBlank:$n,isNotBoolean:nt,isNotEmpty:rt,isNotNaN:et,isNotNull:Kn,isNotNumber:tt,isNotNumeric:zn,isNotString:it,isNotUndefined:Hn,isNull:l,isNumber:S,isNumeric:g,isOdd:function(n){return!!g(n)&&0!=n%2},isPositive:ut,isString:v,isTruthy:F,isUndefined:p,lengthEquals:c,lengthNotEquals:Bn,lessThan:k,lessThanOrEquals:E,longerThan:f,longerThanOrEquals:function(n,t){return n.length>=Number(t)},lt:k,lte:E,matches:I,notEquals:Jn,notInside:Qn,notMatches:st,numberEquals:A,numberNotEquals:at,shorterThan:function(n,t){return n.length<Number(t)},shorterThanOrEquals:function(n,t){return n.length<=Number(t)},startsWith:D},{allOf:function(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];return i(e(t,(function(t,r){(t=s(t,n)).pass||r(t)})),o(!0))},anyOf:function(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];return i(e(t,(function(t,r){(t=s(t,n)).pass&&r(t)})),o(!1))},noneOf:function(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];return i(e(t,(function(t,r){s(t,n).pass&&r(o(!1))})),o(!0))},oneOf:function(n){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];var e=[];return t.some((function(t){if(f(e,1))return!1;(t=s(t,n)).pass&&e.push(t)})),o(c(e,1))},optional:function(n,t){return p(n)||null===n?o(!0):s(t,n)}},{shape:function(n,t){var r=j(n,t);if(!r.pass)return r;for(var e in n)if(!Object.prototype.hasOwnProperty.call(t,e))return o(!1);return o(!0)},loose:j,isArrayOf:function(n,t){return i(e(n,(function(n,r,e){(e=ft.run({value:n,set:!0,meta:{index:e}},(function(){return s(t,n)}))).pass||r(e)})),o(!0))}}),pt=(Mn=Gn({context:function(){return ft.useX()},extend:function(n){qn(lt,n)}},{partial:q}),X()?new Proxy(qn(M,Mn),{get:function(n,t){return t in n?n[t]:lt[t]?G(t):void 0}}):(R((function(n){Mn[n]=G(n)})),Mn)),vt=function(n){return function(){return""+n++}}(0);!function(n){n[n.DEFAULT=0]="DEFAULT",n[n.SUITE=1]="SUITE",n[n.EACH=2]="EACH",n[n.SKIP_WHEN=3]="SKIP_WHEN",n[n.GROUP=4]="GROUP"}(_n||(_n={}));var dt,ht=W((function(n,t){return t?null:qn({},{isolate:{type:_n.DEFAULT},testCursor:H(),exclusion:{tests:{},groups:{}}},n)})),gt=Y(),mt=Y(20),yt=Y(20),Nt=function(){for(var n=[],t=0;t<arguments.length;t++)n[t]=arguments[t];var r=(n=n.reverse())[0];if(n=n[1],t=On(),Tn(r,n,t))return t;var e=function(){return r(Cn())};return Sn(n)?(e(),t):(wn(e,n),t)};!function(n){n.TEST_COMPLETED="test_completed",n.REMOVE_FIELD="remove_field",n.SUITE_COMPLETED="suite_completed"}(dt||(dt={})),kn.group=function(n){return An(0,"groups",n)},In.group=function(n){return An(1,"groups",n)};var bt=function(){function n(n,t,r){var e=void 0===r?{}:r;r=e.message,e=e.groupName,this.id=vt(),this.warns=!1,this.status=Et,this.fieldName=n,this.testFn=t,e&&(this.groupName=e),r&&(this.message=r)}return n.prototype.run=function(){try{var n=this.testFn()}catch(t){n=t,p(this.message)&&v(n)&&(this.message=t),n=!1}return!1===n&&this.fail(),n},n.prototype.setStatus=function(n){this.isFinalStatus()&&n!==xt||(this.status=n)},n.prototype.setPending=function(){this.setStatus(wt)},n.prototype.fail=function(){this.setStatus(this.warns?Tt:Ot)},n.prototype.done=function(){this.isFinalStatus()||this.setStatus(St)},n.prototype.warn=function(){this.warns=!0},n.prototype.isFinalStatus=function(){return this.hasFailures()||this.isCanceled()||this.isPassing()},n.prototype.skip=function(){this.isPending()||this.setStatus(Ct)},n.prototype.cancel=function(){this.setStatus(Pt),Z()},n.prototype.omit=function(){this.setStatus(xt)},n.prototype.valueOf=function(){return!this.isFailing()},n.prototype.hasFailures=function(){return this.isFailing()||this.isWarning()},n.prototype.isPending=function(){return this.status===wt},n.prototype.isTested=function(){return this.hasFailures()||this.isPassing()},n.prototype.isOmitted=function(){return this.status===xt},n.prototype.isUntested=function(){return this.status===Et},n.prototype.isFailing=function(){return this.status===Ot},n.prototype.isCanceled=function(){return this.status===Pt},n.prototype.isSkipped=function(){return this.status===Ct},n.prototype.isPassing=function(){return this.status===St},n.prototype.isWarning=function(){return this.status===Tt},n}(),Et="UNTESTED",Ct="SKIPPED",Ot="FAILED",Tt="WARNING",St="PASSING",wt="PENDING",Pt="CANCELED",xt="OMITTED",Ft=qn(Xn,{each:function(n){return function(r){return N(r)||L("test.each: Expected table to be an array."),function(e){for(var i=[],o=1;o<arguments.length;o++)i[o-1]=arguments[o];var s=(i=i.reverse())[0],a=i[1];return en({type:_n.EACH},(function(){return r.map((function(r){return r=[].concat(r),n(u.apply(void 0,t([e],r)),u.apply(void 0,t([a],r)),(function(){return s.apply(void 0,r)}))}))}))}}}(Xn),memo:function(n){var t=Y(100);return function(r){for(var e=[],u=1;u<arguments.length;u++)e[u-1]=arguments[u];u=Q().suiteId()[0];var i=ht.useX().testCursor.cursorAt(),o=(e=e.reverse())[1],s=e[2];return e=[u,r,i].concat(e[0]),null===(u=t.get(e))?t(e,(function(){return n(r,s,o)})):u[1].isCanceled()?(t.invalidate(e),t(e,(function(){return n(r,s,o)}))):Rn(u[1])}}(Xn)});n.VERSION="4.0.0-dev-31f012",n.create=function(n){r(n)||L("vest.create: Expected callback to be a function.");var t=xn(),e=function(n){function t(n,t,r){return i.references.push(),e(n,u(t,r)),function(){return[i.references[n],function(t){return e(n,u(t,i.references[n]))}]}}function e(t,e){var u=i.references[t];i.references[t]=e,r(t=o[t][1])&&t(e,u),r(n)&&n()}var i={references:[]},o=[];return{registerStateKey:function(n,r){var e=o.length;return o.push([n,r]),t(e,n)},reset:function(){var n=i.references;i.references=[],o.forEach((function(r,e){return t(e,r[0],n[e])}))}}}(),i={stateRef:B(e,{suiteId:vt()}),bus:t};return qn(ht.bind(i,(function(){for(var r=[],u=0;u<arguments.length;u++)r[u]=arguments[u];return e.reset(),en({type:_n.SUITE},(function(){n.apply(void 0,r)})),t.emit(dt.SUITE_COMPLETED),On()})),{get:ht.bind(i,Cn),reset:e.reset,remove:ht.bind(i,(function(n){t.emit(dt.REMOVE_FIELD,n)}))})},n.enforce=pt,n.group=function(n,t){v(n)||Ln("name must be a string"),r(t)||Ln("callback must be a function"),en({type:_n.GROUP},(function(){ht.run({groupName:n},t)}))},n.only=kn,n.optional=function(n){(0,Q().optionalFields()[1])((function(t){if(N(n)||v(n))[].concat(n).forEach((function(n){t[n]=!0}));else for(var r in n)t[r]=n[r];return t}))},n.skip=In,n.skipWhen=function(n,t){en({type:_n.SKIP_WHEN},(function(){ht.run({skipped:u(n)},(function(){return t()}))}))},n.test=Ft,n.warn=function(){var n=ht.useX("warn hook called outside of a running suite.");n.currentTest||L("warn called outside of a test."),n.currentTest.warn()},Object.defineProperty(n,"__esModule",{value:!0})}));
|
package/package.json
CHANGED
package/testUtils/testObjects.ts
CHANGED
|
@@ -3,10 +3,19 @@ import { useTestObjects } from 'stateHooks';
|
|
|
3
3
|
|
|
4
4
|
export function emptyTestObjects(): void {
|
|
5
5
|
const [, setTestObjects] = useTestObjects();
|
|
6
|
-
setTestObjects(() => []);
|
|
6
|
+
setTestObjects(({ prev }) => ({ prev, current: [] }));
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function setTestObjects(...args: VestTest[]): void {
|
|
10
10
|
const [, setTestObjects] = useTestObjects();
|
|
11
|
-
setTestObjects(() => [...args]);
|
|
11
|
+
setTestObjects(({ prev }) => ({ prev, current: [...args] }));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function addTestObject(addedTests: VestTest[] | VestTest): void {
|
|
15
|
+
const [, setTestObjects] = useTestObjects();
|
|
16
|
+
|
|
17
|
+
setTestObjects(({ prev, current }) => ({
|
|
18
|
+
prev,
|
|
19
|
+
current: current.concat(addedTests),
|
|
20
|
+
}));
|
|
12
21
|
}
|
package/types/classnames.d.ts
CHANGED
|
@@ -59,7 +59,7 @@ interface IDone {
|
|
|
59
59
|
/**
|
|
60
60
|
* Creates a function that returns class names that match the validation result
|
|
61
61
|
*/
|
|
62
|
-
declare function
|
|
62
|
+
declare function classnames(res: IVestResult | TDraftResult, classes?: TSupportedClasses): (fieldName: string) => string;
|
|
63
63
|
type TSupportedClasses = {
|
|
64
64
|
valid?: string;
|
|
65
65
|
tested?: string;
|
|
@@ -67,4 +67,4 @@ type TSupportedClasses = {
|
|
|
67
67
|
warning?: string;
|
|
68
68
|
untested?: string;
|
|
69
69
|
};
|
|
70
|
-
export {
|
|
70
|
+
export { classnames as default };
|
package/types/vest.d.ts
CHANGED
|
@@ -149,7 +149,14 @@ declare const baseRules: {
|
|
|
149
149
|
loose: typeof loose;
|
|
150
150
|
isArrayOf: typeof isArrayOf;
|
|
151
151
|
};
|
|
152
|
-
|
|
152
|
+
/* eslint-disable @typescript-eslint/no-namespace, @typescript-eslint/no-empty-interface */
|
|
153
|
+
declare global {
|
|
154
|
+
namespace n4s {
|
|
155
|
+
interface EnforceCustomMatchers<R> {
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
type TRules<E = Record<string, unknown>> = n4s.EnforceCustomMatchers<TRules & E> & Record<string, (...args: TArgs) => TRules & E> & {
|
|
153
160
|
[P in KCompounds]: (...args: DropFirst<Parameters<TCompounds[P]>> | TArgs) => TRules & E;
|
|
154
161
|
} & {
|
|
155
162
|
[P in KBaseRules]: (...args: DropFirst<Parameters<TBaseRules[P]>> | TArgs) => TRules & E;
|
|
@@ -288,11 +295,11 @@ declare function skip(item: TExclusionItem): void;
|
|
|
288
295
|
declare namespace skip {
|
|
289
296
|
var group: (item: TExclusionItem) => void;
|
|
290
297
|
}
|
|
298
|
+
declare function skipWhen(conditional: boolean | ((...args: any[]) => boolean), callback: (...args: any[]) => void): void;
|
|
291
299
|
/**
|
|
292
300
|
* Sets a running test to warn only mode.
|
|
293
301
|
*/
|
|
294
302
|
declare function warn(): void;
|
|
295
|
-
declare function skipWhen(conditional: boolean | ((...args: any[]) => boolean), callback: (...args: any[]) => void): void;
|
|
296
303
|
/**
|
|
297
304
|
* Runs a group callback.
|
|
298
305
|
*/
|
|
@@ -318,5 +325,5 @@ declare const _default: typeof testBase & {
|
|
|
318
325
|
};
|
|
319
326
|
};
|
|
320
327
|
declare const test: typeof _default;
|
|
321
|
-
declare const VERSION = "4.0.0-dev-
|
|
328
|
+
declare const VERSION = "4.0.0-dev-31f012";
|
|
322
329
|
export { test, create, only, skip, warn, group, optional$0 as optional, skipWhen, enforce, VERSION };
|
package/docs/.nojekyll
DELETED
|
File without changes
|
package/docs/README.md
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-

|
|
2
|
-
|
|
3
|
-
# Vest 🦺 Declarative Validation Testing
|
|
4
|
-
|
|
5
|
-

|
|
6
|
-

|
|
7
|
-
|
|
8
|
-
[](https://badge.fury.io/js/vest) [](https://travis-ci.org/ealush/vest) [](https://snyk.io/test/npm/vest)
|
|
9
|
-

|
|
10
|
-
|
|
11
|
-
[](https://discord.gg/WmADZpJnSe)
|
|
12
|
-
|
|
13
|
-
- [Documentation homepage](https://vestjs.dev)
|
|
14
|
-
- **Try vest live**
|
|
15
|
-
- [Vanilla JS Example](https://stackblitz.com/edit/vest-vanilla-support-example?file=validation.js)
|
|
16
|
-
- ReactJS Examples:
|
|
17
|
-
- [Example 1 (groups)](https://codesandbox.io/s/ecstatic-waterfall-4i2ne?file=/src/validate.js)
|
|
18
|
-
- [Example 2 (Async)](https://codesandbox.io/s/youthful-williamson-loijb?file=/src/validate.js)
|
|
19
|
-
- [Example 3](https://stackblitz.com/edit/vest-react-support-example?file=validation.js)
|
|
20
|
-
- [Example 4](https://stackblitz.com/edit/vest-react-registration?file=validate.js)
|
|
21
|
-
- [Example 5 (Password validator)](https://codesandbox.io/s/password-validator-example-6puvy?file=/src/validate.js)
|
|
22
|
-
- [VueJS Example](https://codesandbox.io/s/vest-vue-example-1j6r8?file=/src/validations.js)
|
|
23
|
-
- [Svelte Example](https://codesandbox.io/s/vestdocssvelteexample-k87t7?file=/validate.js)
|
|
24
|
-
|
|
25
|
-
## Tutorials
|
|
26
|
-
|
|
27
|
-
[Step By Step React Tutorial](https://dev.to/ealush/dead-simple-form-validation-with-vest-5gf8)
|
|
28
|
-
|
|
29
|
-
## [Release Notes](https://github.com/ealush/vest/releases)
|
|
30
|
-
|
|
31
|
-
## 🦺 What is Vest?
|
|
32
|
-
|
|
33
|
-
Vest is a validations library for JS apps that derives its syntax from modern JS unit testing frameworks such as Mocha or Jest. It is easy to learn due to its use of already common declarative patterns.
|
|
34
|
-
It works great with user-input validation and with validating upon user interaction to provide the best possible user experience.
|
|
35
|
-
|
|
36
|
-
The idea behind Vest is that your validations can be described as a 'spec' or a contract that reflects your form or feature structure. Your validations run in production, and they are framework agnostic - meaning Vest works well with React, Angular, Vue, or even without a framework at all.
|
|
37
|
-
|
|
38
|
-
Using Vest for form validation can reduce bloat, improve feature readability and maintainability.
|
|
39
|
-
|
|
40
|
-
**Basic Example**
|
|
41
|
-

|
|
42
|
-
|
|
43
|
-
**Memoized async test**
|
|
44
|
-

|
|
45
|
-
|
|
46
|
-
## ✅ Motivation
|
|
47
|
-
|
|
48
|
-
Writing forms is an integral part of building web apps, and even though it may seem trivial at first - as your feature grows over time, so does your validation logic grows in complexity.
|
|
49
|
-
|
|
50
|
-
Vest tries to remediate this by separating validation logic from feature logic so it is easier to maintain over time and refactor when needed.
|
|
51
|
-
|
|
52
|
-
## ✨ Vest's features
|
|
53
|
-
|
|
54
|
-
- 🎨 Framework agnostic (BYOUI)
|
|
55
|
-
- ⚡️ Rich, extendable, assertions library (enforce) ([doc](http://vestjs.dev/#/enforce))
|
|
56
|
-
- 🚥 Multiple validations for the same field
|
|
57
|
-
- ⚠️ Warning (non failing) tests ([doc](http://vestjs.dev/#/warn))
|
|
58
|
-
- 📝 Validate only the fields the user interacted with ([doc](http://vestjs.dev/#/exclusion))
|
|
59
|
-
- ⏳ Memoize async validations to reduce calls to the server ([doc](http://vestjs.dev/#/test?id=testmemo-for-memoized-tests))
|
|
60
|
-
- 🚦 Test grouping ([doc](http://vestjs.dev/#/group))
|
|
61
|
-
|
|
62
|
-
## Example code ([Run in sandbox](https://codesandbox.io/s/vest-react-tutorial-finished-ztt8t?file=/src/validate.js))
|
|
63
|
-
|
|
64
|
-
```js
|
|
65
|
-
import { create, only, test, enforce, warn } from 'vest';
|
|
66
|
-
|
|
67
|
-
export default create((data = {}, currentField) => {
|
|
68
|
-
only(currentField);
|
|
69
|
-
|
|
70
|
-
test('username', 'Username is required', () => {
|
|
71
|
-
enforce(data.username).isNotEmpty();
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test('username', 'Username is too short', () => {
|
|
75
|
-
enforce(data.username).longerThanOrEquals(3);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test('password', 'Password is required', () => {
|
|
79
|
-
enforce(data.password).isNotEmpty();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test('password', 'Password must be at least 6 chars long', () => {
|
|
83
|
-
enforce(data.password).longerThanOrEquals(6);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test('password', 'Password is weak, Maybe add a number?', () => {
|
|
87
|
-
warn();
|
|
88
|
-
enforce(data.password).matches(/[0-9]/);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test('email', 'Email Address is not valid', () => {
|
|
92
|
-
enforce(data.email).isEmail();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test('tos', () => {
|
|
96
|
-
enforce(data.tos).isTruthy();
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Why Vest?
|
|
102
|
-
|
|
103
|
-
- 🧠 Vest is really easy to learn. You can take your existing knowledge of unit tests and transfer it to validations.
|
|
104
|
-
- ✏️ Vest takes into account user interaction and warn only validations.
|
|
105
|
-
- 🧱 Your validations are structured, making it very simple to read and write. All validation files look the same.
|
|
106
|
-
- 🖇 Your validation logic is separate from your feature logic, preventing the spaghetti code that's usually involved with writing validations.
|
|
107
|
-
- 🧩 Validation logic is easy to share and reuse across features.
|
package/docs/_assets/favicon.ico
DELETED
|
Binary file
|
|
Binary file
|
package/docs/_sidebar.md
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
- [Getting Started](./getting_started)
|
|
2
|
-
- [enforce](./enforce)
|
|
3
|
-
- [The result object](./result)
|
|
4
|
-
- [test](./test)
|
|
5
|
-
- [How to fail a test](./test#failing_a_test)
|
|
6
|
-
- [Warn only tests](./warn)
|
|
7
|
-
- [Grouping tests](./group)
|
|
8
|
-
- [Optional Tests](./optional)
|
|
9
|
-
- Advanced cases
|
|
10
|
-
- [Cross Field Validations](./cross_field_validations)
|
|
11
|
-
- [Excluding or including tests](./exclusion)
|
|
12
|
-
- [Using with node](./node)
|
|
13
|
-
- [Utilities](./utilities)
|
|
14
|
-
- [Migration Guides](./migration)
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# Cross Field Validations
|
|
2
|
-
|
|
3
|
-
Sometimes it is not enough to only validate a field by itself, because its validity is dependant on the validity or invalidity of a different field.
|
|
4
|
-
|
|
5
|
-
Take for example the password confirmation field, by itself it serves no purpose, and as long as the password itself is not field, you might choose to not validate it to begin with. That's an **AND** relationship between fields. There can also be an **OR** relationship between fields, for example - either email address or phone number have to be filled, but neither is required as long the other was filled by the user.
|
|
6
|
-
|
|
7
|
-
All these cases can be easily handled with Vest in different ways, depending on your requirements and validation strategy.
|
|
8
|
-
|
|
9
|
-
## skipWhen for conditionally skipping a test
|
|
10
|
-
|
|
11
|
-
Sometimes you might want to skip running a certain validation based on some criteria, for example - only test for password strength if password DOESN'T have Errors. You could access the intermediate validation result and use it mid-run.
|
|
12
|
-
|
|
13
|
-
```js
|
|
14
|
-
import { create, test, enforce } from 'vest';
|
|
15
|
-
|
|
16
|
-
const suite = create((data = {}) => {
|
|
17
|
-
test('password', 'Password is required', () => {
|
|
18
|
-
enforce(data.password).isNotEmpty();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
skipWhen(suite.get().hasErrors('password'), () => {
|
|
22
|
-
test('password', 'Password is weak', () => {
|
|
23
|
-
enforce(data.password).longerThan(8);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
export default suite;
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Optional tests
|
|
31
|
-
|
|
32
|
-
By default, all the tests inside Vest are required in order for the suite to be considered as "valid". Sometimes your app's logic may allow tests not to be filled out and you want them not to be accounted for in the suites validity. The optional utility allows you to specify logic to determine if a test is optional or not, for example - if it depends on a different test.
|
|
33
|
-
|
|
34
|
-
Read more in the [optional tests doc](./optional).
|
package/docs/enforce.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Enforce
|
|
2
|
-
|
|
3
|
-
Enforce is Vest's assertion library. It is used to validate values within, or outside of a Vest test.
|
|
4
|
-
|
|
5
|
-
```js
|
|
6
|
-
import { enforce, test } from 'vest';
|
|
7
|
-
|
|
8
|
-
test('username', 'Must be at least three characters long', () => {
|
|
9
|
-
enforce(username).longerThan(2);
|
|
10
|
-
});
|
|
11
|
-
```
|
package/docs/exclusion.md
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
# Excluding and including tests
|
|
2
|
-
|
|
3
|
-
When performing validations in real world-scenarios, you may need to only run tests of a single field in your suite, or skip certain tests according to some logic. That's why Vest includes `skip()` and `only()`.
|
|
4
|
-
|
|
5
|
-
`skip()` and `only()` are functions that take a name of the test, or a list of names to either include or exclude fields from being validated. They should be called from the body of suite callback, and in order for them to take effect, they should be called before anything else.
|
|
6
|
-
|
|
7
|
-
!> **NOTE** When using `only()` or `skip()` you must place them before any of the tests defined in the suite. Hooks run in order of appearance, which means that if you place your `skip` hook after the field you're skipping - it won't have any effect.
|
|
8
|
-
|
|
9
|
-
### Only running specific tests (including)
|
|
10
|
-
|
|
11
|
-
When validating upon user interactions, you will usually want to only validate the input the user currently interacts with to prevent errors appearing in unrelated places. For this, you can use `only()` with the name of the test currently being validated.
|
|
12
|
-
|
|
13
|
-
In the example below, we're assuming the argument `fieldName` is being populated with the name of the field we want to test. If none is passed, the call to `only` will be ignored, and all tests will run as usual. This allows us to test each field at a time during the interaction, but test all on form submission.
|
|
14
|
-
|
|
15
|
-
```js
|
|
16
|
-
import { create, enforce, test, only } from 'vest';
|
|
17
|
-
|
|
18
|
-
const suite = create((data, fieldName) => {
|
|
19
|
-
only(fieldName);
|
|
20
|
-
|
|
21
|
-
test('username', 'Username is invalid', () => {
|
|
22
|
-
/* some validation logic*/
|
|
23
|
-
});
|
|
24
|
-
test('email', 'Email is invalid', () => {
|
|
25
|
-
/* some validation logic*/
|
|
26
|
-
});
|
|
27
|
-
test('password', 'Password is invalid', () => {
|
|
28
|
-
/* some validation logic*/
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
const validationResult = suite(formData, changedField);
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Skipping tests
|
|
36
|
-
|
|
37
|
-
There are not many cases for skipping tests, but they do exist. For example, when you wish to prevent validation of a promo code when none provided.
|
|
38
|
-
|
|
39
|
-
In this case, and in similar others, you can use `skip()`. When called, it will only skip the specified fields, all other tests will run as they should.
|
|
40
|
-
|
|
41
|
-
```js
|
|
42
|
-
import { create, enforce, test, skip } from 'vest';
|
|
43
|
-
|
|
44
|
-
const suite = create(data => {
|
|
45
|
-
if (!data.promo) skip('promo');
|
|
46
|
-
|
|
47
|
-
// this test won't run when data.promo is falsy.
|
|
48
|
-
test('promo', 'Promo code is invalid', () => {
|
|
49
|
-
/* some validation logic*/
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const validationResult = suite(formData);
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## skipWhen: Conditionally excluding portions of the suite
|
|
57
|
-
|
|
58
|
-
In some cases we might need to skip a test or a group based on a given condition, for example - based on the intermediate state of the currently running suite. To allow this, can use `skipWhen`. `skipWhen` takes a boolean expression and a callback with tests.
|
|
59
|
-
If the expression is true, the tests within the callback will be skipped. Otherwise, the tests will run as normal.
|
|
60
|
-
|
|
61
|
-
In the following example we're skipping the server side verification of the username if the username is invalid to begin with:
|
|
62
|
-
|
|
63
|
-
```js
|
|
64
|
-
import { create, test, enforce } from 'vest';
|
|
65
|
-
|
|
66
|
-
const suite = create((data = {}) => {
|
|
67
|
-
test('username', 'Username is required', () => {
|
|
68
|
-
enforce(data.username).isNotEmpty();
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
skipWhen(suite.get().hasErrors('username'), () => {
|
|
72
|
-
test('username', 'Username already exists', () => {
|
|
73
|
-
// this is an example for a server call
|
|
74
|
-
return doesUserExist(data.username);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
export default suite;
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
!> **Note** Using suite.get() within the suite runs returns a **DRAFT** result. This means that it may not contain the final validation result.
|
|
82
|
-
|
|
83
|
-
## Including and excluding groups of tests
|
|
84
|
-
|
|
85
|
-
Similar to the way you use `skip` and `only` to include and exclude tests, you can use `skip.group` and `only.group` to exclude and include whole groups.
|
|
86
|
-
|
|
87
|
-
These two functions are very powerful and give you control of whole portions of your suite at once.
|
|
88
|
-
|
|
89
|
-
```js
|
|
90
|
-
import { create, test, group, enforce, skip } from 'vest';
|
|
91
|
-
|
|
92
|
-
create(data => {
|
|
93
|
-
skip.group(data.userExists ? 'signUp' : 'signIn');
|
|
94
|
-
|
|
95
|
-
test('userName', "Can't be empty", () => {
|
|
96
|
-
enforce(data.username).isNotEmpty();
|
|
97
|
-
});
|
|
98
|
-
test('password', "Can't be empty", () => {
|
|
99
|
-
enforce(data.password).isNotEmpty();
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
group('signIn', () => {
|
|
103
|
-
test(
|
|
104
|
-
'userName',
|
|
105
|
-
'User not found. Please check if you typed it correctly.',
|
|
106
|
-
findUserName(data.username)
|
|
107
|
-
);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
group('signUp', () => {
|
|
111
|
-
test('email', 'Email already registered', isEmailRegistered(data.email));
|
|
112
|
-
|
|
113
|
-
test('age', 'You must be at least 18 years old to join', () => {
|
|
114
|
-
enforce(data.age).largerThanOrEquals(18);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Things to know about how these functions work:
|
|
121
|
-
|
|
122
|
-
**only.group()**:
|
|
123
|
-
When using `only.group`, other groups won't be tested - but top level tests that aren't nested in any groups will. The reasoning is that the top level space is a shared are that will always be executed. If you want only your group to run, nest everything else under groups as well.
|
|
124
|
-
|
|
125
|
-
If you combine `only.group` with `skip`, if you skip a field inside a group that is included, that field will be excluded during this run regardless of its group membership.
|
|
126
|
-
|
|
127
|
-
**skip.group()**
|
|
128
|
-
|
|
129
|
-
If you combine `skip.group` with `only` your included field declared within the skipped tests will be ignored.
|
package/docs/getting_started.md
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# Installation
|
|
2
|
-
|
|
3
|
-
To install the stable version of Vest:
|
|
4
|
-
|
|
5
|
-
```
|
|
6
|
-
npm install vest
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
You can also add Vest directly as a script tag to your page:
|
|
10
|
-
|
|
11
|
-
```html
|
|
12
|
-
<script src="https://unpkg.com/vest@4"></script>
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Vest tests are very much like unit tests, with only slight differences. Instead of using `describe/it/expect`, you will use `validate/[test](./test)/[enforce](./enforce)`.
|
|
16
|
-
|
|
17
|
-
- `test`: A single validation unit, validating a field or a single value. It takes the name of the field being validated, a failure message (to display to the user), and a callback function that contains the validation logic. [Read more about test].
|
|
18
|
-
- `enforce`: This is our assertion function. We’ll use it to make sure our validations pass. [Read more about enforce].
|
|
19
|
-
|
|
20
|
-
## Writing tests
|
|
21
|
-
|
|
22
|
-
First, you need to initialize your validation suite using `create()`. This initializes your validation suite state and allows validation results to be merged with future validations.
|
|
23
|
-
|
|
24
|
-
```js
|
|
25
|
-
import { create } from 'vest';
|
|
26
|
-
|
|
27
|
-
const suite = create(() => {
|
|
28
|
-
// validation suite content goes here.
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const validationResult = suite();
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
`create()` takes a callback that contains your tests, and returns a "suite" function which runs your validation suite. All the arguments you pass to it are being forwarded to your tests callback. You can use it to pass form data to your validation, excluded fields, and anything required for during your validation runtime.
|
|
35
|
-
|
|
36
|
-
A simple validation suite would look somewhat like this:
|
|
37
|
-
|
|
38
|
-
```js
|
|
39
|
-
// suite.js
|
|
40
|
-
import { create, test, enforce } from ‘vest’;
|
|
41
|
-
|
|
42
|
-
const suite = create((formData) => {
|
|
43
|
-
test('username', 'Must be between 2 and 10 chars', () => {
|
|
44
|
-
enforce(formData.username)
|
|
45
|
-
.longerThanOrEquals(2)
|
|
46
|
-
.shorterThan(10);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test('password', 'Must contain at least one digit', () => {
|
|
50
|
-
enforce(formData.password)
|
|
51
|
-
.matches(/(?=.*[0-9])/);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
export default suite;
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
```js
|
|
59
|
-
// myFeature.js
|
|
60
|
-
|
|
61
|
-
import suite from './suite.js';
|
|
62
|
-
|
|
63
|
-
const res = suite(formData);
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
In the above example, we validate a form containing username and a password.
|
|
67
|
-
|
|
68
|
-
**Read next about:**
|
|
69
|
-
|
|
70
|
-
- [Vest's result object](./result).
|
|
71
|
-
- [Using the test function](./test).
|
|
72
|
-
- [Asserting with enforce](./enforce).
|