From cdbb11b14aa3cda27feb5a6f4f9fd5f2da651a36 Mon Sep 17 00:00:00 2001 From: Chris Kruining Date: Mon, 11 Nov 2024 11:47:07 +0100 Subject: [PATCH] maybe tests are cool after all, fixed bugs and simplified deepDiff --- .gitignore | 1 + .vscode/launch.json | 41 +++ .vscode/settings.json | 10 + app.config.ts | 118 +++--- bun.lockb | Bin 354621 -> 348543 bytes bunfig.toml | 5 + package.json | 8 +- src/components/colorschemepicker.spec.tsx | 11 + src/utilities.spec.ts | 426 +++++++++++++++++++++- src/utilities.ts | 81 ++-- test.config.ts | 3 + tsconfig.json | 3 +- vitest.config.ts | 10 - 13 files changed, 585 insertions(+), 132 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 bunfig.toml create mode 100644 src/components/colorschemepicker.spec.tsx create mode 100644 test.config.ts delete mode 100644 vitest.config.ts diff --git a/.gitignore b/.gitignore index d16c893..cd61559 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ dist +.coverage .solid .output .vercel diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5fc0918 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,41 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "bun", + "request": "launch", + "name": "Debug Bun", + // The path to a JavaScript or TypeScript file to run. + "program": "${file}", + // The arguments to pass to the program, if any. + "args": [], + // The working directory of the program. + "cwd": "${workspaceFolder}", + // The environment variables to pass to the program. + "env": {}, + // If the environment variables should not be inherited from the parent process. + "strictEnv": false, + // If the program should be run in watch mode. + // This is equivalent to passing `--watch` to the `bun` executable. + // You can also set this to "hot" to enable hot reloading using `--hot`. + "watchMode": false, + // If the debugger should stop on the first line of the program. + "stopOnEntry": false, + // If the debugger should be disabled. (for example, breakpoints will not be hit) + "noDebug": false, + // The path to the `bun` executable, defaults to your `PATH` environment variable. + "runtime": "bun", + // The arguments to pass to the `bun` executable, if any. + // Unlike `args`, these are passed to the executable itself, not the program. + "runtimeArgs": [], + }, + { + "type": "bun", + "request": "attach", + "name": "Attach to Bun", + // The URL of the WebSocket inspector to attach to. + // This value can be retreived by using `bun --inspect`. + "url": "ws://localhost:6499/", + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e57826f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + // The path to the `bun` executable. + "bun.runtime": "/path/to/bun", + "bun.debugTerminal": { + // If support for Bun should be added to the default "JavaScript Debug Terminal". + "enabled": true, + // If the debugger should stop on the first line of the program. + "stopOnEntry": false, + } +} \ No newline at end of file diff --git a/app.config.ts b/app.config.ts index d2f21f0..9c8e86f 100644 --- a/app.config.ts +++ b/app.config.ts @@ -7,69 +7,64 @@ export default defineConfig({ cspNonce: 'KAAS_IS_AWESOME', }, plugins: [ - VitePWA({ - strategies: 'injectManifest', - mode: 'development', + // VitePWA({ + // strategies: 'injectManifest', + // registerType: 'autoUpdate', + // injectRegister: false, - registerType: 'autoUpdate', - injectRegister: false, + // workbox: { + // globPatterns: ['**/*.{js,css,html,svg,png,svg,ico}'], + // cleanupOutdatedCaches: true, + // clientsClaim: true, + // }, + // injectManifest: { + // globPatterns: ['**/*.{js,css,html,svg,png,svg,ico}'], + // }, - // pwaAssets: { disabled: false, config: true, htmlPreset: '2023', overrideManifestIcons: true }, - workbox: { - globPatterns: ['**/*.{js,css,html,svg,png,svg,ico}'], - cleanupOutdatedCaches: true, - clientsClaim: true, - }, - injectManifest: { - globPatterns: ['**/*.{js,css,html,svg,png,svg,ico}'], - }, + // manifest: { + // name: 'Calque - manage your i18n files', + // short_name: 'KAAS', + // description: 'Simple tool for maitaining i18n files', + // icons: [ + // { + // src: '/images/favicon.dark.svg', + // type: 'image/svg+xml', + // sizes: 'any' + // } + // ], + // display_override: ['window-controls-overlay'], + // screenshots: [ + // { + // src: '/images/screenshots/narrow.png', + // type: 'image/png', + // sizes: '538x1133', + // form_factor: 'narrow' + // }, + // { + // src: '/images/screenshots/wide.png', + // type: 'image/png', + // sizes: '2092x1295', + // form_factor: 'wide' + // } + // ], + // file_handlers: [ + // { + // action: '/edit', + // accept: { + // 'text/*': [ + // '.json' + // ] + // } + // } + // ] + // }, - base: '/', - manifest: { - name: 'Calque - manage your i18n files', - short_name: 'KAAS', - description: 'Simple tool for maitaining i18n files', - icons: [ - { - src: '/images/favicon.dark.svg', - type: 'image/svg+xml', - sizes: 'any' - } - ], - display_override: ['window-controls-overlay'], - screenshots: [ - { - src: '/images/screenshots/narrow.png', - type: 'image/png', - sizes: '538x1133', - form_factor: 'narrow' - }, - { - src: '/images/screenshots/wide.png', - type: 'image/png', - sizes: '2092x1295', - form_factor: 'wide' - } - ], - file_handlers: [ - { - action: '/edit', - accept: { - 'text/*': [ - '.json' - ] - } - } - ] - }, - - devOptions: { - enabled: true, - type: 'module', - navigateFallback: 'index.html', - resolveTempFolder: () => './.output/public', - }, - }), + // devOptions: { + // enabled: true, + // type: 'module', + // navigateFallback: 'index.html', + // }, + // }), ], }, solid: { @@ -81,8 +76,5 @@ export default defineConfig({ prerender: { crawlLinks: true, }, - routeRules: { - '/manifest.json': { static: true } - }, }, }); diff --git a/bun.lockb b/bun.lockb index 624c3fed3705ab6c8095def7bbf6a7c1eb57b483..ff7924ab4808825499510d9299999d124b9d2eb2 100644 GIT binary patch delta 63624 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 SPyZ0Zs>lLz=JW*_taAaj+nr+o delta 67270 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

WMp7aVq{>@U}Rv> zVuXzC>N7Gh7%(z07=iLGBLjmOD7!K;Fjz7&)H7HyLI!(n85tNr>vJ6$Ap^axj0_B* zrR<>bU2jInm~I#&0|Tfq0F^$V!Uj|$fhr(Sg#)T!Kvg4X7zK1}7U*oPEo=-7pcDQ; zN6{SwHB=cH7(hn_f{w`oo%OYlO`3rLbUGO5Br(wOWS}F?%GnqgD%cnpw5NYeWY(?+ zjiOqzGBAKfNv&BK7(k<-pg~X2Ag4VmWDwJlm4U&Dm4U&T6*2}18gm4VF@nYvL1T!X ztPJ2GLeP*PXb2EAOo^ips^y**iaTL14A||149lg14Aw=0|V&T!zD}% z3`?097?v?Xj*aePVqoZJVqgHB%L!@-gIe77EDQ{wRyL?nZNKARM4O` zXgnG;{_H$`W)icxA86zcG|~qe#RH9*g2qTeW1^r@U(n&Zpre98vjz&F8#tI57*s$b zOw0@npotvN6cj5cyD~5^fZEho8K%o6GwaoZ=HfsNG*AZ+)Zqh-EZH(KFxY`oGU%v! z&;%cdW@2Et$i%=<%*en{!pOh?I&pdf69dCWCI$x3fRZ;81A`9}1A{*k14AGa14A$q z149TC0|RKl=rl|1oRNWH1tSB)N=60-&>af17#SGm zFfuUAWn^FgUHJeSZAxZjV8~=-U;tI8pe7QiRRe0pfLbk}#s?ed=vYwe0#wf)0rj;Q zAtOkj!~UW{V=`L3D8Nb z?ko%p9xMzDpl%VU8|2Nxz~IBez~IZmz~INiz~Ilqz!1Q~zz_%;3;-RU4mxrjbaE`H z=Li~y2aUUfP8SEAI1ZX^0?jUgW|K^r85lq_QlP#xsA&vp;)1%tpl&ay6$|Rsf?BDd z<~69V-p$Cs0BY-j&h0K|WMC*|WMBXt^{}6b0enb$J?K#Ra3%(Z2qp%GNG1k`XeI`R z7$(Sw1Nc?|&|Dj6ewB%VfrE*G0d(-a0}}&-BWOC5iGkq>Bjg4O(CrkU9Z1taO&mtZ zNJI-G14BC_149QR0|Th_0&2N{S}LHn+Z0fyWn-uZ_qRd)>nc_ThWShk44|{vC0H34 zqFERiKz%Gw52KWYfuW3rfdSMJ05$w;LERV@&>f}>44}4rD+>cd8w&#isBI2vi+8aw zF!Zu8Fo2rOpe8b?NepTNgIc_x7A~ko3u?j61Pum&ny8@GC#Yo!YDt1xj-Zwzs9^|d z2!a}ZpoSi(VFzl+f!b|(EDQ{wQ}GKxWj_N01E_Hi8UO$_p(_{}7(n+mykulxc+JSb z0P44a`e~p;>p^|9QYHolP=BnPiGe{C)EETyuQZq#7(g3mKnK`^?pokxVqkD)VqkD# zVqkD(VqoB9VqoB7VqgFrXgY(Hfng>q0|ThbG@F%yVGb(;1L)A)|11m)zgZX<{;)7G zJZE8GILE@ku!)6%VG9cb189H&bm~6Hz6Q|15fcML3ljrFJ?Myj&}9gqofDwj80484 z7?hY87(geb&SPa@0G+zKjfH_>I}4-*3ECq7YBauNW?%pv$hek`fngIH1H)ft1_sbb z6lehGEi>fkL(l{wXs-4ND6fNRM+OE48Ab*MWkv=DLq-M$6HxxQVPs(NWMp9QVPs$c zb=*L`O3>i{RyN2CqAn`~186)Rw8I!Q1`isM0G+k0$HKs%#lpY<8j}GH^neC{)L0l8 zKnFmB28cihLW2gBK%-Bf)1-x2z?X?KfF_hc6G)&5qX>rSUKz|@^`NN|&_p!oY<68{ z1_sdFFlYuFH1!U;5dt){4(g6p;Vug%w*Rz7|CSza# z9UclA-3A>d3OZO6bjWB18v{co8v{cs8v{c!8v{ck8v_IAa8l4grJ#Xp&_SjFYzz#b zgH1t)oO-e`Fu1WXFxay(FgSn)w%HgMK!>A(#+5;brJA!bFn|tGH3FUEsSm2U*%%l! z*ccc<2d#nzm6g~S7(fHbpo3UJhq8hWXq9ARU=U+tU=U|xU;v%uD$K^f02(g_jSus& zF);A6F)#>#j?)Akt;xo~@Sl}|0kq#2bZRW<1X<8n@K;s_2GHrUpp#}nr_R0t`T7Mb z1H&~|1_sbMwxF|ZLFe3p&b$R3oV$*dfng0R1H&p-28I=^3=GRy85kC`GB8X84Mc(l z8CfAm4}*>^R$^sfP-bOdKxTtR*+8Reph-&5+5%8igD`095p>ZQE1iGcxh zR|M!(peQB=hFB&B2G9^KXh;@xd&hLpP%0w>1L(>kP(KhfiVErrN-#ru!P{9G7QP2n|s2hhY4jRNn6RT(7W`lH@L4%5*K}1l9G_XPj5787e>}6$O*vHDi02&9> z1NEw)X$D;#XlM>J(8UHi2p4n+EgJ&^j13x&19itCYU(jv50OAofeCUf7ig?Wnu&qI15_x1 z4#(?bWMBXdBEg~q)UyTM!f=w6fdOVQvM*s`$nv1$dqHDFk!+ZrLRN=tPCd*Z(74Yt zRt5&pxDK)c&_DxB4Z1k8q1e>G#E{j2Mn^!w4>hYEo@hW4P(ipDG9P9bNFB%kn4vH} zvRaU%VbKN}6@i5&a-xN>>lqk8DHwDI9OxpUkBkfqpwWyv(BuRY149!N14AVf0|V$< znN%hQ2GE^4pnG=Ym>3uom>`>tLAeKXAqL1nptH0=i4^7-n4>{*$ZVMW4v;Hh5-=KF zF}gU24^xB8Miv8!gD^}Cln6nNgoOl*b^=|e1R62{`2wUEgh2{H7?v1eG-z~W5+efx zNbLhqhn9hX;l~W{$cPwdjR)wO4A3eV4`}1tifOx0KJzTT08p@jDiF{{F;G=+3tGzo zT5!Sy8HO=qf(*ZcCMQ5+HK3iKpkM}_R0rCT3_8gU)JyKcKX+@Pj5sHTB6y+PAj zpguWhkQdZH2bGneYnnh;IDzsWC=Y@z2Ra1m`GDGQpuQ!j6$;9rpaveORayh>XM$Rr zpuT1`69WUNod;@lg8HE#^&oYiz9^_q3Sxt1BSD=Ikb2Oh0H{*}69=gS-T4G+xgv{| zfUY+x0(AtteJ0JSErL2U!M6FQCv`!~_}2 z2KgSO21J9>2uLkR-yBf0RXuOBya~bTEWD?04n`Jr5#8N zbV(OzAQ05o2KBi?JqOUxj65>~gB&vhgDf)xgA6kR1E`jPRYjnB7}SmeRm{T73=E)l z6sV~RT00Bsk$~3Pg4W=IhIBw{cDX={c|oguIhdzkYGT%#&eF`RBlr?J{s|fjeG2NN zPfu)Smajj_#J~W$@C!652^yW;&BVa4lZk;LgOPy&@R22g+gF(U)RBSr=W(5Vif z8^%C#Fi(K$8qnAeXo&fC3LIN~odK5HF z%E-WQ0@Q_OVqiGN$iQ%l2{JkXQU@BY1r4df9CroUi3E*gfNmoL4YPuVTS3FKpkZ3j z;1oy=$ZTYD5bSz{;UGtVEWt*D29!Z^ph0DjVGo%Y7#>3hnD2ue3aR-RPJu!QDh^Ty z!jG637(i>SLF2)o%OlS*LiixLDWHXSpq2y3rPwS6jaq{&2Gx=K#0Jsz$OgeI0MQ^rK#DK?Xq*tlM^=N( zM+7ru=pLpHv<4fr7XLV?tN^(LqzOcWTm+**WBnivpkM=ufz-gnK$?;HAT~%XJ{sm| zm{}n8cR^(ZvL?_PdXNN245Sd`AQ&InH~7Rra-cK;G6NJq|@}Q;hAp0N=sb^qtW@cajP5Xh0X%O~e zhLriBnLp46IFf>e>(Cl6H@@^n# zcoj5T3|ST`$-vMsyTRsWsqy=#2pQ1wc4-EN2KPCfSw2$h7a?Ro%Yo$>7#bMv{1KQm zqkaVkBWS%I7Xw2>R&h!`Xo>CW#^>86UQ0Jc=xGEk`{!q1Xh^%i!_IX68!ryVI0HQ+ z13gm)*nTwIize-cu0mM|O%tZ~b}>tufmZhMGB7mMv>v+6BfZs>39Qvp&x8R~LxT*x zzW-J4!3)eTU>QRbJwtGb;`b#2psb~B%6oHG4n z53@1j;^}{Tm?fFkFisbk!7Msmx0l&mW;bXx0RuzBmX~rqA1XE$WGz65~wBfn!bDxPZ&PdNv&ya!P1|xXEZ^L)nMgHsZbveL#P4o;H z7+x|?KiA8gCjA|%Lj0z^(wsG7Ak&TX3_yB0ru+9Xr!$I7-`>Z(RT$LT;AUWGn5ZAs ztG3nFQiQR6dVN2$BIDBO3;UUknKm*_zt+#3#%ML&b^^08qxe( zZ~E!U%#t#jpz0=DzfsQWoz;O*cZ_%16lMw2Tf7Vmq6`cT^P~-SU4EGyg;4OGmw`cy zfuSMD?t-?Atl)Bl4C{2?Da?}6(tHpFtKBkVi|p0sAQTu*Z=3>-?%7kAXEX9nH=oLE z%yffs`n=i964MJ-F-uLKHeNs^_-Tpkp6K)PX#Pv49dlKMW^qZ#w@|~Ty*-4Y0N%w&)Q9A zmXfX&hd4I>L%EAsR|qq>Q~*1+XL|8;W@E+$)0a83rhkTmDV^K|-mt(H_s*$E0@*!FJMi7C4)i_KZU`N9As(=U%h_{h*y zl$pMCF0(Jwd&TKr<}&**E}HH*k6DrlTGmc4na3=}^jvxRgn7&oW^pQzjm5T~4{SUo zV44AT4LHFpQGvuWON3F#S+-S2!IpuG)o&`(@6BVDU|c!<`#ff2n7PuhE$kUTYZ_SW zx4J`v#+ZS@VtV|1W=T^wHE=V$LE*>;<{O5tfh>$hdf?b(h*x7^kYZqH(Dr@#sBXiR zlL(p0>1*dROPWnqV_*PPxUM=3Y71`OOh71D2bGz&ZtB^x*B4t5GAGrh|C!G$A^lX1 zfdN$hK6dWwJbKP|DnbR*bo~XO09R*V02Qm%i{^S&gx_>TD6ogh+_&;G3;F1rkC2I* zUb}!e9M>^>p&4>#K5ph2NH@d{2P{+^j_#3$2DjTrr=H!fs0mU*rWNjIShZ~p(9koXN8>)-%_zF-lvg!D{( zNC5s6OwImha&{&-a!f%<$7;Ib24+dd&gpL#F-tN|nr^>@S#rC=VrCXb=}rTPo3^ZY zRK;(;?h6xRogt(UfG9INX8`fH@63JXkGXo*F)@N_UeF4xn@|}G*VIKx%;M1?8Ax0| zF__-BggK4riQ)8bOPGzAJ{eBeTFUHW`pOg%Qj4?7N-O_G%Yp;I&{)ra;fE zZUL#FewaPIKV$vlsbI4$K)&~!uDgs`QaaWG5`fHBn>X5IO}htDV5(=JXTeZ1J#iU0 zc&b6voawt?F-tOSx0t?R8M6e_S&Qi(UNMWxn=mjuvVasBhp)T5X?$L-0?sbry!q8) z`oCq&5{zuq#g{X0g%(2R7zL-#UBR5rs5+f>CG$&IY_hFl4uBR$-~!)-QE&RvRm{ew z4wjHIc2D@Hvnk2x>CiARU|`6C9!8NOvW9z`kIO%>3^)e|Oy^zA?8_K4J$f~>FRo^i z5d#CbnIt*=&T8g4j3U!3*D$9;oa4)wHC=x#voX^ni|HwAnT;S$1|=160$e=(^jc;~ zX-O+cBH5O zX|~uN(t>?*H}H7oTiG~J+5*cn9Cd&sY+0p;$_F@=KnWXE$r>^+oOhUhXCt$O%q<5< zx?GcQxFzRZ@;pRsa?o+Qz$Ru1(?Tam@P}T0qf(VG5D6~8!LshvB21tb16V&;l_b+qhv{oJF-u7Qb%Hc4k_uI99k}@|z}^7Y2R_s9Z(^2| z)^mYGW7U3<2O@%^KcNZ?7#NzS3vXsNW^9`7zM0vVaWOdEFkNz;zF{-7gbeQRyX!jr z$!2CFX*qXD6z;m4RVTNl5R!YrPGp*HxP@7gQFyxd7G_^lWe5N;MB^h0& zOK)ZNmA>K)DMrf_&(`)lm46HNBRH2sd^LT}R%R)t_ukWYY-KiL`r$qO%~oa!#)9eG zpO_`5%WY$pGOhN7*!1VR7n5tqxel-iV9(%|DVUzSjagE93bYY@@815otBv+rg4>PY zd;)HaOET@?nZ9QmvxLkksKSF!C$10{cmIx1c!y{Dhi%LfrdV6uV51nJ&Fw`i>$2W) zs9r+o6`5|komo;^9jbss&`x^?lCbB%|N-ZjibpXbbuf!#j7imrM=_b!F4{ zZ)cWd1UI-v6v4L6gDOrE`@_jEFY*nccoXk*z8%aGX2+l^PJC;SuUQg08KDAeOB`(K zd*10WJD4S;S)mPXUU8R~^VXFeN9dKF-oJxck`dhQ7Eu6ea_56&xr+-0WRGaP^hYRG zoPKu)v!wLoP)J3k6d?ZP?>?qD5m1-g6jY)toG!SNS(0ge=ysi*%rcCSLQj&>VS4f| z=0>I)jN6~>VrF7w`Vcn#)o$h&Q0eJ!_AvV~Dop>lmsxCj;9h1~M!o6zd%^vhiTjx) zr9C4d2}UVKDrfcrb$M_BW(cw_bo$=C%#zaak&sd(%J8#Hd?8x`6C=2(Zpgp@HdK;v z>2&UWaPydcM^1Ox$DAh39R=~m?n}>-Rupdm_3I7wK-Dcn?DT^m^={K|?_)M*WS`Ez zpV?SuRSd)#Yxc5jjg&eBv&Ddc;k(@Qxc$r$(mS9{of@{-*|t4P^AKf~)%1z`nT;92 zl;re#`oQ|dso237-y+x0BTFLOh0>&SyH+mbl?#KLxZG{P)>+4{}rfK0|tiq(-{vj zOEPjzmj+Ry(@hUCYuippgtTyZMIknRI8s|M=lYq;px8737g91w5T8Zvf5$rK-dhc* z&kPwD3a8IK#4IWOHwjVz&s#O=wV3FoRwl+c3rK5>Yx+fyRW;KW9%dGq{{Ij&tIXPD zNMZcrS9Qjrh$%~%7^fve()Ce?=?aILC8RGUL*hRr^6;T~{0mr_822Va`fr8P*Is6p zH2sncvCoj}<7+K95f&!K2g#7$HI_QV3{sqeodB*gKz7I+bc7~N#yPj$zRw4RBD8{o zx1El(SlM)qr*X96dl*&>MTs?nInXYn#*@)?H>huUG-E)LlLfSSBVrJ#p<8Q>O z0~(qLWG-ev0<6YF_eq9>C1_|0)POc+V0fA_J>eMhIi~HI z(+!R@OUPj9Jb_v=1`G@bGpDB@IM|-&Qc);WV>^-jzH^cIjVUZ_;8^{Q|54Tu;|P z8+?Cr7&jCsx!hu6{9ib|?KHE3G>$%;5d%Z#^n<6FB^k}9-v&{$rq4HIk!0kV&VPnk zl5z2L%`?pLoZCwwBQ8ACC!S$8mR2f*gxobg%RC`bZ%?pyj6e?1o__xfv!rQP8N|OW z|F_QjEg=djZb50wfPq2J9+E?zyxApnK;iF2aEsgw)YzLeec@eZNye4a*Pmq;XEtRJ zoSt}=S(0()^y;(BlG1xBAo>5{zq9K!On7I2y$tSxf;C8*V(mnNMwA(*S3(?fWr6)G z$A^DF!-ddpZtV2GAS)n!0TyG1M;6l+E--6xsn|g}-4MP6WApU-bIg*`6RRNJcDZ(V z=9B#rpjZU8;fxp7%?zFteoC(o>_!ZW%|_f z%!<<9H4xK7+Y354d1*~81A`(1LxaGp8U4HDU5+s^8tNH>2eb9-Ae}^kh|5)? zqC!iU7@;LNgVS`|i_FH1_0tP4GD|Y{Oz#F!Gp8@T$ovx2W1Mh_S;F+P6r{XaTG`+J zHzx$tRENemPbnmea^~9{dlfiqH@Nd@1llYlH~sDEACgr!%c@nx1f(S;BNj z6C@lAZD#&sIy;2{TzP@g7K36aMCPE7_1AcxNvFZd4%`ce)(QukAc zt%eK?r<)*Yfc4gI*W3+fH-L*naNvS#1xUrj2xdbwqa^kbK5!$XXL|A#@Ce`ZE6l#o z5k3QE0|xLIpD%QHZwuPkmh|x!NWT8FduMyMWN8!=BWRl#XgVi+}K%77;cRJ#&WVt<(E%FpIGmFnn*F{_YyH1f#_Chl(uX z%tj36(-p6S$Jp#8S;UzQ7=orByumEVm^htL7A#*dT@a$MX8Pjm%&v@m(_da^wq~3) zJzj)Gl+8rXf?;d>bcY+v5;E7@A>9#2k=2<}>%*$Sfea3QOs7aNx=sgMXa=(oV$bwX zH<-;BA#7#?28bdS0|uxGtRT-+PrrYYS(52}=k!T8nT@0ip*{5%E4uivU1I~)#wL)V zNvJ}Y`>@pS#(Lm_;I8X*y<5x@jDpkMZ!sG){dJmNbBkF*+Q%7^C@w~Mi60UaP^oCaBX8p=~_&`|-PiI&%^QBNv0yo*~Hj2c}MsxzFswm^ppreP(0E*6DZeGfSGCoeGIs z)_3)}U+?g^g1rlF2w#WF7?hFVEvPKLH52sGodB7|InMf36HP$m`u$>7;C0M+SJqYo-m6|7kJ1l#yD-d`a@=GXfRE$dB`lJJPoSqc`KwL@j9!zjnm3( zJ|ymq^~@N+$qk-v9z0~WkXE0;zyO*^bGf?|E`qmYxvs(nhP+5ASzc5g#AKTVZ97bI4H0a) z;f^TwWTpo`W|m|$nw|}!peBKf8gOodn1n3sI{orvW@A$C zoUuYpjY6D>=ydBR%)X}mb0Aq~rQnSZ6Qs7>WMVV`P32lLFyzdIq@{{K=MJX+@&{G! zpf0Bg14H`sy-%2p85yU4e8LQB7;!&kZe$Fc-usl#%uv8Bt@qmc*ZQpbZ)`)2hW%#P)tjoUiF;WjZ<(TB*|d2Z~BZE%zn_M zGwmg_6l39Z>6grsjIGlf-!lu#gKH&*X^=1(8clDw%50LJ3_Vx&N3U3g$jNfhpgm~L+kk$2};A@ zLV;lhROYXKlXrcyS|CDZ8PrC3i)O#8c`XVEnT?Af>Hg+F?a%K^y(Tj;*2jUGgC-0N z#}-2}iv!0Z?X^Gb{1KWiFNWmLphc&)PtNwtN60*eI$_(I8x}1!3P%t!u%meoRXo^z z+UIX6Lgp9Lw8Dvpi_~<|>nlazEdea+0GJ@nGOi_%q@5t3R~mTQ>JmZ^`r-|QjPMdj zw_Q+0UN~gVpBEyGP@gg=ErFzVHt*x})z{p5UyYDTP6VwJVPJT-hwWeKD}Fohkd3*X zp$Rw@F`7>|SjQ|gUF0FN!1M=w%&g1?dIn&jdfdU6lV4f@I%7_-;?-jD!(uAnb{V)w zgEM6?V8#>7?Kt$X7{Hp(j?UcYtisR(GrhzY3U4q7teTfA5-c1nW(*AAi6luG92Guj4r(Ncch+txgR z#0z*@5;Bt~!L)DnbgtLTMof=ZPq%x`EWz}4_4J6>%xR1P)Azq-HkQHcTC=Z#6lfxA zrt`gFmS9p@GhO2ivk#Nen&}tbGfOaeu9-gJ4YP!F;u?q-3%U*ZZY8nlfU9~?pPT_) zzeqAwubF=D4YPz+mRtrkP^g}8|Xx%7DwC9+h4uu&5a|YBnG+`sCFjfi{z)(s2T0!H? zZ6BD8%&>HC4fG5_VSK`$wiMN zwqkxoe&Nt+-;jYpVAu2pCKk|0i1e=M3g4L}WK?!RN+ms;!>KR2g2TXS!3Cr7uIT~H zEE3a?d}fwna@aNf0mugLUDMb7VwPZv*fs4BvjkJ#uIYMTm?dQDcR`wWykbA1KJ+}O zg_>fIn*?n^gWQe`os2)2{SpKLRvuJzUhfQ)6e172=UvUJ<|ieF-yQLftm_(>pWy} zs2`@k`o=89gl4cz(mqHrQ}l23uWOHbRKX!&1nPakjE95-p2&fk4-eE6dmu($l{s)H zc*_w`0SIl^-Ptq!!*^y0rj-5D&-_LN%XFI`%u=}G!i0eVWW?)!;VETa{hy=Cw0HhgqYDGK$4OaKNV9$Z8uCoWG^ZjI&ka=_f z(z?6Vd{9E{+(%dfFkoOni#j|B?)!o16MiyFm~kG2B+0iaPhNiOsD`y#4H+0D4nl_8 z;`|;2zYNrH1iQmf57ae+Bvu*ygOI|GpJm>ocq19uM1T*l%Vd zvsS3x60Ij@?u%IY80dci+t2{Y%TkPzm6Wc|u}@%O^=z69Xu%dpuL%Rg z?1R(y{bQDpNjVBh3JYd(naS_$c@NeLP9zYoh=S7K+e6b2u(C*id?~pyh77o?DXirj zxV!Iic6tvh3(ll##J~VcudtdEnmecSupt5nDUg|9B_}joVf7M17~~=3Xo2g1R$Z{* zz#r-YyQU|Aig4*&kUXdAtGM8Z{T*R&o&z@zAPyE~HD+M&hnDv^N^v7l-hw#G6t0-* z==tel94rmEW?YRJ7$8$ZOk13$3z)D-Fx_>X{)~gg2&wgE4x0Tk;bhTLUULyrtY8^t zGlEQiTTO4|WC5+Uo6X6h&B=TTQfPvQDn+aeK?AT@Rvdz+ehnBHY@ws9ZJu`Ci@$XI z6#;G8Fa-6DA)}Ym&A3>ERA6R`U52!%cvfAwV8t>AR8<)08G;sPLx#=8SS+BEA!5wt z4B$a(Ni&9i1_sQLbW=TZhCP=V7%UhV8s2S~80f zfuUhDD}TrWeLK){a_DgDo~zUMf%HCxnl2-znRM^LnNFBq3kH#E3=CSJEjlLA?3Ro! z%V9F+40hM1^YE}p$mCoD?-**ZVDH;G*;J_!pb8 z77UNCK_)~0T&U1GA~XlIh7#&;rt8!DKzenrLrizuwf?)s=YwZqdd(Svt}`&GFfcUK zcW^&!W+{J(kSV)9{SL@wbFM=|HQ~I}jDKs7PDH421L>{00dd*X6;ca!Dky0q^v=Hlahd1Y zz`&T#fltrmx{;k&tNb$yqR%-G=PT zdH6qdUfaH^MF_PKx2OB?vq;F)-)3MiVqj>vw&MBT?Pn)c!BkiDn9#go@ld z5MNy9Wfy%mbHxvY%)~p>Wdv9xWOm(w#QeUAmn-8#79gdo`*)@X2(U<)vE2n<1=aAt zT)WF_dvX`T43oPMz3#JngZzKr1+6{Kzirgg|y8&O82NTd9dd)F*e_Y z>>t>8mjS$>pK0k&lO_WWUGQiTcp1XEyVKu*T=x1dWCp&U)7^Law=afZ6=t9Tbe?MH&KS?aJeGBeEn%+2O`;06YAhUfkq7xv!kbw6Kmq(qb0j+!ht)ekt zU=Y7Q{evKjgem9%3ebj+EkEUMO=y_6Lx9otKExy6TOrOgsp*~Zsb&+X`DqT?Rb~b$ zWksh439-mA9lk%kNQlKq2Ddry`lcTcVv#V#T_~eZL4tb{MxZjD7c}2#%mj5T6C`}Z z(`-!ngFtt3LUMI?8 zB(v}-q<3)cxRKrQ+fJY|z(CIs)U;pobov=l773ZNPa*Y%yWPp7OeZ&ix}c!3TF~;Q zXVXAN{eL!HN{qz_W;A4ON|Fh~S)inbT@>MTkQ$PCOb6afSCC@?&9s8`gV!QJXEG(B z>l!4OplceK%^|A_ldNqNcXA0${zV5%WAX)rS&UJ_@qV0hm-y-$)wf)Qn@ zfXMV~k}Prr7ZyNF0c|cpT7ERWM2ba*2p>!Pe1H@LcjKS_cyMg9I5;yKf)?CDX33?o z4hVxMmBC35lrTV{15X(1K2F~tjht*yWc@x(KPST?Ayf4UQg+4|H+OEG@&5v%>{{?? zx{nNt1U&E|p+0?v42u*j4MGi(#%%~h6I4AcfS`ilsaZ)TtnS1bVsNKGLIk@SsIy_K zUm)vS5KTI1+*J`CQ=z7z+K8FfK{*hzk_NiW0TwBY;1;bY8z`gi?VUbBfd#hKLxdG1 z1`QEN)&{NckcBP!fUdlOr&I~hIvtqlumS|t3{X6yx`GL6C(IithQI_-QW2_8@$s0@ zLm1|Kl;Ff0b<)57K^oH&lD8#I-mWT*NQ9`4f(8>L;h;JSM`WPr$5aCjDik#^Q^AXM zK!pdy8}M9(?pr2UdP|&sP>sbH8km@g`k@Gm2)iL@mWKHB4mAv#c)*biaVxV4E8}!u zO%`#e3YhDpPp~qAHxRB)*k0Ou;%XftAfZ7AO<{1~L4{F56k$4477_%okb&?(VR=py zR=kL?8G@E=Kuw1@66!WoZD@jU3&1%Cq7Rl-pv^~6sSgS~Ht_O1h!R+Nf|ZA2=5!7n z7AcwKJdEJYs2_fp&$npJ2TchW=z*FA44ZhS+v%`uk(tNK$N<`z-y<>OQ0PrLP{#u_ zD`~*Mu$*@~pDv4p*#=%l2G9WqRYjXmI^A4)4AkWY8Dh+UWrhUQuhcVO*u^{jf&q(! z%u!y5{W;%bSu-0eL0fh}E6q$87%uQmpP$CVWrVPpW!qKZ`1NvkY)FbBHr(tv>h8VJ~? zo=^hThe=v|x||`4gp8^<#Hu{3Yp4S6ABLMMCCU zD2W43MqCp>r%8iur1hF^X37%8XfeIhltrG= zV){x`7I~xd=8$pk7*)BJO*Mf(&=0mimp_~_{g)|=oZ;Uh$cXx)>stjjUY4m7DTcI8 zC*IyUOJ+`|hKUVSSapo*0)7P4_ zXl%b{&N6cm8)!L2amn-rek}6!5VpRqK7^qQY7U#|m84gtRurTrm*|#M7Nmj}cO<3e zC1-#bMTwbtN%`gF8I`)3#kzUej zN-Zg=uhdP;FUn0Ufr*xuWabpZIK_F11;rWpa7mCwsYM`bz!p2Crlf;yFUibJ)i2A< zNGvF*)J@6Hh3QW!$}cZQSYDb5*Q%GBRh&^$QZRjmAB(soTo@V-VADZCG5w=Giz0t= zVzR!jesW^6u9=>>p5gRFCl*C1ke=caeTb9vb)gKHCM5}|JlH?_y82)mE(?o-Q(mkJ zOnQc3Yb23ES6^2ji8npKk423Sv|>bGS0B78NY{A!gFF^xd6-9G0j0024`agYQk;H1 zjYVmCVi${|2-Ho*1(hI$1(k3$A|Tr!!cdm3vEKBJZ7j+#e?p>BUsoT(faz3%$wMMt zUl$ttFnL9N&VkLBgA!L_adB!', () => { +// it('should render', async () => { +// render(() => ); + +// expect(true).toBe(true); +// }); +// }); \ No newline at end of file diff --git a/src/utilities.spec.ts b/src/utilities.spec.ts index 46e096c..6b87caf 100644 --- a/src/utilities.spec.ts +++ b/src/utilities.spec.ts @@ -1,22 +1,430 @@ -import { expect, describe, it, beforeEach, vi } from "vitest" -import { debounce } from "./utilities" +import { describe, beforeEach, it, expect, mock, afterAll, spyOn } from 'bun:test'; +import { debounce, deepCopy, deepDiff, filter, map, MutarionKind, splitAt } from './utilities'; +import { install } from '@sinonjs/fake-timers'; + +type MilliSeconds = number; +const useFakeTimers = () => { + const clock = install(); + + beforeEach(() => clock.reset()); + afterAll(() => clock.uninstall()); + + return { + tick(timeToAdvance: MilliSeconds) { + clock.tick(timeToAdvance); + }, + }; +}; +const first = (iterable: Iterable): T | undefined => { + for (const value of iterable) { + return value; + } +} + +describe('splitAt', () => { + it('should split the given string at the given index', async () => { + // Arrange + const given = 'this.is.some.concatenated.string'; + const expected = [ + 'this.is.some.concatenated', + 'string', + ] as const; + + // Act + const [a, b] = splitAt(given, given.lastIndexOf('.')); + + // Assert + expect(a).toBe(expected[0]); + expect(b).toBe(expected[1]); + }); + + it('should return an empty second result when the index is negative', async () => { + // Arrange + const given = 'this.is.some.concatenated.string'; + const expected = [ + 'this.is.some.concatenated.string', + '', + ] as const; + + // Act + const [a, b] = splitAt(given, -1); + + // Assert + expect(a).toBe(expected[0]); + expect(b).toBe(expected[1]); + }); + + it('should return an empty second result when the index is larger then subject length', async () => { + // Arrange + const given = 'this.is.some.concatenated.string'; + const expected = [ + 'this.is.some.concatenated.string', + '', + ] as const; + + // Act + const [a, b] = splitAt(given, given.length * 2); + + // Assert + expect(a).toBe(expected[0]); + expect(b).toBe(expected[1]); + }); +}); describe('debounce', () => { - beforeEach(() => { - vi.useFakeTimers(); - }) + const { tick } = useFakeTimers(); it('should run the given callback after the provided time', async () => { // Arrange - const callback = vi.fn(() => { }); + const callback = mock(() => { }); const delay = 1000; const debounced = debounce(callback, delay); // Act debounced(); - vi.runAllTimers(); + tick(delay); // Assert - expect(callback).toHaveBeenCalled(); + expect(callback).toHaveBeenCalledTimes(1); }); -}); \ No newline at end of file + + it('should reset if another call is made', async () => { + // Arrange + const callback = mock(() => { }); + const delay = 1000; + const debounced = debounce(callback, delay); + + // Act + debounced(); + tick(delay / 2); + debounced(); + tick(delay); + + // Assert + expect(callback).toHaveBeenCalledTimes(1); + }); +}); + +describe('deepCopy', () => { + it('can skip values passed by reference (non-objects, null, and undefined)', async () => { + // arrange + const given = 'some string'; + + // Act + const actual = deepCopy(given); + + // Arrange + expect(actual).toBe(given); + }); + + it('should return a value that does not point to same memory', async () => { + // Arrange + const given = {}; + + // Act + const actual = deepCopy(given); + + // Assert + expect(actual).not.toBe(given); + }); + + it('should handle Date types', async () => { + // Arrange + const given = new Date(); + + // Act + const actual = deepCopy(given); + + // Assert + expect(actual).not.toBe(given); + }); + + it('should handle Arrays', async () => { + // Arrange + const given: any[] = []; + + // Act + const actual = deepCopy(given); + + // Assert + expect(actual).not.toBe(given); + }); + + it('should handle Sets', async () => { + // Arrange + const given = new Set(); + + // Act + const actual = deepCopy(given); + + // Assert + expect(actual).not.toBe(given); + }); + + it('should handle Maps', async () => { + // Arrange + const given = new Map(); + + // Act + const actual = deepCopy(given); + + // Assert + expect(actual).not.toBe(given); + }); + + it('should return a value that does not point to same memory for nested properties', async () => { + // Arrange + const given = { + some: { + deep: { + value: {} + } + } + }; + + // Act + const actual = deepCopy(given); + + // Assert + expect(actual.some.deep.value).not.toBe(given.some.deep.value); + }); +}); + +describe('deepDiff', () => { + it('should immedietly return when either `a` is not iterable', async () => { + // arrange + const a: any = 0; + const b = {}; + const spy = spyOn(console, 'error').mockReturnValue(undefined); + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([]); + expect(spy).toHaveBeenCalled(); + }); + + it('should immedietly return when either `b` is not iterable', async () => { + // arrange + const a = {}; + const b: any = 0; + const spy = spyOn(console, 'error').mockReturnValue(undefined); + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([]); + expect(spy).toHaveBeenCalled(); + }); + + it('should yield no results when both a and b are empty', async () => { + // arrange + const a = {}; + const b = {}; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([]); + }); + + it('should yield no results when both a and b are equal', async () => { + // arrange + const a = { key: 'value' }; + const b = { key: 'value' }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([]); + }); + + it('should yield a mutation of type create when `b` contains a key that `a` does not', async () => { + // arrange + const a = {}; + const b = { key: 'value' }; + + // Act + const actual = first(deepDiff(a, b)); + + // Arrange + expect(actual).toEqual({ kind: MutarionKind.Create, key: 'key', value: 'value' }); + }); + + it('should yield a mutation of type delete when `a` contains a key that `b` does not', async () => { + // arrange + const a = { key: 'value' }; + const b = {}; + + // Act + const actual = first(deepDiff(a, b)); + + // Arrange + expect(actual).toEqual({ kind: MutarionKind.Delete, key: 'key' }); + }); + + it('should yield a mutation of type update when the value of a key in `a` is not equal to the value of the same key in `b`', async () => { + // arrange + const a = { key: 'old' }; + const b = { key: 'new' }; + + // Act + const actual = first(deepDiff(a, b)); + + // Arrange + expect(actual).toEqual({ kind: MutarionKind.Update, key: 'key', original: 'old', value: 'new' }); + }); + + it('should iterate over nested values', async () => { + // arrange + const a = { some: { nested: { key: 'old' } } }; + const b = { some: { nested: { key: 'new' } } }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([{ kind: MutarionKind.Update, key: 'some.nested.key', original: 'old', value: 'new' }]); + }); + + it('should handle deleted keys', async () => { + // arrange + const a = { key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4', key5: 'value5' }; + const b = { key1: 'value1', key4: 'value4', key5: 'value5' }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Delete, key: 'key2' }, + { kind: MutarionKind.Delete, key: 'key3' }, + ]); + }); + + it('should handle created keys', async () => { + // arrange + const a = { key1: 'value1', key4: 'value4', key5: 'value5' }; + const b = { key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4', key5: 'value5' }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Create, key: 'key2', value: 'value2' }, + { kind: MutarionKind.Create, key: 'key3', value: 'value3' }, + ]); + }); + + it('should handle renamed keys', async () => { + // arrange + const a = { key1: 'value1', key2_old: 'value2', key3: 'value3' }; + const b = { key1: 'value1', key2_new: 'value2', key3: 'value3', }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Delete, key: 'key2_old' }, + { kind: MutarionKind.Create, key: 'key2_new', value: 'value2' }, + ]); + }); + + it('should handle `Array` values', async () => { + // arrange + const a = { key: [1] }; + const b = { key: [2] }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Update, key: 'key.0', original: 1, value: 2 }, + ]); + }); + + it('should handle `Set` values', async () => { + // arrange + const a = { key: new Set([1, 2, 3]) }; + const b = { key: new Set([1, 5, 3]) }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Delete, key: 'key.2' }, + { kind: MutarionKind.Create, key: 'key.5', value: 5 }, + ]); + }); + + it('should handle `Map` values', async () => { + // arrange + const a = { key: new Map([['key', 'old']]) }; + const b = { key: new Map([['key', 'new']]) }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Update, key: 'key.key', original: 'old', value: 'new' }, + ]); + }); +}); + +describe('filter', () => { + it('should yield a value when the predicate returns true', async () => { + // arrange + const generator = async function* () { + for (const i of new Array(10).fill('').map((_, i) => i)) { + yield i; + } + }; + const predicate = (i: number) => i % 2 === 0; + + // Act + const actual = await Array.fromAsync(filter(generator(), predicate as any)); + + // Arrange + expect(actual).toEqual([0, 2, 4, 6, 8]); + }); +}); + +describe('map', () => { + const generator = async function* () { + for (const i of new Array(10).fill('').map((_, i) => i)) { + yield i; + } + }; + + it('should yield a value when the predicate returns true', async () => { + // arrange + const mapFn = (i: number) => `nr ${i}`; + + // Act + const actual = await Array.fromAsync(map(generator(), mapFn)); + + // Arrange + expect(actual).toEqual([ + 'nr 0', + 'nr 1', + 'nr 2', + 'nr 3', + 'nr 4', + 'nr 5', + 'nr 6', + 'nr 7', + 'nr 8', + 'nr 9', + ]); + }); +}); + diff --git a/src/utilities.ts b/src/utilities.ts index b5e000b..8408a4e 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -1,5 +1,13 @@ export const splitAt = (subject: string, index: number): readonly [string, string] => { - return [subject.slice(0, index), subject.slice(index + 1)] as const; + if (index < 0) { + return [subject, '']; + } + + if (index > subject.length) { + return [subject, '']; + } + + return [subject.slice(0, index), subject.slice(index + 1)]; }; export const debounce = void>(callback: T, delay: number): ((...args: Parameters) => void) => { @@ -53,23 +61,19 @@ export type Mutation = { key: string } & (Created | Updated | Deleted); export function* deepDiff(a: T1, b: T2, path: string[] = []): Generator { if (!isIterable(a) || !isIterable(b)) { - console.log('Edge cases', a, b); + console.error('Edge cases', a, b); return; } for (const [[keyA, valueA], [keyB, valueB]] of zip(entriesOf(a), entriesOf(b))) { - if (!keyA && !keyB) { - throw new Error('this code should not be reachable, there is a bug with an unhandled/unknown edge case'); - } - - if (!keyA && keyB) { + if (keyA === undefined && keyB) { yield { key: path.concat(keyB.toString()).join('.'), kind: MutarionKind.Create, value: valueB }; continue; } - if (keyA && !keyB) { + if (keyA && keyB === undefined) { yield { key: path.concat(keyA.toString()).join('.'), kind: MutarionKind.Delete }; continue; @@ -112,40 +116,42 @@ const entriesOf = (subject: object): Iterable = return Object.entries(subject); }; -const zip = function* (a: Iterable, b: Iterable): Generator { + +type ZippedPair = + | readonly [readonly [string | number, any], readonly [string | number, any]] + | readonly [readonly [undefined, undefined], readonly [string | number, any]] + | readonly [readonly [string | number, any], readonly [undefined, undefined]] + ; +const zip = function* (a: Iterable, b: Iterable): Generator { const iterA = bufferredIterator(a); const iterB = bufferredIterator(b); - const EMPTY = [undefined, undefined] as [string | number | undefined, any]; + const EMPTY = [undefined, undefined] as const; while (!iterA.done || !iterB.done) { // if we have a match on the keys of a and b we can simply consume and yield if (iterA.current.key === iterB.current.key) { + // When we match keys it could have happened that + // there are as many keys added as there are deleted, + // therefor we can now flush both a and b because we are aligned + yield* iterA.flush().map(entry => [entry, EMPTY] as const); + yield* iterB.flush().map(entry => [EMPTY, entry] as const); + yield [iterA.consume(), iterB.consume()]; } // key of a aligns with last key in buffer b // conclusion: a has key(s) that b does not else if (iterA.current.key === iterB.top.key) { - const a = iterA.pop()!; - - for (const [key, value] of iterA.flush()) { - yield [[key, value], EMPTY]; - } - - yield [a, iterB.consume()]; + yield* iterA.flush().map(entry => [entry, EMPTY] as const); + yield [iterA.consume(), iterB.consume()]; } // the reverse case, key of b is aligns with the last key in buffer a // conclusion: a is missing key(s) the b does have else if (iterB.current.key === iterA.top.key) { - const b = iterB.pop()!; - - for (const [key, value] of iterB.flush()) { - yield [EMPTY, [key, value]]; - } - - yield [iterA.consume(), b]; + yield* iterB.flush().map(entry => [EMPTY, entry] as const); + yield [iterA.consume(), iterB.consume()]; } else if (iterA.done && !iterB.done) { @@ -168,7 +174,6 @@ const zip = function* (a: Iterable, b: Iterable const bufferredIterator = (subject: Iterable) => { const iterator = Iterator.from(subject); const buffer: T[] = []; - let cursor: number = 0; let done = false; const next = () => { @@ -176,7 +181,7 @@ const bufferredIterator = (subject: I done = res.done ?? false; if (!done) { - cursor = buffer.push(res.value) - 1; + buffer.push(res.value) } }; @@ -184,16 +189,10 @@ const bufferredIterator = (subject: I return { advance() { - if (buffer.length > 0 && cursor < (buffer.length - 1)) { - cursor++; - } - else { - next(); - } + next(); }, consume() { - cursor = 0; const value = buffer.shift()!; this.advance(); @@ -202,15 +201,9 @@ const bufferredIterator = (subject: I }, flush(): T[] { - cursor = 0; + const entries = buffer.splice(0, buffer.length - 1); - return buffer.splice(0, buffer.length); - }, - - pop() { - cursor--; - - return buffer.pop(); + return entries; }, get done() { @@ -224,14 +217,10 @@ const bufferredIterator = (subject: I }, get current() { - const [key = undefined, value = undefined] = buffer.at(cursor) ?? []; + const [key = undefined, value = undefined] = buffer.at(-1) ?? []; return { key, value }; }, - - get entry() { - return [this.current.key, this.current.value] as const; - } }; }; diff --git a/test.config.ts b/test.config.ts new file mode 100644 index 0000000..9cae201 --- /dev/null +++ b/test.config.ts @@ -0,0 +1,3 @@ +import { GlobalRegistrator } from "@happy-dom/global-registrator"; + +GlobalRegistrator.register(); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 65df43c..2464cc2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,8 @@ "@testing-library/jest-dom", "@types/wicg-file-system-access", "vinxi/types/client", - "vite-plugin-pwa/solid" + "vite-plugin-pwa/solid", + "bun-types" ], "isolatedModules": true, "paths": { diff --git a/vitest.config.ts b/vitest.config.ts deleted file mode 100644 index a13a54d..0000000 --- a/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import solid from "vite-plugin-solid" -import { defineConfig } from "vitest/config" - -export default defineConfig({ - plugins: [solid()], - root: './src', - resolve: { - conditions: ["development", "browser"], - }, -}) \ No newline at end of file