From d6317b671fa0e59eaa1132fde78464cee7bc7e13 Mon Sep 17 00:00:00 2001 From: Will Hunt <2072976+Half-Shot@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:19:02 +0000 Subject: [PATCH] Add Playwright tests for URL previews. (#32519) * Add Playwright tests for message previews. * Fix displayName * update snapshots --- playwright/e2e/messages/messages.spec.ts | 48 ++++++++++++++++++ .../messages.spec.ts/preview-basic-linux.png | Bin 0 -> 7450 bytes .../preview-with-thumb-linux.png | Bin 0 -> 15769 bytes 3 files changed, 48 insertions(+) create mode 100644 playwright/snapshots/messages/messages.spec.ts/preview-basic-linux.png create mode 100644 playwright/snapshots/messages/messages.spec.ts/preview-with-thumb-linux.png diff --git a/playwright/e2e/messages/messages.spec.ts b/playwright/e2e/messages/messages.spec.ts index 04763e1079..641929e61c 100644 --- a/playwright/e2e/messages/messages.spec.ts +++ b/playwright/e2e/messages/messages.spec.ts @@ -9,9 +9,12 @@ Please see LICENSE files in the repository root for full details. /* See readme.md for tips on writing these tests. */ import { type Locator, type Page } from "@playwright/test"; +import { readFileSync } from "node:fs"; import { test, expect } from "../../element-web-test"; +const MEDIA_FILE = readFileSync("playwright/sample-files/riot.png"); + async function waitForMessageSentStatus(msgTile: Locator): Promise { await expect(msgTile.getByRole("status")).toHaveAccessibleName("Your message was sent"); } @@ -208,3 +211,48 @@ test.describe("Message rendering", () => { }); }); }); + +test.describe("Message url previews", () => { + test.use({ + displayName: "Alice", + room: async ({ user, app }, use) => { + const roomId = await app.client.createRoom({ name: "Test room" }); + await use({ roomId }); + }, + }); + test("should render a basic preview", { tag: "@screenshot" }, async ({ page, user, app, room }) => { + // TODO: This should be changed to _matrix/client/v1/media/preview_url when the matrix-js-sdk is updated. + await page.route("**/_matrix/media/v3/preview_url**", (route, request) => { + const requestedPage = new URL(request.url()).searchParams.get("url"); + expect(requestedPage).toEqual("https://example.org/"); + return route.fulfill({ + json: { + "og:title": "A simple site", + }, + }); + }); + await page.goto(`#/room/${room.roomId}`); + const msgTile = await sendMessage(page, "https://example.org"); + await expect(msgTile.getByRole("link", { name: "A simple site" })).toBeVisible(); + await expect(msgTile).toMatchScreenshot("preview-basic.png", screenshotOptions(page)); + }); + test("should render a preview with a thumbnail", { tag: "@screenshot" }, async ({ page, user, bot, app, room }) => { + const mxc = (await bot.uploadContent(MEDIA_FILE, { name: "image.png", type: "image/png" })).content_uri; + // TODO: This should be changed to _matrix/client/v1/media/preview_url when the matrix-js-sdk is updated. + await page.route("**/_matrix/media/v3/preview_url**", (route, request) => { + const requestedPage = new URL(request.url()).searchParams.get("url"); + expect(requestedPage).toEqual("https://example.org/"); + return route.fulfill({ + json: { + "og:title": "A simple site", + "og:description": "And with a brief description", + "og:image": mxc, + }, + }); + }); + await page.goto(`#/room/${room.roomId}`); + const msgTile = await sendMessage(page, "https://example.org"); + await expect(msgTile.getByRole("link", { name: "A simple site" })).toBeVisible(); + await expect(msgTile).toMatchScreenshot("preview-with-thumb.png", screenshotOptions(page)); + }); +}); diff --git a/playwright/snapshots/messages/messages.spec.ts/preview-basic-linux.png b/playwright/snapshots/messages/messages.spec.ts/preview-basic-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..32981108e606016231115d04f3a9e3bbd3f52943 GIT binary patch literal 7450 zcmb_>WmH_tvoA4D5+GP`OV9v;!C}w@8{B=6;5q~tT!RM>5Ez_;I|K#^Zo%!~?!nz* zVBpT=+_&DhxBlzh`(@YOE!9=EtLxWY6{eyD!g)#l5(5JRM^;8s4Flr|59&SS`D4^G z2%*!7fq{o1EBR5wJ#Bx{OGDkVh5s1zhUD$H+)o4p3`s9P;uo6KTgh%#hl7Nqe3r!< zyG;&kj5i0{bl1x+OHD@f5{BJVhdm;O6|&UXCX^TsfB|JK(sRk5!0hCZpU)pf>NA9W zB6yyJ1%p4KE&LK7D2?<@jM(2t?wc{)pBc0+!!v*4yn01|k_N-!mHksRO~dRULy<3p z9|fMEn`xh0qMMbTu41D|TiBblM<^9FEJn7sw=<`!+-sV*AKlxJxn9j8 zdZ<>U-ORCsr!9nA-68MLVtgq|(i51!J$s^9?An-jR7+>APzQ`{NsVrjMzdLoUbGfa zr&52|xVUTgFG`rz*EjIJuvWVc|AhVn7;bGFN|?y&8)ZLa-9v^AR}S_$u6Nq0W*-U5 zzx^whtNZ(-DS#zW`@NcY>q>)~2gp3<z4ZE%I)+HYl<4fE_!;2Rl|GYm?41FlbFGXJRqg??*7%x5;&ZR50=Rs8u z(qpOV4>>7x%$fm3w8!XJ3t$mq7HDJ&zV%Ou{XDg_^U*qbjH&mA5Z_D z-|Iqpk)A_DPGUNZL`*J>9lEU{BaDlu@pF#0rh^|;cM)HS;3qknC?+epjM$bWBh|C- zwRg@6+Pd+OHrE0!zn%l zgD#Ng1ri#|XEy+LFr{*tSi0~=itb#?u%kHwxq;DVtaM=Cu~A{pv@d@Ah2h zo)d4B7TWB`${fZ5LJwD1W~V}r+Gua3 z>7|*%_}{8~N40Rmk||EMqEF!$=II|xnwbQ;7P72pC07~+o!v7i=@1D-p&_-^;d}{E zI(s9cgnq7rWX(0&2&Ps)wB=V06}cflRYisv-rIBQBZ2K!Lp?9kwz}!QBJSF0y8QT~y5N+25 zOTrNDBaF+ulrX(-<#sGVCsg3-AC`3n?yl$0=K-$FTh0<&lIcUb;_UTxr6Fsy#RWS_ zg2ZB80ty!td+eKOdz!Cnc-gPW-6pXa2S6)t+ot% zqR|dv(94{nTE-n_p;;Aq@1QL7hFI}UX2Dpy>rz@T;~zkkJZP+EDBpby?`aJ`p&K_Tg2+(XMxAdsaE{BTUW@`WrfSY zwKo{F%4rb)#;m!3BAzIYrHBPk?*6tb>GirSc`9_EA$fGf7jW{gSIq{kz87Fu(G|E4 zxVOLek09YL!tvU;qA9&OTsyY0GQ1-SUDj!wi6SN=CwI=TvAG+zI3D}pq&!K?3sX1f zm4fE02~-{dfgE|Q`?yqGFYB5NcYPP#B=K_wtPTX6i#r0qHgEB z054u;B7YPDQC=AK4;_8P(gVcmc|!`y77h=J*PUB)A<=`G=2yC(50o2Djl4YOm+Cb( zN;e*m7lDJdC3LsQdt?n{9%+@U3|}8F#jQA^*^qWajvPHerqY=H#P>+c4wvDlP#=NE zQv!dHrmfWYMrY(pfqj}x6&~+R`)V()=^PCX`94%dv^Nsk$ zY<|VA4_tp;SzO0REYYJ^`X&jrB>fw$Yd4k zt!(S9Hc6eeG%E=|?DvBwr?(WxpSkn(ir}*bIS*v!G!6AO%^USqIp~ecA#2va<{wb~ z`NWNUIK<}%-_=^O*1rISU00Be^t;vM`olnouf{Iv`45_nAmM4JXrX7?O_KUiPCm?MUSmE z^DdOtGmLQO^Lv&TI@)ShZ%~|9?x^n__+G$$&-QxO%%+`ErJ$nhJHIzy3e~$s)}&B9 z(@Tf^uFs;|`()}kLWeB-6P|)d9r+Qd6PSdVBtvdgzV>#bCC^z6CF#(jj-Of$0x39Z z`I_r@s`Vkfqok??Cq35w9aCom;}rcxfq%7H(wxuSajma+YAXbNf9N^!5%%+#5+1l$ zXU1GssAS%Aw+xOVCSsKF^YI;XD9?WRX;yQ#zr2B(q=kmxqqF0n@=&2zOh+xjsgU1s zd~IUYxORyvF9C2#JQfP*EZ0)g9TE%J>$M@403Bu_n&O6?a^!y`!BXBSg;zIN1NK0mHDqbUaOQpK40#HupNi8C=chNoYtH&6}OQg^en{VBZh#Hp`6IlweiK z{63nshlI~|eWX04Y-xH%gpAEqLe>rJZ=^%nMGJD(C)a6Ttum+rqzsyJ5IPTQ^HFyR z!s?C@3vI*wdU5>+Y~LqUU$11{Ts$y(=#8I zqE?e*c`oWSt)FRswYo3r3k@4hb;PMRU4#$Z)CAy%?ySkM{|`W=Tv#YKQd%w2|?91 zwY`Fo7V3xhXI%?z&0(UHCcs#O`&~!di3XXQBU3X99rM3N%->ZE<-kdWpuGE$=_BcL zz1-Bd%!dal`7;hTAhlV!{NinIt&JLE>GcgaGmE|u(%q^$MDo>L62_Ir5LS-ktENTXcc_sGa9g9O&U2&JI~4 z^sf^c>J&0Hb&t#GUcU*2NY)jxfMzLL`!y{|SH9kjGl=>-(=Ju>7*3Cn+2~7`hK*N{ ziOlPiXpc9m-Bs{%vNgN{X<_Bq*iB@0>r=TM4JS>kK2|Hmoj>keqV1gOoqZf@bp)se z_!`1PfA;Ylf|m(FLUFXvuKY~iR0Dz1tP|S0s%$k6NCiXUfxu?FlI*z~kMhl0S=SuD zOTelvmcnaRxsmU-o@}xES@NIg^Vk>2_mm*d@}>07#r8$=m&td8Ji9P`48uf>O&2WH zdPr&0sXhu_n5ahBY!FIJJ0PLFn^p_s%iufT-hV(58!x<+Ai(@Z0P#NG%R-Lmqnh|UhIrWxoX=KEDMaW$y_$oT=~Y-b)?KUm z=NlF96-F8Cv?3UN247%T&YICZZm|7Td>lDOGuBG^%}ytdfJ^YBVu5{bN`hWseN%u< zNZiV?zwKXE_K&A(_RLhwfr6&LvH2Ovek4_h7<>Mp&yJOF)~Zgje$QJt)Y1_<+MO89 z)m&rm7HfBvG;o?UJ0Z~>#NE@iC)`AT7mJm{P1~^``!Te^@?DzhGDn0f^4X-Th4
5^a$wRyw^TskUv7VH(7(QZ~*KBNS{07Ep6vz;bo?y?2LG$=HN zWWF8Kb7lvbw^Z#Hb8(s14RTQY^mq!faM}$pYvs%g9>#;BuMq-apnLlvf7$3{y$kbc z*gJ00a4_bzFE=o{ $Pfzl<`q5{<^27LJcN0N57t+td(__VK{Ea;kAQsI{_Iisq zv~eQeC-rZ9-?#XDId0BdZOZb~_fO}jkIXtY1H^0YSKg3Ve3en{iq5h&){xi8KUBU} zoUpV$Q_q9v(YmoPD!FX%$;arHR~mYmaKnn&f{u7ytHk0*h`eT^oG*JdPbgK#I+5KJ zkM(a%*jo!qboi?_zYY}_?=$#{n#80o$M)rke*S#34U^C$Y;;b7qVA;*B-A?&(r$$A zcxqFjpVgB7KcwPp!6-}3}A%{~MY|5;CQ!`W%RukmT-bbTSJUj>Hd|G!h+NyZWOVk##@DlHs zHMyL2=d}+vr&N}g@2HMSG&7W0e{?fp%F;=JJ8#dbY?Vk0v&rL?_gF=j+_UrQDziP5 zFK@(=ixTH3(8lgW=K|U^#Mt9!B5*Uj3JMLf>;{$!1`C~|jDTQo34zpRkyry%2;7Wy zO(@sSQ(UXDli~pyHC?&V69xusL%f%w}Xr%f84gmkEKnK^EFtGb-%+RvUT;#Ty@8<_>H6L1@qv- zfh6DRy|2XL&WrZYdr^cH$H!b}c1Fwhl51RYXEr6sh*u?0-4{P;MvZqP?1IuBVUu{* zw$m&T;b!L}pLUpZy)0(&l+8p@gBp0X**@+8oKO!jGrzW^2(g%$y``iXvZ$E}0f=^2 z870@=R@2!yHgVTU+2hc-o$y@+RVRr*q%>Elo!mb%PU0|KEL9-eL?4M@3*P@wx(A-wOz@7~3IktVEO?*zK}WY%?qqc!MBRIQ^gxeg#=>nF;c{ zd|Kt3GnBx6O2tQO4X(-AGY?NMV|8ajNO_)5-`|Q&1+?jlU7~bNZOK4PN5A;)`!x zHZ45D*XzL(XIN%M{^QKj=!4d`p4u|>&R&UB0sil2a{j;4K)-^8e|xgk%6rnG55Mm8 z!siLxrrMv4{KWpx_bT?EgEuw9pZ$xiym=7fc2J=w)*03^;eVq6nGsBzmTqEJam3B}(XsmC>oFQ}@ZMl*zjO*u>MN zGCd&~Xmo3QBid|g*9BXKV>O+L>ZSauD-0*Uq_hQS8S#2@&~|upt8JC7G@>s+4v%A? zV7QTDLVqEMT8QPBkf9_*cOx7uluF$7(Hv115>6e$BYm7rQ&eatyQG>&`Z*){BHJQj z@b5f6&%vs|f_1+1fidi|^HJ!fK zCGR@VDQO<%1W+&zxi&8KEOEbO@n zwQhT$l&Sl`fNGa}d}`#bY5#`bL@y6L?PlLov22z}`X--pl~5vClqzW*rusm5a)f+C zY0z_trzR~-Op#I(n~dh*WaGdiYi~f@lx1-u%wQ_?p zJMHnG1o%;}Br26K%3ub$IwwPapD9bc%d|9f1LlzD#rQk7R6>~`1~{=Hw` zD>`h=$S(k`;>sg0Z&u61sakK|i*3eOhi5^I(Hp_)BaxoE2a0E#WTR>s-|!4}l-FvE z#Lf3uws zPn$-OKBw7AkkX1z&M_tKx*GL`%_>EJa*o%T&EHi$m?ao{=gFAgUd49dcj(gtf-NJ{ zpMWx%siCcpL9gj=d%=cIvgJGpnufzb8RU3wbKP&BrQC}B-mj(AQD+41IcI}O`hZ91 zNdDK6V_Dj)f>Uq~v6Qey$cV8N4ibwdB{i?aj(s|cO0EVg70b3vye}Ze?XHxTl_!HG zd`GBI#0-JiFDIBvc`{JWa!{H>U9YiA&drc{NWBU|PGggLCE>3MTMGaJ>{aV7Q@-vc zzR#||tp$i6`{LN3h3T6);pHc`pCnv_7-0;q-U^Lj-HC#R$*kKuT6+gU z(G=*U9LjC=fN-noV3HzG-LK{MNCnRWVi|de=7NQyRLtAfT7G{qC!^e^_a`?}c4*kU)g$JL~@Qa;QD)$#);a!O(S;7)3FAe5*g{5u3s(nDVa z0U2*G2~6xv5rL$4()5H$oTgE=2G46w6vUklT; z&fc|Q7;&-TB1ibq(g=SrSlk>j0|^P@Oz^?hrI5U&jfJi7rusfWg@wn@cxLfG1)(Iy zlA*+SR&E!Uo-TI7*P?y`;V!9O--~x?`iHBUh1KH-$*>XM4GI5f_9>-BkfoyapYs76 z0Pgf)Hy5d*AJE;s#r<$MVI;Q5ef#sDbfEj2!b@`(NN2yfV;v)RvAcA_(EUZdfTkv! zrZ%0r|DO^Q2NkaiNnxV-uYhlMrkp>DM`d!oqs*kI$c&4|ntPSb9?`_fgfXNQ!3N>y#nDzmnj$sZv+wbefN zlhc~K7iF+&k5DWUF)H#0fIO)C+efaN8{~B`+K69vjxRU0N+=4WzN%CfmE5+ripu7U zW_SoX&yFPO(~Otz;f-~`xK4-VwON7!08x#5BRq7nH z%c@EbVtf{;%?9JxR=@SY__uoJaK+A7lOd|@F=>)lYsp2X8qsmmxrNp@=J5g^n*OKt py*mJE@WX?Lrj7{e1rvRpd4eH}>sOx~HdSx_jm~-JxF;rLbO-zC=Po!jh2|S3yF0&V%?rjQ$Mq%OvPD zfP{pDBqRPw%`^RI8N*O*yNUnIBas`HYGz&?g3R^tJ@PXdB$-B19JP;Do%LZGcI%LO zN1X=ij+_S2gieDuK*9!7gF%`#&kY%q)I=_a1^GD*jVbcyzaO;eYfS51%y)d~jqs{J z?|p=Kq@|?`x`0!-@fPl3!lz!*960DW2q}=zvBaLFL85%V{tD5&4}71FjA#RK0=W^* zSDf#TFAyz`7!DZGAc>)Oksz9n=${0hBU*Gybc?6YlqmmiVo74~u*HHBMOi6JnN@}T zY0+VhP1h!`vdkO2ohT9jeJ2Oo_a{Do&d#5G`}5mf;9@q8;$aj}W-hdQeckl!3(Xg@ z_?z+$lRm!zl&6ltCZ6j@2|o4d%vR>hOIbQxxa-Na$^D|f$^Y2=!s1O&I4Zwerfzxm zxSlY7`|J@L-bl3#rujG5&wnTeCDGun8`yB@qhlP&_6>AZ|6%rX02}2KIS0y*kQx&o zrpNm$(aJbl>J7K5Q<1s`Qv=#3&3x^AH8GPnT}?s4_v$9+o2b6zADG>wH#tb^i8d?X zhZ8}7jkISYE3N?IQZ2wPBYWoA|{kUGn&``UshS{Wepp+U8 z_#h#vAX?=`E001^}4he*MV?9j_UE)FGX_;8D__*Fro2p*iVq*72r+v^CJ%b!y z>y`6nnDTfYp@QnPLU*!#uC0wnVZ%!ncJi^7x|d%LGL##w2oPKXi~PIi=POCuPQF!+ z#YZ=J=n6c{PkeF62k;Es^p(6=>O3^IiQ@aEyk>8|hN7J39&gnx&8K3#{djP2zgM;8sPKAEh`?x}g^3Z4wAS{Lg{f&jML+8?6R594sy z*`h-RBUNg?N8|vGj(c0(X=al3@Y9YooVs3IvneCqQu%r|KOl2{RoJqAS~qPRcNry~ zBI-0_>jn*(L1qiKt+1t@&FI&^)ouy-$;CzeN>*DVQA2kn^QM8$WykY#K+D{s$8nhr z<)GW>D$JVhxX+thaRu((R5S!`I=0~37V6zB-0cvwDTx)Ggxp2L?>ryJ^=|s%nz(n_ z2st>K?-a=1xy>NEQyX6=x8P2@b}sAd&)Czcn|tIa=SVlRE4NkV<-+L<7X>k!R+dI; z6?dqO&Y26)7EAEB`t#eT{kP`!bE3}Wx?%IZ9)Knz@j|10&9$+LR^pMKTt@KmMFROF^bKnZ{;;s zf41=5>RV^R)+F@8*cXN!`>eFqHrF`KaxP9lON=N+$?gkAlOK0Ha(HvXZF(^_d;jS* z{+bNjwK=Uo@KE<2)ta>Hs*~1y&`!zEZ!zCus;XwkGAeU_ud;?DC5v`8sb3{o$tSfl z+XOSmyF0$J^zLY96a4+YZvk2&YBBPQfvOr$dS$;ada$L&XCYN0pukRHKK67Jn3|>V z-Xhx7Ie07Z)xr$TvIHojnC1<}KVM^5i;y6vPYOZ??g`8D!87v%(37~V3Uq^nNbmM- zC6#{C%qGB=QZlv!88$%oR*(mxoxhHn%yJqOqRwU2Szh-Oq8_TGALZyHd-lse|%8Do=nh#WZzpi(yBx5sU4^VU$mL%`IDXOyuFO z^7L56yTjbXwHW?|Q1Dh#2jF@!Mfyg$}EM&J$vZB z0bCCX00m0}jI{a~&fw6hQOL9m0vocbHGUds{UuCTh zlDO@S(w>S!s-oLOlk{H_KXzBLE5IT6|D5~78ur;z*=b&%!g$;v4J9w>z*Af^G<>cO zF8T^M%PqpX5^Cb}MLr!VxE2z+4Q~Mpkc_Q# zr~gDM!=m-F+0q+3A(;B}!<`q)v2QT@&3hiMDw#2!#(p(_)(A5M?^)QdRED5ORo;ew~pteIbqrj{-&95(Nz{`6Fs3j8Yr=X3Wp z7dB5ted?L=Cip3GBN1cG@<=_+07=*2zZa!nbTpV3xzxfp01)u<#6BJTl|JkQyW_ET zd&9TYR;F{`E?*H>%(o62vOytGyC{ZW{r+nCe%%%+YNnrJUWot3*WP6|J+)<{re99m z`N36vMi?H`)a$cemG8GXv(R;-bEk@s@#}aXu@kHBZV8J<8{230J-;RORiGF?X2h$f z1tyNsF&R$jC|zH|CKpQ8+^*uS(K(l>Hk6 zI`#QXl+@sq0~=x2&@tvqE+e~fi}y~sVhnbRmIscfm0BX(s?HY}>$ve7P?YL5Sub$c znBp!_2&>h5hqypZxM!~HciadGe69-4P?S%teyjKLl=kLZ|Ii+>vs$g+yn=jwC)Io_ zL${o|T`*k}k1Ms?XMruM6af<9XH@^RbX|unsy7oG*R&gh9@*V2)L?C5WMfnc;s{G9 zrE_SMv%ncI*orA*-5S`gZjC;`WZ5`sktcIbZhc3P7XEHmd;(QFj;|tA=4jrwld$>( zSzF)U84U0^G1QX8wRJ=2`*a2p6_)Xi*bS$3(u$MI& zoOGLYn<2B|!a4L+F^Wg%Re8sa3McQ&B7u=VT4o5fVt#rG*3;{7f zELfEW9#Zxx+m4|`*zlY=1$?8@*;ExW>&(A)r_NdpZC)i`(ryPY(6O8Xn)mij)y7MjQ zNOSXof6U=uV1kSiY(T4j2=22*)TTJ>|Cc$u-eO@s|_+UwHL*VL~HfU3^#`h)7ll(0Q-JEPy;l?^z+Slj@u9|`jJ+-;DTMZQbDFU4LoOrpcV6;shfFHg z=ma}9ceX~kG2?Ta2&cnpDqM-4tGRSkR#63|O|I*ert%y8g_hFlI@vtnJCF9zeS0fx z^E$@bK1oo?@=T83cF-_y8)}~R8|$HOnis4}1rj6?eVXkS`uBxlNueAKl8`Nzf(S#E z_$BCE>jyN0+`ah~29`lUy5_#?s0tb=u2hpf8k0}yx_};Y1YpT|m8rAgtlGI=88s!a zY;};Sic_h@eLSGe)g0f*H?r)#me5wNRM4yY!9?y5^7$xMYPUV@-BPfrR6dsh3%HV9 z8-K>-HPNc(@eb*H^RD^5wb-amTE5)g<3?!P4*di!R%d?~>W~7q!k*ywe5XrFJ`?r3 z#T!WcUbP#>%6HnJC!Z>LG=pw&AE*_S?V;RbX{kBBLH)UCwaA1Wi-;O%r}5TnJFon( zA{kX~Q^la{?_IP@ftI>=s=bVRM0RxBGHtI05F|I98DLvsU9MsY`kDW&Z&t;u_@KHR zw!S)}SN~&f>$i94CmQKCX0wO&=ZB9Qqd;Dt>p;2ZQ@|2ytC|U0r?-sxBVS_UHvn)H zY90nKs4zKkTYLl42c5R()IB}meGGGT1W_g~BbR(^MRy{TlzdlEdCS3KI8bDoeS5dv zb>3f=F z7=H7#b&7Rp(qj(u=_jmI=#J-&Sp?@BZBCnx)6(>zst=OD=iL4-I0@Y`n%n%Wv-*GS zP9}^)=He|6WCUwb8O8(Q*2lN_(0mb^m%Y$&D}7ME+z+A=b)pTTW10y*%LGrEL^kHh zMjCoL4^{0qB=x0|$<(WSI)*TRGj$)L&;Xzet&4CarrQkrsE2lX=GGOo2s*|bFq2lF{=oS zdzWArKb|bGl(M+A9MwuX3PsbGQcg(QQ%}N%B<lS+o=?(Ee^&~%u%+o8V@l@70)eb`dg~ym|bcq%`L*+`*0C1rO&ok zR;LA6c5b?7+4w(Lfa&9Lc zmK7ZPJvKp!LO*TMx?oiB1HTCT2AY<-Uv2*Ve1P$2hbY>CB`d^wrM~z!G;YIf$ON~t zxkweaP$z?tZ3%eavjSNlyyJ@oDDOR;OdYZ8_ZRs?r-mqg&R=hY#*3XF>{hQzhkF?- zPhRk2;%>z(@+%^)SNwedtLl!{bw^%mMG$TcR8Vyk1!pjXJj2{C_Xui%nVE$a!<<-| zT5m*H?gbSllv4juGq_Hz@1b0!3NYFTlHu{D7Y=XY`L2+sdv4jB)|Z;pu1g{O(|Wt) zO4B(WS8g+y|6sYM!0zwss7YY8`9)ZN7-%j}&Ts0sQMuD{K`Jdk_%px$LtD@GwOKd0 zR^@nwPRZXz=c|Ow0in$M6e~T)wT{zj*5oOl$%eR1z?`=$%>3?4dL6^|vbqTMffn2C zOe=Xq!_5}=vIAkI-@YY>wN)3ta00|s78KVokXSad^iK0!_QYs1?J-Yt+h3tjsE6?Sxr6Jzcd7Q5-|Q#&FEmCgL1F+l11% zZwFeyKeU4NMtAAUVb(hNi^qohH?5w zGdU_K5lt+sHg~z1)O2wFr3M-W=HzK|dJCNsO|LY9X78MRapuY6qDvJ051>N-UyxE4 zJ-=Y#;^NeT1VSz(dklWR?XsbrEnm^6!@r|k<9;_u>=Q(_B+Ie$A3$sA$^^VNv-R7* z`Q}hB-<=+j6a4sy5T5n?1b_$cEfrNbL?q z2Q;;R>oA<&DjQ6V40(4lcSaE2SJ{C$+3KB_h`LxE4>etTsn=UqatshxnNM%IF;+X+ zZnzQps?}3=wB>!P!8Mv7K8{7B18~d99CYZnRBl_mmo9{V^8drY+iCCtmY z0Oyz8(L@2c+*YD$_0FYDzdJ!3y}zBCd%Ww96Ntk3^+mz*40_c(_TT6li^xs1U>|i$ zmNe@cJRjjRTQk3=hWBWz^0pjDVhf{B?K^GR5qs}dQF_AJ%n%g{(p(?=IpSLPfgZaZHl(HH^D*V;chg+I&P5oggw`)*EO5qLuot|bxQ zdr5MVh&_VeYcb&bwo{W-m^NRrVgEk(V4u-IIL;Ec3N@`=>nvtd+Q@F8tvKo3U%gx9 zhc}6NEDCU2g}~t7v^uYcAHwZ?>^GYkP4Gr%=X_^0EY9A#a#jlSvg!r|2Sz!foj!fi_N$Hh0C1^&Z5m}fX;-Xs#`gXal_H%K#$@lnoX(;8im)FMpZdq7NSm}2e#A@LPP~9)wXi4D-jdXG;e96wml=7blmlR` zVCpxkV-CqJqDw}X1AHjL)|Y8!e_-!?YgH!zWQ(N4+nY45-VUstVfS?OxDW8HtLm$q zk>#P{8f&qyi+_=uW^q~L)oG)43hO_JtF4j)0`(d@h!HpRcT5(J%j22mHopsH8jr~? z>J5OS+uI(=7QMu53Ai9Hs## zd_y>vR|JT`+q}xXP&D&BqOb?Ie76VA|rT0O0XmWjAuywKy_-2{7i z{g2_s<;SjAB!U6s*-9D`?E4}?WRl~!U7c;62ah3!HYm27k5g&v+P0O@N!@~hFu?N=4t9+6%*+IOmr_x&y_BccHqc`enpC!4(a%ZYjkVA?y(Sqbm? z*fz6LY!`9W4(CMKi3#9G)hOKzGyFJGF5{CpGZzZMjQ7TJI)Zl`BFvoXaVAT8o)$Lbw+Bj66O5 zR@86eaE_|HWpBtc3@B>WIVTU^PFHly)x%G}RdfSo!p%GqhCbsf-2;=d>7TrJ;2?>v zg?h-a)E;(|`vA&$Z$j+c9zo{@o@Vl@zK>J6bp6Ko@Q8Me;JJ-~`ay*wRQsMq#^`{o<^2!8`dUcN8nFupFu+CzPEr<<=vvd-D<4&pPN zqz*tBkEJ3&PNBq?tg3B*rOxgKa3nLY0T(ac(#d&gA97LYqE9j`D~>q8gkj(_I60GD)tR$1o7uA z1c?|ClSMb)8Jh0$iK>J;ZP2!Y#Rz#)8oDPzs~wx#Bj!}2Am+PC&wa&_$VzV zK=z`r+wD$kWYxoO9JnfpY2GFwMcVhwjl~B%5N;Ug!Xp-^!a%a6dJTJ6CQs_#EV+RV zey~ZQlcZNy8tWldR|dxD_WkrSJqzUL`1Xb4u;R*I=O!h##!lh5hA@A!ro6Po!Qp_0 z-=i2G32BWm#F0=<-gWVRg~e!NIkbh*MoM!N}RuI7f`0P*?R*`7gRTd#22D5AGpJYx3)|BR748^&K54K}7ce{HG^4F_NzNU#>hJ zgu4`lb|aq}u3*o0Ht3|@zM+vun~Nx*;WS{tlZ}s1qrw?yC!n5|<1zP0>fIEuuBdRS zUB&~EQ&X%5z2*tyO}AfZ*{%tmjI6EKyq@0Qt5Q}l;Ad8IMur1@3J~LPc;kRy?A|~- zM7_YevwZQ)I#y@v&8<-fY}uJofvw1VHIwMu_2Z~bUvL@KONj;T%;^47Cy2?!)zpm7 zJf7@7gyWejj`duG1XvZ8F1Bs<>Nd$jj^RLO&(kUogWK>gG&tyim=x`LCGk&~2)a7D z#g9v;cJBTT^1gKHZ(n~e6ZH)c2Q{AV%KT0nfcohJq&kHBGHW1&#b5H0tP{knlC@-1 zfpIn6>rN*^Hwge74lCmnBmKVvKa&FSSM!Xq#!0MpVw)$VdPbBq|F1Lw~uPr9)X z_pIiBQ-kRo3I$g^k3K7Z{QFgf^3V5nXa8` z$0{zd9I7X7rJoVpqWkgW#Frr_*{2)3Xw8lG?Th?-G23FH`Z*dX?3jk}5oIgm<|Y|# z%XXo{`bq=}$B>%HdPoOooLbQl1ajWBdgVvfpHBVq|EKkE{j);5^%C#*3< zFkQO%B1rZOS;;gWZSa}!$}hU?tTc(9pnj=-%$}~tf)AHy&&ohGHHzW0`x{FcS;m!+_L2_z$?pqf6RTmOi;w~zmT#i zTZ=n~ew;cws`Y$l?m<*;S1dlkkOC>oO)%#oT~Lc)k+k*#7SL)Lvj*Xa!oUIW z|8f6@zA;0)`#Vdu6Ny<4M7Ku_+Gay^Av)8Z?=iu?%E8CuQ4fLX{o$tD^P?p2z$r??>y2 z9?o|iG9r>wNL@zC_3Dk_avcj^baZyWtt^jXi^CiEI&`GhS2awTcg)8~M|K7Fu-E~+ zTxkU!4;PO=Z#|6(5a{NZntXhr15Hfg_xnO5Dk4FT05Uji8-XswC@Mx1-HggN(VLM8 zFR6Q|>a?;9e~K}n6BWxFg|4Q&*EWCuOy9wI<5?#e(iK!G=J(ui^{^*(1l7-g_}WLGA!QWI&|Na(c+ptMtg;ZTC=FYe8k* zQyP9kY7C`_u<%HY@u{scubZR}UwaQcxyMlA1U4o%PH+~fK;QfjmIDTP+3INV6x%@fh2BRTm?5%yBv6;cu~ zinz&gh@o3hcj8@$d#6YeO1i|(AFN}F3-1h)(%5M)H2I$}ByN^jqOg zu3l60MldUei35~L53!tZxUEjPn4?OPP zgx5ky=C*N4h|XD)z7&$7G4m)7O zCAX>Nm3DO_KE4)S^^5Rv+9Z8J%R(}A5}_-;>34(sSi3C3$R z;f99+lb&CfxfY2%+?tsx018D4G#&{4%G}OIw8s&1rInkb%5ie&Ja)z3h(nnHaPWo* z>@`S0b@kKUoy`2@&WNJg3!(AKcGb*e&Vu~gJwf}6Zh(I0v0%VL*P5#OCK1?`z)yeS z$doElm5Y#lfTMV+zo8v6!-*!cqjLyKRD_qEIKz zhKsUGc?j|H?8ITnYE!HPVWHe?P8KeuCtW+4S~iz2n}skPGLw1vKF$?~#!bYDs$c)dhwjM!zgqZY#E@2v-CP1z5NgGS-(3a z9M4xbNeh^)bfpvbc^BNqiSV*zpNCPG_A7)@gVKxKOb_dNG&EPbFy;%YCHb)|Y%NAY z6+=1c?>6YcJ;Oebpj!`v1r2V$kKUA3s(&$kd3YDbk*Ll4m@(5H8eI;@)vNgKU4$8WcU&psjNOJ@MdM+|#%5Pa98# zdvoZDKCDeA)F6wdKfWeb0)}}UF`W=6)p$?m{RD5^tinw%MVBX6xwzi->Z}fyk6W3ka}pjYsd@+S=Y-vllqSNXe`@C^mH)TEFq| zzh6{bpM<9f+D)s%J(d!QATk;v*I&*|Txay|eA(K@?5vF$Vb1WK29_g})r@zde*n*) zA)T?mUbl6{fIb5vwfJITY1fj|tzFvKnlH4t{$^Xq%|op*e7`9Stor_fYoYz>b}rNA zm1iy50p_jMb$CDKSfOru{~?8~Xf*k|k;G{Kh8tb8HZ8gf*mHX9%nvTDbi3cYQh$;; zMk~r)SCMLXESdtBjB^SUBZk?TDo&&`N&FwJvf1366rFzuaxgJb;0``wEUz)QlrgE({=g_y)!v#jkYemQqmdRg zE*Scfl=_8$pd@ih%|Xi$t`)9K8tLcEfR=*hUS0(^uR<-s<4*WpooZ3yHBFGXmD{+` zb|I^6*u}w?;a{!xI~_^wQH=f=h01r#B`HKoLM5;4zV2=fD^5Xdd+QCBIyF=sW7F>b zq)uCj%rfOEa80zyhTAxAC_LYajd}#6KVlQ_R?q$9@>1;M0hWd7UFG)3mwut7wtcAT zR+nEmP`^<)fi`dmat>-4HGQeY4OSY^PA6n-*{Jma$tB#_Cq`VX;k}NZ=NjrZ z{yL+k20Y9dhsUn3UmTG}%v#=9BLCMiP9G( zBsnRAg_mn4m3m-TR=leqoA0MvzGs{5CnMKSVQ_y=!49C!A90%=XJ0LaV_STEK4?5a zs3?4Wve;1^HBNHnG%z`7uJ{u2{cyCF^G?3IH@+e)Gv&?lCD#=^NF|{bg!iVzWRsnb ze7Z`;sp}&3g^-WvSN$M2-3PHalR$bfkIpWm3;_Owa3c)moGq`)0Uc+dGfz2!=zYXT z=}C>>T!iT8(9Ul*kD2!p%vRqn7hkaLa08Zu`pE|OI1886o$|aPA|wMTcqsCYxPki( zg|5j$L)e-le^WjTu1DBaGE_J_Ex{_`w-0hQBNFPzliZ`T5_kT7_Lc!@DL|+#xP?2z~@1`b-V+-&rNGPI4^$Zw%s3gfsKD8pmGLHPl#p@ zr=xbu*!}xC<`q&FJGw>gP-jzGdgA3di=+Pm?#yY8PX>?GcvPV-!}*;+y+t1|=!;k! z$t?G5ur$tnw*VRdoWWn#}+w?Ox;tTXrC-RT(m)md*xFCsr;x38vhYqfI zh3tRMq-m%XzeHe6USf=bo0dd1{%kS_ssI%)$Fc|;iKl#Z|IqKsecx_CI=|Bn67M@h z1HD$ujvd!~tG7%vdn*9yUSLfOyZt`iW*cW$TrkkrXbT>eX$}vlpLZPUG@+niwHwN; zJaUkt8;%#@47fbGS)s+WI0&rgMiUhrxz^J)qEgtb^SO{q2@EP&`^|Sebsqcup-_6b zYwLHZyCDr1qlJx?&FQZ}wU=BdwaW#BA4*>PY7?fB*p~{rt_|U3=z_SvjS(Fd&DFTw zw3a#HYMPA0P)7~~G2^;0toGn*>x@G?L>-XFde-`MiOJmgg@@A2Q@W6KHvO|;B(X?T+oX&p?#C|;&hy7u<1&yN4Y&< zRoUnwnk$FI7y%uOVF%WXi*+ad>M!iAMv7ERa6gfg%gQ*ml7^tL0?uVn6!tU!E^dDK z8EMY-Lv3gmweoqER}>q=ckUF_WF7zO^_EajKQI4&G2*E;_+=@lV>r zjh24CG=2kjlL}^NOnnMupD#&B6n4Tkyy@;99W;Jh)+eXj4uDN)cf1;|Tj+B$nvAh9 zU^D@6pGptsl0d;BLX6eb$=yB9zF)EUF{>HLlC~RUR3rRe(OXc}I8P`Z zd7gH_D~)Hc16q?`ePgofeQ>F74_Lc4Ai%MjijW}T))6f}*-bCpG5z(NqBZk0F}RnO zUBAgz|4eKM8CD~|)S3XGYD!yOeY_{X`@%`*2c;g0MN65p&B88(KUW0a=9(?Fz?=;P zK7OZu=r$W&^?#u3aKteK?XU!UkO6Nw8fl-%CUU9|8i zlBV!%XM$J;_L}g&7tw=t1pF7#D%+Dmj-%YAo9xHg%|}6dr;L;)*8wZs&=hmiu4`v1<;^d>NJ6Kz8MM=S!yuJ%ac5XUBzMqn{26oSn%i=0xxK*4Scep3kt1xfB zOBdgTH3{C~aq}Ilz;)H!jv{)OXz^cipJsA$iZBjmJwZ%3T{z&18YGO`rt%DOAwA=p z`j(OpFPa)-rJiNj!gjAOEG4K{2cd$g!|@S;gx1HKPib^iVAOatR)kXF8}A}`*b~}HtNB-uhG}AXKwcOIfq?Xf@teS zHJOi%-#wHBSYyY7i+|B)(elvm7F0#>@jwHm7Bi5^mF4g`!_c|jib*nTYUBVIu7L31WaI*T6i zsJiOqXXLASk-0%U&RE_jJdP#~)lW!K_czg5w~sn0x}*8=y6l4~Quj|~0+VVj#ulj-u-SU(Q0w%I!^jgiesU&@ zS!6q7z7IlBB4!ojjfQH)LYv0^bzR$$e)SEXt7TjbI{bcS*JqhoLx)*tc<3l_!VEE; z^exhKMiHHKgNwGp_FhB+0)kf{0>iSwZ=H^1U-S4~F*J+X`gWHBB7Tn?kOeE7_WNG> zHzFcVYV5IKvA@2lTyz6OE(*>IrR;X?6=uA;eLEDB=5vBT%)jcq?V9I}LGRsE=hTc| zzu?qun>r!Bg)C}fM7=P1{>{WagHfN54ifj##G@tdvZwS~dpwThk;7lxzHqlKY1PAZ zo_+aaM!(B~UZVg)toJ?ZO4qz^E>M|bt`0(dpEFTm#kpOUQ!}VSSyt*Ft_K;^{jw(e zny5?<7EM&9BW$(M-k{$ad6$1-xR-Q%h4cFPKMb6#Yrbyd4Y{4of)+i|nL&N*S)Z&I zJrw!ocUoF)&$L@fn{hxsKs7soX}348XNWq)CzO`jJn_+SouK&qZ()D?-4O~R*YpX0 zbAR{SKcJ>`Xxit;W%$ND%_rO<*C^ASm*k_@5;~r>&i>$9j8rY;fIy;Y{WtrTN~$ab z=eNnSh<*9ql`>rqyVbBbVsvw#Hg)KS+M2yWT+@Wj^{@3!r@#jvsX6&74*8E2aaD|= zF`Vlvy}Tpw2*X6meR-L#$Ip`;Bo`lpd)>>f=Nfn}6!#Y$Qyn>EUgLK52YFJGE`6%B z8zRR|7Y{*zGl;M+GJPe{O}tFN+6~mNv+}Fb2T1}!em;)-!)MQsH*R31Q5k|zGp|2@ zi+T2RcTJN>C@=~^io}l_#xSe>UH~p36*3Fn&A@K|HsJdyl4ooW10^`)m+tGEnAXiZ z6uqO{y_jY9{oBVl13&M39{}84+?CjV2?4?4+#yB>q<*vHnv|JxrW0sp&O-Ne&`be{ z9#*?z^Jk71%{mtBuk}k2!41F3^R~|Ocq?Rze4?NrDVTl#l(W5rk2qzZj(p<2l95dK zHtSOLl|5DH;0vMOeZuTetkDJ3cRPgHq>mJVz{&(Gy{pJE_y_#r61(sL<0E)fN}_(1 zP|+~8(b=xFx#aW{OKP-VcnX6~@4qLG1=ne2u|IVeBV)4Q|0zaoaM3N1_BhJduqbjg z^!!=RzT@L|oruljE@g_!hjjUj$p6jQb>6 zb-h}&Sg5EcR^}d~^$e;rDS0KKzU{iSn%4N5z60@GRer7o3j z{Y1IsS^6`CU6~l|j&6(lKJlCP40nY%{CgIt`SfNx7&k1i<|Orv$x+i6!&}>T^_6m? z-pjLgKp;YTbY64|e*EbEN%}o=Fo;eS%W7|q;QsMzQ~mV#v;v~T8exzlAI+>&EQcrv zl*;QR2E;Y^Lvf<~{M*;^$sO0mr;?zh9F84Z^k=)1+NTnUZSMv!JxpJU61`GL()%Wp z7s$ke_5^2+W+`KtrnYXGdP#`(KPa7JpseTuDW6%6=74h$b}| znLIl7su${a)gu09EWsXph{*B#_OpOFX|(%JAm-zo&k)_rDc(iUv&WC>GM~TOcMdLk zwBJ2C4jGEYI5O-H9vWS)GG{@Le8pd-V_U5&8*%R{5e)VGTQ1y%)E}Fds4*(M(W5SR z!r#6c(8d2n*{}!etuC+Z9og>LJ2<=FJ@=24{sfC}|GL`iwH+Z&MQl14aXuL_znV&o zgC6W}hg9BY)V_!`7T>62(2SeR>tgn-vrK3SFiKW8FHwBUr0T-ZKaBZ zJTEU(r5O8p+ePf_El`}6kV7R~K!Y%*Xl(LoXRFmbNrDQWWLnv} z%6N==C_Z*EX_b($nDR4T!DN&I3AHK8=lNv5kEmjwWQ?Ff@CSMj``Mq#Rd6e_LPhNQ z>%D)=wQeh|Mx||iOI)XAZ<4Y5*3KTxO!yNQzgZ@=5#vBBL+#yra$PcYRRL!4uZ3NRk{Z3@9x=RWX)GaxNYWb&mB`^BczE%_+%>*-@*H3761v1 zW`i8424BTrBkZ!-vs3%My}8>+r>KdqngEHPJ_W3d^G+dEPM? zDO#FX**e)N*#3SjZeHTGjYn_HWYE)t?9mk-Jm27DH2vD8t5fs5M`0misi-Ipu!gJ_ zgj{m^j<3dIGeMX98N8bK>fFY3o8WzJ=Yk2;r$0c)lU*0is$hwqf=qU zd2Lms&92!1yHSEyE$+15!pz#rqPP32jOF=H$-U?@2pGH{)mNXQfA`$-J=uI4 z7i_bTWNbIr>InGa6!zdJuPNt~>MOeN&qgs-ts>HY(c`=>Oyza;6}3y&KdcNMm3oZ` zO^wk1i7L+jUcTPhfPx|e&eI$CSDju31Hs86Q$0RP zP+K7x{GZxbLmH-%jsn)9sR6tSt<|Lo$fCzesj#2>K|F?7_V1kL;8$q>s$>61*LrBZ zYDRB1tP=!JOMGnRNrllMo;&Fk9$hw~$Onm7FnSi&(E7bPY|^-jK|Z&@=0i&vd9=r1 zUS7+NMW{q~iwM$xs)!riEk=3Yiug}#L&nUC#nVMaQ29mC5G)!A*1rFn^nbGoc?*u% m`*1iV?l>!g?8Vcq={Zuj&z0$KPL|OpMluqL;uT_s-~Sguf2q^} literal 0 HcmV?d00001