wrapito 13.5.0-beta9 → 13.5.0

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/dist/index.cjs CHANGED
@@ -1,18 +1,18 @@
1
- "use strict";var ye=Object.create;var O=Object.defineProperty;var Re=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var we=Object.getPrototypeOf,ke=Object.prototype.hasOwnProperty;var xe=(e,t)=>{for(var n in t)O(e,n,{get:t[n],enumerable:!0})},N=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of be(t))!ke.call(e,r)&&r!==n&&O(e,r,{get:()=>t[r],enumerable:!(s=Re(t,r))||s.enumerable});return e};var E=(e,t,n)=>(n=e!=null?ye(we(e)):{},N(t||!e||!e.__esModule?O(n,"default",{value:e,enumerable:!0}):n,e)),Ie=e=>N(O({},"__esModule",{value:!0}),e);var at={};xe(at,{assertions:()=>ot,configure:()=>Me,getConfig:()=>m,matchers:()=>ot,wrap:()=>He});module.exports=Ie(at);var K=E(require("react"),1);var h=E(require("chalk"),1);var W=E(require("object-hash"),1);var j=require("@testing-library/react"),A={defaultHost:"",extend:{},mount:j.render,changeRoute:e=>window.history.replaceState(null,"",e)};function Me(e){A={...A,...e}}var m=()=>({...A});var $=e=>t=>{let{method:n="GET",path:s,host:r=m().defaultHost,requestBody:o=void 0,catchParams:a}=t,l=r+s,i=!m().handleQueryParams||a,u=(0,W.default)({url:i?l:l.split("?")[0],method:n.toUpperCase(),requestBody:o}),c;return o!==void 0&&"_bodyInit"in e&&e._bodyInit!==void 0&&(c=JSON.parse(e._bodyInit)),(0,W.default)({url:i?e.url:e.url.split("?")[0],method:e.method,requestBody:c})===u};var _=async()=>{let e={json:()=>Promise.resolve(),status:200,ok:!0,headers:new Headers({"Content-Type":"application/json"})};return Promise.resolve(e)},Te=e=>{let{streamBody:t,status:n=200,headers:s={}}=e;return{body:t,status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"text/event-stream",...s})}},Oe=e=>{let{responseBody:t,status:n=200,headers:s={}}=e;return{json:()=>Promise.resolve(t),status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"application/json",...s})}},L=async e=>{let t=e.streamBody?Te(e):Oe(e);return e.delay?new Promise(n=>setTimeout(()=>n(t),e.delay)):Promise.resolve(t)},Ee=e=>console.warn(`
2
- ${h.default.white.bold.bgRed("wrapito")} ${h.default.redBright.bold("cannot find any mock matching:")}
3
- ${h.default.greenBright(`URL: ${e.url}`)}
4
- ${h.default.greenBright(`METHOD: ${e.method?.toLowerCase()}`)}
5
- ${h.default.greenBright(`REQUEST BODY: ${e._bodyInit}`)}
6
- `),F=async(e,t,n)=>{let s=e.find($(t));if(!s)return n&&Ee(t),_();let{multipleResponses:r}=s;if(!r)return L(s);let o=r.find(a=>!a.hasBeenReturned);if(!o){n&&qe(s);return}return o.hasBeenReturned=!0,L(o)},G=(e=[],t=!1)=>{global.fetch.mockImplementation((s,r)=>{if(typeof s=="string"){let a=new Request(s,r);return F(e,a,t)}return F(e,s,t)})},qe=e=>{let t=`\u{1F32F} Wrapito: Missing response in the multipleResponses array for path ${e.path} and method ${e.method}.`,n=h.default.greenBright(t);console.warn(n)},V=e=>{let t=global.fetch.getMockImplementation();global.fetch.mockImplementation((n,s)=>{let r=typeof n=="string"?n:n.url,o=s?.method||(typeof n!="string"?n.method:"GET");return console.warn(`
7
- ${h.default.white.bold.bgYellow(" \u{1F32F} wrapito ")}
8
- ${h.default.yellowBright.bold("\u26A0\uFE0F pending request detected after test finished:")}
9
- ${h.default.greenBright(`URL: ${r}`)}
10
- ${h.default.greenBright(`METHOD: ${o?.toLowerCase()}`)}
11
- ${e?` ${h.default.greenBright(`TEST: ${e}`)}
12
- `:""}`),t?t(n,s):_()})};var S,y=e=>{S={...S,...e}},R=()=>({...S});function q(e,t){if(!e)throw new Error(t)}function k(e,t){return typeof t===e}function Ce(e){return e instanceof Promise}function v(e,t,n){Object.defineProperty(e,t,n)}function x(e,t,n){Object.defineProperty(e,t,{value:n})}var M=Symbol.for("tinyspy:spy"),Pe=new Set,Ue=e=>{e.called=!1,e.callCount=0,e.calls=[],e.results=[],e.next=[]},Ae=e=>(v(e,M,{value:{reset:()=>Ue(e[M])}}),e[M]),C=e=>e[M]||Ae(e);function We(e){q(k("function",e)||k("undefined",e),"cannot spy on a non-function value");let t=function(...s){let r=C(t);r.called=!0,r.callCount++,r.calls.push(s);let o=r.next.shift();if(o){r.results.push(o);let[u,c]=o;if(u==="ok")return c;throw c}let a,l="ok";if(r.impl)try{new.target?a=Reflect.construct(r.impl,s,new.target):a=r.impl.apply(this,s),l="ok"}catch(u){throw a=u,l="error",r.results.push([l,u]),u}let i=[l,a];if(Ce(a)){let u=a.then(c=>i[1]=c).catch(c=>{throw i[0]="error",i[1]=c,c});Object.assign(u,a),a=u}return r.results.push(i),a};x(t,"_isMockFunction",!0),x(t,"length",e?e.length:0),x(t,"name",e&&e.name||"spy");let n=C(t);return n.reset(),n.impl=e,t}var J=(e,t)=>Object.getOwnPropertyDescriptor(e,t),Q=(e,t)=>{t!=null&&typeof t=="function"&&t.prototype!=null&&Object.setPrototypeOf(e.prototype,t.prototype)};function Y(e,t,n){q(!k("undefined",e),"spyOn could not find an object to spy upon"),q(k("object",e)||k("function",e),"cannot spyOn on a primitive value");let[s,r]=(()=>{if(!k("object",t))return[t,"value"];if("getter"in t&&"setter"in t)throw new Error("cannot spy on both getter and setter");if("getter"in t)return[t.getter,"get"];if("setter"in t)return[t.setter,"set"];throw new Error("specify getter or setter to spy on")})(),o=J(e,s),a=Object.getPrototypeOf(e),l=a&&J(a,s),i=o||l;q(i||s in e,`${String(s)} does not exist`);let u=!1;r==="value"&&i&&!i.value&&i.get&&(r="get",u=!0,n=i.get());let c;i?c=i[r]:r!=="value"?c=()=>e[s]:c=e[s],n||(n=c);let d=We(n);r==="value"&&Q(d,c);let p=f=>{let{value:I,...U}=i||{configurable:!0,writable:!0};r!=="value"&&delete U.writable,U[r]=f,v(e,s,U)},b=()=>i?v(e,s,i):p(c),g=d[M];return x(g,"restore",b),x(g,"getOriginal",()=>u?c():c),x(g,"willCall",f=>(g.impl=f,d)),p(u?()=>(Q(d,n),d):d),Pe.add(d),d}var ve=new Set,Be=0;function De(e){let t=e,n,s=[],r=[],o=C(e),a={get calls(){return o.calls},get instances(){return s},get invocationCallOrder(){return r},get results(){return o.results.map(([p,b])=>({type:p==="error"?"throw":"return",value:b}))},get lastCall(){return o.calls[o.calls.length-1]}},l=[],i=!1;function u(...p){return s.push(this),r.push(++Be),(i?n:l.shift()||n||o.getOriginal()||(()=>{})).apply(this,p)}let c=t.name;t.getMockName=()=>c||"vi.fn()",t.mockName=p=>(c=p,t),t.mockClear=()=>(o.reset(),s=[],r=[],t),t.mockReset=()=>(t.mockClear(),n=()=>{},l=[],t),t.mockRestore=()=>(t.mockReset(),o.restore(),n=void 0,t),t.getMockImplementation=()=>n,t.mockImplementation=p=>(n=p,o.willCall(u),t),t.mockImplementationOnce=p=>(l.push(p),t);function d(p,b){let g=n;n=p,o.willCall(u),i=!0;let f=()=>{n=g,i=!1},I=b();return I instanceof Promise?I.then(()=>(f(),t)):(f(),t)}return t.withImplementation=d,t.mockReturnThis=()=>t.mockImplementation(function(){return this}),t.mockReturnValue=p=>t.mockImplementation(()=>p),t.mockReturnValueOnce=p=>t.mockImplementationOnce(()=>p),t.mockResolvedValue=p=>t.mockImplementation(()=>Promise.resolve(p)),t.mockResolvedValueOnce=p=>t.mockImplementationOnce(()=>Promise.resolve(p)),t.mockRejectedValue=p=>t.mockImplementation(()=>Promise.reject(p)),t.mockRejectedValueOnce=p=>t.mockImplementationOnce(()=>Promise.reject(p)),Object.defineProperty(t,"mock",{get:()=>a}),o.willCall(u),ve.add(t),t}var z=e=>De(Y({spy:e||(()=>{})},"spy"));beforeEach(()=>{global.fetch=z()});afterEach(()=>{let{warnOnPendingRequests:e}=m();if(e){let t=expect.getState?.()?.currentTestName;V(t)}});var He=e=>(y({Component:e,responses:[],props:{},path:"",hasPath:!1,interactionConfig:void 0,debug:process.env.npm_config_debugRequests==="true"}),w()),w=()=>{let e=Le();return{withProps:Ge,withNetwork:Je,withStreamingNetwork:_e,withInteraction:Ve,atPath:Qe,debugRequests:Ye,mount:Xe,...e}},Ne=e=>{let t=R(),n=[...t.responses,...e];y({...t,responses:n})},je=(e,t)=>(t({addResponses:Ne},e),w()),$e=(e,t)=>{let{extend:n}=m(),s=n[t];return{...e,[t]:(...r)=>je(r,s)}},Le=()=>{let{extend:e}=m();return Object.keys(e).reduce($e,{})},Fe=(e,t,n)=>{let s=new TextEncoder;return new ReadableStream({async start(r){for(let o of e){let a=typeof o=="string"?o:o.text,l=typeof o=="object"&&o.delay!==void 0?o.delay:t;l>0&&await new Promise(i=>setTimeout(i,l)),r.enqueue(s.encode(a))}n||r.close()}})},_e=e=>{let{path:t,host:n,method:s="GET",chunks:r,delayBetweenChunks:o=0,keepOpen:a=!1}=e,l=R();return y({...l,responses:[...l.responses,{path:t,host:n,method:s,streamBody:Fe(r,o,a)}]}),w()},Ge=e=>{let t=R();return y({...t,props:e}),w()},Ve=e=>{let t=R();return y({...t,interactionConfig:e}),w()},Je=(e=[])=>{let t=R(),n=Array.isArray(e)?e:[e];return y({...t,responses:[...t.responses,...n]}),w()},Qe=(e,t)=>{let n=R();return y({...n,historyState:t,path:e,hasPath:!0}),w()},Ye=()=>{let e=R();return y({...e,debug:!0}),w()},ze=e=>{let{defaultResponses:t=[]}=m();return[...e,...t]},Ke=(e,t,n,s,r)=>{if(e){if(s){console.warn("wrapito WARNING: history is DEPRECATED. Pass a changeRoute function to the config instead."),console.warn("Read about changeRoute in: https://github.com/mercadona/wrapito#changeRoute"),s.push(t,n);return}r(t)}},Xe=()=>{let{portal:e,portals:t,changeRoute:n,history:s,mount:r,interaction:o}=m(),{Component:a,props:l,responses:i,path:u,hasPath:c,debug:d,historyState:p,interactionConfig:b}=R(),g=a;e&&X(e),t&&Ze(t),Ke(c,u,p,s,n),G(ze(i),d);let f=r(K.createElement(g,{...l}));if(o){let I=o.setup?o.setup(o.userLib,b):o.userLib;return{...f,user:I}}return{...f,user:void 0}},X=e=>{if(document.getElementById(e))return;let t=document.createElement("div");t.setAttribute("id",e),t.setAttribute("data-testid",e),document.body.appendChild(t)},Ze=e=>{e.forEach(t=>{X(t)})};var B=require("jest-diff"),D=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t?.host}${e} ain't got called`:`\u{1F32F} Wrapito: ${e} ain't got called`;return{pass:!1,message:()=>n}},Z=(e,t,n)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: ${e} is called ${n} times, you expected ${t} times`}),ee=(e,t)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch method does not match, expected ${e} received ${t??"none"}`}),te=(e,t)=>{let n=t.map(s=>(0,B.diff)(e,s)).join(`
1
+ "use strict";var ye=Object.create;var O=Object.defineProperty;var Re=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var we=Object.getPrototypeOf,ke=Object.prototype.hasOwnProperty;var xe=(e,t)=>{for(var n in t)O(e,n,{get:t[n],enumerable:!0})},j=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of be(t))!ke.call(e,s)&&s!==n&&O(e,s,{get:()=>t[s],enumerable:!(r=Re(t,s))||r.enumerable});return e};var E=(e,t,n)=>(n=e!=null?ye(we(e)):{},j(t||!e||!e.__esModule?O(n,"default",{value:e,enumerable:!0}):n,e)),Ie=e=>j(O({},"__esModule",{value:!0}),e);var ct={};xe(ct,{assertions:()=>it,configure:()=>Me,createStreamController:()=>_e,getConfig:()=>m,matchers:()=>it,wrap:()=>He});module.exports=Ie(ct);var K=E(require("react"),1);var g=E(require("chalk"),1);var P=E(require("object-hash"),1);var $=require("@testing-library/react"),U={defaultHost:"",extend:{},mount:$.render,changeRoute:e=>window.history.replaceState(null,"",e)};function Me(e){U={...U,...e}}var m=()=>({...U});var L=e=>t=>{let{method:n="GET",path:r,host:s=m().defaultHost,requestBody:o=void 0,catchParams:a}=t,p=s+r,i=!m().handleQueryParams||a,l=(0,P.default)({url:i?p:p.split("?")[0],method:n.toUpperCase(),requestBody:o}),c;return o!==void 0&&"_bodyInit"in e&&e._bodyInit!==void 0&&(c=JSON.parse(e._bodyInit)),(0,P.default)({url:i?e.url:e.url.split("?")[0],method:e.method,requestBody:c})===l};var _=async()=>{let e={json:()=>Promise.resolve(),status:200,ok:!0,headers:new Headers({"Content-Type":"application/json"})};return Promise.resolve(e)},Te=e=>{let{streamBody:t,status:n=200,headers:r={}}=e;return{body:t,status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"text/event-stream",...r})}},Oe=e=>{let{responseBody:t,status:n=200,headers:r={}}=e;return{json:()=>Promise.resolve(t),status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"application/json",...r})}},W=async e=>{let t=e.streamBody?Te(e):Oe(e);return e.delay?new Promise(n=>setTimeout(()=>n(t),e.delay)):Promise.resolve(t)},Ee=e=>console.warn(`
2
+ ${g.default.white.bold.bgRed("wrapito")} ${g.default.redBright.bold("cannot find any mock matching:")}
3
+ ${g.default.greenBright(`URL: ${e.url}`)}
4
+ ${g.default.greenBright(`METHOD: ${e.method?.toLowerCase()}`)}
5
+ ${g.default.greenBright(`REQUEST BODY: ${e._bodyInit}`)}
6
+ `),F=async(e,t,n)=>{let r=L(t),s=e.find(p=>r(p)&&!(p.streamBody&&p.hasBeenReturned));if(!s)return n&&Ee(t),_();if(s.streamBody)return s.hasBeenReturned=!0,W(s);let{multipleResponses:o}=s;if(!o)return W(s);let a=o.find(p=>!p.hasBeenReturned);if(!a){n&&qe(s);return}return a.hasBeenReturned=!0,W(a)},G=(e=[],t=!1)=>{global.fetch.mockImplementation((r,s)=>{if(typeof r=="string"){let a=new Request(r,s);return F(e,a,t)}return F(e,r,t)})},qe=e=>{let t=`\u{1F32F} Wrapito: Missing response in the multipleResponses array for path ${e.path} and method ${e.method}.`,n=g.default.greenBright(t);console.warn(n)},V=e=>{let t=global.fetch.getMockImplementation();global.fetch.mockImplementation((n,r)=>{let s=typeof n=="string"?n:n.url,o=r?.method||(typeof n!="string"?n.method:"GET");return console.warn(`
7
+ ${g.default.white.bold.bgYellow(" \u{1F32F} wrapito ")}
8
+ ${g.default.yellowBright.bold("\u26A0\uFE0F pending request detected after test finished:")}
9
+ ${g.default.greenBright(`URL: ${s}`)}
10
+ ${g.default.greenBright(`METHOD: ${o?.toLowerCase()}`)}
11
+ ${e?` ${g.default.greenBright(`TEST: ${e}`)}
12
+ `:""}`),t?t(n,r):_()})};var B,y=e=>{B={...B,...e}},R=()=>({...B});function q(e,t){if(!e)throw new Error(t)}function k(e,t){return typeof t===e}function Ce(e){return e instanceof Promise}function v(e,t,n){Object.defineProperty(e,t,n)}function x(e,t,n){Object.defineProperty(e,t,{value:n})}var M=Symbol.for("tinyspy:spy"),Ae=new Set,Se=e=>{e.called=!1,e.callCount=0,e.calls=[],e.results=[],e.next=[]},Ue=e=>(v(e,M,{value:{reset:()=>Se(e[M])}}),e[M]),C=e=>e[M]||Ue(e);function Pe(e){q(k("function",e)||k("undefined",e),"cannot spy on a non-function value");let t=function(...r){let s=C(t);s.called=!0,s.callCount++,s.calls.push(r);let o=s.next.shift();if(o){s.results.push(o);let[l,c]=o;if(l==="ok")return c;throw c}let a,p="ok";if(s.impl)try{new.target?a=Reflect.construct(s.impl,r,new.target):a=s.impl.apply(this,r),p="ok"}catch(l){throw a=l,p="error",s.results.push([p,l]),l}let i=[p,a];if(Ce(a)){let l=a.then(c=>i[1]=c).catch(c=>{throw i[0]="error",i[1]=c,c});Object.assign(l,a),a=l}return s.results.push(i),a};x(t,"_isMockFunction",!0),x(t,"length",e?e.length:0),x(t,"name",e&&e.name||"spy");let n=C(t);return n.reset(),n.impl=e,t}var J=(e,t)=>Object.getOwnPropertyDescriptor(e,t),Q=(e,t)=>{t!=null&&typeof t=="function"&&t.prototype!=null&&Object.setPrototypeOf(e.prototype,t.prototype)};function Y(e,t,n){q(!k("undefined",e),"spyOn could not find an object to spy upon"),q(k("object",e)||k("function",e),"cannot spyOn on a primitive value");let[r,s]=(()=>{if(!k("object",t))return[t,"value"];if("getter"in t&&"setter"in t)throw new Error("cannot spy on both getter and setter");if("getter"in t)return[t.getter,"get"];if("setter"in t)return[t.setter,"set"];throw new Error("specify getter or setter to spy on")})(),o=J(e,r),a=Object.getPrototypeOf(e),p=a&&J(a,r),i=o||p;q(i||r in e,`${String(r)} does not exist`);let l=!1;s==="value"&&i&&!i.value&&i.get&&(s="get",l=!0,n=i.get());let c;i?c=i[s]:s!=="value"?c=()=>e[r]:c=e[r],n||(n=c);let d=Pe(n);s==="value"&&Q(d,c);let u=f=>{let{value:I,...S}=i||{configurable:!0,writable:!0};s!=="value"&&delete S.writable,S[s]=f,v(e,r,S)},b=()=>i?v(e,r,i):u(c),h=d[M];return x(h,"restore",b),x(h,"getOriginal",()=>l?c():c),x(h,"willCall",f=>(h.impl=f,d)),u(l?()=>(Q(d,n),d):d),Ae.add(d),d}var Be=new Set,ve=0;function De(e){let t=e,n,r=[],s=[],o=C(e),a={get calls(){return o.calls},get instances(){return r},get invocationCallOrder(){return s},get results(){return o.results.map(([u,b])=>({type:u==="error"?"throw":"return",value:b}))},get lastCall(){return o.calls[o.calls.length-1]}},p=[],i=!1;function l(...u){return r.push(this),s.push(++ve),(i?n:p.shift()||n||o.getOriginal()||(()=>{})).apply(this,u)}let c=t.name;t.getMockName=()=>c||"vi.fn()",t.mockName=u=>(c=u,t),t.mockClear=()=>(o.reset(),r=[],s=[],t),t.mockReset=()=>(t.mockClear(),n=()=>{},p=[],t),t.mockRestore=()=>(t.mockReset(),o.restore(),n=void 0,t),t.getMockImplementation=()=>n,t.mockImplementation=u=>(n=u,o.willCall(l),t),t.mockImplementationOnce=u=>(p.push(u),t);function d(u,b){let h=n;n=u,o.willCall(l),i=!0;let f=()=>{n=h,i=!1},I=b();return I instanceof Promise?I.then(()=>(f(),t)):(f(),t)}return t.withImplementation=d,t.mockReturnThis=()=>t.mockImplementation(function(){return this}),t.mockReturnValue=u=>t.mockImplementation(()=>u),t.mockReturnValueOnce=u=>t.mockImplementationOnce(()=>u),t.mockResolvedValue=u=>t.mockImplementation(()=>Promise.resolve(u)),t.mockResolvedValueOnce=u=>t.mockImplementationOnce(()=>Promise.resolve(u)),t.mockRejectedValue=u=>t.mockImplementation(()=>Promise.reject(u)),t.mockRejectedValueOnce=u=>t.mockImplementationOnce(()=>Promise.reject(u)),Object.defineProperty(t,"mock",{get:()=>a}),o.willCall(l),Be.add(t),t}var z=e=>De(Y({spy:e||(()=>{})},"spy"));beforeEach(()=>{global.fetch=z()});afterEach(()=>{let{warnOnPendingRequests:e}=m();if(e){let t=expect.getState?.()?.currentTestName;V(t)}});var He=e=>(y({Component:e,responses:[],props:{},path:"",hasPath:!1,interactionConfig:void 0,debug:process.env.npm_config_debugRequests==="true"}),w()),w=()=>{let e=Le();return{withProps:Je,withNetwork:Ye,withStreamingNetwork:Ve,withInteraction:Qe,atPath:ze,debugRequests:Ke,mount:et,...e}},Ne=e=>{let t=R(),n=[...t.responses,...e];y({...t,responses:n})},je=(e,t)=>(t({addResponses:Ne},e),w()),$e=(e,t)=>{let{extend:n}=m(),r=n[t];return{...e,[t]:(...s)=>je(s,r)}},Le=()=>{let{extend:e}=m();return Object.keys(e).reduce($e,{})},Fe=(e,t,n)=>{let r=new TextEncoder;return new ReadableStream({async start(s){for(let o of e){let a=typeof o=="string"?o:o.text,p=typeof o=="object"&&o.delay!==void 0?o.delay:t;p>0&&await new Promise(i=>setTimeout(i,p)),s.enqueue(r.encode(a))}n||s.close()}})},_e=()=>{let e=new TextEncoder,t;return{stream:new ReadableStream({start(r){t=r}}),sendChunk:r=>t.enqueue(e.encode(r)),close:()=>t.close()}},Ge=e=>{let{path:t,host:n,method:r="GET",chunks:s=[],delayBetweenChunks:o=0,keepOpen:a=!1,stream:p}=e;return{path:t,host:n,method:r,streamBody:p??Fe(s,o,a)}},Ve=e=>{let t=Array.isArray(e)?e:[e],n=R();return y({...n,responses:[...n.responses,...t.map(Ge)]}),w()},Je=e=>{let t=R();return y({...t,props:e}),w()},Qe=e=>{let t=R();return y({...t,interactionConfig:e}),w()},Ye=(e=[])=>{let t=R(),n=Array.isArray(e)?e:[e];return y({...t,responses:[...t.responses,...n]}),w()},ze=(e,t)=>{let n=R();return y({...n,historyState:t,path:e,hasPath:!0}),w()},Ke=()=>{let e=R();return y({...e,debug:!0}),w()},Xe=e=>{let{defaultResponses:t=[]}=m();return[...e,...t]},Ze=(e,t,n,r,s)=>{if(e){if(r){console.warn("wrapito WARNING: history is DEPRECATED. Pass a changeRoute function to the config instead."),console.warn("Read about changeRoute in: https://github.com/mercadona/wrapito#changeRoute"),r.push(t,n);return}s(t)}},et=()=>{let{portal:e,portals:t,changeRoute:n,history:r,mount:s,interaction:o}=m(),{Component:a,props:p,responses:i,path:l,hasPath:c,debug:d,historyState:u,interactionConfig:b}=R(),h=a;e&&X(e),t&&tt(t),Ze(c,l,u,r,n),G(Xe(i),d);let f=s(K.createElement(h,{...p}));if(o){let I=o.setup?o.setup(o.userLib,b):o.userLib;return{...f,user:I}}return{...f,user:void 0}},X=e=>{if(document.getElementById(e))return;let t=document.createElement("div");t.setAttribute("id",e),t.setAttribute("data-testid",e),document.body.appendChild(t)},tt=e=>{e.forEach(t=>{X(t)})};var D=require("jest-diff"),H=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t?.host}${e} ain't got called`:`\u{1F32F} Wrapito: ${e} ain't got called`;return{pass:!1,message:()=>n}},Z=(e,t,n)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: ${e} is called ${n} times, you expected ${t} times`}),ee=(e,t)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch method does not match, expected ${e} received ${t??"none"}`}),te=(e,t)=>{let n=t.map(r=>(0,D.diff)(e,r)).join(`
13
13
 
14
14
  `);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch body does not match.
15
- ${n}`}},ne=(e,t)=>{let n=t.find(s=>e!==s);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Host request does not match, expected ${e} received ${n}`}},se=(e,t)=>{let n=t.map(s=>(0,B.diff)(e,s)).join(`
15
+ ${n}`}},ne=(e,t)=>{let n=t.find(r=>e!==r);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Host request does not match, expected ${e} received ${n}`}},re=(e,t)=>{let n=t.map(r=>(0,D.diff)(e,r)).join(`
16
16
 
17
17
  `);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch headers do not match.
18
- ${n}`}},re=()=>({pass:!1,message:()=>"\u{1F32F} Wrapito: Unable to find body."}),H=()=>({pass:!0,message:()=>"Test passing"}),oe=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t.host}${e} is called`:`\u{1F32F} Wrapito: ${e} is called`;return{pass:!0,message:()=>n}};var ae=E(require("deep-equal"),1);var ie=()=>{let e=m().defaultHost;return e?.includes("http")?e:"https://default.com"},et=(e="",t,n)=>t.includes(n)?t:e+t,T=e=>e instanceof Request,tt=e=>T(e)?e.url:e,P=(e,t={method:"GET"})=>fetch.mock.calls.filter(([s])=>{let r=tt(s),o=ie(),a=new URL(r,o),l=et(t?.host,e,o),i=t?.host||o,u=new URL(l,i),c=a.pathname===u.pathname,d=a.search===u.search,p=a.host===u.host;return u.search?c&&d:t?.host?c&&p:c}),ce=e=>e.flat(1).filter(T).map(t=>t.method),pe=e=>e.flat(1).filter(T).map(t=>t._bodyInit?JSON.parse(t._bodyInit):{}),ue=e=>e.flat(1).filter(T).map(t=>new URL(t.url,ie()).hostname),le=e=>e.flat(1).filter(T).map(t=>{let n={};return t.headers.forEach((s,r)=>{n[r]=s}),n}),de=(e,t)=>e&&!t.includes(e),me=(e,t)=>t.map(s=>(0,ae.default)(e,s)).every(s=>s===!1),he=(e,t)=>t.every(s=>s!==e),ge=(e,t)=>t.every(s=>Object.entries(e).some(([r,o])=>s[r.toLowerCase()]!==o)),fe=e=>e.length===0;var nt=(e,t)=>{let n=P(e);if(fe(n))return D(e);let s=ce(n),r=t?.method;if(de(r,s))return ee(r,s);let o=pe(n),a=t?.body;if(!a)return re();if(me(a,o))return te(a,o);let l=ue(n),i=t?.host;if(i&&he(i,l))return ne(i,l);let u=le(n),c=t?.headers;return c&&ge(c,u)?se(c,u):H()},st=(e,t={method:"GET"})=>P(e,t).length?oe(e,t):D(e,t),rt=(e,t,n={method:"GET"})=>{let s=P(e,n);return s.length!==t?Z(e,t,s.length):H()},ot={toHaveBeenFetched:st,toHaveBeenFetchedWith:nt,toHaveBeenFetchedTimes:rt};0&&(module.exports={assertions,configure,getConfig,matchers,wrap});
18
+ ${n}`}},se=()=>({pass:!1,message:()=>"\u{1F32F} Wrapito: Unable to find body."}),N=()=>({pass:!0,message:()=>"Test passing"}),oe=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t.host}${e} is called`:`\u{1F32F} Wrapito: ${e} is called`;return{pass:!0,message:()=>n}};var ae=E(require("deep-equal"),1);var ie=()=>{let e=m().defaultHost;return e?.includes("http")?e:"https://default.com"},nt=(e="",t,n)=>t.includes(n)?t:e+t,T=e=>e instanceof Request,rt=e=>T(e)?e.url:e,A=(e,t={method:"GET"})=>fetch.mock.calls.filter(([r])=>{let s=rt(r),o=ie(),a=new URL(s,o),p=nt(t?.host,e,o),i=t?.host||o,l=new URL(p,i),c=a.pathname===l.pathname,d=a.search===l.search,u=a.host===l.host;return l.search?c&&d:t?.host?c&&u:c}),ce=e=>e.flat(1).filter(T).map(t=>t.method),pe=e=>e.flat(1).filter(T).map(t=>t._bodyInit?JSON.parse(t._bodyInit):{}),ue=e=>e.flat(1).filter(T).map(t=>new URL(t.url,ie()).hostname),le=e=>e.flat(1).filter(T).map(t=>{let n={};return t.headers.forEach((r,s)=>{n[s]=r}),n}),de=(e,t)=>e&&!t.includes(e),me=(e,t)=>t.map(r=>(0,ae.default)(e,r)).every(r=>r===!1),ge=(e,t)=>t.every(r=>r!==e),he=(e,t)=>t.every(r=>Object.entries(e).some(([s,o])=>r[s.toLowerCase()]!==o)),fe=e=>e.length===0;var st=(e,t)=>{let n=A(e);if(fe(n))return H(e);let r=ce(n),s=t?.method;if(de(s,r))return ee(s,r);let o=pe(n),a=t?.body;if(!a)return se();if(me(a,o))return te(a,o);let p=ue(n),i=t?.host;if(i&&ge(i,p))return ne(i,p);let l=le(n),c=t?.headers;return c&&he(c,l)?re(c,l):N()},ot=(e,t={method:"GET"})=>A(e,t).length?oe(e,t):H(e,t),at=(e,t,n={method:"GET"})=>{let r=A(e,n);return r.length!==t?Z(e,t,r.length):N()},it={toHaveBeenFetched:ot,toHaveBeenFetchedWith:st,toHaveBeenFetchedTimes:at};0&&(module.exports={assertions,configure,createStreamController,getConfig,matchers,wrap});
package/dist/index.d.cts CHANGED
@@ -40,9 +40,10 @@ interface StreamingNetworkConfig {
40
40
  path: string;
41
41
  host?: string;
42
42
  method?: HttpMethod;
43
- chunks: StreamChunk[];
43
+ chunks?: StreamChunk[];
44
44
  delayBetweenChunks?: number;
45
45
  keepOpen?: boolean;
46
+ stream?: ReadableStream<Uint8Array<ArrayBuffer>>;
46
47
  }
47
48
  type DefaultUserLib = unknown;
48
49
  type DefaultUserInstance = unknown;
@@ -54,7 +55,7 @@ interface InteractionDescriptor<UserLib = DefaultUserLib, UserInstance = Default
54
55
  }
55
56
  interface Wrap<UserInteraction extends InteractionDescriptor = InteractionDescriptor> {
56
57
  withNetwork: (responses?: NetworkResponses) => Wrap<UserInteraction>;
57
- withStreamingNetwork: (config: StreamingNetworkConfig) => Wrap<UserInteraction>;
58
+ withStreamingNetwork: (config: StreamingNetworkConfig | StreamingNetworkConfig[]) => Wrap<UserInteraction>;
58
59
  atPath: (path: string, historyState?: object) => Wrap<UserInteraction>;
59
60
  withProps: (props: object) => Wrap<UserInteraction>;
60
61
  withInteraction: (config: UserInteraction['UserSetupOptions']) => Wrap<UserInteraction>;
@@ -105,6 +106,11 @@ interface BrowserHistory extends History {
105
106
  }
106
107
 
107
108
  declare const wrap: (component: unknown) => Wrap;
109
+ declare const createStreamController: () => {
110
+ stream: ReadableStream<Uint8Array<ArrayBuffer>>;
111
+ sendChunk: (text: string) => void;
112
+ close: () => void;
113
+ };
108
114
 
109
115
  declare function configure(newConfig: Partial<Config>): void;
110
116
  declare const getConfig: () => Config;
@@ -124,4 +130,4 @@ declare const matchers: {
124
130
  };
125
131
  };
126
132
 
127
- export { type BrowserHistory, type Component, type Config, type DefaultUserInstance, type DefaultUserLib, type DefaultUserSetupOptions, type Extension, type Extensions, type HttpMethod, type InteractionDescriptor, type InteractionOptions, type Mount, type NetworkResponses, type RenderResult, type RequestOptions, type WrapResponse as Response, type StreamChunk, type StreamingNetworkConfig, type Wrap, type WrapExtensionAPI, type WrapOptions, type WrapRequest, type WrapResponse, matchers as assertions, configure, getConfig, matchers, wrap };
133
+ export { type BrowserHistory, type Component, type Config, type DefaultUserInstance, type DefaultUserLib, type DefaultUserSetupOptions, type Extension, type Extensions, type HttpMethod, type InteractionDescriptor, type InteractionOptions, type Mount, type NetworkResponses, type RenderResult, type RequestOptions, type WrapResponse as Response, type StreamChunk, type StreamingNetworkConfig, type Wrap, type WrapExtensionAPI, type WrapOptions, type WrapRequest, type WrapResponse, matchers as assertions, configure, createStreamController, getConfig, matchers, wrap };
package/dist/index.d.ts CHANGED
@@ -40,9 +40,10 @@ interface StreamingNetworkConfig {
40
40
  path: string;
41
41
  host?: string;
42
42
  method?: HttpMethod;
43
- chunks: StreamChunk[];
43
+ chunks?: StreamChunk[];
44
44
  delayBetweenChunks?: number;
45
45
  keepOpen?: boolean;
46
+ stream?: ReadableStream<Uint8Array<ArrayBuffer>>;
46
47
  }
47
48
  type DefaultUserLib = unknown;
48
49
  type DefaultUserInstance = unknown;
@@ -54,7 +55,7 @@ interface InteractionDescriptor<UserLib = DefaultUserLib, UserInstance = Default
54
55
  }
55
56
  interface Wrap<UserInteraction extends InteractionDescriptor = InteractionDescriptor> {
56
57
  withNetwork: (responses?: NetworkResponses) => Wrap<UserInteraction>;
57
- withStreamingNetwork: (config: StreamingNetworkConfig) => Wrap<UserInteraction>;
58
+ withStreamingNetwork: (config: StreamingNetworkConfig | StreamingNetworkConfig[]) => Wrap<UserInteraction>;
58
59
  atPath: (path: string, historyState?: object) => Wrap<UserInteraction>;
59
60
  withProps: (props: object) => Wrap<UserInteraction>;
60
61
  withInteraction: (config: UserInteraction['UserSetupOptions']) => Wrap<UserInteraction>;
@@ -105,6 +106,11 @@ interface BrowserHistory extends History {
105
106
  }
106
107
 
107
108
  declare const wrap: (component: unknown) => Wrap;
109
+ declare const createStreamController: () => {
110
+ stream: ReadableStream<Uint8Array<ArrayBuffer>>;
111
+ sendChunk: (text: string) => void;
112
+ close: () => void;
113
+ };
108
114
 
109
115
  declare function configure(newConfig: Partial<Config>): void;
110
116
  declare const getConfig: () => Config;
@@ -124,4 +130,4 @@ declare const matchers: {
124
130
  };
125
131
  };
126
132
 
127
- export { type BrowserHistory, type Component, type Config, type DefaultUserInstance, type DefaultUserLib, type DefaultUserSetupOptions, type Extension, type Extensions, type HttpMethod, type InteractionDescriptor, type InteractionOptions, type Mount, type NetworkResponses, type RenderResult, type RequestOptions, type WrapResponse as Response, type StreamChunk, type StreamingNetworkConfig, type Wrap, type WrapExtensionAPI, type WrapOptions, type WrapRequest, type WrapResponse, matchers as assertions, configure, getConfig, matchers, wrap };
133
+ export { type BrowserHistory, type Component, type Config, type DefaultUserInstance, type DefaultUserLib, type DefaultUserSetupOptions, type Extension, type Extensions, type HttpMethod, type InteractionDescriptor, type InteractionOptions, type Mount, type NetworkResponses, type RenderResult, type RequestOptions, type WrapResponse as Response, type StreamChunk, type StreamingNetworkConfig, type Wrap, type WrapExtensionAPI, type WrapOptions, type WrapRequest, type WrapResponse, matchers as assertions, configure, createStreamController, getConfig, matchers, wrap };
package/dist/index.mjs CHANGED
@@ -1,18 +1,18 @@
1
- import*as V from"react";import h from"chalk";import v from"object-hash";import{render as de}from"@testing-library/react";var P={defaultHost:"",extend:{},mount:de,changeRoute:e=>window.history.replaceState(null,"",e)};function Qe(e){P={...P,...e}}var m=()=>({...P});var B=e=>t=>{let{method:n="GET",path:s,host:r=m().defaultHost,requestBody:o=void 0,catchParams:a}=t,l=r+s,i=!m().handleQueryParams||a,u=v({url:i?l:l.split("?")[0],method:n.toUpperCase(),requestBody:o}),c;return o!==void 0&&"_bodyInit"in e&&e._bodyInit!==void 0&&(c=JSON.parse(e._bodyInit)),v({url:i?e.url:e.url.split("?")[0],method:e.method,requestBody:c})===u};var N=async()=>{let e={json:()=>Promise.resolve(),status:200,ok:!0,headers:new Headers({"Content-Type":"application/json"})};return Promise.resolve(e)},me=e=>{let{streamBody:t,status:n=200,headers:s={}}=e;return{body:t,status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"text/event-stream",...s})}},he=e=>{let{responseBody:t,status:n=200,headers:s={}}=e;return{json:()=>Promise.resolve(t),status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"application/json",...s})}},D=async e=>{let t=e.streamBody?me(e):he(e);return e.delay?new Promise(n=>setTimeout(()=>n(t),e.delay)):Promise.resolve(t)},ge=e=>console.warn(`
2
- ${h.white.bold.bgRed("wrapito")} ${h.redBright.bold("cannot find any mock matching:")}
3
- ${h.greenBright(`URL: ${e.url}`)}
4
- ${h.greenBright(`METHOD: ${e.method?.toLowerCase()}`)}
5
- ${h.greenBright(`REQUEST BODY: ${e._bodyInit}`)}
6
- `),H=async(e,t,n)=>{let s=e.find(B(t));if(!s)return n&&ge(t),N();let{multipleResponses:r}=s;if(!r)return D(s);let o=r.find(a=>!a.hasBeenReturned);if(!o){n&&fe(s);return}return o.hasBeenReturned=!0,D(o)},j=(e=[],t=!1)=>{global.fetch.mockImplementation((s,r)=>{if(typeof s=="string"){let a=new Request(s,r);return H(e,a,t)}return H(e,s,t)})},fe=e=>{let t=`\u{1F32F} Wrapito: Missing response in the multipleResponses array for path ${e.path} and method ${e.method}.`,n=h.greenBright(t);console.warn(n)},$=e=>{let t=global.fetch.getMockImplementation();global.fetch.mockImplementation((n,s)=>{let r=typeof n=="string"?n:n.url,o=s?.method||(typeof n!="string"?n.method:"GET");return console.warn(`
7
- ${h.white.bold.bgYellow(" \u{1F32F} wrapito ")}
8
- ${h.yellowBright.bold("\u26A0\uFE0F pending request detected after test finished:")}
9
- ${h.greenBright(`URL: ${r}`)}
10
- ${h.greenBright(`METHOD: ${o?.toLowerCase()}`)}
11
- ${e?` ${h.greenBright(`TEST: ${e}`)}
12
- `:""}`),t?t(n,s):N()})};var U,y=e=>{U={...U,...e}},R=()=>({...U});function O(e,t){if(!e)throw new Error(t)}function k(e,t){return typeof t===e}function ye(e){return e instanceof Promise}function A(e,t,n){Object.defineProperty(e,t,n)}function x(e,t,n){Object.defineProperty(e,t,{value:n})}var M=Symbol.for("tinyspy:spy"),Re=new Set,be=e=>{e.called=!1,e.callCount=0,e.calls=[],e.results=[],e.next=[]},we=e=>(A(e,M,{value:{reset:()=>be(e[M])}}),e[M]),E=e=>e[M]||we(e);function ke(e){O(k("function",e)||k("undefined",e),"cannot spy on a non-function value");let t=function(...s){let r=E(t);r.called=!0,r.callCount++,r.calls.push(s);let o=r.next.shift();if(o){r.results.push(o);let[u,c]=o;if(u==="ok")return c;throw c}let a,l="ok";if(r.impl)try{new.target?a=Reflect.construct(r.impl,s,new.target):a=r.impl.apply(this,s),l="ok"}catch(u){throw a=u,l="error",r.results.push([l,u]),u}let i=[l,a];if(ye(a)){let u=a.then(c=>i[1]=c).catch(c=>{throw i[0]="error",i[1]=c,c});Object.assign(u,a),a=u}return r.results.push(i),a};x(t,"_isMockFunction",!0),x(t,"length",e?e.length:0),x(t,"name",e&&e.name||"spy");let n=E(t);return n.reset(),n.impl=e,t}var L=(e,t)=>Object.getOwnPropertyDescriptor(e,t),F=(e,t)=>{t!=null&&typeof t=="function"&&t.prototype!=null&&Object.setPrototypeOf(e.prototype,t.prototype)};function _(e,t,n){O(!k("undefined",e),"spyOn could not find an object to spy upon"),O(k("object",e)||k("function",e),"cannot spyOn on a primitive value");let[s,r]=(()=>{if(!k("object",t))return[t,"value"];if("getter"in t&&"setter"in t)throw new Error("cannot spy on both getter and setter");if("getter"in t)return[t.getter,"get"];if("setter"in t)return[t.setter,"set"];throw new Error("specify getter or setter to spy on")})(),o=L(e,s),a=Object.getPrototypeOf(e),l=a&&L(a,s),i=o||l;O(i||s in e,`${String(s)} does not exist`);let u=!1;r==="value"&&i&&!i.value&&i.get&&(r="get",u=!0,n=i.get());let c;i?c=i[r]:r!=="value"?c=()=>e[s]:c=e[s],n||(n=c);let d=ke(n);r==="value"&&F(d,c);let p=f=>{let{value:I,...C}=i||{configurable:!0,writable:!0};r!=="value"&&delete C.writable,C[r]=f,A(e,s,C)},b=()=>i?A(e,s,i):p(c),g=d[M];return x(g,"restore",b),x(g,"getOriginal",()=>u?c():c),x(g,"willCall",f=>(g.impl=f,d)),p(u?()=>(F(d,n),d):d),Re.add(d),d}var Ie=new Set,Me=0;function Te(e){let t=e,n,s=[],r=[],o=E(e),a={get calls(){return o.calls},get instances(){return s},get invocationCallOrder(){return r},get results(){return o.results.map(([p,b])=>({type:p==="error"?"throw":"return",value:b}))},get lastCall(){return o.calls[o.calls.length-1]}},l=[],i=!1;function u(...p){return s.push(this),r.push(++Me),(i?n:l.shift()||n||o.getOriginal()||(()=>{})).apply(this,p)}let c=t.name;t.getMockName=()=>c||"vi.fn()",t.mockName=p=>(c=p,t),t.mockClear=()=>(o.reset(),s=[],r=[],t),t.mockReset=()=>(t.mockClear(),n=()=>{},l=[],t),t.mockRestore=()=>(t.mockReset(),o.restore(),n=void 0,t),t.getMockImplementation=()=>n,t.mockImplementation=p=>(n=p,o.willCall(u),t),t.mockImplementationOnce=p=>(l.push(p),t);function d(p,b){let g=n;n=p,o.willCall(u),i=!0;let f=()=>{n=g,i=!1},I=b();return I instanceof Promise?I.then(()=>(f(),t)):(f(),t)}return t.withImplementation=d,t.mockReturnThis=()=>t.mockImplementation(function(){return this}),t.mockReturnValue=p=>t.mockImplementation(()=>p),t.mockReturnValueOnce=p=>t.mockImplementationOnce(()=>p),t.mockResolvedValue=p=>t.mockImplementation(()=>Promise.resolve(p)),t.mockResolvedValueOnce=p=>t.mockImplementationOnce(()=>Promise.resolve(p)),t.mockRejectedValue=p=>t.mockImplementation(()=>Promise.reject(p)),t.mockRejectedValueOnce=p=>t.mockImplementationOnce(()=>Promise.reject(p)),Object.defineProperty(t,"mock",{get:()=>a}),o.willCall(u),Ie.add(t),t}var G=e=>Te(_({spy:e||(()=>{})},"spy"));beforeEach(()=>{global.fetch=G()});afterEach(()=>{let{warnOnPendingRequests:e}=m();if(e){let t=expect.getState?.()?.currentTestName;$(t)}});var ct=e=>(y({Component:e,responses:[],props:{},path:"",hasPath:!1,interactionConfig:void 0,debug:process.env.npm_config_debugRequests==="true"}),w()),w=()=>{let e=Ce();return{withProps:Ae,withNetwork:Se,withStreamingNetwork:Ue,withInteraction:We,atPath:ve,debugRequests:Be,mount:Ne,...e}},Oe=e=>{let t=R(),n=[...t.responses,...e];y({...t,responses:n})},Ee=(e,t)=>(t({addResponses:Oe},e),w()),qe=(e,t)=>{let{extend:n}=m(),s=n[t];return{...e,[t]:(...r)=>Ee(r,s)}},Ce=()=>{let{extend:e}=m();return Object.keys(e).reduce(qe,{})},Pe=(e,t,n)=>{let s=new TextEncoder;return new ReadableStream({async start(r){for(let o of e){let a=typeof o=="string"?o:o.text,l=typeof o=="object"&&o.delay!==void 0?o.delay:t;l>0&&await new Promise(i=>setTimeout(i,l)),r.enqueue(s.encode(a))}n||r.close()}})},Ue=e=>{let{path:t,host:n,method:s="GET",chunks:r,delayBetweenChunks:o=0,keepOpen:a=!1}=e,l=R();return y({...l,responses:[...l.responses,{path:t,host:n,method:s,streamBody:Pe(r,o,a)}]}),w()},Ae=e=>{let t=R();return y({...t,props:e}),w()},We=e=>{let t=R();return y({...t,interactionConfig:e}),w()},Se=(e=[])=>{let t=R(),n=Array.isArray(e)?e:[e];return y({...t,responses:[...t.responses,...n]}),w()},ve=(e,t)=>{let n=R();return y({...n,historyState:t,path:e,hasPath:!0}),w()},Be=()=>{let e=R();return y({...e,debug:!0}),w()},De=e=>{let{defaultResponses:t=[]}=m();return[...e,...t]},He=(e,t,n,s,r)=>{if(e){if(s){console.warn("wrapito WARNING: history is DEPRECATED. Pass a changeRoute function to the config instead."),console.warn("Read about changeRoute in: https://github.com/mercadona/wrapito#changeRoute"),s.push(t,n);return}r(t)}},Ne=()=>{let{portal:e,portals:t,changeRoute:n,history:s,mount:r,interaction:o}=m(),{Component:a,props:l,responses:i,path:u,hasPath:c,debug:d,historyState:p,interactionConfig:b}=R(),g=a;e&&J(e),t&&je(t),He(c,u,p,s,n),j(De(i),d);let f=r(V.createElement(g,{...l}));if(o){let I=o.setup?o.setup(o.userLib,b):o.userLib;return{...f,user:I}}return{...f,user:void 0}},J=e=>{if(document.getElementById(e))return;let t=document.createElement("div");t.setAttribute("id",e),t.setAttribute("data-testid",e),document.body.appendChild(t)},je=e=>{e.forEach(t=>{J(t)})};import{diff as Q}from"jest-diff";var W=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t?.host}${e} ain't got called`:`\u{1F32F} Wrapito: ${e} ain't got called`;return{pass:!1,message:()=>n}},Y=(e,t,n)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: ${e} is called ${n} times, you expected ${t} times`}),z=(e,t)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch method does not match, expected ${e} received ${t??"none"}`}),K=(e,t)=>{let n=t.map(s=>Q(e,s)).join(`
1
+ import*as V from"react";import g from"chalk";import v from"object-hash";import{render as de}from"@testing-library/react";var A={defaultHost:"",extend:{},mount:de,changeRoute:e=>window.history.replaceState(null,"",e)};function Ye(e){A={...A,...e}}var m=()=>({...A});var D=e=>t=>{let{method:n="GET",path:r,host:s=m().defaultHost,requestBody:o=void 0,catchParams:a}=t,p=s+r,i=!m().handleQueryParams||a,l=v({url:i?p:p.split("?")[0],method:n.toUpperCase(),requestBody:o}),c;return o!==void 0&&"_bodyInit"in e&&e._bodyInit!==void 0&&(c=JSON.parse(e._bodyInit)),v({url:i?e.url:e.url.split("?")[0],method:e.method,requestBody:c})===l};var N=async()=>{let e={json:()=>Promise.resolve(),status:200,ok:!0,headers:new Headers({"Content-Type":"application/json"})};return Promise.resolve(e)},me=e=>{let{streamBody:t,status:n=200,headers:r={}}=e;return{body:t,status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"text/event-stream",...r})}},ge=e=>{let{responseBody:t,status:n=200,headers:r={}}=e;return{json:()=>Promise.resolve(t),status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"application/json",...r})}},S=async e=>{let t=e.streamBody?me(e):ge(e);return e.delay?new Promise(n=>setTimeout(()=>n(t),e.delay)):Promise.resolve(t)},he=e=>console.warn(`
2
+ ${g.white.bold.bgRed("wrapito")} ${g.redBright.bold("cannot find any mock matching:")}
3
+ ${g.greenBright(`URL: ${e.url}`)}
4
+ ${g.greenBright(`METHOD: ${e.method?.toLowerCase()}`)}
5
+ ${g.greenBright(`REQUEST BODY: ${e._bodyInit}`)}
6
+ `),H=async(e,t,n)=>{let r=D(t),s=e.find(p=>r(p)&&!(p.streamBody&&p.hasBeenReturned));if(!s)return n&&he(t),N();if(s.streamBody)return s.hasBeenReturned=!0,S(s);let{multipleResponses:o}=s;if(!o)return S(s);let a=o.find(p=>!p.hasBeenReturned);if(!a){n&&fe(s);return}return a.hasBeenReturned=!0,S(a)},j=(e=[],t=!1)=>{global.fetch.mockImplementation((r,s)=>{if(typeof r=="string"){let a=new Request(r,s);return H(e,a,t)}return H(e,r,t)})},fe=e=>{let t=`\u{1F32F} Wrapito: Missing response in the multipleResponses array for path ${e.path} and method ${e.method}.`,n=g.greenBright(t);console.warn(n)},$=e=>{let t=global.fetch.getMockImplementation();global.fetch.mockImplementation((n,r)=>{let s=typeof n=="string"?n:n.url,o=r?.method||(typeof n!="string"?n.method:"GET");return console.warn(`
7
+ ${g.white.bold.bgYellow(" \u{1F32F} wrapito ")}
8
+ ${g.yellowBright.bold("\u26A0\uFE0F pending request detected after test finished:")}
9
+ ${g.greenBright(`URL: ${s}`)}
10
+ ${g.greenBright(`METHOD: ${o?.toLowerCase()}`)}
11
+ ${e?` ${g.greenBright(`TEST: ${e}`)}
12
+ `:""}`),t?t(n,r):N()})};var U,y=e=>{U={...U,...e}},R=()=>({...U});function O(e,t){if(!e)throw new Error(t)}function k(e,t){return typeof t===e}function ye(e){return e instanceof Promise}function P(e,t,n){Object.defineProperty(e,t,n)}function x(e,t,n){Object.defineProperty(e,t,{value:n})}var M=Symbol.for("tinyspy:spy"),Re=new Set,be=e=>{e.called=!1,e.callCount=0,e.calls=[],e.results=[],e.next=[]},we=e=>(P(e,M,{value:{reset:()=>be(e[M])}}),e[M]),E=e=>e[M]||we(e);function ke(e){O(k("function",e)||k("undefined",e),"cannot spy on a non-function value");let t=function(...r){let s=E(t);s.called=!0,s.callCount++,s.calls.push(r);let o=s.next.shift();if(o){s.results.push(o);let[l,c]=o;if(l==="ok")return c;throw c}let a,p="ok";if(s.impl)try{new.target?a=Reflect.construct(s.impl,r,new.target):a=s.impl.apply(this,r),p="ok"}catch(l){throw a=l,p="error",s.results.push([p,l]),l}let i=[p,a];if(ye(a)){let l=a.then(c=>i[1]=c).catch(c=>{throw i[0]="error",i[1]=c,c});Object.assign(l,a),a=l}return s.results.push(i),a};x(t,"_isMockFunction",!0),x(t,"length",e?e.length:0),x(t,"name",e&&e.name||"spy");let n=E(t);return n.reset(),n.impl=e,t}var L=(e,t)=>Object.getOwnPropertyDescriptor(e,t),F=(e,t)=>{t!=null&&typeof t=="function"&&t.prototype!=null&&Object.setPrototypeOf(e.prototype,t.prototype)};function _(e,t,n){O(!k("undefined",e),"spyOn could not find an object to spy upon"),O(k("object",e)||k("function",e),"cannot spyOn on a primitive value");let[r,s]=(()=>{if(!k("object",t))return[t,"value"];if("getter"in t&&"setter"in t)throw new Error("cannot spy on both getter and setter");if("getter"in t)return[t.getter,"get"];if("setter"in t)return[t.setter,"set"];throw new Error("specify getter or setter to spy on")})(),o=L(e,r),a=Object.getPrototypeOf(e),p=a&&L(a,r),i=o||p;O(i||r in e,`${String(r)} does not exist`);let l=!1;s==="value"&&i&&!i.value&&i.get&&(s="get",l=!0,n=i.get());let c;i?c=i[s]:s!=="value"?c=()=>e[r]:c=e[r],n||(n=c);let d=ke(n);s==="value"&&F(d,c);let u=f=>{let{value:I,...C}=i||{configurable:!0,writable:!0};s!=="value"&&delete C.writable,C[s]=f,P(e,r,C)},b=()=>i?P(e,r,i):u(c),h=d[M];return x(h,"restore",b),x(h,"getOriginal",()=>l?c():c),x(h,"willCall",f=>(h.impl=f,d)),u(l?()=>(F(d,n),d):d),Re.add(d),d}var Ie=new Set,Me=0;function Te(e){let t=e,n,r=[],s=[],o=E(e),a={get calls(){return o.calls},get instances(){return r},get invocationCallOrder(){return s},get results(){return o.results.map(([u,b])=>({type:u==="error"?"throw":"return",value:b}))},get lastCall(){return o.calls[o.calls.length-1]}},p=[],i=!1;function l(...u){return r.push(this),s.push(++Me),(i?n:p.shift()||n||o.getOriginal()||(()=>{})).apply(this,u)}let c=t.name;t.getMockName=()=>c||"vi.fn()",t.mockName=u=>(c=u,t),t.mockClear=()=>(o.reset(),r=[],s=[],t),t.mockReset=()=>(t.mockClear(),n=()=>{},p=[],t),t.mockRestore=()=>(t.mockReset(),o.restore(),n=void 0,t),t.getMockImplementation=()=>n,t.mockImplementation=u=>(n=u,o.willCall(l),t),t.mockImplementationOnce=u=>(p.push(u),t);function d(u,b){let h=n;n=u,o.willCall(l),i=!0;let f=()=>{n=h,i=!1},I=b();return I instanceof Promise?I.then(()=>(f(),t)):(f(),t)}return t.withImplementation=d,t.mockReturnThis=()=>t.mockImplementation(function(){return this}),t.mockReturnValue=u=>t.mockImplementation(()=>u),t.mockReturnValueOnce=u=>t.mockImplementationOnce(()=>u),t.mockResolvedValue=u=>t.mockImplementation(()=>Promise.resolve(u)),t.mockResolvedValueOnce=u=>t.mockImplementationOnce(()=>Promise.resolve(u)),t.mockRejectedValue=u=>t.mockImplementation(()=>Promise.reject(u)),t.mockRejectedValueOnce=u=>t.mockImplementationOnce(()=>Promise.reject(u)),Object.defineProperty(t,"mock",{get:()=>a}),o.willCall(l),Ie.add(t),t}var G=e=>Te(_({spy:e||(()=>{})},"spy"));beforeEach(()=>{global.fetch=G()});afterEach(()=>{let{warnOnPendingRequests:e}=m();if(e){let t=expect.getState?.()?.currentTestName;$(t)}});var pt=e=>(y({Component:e,responses:[],props:{},path:"",hasPath:!1,interactionConfig:void 0,debug:process.env.npm_config_debugRequests==="true"}),w()),w=()=>{let e=Ce();return{withProps:Pe,withNetwork:Be,withStreamingNetwork:Ue,withInteraction:We,atPath:ve,debugRequests:De,mount:je,...e}},Oe=e=>{let t=R(),n=[...t.responses,...e];y({...t,responses:n})},Ee=(e,t)=>(t({addResponses:Oe},e),w()),qe=(e,t)=>{let{extend:n}=m(),r=n[t];return{...e,[t]:(...s)=>Ee(s,r)}},Ce=()=>{let{extend:e}=m();return Object.keys(e).reduce(qe,{})},Ae=(e,t,n)=>{let r=new TextEncoder;return new ReadableStream({async start(s){for(let o of e){let a=typeof o=="string"?o:o.text,p=typeof o=="object"&&o.delay!==void 0?o.delay:t;p>0&&await new Promise(i=>setTimeout(i,p)),s.enqueue(r.encode(a))}n||s.close()}})},ut=()=>{let e=new TextEncoder,t;return{stream:new ReadableStream({start(r){t=r}}),sendChunk:r=>t.enqueue(e.encode(r)),close:()=>t.close()}},Se=e=>{let{path:t,host:n,method:r="GET",chunks:s=[],delayBetweenChunks:o=0,keepOpen:a=!1,stream:p}=e;return{path:t,host:n,method:r,streamBody:p??Ae(s,o,a)}},Ue=e=>{let t=Array.isArray(e)?e:[e],n=R();return y({...n,responses:[...n.responses,...t.map(Se)]}),w()},Pe=e=>{let t=R();return y({...t,props:e}),w()},We=e=>{let t=R();return y({...t,interactionConfig:e}),w()},Be=(e=[])=>{let t=R(),n=Array.isArray(e)?e:[e];return y({...t,responses:[...t.responses,...n]}),w()},ve=(e,t)=>{let n=R();return y({...n,historyState:t,path:e,hasPath:!0}),w()},De=()=>{let e=R();return y({...e,debug:!0}),w()},He=e=>{let{defaultResponses:t=[]}=m();return[...e,...t]},Ne=(e,t,n,r,s)=>{if(e){if(r){console.warn("wrapito WARNING: history is DEPRECATED. Pass a changeRoute function to the config instead."),console.warn("Read about changeRoute in: https://github.com/mercadona/wrapito#changeRoute"),r.push(t,n);return}s(t)}},je=()=>{let{portal:e,portals:t,changeRoute:n,history:r,mount:s,interaction:o}=m(),{Component:a,props:p,responses:i,path:l,hasPath:c,debug:d,historyState:u,interactionConfig:b}=R(),h=a;e&&J(e),t&&$e(t),Ne(c,l,u,r,n),j(He(i),d);let f=s(V.createElement(h,{...p}));if(o){let I=o.setup?o.setup(o.userLib,b):o.userLib;return{...f,user:I}}return{...f,user:void 0}},J=e=>{if(document.getElementById(e))return;let t=document.createElement("div");t.setAttribute("id",e),t.setAttribute("data-testid",e),document.body.appendChild(t)},$e=e=>{e.forEach(t=>{J(t)})};import{diff as Q}from"jest-diff";var W=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t?.host}${e} ain't got called`:`\u{1F32F} Wrapito: ${e} ain't got called`;return{pass:!1,message:()=>n}},Y=(e,t,n)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: ${e} is called ${n} times, you expected ${t} times`}),z=(e,t)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch method does not match, expected ${e} received ${t??"none"}`}),K=(e,t)=>{let n=t.map(r=>Q(e,r)).join(`
13
13
 
14
14
  `);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch body does not match.
15
- ${n}`}},X=(e,t)=>{let n=t.find(s=>e!==s);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Host request does not match, expected ${e} received ${n}`}},Z=(e,t)=>{let n=t.map(s=>Q(e,s)).join(`
15
+ ${n}`}},X=(e,t)=>{let n=t.find(r=>e!==r);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Host request does not match, expected ${e} received ${n}`}},Z=(e,t)=>{let n=t.map(r=>Q(e,r)).join(`
16
16
 
17
17
  `);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch headers do not match.
18
- ${n}`}},ee=()=>({pass:!1,message:()=>"\u{1F32F} Wrapito: Unable to find body."}),S=()=>({pass:!0,message:()=>"Test passing"}),te=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t.host}${e} is called`:`\u{1F32F} Wrapito: ${e} is called`;return{pass:!0,message:()=>n}};import $e from"deep-equal";var ne=()=>{let e=m().defaultHost;return e?.includes("http")?e:"https://default.com"},Le=(e="",t,n)=>t.includes(n)?t:e+t,T=e=>e instanceof Request,Fe=e=>T(e)?e.url:e,q=(e,t={method:"GET"})=>fetch.mock.calls.filter(([s])=>{let r=Fe(s),o=ne(),a=new URL(r,o),l=Le(t?.host,e,o),i=t?.host||o,u=new URL(l,i),c=a.pathname===u.pathname,d=a.search===u.search,p=a.host===u.host;return u.search?c&&d:t?.host?c&&p:c}),se=e=>e.flat(1).filter(T).map(t=>t.method),re=e=>e.flat(1).filter(T).map(t=>t._bodyInit?JSON.parse(t._bodyInit):{}),oe=e=>e.flat(1).filter(T).map(t=>new URL(t.url,ne()).hostname),ae=e=>e.flat(1).filter(T).map(t=>{let n={};return t.headers.forEach((s,r)=>{n[r]=s}),n}),ie=(e,t)=>e&&!t.includes(e),ce=(e,t)=>t.map(s=>$e(e,s)).every(s=>s===!1),pe=(e,t)=>t.every(s=>s!==e),ue=(e,t)=>t.every(s=>Object.entries(e).some(([r,o])=>s[r.toLowerCase()]!==o)),le=e=>e.length===0;var _e=(e,t)=>{let n=q(e);if(le(n))return W(e);let s=se(n),r=t?.method;if(ie(r,s))return z(r,s);let o=re(n),a=t?.body;if(!a)return ee();if(ce(a,o))return K(a,o);let l=oe(n),i=t?.host;if(i&&pe(i,l))return X(i,l);let u=ae(n),c=t?.headers;return c&&ue(c,u)?Z(c,u):S()},Ge=(e,t={method:"GET"})=>q(e,t).length?te(e,t):W(e,t),Ve=(e,t,n={method:"GET"})=>{let s=q(e,n);return s.length!==t?Y(e,t,s.length):S()},yt={toHaveBeenFetched:Ge,toHaveBeenFetchedWith:_e,toHaveBeenFetchedTimes:Ve};export{yt as assertions,Qe as configure,m as getConfig,yt as matchers,ct as wrap};
18
+ ${n}`}},ee=()=>({pass:!1,message:()=>"\u{1F32F} Wrapito: Unable to find body."}),B=()=>({pass:!0,message:()=>"Test passing"}),te=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t.host}${e} is called`:`\u{1F32F} Wrapito: ${e} is called`;return{pass:!0,message:()=>n}};import Le from"deep-equal";var ne=()=>{let e=m().defaultHost;return e?.includes("http")?e:"https://default.com"},Fe=(e="",t,n)=>t.includes(n)?t:e+t,T=e=>e instanceof Request,_e=e=>T(e)?e.url:e,q=(e,t={method:"GET"})=>fetch.mock.calls.filter(([r])=>{let s=_e(r),o=ne(),a=new URL(s,o),p=Fe(t?.host,e,o),i=t?.host||o,l=new URL(p,i),c=a.pathname===l.pathname,d=a.search===l.search,u=a.host===l.host;return l.search?c&&d:t?.host?c&&u:c}),re=e=>e.flat(1).filter(T).map(t=>t.method),se=e=>e.flat(1).filter(T).map(t=>t._bodyInit?JSON.parse(t._bodyInit):{}),oe=e=>e.flat(1).filter(T).map(t=>new URL(t.url,ne()).hostname),ae=e=>e.flat(1).filter(T).map(t=>{let n={};return t.headers.forEach((r,s)=>{n[s]=r}),n}),ie=(e,t)=>e&&!t.includes(e),ce=(e,t)=>t.map(r=>Le(e,r)).every(r=>r===!1),pe=(e,t)=>t.every(r=>r!==e),ue=(e,t)=>t.every(r=>Object.entries(e).some(([s,o])=>r[s.toLowerCase()]!==o)),le=e=>e.length===0;var Ge=(e,t)=>{let n=q(e);if(le(n))return W(e);let r=re(n),s=t?.method;if(ie(s,r))return z(s,r);let o=se(n),a=t?.body;if(!a)return ee();if(ce(a,o))return K(a,o);let p=oe(n),i=t?.host;if(i&&pe(i,p))return X(i,p);let l=ae(n),c=t?.headers;return c&&ue(c,l)?Z(c,l):B()},Ve=(e,t={method:"GET"})=>q(e,t).length?te(e,t):W(e,t),Je=(e,t,n={method:"GET"})=>{let r=q(e,n);return r.length!==t?Y(e,t,r.length):B()},bt={toHaveBeenFetched:Ve,toHaveBeenFetchedWith:Ge,toHaveBeenFetchedTimes:Je};export{bt as assertions,Ye as configure,ut as createStreamController,m as getConfig,bt as matchers,pt as wrap};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrapito",
3
- "version": "13.5.0-beta9",
3
+ "version": "13.5.0",
4
4
  "description": "🌯 🌯 Wrap you tests so that you can test both behaviour and components with less effort.",
5
5
  "type": "module",
6
6
  "exports": {