From 0b28e202305a90e25300c6ea3cc2877dd6d082d8 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Sun, 5 Jan 2025 20:54:00 +0530 Subject: [PATCH] Add playwright tests --- playwright/e2e/crypto/dehydration.spec.ts | 4 +- .../e2e/lazy-loading/lazy-loading.spec.ts | 2 +- playwright/e2e/right-panel/memberlist.spec.ts | 43 ++++++++++++++++++ .../e2e/right-panel/right-panel.spec.ts | 10 ++-- playwright/pages/ElementAppPage.ts | 12 +++++ .../with-four-members-linux.png | Bin 0 -> 17967 bytes 6 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 playwright/e2e/right-panel/memberlist.spec.ts create mode 100644 playwright/snapshots/right-panel/memberlist.spec.ts/with-four-members-linux.png diff --git a/playwright/e2e/crypto/dehydration.spec.ts b/playwright/e2e/crypto/dehydration.spec.ts index 39629c8262..52c8844ea4 100644 --- a/playwright/e2e/crypto/dehydration.spec.ts +++ b/playwright/e2e/crypto/dehydration.spec.ts @@ -39,7 +39,7 @@ const ROOM_NAME = "Test room"; const NAME = "Alice"; function getMemberTileByName(page: Page, name: string): Locator { - return page.locator(`.mx_EntityTile, [title="${name}"]`); + return page.locator(`.mx_MemberTileView, [title="${name}"]`); } test.describe("Dehydration", () => { @@ -93,7 +93,7 @@ test.describe("Dehydration", () => { await viewRoomSummaryByName(page, app, ROOM_NAME); await page.locator(".mx_RightPanel").getByRole("menuitem", { name: "People" }).click(); - await expect(page.locator(".mx_MemberList")).toBeVisible(); + await expect(page.locator(".mx_MemberListView")).toBeVisible(); await getMemberTileByName(page, NAME).click(); await page.locator(".mx_UserInfo_devices .mx_UserInfo_expand").click(); diff --git a/playwright/e2e/lazy-loading/lazy-loading.spec.ts b/playwright/e2e/lazy-loading/lazy-loading.spec.ts index d6a2edb3e5..8d5f32adf5 100644 --- a/playwright/e2e/lazy-loading/lazy-loading.spec.ts +++ b/playwright/e2e/lazy-loading/lazy-loading.spec.ts @@ -78,7 +78,7 @@ test.describe("Lazy Loading", () => { } function getMemberInMemberlist(page: Page, name: string): Locator { - return page.locator(".mx_MemberList .mx_EntityTile_name").filter({ hasText: name }); + return page.locator(".mx_MemberListView .mx_MemberTileView_name").filter({ hasText: name }); } async function checkMemberList(page: Page, charlies: Bot[]) { diff --git a/playwright/e2e/right-panel/memberlist.spec.ts b/playwright/e2e/right-panel/memberlist.spec.ts new file mode 100644 index 0000000000..9a22e2e25e --- /dev/null +++ b/playwright/e2e/right-panel/memberlist.spec.ts @@ -0,0 +1,43 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only +Please see LICENSE files in the repository root for full details. +*/ + +import { test, expect } from "../../element-web-test"; +import { Bot } from "../../pages/bot"; + +const ROOM_NAME = "Test room"; +const NAME = "Alice"; + +test.describe("Memberlist", () => { + test.use({ + displayName: NAME, + startHomeserverOpts: "no-presence", + disablePresence: true, + }); + + test.beforeEach(async ({ app, user, page, homeserver }, testInfo) => { + testInfo.setTimeout(testInfo.timeout + 30_000); + const id = await app.client.createRoom({ name: ROOM_NAME }); + const newBots: Bot[] = []; + const names = ["Bob", "Bob", "Susan"]; + for (let i = 0; i < 3; i++) { + const displayName = names[i]; + const autoAcceptInvites = displayName !== "Susan"; + const bot = new Bot(page, homeserver, { displayName, startClient: true, autoAcceptInvites }); + await bot.prepareClient(); + await app.client.inviteUser(id, bot.credentials?.userId); + newBots.push(bot); + } + }); + + test("Renders correctly", { tag: "@screenshot" }, async ({ page, app }) => { + await app.viewRoomByName(ROOM_NAME); + const memberlist = await app.toggleMemberlistPanel(); + await expect(memberlist.locator(".mx_MemberTileView")).toHaveCount(4); + await expect(memberlist.getByText("(Invited)")).toHaveCount(1); + await expect(page.locator(".mx_MemberListView")).toMatchScreenshot("with-four-members.png"); + }); +}); diff --git a/playwright/e2e/right-panel/right-panel.spec.ts b/playwright/e2e/right-panel/right-panel.spec.ts index 1e9b8ebe1d..607b479ffc 100644 --- a/playwright/e2e/right-panel/right-panel.spec.ts +++ b/playwright/e2e/right-panel/right-panel.spec.ts @@ -24,7 +24,7 @@ const ROOM_ADDRESS_LONG = "loremIpsumDolorSitAmetConsecteturAdipisicingElitSedDoEiusmodTemporIncididuntUtLaboreEtDoloreMagnaAliqua"; function getMemberTileByName(page: Page, name: string): Locator { - return page.locator(`.mx_EntityTile, [title="${name}"]`); + return page.locator(`.mx_MemberTileView, [title="${name}"]`); } test.describe("RightPanel", () => { @@ -107,14 +107,14 @@ test.describe("RightPanel", () => { await viewRoomSummaryByName(page, app, ROOM_NAME); await page.locator(".mx_RightPanel").getByRole("menuitem", { name: "People" }).click(); - await expect(page.locator(".mx_MemberList")).toBeVisible(); + await expect(page.locator(".mx_MemberListView")).toBeVisible(); await getMemberTileByName(page, NAME).click(); await expect(page.locator(".mx_UserInfo")).toBeVisible(); await expect(page.locator(".mx_UserInfo_profile").getByText(NAME)).toBeVisible(); await page.getByTestId("base-card-back-button").click(); - await expect(page.locator(".mx_MemberList")).toBeVisible(); + await expect(page.locator(".mx_MemberListView")).toBeVisible(); await page.getByLabel("Room info").nth(1).click(); await checkRoomSummaryCard(page, ROOM_NAME); @@ -130,14 +130,14 @@ test.describe("RightPanel", () => { .locator(".mx_RoomInfoLine_private") .getByRole("button", { name: /\d member/ }) .click(); - await expect(page.locator(".mx_MemberList")).toBeVisible(); + await expect(page.locator(".mx_MemberListView")).toBeVisible(); await getMemberTileByName(page, NAME).click(); await expect(page.locator(".mx_UserInfo")).toBeVisible(); await expect(page.locator(".mx_UserInfo_profile").getByText(NAME)).toBeVisible(); await page.getByTestId("base-card-back-button").click(); - await expect(page.locator(".mx_MemberList")).toBeVisible(); + await expect(page.locator(".mx_MemberListView")).toBeVisible(); }); }); }); diff --git a/playwright/pages/ElementAppPage.ts b/playwright/pages/ElementAppPage.ts index 494d9fc9aa..4d7dd001d0 100644 --- a/playwright/pages/ElementAppPage.ts +++ b/playwright/pages/ElementAppPage.ts @@ -177,6 +177,18 @@ export class ElementAppPage { return this.page.locator(".mx_RightPanel"); } + /** + * Opens/closes the memberlist panel + * @returns locator to the memberlist panel + */ + public async toggleMemberlistPanel(): Promise { + const locator = this.page.locator(".mx_FacePile"); + await locator.click(); + const memberlist = this.page.locator(".mx_MemberListView"); + await memberlist.waitFor(); + return memberlist; + } + /** * Get a locator for the tooltip associated with an element * @param e The element with the tooltip diff --git a/playwright/snapshots/right-panel/memberlist.spec.ts/with-four-members-linux.png b/playwright/snapshots/right-panel/memberlist.spec.ts/with-four-members-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..f0e14ee55cf0c7489e8bb91dfeb41b2880f323dd GIT binary patch literal 17967 zcmeIacT`hvlr|bgYzPPlNLLUL5K!q|C4kgO?@c-gp|=1*k={g_^d=Cx)DWtQbm=AZ zK6kV#!h-(82EL~O+(=gsJx$X9Rzv=QUt%&@=o8H_0rR{x$4~GSA2Nq z{_)qxnh%@982*XjHZ`LfVQMrfjLF+3`#sjs`cJ6ugpj`$iVNOZ^dIw+fCl;kJ(|C=_~mU&aZo539fSCj8c1N?lf9WFQ{*gdk=O%JTF;;5u{pxi?a5$e^zzjNOH%JLEuV2L zEL9Jmlc3pXB5_5=J55}(Ia)jL7jjb&OWm1{(#>Ac18s68zjg3MaR~6N25iP#6!tgM z{m|kji4}#(94opSoXO}GA+muEjEUJU8u8@hm58;k7A)USxv%(gn@QaLcx9wX!`Q;m zrh=KM@qGH}aZx0eHI^wN3euB^OP%&P3%<9tVW$XAsCQf_NbA2W6qlLu5`JO)-fUyY z)z+4rWkE(*>x>&WSmZ`-Vx@dfWi#WV@p%29VzZoRRE@i2@116+C&B0Rl;0$uQOc*l zbfBD(Oo1bwNz8|XU1+xZSGilL@K`x}e79nItFp!X@hMmUFzr-3Gf}5S`U)&P+P;cy%PUFw35ujJDW#`gcTK zS$-3_k{fOC=%i$aI&uiSZ!0h+2lG89>Ie?0x&J+5s>*JaZL_?sac_WWk(-gM5a^d0 znPLu~Wcs^K^4T(M8&^eZVkcOtyW0!%!?;Wh&u zN=C9W%(LB}!n!aiErjjS$+f?p*TOr?E%(yyWr@|H?oiYoR(&a-abDaUW6pd`0|x(r z3c9~1XEA1V_4wXI+?X3XOP(^hzq78moh5bj75)D2k_+!CcnMSbajEf0cR-qcbxfm= z<=QKvo>*P3>(VqX+j1H`I}-Th$X;W5@k2tkvg$fz9Q~?lks)-b%p=mNnb7ew=jcn3 zaani-W&FY0ROCjj#|u{+V!Afm+k_-X7Q29$zL&W78esZ}lQo z`6q|8`lG|;_FoQZ?O3@R8!t<`r!naY+!VNAuk7&&QAV`^rwruggdravdSq;ig7W*5 zS%WJvL{h`izR@j}%_T%hiLzu)b4JE1^~{8@uKLM|SXraFnV{7)_5Di&VNM?l1$~3r z5wANG`X1>oB`2`auf6?*R>^ny<9nAmuNvO*#jUMxBu4hK^~-a^H?@NrEbeScHcR?T z8c9i|n-nU8tz*dKpY-r78%|H^{d3SI=X0)7K$005nS2rsMF~e##)>mRx*AokmGEXK zCBMy$^D36k0;+-WNn9W4l&{`i5#pVtj#w3G>vOS^`#a8`y}$|z3f;}FsEf630sgNV z>5Q8kQH<{~KaWp)m-09Vp8D67e)wtclFVmZjOAt@C^v$!df@Ia*&WB8KifLQmSgID zWwc8NczWMTdYN7QLL|>v6QqSnpY5}lM4|A{L*3cMT#{o#X1j#<7+yAH@)v&b2s8pgFP~G$q`4)IS_9f8(5N@Z6*RpCitQxT02cbpYl9`2#%1XZ0u1dbX@&$#B4z)|sv$lUl7+dirPq*5jcQsc{*bC*2QA1)sQfZ^> zi(4J8{JlfXuyw&{hW_fE>^>r9G00}r;(pNI@buRRTO7$joTdwAo zi;GVP*)0(UYNKx4EWR1F8V$nDyP%B73a4o8n&}&1LgfX33!g4iHml8Z5oHu&hV3!4 zfrQpK9JW+sh-yQ8S&q}M>1i8j6dX6Yl{kwsTF4T4=!`nIfsW|1Dhf{@h2Y3O`Cc3C zTz0gF3bJRnTy}p;osP=`>u*UC@@E|gOw#n$61U~O3D~Ga^hauez3K3>RG;M zjEzY(iI%F!e#*-xA;38>JTp2qtP$8-(}l&~FbmY;(3EsfRL)P)_nAbU3hS(R zj?)xybX*P7j8!0i)IZs?DmLQta?6=mhBibj2bQBc! z9+fh2kESK0b}y_6f*U|M`!zEKt+@20{KO%g0aV?^&g3;k=Eil~u8}fxC!kM?MJuvn zwR4}7xsL0SQlaD^`UyRb7L_r-bn&q?-FHutd-t&S19kLL)0FauFMhu#?JUx4E~1;{ zBW19yXZIdCSmkfgtM~pp5$=G#)Zn0LO;fZq!5|Ojw?27Q@A>xEng`WHeIUJ6)NGQX zl9?E9!|`WQ%fM}8d~3d3%JTxXF>^{HQ>Hgtab+fSy?;jLcVBne$gqSxWN`|YlI8!x zi*Tl39}BV<5TGcqS?*e<&nPs4H3RFAv{I1zfoN`jOawzUG}Ly!GZVo~SQwm`P%t-# zm2CI*^*OF%jwdRqu8sw#0vbHWzOp1kc3D{?E-TaG)20zY-cJZwm4YID{e5W5&r=(` z&-g0qo}(=pc9RrhnQwX8Vyg195)+rP{H>32IU(5MZ2&Fyb#+C-&o)i7LOs%QsBWIx zoo-4Yco>uqeq$+BZVwD=6ZEgNZ5HJ7tVf_FHu_ zp7)1p9niYv2Cxe-I77av84(?Cn3fMWHk2vX?B#HhzUD7I&1Cor+zlu5aC5%<4Zd}h z=`(qBx;4WnDSwfoI53X)baQ2>5-54*mu?t~VWtSrTk(~sJrVpGhS;3^#ZCo7?%83- zsw|M|k;m;cgtXSLXK!_rb@dMU(S{~`Ln9+&|BSOpQ^uEom3uWE!*sn-CH=7Sovoz( zk~8a6i^VEVXaiWC$gpw+j9#<#?2HcyPWr=mC4aI}HH)}8_>1g929c?n9<#PQ8Oyyp zgN2)2yAoDlu$JelndQqn5~R5E4%zaLI}`aqX=_w*hG=5U0259=p$7K;3e{>#drq1u z=IBgvsbHQ(%79$PU>Fd(hez)1%l}N{~Fe&Z~jddsiJ{ZN&P4C6?{C#^(6Xp=wmPwW z`aD#aM>fahFf#tikMrXFOFBH$@Yv_IodbVHiRje(m#ZH;?~oZQ#4uXE!8(wP%hMPf z&o;rdIUiF*ALeB%a@Ji0_+zVtulg&#OAn8X@LnM|g5hoRuZgZp)W8YY;FuV-wva@d zA1Ns*wGPuOlhrp^?bntj%FFDF)*5|KTrI9ONLJQLJryvAv4W?7wEsMINCI2eg2rDa zs*({Ycu;aPafuzP3sVF`?5PMVC*54cVDF);OLbUt1pKkLpXAZl^>DE3*5u< z)(1ybRn_4U0S(O&GG_5A|4uawO`nLm|wA0^s1`*;}j6^hBfy)LZ*Tih1?s)mcBCL8v^Ezn*Poc$|8cNTUY!Z-o$3X1pTULX5vpJa&c2?$Ce0Nk4i~C0EmoF#K53|h!k7WE=haDuU zkQTMddgKN_z9%OK{3et!c+GXQ;#~}n38KG}%eT(#)^UpirQ*C3l`x+#`!>DVseel) zNjJ(ar|4gzE{2a9UvFIqPTm7!>cwn#Lu>i0EiC*uR%)-hqvn|!otJeAJp&k-m}(Ue z{sSq!3ln-NtJDt`e#fQWw%uyoJcq_)g?&+U@S}fkXZOOYXX$FIX@0h=m%paAZt%%$ zg9)0uHT&s;wta6wX6lDKpyEF>aO}dS8LQy162-#V8qSF!gzLA+f(edxtK zK^5I#2Zws$8uZ0h80Zz)j&8D?bW4b(u>6Rg;qG6R=vr?v$-uL9ARN(HbI6DI^@VCI zq<$sy90ybL$BzhMxL;i!N^(WF4OJqw7Y;qxwOZ)UBfkp{KeoA5W~@%1o#`EyP>`25 zGWgm7t)+8HbvJ`)>(6^dqu+FyEk zs@x7pB9-q(D*agoKti|*AG+fZ^zGNO^WmZU(UE&_M+jgr%5IvZkk6%wo;c#bE2+d- zF`}Qa>qpmr-2LCwA_{*sa`lZ3UiV6rMP1F)xvU=+xgapmAk=*-NbSW z#~U5%-~8&=NSARapUmHB?wX+B)ri@W zq{`wG@^qB3v^PcfKpxRHM@-!J#Mx1#GD1c8L1ehP;veFP zuN~x#o)dS_wFfv(`kJ9)e;ZoOKEZ$Eq}&2e>DJpd(a(v1*y`$13BgG~J70Zco8?6C z%rSAo^fXhyDpxLuRa1TT_qR=A;_s{XH3f6d$1WXl?I$U|?X72><;|VMLW6zvRX#BH2Gzmu zbn%_1d)R(v>7zFqeVf$CUnNlp9g3d@8A=;7>O>}O*7 z9^^mxnvH#I-Y+d%x{@+Y7iN4xr0DmLcogzscy8Z*#L8MY-@@bo`}Il)5s*!Z6>@zrXGy1`~caO&T&A`+q@q^KZ{wzK;wXiVsQ;>xwt&n+xE< z$z_>?!IA^gdGd8jR21xy-@%mOVeWlR=W2!$Z=+2?KVh$rd`Wh;#1G$M=U`@3+)tlz zCr~Oz+$E7qdegE!ZNcD!#A9V*T2D6<7Z;yZ?aU2@sA2~cOo{*PAXt;1?=-#va}QpT2Y1ZM(9I6j+q)1^<<>W-<~(<~t* zReS2PRC!Ah?zVowW0UuCGsIuGq5aAfvTu9!DH`d1=}YbiWv5nT2fuM6(uUsw?GTOO z(}PLk;M9Rhva1NJSAU&N>tjlRA!8>&0 zZHmb_Ur_hUY|XsChzxbPhL!SPIc>7f!n!8ln@hvZoe;UrSc{+X`rwiIO87x8|ywPqTkjK1=B1k944WOOPGoDx(#?;SU;%rP4j=QX{;W=62C-PRnlh8il05@fxOa6KnOQ#m z;b1vd+=}#~^(yBhbb|)3mo+Qr2(~_Zf0Q3NZSjY_M_TdkPdypu1k+du5pluEk~ApV zHpj#c^~|+5I=+N2ktSixh5BRo>wy7@o2t93>n=hw;;)+X?V7FRu%vnT4Fj)uNQ zSd1YC^Ha|>{tjr=kbW#}@0rbImlWL{Tx%<)V-~x})b>H@*%^Y4qkcNxedPRUYD*D}+fWW^ea?YO=Vmm*6+(#1iDnZW<{-mGibl3fxdEmz5}JLsSo2z z%M_o?ycMq|6xYcUAvi~ikWU*0-yd0R^)HU5_R8tAPcc!=x2k4T3;j+uzMq`HqyI`F zbSiq+QJ^NJIXRly6!|D`P2KW$QLV14$uhb|N#DiiWWQ@Lu{i;Hb`l<@ng)j-uDwX^ zbsWk)q-16ur6Teg8 zXbmeQ_IzY<($74a|IyY|v(4N^a0_p$*Uns7?x$lG(UXhQ$XN-b*V>?3KFc*+*$6!2 z#Y@2t7(&M7uT8S)jg9GCMGHt-RKb3x+syK6PwaEzdrrk~MUE85v#Mjt$YOxFC+yGLRAw=&jIBn?~;3AIgGn`%=>C;ypSc7q*MgwD6}A600Q@ zt=j(EW16VB3AZ~vw9e4Q?7km2UFwIc~?{u z@Kaj4AH}Ch72k-2mKrujgwaPB3D5pB_d1(+Yt=O5*+M6EJ?;qp zvpc>pJ)O}|5Lz&YqoG+jSnWUFb>_^K@!F1wjMTOGLeUm#-0UkQB&6Le)+D#=8_!(8 zW19W6aeqGEG>b!AJW(WsKlVc0xed)EqSW)M@aT4xx6sAxabWD3XK`HGTfDJyzfz|ys8GBt#=)p($DHk5!*Ph=Di@Ax+$M7 zt_p4~$4nrv=8LTYj9V))fsc*&@YRzCRc@~0x8S>Ld+~N7Hl&P_Dtq4~U4}cO=|zs9 zvjKfmStW#LB94USe7GTAeonddtPW=iS5_urVc9`MPKm9RxHbo;wD-`~*DTgyKd)wH zd0j00vax`#qmSEGLRS3xZe=|W*xWG`7It?vs`WL-1Oyq>Iw3u#j}1DbV&O{QoSZfy zqG?E$@bdemNnipfhX6(x!y<9fJ5T~UJ~6{}vYejQ)qAh+VC>$$O%|(`*_skML1&?z zMbjf``NymXyV8*{EkkvVY4AB_3Kw6?wcT?sX#a)fSt(>SA-rAoCV7L`4&i_{arKH> z(%teTRJJ6k)p@%{H@>5lP_;7nv6-5h+M*LuRaMvEwsDpd1jDn4)&#V1v^&ifk8KD; zr*?MU^!-?|2-wDtbz?{y>^GEp3>hp;|3UR{{Qi`}%H?(bI^#ZURDql9JNl z;bGWYU0q#{M8e5PF&7JDXQ;&VFgor19_H4t6ob#xmgg^DQr-=2XZIG0bkryk1YWc5 zp}j1x+GFVQ4kjWjgp}zSWjH|UOUud{-0z5c@7|`6^4@(eCYBG`!I4kSz;|~~4`?y| z)uV%hgF{0LBl=m4(yj?%fd3FRztEGx(A>OvQ$Qxg$;QU8R!Nq#Gawgo`Q$Rr%_otbo^|KPESp0mn2_kSFx%OIjdRk6lnm!x0|WR2h>a)N z8T?#JTwCIDH|tB5=_|0cb-`6r@8~Fak2tw^dC!}&=yO;IIfL)oE=4;Lw6&#~l$5lD zNmxjz7J=w$EHb6qp;2uz{Cno^X<$H4VP$QJ5)~;m_}e~-!a2B+M5Y_@rhiAMHNSCS zTPB&P*Pp02yzLmJv=2tMu>|)?p%BXr5}hnm>eWusjD8kuzI^dMu>SkyagfeM&BcEEK|d)&$kwC+`23h@ z*Kx@2oW+m>l6s$Vn4OJHHqn&mc}Ev;lYNrAxO%^2zSpdAYvX0p3!O2osObwDLqkJN z&5=+%R4S(VT=dv!zvQz5`3_}VbhHQdpw;x1&%s7hlVlz}f%jcvkB!6avS`=%#LK(V zuP!Oo_(w704kpr;+~pz&QpyE$!dBs}gu~`d=FBczUX<52f8oIo_7|5zq$B`umOM{`}S2(Be`;PxB+2 z)ev+Z^aG}Hq@&|(qB4E}u<5-TzkCXB_``<}C#FTbj|G3B%-h7DsYxU~Q zo0^3`%p@cx8rM1*88vlotXk1)oK~WTI(1I3SFUDJ#A&)ULdavC&dm>Kq!`Ez=!gBS zZ?S$2``%sI!;DQJZ?Rt{cU$#KN=d8*d}5zroq>Tqp>7ZTE9e%bdRvGZ@J^17pwG9@ zmudM;OioAki)*dn(hkR~)iF#GFPtuxfY`@CC+>Gz1r4|D!%_c>fVOhZPs8UlF<7ZP zuw6{x4&-H;LQ254{brM|oF~4Npv%cwboz*PqSiH$j?+Ugo&w1w8({sbs@(w3$1?Fk z?-@-jGqnL~k;?hd+zle{7^z;h9VNxq6f~=yO8$yT4v$q&@1>ju@Cxll12`RgEbe*piTW+h}q90$HS40r<(qZ#q*M3cE|f z9XeBDQDpBR2%kE6%<1c6lkut4&&tZ@b8d6e*Qh}Wn$;#m7MJVhY${t(LRlXZBPVN& z+dNLa%cx%o;j*~w#$Sm_efaz_E|VioL~wOrg38|V@u21Xz%#{>lFH8IgwU>4W^WrU+w?T8c!H_paUv!OT{qbG+)r|msF$?9_t;EJtv4>*|^L-$Y{qR)b zmqhAhh0=xxs3ZBZtT*F!A4-_Bi0$ipNkIlBy05vDq#{(p#3<8fuFj}l@tDA`BMP;9 z15BiUF`wLc2PzwMZ3gYi1cko-&jI$myAev5BSuiRFGoku+*!;4ke&*bviZ+__#aka zcN%~G{k{HXunjUsS}79dFXWkl*0q5CPke3^&Gd?==9n*d_@XLoESb+Kw&*DS-F1c2 zqZ7e*X7<^MTh~Vo4G_8pe33J*i%Z4I`NUQpMsjBF2M-Qn05|XBYeb49dk3{Mfa=G2 zx2-k1B%2~Coes7$7sv4;&&Sc0*Fi@~@<-N^z4`#imVXm7#Rhm*zb1=sWuf^~YyfV@ zvAp8$=eiUUREc-zIcKRYe9C~vgWjd29`!ugKVrjMa;(@(2mSp#6K!$a^Tf3;^g2R! zv=smMtR(zJ_f#tQcl39GjS71Q!9d?P8NQKK%4|BOt7rha^ZOIDbRvRxNaUTbxKC2YA52u_Jub z+1a(x>*^YX|I34F;Vp5R2M@-rUV-F`j4BZC{Dd~u$|7smCiT$S`(Qo>FOtF)&)RZV z#{pyYoci&0K9h#@_;?FDJD1(TxYQ&UXJ=;*4E<{=33EHZ)uSldJF_ma%dw6L!% z)^FQivf4`x7LIFwU#_a}9dIz-?22>F8T20iOE-|!S`XU^sO|lmaWJ`^F@5S6P?mSC zNs&8Ic+ZIfa2(w)fynmMbI<+zzTP?nm^$E7orfqfN!OS&rTx!I z#bL*OWA9h_!N=PIKWE!YR2ySV;RpWa=IUFTpRa1%R{6cX>vgrXX6h;OPHivGkLY9q zqJ&qpr4lz(eZQG(ybSPfdH|IRYu#r(_Pb7zGDR<9zf*cTZ_}U7!^L%)ZKx|D(P-V5 z%1kQ5m#CEZj6c3xK8Cr~0iXFIPl52`LZao>bEn@+BysBC2OfLF-zup9;T&CR@*-g7 z8xwq+Ucia9T-9`7YqGJ`tAbey=1D%?Sb>v|dn;(O{i(yGFRgYLesDT9|F})JLSMvP z&vs;`jK&{zc)TUi?2Cs^HI039p^A)%2z!bhHH95-vgIb0jQ5{?=>MyqCE~EaGAR5U zJ8D<OKqQ`Ct|{EGG%Y~0*y9clnLaSrtfyqrZ#Cp4%~5XUESP>Bx*Qw zFK>}?=`YVU-vU3N)HoHChd_3KPEX&c0m_oRw&#>p{I=)1rn@KGx+g96zE*^qKw?99ilUL1UgRf{OfctIi6nt`1z zd0~pc)Rc5)P(enSPydA9W{n6(jgB0nwe_^u?M(RK4oxWv3G|Y-uWCyK9dNSX)d5r6 z;R#I_uuJza^iz<8*E-|U;-ayU(dNQ-|FUcNQ{iKEpt55O{saMa!nDYOY1szo>F6lb z)tsErPEw0l?Ck99y?gg4sj{Z0MIPmjj%robC&e=nY-)@u^oepxS}j!Z!dp0Vvr3V8Bjr^9`Fzm-jtY-sGL7Id{gkQID5SqkX@DE-Bs*pPe730YaK)_ntD_ZPSis#Jkjby6@qertMqY)o#ithQDg zUH%Jpylq(JJ@oV1Wy`74mA*8Nnf9 z46S`7ab+k-u};712NO|;?(Xg`0$k1C7w>x@PeKw&wl!_s;wQw$Ry|c)Z?s)5gN%MC z{b8C#V&!j2R$@l8&&b(4Uq(2>5c$Qi724C+opH3j39R>APwR5!ZqW6QRk6y!SH*yf z+_m7mNxFHp5)I@5rJZ-*`uLm*H3f-#k!(JgX@-d?lSF!nj9e)! zAM*@D$~Uz`iLV8Y`o*eep)$PB3|dkdAz9O20be{jZ=66i3r%vO)jMC5)kwt7cRNOv zB{W-;fS~FJQ}q6;w4VAQN0VGNB_SO)~17%mAvPRIjvH6H;RgCDrCWH>}bK(`- zt0qVWoS6I*Xz*wDo8lD}9dlj9+HmL&-*!E{M4*oCmhs*EQ!9!Re&ZQt%?-|+8!`JE zdv@7BM_=(w6C;o{?<#7HXi&=?-P*}YBt5wLh@XG5S67*WI8F`@>*<}Cvgd|t=Bilt zLWW?Ae68;+W>;pVI?HyTW~CL~H$Xt%2-oMGR2{IC8TFa5R^f*W^2EFIxgoi7tpW&v z9F+;wO4mGdu>Hodu5&D74^bB`-?^6kQfMPlacM(gyIbY&nBUEmJ1B;zmYtZ7MX=BWyr{^{eLr=mpUiKO%z)zpKEKE(Q_)LN z@F@y=lw%J5Lrd?TIojYu4)K?r&AvluTum>vqXxw1?frk)A`jj8;JfGUYi8|eDVX0p z%ix0TNhKN6RMD9x=;9XQVuAt2m%|sS*lWeVli%Ewe7rP#u$9HAJ@fSWf`gSaan8H9 z;OnoKmy07KBWd{zu+uO9!AuGj0i0}Vt*9Sh){IuOI2hXwAi=estw>bXcSylOItU}^ zaGSff?wyCjQDNNNPtSh(lisR8WWTJeS9zwUq?9SJLn56e^I^@5^=r2!n?fw67B(>P zA}`>~4)yM7`o++wMW>opS-ns1I2QYLxwmC&T*&)irR;#_nbuJu$Qy%bS~dEnZvzhx*l z>2u2tLDsWu!?&yR#Hb}?~ru$Bi6KCRHLcUiQ8gg~Mdut{yeP*l@YW8~?9pZ&&09*$7_QUXLsnp>+b zK9u2L0CxW$0r}kwA7yyCN#iya`{Bcf()wipfoTt!)ZfnsQuK(pP^IbXz{Fon03p6d zmG7MgFJHyJf75l%pr+9`>_I#%h2Ousdrg?IQbx9WZO=$uqEq-Xf^J-Y{qKV-6B834 z!hK6fXd)!nYV#C)|E`iDUG4C8cdP{6pV9i3v?F7S z4K+2Ktj0vf1IMI>#|IisbfO2SDiL8(AegcU%gDgDoA|@R+7|Q-^`n`o#o=>|tXNl6 zBVnfQB9wZXFkzynx3;jbH{D?hJK8j<#R3{Xb}_3zt@X>mDkS~6)2|Cu@x>r$hb<9< zf#H|p0d~fvKVK%mj;VnztRJN1CYDNA4BXx^^GaMHdIv4KnAn*76I89OrL|pVFrukj#XKiVtq}`j#Od%zb0@>(LeRzz7w}KB`o@E%$DB^JEEP9 z39TOEv_IjA|31V);`_WR@|<~C>S0wq%HN^u^LoGc1(EhS z_>Ay_w3JD*K5IO#sBbvmj@ubPUskzxBz+1XX{cdYFKHVpYQuuwk(T-2)d$i)e~Ojk z456cET$ULfb+|qK?2yJ8P*t zkPypJgftGs$B*N9`}iaE{MWI^-{1k1N+wF?zyXL%47ZpcKHRwVZ;>&&>|1IopGi$% zSVTl59!PRHo;@RRiv%38-Fhg*t^8WsPKm>xs)!=5 zrX&|$>Bs49sgeZ0VWqsyjREQZ8x`JWHUWkyLFaPT7tBt%4hWGm3_bumyaGxj!`qkb zp|tZ-IqJ=H1FlIPvy@(^!M-IJ32J2Nbkbqrq=#vK?x&tV*q4=}TwFf=P5dW*gdaIU z;cq$OqZy?F(A!cLol$4&h0AYpoc9$pW0@q>Yq2Z5hLMrVN&M$^hUodeG-SWwk9W;t zL`^cIaIXL$nHejEv<9>hQ6dMC1F_Cd21D+~kig$*3S|#&l_xzj5w$*i%PQ_g_zm#o z)&A4Xc)F1=L`_YN+wLtu%U7rEe;Q)|)YDmG=8Pk#JEPLP34Tjk-!^n~lIYc#=b1DP zDs?&HDp*ho2kzld1s;1XertXi-o!`pUvt~EJWh9R+ZqeKbx!UFAi9goUMl2Y?v5Dy zUl7KYbhT`mGH!kS^z@XwWqb6+b0J>G-ks@{zXUCpNT3LC>?=StSc|8sz1?VK`6@ZrL!&a4lN)sXJ%5xyiZBhaBC6cnbmgFYG?D^il-Ygm>S z05sC7+D_P#H9Y)KI_w8PO@NMdWGW+i-w(S^_QLD{2qc9%^gHKNpcc8Sa$-Qo2m-{m zb@PVek{kEz3Pguk0U%RG4k(00ext?DtLyn9Qzq%)9**=BbcS?yRqlP=E@Zjl!u>LZ z)V>r2Ar2-CJAaBw#zZ#;1IN!lfnl4?rPIN6&#Ms2pMkAo@4O5G;LybM@1KGL9H{pq2n-vSWq>*w(@DMvY`vIXWG0vBU}6? z>^oxjGZVhrn>z_-dwF42=Abb;IvfPcZAt*>V8;1i4zfJsmo)P`3=?%icBMFxY+MC4 zYgnL)xl?Luh9a311}Qp-_=i81Z#DB!m+bBuo=YC00D?GX)g2m(EjNl)R8mY-vTBgb zjI7p7j@e3Q5Jw6qwwclr{r^=Z#-AUCy%E=em4<%#X&;ZOb}9geAUFg0r&fBZTT zx}B`6wK)SjnTj@)4+)WKxJgW0$Ie=$<#}>av?1aY+1twitB-y-g_-&5-iNA8&|2MQqJRYTX`D2tjdU zEzwuN#T=r#(uY#M`-i_4IpaI-$++h3y8sjUAEffm=p=x>`D(PcKHdVC3!ZUE<}pbJ}ixOTB2NT>==u=Fg!LG?b41ZV2gS z-UKbej*6DgM1sX5AMyRqWViWfC{Y%B%ZY!d32UnKc`p~0{F&gd$Km*xRNans37M|B zUIW8;XFEF#Os&v>R>F;-;iPz^#4Br+zM57`Pto{8Kuw#E{D;`A7 zqVR+L9lm}0`HKpq)9|G~mlK>|_mhdD35C4_nY7~(5t8VrduXQ#?&RLqGps=9O;2FR zS2hjc!+mX6HZOEBREh!B;+L3v;W;4U1l?RHsLu!kTUkl`CX1ny{>FcDPF$@K_jKj> z@-XTOpVV!?s;{oTcL0U2;noSeN1ynmvyx8swNJVQ!0wkF88b~6!PSKoC!Q3^y;2VX zaAhnD+d+B|FC;aF_wL;f)kg!(%an?$Y2Hb@*tPK10tj8B@8tXBkQm+a&KouRm)_W? z3=X}fI(|X!7>ND2gITEzkQXY-s9X{F;rb%2&Y_;KHK{o;A|j%--;_~2+soSXxTUSr z#!v9LBslBNjhmE3T94+vwivzFair~E>&C}_z25Th@X2H@&zM4@=$SOt)m`@N55HV% zE`8Q_>K7E(c5`WEMMf2|tnrOiJ!L+++2~ppKV>3UYsSEpgxbeIQ*KJGmN~Drdaro- zIaT^*v6k?`lR_x1Fy3x|Wk7FB(v&0rN#XZsg7cSGKatNx()NZXTACXu)K_C1fo_fe z0qbcP*xPff4E*)mP;mD0ICfabtEfQNx|yNCUo$ccM>y(@%2haedwSx!mo9xhHm0jf z_D#u}$VX)~hf6;?`%Z*WHzO0NOW=-{vTlSZshrx(D;2O9%10yRFDj?abd|qu-_hE^ zLJsVBX~-c7mjip&35z&kG@sd7*_qTPMb|DLBr5`g(=#g93l0M|mL=xPnFO@#^X{MC z%+Jp)hAPXk%B6cWH)}naKcI$;X8qxOmLgL!o>f`kgWFh7OG(u-Rtto_JB9uMZgft@ zG|<BO;0Y3pMmYp@bPnk)e6A zK?a=nc9P`LZl1e!r`zKyx^SV`hd?%O|EP9-ynMw&FG)#BE}~VAX}Bo6M@G}dXSsbQ zU!$nSWSIq6WVJDa^%VUAjyKYnSEdktfs%dC6qTgJcnfR$T)#+Crme*+b{&5P+N_De zZjU?VqWVFq|;SZZZ`eKsd3tU+NBPug+)cr zWm>bFn)cbOmE>5%!Af9w2$TKF>`7<^?cWTs{6uJV!v%ff1@{!v?x=lrMAxsit2^gc zM_D88C4G}&YCzJb95HzRo=ct%zUb)NNLmyxF`MpjCJO#N$H$ob=iQT=?D?#$_M7Vg z=i6;qEM9}OmM|}L4<|{-|_~2|`aM-<*GcljjDqQ)?Nt8vSo4PKul#hXt20ajf%+=#^zoa@r zH+GW0rUtBBX((oaloPI>7);~U_AI`hM7HOGPito522c)7R}3ks}^>b=YOT02sOT{gCZ zc613}X2 z-EHB<#;nvn1tm>1%727g?Ge`xrFrfuJS|4XymR{5xoYGd4?{C$WbkmciWIx?ssuN~*bo*{N_qfk~2n z534;K8g$N0cD%N+ap%OZ{VGCPi88Bob5`ne+roq7giW#g+qmJu@hP1BA@40%V@S;L zSih!%LSYId-q4FBWJ|{Pbcz&0j(mIxa}{M2u_>&k<=c^QW!+om!K_HH)9Eu!-})n^ z3Y2Y}3gL^+-s~-=i~39daCD%`aj8xFQCIVJplizO#QRUm+Y}>V-xD*coXV7*!2AK!EFuC6RfRf1#f7Ul$WJebPbu29lAzwEfDT)DInMaM0 zfV2grR_=jz?*2#H9RE+e_kmfu1MyGp&41+G|4q9K{`)!q`*w2t_gw$?T>rNX{NLLE c?h3TzBi;!Q{D=j<0S2Tfrv@&6WA^EP0F&imB>(^b literal 0 HcmV?d00001