From a2df75a6dc7bc75a7e43a97f1a090a2f31476ca3 Mon Sep 17 00:00:00 2001 From: Adina Parpalita Date: Wed, 20 Feb 2019 09:13:15 +0200 Subject: [PATCH] add tests for Upload New Version (#960) --- e2e/components/data-table/data-table.ts | 38 +- .../dialog/upload-new-version-dialog.ts | 121 ++++ e2e/components/menu/menu.ts | 5 + e2e/components/toolbar/toolbar.ts | 15 + e2e/configs.ts | 2 + e2e/resources/test-files/file2-docx.docx | Bin 0 -> 11523 bytes e2e/resources/test-files/file2-xlsx.xlsx | Bin 0 -> 97629 bytes .../context-menu-multiple-selection.test.ts | 35 +- .../context-menu-single-selection.test.ts | 30 +- e2e/suites/actions/edit-offline.test.ts | 270 +++++++ ...cial-permissions-available-actions.test.ts | 301 +++++++- .../toolbar-multiple-selection.test.ts | 32 +- .../actions/toolbar-single-selection.test.ts | 28 +- e2e/suites/actions/upload-new-version.test.ts | 672 ++++++++++++++++++ e2e/suites/list-views/tooltips.test.ts | 2 +- e2e/suites/viewer/viewer-actions.test.ts | 324 ++++++++- .../repo-client/apis/nodes/nodes-api.ts | 36 +- e2e/utilities/utils.ts | 10 +- 18 files changed, 1837 insertions(+), 84 deletions(-) create mode 100755 e2e/components/dialog/upload-new-version-dialog.ts create mode 100644 e2e/resources/test-files/file2-docx.docx create mode 100644 e2e/resources/test-files/file2-xlsx.xlsx create mode 100755 e2e/suites/actions/edit-offline.test.ts create mode 100755 e2e/suites/actions/upload-new-version.test.ts diff --git a/e2e/components/data-table/data-table.ts b/e2e/components/data-table/data-table.ts index fc130716b..69e485ca8 100755 --- a/e2e/components/data-table/data-table.ts +++ b/e2e/components/data-table/data-table.ts @@ -48,7 +48,9 @@ export class DataTable extends Component { nameLink: '.adf-datatable-link', libraryRole: 'adf-library-role-column', - selectedIcon: '.mat-icon', + selectedIcon: '.mat-icon[class*="selected"]', + lockIcon: 'img[src*="lock"]', + lockOwner: '.aca-locked-by', emptyListContainer: 'div.adf-no-content-container', emptyFolderDragAndDrop: '.adf-empty-list_template .adf-empty-folder', @@ -60,9 +62,7 @@ export class DataTable extends Component { head: ElementFinder = this.component.element(by.css(DataTable.selectors.head)); body: ElementFinder = this.component.element(by.css(DataTable.selectors.body)); - cell = by.css(DataTable.selectors.cell); - locationLink = by.css(DataTable.selectors.locationLink); - nameLink: ElementFinder = browser.element(by.css(DataTable.selectors.nameLink)); + emptyList: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyListContainer)); emptyFolderDragAndDrop: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyFolderDragAndDrop)); emptyListTitle: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyListTitle)); @@ -160,7 +160,8 @@ export class DataTable extends Component { getRowByName(name: string, location: string = '') { if (location) { return this.body.all(by.cssContainingText(DataTable.selectors.row, name)) - .filter(async (elem) => await browser.isElementPresent(elem.element(by.cssContainingText(DataTable.selectors.cell, location)))); + .filter(async (elem) => await browser.isElementPresent(elem.element(by.cssContainingText(DataTable.selectors.cell, location)))) + .first(); } return this.body.element(by.cssContainingText(DataTable.selectors.row, name)); } @@ -181,8 +182,27 @@ export class DataTable extends Component { return await this.getRowNameCellText(name).getAttribute('title'); } - async hasCheckMarkIcon(itemName: string) { - return await this.getRowByName(itemName).element(by.css(DataTable.selectors.selectedIcon)).isPresent(); + async hasCheckMarkIcon(itemName: string, location: string = '') { + const row = this.getRowByName(itemName, location); + return await row.element(by.css(DataTable.selectors.selectedIcon)).isPresent(); + } + + async hasLockIcon(itemName: string, location: string = '') { + const row = this.getRowByName(itemName, location); + return await row.element(by.css(DataTable.selectors.lockIcon)).isPresent(); + } + + async hasLockOwnerInfo(itemName: string, location: string = '') { + const row = this.getRowByName(itemName, location); + return await row.element(by.css(DataTable.selectors.lockOwner)).isPresent(); + } + + async getLockOwner(itemName: string, location: string = '') { + if (await this.hasLockOwnerInfo(itemName, location)) { + const row = this.getRowByName(itemName, location); + return await row.$(DataTable.selectors.lockOwner).$('.locked_by--name').getText(); + } + return ''; } getNameLink(itemName: string) { @@ -252,7 +272,7 @@ export class DataTable extends Component { } getItemLocationEl(name: string) { - return this.getRowByName(name).element(this.locationLink); + return this.getRowByName(name).element(by.css(DataTable.selectors.locationLink)); } async getItemLocation(name: string) { @@ -330,7 +350,7 @@ export class DataTable extends Component { async getEntireDataTableText() { return this.getRows().map((row) => { - return row.all(this.cell).map(async cell => await cell.getText()); + return row.all(by.css(DataTable.selectors.cell)).map(async cell => await cell.getText()); }); } diff --git a/e2e/components/dialog/upload-new-version-dialog.ts b/e2e/components/dialog/upload-new-version-dialog.ts new file mode 100755 index 000000000..24d6dc7f7 --- /dev/null +++ b/e2e/components/dialog/upload-new-version-dialog.ts @@ -0,0 +1,121 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { ElementFinder, by, browser, ExpectedConditions as EC } from 'protractor'; +import { BROWSER_WAIT_TIMEOUT } from '../../configs'; +import { Component } from '../component'; +import { Utils } from '../../utilities/utils'; + +export class UploadNewVersionDialog extends Component { + private static selectors = { + root: '.aca-node-version-upload-dialog', + + title: '.mat-dialog-title', + content: '.mat-dialog-content', + button: '.mat-button', + + radioButton: `.mat-radio-label`, + + descriptionTextArea: 'textarea' + }; + + title: ElementFinder = this.component.element(by.css(UploadNewVersionDialog.selectors.title)); + content: ElementFinder = this.component.element(by.css(UploadNewVersionDialog.selectors.content)); + cancelButton: ElementFinder = this.component.element(by.cssContainingText(UploadNewVersionDialog.selectors.button, 'Cancel')); + uploadButton: ElementFinder = this.component.element(by.cssContainingText(UploadNewVersionDialog.selectors.button, 'Upload')); + + majorOption: ElementFinder = this.component.element(by.cssContainingText(UploadNewVersionDialog.selectors.radioButton, 'Major')); + minorOption: ElementFinder = this.component.element(by.cssContainingText(UploadNewVersionDialog.selectors.radioButton, 'Minor')); + + description: ElementFinder = this.component.element(by.css(UploadNewVersionDialog.selectors.descriptionTextArea)); + + constructor(ancestor?: ElementFinder) { + super(UploadNewVersionDialog.selectors.root, ancestor); + } + + async waitForDialogToClose() { + return await browser.wait(EC.stalenessOf(this.title), BROWSER_WAIT_TIMEOUT); + } + + async isDialogOpen() { + return await browser.$(UploadNewVersionDialog.selectors.root).isDisplayed(); + } + + async getTitle() { + return await this.title.getText(); + } + + async getText() { + return await this.content.getText(); + } + + + async isDescriptionDisplayed() { + return await this.description.isDisplayed(); + } + + async isMinorOptionDisplayed() { + return await this.minorOption.isDisplayed(); + } + + async isMajorOptionDisplayed() { + return await this.majorOption.isDisplayed(); + } + + async isCancelButtonEnabled() { + return this.cancelButton.isEnabled(); + } + + async isUploadButtonEnabled() { + return this.uploadButton.isEnabled(); + } + + + async clickCancel() { + await this.cancelButton.click(); + await this.waitForDialogToClose(); + } + + async clickUpload() { + await this.uploadButton.click(); + await this.waitForDialogToClose(); + } + + + async clickMajor() { + return await this.majorOption.click(); + } + + async clickMinor() { + return await this.minorOption.click(); + } + + + async enterDescription(description: string) { + await this.description.clear(); + await Utils.typeInField(this.description, description); + } + +} diff --git a/e2e/components/menu/menu.ts b/e2e/components/menu/menu.ts index a805a1f6b..dc62df128 100755 --- a/e2e/components/menu/menu.ts +++ b/e2e/components/menu/menu.ts @@ -61,6 +61,7 @@ export class Menu extends Component { leaveAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Leave')); managePermissionsAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Permissions')); manageVersionsAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Manage Versions')); + uploadNewVersionAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Upload new version')); moveAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Move')); permanentDeleteAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Permanently delete')); restoreAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Restore')); @@ -251,6 +252,10 @@ export class Menu extends Component { return await this.manageVersionsAction.isPresent(); } + async isUploadNewVersionPresent() { + return await this.uploadNewVersionAction.isPresent(); + } + async isFavoritePresent() { return await this.favoriteAction.isPresent(); } diff --git a/e2e/components/toolbar/toolbar.ts b/e2e/components/toolbar/toolbar.ts index 2fecb66c4..ed1ff9cf7 100755 --- a/e2e/components/toolbar/toolbar.ts +++ b/e2e/components/toolbar/toolbar.ts @@ -217,6 +217,21 @@ export class Toolbar extends Component { return await this.menu.clickMenuItem('Copy'); } + async clickMoreActionsEditOffline() { + await this.openMoreMenu(); + return await this.menu.clickMenuItem('Edit offline'); + } + + async clickMoreActionsCancelEditing() { + await this.openMoreMenu(); + return await this.menu.clickMenuItem('Cancel editing'); + } + + async clickMoreActionsUploadNewVersion() { + await this.openMoreMenu(); + return await this.menu.clickMenuItem('Upload new version'); + } + async clickFullScreen() { return await this.fullScreenButton.click(); diff --git a/e2e/configs.ts b/e2e/configs.ts index 30a79b28f..75d218fc4 100755 --- a/e2e/configs.ts +++ b/e2e/configs.ts @@ -109,7 +109,9 @@ export const SITE_ROLES = { export const FILES = { docxFile: 'file-docx.docx', + docxFile2: 'file2-docx.docx', xlsxFile: 'file-xlsx.xlsx', + xlsxFile2: 'file2-xlsx.xlsx', pdfFile: 'file-pdf.pdf', unsupportedFile: 'file_unsupported.3DS' }; diff --git a/e2e/resources/test-files/file2-docx.docx b/e2e/resources/test-files/file2-docx.docx new file mode 100644 index 0000000000000000000000000000000000000000..c0d0614a84fc9b0ab28ab8964f91a7c74181a5f2 GIT binary patch literal 11523 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 literal 0 HcmV?d00001 diff --git a/e2e/resources/test-files/file2-xlsx.xlsx b/e2e/resources/test-files/file2-xlsx.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..3039a7cdc8579121f821af3dbb78590f00ba19f6 GIT binary patch literal 97629 zcmeEtbyQnXw`Xv-;w2C$F2##GE!yG~iWD!!wKxe5#a)UOx8mC3?hd6mDOO5>-~mFI z^!vUy@6Eio*36neXXb{4+;z@6_x|?Tzx~_$oEt553``0DHUJj@05Abm)k*@_&;WpB z8~}hEu!?4^=;G{YEbv9Y*Ljtnu#@D6 zEX_CKmN|xKi>P_UC5Bb>BN@4*_r@_#@d{ViAhK%CA%m_!iYZpLFR)JKv!u5h&g~-p zI0-ACl1(WI(u0#;+v#TfnLboRrr6MgX%{wQtF>TQw^p5Orq@d1WNJ6{CO>0pGs`J* z{7i0Wh!f$=btp;ptE~1bxjVD{)>6zMQO0*nekKyK(CYN=f=4b+Bgd^5Z3YeBBW%3y zAD-xshIv${KS|U=IxhsVwCb0za&T`-gz(PzlH$_^%`}Iff1$i^X#x<#3*}Gnmfc|Y2;_O?=Px*7C_YHgoV@==lW;ooGw9b#0#lcxkS8gU z^|Qq6f>~E1o+q+jHosJ_n|!--(}>o1-?$Xm_ospBgjsVq0EdH5<~@U*9QhW7DA848 zE3x=9E3Y%s>sa(O$q-DCF!1)nlM~I75!r4Np6iMnyRQS_GS&zw`g7levg06#QY1xn zhr5=YF*pbxY3%>FRJYBq&y-JM_#VNUjT`K&!ejdx<#-Qo4uqcai(T4{N zfY$%O^Jaa1=1Ww|OB9U>08?mY?lz7de7t`@84Jh$KfnL4;dN~Cv_?Na;n0anhvLrN zZ)X+Uf|B-^D(y^q3_UEzpys$D7P;%IFpLm2tJT@7{b^a_jpIE#JrK~6Pow`EhkU(| zrT>z>Pj&ullFyb;Z0#t9AIAeN4AwUs&3uYevn`kI${S*09)C+kFk1@KYf=!L{&6o! z;@2Ltct4v$TW+(Kx+@*g&7k#EYO&WI7snr`Qs!3brlD2%m5UGGUZ7=$Myy;Ox#YOl zuHrj_is{wzPYUCzp_J!2^JJrUPpmNV*j7w5FCJRN+@7d^oKe|2m)eZ>kUKmK=FNX! z0q>lW`dJnRePs=|=p7`{Gy5-nJsBtU4<<^}WHA7M#{gV3A4k4_y1TcFyMv{Ri^E@4 z`Oa zS*L_1vxFbJ`vH`x2MJ2;)P~sOmYaeoaZ>+ zwfNF0-t)b0EfeHytDRr1_n({ncFEv2X%q;50_z zPO)bDv5756Ri1f^#ThR2O;8fw4BEMUYY5 za|z^^H~xT@-M-s(Q7iq4e0sR<)b}NBLP=M^=8f&ItI9jf|H=+W6;G|PQ7vzX0RWD-(dHip_+zl?vMNFf2Gu>tZ}~H?s&4z#nRqf_QjC1F_z>KwL&e%yq7q#Es2y^D ztfE~=F8Lv*iy{+bedZ|zz78GM92dP)Vj+1+S7WVIYCxXM|5cwgTpnIgqdRY} zq#hdcIBAM4WwoimBzaNC>(z!~ilaXJ(=D3kA0g*8n9w64)sC;tTxjDv_93##HR*OP z=FMMHfkz$Kk{pIlCo^_}@%eu)usUVtcQ5AP+x8yb*rKr|7&xYBNkAK{{jm+H+IGUy zqD4%A9S6%ojlDbTS&MeDOdS3LUHFoF1jv`l3wM1^ zK7|~tnG*as=)CYY_$`LR7w`4aq+90jHbvS!YLU~JnknyIZeZ)J3RPxY$_MQF1SMiT z2CMVeFe4Ejlh~R0d*Nly$?l*kpL!>#^tp6^SuP3F+k&#H{U>q-1E0$a$D}J)3((0s zKtg8>LQe}bspzR)1BsqJ`_A)&=X#s7E!aKW*Boco&F3RNoRPf%3+%X_gf}m{zzoa5 zGej=mF(!(Px7G|Ndwz=ZLP#mQ!ns)l4ip= zk>X)zz=ya4lON1=M#@7^zInV{$!n;z;GRxF5BwJEm}{-icl8Q^?LN%OEK@62&(!t6 zpX zqdvR(72SYyB!gX6x}k2N+?;A4-O6?lTK_kT47Bzmen;*Z^mfmDHsi=@j9bbp6}1MM zarHTDy6=mT&!0d79yYg`KU}VaMinSNVcB(Ctun3giyDvt&5OPF_l~$%r(;OQAGVtC zdAYKYqjIwH{qDqcFq?~oOukMgJ-h8FT#Yq5E&9TOW_(yJtbLX6f*Qe{)VAn)xQqt7@JXpDvL~)hV+)L4URdkDQyetJ~q|_m`|$#PxjI!4vMD3E~mU&S3P0a)~A!K0S{_bZ@f>jDFh#DX3VS< z+=JDmBVUTGJ`HyP1QdPhqvnW;koqPZgO{*aX&3_wK%V?A{l{SZ64&|_l@qw@0*nE$mw_x(i8D(_Ou`L z^re^xv2YcZi<-mBGzwT{KA7)wl9&ew{Vh3<7W=qejM&zn^&SmH$78B~eXZd=7-aNo?s6EDN zxViHUy1o#B+VItSqL}5e5Re;~n8{JR4^K^ebabr!`^Sfb+Yogb?OzNp=wGV85-etB zPo#?Rvcm*tWgHOJcsVwDQ-2WSp7)Ccep6Awolpw{J=)7WmB`}+rX>M?Mo|)h$*byK zj`W(qUzlie!93+?lsg5I8XPB`&~B-6z!-|1Tp#WjvXyytI3%7H`I39QeSQqH6CKdj ziJ+ema=WFK$XNG{+Mhg*-YVCJ-oExw+f$ifL$eK^jm35E4@>@shsTvB zG7inA6o%!U-+b!=>kpEP(q5f~35sZWC^@Umv#bB$849FXIGjLB+KDV>2^(%|lWdbS zZ^Xu{ktyT?hKU6;wC~wH34W=H^N7`?Z+VI^WA3}pulY1-T9J#a-tQP67a2gS&=1l% z^hEB0@5b>aZiK9wYVdN>mT%KiIm+)PChU#Mg*>WgXJ1x$wC!?*l4R(I_O5-J31|Fe z+B5b_tkB`Rt4MEbZ1egNcFxy9ALtWP7DXwxiiD<(ahXb5cAI)jUJOPrwSeMj-!jAM zp6Zg(F0|H0v5JwJt`O6`PSH~xs$K%VgAVDWcphFh_Ly1iRflKaA2Xb}&0Vp%ehDAu zK&w?>hg(qftS8on5#8ygEL-37Wmmrx5XG~1)wMY4Dz4MTdBn6xoL)dgB$O5bh;I zStQplq0&dr>@Q!;@VTayRy&oh{mfxAJw+ei`XlyEHEQ0yN>_N?nn2VyXWV=P|7Wms zNdw*PRBg2C4S`Mx&Cr98{skC)3G2}62o2=yj-@1Fw#q=wwWAfDoOm0E78hDUPx{oA zo?xC-&o$o>N#I`ou$t2-{L-kuLX&<5fQNsVgpb8^rTi8(D`u<|| zvhc65+W*~H*6tSGe`}(Dnd)Ds|8A^~I*y^rw%#EDFi!pP!VDG8v)! z6l#m5JXLpCTiY@%rCX74W^F~4_OmghA{8E#c{vc@K$sLLO{?Ip_gf^6Mzwo((1JYiMc53w?))TQ*+zIQR>@IQJMKFU0Q z4<>+`d^pG01px5({jVz0$;R5wg3r#$!q!HJ*WT5}_Tk6F7JyVuNmU7ehK2@ELA?ME zs{qBnXaCCs9UTn~^@oQ3Z^yrXL;pL-e;D9@==N{j|Cj$CdH`g&fMN_r474WzbTTvy zGPH*Q00;m;!}{mg|AdMXeI@qqhVm6V`5-oVWP@Mv_Mol0Fw;s z5tD#CHo3M1&J#BZ!Qi9kgldk7vr6*Ud*V^%hH4o)uNXCk6v;u4C_ zUnnW7sH*Ae>AyBGd}Cx~ZS&6dy`8;>=LauuA78)Fu<(e;sE^UfDXD4c8JSt13X6(M zO3TVCDjOP`np;}izJBZL9~c}O9vK~*n_pP`zVu^x1^RP)XLoP^*TL`8v-69~t84hp z?O$AI0F3``vVS7`pKy_(aG_&jVqoI@#f66M{TDbHCKi(b_9J<191Az{CxXGa6beZN z^}Tq^LOL)?OZQoPDi&cV>*-%;|3LP?2Q1|O2-$xJ_V2h>0E8H5sL8`11IPmIB$1Sw zee0F=2yqyLY3r5`U;kig!0<`SCks4VM6!&T&rE{jH#2hZ65%F9$QI&l<=lJD17oVAqf9i0IKJ-ejNeWmrYPpDZ+6RBc5!kOqrhnp297g zeLjjUtCsEk@iY?Ly{4dOsoxuir9ge$*b&@jXgTz;`LGE1hk5Zk_+u}?Eq+)48{CLO z6v3SjI0p4T0C1gyLQmJrJl+=3JP~<|p3-=2T`}ad>k47$&{Gn{!p7h`Jz-M-f4O0F zJJdg7YpHwykbP4VUR%%Uu6Y13k3RsQS_mPMHiQTaaF(uRX@&#$&CLQIFg5*ooR6dg z^%GV0Lu-TdoNlHOOh^V+ybBzS%i8B>qtT*Tqg@KtUL%m~l$6z5uZjs{5z2l`9)RK2 z*JU#imfPruvJG#0q64>>|H{E5vj59Kphj+D;O#;T%BH&YIMAh_ zD5409tp@-}g*5W)U~Bub_GL6#k9@0JVoFYk?r{!z&jSG8aQ1YJabq<*c$C>&`|kP7GPLr=Imdh7EVv@9*Ilze0qu!zyCo57IHD{XkUnx^_&`$@4@qSm3|oa> zggP(jZfz2~yuQ*d-C8OUOnP#RX6*G7m*kw`#@y?Z*;7+RuBcI_h|_eUh25fF=DeHI z!)AK+N#4U-WKyn5&5KF!hgnvSsSK!c-*-z0)Wipa&V36m+275%pOhlH?AHCxm!ka;%y2_uI@IhN##iQ%z#agT z7tESJJD*ws26OwRgnV_JWMLp7O3|bY0yyYQWf};SFHIRF3^naZS}5-lKSm9D{o8CjaKzk@FAm z7qC`OVf3YXJxx=FnQ5+`Zz z2o?j?b2dOy*7jfOcnhSUMhqMa#6RffgGT!WFu}EGN8z?xM3n+{aMAuCGUUi(FSH%c zT6LAA0Y|bT{1O$e2LQkH*U!(RgvLZQ)J09MEFq&;C6^ULYsq&g_GcBl&czgsWbeY8 zjBf3HCm^_86x+G%u`~!l7>4yREzBSyN_REk&xAqYAFP>5QInQA zU2n(S%O_P&f_9RriS^RgHj1PrJqMpxE$qeY%^5??z7Ne5r)Z}-`8EX51IP={_kHzc^7V zpAaF67A3#_5s-N~efeeot=n>Ez@*(wtnJulli7yKxh`saHI<+Mez47BWVrnx67lK6smyJh&}pUTOv?}5_t^era^+nE z0a;!6xxmFRWm$80?bHLHHcKP+QM=lGb?usO0)mSqoUTQ-Uo-Lnz@9yfV0sH2r@ZSv zCmQ`(jJk|0tUT2Nb(wj>-LwE|Xu&j+z~|^~dijovSh5^}H9+PyhAc0?ofT<2z}O?N zn49tNS21zs(W{?4HDw=mY&4QP3pYjcZ+`n01~9`lJO2)K&Y3`iLgN{S{0y-L=W;5e zxEJn!l^*OBK#Nu@oz5nTzbQC^Z{p#^x_tUs)gik>H zaHsNj6Q@zWuD!8@rVO4~#^`l!#j@h?c zh-rv0xk=5ER9gT&TyG!^ZUciKIi{Ln`8bAj>z3Lsb&3Um;QEQxf3X2XLQ$%$8S%~C z?*Z`6pqz!5S+PFYrl&8_ZJPF6!m>yp6(9S&U6#G<#Ow0#T0`Rcvhc$`pO^d6H$ReO zGHt&*)XZ}rNe~?RM5tgg4Lu~g4o1;o$ZtRY&y>Xc5=w0PoO-AG`67#Q8c^TKp@m); zd3f{O^K%p#1R5 z*BJ2xuC+x5>xceQXm>;1v_V8;-UC4N>YayLH?9n&Ga;BJKoa}q7Nn0F+CZJJ`Der5 zp!`|e`eS#6mVIlMNSU5ISz^vH{4ul@r8V;AsE?;ho2M1=Or9xbOXWohI;p0sG0Q9o zypYgMyrFFrm|^JeawPdyH({47#k|J@;CE?$=qA26YD*f1NEJu99++;NVcm1X&!Ehg zHLw=S96dr&3ntl%3TwAP*td;~MPH|vVwaeD(#fzuOQi-To`})mCRQS7~aC!io zvA`X6rNu$Z`C?b%42z6#X;{9S6>J!Ko$14jB<&^&z9AAt@01RIX7j#(qhXjTLv?ot&Fv?+Gq?gmOyrh9csAjD(626*CPY9%Ss`Bl$Z&60fvL7kI4(Td%9qa> zSs;D`A$)A#-R03h^rM_EpPPYe}GEMP~yyIyei{v0r9xhW0? zfvWS%qo(H9^lLNJoNtLl;Sj4-k9L5vBC*#oDm>~Yc+t)3+5Ip<< zF#7nDt&7%d_Ty}5+*kd35|oaH%fsqQaZo`d&xnxfZv@Nn#>^FE50RJwlOQ;?!n>#g zWc8E8WKkKrW6E(rr?6GEUlpf58~@23eTgcK(tcUB;tmOiDj6;3C}tUW3_;SP6VK-0 z?KVuL>c7@?;=u4)hBSavAd3X0UCUBje~H%--|+w#5&h%}mxUFCT0tZGd((yyAHhIo z5d7)A-%@!oAulegiUEKDfYC~SpiuBWkvU}Sd3B<^v&1c!A&p_f^S6xZUH8(6TC_u! zI?O<-2Z0J!c{0=p8H{!mcTktux!k@JjqgfBLuF7E!4H5KD;TV8w{Z(XY$4$(yPUIB z(IDWpV#r>!Lo(g{jHQ0Jquo{QYMd}nVBrk%xbInU*~HGurI3%$LiTQM0_#5vRp2TM zeS?r;&1PpHfNgT;Y{!Y-=tV+t`eJQRE-drzFm!8^$mIdhrIZzVV^BsD(vWT`W7_Qr z$~Xm?O(o565CRftrexl^41`91wB*|0%US_LvSRH#RzGoxNVOv=PWrx(z+3W3&QzH+ zLj#0YHET3JL8@hulsJ6>{4Nn@B$TKKqhK2mo7?F*c5&*`foV=_2JbRK+KVB$sN(R$ zd&P$KRzyW->yvJ-D}A!m43d-ID#T$;7n&`NoXf)XWbp|aQTAzodts0zp~9nWWc^W) z=dlDsY6VJ|HD;($Nm6fK8Ip991hik~HU*Kmn5C5j>)uV=1a|Xt7Eqdnrt34-$a;4q zE#4xVAJuFZrgqonCrZh(e4cmLJyTBW?mY?DuD3wB=FPBN7cuPI3VAz!aEf4p>z|Em zqS6QJdNjITFr7ItC%?1w9KKYc@&y={{6uY69X(SP_6XaaR1`}YO|c$~x3yovoP?-i ze_MI?YPAuv=Qftcv5@0y+BG>h?=&qciwmZpStvts@XxM$Wfu|b2j3-M>FG+5OBe*d z{x3J70Ug+=l8L*&_;|W2`|#7ng?!vH(GWj{!0_h{V)0`9iERry`J3Q(jQInnxuKwGkXzUI-z$pC-F6O0#~PU$;p(%c>(O_xn18rN4^kV_&8RimO73+r!uU)^KeA(PY1&~%H!HTh;pU#jS2|^$| z8H%9TzX8@fj2k6WB=lpF9%X@n_XnXUzfJB35y^l6agWcpPKXjQJ{*>wpS(>x=(cS9 zs(s#2dweFa>3UH?C6>i9%r)pGGDAQK;*%eSMwdj{1-NAI-+SGK<5T1mXb;UK1Rnd= z|IJizl~J*zGTN&Qp}j%h1Ti1NQ?AeO`4P1eA(FW z{OepB<_*$*)kZ>d@}{aEWqZC34m6_&(*j>Xw`5wiF?11(1ryT2|F zW4V~?&*&dWo+^u>^1mCebe`efE_z_=TkPy$4HSzALPR#hHvqJl*fK=0 zMwqc2KWgULp4mC+Xad1sWoBY;WppP|6_Uv<7zeziJ3R*;PMMc93LJ|FD?My_-( z&FJ*&r0hk{`k`v3vYc9!3|ows^^>59m`!kP5Wz;Lw>&pX@L>K>RT(RUFpOBgl@y5& zn|UqePGJWr)8L*{c;qd_q1D#I;x=3`S`5JGEM{~XL$3}#nSPslZ{Jy^(~#5k0D!Zo z<Vk3-!C|>B6!@r?+sejwDH3S zvRlP>6BEFpg-FU>uCwU&*T^n~I0i^?x!>jmXR*t5dk)aAeZ_?Va@{6GczA=sRw$Ky%@*0fZjk)fFlbzkKk(4~MVsTo* z1&rXmrU9*OBTfxwDeJU@n7yD)=-wYjhmDljL=DeCI3A8xv6qKGz^TwEo%QB>zi1lp zyRR3~91`WG^&vFCv=v8rR7>EO%DP9)c=u0#lMp~ z3+%!R$n!>7nvzUWdo@c=jslspjuX? zrx~3XRMn~R80kGYnqLXmS2}O6S0{OY&MkX5H>miSQttyRBwQ`T;4}df$@YauL5j+B zYiRaZ!8>5n2W)z~I1qKr7m{_jn@}SrEq-xP@tnApW}n4n1VDH(je+sG?D0&){oa>a z8}0iDJ;P8~d7DRKdoc~W)cuKHqLMeMLb8$=9fTyKMfP!9Qf}Xiams^pfO4ta;qZBd z4q>tev!$41@ak%p{J};}m9ExatT5tL4j)Ac$oGmPGeSnU)q7)2Ag>7S7VW5ALqS1A zFdTuUeEa~=%)EDaQxK>9#!#?qgH`qE$n|!ueXKDs5nG;3?8hTfuMIt*73|1peu!ge z45|~haBwzyS0WEkcqAtx!oNk5auAw~>^%|ne5zCy&=P+;@N0hsfh&eescy|r5#o|?E*n*rexcuet zSSX=i7rdwaf=-nn=mF3k5C|RC2a=2x>*L}&Z9fg?JO_wv=QUUD46;w4*5{KyJKk?1 zF6eF#>6HtXVEpNB_$Z@vyyf@R@d)EjFovRH<)CNOw$s{{fNA2#8Rl^YN2%)~u z$^=boi*a5W+f1bu8A_DC5TyeH(e|1cusnH2+=ty8p4`|+E^O~1-U|eyZiN5+RjezJ zc#W(TR{fSqY(DKG^70;%$>rg`=eGM60vqyG(x!RAh>;k?H=XcWoH<{CbM~{<*Htd# zck5qdoJq3IE|B`AEq9AxMH(rwje-0Eb}osFL3HwSbHP8R`J!|Q@VPk8rEf>PP<$OF zBck@S=(g#Mw3h%#chAACmZd;&8a|=VI3)%s(rA{97QLK_@*DqF2RO`2>Jm6VfH5vW z8Lu=XIJPXmgv10lXAkIY{C@lC0gzN|e)0Oc{Q}vgWMyTCU*uk+XwKlV$&7PK@hkE8 zM#(T|NM+RO*#B`?%f3~t%}8I`VZ5{*nM#0gbS(nIZYx18U^*obQaj@w`BX)(;zZ4u zwN+DrU7LY6I+1#uv8r_M0g(4bLFR48<#lPXBy2=cP=GKjsm;}w@ze-FWiu+sV(XBO z5j-p>kq_>=_?5=i3;beFiSh*S4Za*`G3`;=Ns>7o--gOq<7zJ|5}(9YjT zVw4qa)wIW?VWE)J)HhgVFGITzH|4}*Or-5@Q&OI>Ex$sokyjBb87E{S20#_EMp>_O zOtW2%pJ|zN-CegA7S{_^+UR%OWu%1CMl_d zvUjatfcW=WU#D`4jWCbXyu-P6g2xAP>Az`PcDaX`j)&8fO^*H1w~^DL&^e8#Oy?(I zzN=DwteQiTrX)m{dh>O&KPj&(On;X212EEhhe99o0kGNQu@SC)*VyX8r-xtm0AS!w zF_1V?yL|wdNhV3)FKm}=f7Pc5`a&5j*%HJLa=nQ`n}5cs-6TTpKuC#SNzy$PhwH>U<6GR&M?1^w+(x zuz=rmPjf1}F~onX9Ksh%;^;^cfwlz6I2wp^jUTI-hwElgZ1{AlcQ>60KLBLH@Pe5Q*M?9sI9bi@@Kg8oh>dG~ys_jc5Ypsxv{5LK zZo8bmn$Vt-|F)BJsL}rDn7p`*RmRMtVG|M6hmppZTa{*Mz}(H=jnk>PQzuZ!yQbbQ zhQmFKStq-**hG7S_kzWW$#}kmmmdeK1t#b=ykJ?fm~xzv>F!>&GJeX{+=3g=Xz7@| z?W&dRce<3f&ZQJ0j$VO@SykDd8n3a*M2VBmNgsK6r+vo7(1f%ii;v{FE*jX*fne=`6jmi$vaVZd_(2ND|b^& ze+m-0QeD*)%wM3w8i`TG+rQvV^Er(*niB0^P$0og_h`jH^V5BIF{{#VlB_|+u5gNv zL;7ZtnF4{8G_AY0x&!vTkz?wCKgnHon_|I~j!rzq=%HPIbO6gMbi3=ZIfUNBlw<=Q z+*S7@W5VLqw%wOMK0ftI)KVh0dHDcn>WG)+vWv?MnLWnbsVrxf`AjwpeVr=@NcMF{ zzPVA_yBl`j#yA~(k|h}58-+nw4jA{8RV!b(PHC4g6<&J!!WK@6PL*h(VX}*hfq56) zvwgFmqcAb>qy~4R%mUh}Oz&opI-0Ds`1;rKZoT!Y=KHC@4`6Cl#R8GCdJ5H-$c`~a_SCjqILCzOqJlR3N0Bh)e=9jnMgDvX8dTUBs zIA{jHBo=%CO%VkTU1_xu_-6nQG!W0(TJ4FM3|e$ZGATIj-&^Pt`lVwnEblR{3+ouo~c&j^o{ z)w3_A4w^|Po1b<2YaFs<-$^3A3ex&}Od|+{q0aafdM-(IrVSdh>rxDhg(^JZDr@T$ z1!MUh3#W*3riHW=$&aI4S|lTcUKiy)A4OlWb@sDIre5yueod`wNaLhgtBx8^iJ*5? zMr|SKbB0^#O@a2J*ye`8+vzy$)%FxOp}_piMs)d`K)}&-DVMm^S5Yh5bo@kZBPmK* zUQtifid9XcPrK2<;jc&iY7B_St$BNf;XNLs0z8$wZ7YZK&Ln50JdPMd!7sn4cyD7~ z+$e)e?9+y*gzX4~CwmF@_7C}9@6%{S{EfexeWoE^`*Mi-RYv%Lxy~88I;-C z$KFXOA!Mw%&_fE4`=HLP`{Nvsiz2cIK;@Zc*80s&pbt?00l--pTj!|8a;}P*yV0iO zih~Nhegl8r%`#{iNJd4R)6^HCWS{R``Y5fTSx?JoD%5!29W0+czm(h z7-0v{Dfa#Pn$;WYAVdOGViyw_dt*M~wZl(yqYMm|4=?6`tog8Z><^RX_ z8}{y~t-ujClh}|l!)D1d1#}7*1n$wn0itqs0Kqv;iDxbMRGB)0N-`}1}9kM#vBbFK-Z=tYtVveTi&vI14tMc!nK zRk~GC)NCfb=2fdBNQ%V)cumX4Mu&Yd4<|%#Wz|aq`$Cm5TIG$<(D2octrjXn^ZP++ zvCkhr=cz2A=J`QuwYEQ(>d?RJasHmHu<{wL{EMr@8;TKv`ra4YK@{e7mnK%tD!)~g zZdwFxQu%2P*L^{`>bqS_GFqs$MgOL>b8JWupPZlPWrO!DgHz5WYcI&%g~4?2o*l7T!3a6Sv-Bh(pXlKOI6R?BCfA??Xe zDG@W*yWyv|L2h|CyE>d}v`QDlSVI$a7eKew5+|UV{WY>1ol@NWZtU!&0-cvMSyky( zWZ5T!&tvgro3)*oi3H(Z+CAdh!{5St5z6-Usf>w2;p_8Q3H1~U+O2kX?F|}$v0JOw zU5#ABF)gRnls5OXyVUFBdlg+~rVM-oE)o{Q62t@^$ z-MEC#E~Gpusvj3&eQcqh2+wEX=D*1&RN0>|YkrR_qo=bf`l61p=YtILVyQ(B1c{VO zX6knq|D!S@?MG%xKu0g0c25w`pa%YZHzv@_Os#~~3;pqv-{1RSx|DOG?IR4=CdR9e zcIVyU(3yi8P3w?$sLcMTWQ>i(ndcTE~;zq{`al+(QL z*A-6@lj&4sZnNY04zz==NF#23i^v{aMdGrjBeHP>gxMk-I|aN`*=h_Olo-;LJN1cj zJQK$^?{GCVXWM{&`lFQNi3Fsfcwg0Sg0>KY5d4i&)>q=Xnzv?qo=PFPsmV9A=*-N7 zzR}wSYkPd1?W`Y>*KoZ8u+n2PZ0N=v@9;Wo(mNm~BWQO{Z}q9{U>V;ZOGAxTscJDO`T+@f{l_YM+?wZwS?b zzCPVeX@mKZ9UiD3YCO7Mac1IS&YpEIwqz7Q{8-4se3Yba$}lpC4+_pq_jfukH9|=ne5}aJfAbV2VW#O^faLjQBjF zaB<@nFK}6vq=cI?uD>DCn9zBF6C}&E8c%?wXT!7X(VQ9KlAVIAt$hF(S8Ebd?efnZ z^`tE?>#J4Xth&~;xwLh*YxDHBj*fB%bl1YIO3Z;rC(0)efFJ~NJBNVIUDSzr$DIYO zb8H`=H&!S*&bjpmFI@oZf>1;LddlJR9hbOyLru>aA!SeBK7ed4kFmuyGnsu)_bi}L zr!3@oSon~?WsTUaSLccla-zJrM7;U%jNg>}`khL2WoxDt*7N*hC&cdoODcgX=O5Ut zy6yNIpZD2sUiSoJPIh;rPs5m*9MVM~?mK>#^kGut0KJj!Ax6 z_e8~3hJ>?v#w+UalJ45JaeajmT#a@RK6U77kibfQ`099?iG{l;K+=8FztiM-c>I1W z6FYOVcV3yeEZ>1nXXjVFHI4ZZLXqt}II3`%rgnHE9nig%S}tBL*2kTV+CUwdKAVkt z#P8U$o#ydfeF!S$8YGn#iE4|mjd=toW~7D zBj7$W065(!o12xmwB!S`@Vz1vCiIw+Qc1SX&A2p|gnwQ9xUQnc(u-IdGiJF4z_?yp z&K-)E=Y{N|>qWwp=S8G5f*QA>n;W^FxWfkXI_ zab+|>KPMn@WUIY*GCj4A`!bY*Z(AC(9q@4kWNl7z!?btiS1fk~m^GCvMCo5?0EIF?^# z?KXHGoDEhCcmMK0s*34|s%WwTdS$j;A-4-s8fy7ZQ)}Itj&Jv?UE+8xqmtB#ch40C z9D#i6`>kfDB~BtQt60iWKRvDxN07MmMP^p5>zVm%2bHI%UI<_nY&H4o@w)dXEq$_I zZs#g}tYC~Uhu7gw>`g2#UG?FQvnaZa0rMmd4O7Sk&65&!@$FbDbJOCr_7QjLq#pVC zl6U7KCEmO?JN6B`&q_ppT|WRK#Gx2N6x(=*;~=o6Ow&$FVqrN!hWL+;prY2vPn)D_ zZHz<400dMH1Or+vHA@ZLBt5rpSEA;jW1gWHt|pt<_bLA5fou;Mx2&cX@vx*`lhgWA z8!Mw?0nf90y^!wK!9hQC8ZWJPy77%QD5OY$sCIdA9Q>>Gb?gIxTDTX3#xN?|-;=mk zbB|=M>h8tYH;X3IlPUMP9PO&?zbvZj#n~a!N`0h|o=E0y@WMQrCQs&h!q;;Vv%~Y( zb00&u$8%Gb9NSQPqTuO-`DP+APCTYm8Siuj+`}o^$ZGS`Go9VNh3{e#v;wp3cuLxCWWm;T@mXqPLs4y4 z4k-b~=DG1V~3C-wxoN=2#$QF75huUmh(f++(=0KMU zH)>y>o|72;*je-1Enyc?Wg_=S9*y+4_cft%si@bH)_s25su{#&%Zui&``$jw@}TuZ zKiRrN(5)e^yS8JBX;iLAG6IKY^-?yCFLki7E|Hw&1ccg*yahKGH11(3hRF3vm@{+| ziO~v0;eWcQR4DGf5YQmjdxbVz|8v+@+6vV>kAn&OAC^r=JBM3 zLMf02E%b1;40>Q-gs$N0)Ui#dE$iLhDmJaCp>Lz)?bs+{0H7cL*tTUJxQOU#Ql=iK zd(nhI4Su+12NX)xGjTb%e-acW(zBZ4twCSE`L*=F0SrO&zWG8hz-6Nja7ZMMy)(^U zXxcEKpWYVQ;fcT>pC6?LCwAHaAe^XBzd1R^az0a43{;~HU)}v!P{P4YL8jl}QY7Fg zDi|(8xbO8Np48E_U^9`H-q;Q>F^It;Ae39u;BeFZ?hQOfOm%&*!afX zn|k%fnlr)nsE%Nh=I2)KRPd6iKY1i(w0tSr3qKjd`D#BtD0t*0au+IcSOL`j6{@hv z6<3fh&;oEj0ZNM4!U$h~edNY5{?SbSwUf;1MYkCyjX$$*Yf_TGbd1R3Z;e9dEl_3DRVJ2i;nKFJ;oN$2QPvKXK71$U?=XL=^1CF@ktvCpfB;!|e_afQjIyX)<$mcb8y`@^p1t!*(HRvF1Iu8cw}Fwy zIQ+X-j^$Kx(5WlXfz#>*Ihrws*jH;{ZdllEt!C#cH8?nbUq{ACz zY>;O^I*>Elr&@{QuPY|`f;cF~JknN1dqP;T$>X?EIQGZW^ro0unL!&^_26Um9eJzB z>Jx4b=Q-OWFv5CpbKaWUq>E{7zc%H_1p<0+kLLYqUNNb2Ie%Z*{4omy6ttU_yMJGi zpXC5|tYBnHvI0-atM_mT=lT6=AgsgY%Li@PVUVf#iqOaaB9+Q+1mW@Xb;!@n-k79? zW@Q^0B@4AOaJ&w^`KK>$oa8hm7TAC2yHTp%N)2n4R1e2OGNMBaXePaKt9ygB?PK zZ>BeskHV~;p!u6qosG1T=RNb&k4kWIT(B4b@&NnY_{DR}7dY<)_?*+i#!f0zZ=3Ea z7~cz!6yt9}As~AJO;k|(TY9lwzzv&0_5T1qm3Xn*jP9sez#9{0(dmU8RbW9bc9NCV{a|KU~wN0wL<~h z7+wco%C0et3}rITF~j`7T%Ia7bSwu97+|*}kD&JyJWSNNl}5j>Qz+s2R9`!M{fc{A z0TXFoF9U&?pFM6^jJMG-LWdGQL5-D*ZFUS8`u^`7{VH^1%bafNK2P~({Bk{NBE>?m z00P-3Vs0znKQE!7VpUIy=yAiwoPGUe zfQ6W2oUr5YpoK-+-@r0QUzg$29ZV< zL&EgrwPvue_9+p!OriXVCTRx$_* z#IW{Yb5U=IoE72QVE1qN>DQ;}?NS_}E{xa%02o<^wnI71LZJ0#0Eoa`DxJTlCqGlg zTya)+gjdYZ+1gyLHe|%wGY#eA35dI&JN>?X==xB?0;m*jlWxXuHyJ#hn=lXIP$Cyn z!y988Kp-5CZ(rv~pDLDT+^3vwlzjf6hy6NMa_0LrWd8uKQ>q^9rwPzr_Qjtr2MdM> zH~sVS{D(OJ5AdkI%n?|y1yOeA=F2y3huG2}04o!i_iY4#c={3TOy4`5!Q_9Na^Mdw z&#B{%^rMMNDiWJZ%&)7{jJ>3(xmEt^&|e`z3^G}pa|Z!t&raCD{zY|!4DSredhHy3eY*a%EOD!$GA7?lgPy~7%a&yMGo1Er z)iAY@cA<6&vpe2ibL)-V(w;p+(Q>mcmI2!Gr=v4gAi({>k%e*?9C~9vH%eC+EZI;; z%k$tV2dByg5A&^dw}L`5CdZ9(R5IY>+N-n{OrvzN9E=j-e)qlytz9h3+Dn#7OVZw6 zf7OgXvSgvm+KXNOUSHLW^9YOrRU84i*-lE1zzp-vH)t!+Z^zxq#y+{LQ$-YJF&v2Gz(vP%?VcR$x51$SfN>zH9(F>x0c%Sx92| z+5=&M`Tn1BrQ*5QD~0^l-=I*Z7c1=_#9_**AYh)n{{WBq=BD$NS~5S@D`(~bgAzRm zH5rq8ovZi0>Gb~q>vX31k%P7HLjM4(Vbp#jli#fr>!`b3x2N^Fa-}X?HOuN+idK-4 z!GeyCr)EA~y&Hr3-|(rCn3ZQ!i~+fdfsaC}G2iv7v9kQhxDo!*Bz^7u&-bu@9CWJ+ z;ldP9bJutuFVtflFzsoE-5b0aG4X&Itm zio+oyZQG=uC$3$;Kc*z!sH|N~gp7Q`GC=enFBIrb(;pcb>A^B&^kdYIY~z~J7^(8> zZf^YzRT(98wS7AM!yTtrT>k*7bR}4B++Dhs9l7mKTx^e)%CiE+6!718ecm|#03x0l zRrfrNo~*>@o<8byU%*t#6sZcONaU+!w;xbc@yV%JxW+c*Ptb@^tqPZmbB}2eD#}<5 z(vS{L-G_1Y&NEJpNeTQ%8%rVDRDat{)VoMKfx{<67#qJ3DBFyo+&3mz;2fV~LB}4L z=~o!o~_G8ssaCO{s)ZiX{v(xaWe9akVMj`o7e}}j8_02gQQ)r8E8)P|t zBl&uK$DSxz0;;JaJF$^^!c1?1RP|bpYfQ|lc#P%GHM zFV&HKUIsrh^K#aBHUB%LU`b~c4diV>5Ow6-+nxw>KU zx-oybziaP*Uztwdr@u<9X1UB+ZK^>L^vQ0&GZFmFQ)wLX#zIi;$W<64xWE{sS!4<~ zHd)v*Ce`_lI~;t!hALxLo0CyW{;VdOe)E5YzcTP^f_DOd9otleUFEqsz~iMG=g2$R zwjF>+m2%vF3!D>=YNlpnC5AU|0|%e319aKH5j;+1{4z}a=h`k(~h-D zyNqeRWZX9rQHyhux-^n!EON!RoT%N59i?({*X90n{{TH%gDwaiHim3*#|%wm%1->Z z${m3DN%=?Mc;c0ut1M&|-1r1DFCL#O3QDautkR6U%Gzl--_X@*1Z-CX<*=*9JwW5% z)}`E9O{KEO2PKIE=n23*YY@qRhvp=|45YTue!WEjj&}pMKYMv`<^KTV-1haTl~u@{ zoz~A!^ERfR^8Wx{f7i&^$RNk}7`uGns6V>qG1H**>Bl*!OrI+dUMe%MQ3g@ zs+L9pK@Jdp@tv`_YGL8a9TBXR0>$G z(pE_eee8uJ89&O8I!`R&)Pgcu_>;^30G@$I0Q&)tYN0!++Het*uO#66F+5Wl&el!yz)k6t+*W zH9=bk@3#XBz{g&g9e)~POD5KR*k%~toDe_V#yfgaQcw7kvmEJP;Yk_{?8O+i0zMON z@_w0ObNJ?%@=G9y23?2vfKXrRK;xWr#Zofl{{Rsf-GIb%>%pfi#5$G867mBmY=7S) ziWPSH+xqn;oj68onWz1F7Xp~&>y;)}3M9h2FWoo?fCv8oUYWecq;QT`B)9|w`MWS6 zADsSmRppUTIw%|2fIC!>8?FHd1L;*JyM2@H^4-ib3`$lf8*-okCSX5$V;}C4dsW7~ zttl(G$9BKq{y|QhXf+utx3{|8{{RC>Tq(#@CwSc>Fx|bqL2T{(F-->%!2j*O#UU5z}`Jo$BR-W63v4m8d zqsu5qn%39T)VR|5g99z|V1cnS{{VaeidCG3BTO=ZY zr#t{N^uXi)0I$-eS&FbY1PlT=Cmz}9Qn3%(UBxBmprac~4aUkvq`r_9QV1$}QmTGT zjxtBmpEca2h~COK;lxA$gRTG_{{Y6R2V}~!hGI6BB!hr@aCqrRBvx|B2~~bNkFI@B zBdujpbmIN3+@aZT`JGaYO0c&*rM3DNkV|k1s!Br~#pOkweMzNDdCaJ*Z7BzwCAm}o z0DZ_eWAUirzPf<}MJOjEvBo3W=m;M#;aY9tYvw?bJZ?(nHbv!+sUUxx*Cl*qbt}@0 zd0$7ly(}IEaHksXeCy(ACZDFinON!ChR}lAL?^E0Es^Hz{vY;5K`ph?5VBg#Hn!|E zVFazl2{C|I=m@JTtm+c6Ei=OX0>(xc=H2Q2@9?N()%5`yhqxf0zvcvTaqh}U{4rRp zb~QW8lHN`JsM2^msuH{_RQs2gnV8~CGL!(vz$FPMr{~2rS8)M&1t8;g52pVY$yW3)T$QtQ}ZN6Sx&%4s$#$sA|~(UMn=nA#3Mtw1mCKaG)yask_o-;nuu z^u;&rq`H!*rGEFy*lxYM4!ytn-1E$F5q}JSuaQ`M76Da{EmzAfkK{=;yl`y`IZkq>@YEw^7&Ax8dtclZ6YI&^9+ZsW|r- zq!SFPG-#)PK+TSy-p+qoR%B8NN#=!lI026BzjpwhooHEtsif1;t0f6{Omr7{OoOI_)g1{W1e*ABP^)OBWei+0^CrB3Mec);Igh9%c%= z?ZlrZa6WPeOn(pIil(7rU7>+_8*G_XCNZDk$m{Mo=dCL`51p`fw(q_$ThuR=$LUN~ z1;IO8ampRT1;4z&a3J^V?@Cy!N10y5dl^EvES0}5f-@BZ=YKG}WFB+7hU@G90P3jR zh1z2S4hRDz#s~Yvrrhlwlk8Y^X5Ar@#C6eHq<4g z5(j)UDLpgL4#Pf}trjXPtNb78YVi6eI&I6kC%{kuU^CMIkPqk2YLCjDf&}M#@7k-M zm(%9$(xXX9U=^8yeaxvcKR$Y=^{0AI0IWBsV zX|F~4mqc=fMqmsfx3JoN@8Q$`0IyD29hHW{$lWqhFu(8^!1X<=HK&lT-jUgkz`L11 zQP=K~imm1_`BarB?-EJeJ%bVleweOG)0CgazDHE2N)07V%jCSg&E%GTJjoSu@`ERs zxiPMGjC8>IXWp8!FbdvcXFt4mCDsBC#3wE`IJEh8qJ2!z?)Zb?ZzF>Yxvq zLD*GUQ*(V#40Gv^rA$+E}_vY!7<6^5-_<`FK|0-~Rc0gWIlY36Xk8IeY>zc8@|$bx@2b)8~}^tKVPv zawUkBxg#6DBKAl-m@J%aCpb9zu03i817ZbbIWkT*o&NwT=Lk3FKh~+>fJW&8mcq8v zk=NhrNxKcXRaQ8`0k@I0n>(?X{%@h;x@c93mosYL=5SQ0R;;3`MX1Yb7k4NdF}SjQ z(lfX5JkqkR1GBP*T;QSkPI~Y^&T6t1WCcraBL^eq!Sv&b5t$QaUP&H3y;*>KU%Ghdk6;B<5=2#5F&mZ1+N{}LxWnXTfOabF zDBDTO9mYSK?_tT@IQOrfc$lYdb7g{rBhMJAFZg2e7|ff1RWUB;%P_;YsTCs42p(e- z=C_%LRRsLKI*)qISwiD#4U8}|hT1y}woW({h~XInbQ!@1vvvMex3`qxc}r78hrKu@ z6&`Npf=-X+u{{Vq|=A~PR(8wHgIX+%SVYk=$)sHwa zjZSuXnI{Yip4|>=KC@CaRNTGQ+3WsA%MZ;6-jjUYk#;i{c9WGq#sE|G!~Q?#6=7Kw zcA+53JC$$CAmG+|PZ44yWOAoz0a#_Z=p6Cdg=8`z8N&U-RCDzh;Jn#vm2Tl(6JnqPyzWsR{sEijyu$`6mCfv2Rn&UbB?@^^O~ZQGK2SaFG5qF$0M3_ zY^BPTS1;ym7z(S8yZ3k`d(^B<<@?0lzaQ)Rv8uvF)k~J~HdD*X2bXYP1JnB#*atQNPvv*$wj^eLL22Oh+xe7a*!9AfW7hIsR24b_Z@7doD|5Fn#ucf%$i( z98|Yg3E^Vtr|i^CMP*_(`L3OnQGa>UJy(yyg=p2B453xpU9LL5J1JZbzzV4wf`A5Z zFt!zgy6qjfQU~cxS=h01S&(3^6t?L-O163YFOA_C5<$+D9UP)W8{5h(w*j?vydZr2W?@t7bt7CB(QW=g1(>OImNV~~d zRU_)YP!BI(?#Z0~BASwBP>Q2srbLH#UtUimH0ffLekzMnC5GjXv$f~lY-^(Ga9q*JwZA3?s=xX;5+V7 zzp|hwKTde((x@2-*cj(6g1|ON{5n&-(n`5~gni5@&tKGM9epb$ikI4gW|E+t;Tml} zz`nDEXv-iYen`OLK6vBX{{YuWCj}U&&gc0CNGbT9zmKg`R#)SCs<7p--9Hn>DVOFu zxFC{HU<~@@M;(1?)qyw{95i&NGjxsHB&8+5l8ToS<$` zv6P$+Y5>JaCkywtDLcORU%j2Z`g+uCcdwXaVn2ivkUelcn!G7)n90T;ny+l`IWtVaP0G35bJHDCeP>CgvY21qHSeB0& z`H#$cdeRxO)Hy%HfCk*>rUo&Z!ZrD2eNC1XDsfU*l(sH2q>mG9$!=KSd0_oVdLQH< z6P%0`97(^|3&81ARm?>TV1_(^&5wQoz~|DDrDl~}wpmW*To0J^&hDf0#W><;DA`KS z%ufvm1mzb>OSk+I%N`?Ksb>BnIb8aK)Kq)bHh_oaY&(VkupWSP>)N9%qy}Ka4}vfW zKThMCSY%w1>RSgr0O!90jMG@Tt=}n}aBa%=_kXV<)*@C_%eM>|;~5Rqa4duYT$BCd*S|wbUNiFTD$DndPs!{udFkG!7^w2vO{;%h&c%bL zWSnp5{UXe9!l>@@zb7LjDaU=spZ@?|J}`^1i4H)*5*%UuPdxn%Re69_U8=+Vg2jDv zwwRI-OK-}d$saJ-eXw%e`qoant8aUk<|$!RB%EV^k#SXgrwpKNZNWh!E9^(t+N=E?OZKdmP8!jKyzZ9hJE>IEN0K`Yv>HO*#_hV^NzzxZez=isQlh?j!o_mEq=c&l<mRe6Uw!(UK(jhnBhf`%4|3m~W@0Fv_uzS9-|3F~A>88b%=j zMwPeYXgFdpPfQ*?Y6+cLRTaTvdgNsD>)M?>VtY2P{dX;3lcyPbHO((yFC+5n_R;;L zzBhb1_{F4n58)q*S430r#?!?IPMgD?7u1td*C*HYs}(PQ;yW1(7Q)sIHDw4DR}!+Q zVVe1mz#q0R?K>xp{2rby@n?s;UE#eZTOCKo8Ypcu!As(;2Tp@gu+;4|{{Ru``gBuh zx3~Izk@c);Hu6n%a<>}HHpsT= z4q>?#R@!8n$T?HP*CvJ~nE)%+}M|gt6EBJ>e~O%YDY1XLwo|rO-^) z&%hnDfBX}-_J#P7`$v2j@o$U1Cf?~Z=G#ql0$KFWbqB!nWAXZVS!9$RgjtL;;!p1X0ERoKfp6LJt8(}M0EQ*`+%qbZv#}>9+#mk{RZ1Uf zl~TZylDiY>*KJgG5jYB6!28_eJ$nj~BvZG{c10<0-V{GVO@J?>P6{-}U#XS=G7O zw?1yt0Qt84+~Dy`>uv8eX)G0=I$D2U*5u)~VU)85Y_RTE&>p{$r)O(#Qm%XOSbj_h z%~$hO1zn^zF}O1xK7{`OoKqTSQl430nH#zc zo(p5|e>#jvRQ#o#2L(qvhI<3jlf`SxFY+>3eWeDdJ4bTq$qZbDEJo0$ZwIy)9`zgH zHtx#&yYLjS&$u}iO|GEc-z(-HzTdpycK{aosiy6=Zsah06ePCD_wK+fPVe21uYBf* zh>G5^l(PD5xk?&&Zd>ycfXok;a#*1mIqRHpQ4EDv8Qrw9>?LqpgOJCbLF>g+dAF-< zlK@~1fF7gOvq&zcgq3Zsgaf)m85;)}$rPhrF;}~>iohyxe6CG@UZt|gRgN&O+nA}^ zLH5BJ`c-H0*ec~yIoiQKVV<~rXZ5Q7ch8hBBBJF%RRA1yJbd4dY9F*mkc`c-TL2Dl zG1EOyZnTyomRC>m62Qg#?oIg@bF~N0=WZBry#_&;Cs7dF@}AhHZQHmixdaila9x|% zZ%q9$RSf?CHcXN!JgH_Qcg?$y5BG&c(}2Jk95iPtKp>Nj<$C@!m3j4w{7ZN=)Lls1 zn7WF%&g>WDmLz@v1BLu56*2>~vnU*A0GxUfL8{VBGIk>s2V&%tmd9+GhD*)3%OkS& zMI`yXI+4?ybj3GbJH`nD!`a$VyEG(rBqr$q?1Yva{{Xa{)kv5swij?clmmgDicdw) zVaK&qGZhK7fM#6eIUM6XjYMu#7Z}0*EN@+&xY~KE_S2K*jFXS`{cq66>N1>^s#CM* zTQU?_Y*&Xu&v;dVjO{W36XA!G;@XX53aW{61G+M<;h|`teXa z!Zk(`f{gzFG3rJ>y(*(x4qUpY{dtS(a)OJEC+~OtO(Sr@aydY90XwD7PrBS6%9qVn zD#HUOa$p4n`j9XMV!gsdTb^I{MX*VY`$@_9yLIB8E`qxiA)s!9a_9a7>CSo@J)|vr zg23s`Chg>DiCI(^e?$MG6+xKuoWcBy=tode*l?ZLce((js z;Pv@hs{OF5lH@6jFc}5%?0#+%h~gtDk4(c^lGPjfjuyxX8aN z6+MYuA4+RY`@oodxg>$G0DhoxSPiH|p?4K*EPxIC;eP1iI$yQK{$Jl$k#}_@xBYQH z#ow-Lp-Ia`?-MnK<*UmW+tq#NLh_x!w5;VGNP^_3c^9Mcj-H(LSiVZ1jj*w2J%P}mC<`T+N z_*}Z+cEntNiK^y&g6hRpPTw_tW1sh1BR_>@eV~#E10y??0)TfW!;km}ACIj-mrMg; zNDkYPSP&hv*8`{N(wu5Xp8nBW{u{_rz|P9t&(MW03+;6$cF!+pzzTiwN-p^sd>7+6 z{nw`+pZ$8|e$?m+X97XIpPPpDC;W<%OV`?^jskg`RAU2g-QyhMybr9#QcXcLk5Zl= zlAk9or&Ar!W@Ov~b!Irg>-SGuR=Y%r516<AutYOBz{|Q zkN&l58r<7U@&|+ElpI!&I{|b;&A2mcC4zvC8GNn$YyR4!0_oW>U zy)RZJA>1>~KbEXRWe@kk2Z8OmigpI%$B#|rAMX~&fvV&0wcWbROz?YDX8cH;-=c&S$ULhKYB z?y@ja>x{46AY-+1X@05}FiSAy0Rww;+zx~MDbIAEqXLDtHWU;5T~0yI{{XJ7R)UIh zX3@dRmY*z|kukKD<-<#M03|Q&?eQ;~f_?{{REB7iC*w$>s)KrbZ~I9)KVi`igm<%w>^El-buj z_s;;=8gJuO0a!WNxkysEPxIP~-G^aaQp)V}uIq2i>tma6Q62$I<*>?qc_7u8rbZi{NeBaKs3duV+=G$$S01QuqBV?18_2hMeQg(?MM&6qPAJ3ng@${<# z;xYuSAta_p%0h$x09^j}YUC36PSrDDmD*S~K5zNy>5p!eD83$kJiyKuY?5vut9u_` z@uw=Xhr=!Vo5KYt!Y`BFk<~5Yhf{(^;?0srKDo|E;ZOTgmIN@tUF78Qzw^)e``0SB z>h7tGG@KB`s04J$2iQ`J_1v)lI_}T8_ddhvLaN`n&GR;RI()WP{=Quft~-D>Ge}Di zWEn4o9X4Y)^!2B;%!<+FNC#%p#Nl><=Hw6SpK9g4-mIg0D!G1ne=~n`w{`&b#wyz1 zp&4S#pFdNR^O3t5=ltF;lp< zaG&jcY9zW$t|d8Rx;8_S$JCbT{{Yvl)*&{OlfU)-e2pW4<$R9Kc^yaE;|Y*P=Uu>% z-FSdz#!nJs=sR;<+FV3b zsFW5wou?<bqPKJxy*S;VjUAj7A9 z_v8cCxq){PI8b)0VL|JUspQi{<>MYxVNX^pNbS@fDpgvIUU#>Uq4rpqifWEQnI^^?sP)=A8MgqyMu30l>Y#~eJV!1j{xpcxcke( zs_l)u#?MsC)p#5$0;K5r@se=`UNzQpp^@15guG~c&H$XNq!8}gv#q|Bqs z40sKdPMm!8`F-NA+b_dDB>01+X+8(>Z-=7LuKpf;MABxO=I-II4~=!t3+Q^^fvytH zRe(z%zgey0Dg=$^%2dQrHvHkN{{X>7;r{@IXQAl2M~eI#FOFmVnzc<+T)4Q^n%X;m zi`pK!;j2AE!$VHEk{Q0=CY530N$t=~3oM3G4m1-`Zx0It5HOTKB{ytxou72l>=tk4E-MqO$8To^+C~!^==J^L5duEYuVIg-g zP+x$}yCdp}?_ZgJ6n|_{rrCUHw(!d7cNaeld@t~y#8#K{Yc^K;cE5M7c*k0^@h*?2 z$qbXt=dbo0u#AFYTZNslgc|mL6@Jp*8;U;w-FPci)4WSG{Ek9ebX(7`* zai?i_FP1Sa%?Q+#XHFF3%-e*mZ<2p;gUjUc6zRg9 z>Qs+3Rn^+`fM0lm z^jh3o_`l)@h;*x1RGA@`!YOXAw98m*BW;M%Czwx^#=P@G_!X_`o-F>=k4e&^)>8XU z@Lrg&s_KtzrfOFn9FN41#ElKlnLW|bwWB4=+?ii>uvi&7S6Abo8EW?b0JKl-L*i6h zi+imr!aAqd5q7=rD_do2chvp!g!peMt(DTo;wdNWA1aLOrGDvZwDmtH z{wUbb7m0o$T--%rZ+kDqt!BpKPl7GU=4rPYgI&vFX1Qr0vU74iLfeNMae-g1U+_hZ zdgdPz{CV)KpKOla*GBMuzEVqw{={x|y+Z22pX`I@7v4^b5^nQ6u&972^CaK+F+PZ{$9)}MjUC2g(__-^(xC=+VB4WfWO1c{+d?tpMr8g03u-E9G;+Nr(4Xi zU5HC^AFN_dxdij;$4cR$)XqQYq5lAufmnMEI)0UHH4sXJ!YRs(@E_OTzh7RJ`QxuB z$C=Gr@jjVglaDti`Tj>>w~lND5*YT_&T~0jeT6~L!6(xB&Gqe|I8_Etq9EMd@$FRWTih*yCoB+rM?ZB2f-OFPn z;2&&tuQTyijBR{1pk8Y;Vc@l&O|mD`>XuqmL5%zb6W*ae-(TIwiFvKbb%>#r zA~L6&iQOap+PPbHNSwHK$W8OZxP*PVQIVQ%qfRSde{bsK%7r`oHm&E=&r`2kqp|_09b0kR; z4bsfhM;vjk{{SnQ4#fNa0LrqdR#v)tF6OHbO-3-~cb>;>CCTLgCv=~@F3JH;IKUha zr9$^A0;+}t{{R?c{{W!p9-XU`ZA)*MxoFuASiE7kr?6mfap})A*>yaC@uOsP0ONz# z<&c`o+f;J8l764?+nCCNm%`j{-p5h)rBfLaGmtqa6Ny zYnT`7h}0G&bo+q6*N#65jWrd(0m)+0uwA5WRq4~O9<;rro4noc+x`uP@aZeJD}P>R zNRyUE&PtZrXWrQ(jDn!x{$1)LdkPdy=LIrP2R|p5l1Sw3skCDsR$}n6aM(;r}y=(<(0p~6iN!pz_C-upu3)bFLn88uE1&GM?9-oIb zgfS12O{ebf{{RD11&3U`u0Mgk_X;wI88X{R5@(J^IX~wW51+f|$s2iM;~e|fH6_!t z;aDkW`34k&^(1jg_NLfDe5z%O5>IBcWT2Dk(1P zWAhnKG2i6RP=1`!{h%={#PYckD-w|t-;?uxIj&gVDuh0I^56!`jlFmz9-mrCZ&xUY z!PS?6^C%-d3a$l5)@OSuT+z{PojFvBYCGHh80aRt8INP_`GYEa$7_0$Nhk593&@d( zWi6k)08mpLa7GPtBKg>qCBW;KDi7z6dWG+NwvJHwK3~jN2QSkkF#1(SzwbSoe)skB zCKyk8?$$b4E`eoLDjOIDTOkLg8#(-Hth0s;(aRwt7~XcD#~o{xYvaEqfDMhzs&gOE zQhmJettdu+x=NSG*BGs3FdNu#AVq!o7FBrc&?D*XF;0tn;!m$N>WxW^ws|esBK0RO-0HNqgR= zQNzx0rm9NZhfDVL5ukTq!|yR9=Z^IgY8yt;v5NiT0K$C+Is9vu`%<$ISb1l-3{UIM zII8V*v7THYCv<LzmZlmi?Jo1H=(=?R`sM$ry`F~%D)h?$dNeW$?{aUMp4eR&1 za4Nag1Gw_b0LLnRU`ZVEGsph`TDf^7`Bj{f0^|ZgKT)2YzdEXJ$`S!Ap>hkeFPM1b zV1l29D_G7x%UG^spX!yPQu0!8eU6@OPT+*te4rLZWL7-5`@c6|)~d;>xD4Bsr1K{Y_67bmDYhaLJ=38Z-3%^L_7^IR60k_Nxb0EbtPnTqoW~;X81>7w{FvqaqY^ z+KO0>yHgnS+DE^oUK4=FJ225EgsS=o=2O7tXVxmLPGbljmrpPa&xw(h+PDaYZ8dfh4_DwS=) zfms9Z`H##tla79sQLg*g%2X{KVa+Ak9aLI@R@m|s1$RC|s4{xtSAoYt$F)oL*$Iv{ z!Bzd^zXNlQt-#=ZmB+Q-^27oQw&T2^!u}$sH(&_VNrnTHf;SK4+Ml#;T+RuQsHF;N zts%M6{{UzgQY0m_)I>@X_?|~fmUC9Z#O9kBdkYU$6 zrdB_c^yG8RLq4wGBQe_H36ZvwlH8w^@z>hET94u`wGyl;c4TeE@g#VbMpaPB8o1nX zHr10W)=!rlRQ8_~ZYPP+g}u|GHN39`!PTXVxpnirQ* z_ky~ei}(uolVAO+JP+YrRdoGU<9)!j^X>+kvT6d-KeTgXUTMx;6WgV245J#{rwS6}k5;tkIMt_4F_dK+ z%cnBA^;p(EQHc{9i?Cu7E!>TOWANgpi&J70iCy{2gR}yknFEUX4iAmGR;M-Ht%kXx z&vj^BF6|(?vbdVvW99B<0l#q%{r6lRyZc}KJ@CPJH9r$+b6&zWJ*A>v&vz?hn1ojG z1q0kLKJ}z>d|g#~Q0IM>@A(}N#ZiwclpMMCwV!U!%=_&%CFdE9LhV4xUO@iUl7ph2-8ipDGaKp4Cx|pQ8m|8U?DT_ETaUE)Dki%7Ik%7&^3=qmaZLH7oRBH3qZfNRP5htv z8Z2HKoM#!yMp5+nA6>_(GK@wt8S4{A$y*go!>Vd8di*Iq@~rS zm*jmIx|nUd2m^K%-bG@+g2#jS)a$8{7U=T9e~L)tCudAyG3)iOn@_}9=g*gPRBz-# z99tKY{U#rRYE!zxyR#LvB?^azFTM^> z&duMy(yRL_uPj%z)_Se~0L%LMn9mnURHw?HEIl>+PpA`7d1Z_<9jJI9h6mf`2P501 zS&s5enP*gNZuy&c%gE@7Uo6Y<6IjY@mNW_Fe9^;#H%qkP9um#+Hu7i;=%f!zptfy)d!9IK%1EAGc;iBD7I)st%5U>xnIDF(YNu=qY)l#(#Xsd z7}D1O34ZU)Ir(sV{b+erbnNFJywPH4O=$@y-KB5L`YCT_WsfCE0I~ppWO^JZ{{R}5 zZ=}m%#~ndXcS(+;ApV&8SIx=ejdaY}n8w6ymNbc4FE7zukdgHVJaw%*Zyag?Nh@(I zh;!!LM2WcPIoSbFewf8&Jf^zk<*5ntc6a>(II0k}H907GuS4ize8hma8$$i<%e(9M z2dDF=9Z92Tg35zG>bAPS4-gby3)3X8nN?8%Iha6Y{CaB28T!taDy+Ld*pwCW}@9hKy zL(B==pEYoQ5V*%`@K5+owH8t%u#JlVshgrQJrB#rN{UY$>RZ8*#v}mbMzSsfXQoFr zQOmIoQIbpE^G318(3dibjJbcVr_g`eY*ib~F3j7(eX7ddxdV~KJ#{_Kq)Ku=_VKhH zdSGIzxCV|N-0IV!B1FML(XaFK-0P=Wl-1(w zywtzQ_5rE7K77KyZ`>q+4w=b!mrKlLk>GrM~S3#l=<0VzBw3%c;epP zR7KHeLA%WC8|z%l4Jj&3JN^FvLJL_A3QPB;Fk8A$YSez4q8oOX*9B%8$0xFC!lmZ7-u?VNkJ%n2l*XqYo3hyGe_CnS4x_N~?ex_rLL-}5SUu1W;m-)9viN>G7>A4X8|U#FT}f>PwT79b7QTfN z)uJ%P70D8rm9}gpabEI#X<+FHT|yF*8BA*If#k;A@wbhKZ%_H@&un~I`(T*7b>S^9 zMz9xC+3H#+j&xm0dsUt$k5ARDv`s%!`z#^{6I>W%mR+haN?-s01LydY4^Ez0DdH+l zoftTCHSsQ6UrVo%^gJl4Rn9O=4542UE^9*n0Lx~4gQfgL@V2+8MQ@_(UkP;$TG}?$ zG}v_A2Jy8O@@BAGo4D?5^f=^>bb{^U3>$NKk>r*npT{o|Ymp5`^55+maxuEOaTIXL z0gg^%(rISyYZ0{sgi9(e(YbaBU?K}~IUeo(3+M6HRKj1ynTqHkb_^IIu{QHIxd1)4> z1k%eiZyyM%PbKmCSM3$BSbRQ9QA#|~lsRuJZ>N^W;J@1y>+v01-jh`nV-+`~bkZ8z z@;|hw^^g$;=T>H5T(;gDlfXWh{Hod1t=DXVP8-b!o_U7$o|6U-9fHi*M++TLHCit-&R_R08h;(Ki$#X1Gm z{C)nzw>&ENosRup-7_7S0wb6zsPol3B|q!duw~#>gR;QxXWYuLeaqw6_dq zc{E=UUE4qJZrk_E46`FFnOm_UZ3*Savi`LfggjI6x8ocTc%MVj{3Y=R;jXi!!Qyv# z(?zzv)inT9ibCUQw=4*3n%VFNguD;o?;j_PKjC|L3st(&^whT3 zG>b^A?Js7RLeuWP&2crPo+p+}iz}$XDuc{1ot%@O3mJ%|hoMfMKLKCc)l{Ups8xDh zXxw8j^7B7c%B4c{{VtIUzPal@n&40AMmFv5>Tq6JG^P3JV8ibljcBv zTxZTX$Wf2X?}&Q7ovCQL)EZUYwXKZ56*b*f!%ltasX=QkhuJNpYjth0+Xb2h$Zlna zX~-u(YJb5m{CR8e^Wxvc-BVVc%TBY^{ut?&wpW^*q8O)^-^DhQ7$MlCI|Pv*ore&P z!oQ$h7|(=UVwEY)EhnS5xzQ*5to~xhR-ryMl}c4zcwVNkYD?bc>YthYMJA{~QRaDJ zhVh4WLchPp3oD#)7yb60t(#A)aq^wqgOPwq_38fr*006?0FM6vw3o*lkBVOnBKRk+ zX}3NBNpxEeAK&Sh9v{55v$&JRlUeH#-^+ifLiTqF;mt}}Lff!>i17$8WPROz@%zFM zqRDCF9|>E)ScRTlQrh4!_X{z_eou(OLX^~MVyVXcIn~zR=6%*080ztLBbU}tg_WHt zUG27v5k^5E0v(sc{?n`Em4K?+1v#>}Vm*TsLf7lOPYZ5-F$CW7ImnqVxn zEh|vhbvTw8Rc@z!KFY>Pe$0z5GFSJTV=?1%Zkl*n6QfV+wV^dqQi}JM>qq|p0PMz6 zt%j>5EG*w7V<#0Cc&TikpLBPhx95&7JURO^c)4sRXthmWSn#HwrOA?HH`->oZ{sK= z47|n%{3GqlWFi)EhrzCj{{Z6_m8<-5{hcJTn%Y}Wh(8K`BkKBX)6EV;_=igHcZ#$D zXv;2IXVUy3uN9N-p;p_Bwtq0cX%E^z;qUDs;AXb)zlil)s6HOUsB0R%yqZS6qHmj3 zZ88f9ZobzPNqHnzT7Ib*1P~VS#DXlE`Fq1Zw5iawFWJ9dUlv=n_rV_y>7ERZ%H^(O zyMs&9^j{KqW+G!vmkX&jB1p4CJ=r`~=)1fc2?$u+|txGg*mwSl(vI#ZA znq?V=4O(B~; z5?B!NFgeKs(3*2Yci`W}y<1fHW$^b=p61$g{{Vzj zMS|_;49#&Zjf5I~$&I1_u{Rd;lati@3iSr~meSL^>Zv7ZsR*ywX^>KBk2RIMm9F!Or1)pIPKH7;ZnA!S(rvjhAe>P zOo3ad!5n|}>*uRah;g}Zw_QOV8y;1>ZZ>@x#!u&368QU1hz0Xpw1!q7WRO?x{Ns`N z)@uV=oVg`VQj_eT`5hE-G%C__b5Vlo+PC?h;MdO}UPf?1$Oj|S->p1qM0}((Htb|F zuN?rw;=CpPBk5}xaXg|_Ib>u5cjPEvh z`(NQASeztzVCu&6+g%TEeLye>rNLpfRhX{9=*%!r;(JsQUzM3y$(QowA2Nmc)%T7R z0sgQ2de@FeKHWV?SiCFRYw$gh^%iJG)mAdU%*x!4&+h&d*>yEl2%x8wI=B-rXO6dr>;IqTECc^i0| zH3n6caH?2<%gXyu{wTKt&3OjZ@`+(0?fHgV<{b0&t5`bFmokGhgs3@kxvL}9p7BP) z(k?dThh4;b^%Wal5wRa(JHBG4XCB+SfA#CikBe=_*GVFgm5PLtM2ut8p1k_hZQ`iF zQqLQ2G7?>pPFL>#0IYs1NMUh2&RmY+Ql$uT^36VO%=IZR5J|htU5t2Oa~bEjJf8HA zdW2vS9fl8=kGwm9{6B^(%14TA5TR>`SPoE$5n*rLZy67qeB9MW@nxu#?7p@w=6tFy zQE{K5bg6i1?s0OA(w5dN~hu)?=o@;XyTiy_N8UTs1NZ@f_*4(6D~?70i)acJwy^Xp4h?xc zo-2XQQe_}1BL*S7`;feM>53o4a0Ud*s3iH^XLd*Zv+4L&>kT(#x#D1_7&f`%_nx0M z@n!?eAqXHU9ou+3Ww}3%Gy6eU9J;zIVZJ~%4wx7f1#7M(f_Zb$ofJN9BO-R%OEpHyHr*0x~xB?TTsf?v`*` zSwI~m^4DPFxyL_^Yb+IYYeDK0oj7Y6v421K2eYlxs4T|-$A)YvM*0#mI`+p}jqepz zLrIx8N)-gFz+O~jN6+J$@x<}fqq6fqqUECs2m6FzpL|rQ<7+ufFqz3$U?g|iW8C46 z06#bGjyVU{tyC~rrM)+={15B;M>T4cRBWoo{=SE<4MHM8SLd+-hCaAIH-5b;Pqt?y z9k@`V459J<=;Ju`uOd$wSf>VYxV{$!aN{1h`FeJ!)5Z2v4T(CjJifqGr_tY&`O|nx z(3Y@nFQWdC;a;4gnyVIk7GQ5I0#Td|eoEpw;_MUq{t%6=uA;!diU0h3tNV<*iw4gH~d z&doN@F~d(Y5h)R`%m`tQ4<|o4%j1Mcjo4gnlYUjC;16w;4v`8j`6={Y=XWb@f?BnIKPnIXtanYw1-mzn;KSa-&1iul&*-q6PesWbpK z({5eXCSBXgIs=I#-Oknpdt)3|h}igyq%9C(h>q>5sLoGZg=HhxwkgL^f$fs!JBegw zl$M1c^D@2pk%{#0UhNzlDf7~mK5BB?O@B|rL(0WwQ)-l>iIi%3%H2P{dt5&e^{YA7 z=EG2$*5s_7bg&Hr-8$ARAKOE?oZ3mIanfM;WHetc)Qu4+4- zco^0+cMBqXz+=q(20l~t#cH7*bewtJDi@i8a8mYq(<5ZB{XCW-Go@(kkWMncE*T5m3YN$Hls?r)#Tfe-M06ZGUSe zth#i++Y))Yd&3jO8MBC8{hr$q$ioR5gPgWV74UREC^30!3(1C*sF3a|;GCSX$po_Cq@fjuROLVAU+~9f4;?h*)YW=$Tep9> z{SvzUro3yYGhb^O^molh4<}Y;>*iu>|y&J znQw3QX=7`7Z&E1nEXi*=z_%L%$f}_HxEQa_NIX+2?q|8*x>soz_mVJaGrRX_P!N4F zf!GSwi^Q(h>gdqAONg9pQeu6~!RFkjYKC^e91QR{6^wFh4MeJaT_xt-`gt95&#`fh zC@QKH-*m6~pMOdFVti17(hVNh#1FI1S6i6ut$y7olV&aCyDydsR$faJ&nJOe-|*X? z7$TUwdcK(@y2Z9jDfEpzqkx+@*ubgZ^W+eJ4lDC+e-zIIimxP$pt0JLGODw0+;XH~ z;ol!#J66q~h^_Svw|A4rZ65ysD-aAz%zjq#i^2Wh9Xj*Zn#ztzm$*e#!p3~tb4mXI zk+RLP(x$1y7aKn%bM$W4_T>1L1AhMiQ-WhGHvVLi*lENgz?&}!NU#R^2{;4g=(rV| zuYTBn5w*l-kH@;Dq;DBm?X6+6w2Y52X2Dx)M3enuDeK!EIIqt6b^BPPFC6aCFP(uS z2;Kf|=W?b1`TqdIszKr?rItsMVyzls&h_8_00DlZ@HN*%C(G(6OW7+!%lwZzws(!8 zIHvu#H}ZeMvHHv5{{Y)p#&cRM8jpnjc&!Hc33h zKl;C!Nd14$70Zgsa^GmVC@C)}$IHA=Uk{pBt4{SP%09F7?0(Pbf4A#cvy9 znq#6ipB!zm(>Epy;e+P9Tt&2Tj)t|ZKj5J9T`kJn_*TK>j&>H7_Un5*lUp^s`>rk+ z+$oKGfz zXxKCI#5P2nKhEDU!*kZK{{UBVij=wIhmwA8(Au7Rj)%EY5tR<<`gi{TKlnef7ykh8 zP(K$z8#S+mG@>Ds%0Fp0tW`g~{*Q1sjC$v-aT=%X%kiG>`WdVx@a~so<}S-yJqpfi zdxUKHAkV10k}sLx4mS41ersF&KoZ1^JecKG+U$)R37654l&*N{25Kvxh)EHRo@Sld zW(b6S;ba{n01O2kjxswDSW?JvbmLA@!N$?=DS3Hoq1im+nW;Quvh5i8d875KMgIVT zh-=o??{DHC4Cpr+qB)ue(<9VY)@T_vlQMm+fHNT8E4^n5B%}-^CTN49XH#Xw_O(R@#Sx z3aq`m`wFQ)k1rgdlad7?|H?1_J7x@`*k<`6f48f+%>db2h^_F;`0oao*}h%b`862ya!EQe6BwC_}3w+ zf5Aa6VwUNl@FjtXn-)gz#5Yi+R{sFrzjV?Vn~!M775NLPc;dq1-q2gvTUazQtC^Nt zhe@NBFC|^l?)GSuE06hPQ$6ZkH{udYDo1p(A1rTx#SCe^afWA&V*rH*cH%qwRmX?$ zYNa@=E$#Msz3!bZg*?j#QVBUKF1FHJeA)V-Kj5NXDY;ANEc^$c>C-5RJvwXq?M~*^ ze68Mn#n2Hz@)z=t3UEBnlnyJZvHt*qhneM))&3sAwkMgcB#Xqd0VE&u(g7xoy_@mk zza#Z85-P!Kb7#t3BZyEcqemib+b&Q7w*LSk{cv;C=bAeFv0~yuG)72el_m1s9mj7d zzxvSJ;3fy4u8Lecm(Sgn8`;tGZv8z^K3UCNER{ccv!|oHWY0SlBpE5vMu6$8p7$hf|H}2rJ4a$4*+PS;$+uOvlYO&2{;SClY7B-qIiy8I#{?#lp z{{X0ew568Bx=#C0M0=^P$Qis>cLX*hSzIg^aJ-OQG*ZHDol#(z+pyea+RG$(Q_$}F zz%@f*;(Pb|M2l~!Pb{|A7nb)66ygXpn;DI@{PH=2%$^vgc)Z*KSIvki0f;iVZ!eD2 zS1)%vuAPl(@danePBf}seJ?FG{^|P#fBygl0M+c4-JtMpkgIVfN1d{p z5PYsb`t{IRf5Aa7?u-c^f-R&INiDmWyg_pEsw}$)lET9;HqV;`k&66gweg+YhT3bH z1=@s>8aat*1dA7v2qb*JJ$18uOuhRe>DB^h?qdc-zKN}&nh?=>EEe7yar?s=#^T$u zbDiAORpE*syQTFg-hXeO-CJ+=w(>VzO@^YUIbu0^HiL}$rT!fn{89R);xF63$5Y$M zWvBRCK=9rBnP4|_Uuzn)wsJ2D$z;~>B$NLDve{p1`M&4&pZLjfc?P3@@dH}Fx6|&v z*Y;MG6H2(0N#@&`EbL%}PJ%<7uB@lJk;QyNq3Sk;UTtpXOOGL>^7PD3(_UOi<|x^w zGbn`b{w6Mc>u74)_loXix3aUnzJlIHU-Wwhfi2*Q2`=M`d)UIm_MvAC?}-{Ln1DG1 z=L*>-2QU5ZA~fjXXm3(diib_E`M&gytTt=?r%lwO3bMxHe}_(-B`GgdmY*Z-R9zx|@VJZdWxw|^9TYXour z^M04CO=hV!KJZIDio@7~J*&Z`_(9{%K5Y`yRka#CnzpobtA8eYN!AH%Sk13bc5Lq& zG&YGM9h;ryGZlc!6bi!B;PD=lbEx=YO)FSS`v|YK8+j!#GG6GgOK_2D;!AcBn;nn^ zSwnep%4AT{fS`HttCC{p2bao)XiKV`f6VoxfX%Qp=-3LyN`dHF*xzp`*bhFtLD@=-6q*h~%q?O38&0iF2w^ni`gK9?RXaft_ zmD*^_Ki=}CQ?_OHY>#T;*I3mKWQpWCx`TAx7@O-EdE^4 zNWW;>viz9Y&)w-=R*Cy({7-;r`mVio;Qs&+Sj%^N4epO`rcI^mbHNNzUA4`|p>260 zX`$k|i6NWph9>f4CL%^_^1DOv6gCmbZ+A7%+8nWPZUe!VXJXKKWCv`>+>m z@e!vkSuNUq?R{6J&)Qup_RG+b@wwltA|5i>s8k(1X2! zKg5I|dgJeZZmkPTyf(LbHkqqLZf&BH=S7=Ww~kokZPK-`_L4{Tj77#q&tA3p6Je<9 zb3oVT{x2z*#}001-l4wqD&`!NBdX^I(z$!v>+6elmR(puJZkEZARtK6CzkBNN6dEd z&T-oZn)4}T_$P?9Oj45V8@}F$r}dg@jDD+>)WkQ|QnJ~1XY9q_?dPNF8hr6+-W9gf zH5)nahMzX2s#{(lw!MnN8BEr&K(F?Qt}G{zF8m)ff(r3odGMd&w~Ib6_=i-V#aFj} zBGR;L?LKIQz(t2lI=$?zFO-((n?u=I%ETTyj1H$imO2KgmX`i*rtftsr zjrDy?!rHCmw)Y+$dygI7v{LwmW}fRn)-QY?{{RS@J)E!IjcdRcv;5wek7=~og)x&7NoGbYvm*WezlWqqt__fhD2ZlkQuw+gKVm8ADF!vvEU z(p!WPC{e%nS(TUfqZPs6#(OMoJ302)cvGc@gkcxRpqDG&ZEf@N(H_T+96qr5R}NC4 zi=HMjr12u){mtGw;v2YUszf?It`*|hur04y_F+giP|NhQbHB6Mfkc06jJ zjIcWY004dh_}fjtwbwQO02KT^@Vs+d*|avAr;D`vjcHobQ`7Y+9_viAl3%gG-G%g=uecrzwarR?F7yXr&LKSc;c|tO2JEdo6 zzdyL}ygTs2DwYbCZJj!l^A}&;g!R(|y3Hk-VXjiYz1{uJ5sRlU!P4EkQBJbLA- zYZL9$ZZ34)UK?A>mKNb5)4Z!UT|!oskr85N+{~vKG>2XBRgLweGuZf=3(2qMOL*?| z4Qkd|E^TL!G-+i$gmTR)sCi_LHGB(l7CdBE=r_dw02TOS;%AF&wY?uv_*dX93e(~j zf_!0N;e7|ii24SdVc`D&2>5%$7up<;ZQ;u}UgJ=oKuh=X;J1$2>h;w{$jx(K81$__ z;&zen{WMP#d^ylt;rGLR1H*c}`X-|t>G4LhrP%7;9@PAQu8liOwUM=Jsr*Z4Eyd57 zJnbd%g&TIx{WK|EUKnQbH`?Jw4IKMJj8 zizI|`UH8Mib4l?Bg*3?Rt{y!eZ6isxI$hSAdu?HRf1=q-r)n`r1eWNsSx0?odB4j5 zNM*Qbca|o;ve&hB_?6=?7I?Q#PYGMv_`k+FkBaBB@TJV!hL@vFd2+W`wt9Wc5F^~( zMQaQqNknKR7aNRmB!U?HFZL?@fEz+5v_~uhWyC4c1+08d=_KG7|eDDG{s`$JRN)%A}vKmN%J(@ zn$pebcdE9&N8e=G78e6wEW+U_MzYN5D9KctyK-rJuJ1(j*4IbFf3(JzrTjVY*MfCD z2THoJvA*%wi5~5&tZre8Q%yrpn^lI!6_zt3*7lcD+@xs4s>2$v8-OF=9~gW<(zTdv zwOe%5EVYn^8~Z7&9qsRI;kq!yXGmBEWn#<@G8FC3-YfO{_RjcCulR?<9u@HFYWgI1 z{uS}2w;ZoL@>)T9@#!{J(8*^kvBsA75(zQ0a6%+uxQ?HXnva2R{OhSB)vXc}EyPVD zSzTI{nlXuOW{OAMZ7TNzaL+w!`p>~E`mYdhb{<%~Qp_>Yl&QaSVE*5c*Ejmf4sk?Kwqb-+R4<)|3mgVAsR^#mALfejJ-bnXJ{-3n;Wf+FFf|v`zM+! z(4;81jkB{jW6lMB&5OfTrG%1}7Mzk>JN{Nb0n5FF^9VXPn#xjZSjJF#+tm7V;J=2x zA?scr(VtH6#m(1-<(l-1_^h={>%)5m-10P1rIoC(VVlg{2KfY2gOC}s?B~J$D7BVV ze-3zxcz)G2wX>#yt*_dohG}CjZDh7_hE4HEHg4axB7IGLG5a<62UPfV;ok|}S^PxN zCA`ozU2{{myNknDEoz#Ex8ZF^!y1LGGiqAgMn$)^)uoXpF(}<)lY_ZdDPnt@ zO()_#!I@6T)@ZGQ8`nZv3_Y zE|sZGV=Q`Y;@n7Mxe(mh#FnzKX@X3vG>)i&erlHLW}YBb{IL`&l5hf#af~Mg`5s5kjI=CHAFguT4+UaFC-?l(6+E)v1Vz zQgMu&rOT(iWUp_L`;D&rXz(A0ZB6c@;(K|P9WLiuBTr$eJk~aH+ojZz{g)zn6)vJ+ zK1_ipUn%Pr_x6eSXKSKI;vwR@TZ<{31U8Yp@#<~neV{sASYN{g+IT)m9%aJA05ZiO zm+b6huglMaz9_e!N%)te>QmSy<==&6hfB5lIr~H2&7|v>L`QI;f>{eOA!G-0H0O3n z$@eddQrla6JNSzY+%|9p(5>Z-);m;^0V>``Bv|BtypFdqMIIQRmM{)Lugvs*6B^h_o`Fo_pNWU{aF1E1>yc%jL1K>R$)3)N?*E^;+MPV-sjdHAN{F*6>I(+ z{{V!9_^!iACQU>(k*(@FYU`?&7x!9vg|O47m_MFu+GsiXp}C2PB<8&X!G9HeH}NAw zgT&qx)W!aXEc4nV#@gc4wavOmE!0exixj?eDK)}YSC(z*LtK6swjL(X)d+m zn+UE~Vkg<|A5PXHXdv@eQ@skmINi`!9xo}!QJ~d40<9Qyjk&sQ&1LwV)Zv1bB9v=p zQKYL&l}X9jJvX)A;qpIZ$B6C#`EJ>wSlArOLSe=u1&Ze(er~-zsul4xj8B(&ETxE7 z+7Fi$i}z8`r|(~%xV~F{mHA6Q#=S?z-ZHp@Mf-M#q}^F+_mF7T+Qzdic2Q_v7u4^h z-+Os`Biv@z!KC}=k=$myvqt#qLcgk2djoNp(diAfxjcema#I09u zsd3}0nBifBhR0BQDa3y-2HxH@LCm9_x&7bPy<@>Yv{%Fz(LT#Bi2M&4+N5?+>K-Re zWi>Rmg-XYJeA;SClUs$JAKy+8pDUC+liyP(R3q(NV>Q`c{{WSbK7&}t3Rr6LbB|eB zD}34dlr{0?fMqfkI}#@jM&P?LdE@1%*IsbwU71KZ2)obfPECGX>wmN-#El5st*488 zA*i+5d5?8tV}EfCoB7)@aUJHH6I)NWji-9^(z7mpGW=_e;<$sx{u|U{D;&n!(mMma z8?0tQqoV`YxHS>WWl}Jcq^WXlq_z8%{{S-T(5*>Io2=zlKV?Z@rrM+RZ1{#n1fX$UHe}i_lK$q|ap%Wx2%C9$_eG3Dmh+BDz{J(SMvc{aE)tA+ zt;;9)Bz4ljVlfUfrHJ;CmtJdj-u6E7I^3w)W_gb7`7Gj1-na)J=hl&R;0l!zDQ^4Kkfn#I8A>XyurvvI~Ketp5 znY_f?n3xTv$m_Tv75VgkYQhA`{ec1m3=poRG=zrEdRg<=zI~|w0EV-Rd@)7g!@Z-+ zD{2$4C(YZk4VGg(aaw&sQ~0UMKO}NX4JsV2c!WwqSsZ z&)z-y_st;I=GZXPyB22H$e(qk+SvKNQ@6OU&)c8clUaZ}+ju@W;+hD;8?8#=OS?<8 zxfYpIw~jH^tAE2&-rJ3rdM1}F;Q36E++JG<({}y9n{$!7)~XmcDB3FW^rY)z(5BXA3KU4n(e+?PoHF88b$*1m%iMj=mHEjJ?K$Fv zo6fki(;C5~-tjb73viI_Me^Zz?=a`n^RI!E_NKIO#yt`hXky;` z?u(;0+4xu^Roy4=x#vEeIIGeA)0T}bxP2K>3TEO%cPu_(^@JN{$KgxrukBJx?=Cnw zQKcD1uRk|wC;FeyX}`)UGeskWN$r~~wZVV6-7t32@C%OFIKLA=By!mD;WLF4&X>k)J*O7n3@{Ce1m z?wx!r9a&Gc?7ei;@io@_$&=-f0OxBGS)M-SZxL^gf*`Yi6~XRgwt?TXUoNpep|WvO{tB8b5TGwQy=3 z?7z&@mb0lEb=!-lzq=-$+gUSi=HVqJ+EVV#wXuL>Uf5^P_|{urExC*3a~x5S#rFJ< z>Nw>6b5+{PW1lJsyrKKX^Jhk4IOlU@^`$mbOzXBJD(8_SHV4<9Xjr@iTDpv4zVhnf zE2&zVbeEOQPwg~lw~1Nysmkne@^=SrIQQ#S+fiAhhB%yw7-Kz9dJi$V{c4lJacJy- zNEPGCw&iT6{PQ66KK*MjypT9~;dopegkl&4^!?sA&23NW)qV9PReyJX#>QC3h_a;L zEiawUrW>|GvMlPn?h4r3yQV_p0Dcv`H8o`)y=PWk+i(CU=m)n>mF6jXDzI-XI79QJ z;XifL%=x+>Z_=;X-o8=^WQj=OA1}b^>w{BQ3mH06ij-HKzsxY$$>Hd{G+TnJvwtJM zT}ifpcQk-*GEBwLp2V}{_7sn-%o-F~9y~52@`xfv9oP^N za#(s3)4dC>{hBDuGX!Ec2;FyOPpdd2eutj4+sSPsfufwDAnyzU09*T*1Fs*-xrt1Q zS-g`Xy6j@S#);^xc^{v8-j*VS;YXgDjrA^ctKnVW~ z7U3e0A<6S5ExB|4((zF7_)IiCnu4t_?rOSsvDb&eV=>hrr9WX9_36;dT|(hg<#~Q) z!jP`WqmJkS?0@}rZ~JE9f(c}7G=DReZHnWm2l#&q>t5>EVWEx)RpNQX5vJuvf4Q`% z%Rss7)b}R1JyQAwIWdUiW?*+J`DLRYJ~-h1RmXY?2*{7w&*b}^C)j?c^F}%kEzQERka!I zd*AZ?bvj!M*(FmPNiI)Ta*Or*qmTZ*U1?>FJjvxdVg(C)_%7VEWk(n%TwLK;ixJq zHELddzK2t1c<9^r%Am#MnB?4c4`xHKpL}M!74cm5nq+o*W8bX0ft@uZc~i@HjDl!V zIOF32LlMXsK5+z)03J#Gt-V$_jH;17^2p1uuls~;Vbir=w$);`iKInll%QN3aI2hL zE`I6fpupg9z`;(mT&+_Iq`bae&V?C9nso6JqMt=K{ztUx@J@U?V|dSQWU{t~If0a{ z(@8rQ^I?hGYe21Vc_97D!P6VduuIpD;&zJaJ9eE`Mzw^`%q;TARVA7K0Ogoa0sbIs z&zr?7BuJAylNTF&$83nA=j2rTyMANFJB)M{^!J7=AiMBpo1tN#GPDXCmu*y(aT(pzZrYZn?;n73BRCaZOFvC1r<^KPJAg4i;EFrK+TTf`NiHs|#RU3c}k(}oyzS!`Gi8Y8Vd`B|hY3#Qj z4sUebUQK%QQ_=0d!*#59a!6XnI{+Hy{A)J4Yzq_ZMf*cMtkC3F#U44)H4SD{s>?mG zj>dd9-`pdr1Tn1Blw1b{CV4gazYXy%Ov5yClyC=d&E0pV0wyH`T--2hA+g<9H41(54TWDyb^JXM0ZPgV{KpC#$-%`Dn7$VeV zNuJgy;Zmv;Pot}5clI1`VK2ImM@wZeQ8H~Z~p)U{Le4S@fcNBSd3Llk57rOEstdI zrl)fTp|bw`C6TX$n6^fv|n0JD~PT03m9$jb0}TpnwN*Zf)Hn|ND6gT!|S zO^(KUC9|}VlV&rDMe|M?d)&<}54A3QFQWKM!y4|rbK@@u z_@`IA)O7o86G@8MZsoDk;nn0fFS_O=OFPpFpkM=r-V8D?TH`zo@z+Z5W~-;Ro8j*X zk!!4r+pAql!b$G6DZayXV>Pp0t>Fo5VP=ZmJ z%hPkQ##ob~9RC0hKjAdfthFt0>An_{#x&J$tt7a*VIs_iRklleDZHX#MRU8j!Q&#Q z)g$<2Xtxidc(vtWILJm%UqoLXF=k(X7} zq|>b}^6xa4w$EnLBU=bEh|%9b0Sqy?k&ISvh;9>0)Nb_YWsXLMdz%3MKmor=mLgFM z)^`#?a>!agx~3-!gM(d8lcVVx^w&wIYZeAQGTMDc+R_ERvV~?h`gWFHJBPPyN#@;Y z>z$;LDQ>6;>MuSQ$>JO6-R@w5OB;E<&~LRXs1|lfr?|VgX>Dxo36sva2d~YX9F8mK zqlv*&oe5$w3Yz{_r5DqqOZrF2)WYNHMx(%CB`Hh(Uq{|uKGSJ_Cx*j*@ol&QLljdg zFas*;74Z#u#)i;Ys_}A z#1AhZXK$eGUXT9(3fsln?z0`9hK(JclckG~5o<2C9vz1FQ_}3UHO8dzAGE49^bwe? zVxC;F%4AnL@XuBFb)?u`TX?5MeOq6*)?Ot@yoR&5v0F85J}X#mW0FO=eN`n5yqK_X zK~akRO43`vo+a=8COg9W#c zA|f!pUeUI`AC0s6yf^h~xO~5sc)#IPZXV8FjY|HyAEodI4pZWqQ;s(=l|_VCsY(&4 z?PIo$Mh$v9+syp)_=E6=#Xkxm(%)a#{4b~v5y>^JfsOB$<(|o*Ym~RQk4}{)m&(4e z{{UYkV0oDsHQIP{;g`kBdmBwlO7WM5{67uCrRUkA@gB3L-0h9GTD9%Anc>+H?$w<> zR-A+9oxtOdp}swQMz>!Kcn8ORA@F96;ux&;xoq@X-CJL})h*=HwXGxV*BYLQd*N${ zRLQqTfpav>RJ#Z8*{L1Wp%RP(SK=4~h7XJW}OQ^t6nD*297v8m6JrC6#{f_`yQcDMJE zcij4FoF&7!J}Jde%dzS2mZac=u8pi)}+oj^!q`OPOU6$M!453hXwaQt5^zkHhoL_G#L5 zcJp66?^Cq10>o|y=OsZWsmaOY=k2&}E?CSCCRHj%ht@xr4@NFpFXCP@<~|pSv-OnY zFchiKtzFP___1|m$<1qfJ96^*pQaxMbf1b=dd9z`L#Fr-#t^JlFR9!3yGTOPTWL|Y zvt}&b&P!tlp0?uIhDPSpS`(H&ZF}#IJYO$^{vR!(cxT{FvEpxxS{j;@^ZkJ*#S3 zESm0{Yk3@UO@FAxs0sBbiM9I^=`)cOjyCy97C_3$DU5=EEnxU};x3Z)>+3Gd@fZyH$8k6Ty#Cj;u?~tD{oCoE>c@7xht)0bL?La{?wLM zo*eP6iFxn~!#*UF#n!$N(`|f3E~DaG8}9_KgN@|xap6gHi?Cvr_H9DqE4GlcH`yU# zOLJT&f<7temcBWT<3{*R2Zp4)wbpcOVGre`u@P$oFWcCI}KOZ}t# zN8w<%I!2q}0jtL!hyMVxp6f`8>rY#C)9$134ZY&tT}aU>)EXp!3~-Fbq)ZCC3ys1< z7r}oEKWY1q4C{U<*F0aRX?`lbzO=VCx)tmZ$E8_G3_7*cw>nfBj-5OflR3S%RWUjr z+<_OHU9ZLO+84n;A8ouPWgmw$--QtPcFM-uYm0pj4Mnww)AauU8DCxM(rTI>odmjt z)z+{lmne)keu+wf<^)dWq@$2Fisi;eJZ}Agan@7LAYwbGV z#SP5pwv*gI3Dhq%lXoq??Z{$jnkLW8gre>FOT~U5)%6>QbnQw=uB_~u>i!v`g2ocF z>VNU`Bi=!7uG4!qcK-kf723&p7OiQa+FWV+oxsv`+vtLQqfWO;pnX?U)=NV3%IzlS z)g+85CP0ED1WEx3dt;*bg7kQ!#JYX|0EVE~ZZ-S8HtyZ+8%~n)-7apdH0zstSS6my z*r~RFOXaXH3&>ETji0(?I1HC9j2>H;P{Anlr3BaD;D0yq26LZhHD@eNWm^*AClsnp z``q6fi<*r#mrkdW*uq{xCB?Lo#HT(;mPTnk&(Fa6S94=MvANOjlGE(Q-b;p(BP_0x z$UzXb%%V-o!?p4W8>N;+%r|I@S8;;8E=TX)g?m6Cj#F7hqLuYKz z#Ec3%%Qeo`H~EVA3+_92I@eYG|0Mw$1uB4vHtl_)T+sKCtBx~iejk1H(0zM{B z2y5DAucvrV#CmncfvmmFmG-FG?ZeyKSy^fk$8}|Ob`%5_qS>T!KzWoYkIM5iU1!8o zrQ6?I+4y(FRywVphWr)a%^nF-?IMfBZx)wv4x_4C!Epo!d`}gjnIy}Da7e-Czc34AI5Z!6EdX=;f#Qy-a zFN1tXfAG&pyzuvmr||EF{vls$nv33Ri7d0psOh$PDoLeEw_)w(Nz%&ok~Ub`q;1MW z5Pl`q{vvpb#9j!}d>4CTWi^hEtz6%oW(!M)*Cn{rX1o!{d2+M)6I#aw)x>Z_u_i^h z%aToX+8%>t<@w$qxl64!&i>NM(%QpXScmq7{h~bATjjg9yYhrknEc4VMVj0JjGEUU z;r?BOz|qBGuo0t(!77THr7mY_t7^2}GBU3b^Ndb5t`iHGeR~g$RO-#vqT;DaEnX3N z-W{#?AF0~6*}PToOHlC^kA0}=`d!YP<}VH3-zCVi4dNSnW=D>9+!jl_XOcNHvQ3Jy z;Z7^@-^Nz5TkATiv%Je4-PuXvLSvD>(J{DT8iyQhmCE_MfIV;peL1asdGQS4EwtO| zH615K@Yb7WtyzgLQVZP!PrQo$%Sw)TRz!~KE4We8?_;nzA9a`?9sdA@qv5~!N-sQ9 zY2endcY9|V3$u57Zyh@@gEHFZA=X+dA&R~D=m++s-&j5rDd!fV4jV7U)`l1BU%r;rc57|! zUDSL>9oCn&g5W&Z$&Z@fD%f{Wj+?0SrTJ-pX- z3A{vxIKIr5aoJjk?8c9~5s)DBPv0zG=C7H=WAGGtIkJkFj5KA-Wof}a{`-Tm_5T3b zxrJ%MSY9BZgsiE1DNCD@qmG&>K~LWKe9m{nka)Ypi)pFLsa$DsYgS)tvUu*~GF@0+ z+ca^{pmpcB%10ie^=M9Cf4-WZf1&YLR-lsvYbq-B=I|y zw?1)}O{4%k?wA7{p10!v01eye`W}eyJ=xJT+bt5)dd0CUY$m&3GHB)w25s6QoM+|E zbIm_fxrW3^b4?0HuJ&vPM+cDPd{#G&J&;Coj`;Xf7McnIA8W^3Rud!b0uz_wLVgLBFr&#;fuz+ zJ_8T8BXWQFH!A#27F|+JJW8@H&zvTbC1GsQ?IF@Dh8vd+75MuGDZzM#9k$zQe}qeZQ?LqY7>c&`5ttdl#eq=!cD_?k=W<9a4-M^i$7=c zGX(DTrDi5Konw?pI*?TXA5NU~uYU=g(XB~Tt3fL5ZOr_SmdE6Ll_5@rXxD@~^1Ivr z00RD*+kb3H#9m_{W>*6&qjHU_y_AB(9f=~YuZZV@Rg}#0PGsG+foP?Gv%dJY0lVjs z&JQ0pF^pFsq+fV?E99G6hfteNQ#ku9a)B+(h8uwlW<j0e(@R zTysQv?wExnXNg^y2)8L2ZQJt4JpA6Z;^E<1gZ7vsx$a`|KHiQG2~QZJ zu)Ox1ugv+j_j#@Oo%{Hb?M#F1EZG=v{{Sqq1G|M1WGCKlyN}RfXtm~J8a2eBWQk;o z06{>~V`|UG$jgD8W2ZId7kcHK(xS%E+>*PJM`=)~!QhhIkFIJxGgy{+*3erkNN!LD zNgvCEN%w`+uEfYc-8^>1dvvElRN9sv%01Fwsq)fTwO%oXE!Ld8`F6JUXSYG(4Ha!H z{Mqk~+-6mf;@ik|R@|Zo^RxDy-1Vl*;|RlSwFT`78{TGNG9vxZtDb}Z0M}f4>0;ol zHu8|@3bU7$j^V%wRvwg$!JMN zwN)%kwu?utLoCnhH7a;%PMu%*ea$UBU9I@Dwu{Gh(V}MZ?i0QDz>xj#G9u1d_hpGa z$;j-p%{Fd|D&wF93LQ_s1Hfx>lcWXADmSi#(3j_T?^~(&9@+Q!Ed+ZPlu_ zMl-huE0BG5@Ah@^6xWcgg`SITh|G;|E&OE8V)HlL1-T83?~5>p0PPu5#cHMfbVhDRo$@fOg4yQjxc&Amme~kKmpB}9u+ay*R zcAsMsLoS~%)-(e#mgdo}R4nVL#S@t^<_+6-Z98lE%Z~W7h_GBwio#&A%MDJBADymQ zNi}QPd)xj;^uGmgmk#3ia|?;b;k~Tt%av;5u8Qv64~zagd^_dqjJe}TCcYpPx7~;QT@W(Z)obav_G0m}wVk&6;)#bLo)sMrxP|9PH zaW!lnS%j3Z(dE+aPu{h@4qxkI*CxKwqzH$^(1&#juW@4$V!-5XEpU0Lf3%|_IHA^T zq)*-9kjoN}ER!Q_+ycOIa&eQmf^cie*G`#a#-j46kcLG`Lvt@flOM~s{{Yuj?$#Se zjUk?90h~!ADEU@TzMx7E%6Q`#^sl~*FqJArQ>(1|p8<%DV!f^*QJpJWPH9WGdmgtX z<>jrwnmdbT5-vxPBCt=YoP+q)AMLxSo6K4AQM|}@xI$NU@hX+Z)4Q<1=cRcJa!vxw z*9@-z04s!&Ngyfz06htfK1TK!rAL}ZMwVHkg(TdrOGYFI{#dMU^MvctyMC{QsV+rR zo=>E8{{SP8>p0gOGMwsRRZX6fOKz?wy;en+)UskC+;}VGG>fMPqemKA#Y_ zxMOo9H!2xp^S4Z_$W6;O#pp=mikZAEDm;~1O?Fyz@<&Z7n7l-ysLfsM-R<|<=TC3q zM|enL$_d!T_7dcI*uW!!@(uv)TGo2Rk_Gc4xEW&VvTfSn^&4@3r_&hpuNt=#S?ZHo zMzde}cTxyW=L%hZ(TK_2$oD+^*Q6{yGPqdwcvo0tlYDW@9-QGzKb7Sul13;O=98R% z0p_!*JS8Z`OA$_-Wo>08AI&3|35Uhz4z){{V!B8)PVBVi|n6*;A6=-%$<%b^aU*;N=&(bTS=E*7n7N zF5k3_6%wbMBikW4DUZhBlbLJ@CTXSsbpZ%BUFe;tQlExc! zW>!&*lAx9J`G2KVk5NLPh>*F1h0r@hAFKtkp}yi^6<_&@pLyJ*u?B%ibP z5q@jS`uzyTIM=45AKpvJHTl@hMv`e%%?rk|w&#)Am@)qVbet&8cmN97OJsG8mn5&7 z!m{(Xpc(qtwtO}Cci;~bd_MSx;=dGl%TUp^ZwJ}Qd8BBT)+uuypd_&^VfKRYnH~wX zm$kD729U;OGRR5_@R+2KV{#zdyUW=4&hERggZzqb8AlabcxcX1mKWlavWx!!4!@>` zOD>*VuoW?I_McmiG*#4^@{&!o{_|qpVn_3sJc>zRyMQ82xdu%8anstg2B;y3ZC%Dx zl)8eTlD~BDGCvB(n7RnS+O9_MtiEVg^(1xU)~Lwg3P?e1gsW|hhTz>m51;ZYn$)UG zox8)eoz98R>gmDJO{;2}^7A%Y{!5ow*;P_0e8Qy=%FX`(0$$glVo8M<55x8BUd-;hh6l*Cd|jO0k;w z!32`b)=_|vF7XnH8HQENW-tKj=8~Rq0F0-I!qDb^(P5(>w4R^m_#H8ZBOOx*goI^U zGWe3;=d%1xk{gILojy3>R=A!AlRj!(Dd9E^+f$$3VDtRAt}gpgM3hK?!{#B|3i7KX zbtE=(^#1_$QzeO_xVyI4ME2%L=eM|xjJ{-#zBy&x8tfatyMc~6S39UiB6NyL(dJW< zL2sMbVBmh07)&-AZlvQrbv;q(|qecqAsj^(G%~o_rZK{U+Z_)a_v=-pzG-79 z%&6rsuFlJdyFUj9za2QN=X^j}WQ?i|86#yZX6nL8n2!o%PQ{n<`e(OF zoFxcLo=|f4d+zrC05Y){>e@naN%rb%8;O5*(16f`u^L<{W%O;JbJD(~_$}hIf2nv+ z!uqw$aM=F~7$;4aQSksbFNL|Bz z2ynlJbY2$mE!Tv#i!EBtI3$+M+TjJvG6(>W6<}65H?x8gh5Qq~!kOBnRwrP^DV<5(^278aCC5(w~; zlw&Dz^RsZwamSb5-q~umhWMfTODK?h!u&!o)wzc|e6)~in+B|<*~T**DH z%X=P;W8*uYvfZ`Iq*2@f1fEn|LM6XR!YYB5^u{S-@m-u(OCSq$iyGE1y>mCz-3SP5KB-6d6?WMeWwbQk{h+5*|?MCI!FfgD3 zbK#P#@g#Q=EyP%9glg-uCL6bM{$j6Oe;<0arrphQQYc++uN!Gdt?_Xzn@g3JDB)6C z51syF&tselD&eqR&B|3&;~uT)r<%Gtu$jhZ3`A>TXiASiRY}Qz&D4>!x{dK!m@d>%xAG_-!fnA^9%@Lh9?H(%#u>nd@r0AxTSn@OKmEP`&NcYqM9w&Hu76Wj&d7o%@IMgXE{B{?rW&? z^sN1*Zf#Kt;Yv>%q>Zqz?n_Fgzj@C)2R@bZmF0z{I+S@moMkxHPCH6c+AHq#^FHSV zTQSB{p^A0tO0-j_%+pehIO^dG$8VYFI+m?-cXHQyjqJDVutZGv(+P`+qe!BOnd2dX z#*%;!_p{dqx$QH@*M1h%Ui(M7gGadBjcKSYy{VPH$0JQ^h1%^BiM)qU`32ND8@a5Q z{6hlR{hZ%g%>zH0jV;Z-=J{PV5?dg7j@|qFU})){F48{8Y|OThLp9c(FC|rgUKk^F zX;bG_KLKR@T#`&%HsmSXXG>*a64O(~7~C?!q-bNSOmJ@{My2(Khn? z!bctyhCE;l02F+n0k`9OtvYRP?AYGhh(fDI@tE12Q|?EI+yH)@`q!Gg;JC@c6M)#* zPyIAtWEdZ%eT^FO_FTNtbmK2~Renz27XC-)n2JiCBCa9Ie$x>jeRDLq`>VD39-C#W zLv8knwAQ(TX{~08JGiwHBm)U>LGpaP!_JO2=e%lvgjW1sIPpw+8(T}QO%Iww%j8_V z5^c9dUo*{stNhZUWplN$f(?0fg!XEP@&;zTC61Sk*!ic%>^~ny^j1QCl`dm!R){(9Co7i;=b(74M1W6RLk&Ha|Hu0phxW)rJu^BicCpqimty<4dwT#TN zBgtyW$evp=Sm@DdHn753a_W}Q!k`jHV-9lTb$N1LvP!s>iGTHl8#@!GFna$0_3HGO zM&+#4Wir8OhbYU$b7wo0^~bhx?ODo(3efi06$^QK8Pm-(HCnA&82Y@}kB;>vCDY-& zk6`fKhNY@%dQ4h$>1%(eYL>R|J7PH_H#ZFdmF5F;BAFS&leA}n#eGfi&*S&RD<2Ep zd?dBeG@HK+Ug)~dhZ|6_Ta7zkxSHnQQkO+&uB7n<7Rxx)q_zF~#BmGC#FC>Q3R-xM zZ9TlmE@Tqhl`0glaVYz&uhcLe{j*lIpB-Q6E^cjQ5zQi)eC2lp#>(llWMnA9JAuYj zF#v&H7IVYcOy-nUBL_;nXxrGqr)qnDU#a%_2N?eVt94-T8HG$PBD3YMIP%o?lx^^9 z8EfXxuYN6SKM?gl1$;dCXRmxV(R>ka@as)|5Z-9l+Wxz#c(VIWvy#E}t#a2;@ipz8 zrNj9;jv><`vxG}|B8c{+VLo-zyj$Y$hc|+4GS=2ByS+874atV)c+Hc|9PKK?Wp6B* zVu;~^#=r+0R~xB(O7RAxA$#3k^5YNYd6ySc+$qQ)v$U>DvE1aA&RRxtcQGU$HNI4c zH-9qO6dpnJ0&dS#Q3rl$;wz-DS zPE9H#Xyc4BLoK{$g;1)DZU8^cTohNjjPl16v4;~rz!8-h$o~MQq-|fr71NDTuZmrV z8Hx#G-4ZV2wZx0gI)=tQI(t)KxkoVK)E_2H$>uCVF(!WSgeX6UPio%2GYx_L&KC^| zbl#h3+xq^k;#10V48s#fzCRl$t@m%U?0sM1?~0Z>mXF~-4L*|g38(40ZLX`XT|$CM zHH|B2jcw;<$JtKi&JYIs7~Bp`e8Y9&>7vz=cXVCa*Pn5*BR)mBZRS|SY63ZaPB2M1 zIW>!`Yj+mc7W+3d?g9rzLRp4zNh|X8KVEAFe-vsDBu-@8zE3dbCr>zb3=%<)pun%4 z%d+pNVk_3mBexbZ<3R3Xy;i3Y6vG|Z(Oh$ATb;h zk6hQ)L06O^P11v$H+J;@059uP;iXS2h9+*MdX(wZ-CcPevEi*c+S2}OeN{G0ts9xx zc@CkB`{NEWKsXs4@q?Q0tcI0qX#}B*Pa$zNys*dTDT+Aahz8r1RC%QeGldcrPyxk! z{{U~}h~~JtxVVm3-s60PK*Q#E_XHq;@_-$<9COZVV^8teNv!6QBQjgbF+;;koyz|J zIAQbr%D;Ofw@ixjF_~sB87^t_CEuC<0O>Zd?dAEVQ-Gr5O1x5+!lad#n_AfV7ectx z?ckqLmNvMPO_nQ$g=1BQHzMFd7BvBjWgWlTdv$ipfWxuYbzK`>(;Gn5ENw2dxvU!T zVh?o$(CVQ3r1A3Ts&{N30nD@+u|TyI(sWiW@f&cH{@bc@zO*O3A9re}J653pgr+pz|(kw=h zG`ZU3n4Syh9z~HrQtr&#i#G2VwR15pVWi6Dfm@Kk7HbFrs!xiVIap_bg*Nkcv!lN+qzG)n9D>mZ}%;msW%WyQ|T8wXAA8q_!_U^v#;(I5Ed~>R6lfiMU>KFQ*>^9=o8;wF! zbuZaOvP`zVY@m^DC7MQ9^R-Ff02ds6#}kczkR!Z?wB^>$sqp#mVlF-boQ)EjYi?7Mc&MXu;X_)$7brkffc43Bc(=AQHLic z*4zI80o(C8vHVi2dr3LD)t>34ew)ho{12jRJZY!tG1||fX_|CyEbc9@{@G<6=iBBt zmr{dpuYmEalf+dB*n%<@R1yy-;=Nl>vTYhI2L9tvS#)b=)CJF;i*I)GTm-d=CxRe~ zn1JDN$Si(lVtm5iR~P}(7Y@WUa^QjsGdIk62PE_()3s@f`$RU*k=v6To@+)Glt0WE z(g`h+= z7!3E2NDOezYy*s1Ba)2JsDtI+uOi!kFvSS_zz@o~Ch)@<6$^2c&sXw~Iqa^RL5m+r7b!u|kfy?L|4;;PkyjMWNJ z=@jqN%`J3zkqw$tu8xIZ??6zp1Y&)pa(JL@+UD3$(hHIZ@jTNc?LmNngr_MDu_v zux^v)MfBWGe;&V;dvvH(l?cfp(;RoLcJXbj(84WZl3Qrs$&pdY<%rw8oz73MC$Bwuubne; zW&w!`{HP!-ir+UUXc<2{a%wq>fo8Vv58%^iUXe7}-|C(xDm@Xufw*#W^{7YioM6Xf&6ajl_45q?Xd488{Ke zaR3tl><|uqMdOa1q~~@o7iyMvLe}vmnWvJ_MCL)W%!V|Drgs=6ytF_`J+gTu*Bu72 zlz5Tx<(X0_@NngKV0FkJJ8{#RtEuW_vMdp?*^uHuF|gne20mY?!LKS2uU4!nI!RHN zmc2ZWMs?{>o5a$aa`S$jE_#KowPS7`>T8BuhtA!SyF#!300LqN_QpM{LS1e-ZNeN} znAgtv{LC_E?lQtabDvO6cnQBvh^obdoyvwmw4YPYABAn&>T|N9CC8S0yb%*VH)q#( zJx3hU#ANaJDycP6KXKoN;&@kH!`UXPXqx#Rk8`OGZ6*?vw^)5)Gk&%z$rp>OuPAxkr{cZB^08zKUh@VOd?HktKcWgk~x>w>bbF$BrqY z>0?WDxyF3N+$DArMYH{Dl~Mx({?A=QD4mjyc{i@$%h}#I`5Gv}^-9756L1?fF-&PEw68W~qC}g&K5YiM?9ak888I z((D!|@-AJaIM}U#+gtv5WR9NX=ia>+!iu&H=eUYdD-y69SY`5L{{WUU?{ZiH>6{$% zn((=GxgZMucIh1DoC2s*oE|zJdX9bTsnPYIwsSa{CG#UO?OXzeFZE$cjPb|0?_Lf% z7}-;t>GMW1e?K$qGGFXxiKjZ4H7-x@dVi7Y()ggj@|$@POsTUGqzIe6N-SV@^sMoz z-_IIc%``hfoU){ZO_RyxPS413UUL-jNbQ4{2XgJ?Gj=1=w7%IGh0-|yj57lW#^M-r zg~l^p6T?YWgj_wVj`ML`-8}yQt$A(lHZse%jCAi(PjfMl zLk8H|V-#*e$0iE}oVX!=P(rUv56sqt7GV@!OgBh+lZ^R$ivf;+`CNMbHR(dVEHq;$ zOKbes^@P)1$788Y;#=EmYr}5{xJz4~ z3*H8@o=M}81-QMEHNhAI(!Woy{0rg3uf?rRuf5-hW%~ufUfkK}>u8E&ipf$VC9d;z z9F}b%C48|9=0OoTug2ei9xu_nE8~q8O=99JEf`&1PbxudW?610(}kMIOiqM0FgQ2| z=D==i^drY!F4L~(lJ7_HK7?=XG?BjQ>h&X?5($jLD<)TA4sD5vcX9#wPHXvl#N3}7 zisGtOa9FCiSYsp0%&GG(UA2CDX?;)XKMgV13LGm=m3cmMX`oOh70{V_ToF3qJj^z${lQ$ zNh6vV!%WRIPFa|edJ~HIHfxxoB|PQWW|hMEZg^gsk5(UA{g=b+s-|1R*eo4O&y#!q z0Kq>d@dGi2D~amjaBz((RkO7_c~$Xo7owjXOWZ^D5gdQ(Z2QwAg=?qG1{kX zO=bDzc4RI*zcUO^U%U_h0A9G+uOop;kyWlcB5v~C2VirN)3-kL8PwxQqnX)yWp6ylUUlxNKj_P6GKZ934YDzUFtEqNZPqWGrgNw=QfQDnA{iDnW& z9%p`lsd7wX*+?GMYU{-MW~TP7sYa1p+dryXsD(q46 zXKMh@(?7%wX2q#ZJh4OPFpwR^allS^JahQwy&Nq%^Qf^^CF~{J?(#g$W$0d*qPuV+9UVSNXO?N?PUFG>0_#WaYm=Wg0@wH zmJ^npM@tm`%C-Lh$m%q0Z&Hzr7Pk|jP{ah=9(VoZMhXg_ae_Nyx;OC+)|Gt}(-C)b z40uB_ywO`OTZpaX&ei$bfCpOg`EDe9eVO(cztUBsZ!CxIxm<4JvB;}hRqfHan&x@Z zc}mEpLgm7h`@b`C--)kMb+EXYDb%GKEi~WmJUUcym@2TsQ^iWr`%Ws|I`8-$z1N9v zZhp~qY@!*NnWYfh6-XJgmRSPix6b|h)s^_cSAwI4Bs*KHH6`XmnACrI(2AATgn{o@vuWM%qb|m4r@FuX>S-_5uf;=qSxcpn^5?L ztm=0U_Up+t3zH*A$t>?AELnD$fhXlVe}rL1MgXqIOz}3YaSfbP*jvh$a^@zIDODtg z`-V1?X-;}z*PH3uO_j_2u^l31c95pwDBT>}4nm^*ti8H=3huOLE@cc9#ROYKZ-RGw zGi3DltTB0(3k8RiaP(8B9rnM--!IECxT^IrIP6rVI=d*|^8WxG?QfOOfm2qx2+Ott zvI1Nf&pVfEV28@(eF&=~Tf5w#rMVESVL?eSc{`bho5?-xB5MCAxVzwu99!1Be10QL|26+8*Q$wy@MI$JN(aRxn?+X_U z3FSzTV0(0;iry(FqPG74kx)wSLd;sN$1Ab`K4%{z?g zsi{M&d{B!~)MJWdxy^SoO4Y!2LW(=<_E&-l!KI*vCG=;LbAZd&rxoNv>lmqfnge*XYV2ZXCf3mUju zbt4;DN)c&#CY_9%&x3yry!J@EHTG~<8H-!-8DX6CGV2ZLSd)AY_kwcgzDX3hk2}xWZR9!K&NGi}ab9=gFAizCMZA{Q!r{=%y_#EzH@V?3 z{z*l3+v=u@E9|gUYRyt}sVO$Kyqo;l^BhNq!_dRELWC%qgZKR&0{xJ2Gi)*53$vw=|N|x4F2(mj$OK<-GP0JzO%92#zWNRxygJ(eIiiaC%(9(0r^`+;+hmth=Cc~rr9Ep&@4TP+ zk`EDIpa3Pe$_eEpJBY_DJl;<~O5f9bPj>^PzhctnX8SvVJ+!haZxP7Ks%}2%-dCKQ z4i4{{iYubDAgHMjvOSZF)a^eenM^$ML{IqtG zc4m-z?yhQGe(pJr*ex*8i5Piva$K(&^YRo7;|KVTbH)lQ3K5EFD5RbCUWZkA&EivY zZQr}>is!`oiZaHjY88nG_i_`;0450-=k+z#*cV+3Wlds}=!vtm&`8vHPYa8-7AZuU)}WbyW$W=x;1XrjLw&Z|~g zya?P{f^Ni93SFEh`c z9}n$c?jgVO$NY~?@OSMmVFVztwCqQ5o;HYgkvL*yY#{4 zzJ&0{{1ijuhL;4ZE`jjVS^oe=7V$}~Xr3p#xwni+qYz$0;~1tKXYWYEo}DmJUz~A% z7YjTRl(5w0E3I52-rd?iPvHz!DxEkgc$$z_dMU|%O!2=D{?>mH^pA_)C-|2Jhw%3A zTi55mk@W3j!h>A!_L=sVQ0b)UTE+bT0B1ll7tDD`+<7MiY-_*pRUeOfRmJQP{4xEQ zF5-^j>;%5}7og6r7VVlbFc+)m?HEzNIRob0a!EyV%L9VNLkabq9V|ttQ~2q^fBI5q zYs~X16fo+BVP1;;=fPH_dv=mM&rtsWf~$OXm&_;OAMBwYn7jV~b?^hjs1e7{xd+>D zK7Md=J7XMIm};N!QU3ssda^Vz_(%40(hz_@;#d1Qd?p+O2sqSyH*gQiamf8>qQ0La z$#QiV+bP2@`+-Z#`-jeEnZ|7<)U!-XmYdhA{{Z&m&UNqGBjb;Vqj9KQd^1I6&f5=x zp9OTnIL{JTcm_8E{smq+s(e`SuB{<^`}=8GqVk{0)9mcSC;PTBMiBAULYgSA)pEQJ z3kyg6n+Hn|qW&E?L$~szeoe$U{CwQG@wKO?T9bXd$e|aE^>4f7+2Aq$3xm*f{{WA! z1w|)}wRU2RwuN_d`?-{{^(AK*KTJ_Yc2R^qtM?a9i1|rZt;+uZeJvmJKQA&k{8g#> znA>UqO}G(AILA_a?oTx^@usg3jHGs8?aBS!$1R_{f6}`Cp43r9;R#e+&`;GbBTOA? zwtu~s{sjL3%(Ogft4hSYRwbFk77hnn>HMX3mc$934=xsfAu5S+2{eA17m&SUdyeiiEe;*(|O!-yg zfDO(&_Xdh9e72o66qPuo=#FgawN)yORg!MsY5xG3Qsc$?nJ7G~HNr}{RJa6&Vafjh zNx?Yw{c4%q2Y%@kI3 zDZ%pI3GLB#I-ypiVeZtD)1zy!vUt;0O{$SuC<;i#cPEj~PV1w)@y$|y7wVG*c_OkW z1%K4bj0|-D07&5T+Z0h%8dUEe-N)`im3rK-_tO6Wz@Pb<*B&R-S>hXQlq+x*Cczla z4re*2o5ebszU3Cf_nkbs2m{b&UX)Q@ha^9deaQ0VR;Rab+DiKMWs%~2L9neAq2sTY zC?T=;!4v)O)7q_{6zU^pBD5Gl2gyGJr~Lf$_~wc$hY?PmzT*3rbaX_@gJ zqP43|n})DYukgpb*t&R>1-1YB~>qQmQ?BVRA?k(3u zaK@!iZAagJ_WHejdy{{{NqXx0;Iw0o4$0K7UYjljQePEnigvHr)pN8cNj8PgK)!Yd z{{UW!D}VTi#Nm#Y|4_XI($sHQX+=sRn=hflrT4EA0g^6bIo)S{6^OdXoS59G*o~1 zKdutVR%8#AEy*sskv$1X5kklo#@Ly$lzj<>ERC@i*+a|>hV03{P8efnkP&7~W(>di zoZmVB^E==FcF(!zE_3dkd*93RJg?{V+~+BDpY&UQ9~Bgq*`)kxgHnst&QYR`AV3^* zH%V?{(KUpi@h!L7yrGbyPm`Z&!9*$cMBBB1;^#^W<3l#QouCIdqE#sl@`b)N;Jc2( zno;x?Hr>jf-Wz-D|GL;To8eRYP-6()+bwzB$JKH?=JM^@hrcxi&0lUic}{tHteZ*K zw3hz<;ieXMCrHFZ(DswB$Mh$A4dd&5#rq~bIpYt+6HEjGhJr~_852Ab41eE*T>pFV zr9}F@U?wR$&+1Nr7}lAI=l&0PU{U|6dH zNdcJ=n!U~Y((GE}-VAmRVwp@!c^LHiaGJUXKXqT<&{0X=TfaN(wu z+Y?jG)QM z@Pkvaoin;uX;br_(w85s>og;ODny(b>}jX@&2zChXw78kMzg9G(ffD+d9S9gNQY#f zm|nBWEI0pcH`|9zX_0*Pwf^bu6GzCs$rWYfHI6&;p5E1~d)>in^gch%qx(}a`D+Cm zg*-j5U>>)$c@z8JGW06B&LM08QG~561Fpk=)mn^~b4qCw4p=8EGS}@aRr!6_!OL+Y zCnxW0_OZzY`pb0xd$~#XEJ-_A^Aa81e=8^LWT>~SkLxQ>Cs|J)CwEr`84%Dt>9Ls+ z>t+7`u3f(qkMG@iAUe()^W{N_OW)^IaZg1-==aw`rY!enrrZ=5 zToi{rSZo0Wet!@WD2A^E|T?79=gwy~&G*l|<*#N%T@!oW9;nRVjt z{9MlhHMG4=2orfw7h=>_S;nmG95shj2iG-_EM4p)`vuU8#(jAFrs^4bg z7i-%FDwv5rF%gz;IhHXcz&U{>j;8$Wl)HmV=R4^P3uh6!^9rHZE=R6t=`iNP7a#c0 zKGz#UgK(*ps5r*#E6E9l45Qx{-?$74Bz$kt_p!onXQ#>PM(j@>v=RP|eg6HpwxgqC zv(S2iTbvIffzhcbiA_O&mKSiNS6KZhD0GlQ+Q9(AKrfv2!y>Xi+@ffKn6qq@HQ&kx z=9PbjU~XxP;I0D%AsXAf^GC<#{qEvp)r8YZBf-bXcXl+k`Js2x{=`U<{x0Y9&=PZU zx9awk=;b%JNZVMjyY;^6Q(mZnEo$kZa3?}b%k>FLLL#v=5ffK z0xiVpXiU=j$U=}JM&b>#|Lnfxw7gB z6>6@E1@pY+4G#?V9(lUPwSK_eh?eNS@KENQv(X>m6I-9}zxO*N_TN_e(LO2TuCz0~ zBB098LZ`^UVCsv1p|S_4>1Eq5DO7It^-MQ&0wv2EUoCzR@0<6F-YL8IdbqIfRqEW8 zz&Kg)D-m~Mluy3RHm9t-&uagGa4Ew1`up=wvsG9JFBcD)GzP`W6swUjADN`g8Me}=+ccWWX!Vcz zQj0`Im@XTaJ-67@6f$>rcP|{^7WDId8mRy1MHbqK|8(OLQ_3qH*Dpr!wep9&K69tH zgs)wrhyEJ*4h+4OAU{-`ys?~5AJE=Isls;BflgroEG=k}Olgk?myK9{_mw z?TPvO^xPu5x#YdCl|c^%B*qNYg_1aK%S&HvxTxqoOsnzfv0T|xf_e3W`{TW9Bpen%YlT1pmXYpy&aIhDS}*0)?WHLV0X&_jNx{jaT905{;;RHQM!S^^$`yz zWW`^-ipe?jzE4hU{pjZ5FOMXZ#&8uRAYpJ7^X&wK5kDlw>s;`^RVM%K6nmj%E zvogW2x+BQo&7VIFX|B`t`N^3viwBU(bK7uyJt8$+{kHhkkkayP|1#W1@TS zK>sDW=moe;{9-|n`PD{;E_cmuxR=CE2}Nf0y1<^ep{Sh?aCg(< z?>HBb#l2Ytx1`I=&%fQcr7q6U33W{%xXb@_nz?jbxA@YYC=e2Z z-uWoH^?NhtFxyb~ehbCBVw`jdaIWufB<71!9|~5${ywr7io$A6e~=Bn{OXd=3=VvQzXr>(7~-TY{+@p=13^O?q_74`LE`F>3px zMon4CK~&w#XP1d~)iaF>Bc|47PW4aNEE^cfOkM?-B_4MDJ0xq2ecPv|1C-Nk%3)^N z`_K0eAp=o#Eh724Pd|&6{->3V4b1dwbzesRXKY-fW1yp17j!r28Z(*hSp(?khT6{k zKNuVGGOj*uQ!u+~G3%gOc#O{t)_=h8Zh5m?mzX5pKfjIp*>jGip6Sx##6^w{gXFXl zP5s3FH8Ed{g2yE>*Va25ICM+?z3~CH&VMK2t0*h07tV!ynjmlAW-s~;1hqiw)EB>Y z%zU+IbQ`V=YE+rQ9XxM(T}K`6I91!o_o}fE8km`xIa^sg>0tkW@zj8x0iup)W^#b@ zb1l1g^GI*6os62ybjJpwRRMDX?&qND2CJQ2;YO1Cr$X4-o;k49duKAF%_)WFH+Vg+ zre^POZ&etzDRP}GVRtele7XmZ7*C7%M9uL=g?a6;E}rQ@P9CAwu2}!`ke%6X|gLDS~Xh_cCD1I*QQl zqPTJ-;fB_1F=;!)-A!^-Q@69mka4~6DB?j5vE>M7=VHAtayX?@g1Br zDebt2m=;#01vm$$WjgBfC+w_6j%F&Z%*2>>Om(yREVmzhSm;?qPenYP%WTE2O;BFH z?h8LNHRr7%ntc55thwl2-#zv{j%$p~*4J}UyN?b0chR5ndjjgWb0Z_CPx*{$6QIiJ z{yT4C=jX2=2Ra2e%ltW2w1K_QG1~3-=~xluq}l0&J5BmXvTI|Rzrj!|hPAXh1#;U&rXHUlH()B zBm7Q#y%liQE%7%=;*q6LSH$3{J?P%dbA{2XfGX;Fu*oUwcwJ9w)Cxl6F)1m)_k2WR z>uTPZqXrn=E=&knv%+Ihn>TFBJ++3O5sr)#zDK-;E)?YVAH zGT|P@)b|xPoM7e;Qk+Bkco0v8CEQ|JKOb1>c9U%CNZxwaLb0itJqqP``$6jGvQ2dSn_e?7`l6S_V#U<=0)(^`T567 z8x?lV=wkSbtiN1BhIp^B)BQB}KcasNUgpAol4?l>8)>IDZvcD029==K8mE2NGu zl~ume_MC?k?_QR#Q{1fq?N!9s@D(*oTh}f*+z7Gm z)AHVACWuowvfIk$+iRab2{-cCyCD7|dSh+Ig(Ex2(9X#vDJDC|?4;Gks!0Jy6oOvN zKa<_BpDGCC<9E326%0*nhHLp%0~%TEo$?v zZ@ft~1H|5IiQ)pP)8VB2WK#ig8n1LelN(HkEId zcWs^IDOGW0PdkTMj`rM&-nH?U~&{FWd8j=ak zRwcV3(K5(+aatExnzw)(IfcCz9v=+I_JRF>yiVz&J~kuw-Tq^YP%N0;3Wep7Uv|Vo zJ+_z1km=2*3}B8Bs?*0l!D-GH?nKIF`tYT!G2`*>xaK`|1t@QR#PgcIX=7#UsCC{h z!c2nqVc5C+6PZ!`q(5LxKu%TxHKMLc45_m^M1^93&;WN*tFHlSn25)d>#IX6)>0 zwQcSFelvj1^E=Dc^@nY4$oVObs8AIKheu3{QsxOl>$UUEEF^zi+{&<}AimoGh5k9r zcRO7N-2A4%KRwJX0}Ea?Y2No)$xaFu)=kIoQhyEmkro;*gS!@v#?Os@eOyUlI~uIU zasaB-HH>^RFR_#CjsuH@WZ#N^0;m_E{Lms*WO-a3xPhKjg44t36&NF~M#|%F!vBTk z-fr_VaoG^k@m;6dwlmy0x#y1Yz(dsuaB}{?z<;GPE6dsADVz9BX{o54%{uYH35h z37n&=eQiP*a#%AAC6V4AeXzUu0o?Ez%efGJ6fsbW1*sIw)-!|(#1pK9?UNv$1ORE8 z__%{br9g=Fsfc?}ee(wl=rp4wABf{@B?$N0JHZm)9FJ$kKd* z*7ir&!s&l(HrKf)2>?!NbcyoXD;HiAiKVoYg8wqiK_=RQx%pY zM=O$Zb*o)2)57NfDy($yQNj5eqj!IxZW6w#U{a5GUly^h%pB+v{q%h+05HHqyPqmQ zQ+=-64qO|(_I%aSx-j3X%_nKcG=n&F9z2K_&{e^&ns)pFL85lSeQ9~-Uek_@5gF?R zx5KlPp*e`@0)R?TqmZTA&7wt6AVAxAJ4vX)RMe6AKLME@z+OE0#-iW7*Udd)9`zPI zun9J*8#JjURbos^%Q1N3&)wZwPcps>b8(>jcUc|zDZWT6L$(`rOFb=_km9eHH+zjH z9t229VS<6aqNhhx4P~aru-|P3fhSb_BrJ^UJV_62t^6v}lpust50 zvDHByoe}DjAIn53a;_D>RtvBNyuMd>DTH(WbdKF4`U_nLez;$nj6^g!VzPZzBC=wM zSU2Qbld<06JsHp>?^v(td2oToRt^|9AE^SH&{>tQANjf19I4Y$?(g9KjwR^voC}9{ zHFe1RfY_6yWg`f4OB4c%qR9&DGpA~WGrm%ORp*!@o(4Lzkw3cg15ab!pW#D-c4!qj z%x{tPXV&BpB$yJ46F4{au5^+Z5B=s>j+cqRAlwZCS8I1d3hgKh{Rc^85A32K-bX-# z`6_aNQ_V=2n*c;cXwG@QcI_J0AKqTl#VARZq(_T0{-Bmw=0!3ECP1)8&sNdhsLSB) z2+^9D4^T|oi2Tm9#6P|}7^m6^e~A4eJ!t~>L7-a+3z{KEbeFNF_`8IBE7MmZ z>rd0ns^L~9_((SghI5<~sP#zQ`QY2=LTDdF%;yc1ze5e*Zf7_y;Wruo1u5~c{dS9A zVeMym@tc}^p%GkouJOh+S2Is%r=s^kUi=fAprjeJhzWq6N2}eq!pFqQ{O=W_^%g5VK zpZrTSx7w}NA`FgBfk_C@3%GFlUP)Va(nFjY@ZZ#C307d)K?pUpuv@x=Zmm!>naZ}n zj~T%Pb{8hc6}wN%VxIJ(pxetQDZ(X=)#7H$!F8il(+k|2X=7^mUd_qX_CN24+Q-nI z*ChdkugPC_3)3|+i3LAUZ~m$Q$6)jGMSx0hm)R{lyXtKB?U(1ZX!eE#lQyh%=HI=Q z0?}|DYD0Nd8@5yNB5IhFNtofo1)HMhGe3;*kEK$!^353#icP&pH4XjpcXvH_`Q@Sk zh4uRQVgNr;+}z8gODhfFM)D);i8t@SKry@&FG5Si?r{GZfaLY20OXD;zzyp)6;~wL z0MmHO9Xs)Y__u&hn+0`7L1x~7+cU2;oJsPdEVHQP+R@f^q-{F~39;>hvuQ2IAm%M_G4&`JW3m|HQpRfw) zO2uz29gUdz>4%tA9I9S&S!S9WJwLw$t{Y(`t491CQb!W)Z(O~L60A@RAQ)pRrAxsn z(A|kKa;GGY*6V^WhO8}``r3Qw@*dsu+lVu&6l>vnA$alMQtx2e=qJDSAsQUa0r)ElE6tFjx%z%t=L+TV zIh%%UIl?+lMn@Z;>5fFEy-i4}Pt`~oq9%ChEjF8ZR)_N*|NJxIJCnuka4r8(ZD*89 zjB}(?mX2c490!h9njp7-z@e!Q}Vq^Mj0nZBagcv9nOgz@J34c z;w&{K3aa(jaeDFOTT;hK`fFo+wENNpHYV2n`aFw~j z+zC;y>g|oz(r_cDD;ey?DNx5wBzbkuwuA6veTrLS)V4#6xJEU%?g)0?NKA039BH$K z<@a0GSxH2`5UlDR?;Q@lwy>akEAZyQ&ZW;caScM>)Zv79J8B01SjA%h=(9y|6WC4Y zzSON2#4KBJDZGm{h7tEcM$OiL!uRALPT*{2rHpYj#5pZ(`vY`jcwi5-qcL+WmGP{x z+mr@tWsqZ>a7{wYWv&Wf)Zg7%lu_`W`gh7vRNDj0-;d0Hc+~GR)bJW^%BdLxPXoJ*-jGX4b;06{(#oLKr5@_-SeSeMfph z=*DR#s|w+PnehERO%+E*P8GWm)kGMxI~xA??e7>%S@_cBg|7{7M&wuAm`S(6U8yHD zkOrToY$$$YJmON1n5tt$PoPOK4wVpuu5OU!2t!CD2UsdRLMlLoCAhr&GW96oUF(~) zBVKjxAV148J3M66sxZ9X88T|4AtIv|2@1>rXmKP%Ez^Aza80XmX2Q?n&e>C&VjMyq zKjY<#Z{S64mEnfh5|RujWwpuSL;>07n4p>PKN#VSl#fK$O<23ZX4l`v-@OkU90CIg3{OK|$ z0|8t(#Kqlp2$Q+ZD|VvA%Knp3NsWtt{gnI__cMOCf2sV8*?;osL@PhQ@(ID(_Cta4 z?~9wliaU+2N^VNM(zhk{-z%~i4qW>oCb54oQPhEXch)8jC>BxwE{dM2oTiA3=9y#e ze4ic+akSUcgq_mNZArwd68^S2Fv+ldE|6e$60rxbiiI*<5*#Sq{-oBj zrbNfQzpby~fj-p0+502o$RfaI88zdlf)|&A36!+?_s09c?SX|++6N$M&%Uu@m|9HC z&f_gNy>HQpm2*6k(<)KuavJM{0dyjkGzV`LiKyTZY9p^2aBXgd&|-;o273&92c|@u z+?_nem%z@NYan^$21AqiYlA@S%QsNrbeROGwMQjIFDBj(Xgs1vXuf#}(!%RU1?XKC zI`9%zv%BWX&)bbO&KID5wn-Toqq;&m-X7lntL|rEM9H*}lxNW%^y(`aN!kTbh_B_z zK1P3R2XNaM(dW@uKfgJhmk36dqRyPh#MA;0cPVLKA|70o}bCt67 z>Gs1St#jFF=+G%)BLO`4t1nWgJVdt+Kwddc27#x0dK48{x)A;{YJyp=O`|Qm>18a2 z{HB?HQ)1;TOPtV>pNn`-AT9D&#Ee^OpG8pvnmv{2TgUz&EkCRG=OK@Gpyo!=aD`WG*lFnM#JFHM*? zL>M-=%_?O38Z_Y?=JfDqt2QgCMkClFlD$LpqPtoN#OJ1y+2Bcb7*aZJ!^GS>Q!wM( z-C+0EOSn&=2+0@m*QzUZJg-Ww=4yz(k%f5e$)`lTp@h@V z&z(cHZRrzwQ{@KfYZ23YNs?(YNJLoq{PqBBu|gAphi(QAM|HehCJfPs`CfvE;g-m; zA7<3SYgTCsp2)F%R8A>3)oYj{HzjuYme65|Syy_gilx-*>F?QJt9^>5BM`|#t$C0J zIl_InQYgz@4;>Q5K5L)(luyv!B@;)%dGrljRi7ytrZ2GID$nodiZ2p`b=%@w84)^0 zFO5gIZysAd(CL;Alrf2kTyfjM`GpmK{MtO#6W3?qm>!*G=OM7FSva4IrTqn~Iee~r zm`(~<9qn`NLG;VJ*HK-nB$`%F7+Y1nGrb%fh~Vqpjjf98-tJt?%2?%&jy*h}rqrwf z16jY6Vr-@bVGTdCIvFhztX6blmW+}N!vFF@=v*$=ixAqhviXNg{&Xje!ct3B$z0? z;EutdbfJe7>Vsw#`Tg1i#9}}vE9~*y1(R#%;omXgnkzV0nsY^!q>Hlw^8e>X)l?}c zW(^s2dC0gfs*k5fJ+{jin6~#7yGUSzo5AUv^;~a@xzfGtYzjI7DFR+x$8&Ge zkSA!hkbX{>t@tp4bIeBw3L3;+f!t^=NtekJ35j-i{{o{&Gr%~Wq2aFlK%;(%gLitF zsw&3Zs2}!UrCousAp{QiSR+jpj}8~aYJ3R4w17+y9W5ybr%+nX=8wj2hw-6C?G3GM z-eD%k?SRjQXeo?mW6qV+k761H!ci=C@t3>pg%vwZD57_m8!_Y;rym5vH!4*+z=PWF^BGdY1RI6875-w`w%eP=uqH7Zv=;tnGKIUTc zLO=z#B2yY8aN)&^5v!{aCE-7%zc*_qradee*YKCX=`|U!Cens-Bh4S?O6Wxl0{PZQ zS`08L53&BMtn9UvjWF$j8U5hb+)P^MhIk0-5UaRPkWZFab4xDz6P(D(NdL(@l@jAF)kU;gK?NkQ;b4!DWr$wl zj7M@G_3tNKj7Jq55tn98#+2e#%*IgfrI6(+QxHEE4_5uT`_fvng7Vz)j0C}wx^1~Lrd9gdCk*|h7*0;YY{izXd?Z0UV?pOleG!5S$VS`< zj4*yT#KwP&6Avky&i2DAfCEzkBrgJW`?oZ*^4wjqUnLesz{#uVHUu}Awi=Q_|%-Nl2c+jwo zxQLovdCv=AkxW{@n8&nbnt>bcj$W(5E`gUg{puPg3G1o zZ}7f35&;Vm{P0P*4;m?eDV^o)aUNY?q-r zYY+y$E9-uiwXK7PiNw1Qf?4b$3cMVRh+jLhD(lMT;Fg;_+N;xl(rKQks$qFTNa60$ z{lgr1xTOP2l^@#j*IgBYb_GV7jGcnogfB|?o5Zwx0)vJxo@hDV<3g}%fp(k?4hVB6 zJ{WWMqrvZ%=LHcK_V$w>k6vYBva)!)Kh{gD4t(Ell1@7Wa};X{mqjh?fImPP{yZbd z<59^#Obgbxe-X$f1~Dhn#BAXW0vk;?e7V(#U-#6|{$L*7n!jBq53YpcNC0pFWKY2D zJtUnb%t;F5OQZq=;Y}I*#!W*&^8iYD=l? zD3x4N*F&`}kx;}wL!#3GZE~qNucb))F*x>{>zRFT2mJ4z>B)S5htx4?=Y%pQW@qPX zCUh2fn0q#THe7givTjGKm*nHMqxgr4X9kZn3$HA~+RVs{us?_xYT?G&-o_%&zmTZI z0Jskf^QogiOGW!AqedX~^J?w6sng-JRag>95PJ2+uvHEkayD+m(cvH1T)PC0c(Frj zq0!htYqU0I;}3!A({8zyeLeWZ>37rP#}S~I9ZUhddY-lLdC zV~mo>xCY?Ghe$pkkXhcqcR<)CGn|W%4e1YG0r$5}3l-9#WPtZv)W|{p0S3>aO|mK- zx0mCaK>=!G|0h=s-T6y7g%-%!?&NgYyH=%SX2V+=8HjIVWf=~rI`&j6WUXfPi)uYJ zo^R_*M9}1h!gp;b2qJJxMGd!#c?w+F=!e?v;%IjceWUz>+Vf{yFW8cAbXpclCHC43 zEJ(cYMMwCr>XZ&o`A%mdOt+1Xosb>29pQl_8q-nG(^ebe<1<_FS<8o4IOJCSrt8dU zqaHyJZxm7^YlzQ9S0AJ!)N&{9sXC~8JtDsm$1V;$2P7Ln|z~)8u<8z10--!3G zAv=WHu10ViTm_CvZt!n6R{ObkDeV`JX@I+_#4u_0YTgAD7L-8#J;PbV1k~#!jwL0k zW|_Y-WxJr|??_5*@*h;z>uJ|^`gCvwZ+Em8T~*(g5tjDXW|wEo?!Y%OQVe*)*)RCE z#XKLvNz+_{qp_!Rk%Pp)h3+!dt`DpJ)&Ma6E{oeW z{}@-;B}nnI+KY$gsdj!cCs`x*e*o2Pxr-UZBSzZL20iV<8T4(RREC@u9q&%X_Mz;@-~49it~uraYH%G=i|P`fjTVp9 z!!8rf!{Nn0hAlCj9<1O&11861r?qy5UE#gZKC|qJ_~w45M46L=tvq*?~>V_7>E9IomyZ zKj{v5roU995z(F*QfG%^A9}IceiQ-Rp{r-}kGg+9qU{EO1fFk@ttTPu>sehT6_P3f7N+{_lfjEM*Q8oui%jmeL_ ztByG;<6B(`jvG&kZ`};qWdz@WduNW3hUNUsbsbmm;Ih$SwSj+j03Bby#szvXjgU>l z)<$Ug4*17l$pX&NP3OmAg5vDHZP+2L;fPAJRxE^X0TTBh+*V&nn)eR#EN_$p6RAf0ItD2lf6h z$nu@fqggzm7nhn_HR2K36D0PeG2Q8??&qZ@J-$rR`Z#g<}%=Cf&21NFEq ztg<@-@s-4nRJ*V)|6r7Rj27`T`e?$=H+(?3-4vrRj@P3RSf!50|L7f4ztV%*v)y$=^Qd z)I111>LbbPm>+?T7DDd6ZVxC7M8vrFAs796uzBLIaDQf|rA1wrdDb`hd&d{~3V#f< zlnrU!LC#s;?>Gu2Hj9{cT%XVY+oP?lw49`XS-rKhhi&m)EgH*B@G zwwL~6sQm{gVt6P3H8m-iE&`h znQy0#RbR&h(*Zq=)3o^8=N5e&WH(iZh|S^cndyl&Y^Pln$%u6i5xu)%mIu!%muWWP zDFa$FRckv^GOAw_3_H94u1@#qc!XFCsJvBnWheK%S9s;9>4hJ=0sYE9Nz5SMOIq8k zA*EUjydE)#rna$Ar4snlLNnnn(rW^1eadV#uae#WqqVEdNA6*PK-OD@EMacvP_87_ zVgb^AnWJIhH^m)34L3l|vnWA=aW3YGiwZ{+zG5nLpSqOV9X*oxiIBVroGg zFI)sJ1e(wg20=4qLY7D~3}vr6b{$2FmTGm1hVkmSg3i9V(GyWe^ZehO z5=XBt)qis&fJBhPT4c2}`AH^T9T}dc7PyMCHsuI6sVY*z z7)^jVkORXz*Bc#BocK7*Eqqmv;Km(kIJ(~yB%3OPlz+6!>Yf@DVFCQZHj|ZTSojs( z#o7|4vOE*^JQ{Kf+*OlcN&XUkUTOS)5Y-g0JHoSj0>dfhcx?e;uEKAG8qjcXjDr{u zs#lq5(O-u(cSE#<~Y zn|ZEIOLjAUSZvI;4v5_F1@7hG@@JNO0XG5v8bIwhg zmW-VBj0A3y=yG`gn!gnbUH^}pUI04eO>2Z2Zr-edA4g_j)h{g6Zh;{RPu$P909*3* z2k1h|npIV#MM7(yR44x5ndy)egxrYCUX_HwRuxnY}x*2sL z=1P4t%l7U;`lXH{_jp9++)4qkX|cI;`n5?!Z6DH_2LLvNhfVAO=N^xmKfx=SI(j47 z`QXELWdQ=@PnR_@`U!Rp+LJ^woeFLvPj6Zjg~sLS;6JC==0Ji*UmVq(qYZgvZIXHR zlwDWdN*;$w)0d+kSG+JCx#k$T)h_m_JYx)TF52;JdQ+{}0l2+3Jd76SC_-zGA~YcmWLwqABxOK&TrGLza1bYpsM`f`&k?eE6pAFy1__ zrfG%I?X>E<poA5m$T-HyhMvxeadOm zF+DihoLyCb7&317IyA6vLo<;7-&tx=r4+y;oQTTdbC(*~=T6n(aa$kqZq8)ooK7DP zo}FmgiLL$F48A<}5lVPgphwE&H5R%?^cJdwmb z*>L<=uZD2@ZM@rc*iTavj;!$nWm2UVvyt*0Kz}Hcc>}IV;oCP zlmRyD;czve?xl0!&n9Wv`2>NE@a4XaCd5|fAuPAF6uedz5OAP@A*bClSnWLf1DbpT zXfcr?^hmQ)i*yYt=Y_)|!FwMTTG@8nslu`xD&gzrDRFG?b)@3Q)gFyp)xwmK{3t1Z z4QWt=S{hYzdfZ_&wjixEA=Yu0H_OO2XKE8D6V9{u^|E+lFy|ukki2~%= zt8P}Uj7i2ZjnQFrXU}l9BAfGO*DO&w{KnDJ)Sxs%SEcf9QNTOIY?oGY0Z637Px!YF zvHkeb`r8N^w@ggwY$6aN%6o$V~ttZs-V$zH&1vz%t)e1n(%elXY=&fm5nJEC<}Nuw0P3!nbUpisNEv8;8QNc z_~N^Uz!pic;;~c7IAJgy;7ILb<_>|~6V@Ol96O8g>@cHuyvC7oCn~}6896+NK^!J& z962r&m10*Jz~J#t-0tT&F;S2a&8bpeyBMNncQqukj=V&w{;UbXo(FpuNqMo12k5r7 zg}NIA@c`;uY41sYz0O=$V*G)UQkuFthJ{!LM<6G&7+1d_W)G5EKo3l`JNinQqYhqN zR0rxnjvcxzxo7nvvO?RgIs7s^7k)hz^QcX<*|*}3WJp_SpIK(%WTvjWQc@GHM+Lrt7hfq4Fxl>Z@O17jCIz9$@`bc%uea z@+~*rUhM-v!CLOu&6?4366;2pwMpo$6;kB7kS8MR2+y|Y|)PS@z*Yl~Z&j2i0? z-8OZad!2Z~2F`f_EIv(y)|i-aJTuZk2vXZum0vw+gM$4@0bDn8T)4b1ghb;rGT%_9 z)S#E{4^-%LJxc%j4#fN2uiX5xu*3my&X{4QKR2L+efPPL6jsE)o_2^@D=DRGt`_fjpN> zwszq1(nG0ux0kQA-P0v+V$x)QrZwKMqomC$NMTjvVOZn8{=&N4S~(hgA&X7wMNVEJ z@0t&-OqpktD)9$wdnkWkG5k~RRdW075&d&@hgFNH>pqB`;`Vh07?ue|#-(gZb!|Q4 z{K8u`ug*WEj$+x0f%@Iu>Hs7h*5PB4c{&?Fy zF>gl!KqVhC8*+u;`R_R-s?s{@$-=k>W=})jlFqd2*}=aUPs4*KfDUkS_<|HRnVuY#vsqtsq0;R?}nTqMjf$j~{t)I6J~>A8`K=d>7JX)Dg#Il`2B?4X^N&qy z@=$#1{yj7Eb8rFKVns;<`6H>WCP;_AbVC0usrw^{f?=w-8t}QWdZi#!uZ;Gfdm(=0OH)yZnt#|Q3(Tp8RjlQCuW*o_BpuQy4qGU%Pvm8B?iRpwBsDp zxa&hy(zq)C*ol1Q5`oU$0E+zvhyb|^113l3ut));am0uK zu%_ys4_`7#(-~kTkLxU1zr}>NKi4U0x|T?N zwzYG5F|uc0n;jD+TgMTja|>A=cRPDdH+tmB|xkPEW2~2GDGBm(F*bSkb!31RR&hT;4^) zt++3AYAzlVdpl4owW~CNnwXKfd#T>Mmb~osRv>4B@(`POg62~U8gk3ku4^6xz*b#O zlnKnSxy*m8-Z*izyM^Giybkt5+gJ`KZtrfh|0Hp|3r#Qb%3}Chj_~yN z-Za}!!sAv()NBld8IyQ|KdwUM94CXx$g&iN(ol}ZVg_Ow`L+o6@U})ZRNm_*e#q4q zb6f$&MGDX@>+vo}RtS&viQ4D#tv8_c+U_;wG{*E_lrD+ubG0}&5-v|N*osxO4bS-5 zGdG4o=JP~6he;EIq;UYg(32nv(VD z+0lkCBL@dM9lpN@Gbf?CXZo4jUUB0e0z788n21Q+S~V!rUX7Me%b0pK4wWS9Y&a!=IEshYvGMz8W4U=nM9EHAA z93n97Ekpn)#Mg9O#$hL!7SB%ud)ZE8{q;tPV){$+bfUQeZK-9f8B2KjQ9Ull8v<6FLHF==tC)!EFs+5lXBK9AO0{nh@t1Umm`VAO<7<0>N-+Y(G2-A5}2Qs8x!6{$}cf&T-NCDUpU-{+iqIQGCsQ;G_O>O2>y4 zo-mes|7C|lF93JrwwRZJfE6-0#1`D9IobV?0X9gxp908aM-Y`bTG3lDbrcc3>Qnc4 zz3sChPh{ZCqrV*@ZnZr3&9frN_N|ZF9{+Xe#pbqCXyu(wc~75vi5d5Wi&&?_Nui|Z zwnL`ljEBqZ4}VbZM#qdn^6`1$N09q6#Bt2A95(&xdgvn3L(BbJJ2hyaog6gNP6+C0 z#{rGCqk|UP5kXNN@OSdpqk9me8pL~@muhBsq`-;(#_?_INo3~owRoq)H_YW$gXE5T zP;%%!^RCnN-9@2?z5C{h902`tW94DLDXHLk*=i~Xj4~y;TsBDqE}LlNCf)%bOcX7L zOD<+VS)^Ue+Qyy86aZevmV3{d03w19?z|Z*YggOAI|r?eOV67g(vMf?J-}0UM38ysPfxH=|D1>Z(1`9ufdB=CiUS4p0&)i= z>CJlwBNq!>GspiuVPkf+v2N4U0W5Lhd?c%S654e#FAuX>kT}YZn8vZO z$PtUkH!%ZvEN3kne0|d+!J|zIjbXqee?&aGHmr&8Vh0 z_2~88<@8pZmRMbmoN$2k&FhveUiXf>(;%}T5vHp<5loDUUHCTUys2boHbM*av(){f znk}?Xwvg1zJ{t8TxS_|wKqd(bVg<<-wRF6eO|WiL!oYA|RJ8hZX^8sV>)NEsCJYur zb(yU~E}1#o&-t2inGqAP#EY=3uAK{?sNG(NY}ld|9oEF&+rb4Hq0c|qCO5Q}f7MTl z$@rlb3-oQ3e#<^qw6{rGV6i`zZdq^EQlRfR(Wq9(#Nb?FJ}NDj5<5K5U)byhs=Mh9 z3Tkh?&6ZMwLR<%8#UP+F=V?%>1yW895dAnF(`w;Szf`ZWLQB)LJ2`GR-$CQC#@P&F z-uxhnK8)z?8m53Df&ar0(J_v3L|bVsx)J*NZVjF@{!sN2k(dog=-Y?qyootT$~1`L ziXq%}A9{*1=*$TSHwjtyC0s3HE>o8jV`7!vmou7vP3VdmbFu=$i=5u5rKOLKfJRQ? z6-{DS;V+HhIzKmj#PX{_uNuP`PoX5;X{Ol}HQ($@-?CL;8%EmXQKk{BbmPs)R3p~R zUy9`W4238@t4nseTgpG2X<;}{^Z7{Djod;Exq^V4{2kLk8d`G#Uyr#c$Ij>Y1Zt+` z^$GaY_M|wkLcb!W}oVgasdszrl1eZKB96O`80)B!>TDJS(k7 zUp){KPul%{GMl<%!JBXOS;qiLa1(tPKOOxAN65KnDzpfFmt-nmiGL^)&ifBI82YK> z33Qb*iz3LzX7|cn)E@t@JY*NX;uTjTIOTpbN?q`ALqG@;2YZW0fh|Bf#N zW#jAiJSrj@LxQ@Li^7AJYFO&2BQI1^tjz*S%|c)d>hw!{ek~n%YpA2kkOX07Zrk)d zMU9nOJrf(w3kSqhE{$zgj#E$3rA&vVSg3rJ3wF`WY#J#Vt_-lot^ z1`=&S>2|(Lzl!iR;3a|g?&x)*#3Mqg|}b6Hsd)WPzx4|X(Kknyvf|$7?k$$ z_cceMo$F_mH*;)+<`AqA;=;;9ly_S+%ss-G+IGC11+Dtg&NLdrGSaxg$h+{688670 z6gmH}2uN7Wa(x>_O-_0K@Qp6$*h0z-)M`FjXXHT(Az1+NK^HQ)oK@WNA%a{Nxt1y^ zRR&%v&)AO>a%2OZOVQ3hu~@wxPZbKTG(~n`Fw|~|YG)k%;O%lqifvw|Y(BwA)ayd# zV1{5{w`pgBD#Jnp418`$+R6RWed0Odq{8#23D}Qa0Uuj}-W#;Q@IbGYZFZdG;mC+S zc}4jsk1wdeWU3IVI?WG21%U{fRYbjCJiaRaS`s^_;AM5f`ceo)e$Hp?@#Coa$PnbP zv=e8MPF3X}EKj|GnhLM_@bJ=R(EDjX=K=QL`ju$cR&6^-ezLci|JSd$0356w%}q^# zjx4_pzxtJU&865y2@H^e+M{qm(PlU6^)TM5jN8#?HR+)(xpgywKylM(91G{_^UF7R zlQLC!4X#ijF?SbxnH}$HU2kuz6iD@!H%+VG?S{;9g8GP?YKYh~mp;@XCcuy*LaPOuv z%e+)467-OcnY$gt$TAgdr=rkJ+qmR;WIKG>+l?#WJ7b&W_8s8tHk)78N8Mj*sHog} z^t!!(yOKa*r%b%;E(=VO7I&Y&kkD^%;Cb$$&+`@f`OV=*#!_p&3(*awoNqbV@RTLe; zaVIBnv<@|Yev7nngYV6zQP|XGG$^v}EaDrJ3YUq5a!K;LxJ%KE;ohJdZ|8NTXeZw$ z($*c;OClK7f?0nn8Yr1~O?3TlvDg{J6&dLd+mIlN%hknpzz1Jxo82by^WB)a>c*6D z^{|$=)WM`pg(Wo@Ve1HnlVQNQ+9N%pA5(+=5AM{xoMNk|Pz%R9ui@buC_m3_gtBZ$ zeI4c$=-Tx$JVKg?bJgra&j_xyx96lMRW}+9;o0lc`B>Tc(eDb7emb3p++%46wyc($ z)AG1}OcDfm-MO)SLoh*d21`kxHu}nl&_O(fa2-*GC9mJv_m#&Wuf6I=3KU^K{2T|{ zyN}&n1>gF~Ijv6CdYal<@~y=g7kkzzKEhyk0A9SJRWN7!)xeXl?`}9c_8OLMPTi(1 zW(nuJoSO?pvrLJ)s25o3lBfjJCTP>j_9eL7fyn$kjLIDd$U+jd(k0R0VCcPYHu0A) za=^?An~deSfhxKj(=rT8_tXv@2w~dNxIJk46Nz@^9-kcNc5WYW*fcM5x2Xbi=RfI-K711*jI$J~LTCA69X*vSo~cnJiAp79Db_tMoQb zL>h~yQq_9t-;P7E6Hw#gteGj5Ds670NLhdzzG$SwH#cwCZ7#oR89C5!rYx7Uq1LRI zIY5Y6jPnYQN)ao>+MSf5`g1>)yK>GKEFyIkIKmB8HWQ3B{y8_pyyb9sDb36QZ5h7_ z>P2m;`a124R9*uEzdls9MU1-l6e;;hJ??D*lV5YFZ-U0-YY;JgJD#&xlq#qcZ}1bK zWyoeP=H1%)qDnq{QL_nN+Q@*+l4>|PV!%frlA#lBZrElpGk~T-L*-UqwL=}EnRFg= zYtx!yNKFyvMK;Zr(BY_y(>#0&g2x-Pl(K+J%@@HiV(z5NBV-Nx52j4iEVH96KKQbLiAeBM@M;AhJ7EWHOwaZUChXF9W%^d#aiHIUkl>s7im zCdyzo9l{l-CQlQV395V~Plsh6bG*R2Bop{nJ^jKqem$=uf4e$7VM=7ZqV41J$wG~$YrWPe3im9y)DO9yYIw_nuttWZ zH6GWJ>fd(6;|`bcuChPpM$FjjM+kaq1+2;lB$7Isd$jhBoUqEoum;-4K7;p7lws){L<&H$s9@%7+%`wT^T4sh{=U9TjF+zxtkr$2NF%3p#yy-5P29 z0zTVN#Z2-?0-ID#6(sk|$%<(`AlB(tu`7Ne^KN$Sh^OcJIcw1P{S&`BMDhO@?Oz@@ zj~fY+kV*!U#S$_A_^JJym>W4jTIgSgUoG^ZmK9)$2k)Vy>+x9xrlG*>%f6y;UcVU| z1eChuY>S=hZ!c1+>tm=yV|9u;KR%b{C+6PIU+Ba6Y6C-wRUo_4-yD>rG48bpINS9r z-~Yt8jm=9HH-Kl+JQ6zVdG@&6$Ic(J{{=@jE-4^G;n&jyM}KE{cKaD`{NqQqH%@-~ zS}v3C**0_ICZn#1aPE!~w8`(S-XRqB}JFWX@PK^DG{Rd&W(Mk();hTAqrqPkq z+D0hF=8y{IX^w`)ZPSf-t2UlZJ2da%G>R+ zxXlFhZEC<0Uh%EwMxndqoWr{j5g%_(gW@!3hM=c95n}?N^WNmx)Y7_$AAks{SGX|M zpQogZ38cqZh#0lRJ*{rEJ4ppGJ-l7}a^N$pUX3T?))j>(<4GWho;-%OBIlBJfF*W} z$S_*U0Z_>u6R5YK@U0**?7tPo9vnC61a>Tu7xa9ZnhZ^YrCqW4*xZcNE9Ay)eRi}+ z+>Saj?~}gjW5O%)ni%aC)O)4+VG0LlRB&1x2uWePtiB;8U|^^-J1VQvXm^3f2TMB8 z+Z}UnfJV!if!jK2Vt95YHZHH9`B~sADI>;VH`Y}?7vJOdl`x-W^CSghSB?c>YJg4n@i!~=12 zEQSh0!eB9TiOu9-6cfz=`a*09o;b0-^eHx^peJ(Z4tc3`40^F1ld7BK;6rg$5y~cp zm#gFy{=`nn`{Mo+tbxUp&@9M`b6@FOaE(-ud_Qx^n?N7nI;DL{R-CHrC75Ru5kcyS z-JLWoUJ_c=?142@Jbag}9Do>6F4B5)P|{_K*NZ0dnKx!%wq+6;h8Pn`r(oNkW$%k3UtoG#aKvGid-Ci4caPTs3%J`%*#$;Se!Tb zc^tyb-Jhz%c?M22vCBF33B<)1cQHRAn7iD{6^8m*`f$zo!QGW8RS?$b815AEc7LIL z$vVdOY=J2rq0+|@ZcB=n-%>Vf`8~afjACkEv03-DB{J9lwA&DxY5U&PksYV*H@iG`#bbHEq4vhaV`bgw1@;Y2i>PbHp1Xa z?t|iryHuH7&4|Zvtf3j2Oef5Rr?}eV6Xs8RI!~80y79IlinLK(Hn!XX0%JLN4%X16 z!p8Kut*A|2BXEjA*ycgqj~EAIRSG=cj7>Vea!e{>Y}9SK%Q-cdDc|!l*d9%hWGiO2 zs@S{V-|?QX=U3ft>k(u+A@lRnc`iI;Q3mj31fB4j~cm7yPl|3cOjq0-~f-TuXBHCyL-IGNb*P{M@ zfQ^8*4iK(YH~9;T&rnm|{-g2g;k^~H;)$1EEogouqcdvotZeNzqc(_ZyYWEb@ic-b zO~GU)FVu>T0R1ZVv&}qP#xi_c99`$UsL2_hm0)4Xc}Bes;bWW9lj>ZD0lbIhqx+n# z^f@S|o?rF#QA-bhhzljJ{+_-rBOX5fZe;R;(L82G^2Z{w6W*4yfZXwOGcsj6&Ch^? zFCHy#JJJOX4_XflYVVRL0FJFTWGuDr_b~T6HlP(-Uxr#6m!`+CX%kNepRAyn2j}{! z>z3W|{al*_+|dM^@20j}3Lq;_|EgJWt#wf?f4}Y08z!r{o7L)}&=!`M#t&NpzD?Cv zC=`TG<{CF+uC#8a_(#5o-^9p>CHF#$j5x1Dle2kU!UBm5f?L(Hmu$oMh*2VeeZfIR zPjH@BfPXa{#ucBK$v{Iv`9M-%|3`HI8W~%gI!2(X=Ath30awPr;whn6W8sCJr6gt!#tKL~TAfT!BQ{RM5PnydIz73^? zj?;NL%3Q#*)HlmSC1CfesRlvW9Ztb);Z_UlrWM9_`Abn9YEJ6w?Q<-S>sLBH-Elp< zqp*p#{hnLiCWrKuf{KRQZ)Sf)xl8!ZA~~@9$n1s9;&I z4pkm~R9WPw?gvv5dW&)h;>fDn*mAmG&%Hb`dRNPQ=ciWBmATo#^|CmQahqaZ5b}TnKvvmhm<^8(2pp(rjBJ+cZHayT7tockVNGF zZM1z@ohMwi#KQh?*N&*#0!uzMJfp|4fd7u-Y1OBGl9hRGgoUKkn|P znRrHy(T@acj0^F*yeOaGz!YQe-^x8mm!NJZX zMWonXspTM&z5&`{w|zjuxYg1Y5WO#0Rg`hlGL41F8=8Xo72^Zk=vW*ksg}HitMMCx zwUn**{;!4y5m^{%UMY$WhYOJ~v0Kh15pW(1ho|ytf0&t>bf_(QP&(>-`vX$y|CWhL zE22CQV#to?f`X#?OD1*>7PdfB2NhEw@RvRNk83t&V+-3u?NI<&496=iaY9)UMamNq z9TO{kk=8gC994l+|VeQxf>uPug$qMm+$TN6Y?l=0YUuIS5>;!u?qh9AwH; zt5|T!MHs^2F8Dli{VIDLBag^}ZDnu2dNshAtz9*5v6IHHzO^11=?ZU3%0?aD7$q%H zCu}J6M5vsv{th+$zR0qD_9M#iXouU?SRbJClR?^M)SQL{1J9FLm43LRWjMD!U5@H0 z(ayl)bf8f6H;xmJS}65t{k${y8@C1ogb^PKM(;e%k(^l`^OvZ@R;~&$HE;}7-h$rl zFH9}^p68UN$;krJLJ_~+B4MSi+`KlFMy&V8I8JJH|nq) zm>Lr&7fIaU>I7XXAI+**OKa#+RgvPXN5|b|M}epF$b_(EYW{lMYO+G^*EHX!yDdj*5yOcnP8ip3a_eVZ)>Wmh?R}45 zG{2&}2&T>iasblk-o7&-^eyJ!9EY2-+%Nv5y+2>=71nFLDo61Sv zNz^J`!p_MjKWiV*6It~*_jrKPqIZc%maJpYI(&UNCLE*FZs^9H?vlZT^TwN}pA?myx>@n^?bQA$sv!4q2^ZCH}v~r7!Juzuc<0K zyZ4%mE2nyin;5Umq{y2Sr_Ho?F=HBv6K$L>Sig%-c^^g7G-=W82*Wfi6fTfRX=&k{ z@;He+Z=@I1lX6c-iKd~##Ak7w?!e9sedm&Yk$mr#)USW|3aqucCjU-$ueyI7t{?SB zkX-TN>)ToJwB!8c9}83@9)R5f6w( z!V`GF@}*0?nriCjZr$3ZB|Z0;+NQpDRclGeJe&qxi%@{ zILHrbH3wtkuLIn1+L4nT;j8SVq1o*?i({Uz9b|HMTO;S6&y}9QdA4TOeDn>I4Cu}1 za$66@$K#u=$t}4XohwMR-FIFnL>nX0AUKzJK$31idw-yn%2y=KeCash3AC;OLwzP; zOU1}Z2`h)U2?|h^E&Z6DFT%*19yWUPm4Fd%m`v{_=TJLQu}DB5E(eb?B0nVb$Sen! z#;wed73d@C4c}iDfBH|!jEX!c-PCnMwqKieZ->d z_uLl|>&4Tq2@+qJ*GY2|Sf_HEA{}C>2)Ft}4$q2Nqb6zP^Tdu$gF*SKBlQDO`_||J z0T>F$7~^~6kyx=8*kRt_C+ybxer-(x6ChdM<)GQT31^~+0zb@!H2_sZDIM44WCb^# zf~-c|8SjL0Cjv{{?Wvb;3NdH5m3)+Z4M!ioeE_9ngbD`g!~`{A?H(2#bfHA&PLD4T z-6aJ_O5mg9#jYg~)jsW^B9mttI_kLp5)^OneT2-wdyAdC!k5}Hq^qo0r81m8&0may z9P{SeOV)ju;!lR*aj1FeZ^FOqg)rh6$T6N?`mbkVG$=_F#sv%IJcp#klpNQi{DxC) z7an8ptD#{Y7U`xjK``Qj;PHZ~mgZuxgVS@z73*51LYm@x6Q-v4aG}dpwX2KdT*oU* zSWotiE~ulY@5F-&QT_aRdygltEHX)>Bc;5^ADVZf3@O~aBaa`O^KLI9wy-`1Pjcau zvqc%C1m$j$kzK33y(USB8oT36eHU|O)JaSKo%As+_$p*$Po8ff=*^F;m?(j?9D{E^ zG*~)Ao}_p$Zo}*dmdvYsFarXgx|8v@U=oZ~Qv_2GC(_hXC}D1n7HAnt-Bjw;hZ~f+ z_5r$29e0;!S&R6cKR#Y=5zPyx_6&4BENPtlCihpUX@_xJQV(^xqwqtROaJF65sFNVkRwg$Vr~V4~;%u!ERj01l=< zdvo$!IB42zD9A1UZ*QK;dVn-m98gx>li_W~3lThAvEq0qkaoVb>HZA&e228=51)z* z%*O{*xI{}evZM1g$0&fk*JS7qXka}jQ7WUcOcx@9mE+fmtXUJFWXL&Ks^XIm+ELf! z{n>eu2uE`jqTmFVcL#!`Z=8LzIoHK5D2{#mGbV>iSQjfaSZ4+t^omrow=aaun`y&! zl*5&|dFK;%c;LNR7xG%j%8 z;nR@#XEO}E{JxvQj|J_Al#UL@@N3I8&;u_m-wX+}vw0*4t*#i~dcW^asFI0WCWvu? zbriX;R0iMb-OPf}9G2Q?ZnALnUl0;yK}(A~yZ!pr|80>0S*fHpwN^u9ERT%(?Ca5K z4uh5U3xbv1d-*RYAh|Oi6I!mYbrz*qwLxBmTF?3x`*hSHBedoqzrG4^t_=zKo-7=r zW@j!oSLO<%^)3FtRqWaUShze$t!0Op9x?u2v5oBP{(rsx{Vk`*bw^IKVg#N@wfUWb z4(db@)gm>D;g5W9ac%JJiPNP`%1tD%I4oV=)5R7F8EG6+Q@k$j&s`}_Sn5rg0?pfo zZyjRn1Lf~~npDQ3f>>P0-h{zbKpl{5xAhL3%r0>|;CuS{ph_e%>W;XH&wL69Zs{Rh zrx;|WD|pVSDAOx_Q^P^nsGns8q*T|s5?&3Mz|{nEvIKepbsH}_3j^l)4Lo^)axm&= zD$|;IK2uDyd6V6e23Yr=lja47LkhpSj=6yYdc7qyV zv2$aY%5`QoVZ*jv2$w=@4KS+v2i;J*z4QEM8zTlWmZ+5#1wCCOaVf;R}Xx=V_)(%`8K`0@T$h8 z(mRMCKktdxdgA~=x2R!9QFt_R43$AD11FBMlkl22YP1{RV@G&nqjb!GsF}~5dSN9j zkgxS@Db1SRj)t)?b6%vARAECfJF!eWvBQX=FcoLsM#Bs8mi}t7p<$RH!`%N}y+K;0 z00f3q?bv63Efw|qW&S+V5d}cT9kxINRX00RN4=kQT~YR*0QG9DuP!0CzJoOSDF2|| zg?udr4yM+QEX+Ume-g$%i$8>eJXsKO8{t0)XCQ+gi2eRA+Mm8wV*tSF=d=G6Cqjbz zQ5Awi4PoH!k_>=n*`u)m72$?3N=&$}p4h0o}_kTtIkE8l8Y5sOs|Eny;mo9UE z0=E7aU=5^UgmCnK5mkS|{pa!*bAJQ;y%L#>Z~*Pl1r*fJ-#_L14HBaT0sPy#WbDkA zcBW>3mGL*ipKF=@F6I&%^dAVnRyO-nNPn(R@*6-3?@xeVtCjo-@MmDzZ-5C%z5BaR z{w|I`QT_}g_>DrV^9$u)g9`pc`P0qy8)eM!7s`J*z5Yb_)7teL0mn&)pwC@5tIXsG|vL;ocI lXaD|pat5crk^iT+SCoZ^e6&C7GY*s}BrpWd71DS>{SSe56x09! literal 0 HcmV?d00001 diff --git a/e2e/suites/actions/context-menu-multiple-selection.test.ts b/e2e/suites/actions/context-menu-multiple-selection.test.ts index 7684136db..6e37b01e5 100755 --- a/e2e/suites/actions/context-menu-multiple-selection.test.ts +++ b/e2e/suites/actions/context-menu-multiple-selection.test.ts @@ -175,9 +175,10 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297627]', async () => { await dataTable.selectMultipleItems([fileLocked1, fileLocked2]); await dataTable.rightClickOnMultipleSelection(); @@ -190,6 +191,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when multiple folders are selected - [C280632]', async () => { @@ -206,6 +208,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when both files and folders are selected - [C280631]', async () => { @@ -222,6 +225,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); }); @@ -253,9 +257,10 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297628]', async () => { await dataTable.selectMultipleItems([ fileLocked1Site, fileLocked2Site ]); await dataTable.rightClickOnMultipleSelection(); @@ -269,6 +274,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when multiple folders are selected - [C280574]', async () => { @@ -285,6 +291,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when both files and folders are selected - [C280642]', async () => { @@ -301,6 +308,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); }); @@ -331,9 +339,10 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is not displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297629]', async () => { await dataTable.selectMultipleItems([ fileLocked1, fileLocked2 ]); await dataTable.rightClickOnMultipleSelection(); @@ -347,6 +356,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is not displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); }); @@ -377,9 +387,10 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297630]', async () => { await dataTable.selectMultipleItems([ fileLocked1, fileLocked2 ]); await dataTable.rightClickOnMultipleSelection(); @@ -393,6 +404,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); }); @@ -423,9 +435,10 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297631]', async () => { await dataTable.selectMultipleItems([ fileLocked1, fileLocked2 ]); await dataTable.rightClickOnMultipleSelection(); @@ -439,6 +452,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when multiple folders are selected - [C280664]', async () => { @@ -455,6 +469,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when both files and folders are selected - [C280657]', async () => { @@ -471,6 +486,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); }); @@ -503,6 +519,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when multiple folders are selected - [C286274]', async () => { @@ -521,6 +538,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when both files and folders are selected - [C286275]', async () => { @@ -539,6 +557,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); }); @@ -571,9 +590,10 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297632]', async () => { await searchInput.clickSearchButton(); await searchInput.checkOnlyFiles(); await searchInput.searchForTextAndCloseSearchOptions('my-inSite-file'); @@ -590,6 +610,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when multiple folders are selected - [C291832]', async () => { @@ -609,6 +630,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); it('correct actions appear when both files and folders are selected - [C291833]', async () => { @@ -628,6 +650,7 @@ describe('Context menu actions - multiple selection : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); }); }); }); diff --git a/e2e/suites/actions/context-menu-single-selection.test.ts b/e2e/suites/actions/context-menu-single-selection.test.ts index b20e5b0be..02e79d066 100755 --- a/e2e/suites/actions/context-menu-single-selection.test.ts +++ b/e2e/suites/actions/context-menu-single-selection.test.ts @@ -189,12 +189,13 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${fileUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileUser}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileUser}`); }); - it('Context menu has the correct actions for a locked file - []', async () => { + it('Context menu has the correct actions for a locked file - [C297633]', async () => { await dataTable.rightClickOnItem(fileLocked); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); @@ -207,6 +208,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLocked}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${fileLocked}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLocked}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`); @@ -224,6 +226,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${folderUser}`); expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folderUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folderUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderUser}`); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderUser}`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderUser}`); @@ -257,12 +260,13 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileSiteUser}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileSiteUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileSiteUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileSiteUser}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileSiteUser}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileSiteUser}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileSiteUser}`); }); - it('Context menu has the correct actions for a locked file - []', async () => { + it('Context menu has the correct actions for a locked file - [C297634]', async () => { await dataTable.rightClickOnItem(fileLockedInSite); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is not displayed for ${fileLockedInSite}`); @@ -275,6 +279,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLockedInSite}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLockedInSite}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileLockedInSite}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileLockedInSite}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLockedInSite}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLockedInSite}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLockedInSite}`); @@ -292,6 +297,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${folderSiteUser}`); expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folderSiteUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions displayed for ${folderSiteUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version displayed for ${folderSiteUser}`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderSiteUser}`); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderSiteUser}`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderSiteUser}`); @@ -413,12 +419,13 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`); expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed for ${fileUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileUser}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileUser}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileUser}`); }); - it('Context menu has the correct actions for a locked file - []', async () => { + it('Context menu has the correct actions for a locked file - [C297635]', async () => { await dataTable.rightClickOnItem(fileLocked); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); @@ -432,6 +439,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed for ${fileLocked}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileLocked}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileLocked}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLocked}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`); @@ -463,12 +471,13 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileUser}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileUser}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileUser}`); }); - it('Context menu has the correct actions for a locked file - []', async () => { + it('Context menu has the correct actions for a locked file - [C297636]', async () => { await dataTable.rightClickOnItem(fileLocked); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); @@ -481,6 +490,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLocked}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileLocked}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileLocked}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLocked}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`); @@ -513,11 +523,12 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${fileUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileUser}`); }); - it('Context menu has the correct actions for a locked file - []', async () => { + it('Context menu has the correct actions for a locked file - [C297637]', async () => { await dataTable.rightClickOnItem(fileLocked); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); @@ -531,6 +542,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLocked}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${fileLocked}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`); }); @@ -546,6 +558,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${folderUser}`); expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folderUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folderUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderUser}`); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderUser}`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderUser}`); @@ -577,6 +590,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileInTrash}`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${fileInTrash}`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${fileInTrash}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${fileInTrash}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileInTrash}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileInTrash}`); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileInTrash}`); @@ -596,6 +610,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${folderInTrash}`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderInTrash}`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folderInTrash}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderInTrash}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${folderInTrash}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${folderInTrash}`); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderInTrash}`); @@ -630,12 +645,13 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileSiteUser}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileSiteUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileSiteUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileSiteUser}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileSiteUser}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileSiteUser}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileSiteUser}`); }); - it('Context menu has the correct actions for a locked file - []', async () => { + it('Context menu has the correct actions for a locked file - [C297638]', async () => { await searchInput.clickSearchButton(); await searchInput.checkOnlyFiles(); await searchInput.searchForTextAndCloseSearchOptions(fileLocked); @@ -651,6 +667,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileLocked}`); expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLocked}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileLocked}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileLocked}`); expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLocked}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`); @@ -671,6 +688,7 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${folderSiteUser}`); expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folderSiteUser}`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions displayed for ${folderSiteUser}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version displayed for ${folderSiteUser}`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderSiteUser}`); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderSiteUser}`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderSiteUser}`); diff --git a/e2e/suites/actions/edit-offline.test.ts b/e2e/suites/actions/edit-offline.test.ts new file mode 100755 index 000000000..889d0f137 --- /dev/null +++ b/e2e/suites/actions/edit-offline.test.ts @@ -0,0 +1,270 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { LoginPage, BrowsingPage } from '../../pages/pages'; +import { FILES } from '../../configs'; +import { RepoClient } from '../../utilities/repo-client/repo-client'; +import { Utils } from '../../utilities/utils'; + +describe('Edit offline', () => { + const username = `user-${Utils.random()}`; + + const file1 = `file1-${Utils.random()}.docx`; let file1Id; + const fileLocked = `file-locked-${Utils.random()}.docx`; let fileLockedId; + const fileLocked2 = `file-locked2-${Utils.random()}.docx`; let fileLocked2Id; + + const parentPF = `parentPersonal-${Utils.random()}`; let parentPFId; + const parentSF = `parentShared-${Utils.random()}`; let parentSFId; + const parentRF = `parentRecent-${Utils.random()}`; let parentRFId; + const parentFav = `parentFav-${Utils.random()}`; let parentFavId; + + const apis = { + admin: new RepoClient(), + user: new RepoClient(username, username) + }; + + const loginPage = new LoginPage(); + const page = new BrowsingPage(); + const { dataTable, toolbar } = page; + + beforeAll(async (done) => { + await apis.admin.people.createUser({ username }); + + parentPFId = (await apis.user.nodes.createFolder(parentPF)).entry.id; + parentSFId = (await apis.user.nodes.createFolder(parentSF)).entry.id; + parentRFId = (await apis.user.nodes.createFolder(parentRF)).entry.id; + parentFavId = (await apis.user.nodes.createFolder(parentFav)).entry.id; + + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(parentPFId); + await apis.user.nodes.deleteNodeById(parentSFId); + await apis.user.nodes.deleteNodeById(parentRFId); + await apis.user.nodes.deleteNodeById(parentFavId); + done(); + }); + + describe('on Personal Files', () => { + beforeAll(async (done) => { + file1Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentPFId, file1)).entry.id; + fileLockedId = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentPFId, fileLocked)).entry.id; + fileLocked2Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentPFId, fileLocked2)).entry.id; + + await apis.user.nodes.lockFile(fileLockedId); + await apis.user.nodes.lockFile(fileLocked2Id); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parentPF); + done(); + }); + + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('File is locked and downloaded when clicking Edit Offline - [C297538]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(file1)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(file1Id)).toBe(true, `${file1} is not locked`); + }); + + it('Lock information is displayed - [C297539]', async () => { + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, `${fileLocked2} is not displayed`); + expect(await dataTable.hasLockIcon(fileLocked2)).toBe(true, `${fileLocked2} does not have a lock icon`); + expect(await dataTable.getLockOwner(fileLocked2)).toContain(username, `${fileLocked2} does not have correct lock owner info`); + }); + + it('Cancel Editing unlocks the file - [C297540]', async () => { + await dataTable.selectItem(fileLocked); + await toolbar.clickMoreActionsCancelEditing(); + await dataTable.clearSelection(); + + expect(await apis.user.nodes.isFileLockedWrite(fileLockedId)).toBe(false, `${fileLocked} is still locked`); + expect(await dataTable.hasLockIcon(fileLocked)).toBe(false, `${fileLocked} has a lock icon`); + }); + }); + + // TODO: enable tests when ACA-2173 is done + xdescribe('on Shared Files', () => { + beforeAll(async (done) => { + file1Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentSFId, file1)).entry.id; + fileLockedId = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentSFId, fileLocked)).entry.id; + fileLocked2Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentSFId, fileLocked2)).entry.id; + + await apis.user.nodes.lockFile(fileLockedId); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.shared.shareFilesByIds([file1Id, fileLockedId, fileLocked2Id]); + await apis.user.shared.waitForApi({ expect: 3 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickSharedFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); + + xit('File is locked and downloaded when clicking Edit Offline - []', async () => { + await dataTable.selectItem(file1, parentSF); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(file1)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(file1Id)).toBe(true, `${file1} is not locked`); + }); + + xit('Lock information is displayed - []', async () => { + expect(await dataTable.isItemPresent(fileLocked2, parentSF)).toBe(true, `${fileLocked2} is not displayed`); + expect(await dataTable.hasLockIcon(fileLocked2, parentSF)).toBe(true, `${fileLocked2} does not have a lock icon`); + expect(await dataTable.getLockOwner(fileLocked2, parentSF)).toContain(username, `${fileLocked2} does not have correct lock owner info`); + }); + + xit('Cancel Editing unlocks the file - []', async () => { + await dataTable.selectItem(fileLocked); + await toolbar.clickMoreActionsCancelEditing(); + await dataTable.clearSelection(); + + expect(await apis.user.nodes.isFileLockedWrite(fileLockedId)).toBe(false, `${fileLocked} is still locked`); + expect(await dataTable.hasLockIcon(fileLocked, parentSF)).toBe(false, `${fileLocked} has a lock icon`); + }); + }); + + describe('on Recent Files', () => { + beforeAll(async (done) => { + file1Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentRFId, file1)).entry.id; + fileLockedId = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentRFId, fileLocked)).entry.id; + fileLocked2Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentRFId, fileLocked2)).entry.id; + + await apis.user.nodes.lockFile(fileLockedId); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.search.waitForApi(username, { expect: 6 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickRecentFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('File is locked and downloaded when clicking Edit Offline - [C297541]', async () => { + await dataTable.selectItem(file1, parentRF); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(file1)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(file1Id)).toBe(true, `${file1} is not locked`); + }); + + it('Lock information is displayed - [C297542]', async () => { + expect(await dataTable.isItemPresent(fileLocked2, parentRF)).toBe(true, `${fileLocked2} is not displayed`); + expect(await dataTable.hasLockIcon(fileLocked2, parentRF)).toBe(true, `${fileLocked2} does not have a lock icon`); + expect(await dataTable.getLockOwner(fileLocked2, parentRF)).toContain(username, `${fileLocked2} does not have correct lock owner info`); + }); + + it('Cancel Editing unlocks the file - [C297543]', async () => { + await dataTable.selectItem(fileLocked, parentRF); + await toolbar.clickMoreActionsCancelEditing(); + await dataTable.clearSelection(); + + expect(await apis.user.nodes.isFileLockedWrite(fileLockedId)).toBe(false, `${fileLocked} is still locked`); + expect(await dataTable.hasLockIcon(fileLocked, parentRF)).toBe(false, `${fileLocked} has a lock icon`); + }); + }); + + // TODO: enable tests when ACA-2174 is done + xdescribe('on Favorite Files', () => { + beforeAll(async (done) => { + file1Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentFavId, file1)).entry.id; + fileLockedId = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentFavId, fileLocked)).entry.id; + fileLocked2Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentFavId, fileLocked2)).entry.id; + + await apis.user.nodes.lockFile(fileLockedId); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.favorites.addFavoritesByIds('file', [file1Id, fileLockedId, fileLocked2Id]); + await apis.user.favorites.waitForApi({ expect: 3 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickFavoritesAndWait(); + done(); + }); + + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); + + xit('File is locked and downloaded when clicking Edit Offline - []', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(file1)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(file1Id)).toBe(true, `${file1} is not locked`); + }); + + xit('Lock information is displayed - []', async () => { + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, `${fileLocked2} is not displayed`); + expect(await dataTable.hasLockIcon(fileLocked2)).toBe(true, `${fileLocked2} does not have a lock icon`); + expect(await dataTable.getLockOwner(fileLocked2)).toContain(username, `${fileLocked2} does not have correct lock owner info`); + }); + + xit('Cancel Editing unlocks the file - []', async () => { + await dataTable.selectItem(fileLocked); + await toolbar.clickMoreActionsCancelEditing(); + await dataTable.clearSelection(); + + expect(await apis.user.nodes.isFileLockedWrite(fileLockedId)).toBe(false, `${fileLocked} is still locked`); + expect(await dataTable.hasLockIcon(fileLocked)).toBe(false, `${fileLocked} has a lock icon`); + }); + }); + +}); diff --git a/e2e/suites/actions/special-permissions-available-actions.test.ts b/e2e/suites/actions/special-permissions-available-actions.test.ts index 0f4826bde..e0f7b3c79 100755 --- a/e2e/suites/actions/special-permissions-available-actions.test.ts +++ b/e2e/suites/actions/special-permissions-available-actions.test.ts @@ -29,7 +29,7 @@ import { RepoClient } from '../../utilities/repo-client/repo-client'; import { Utils } from '../../utilities/utils'; import { Viewer } from '../../components/viewer/viewer'; -describe('Granular permissions available actions : ', () => { +describe('Special permissions available actions : ', () => { const userConsumer = `consumer-${Utils.random()}`; const userManager = `manager-${Utils.random()}`; const userCollaborator = `collaborator-${Utils.random()}`; @@ -112,6 +112,8 @@ describe('Granular permissions available actions : ', () => { await apis.userCollaborator.favorites.addFavoritesByIds('file', [file1Id, docxFileId]); await apis.userCollaborator.favorites.waitForApi({ expect: 2 }); + await apis.admin.favorites.addFavoriteById('file', fileLockedId); + done(); }); @@ -159,6 +161,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for selected files`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for selected files`); await toolbar.closeMoreMenu(); }); @@ -181,6 +184,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for selected files`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for selected files`); await toolbar.closeMoreMenu(); }); @@ -205,6 +209,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for selected files`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for selected files`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for selected files`); await toolbar.closeMoreMenu(); }); @@ -229,6 +234,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for selected files`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for selected files`); await toolbar.closeMoreMenu(); }); @@ -268,6 +274,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${file1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${file1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${file1}`); await toolbar.closeMoreMenu(); }); @@ -291,6 +298,8 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${file1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${file1}`); + // TODO: change expect to false when ACA-2173 is done + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is displayed for ${file1}`); await toolbar.closeMoreMenu(); }); @@ -317,6 +326,8 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for ${file1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${file1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is displayed for ${file1}`); await toolbar.closeMoreMenu(); }); @@ -342,6 +353,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${file1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${file1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${file1}`); await toolbar.closeMoreMenu(); }); @@ -381,6 +393,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${folder1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${folder1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folder1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); await toolbar.closeMoreMenu(); }); @@ -407,6 +420,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for ${folder1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${folder1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folder1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); await toolbar.closeMoreMenu(); }); @@ -432,6 +446,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${folder1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${folder1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folder1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); await toolbar.closeMoreMenu(); }); @@ -470,6 +485,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -492,6 +508,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -516,6 +533,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for selected files`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -540,6 +558,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -578,6 +597,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -602,6 +622,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -626,6 +647,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -664,6 +686,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -688,6 +711,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -712,6 +736,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -745,6 +770,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${file1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${file1}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${file1}`); expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); @@ -764,6 +790,8 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed for ${file1}`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${file1}`); + // TODO: change expect to false when ACA-2173 is done + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is displayed for ${file1}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${file1}`); }); @@ -785,6 +813,8 @@ describe('Granular permissions available actions : ', () => { // TODO: replace with isSharedLinkSettingsPresent when ACA-2175 is done expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is displayed for ${file1}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${file1}`); }); @@ -805,6 +835,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${file1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${file1}`); expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${file1}`); }); @@ -837,6 +868,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${folder1}`); expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folder1}`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folder1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folder1}`); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folder1}`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folder1}`); @@ -857,6 +889,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is displayed for ${folder1}`); expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folder1}`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folder1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folder1}`); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folder1}`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folder1}`); @@ -876,6 +909,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${folder1}`); expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folder1}`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folder1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folder1}`); expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folder1}`); expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folder1}`); @@ -911,6 +945,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); @@ -928,6 +963,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); @@ -947,6 +983,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); @@ -966,6 +1003,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); }); @@ -1000,6 +1038,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); @@ -1020,6 +1059,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); @@ -1040,6 +1080,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); }); @@ -1073,6 +1114,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); @@ -1092,6 +1134,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(true, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); @@ -1111,6 +1154,7 @@ describe('Granular permissions available actions : ', () => { expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); }); }); @@ -1152,6 +1196,7 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -1178,6 +1223,7 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -1204,6 +1250,7 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -1216,7 +1263,7 @@ describe('Granular permissions available actions : ', () => { done(); }); - it('on File Libraries - []', async () => { + it('on File Libraries - [C297647]', async () => { await page.clickFileLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); @@ -1237,11 +1284,12 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${file1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); - it('on Shared Files - []', async () => { + it('on Shared Files - [C297651]', async () => { await page.clickSharedFilesAndWait(); await page.dataTable.selectItem(file1); @@ -1261,11 +1309,12 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${file1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); - it('on Favorites - []', async () => { + it('on Favorites - [C297652]', async () => { await page.clickFavoritesAndWait(); await dataTable.selectItem(file1); @@ -1288,11 +1337,12 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for ${file1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${file1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); - it('on Search Results - []', async () => { + it('on Search Results - [C297653]', async () => { await searchInput.clickSearchButton(); await searchInput.checkOnlyFiles(); await searchInput.searchForTextAndCloseSearchOptions(file1); @@ -1313,6 +1363,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${file1}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); @@ -1330,7 +1381,7 @@ describe('Granular permissions available actions : ', () => { done(); }); - it('file opened from File Libraries - []', async () => { + it('file opened from File Libraries - [C297654]', async () => { await page.clickFileLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); @@ -1354,11 +1405,12 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await viewerToolbar.closeMoreMenu(); }); - it('file opened from Shared Files - []', async () => { + it('file opened from Shared Files - [C297655]', async () => { await page.clickSharedFilesAndWait(); await dataTable.doubleClickOnRowByName(docxFile); await viewer.waitForViewerToOpen(); @@ -1380,11 +1432,12 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await viewerToolbar.closeMoreMenu(); }); - it('file opened from Favorites - []', async () => { + it('file opened from Favorites - [C297656]', async () => { await page.clickFavoritesAndWait(); await dataTable.doubleClickOnRowByName(docxFile); await viewer.waitForViewerToOpen(); @@ -1406,6 +1459,7 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await viewerToolbar.closeMoreMenu(); }); @@ -1418,7 +1472,7 @@ describe('Granular permissions available actions : ', () => { done(); }); - it('on File Libraries - []', async () => { + it('on File Libraries - [C297657]', async () => { await page.clickFileLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); @@ -1439,11 +1493,12 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is not displayed'); await toolbar.closeMoreMenu(); }); - it('on Shared Files - []', async () => { + it('on Shared Files - [C297658]', async () => { await page.clickSharedFilesAndWait(); await page.dataTable.selectItem(fileLocked); @@ -1463,11 +1518,12 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is not displayed'); await toolbar.closeMoreMenu(); }); - it('on Favorites - []', async () => { + it('on Favorites - [C297659]', async () => { await page.clickFavoritesAndWait(); await dataTable.selectItem(fileLocked); @@ -1490,11 +1546,12 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for ${fileLocked}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is not displayed'); await toolbar.closeMoreMenu(); }); - it('on Search Results - []', async () => { + it('on Search Results - [C297660]', async () => { await searchInput.clickSearchButton(); await searchInput.checkOnlyFiles(); await searchInput.searchForTextAndCloseSearchOptions(fileLocked); @@ -1515,6 +1572,7 @@ describe('Granular permissions available actions : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is not displayed'); await toolbar.closeMoreMenu(); }); @@ -1532,7 +1590,7 @@ describe('Granular permissions available actions : ', () => { done(); }); - it('file opened from File Libraries - []', async () => { + it('file opened from File Libraries - [C297661]', async () => { await page.clickFileLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); @@ -1556,11 +1614,12 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await viewerToolbar.closeMoreMenu(); }); - it('file opened from Shared Files - []', async () => { + it('file opened from Shared Files - [C297662]', async () => { await page.clickSharedFilesAndWait(); await dataTable.doubleClickOnRowByName(fileLocked); await viewer.waitForViewerToOpen(); @@ -1582,11 +1641,12 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await viewerToolbar.closeMoreMenu(); }); - it('file opened from Favorites - []', async () => { + it('file opened from Favorites - [C297663]', async () => { await page.clickFavoritesAndWait(); await dataTable.doubleClickOnRowByName(fileLocked); await viewer.waitForViewerToOpen(); @@ -1609,6 +1669,217 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await viewerToolbar.closeMoreMenu(); + }); + }); + }); + + describe('File locked - manager : ', () => { + beforeAll(async (done) => { + await loginPage.loginWithAdmin(); + done(); + }); + + it('on File Libraries - [C297664]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, 'Upload new version is displayed'); + + await toolbar.closeMoreMenu(); + }); + + it('on Shared Files - [C297665]', async () => { + await page.clickSharedFilesAndWait(); + await page.dataTable.selectItem(fileLocked); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + // TODO: change expect to true when ACA-2173 is done + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + // TODO: change expect to false when ACA-2173 is done + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is displayed'); + + await toolbar.closeMoreMenu(); + }); + + it('on Favorites - [C297666]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + // TODO: replace with isSharedLinkSettingsPresent when ACA-2175 is done + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + // TODO: change expect to true when ACA-2174 is fixed + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is displayed'); + + await toolbar.closeMoreMenu(); + }); + + it('on Search Results - [C297667]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions(fileLocked); + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileLocked} in Search Results`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked} in Search Results`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, 'Upload new version is displayed'); + + await toolbar.closeMoreMenu(); + }); + + describe('in the viewer', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('file opened from File Libraries - [C297671]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.doubleClickOnRowByName(fileLocked); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await viewerToolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await viewerToolbar.closeMoreMenu(); + }); + + it('file opened from Shared Files - [C297672]', async () => { + await page.clickSharedFilesAndWait(); + await dataTable.doubleClickOnRowByName(fileLocked); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await viewerToolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await viewerToolbar.closeMoreMenu(); + }); + + it('file opened from Favorites - [C297673]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.doubleClickOnRowByName(fileLocked); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await viewerToolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await viewerToolbar.closeMoreMenu(); }); diff --git a/e2e/suites/actions/toolbar-multiple-selection.test.ts b/e2e/suites/actions/toolbar-multiple-selection.test.ts index 28120420d..31c2f4ba4 100755 --- a/e2e/suites/actions/toolbar-multiple-selection.test.ts +++ b/e2e/suites/actions/toolbar-multiple-selection.test.ts @@ -181,11 +181,12 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297619]', async () => { await dataTable.selectMultipleItems([fileLocked1, fileLocked2]); expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); @@ -201,6 +202,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -221,6 +223,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -241,6 +244,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -276,11 +280,12 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297620]', async () => { await dataTable.selectMultipleItems([fileLocked1InSite, fileLocked2InSite]); expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed for selected files'); @@ -296,6 +301,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -316,6 +322,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -336,6 +343,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -370,11 +378,12 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297623]', async () => { await dataTable.selectMultipleItems([fileLocked1, fileLocked2]); expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); @@ -390,6 +399,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -424,11 +434,12 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297624]', async () => { await dataTable.selectMultipleItems([fileLocked1, fileLocked2]); expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); @@ -444,6 +455,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -478,11 +490,12 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297625]', async () => { await dataTable.selectMultipleItems([fileLocked1, fileLocked2]); expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); @@ -498,6 +511,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -518,6 +532,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -538,6 +553,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -607,11 +623,12 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when multiple locked files are selected - []', async () => { + it('correct actions appear when multiple locked files are selected - [C297626]', async () => { await searchInput.clickSearchButton(); await searchInput.checkOnlyFiles(); await searchInput.searchForTextAndCloseSearchOptions('my-fileLockedInSite'); @@ -630,6 +647,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -653,6 +671,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); @@ -676,6 +695,7 @@ describe('Toolbar actions - multiple selection : ', () => { expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); await toolbar.closeMoreMenu(); }); diff --git a/e2e/suites/actions/toolbar-single-selection.test.ts b/e2e/suites/actions/toolbar-single-selection.test.ts index 565339c04..d2b930f44 100755 --- a/e2e/suites/actions/toolbar-single-selection.test.ts +++ b/e2e/suites/actions/toolbar-single-selection.test.ts @@ -151,11 +151,12 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileUser}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload New Version is not displayed for ${fileUser}`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when a locked file is selected - []', async () => { + it('correct actions appear when a locked file is selected - [C297612]', async () => { await dataTable.selectItem(fileLocked); expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLocked}`); @@ -172,6 +173,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); await toolbar.closeMoreMenu(); }); @@ -193,6 +195,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${folderUser}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${folderUser}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folderUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`); await toolbar.closeMoreMenu(); }); @@ -233,11 +236,12 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileInSite}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileInSite}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileInSite}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileInSite}`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when a locked file is selected - []', async () => { + it('correct actions appear when a locked file is selected - [C297614]', async () => { await dataTable.selectItem(fileLockedInSite); expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLockedInSite}`); @@ -254,6 +258,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLockedInSite}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLockedInSite}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLockedInSite}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLockedInSite}`); await toolbar.closeMoreMenu(); }); @@ -275,6 +280,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${folderInSite}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${folderInSite}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folderInSite}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderInSite}`); await toolbar.closeMoreMenu(); }); @@ -446,11 +452,12 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileUser}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when a locked file is selected - []', async () => { + it('correct actions appear when a locked file is selected - [C297615]', async () => { await page.dataTable.selectItem(fileLocked); expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLocked}`); @@ -469,6 +476,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); await toolbar.closeMoreMenu(); }); @@ -507,11 +515,12 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileUser}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when a locked file is selected - []', async () => { + it('correct actions appear when a locked file is selected - [C297616]', async () => { await dataTable.selectItem(fileLocked); expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLocked}`); @@ -528,6 +537,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); await toolbar.closeMoreMenu(); }); @@ -567,11 +577,12 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileUser}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when a locked file is selected - []', async () => { + it('correct actions appear when a locked file is selected - [C297617]', async () => { await dataTable.selectItem(fileLocked); expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLocked}`); @@ -589,6 +600,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); await toolbar.closeMoreMenu(); }); @@ -610,6 +622,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${folderUser}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${folderUser}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folderUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`); await toolbar.closeMoreMenu(); }); @@ -688,11 +701,12 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileUser}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileUser}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); await toolbar.closeMoreMenu(); }); - it('correct actions appear when a locked file is selected - []', async () => { + it('correct actions appear when a locked file is selected - [C297618]', async () => { await searchInput.clickSearchButton(); await searchInput.checkOnlyFiles(); await searchInput.searchForTextAndCloseSearchOptions(fileLocked); @@ -712,6 +726,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLocked}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); await toolbar.closeMoreMenu(); }); @@ -736,6 +751,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${folderUser}`); expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${folderUser}`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folderUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`); await toolbar.closeMoreMenu(); }); diff --git a/e2e/suites/actions/upload-new-version.test.ts b/e2e/suites/actions/upload-new-version.test.ts new file mode 100755 index 000000000..e36e3960e --- /dev/null +++ b/e2e/suites/actions/upload-new-version.test.ts @@ -0,0 +1,672 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { LoginPage, BrowsingPage } from '../../pages/pages'; +import { FILES } from '../../configs'; +import { RepoClient } from '../../utilities/repo-client/repo-client'; +import { Utils } from '../../utilities/utils'; +import { UploadNewVersionDialog } from '../../components/dialog/upload-new-version-dialog'; + +describe('Upload new version', () => { + const username = `user-${Utils.random()}`; + + const file1 = `file1-${Utils.random()}.docx`; let file1Id; + const file2 = `file2-${Utils.random()}.docx`; let file2Id; + const file3 = `file3-${Utils.random()}.docx`; let file3Id; + const file4 = `file4-${Utils.random()}.docx`; let file4Id; + const fileLocked1 = `file-locked1-${Utils.random()}.docx`; let fileLocked1Id; + const fileLocked2 = `file-locked2-${Utils.random()}.docx`; let fileLocked2Id; + + const parentPF = `parentPersonal-${Utils.random()}`; let parentPFId; + const parentSF = `parentShared-${Utils.random()}`; let parentSFId; + const parentRF = `parentRecent-${Utils.random()}`; let parentRFId; + const parentFav = `parentFav-${Utils.random()}`; let parentFavId; + + const file = FILES.pdfFile; let fileId; + const fileToUpload1 = FILES.docxFile; + const fileToUpload2 = FILES.xlsxFile; + const fileToUpload3 = FILES.pdfFile; + const fileToUpload4 = FILES.docxFile2; + const fileToUpload5 = FILES.xlsxFile2; + + const apis = { + admin: new RepoClient(), + user: new RepoClient(username, username) + }; + + const loginPage = new LoginPage(); + const page = new BrowsingPage(); + const { dataTable, toolbar } = page; + const uploadNewVersionDialog = new UploadNewVersionDialog(); + + beforeAll(async (done) => { + await apis.admin.people.createUser({ username }); + + parentPFId = (await apis.user.nodes.createFolder(parentPF)).entry.id; + parentSFId = (await apis.user.nodes.createFolder(parentSF)).entry.id; + parentRFId = (await apis.user.nodes.createFolder(parentRF)).entry.id; + parentFavId = (await apis.user.nodes.createFolder(parentFav)).entry.id; + + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(parentPFId); + await apis.user.nodes.deleteNodeById(parentSFId); + await apis.user.nodes.deleteNodeById(parentRFId); + await apis.user.nodes.deleteNodeById(parentFavId); + done(); + }); + + describe('on Personal Files', () => { + beforeAll(async (done) => { + fileId = (await apis.user.upload.uploadFile(file, parentPFId)).entry.id; + file1Id = (await apis.user.nodes.createFile(file1, parentPFId)).entry.id; + file2Id = (await apis.user.nodes.createFile(file2, parentPFId)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, parentPFId)).entry.id; + file4Id = (await apis.user.nodes.createFile(file4, parentPFId)).entry.id; + + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, parentPFId)).entry.id; + fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, parentPFId)).entry.id; + + await apis.user.nodes.lockFile(fileLocked1Id); + await apis.user.nodes.lockFile(fileLocked2Id); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parentPF); + done(); + }); + + afterEach(async (done) => { + // await Utils.pressEscape(); + await page.refresh(); + done(); + }); + + it('dialog UI defaults - [C297544]', async () => { + await dataTable.selectItem(file); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version'); + expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?'); + expect(await uploadNewVersionDialog.isDescriptionDisplayed()).toBe(true, 'Description not displayed'); + expect(await uploadNewVersionDialog.isMinorOptionDisplayed()).toBe(true, 'Minor option not displayed'); + expect(await uploadNewVersionDialog.isMajorOptionDisplayed()).toBe(true, 'Major option not displayed'); + expect(await uploadNewVersionDialog.isCancelButtonEnabled()).toBe(true, 'Cancel button not enabled'); + expect(await uploadNewVersionDialog.isUploadButtonEnabled()).toBe(true, 'Update button not enabled'); + }); + + it('file is updated after uploading a new version - major - [C297545]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload1)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file1Id)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file1Id)).toEqual('1.0', 'File has incorrect version label'); + }); + + it('file is updated after uploading a new version - minor - [C297546]', async () => { + await dataTable.selectItem(file2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new minor version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload2)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file2Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file2Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file is not updated when clicking Cancel - [C297547]', async () => { + await dataTable.selectItem(file3); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload3); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(file3)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file3Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file3Id)).toEqual('', 'File has incorrect version label'); + }); + + it('upload new version fails when new file name already exists - [C297548]', async () => { + await dataTable.selectItem(file4); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(file); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + await page.refresh(); + + expect(await dataTable.isItemPresent(file4)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file4Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file4Id)).toEqual('', 'File has incorrect version label'); + }); + + it('file is unlocked after uploading a new version - [C297549]', async () => { + await dataTable.selectItem(fileLocked1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload4); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload4)).toBe(true, 'File name was not changed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked1Id)).toBe(false, `${fileLocked1} is still locked`); + expect(await apis.user.nodes.getFileVersionType(fileLocked1Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLocked1Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file remains locked after canceling of uploading a new version - [C297550]', async () => { + await dataTable.selectItem(fileLocked2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload5); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(fileToUpload5)).toBe(false, 'File was updated'); + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, 'File not displayed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked2Id)).toBe(true, `${fileLocked2} was unlocked`); + }); + }); + + describe('on Shared Files', () => { + beforeAll(async (done) => { + fileId = (await apis.user.upload.uploadFile(file, parentSFId)).entry.id; + file1Id = (await apis.user.nodes.createFile(file1, parentSFId)).entry.id; + file2Id = (await apis.user.nodes.createFile(file2, parentSFId)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, parentSFId)).entry.id; + file4Id = (await apis.user.nodes.createFile(file4, parentSFId)).entry.id; + + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, parentSFId)).entry.id; + fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, parentSFId)).entry.id; + + await apis.user.nodes.lockFile(fileLocked1Id); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.shared.shareFilesByIds([fileId, file1Id, file2Id, file3Id, file4Id, fileLocked1Id, fileLocked2Id]); + await apis.user.shared.waitForApi({ expect: 7 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickSharedFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + // await Utils.pressEscape(); + await page.refresh(); + done(); + }); + + it('dialog UI defaults - [C297551]', async () => { + await dataTable.selectItem(file); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version'); + expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?'); + expect(await uploadNewVersionDialog.isDescriptionDisplayed()).toBe(true, 'Description not displayed'); + expect(await uploadNewVersionDialog.isMinorOptionDisplayed()).toBe(true, 'Minor option not displayed'); + expect(await uploadNewVersionDialog.isMajorOptionDisplayed()).toBe(true, 'Major option not displayed'); + expect(await uploadNewVersionDialog.isCancelButtonEnabled()).toBe(true, 'Cancel button not enabled'); + expect(await uploadNewVersionDialog.isUploadButtonEnabled()).toBe(true, 'Update button not enabled'); + }); + + it('file is updated after uploading a new version - major - [C297552]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload1)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file1Id)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file1Id)).toEqual('1.0', 'File has incorrect version label'); + }); + + it('file is updated after uploading a new version - minor - [C297553]', async () => { + await dataTable.selectItem(file2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new minor version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload2)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file2Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file2Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file is not updated when clicking Cancel - [C297554]', async () => { + await dataTable.selectItem(file3); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload3); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(file3)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file3Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file3Id)).toEqual('', 'File has incorrect version label'); + }); + + it('upload new version fails when new file name already exists - [C297555]', async () => { + await dataTable.selectItem(file4); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(file); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + await page.refresh(); + + expect(await dataTable.isItemPresent(file4)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file4Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file4Id)).toEqual('', 'File has incorrect version label'); + }); + + it('file is unlocked after uploading a new version - [C297556]', async () => { + await dataTable.selectItem(fileLocked1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload4); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload4)).toBe(true, 'File name was not changed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked1Id)).toBe(false, `${fileLocked1} is still locked`); + expect(await apis.user.nodes.getFileVersionType(fileLocked1Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLocked1Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file remains locked after canceling of uploading a new version - [C297557]', async () => { + await dataTable.selectItem(fileLocked2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload5); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(fileToUpload5)).toBe(false, 'File was updated'); + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, 'File not displayed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked2Id)).toBe(true, `${fileLocked2} was unlocked`); + }); + }); + + describe('on Recent Files', () => { + beforeAll(async (done) => { + fileId = (await apis.user.upload.uploadFile(file, parentRFId)).entry.id; + file1Id = (await apis.user.nodes.createFile(file1, parentRFId)).entry.id; + file2Id = (await apis.user.nodes.createFile(file2, parentRFId)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, parentRFId)).entry.id; + file4Id = (await apis.user.nodes.createFile(file4, parentRFId)).entry.id; + + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, parentRFId)).entry.id; + fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, parentRFId)).entry.id; + + await apis.user.nodes.lockFile(fileLocked1Id); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.search.waitForApi(username, { expect: 21 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickRecentFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + // await Utils.pressEscape(); + await page.refresh(); + done(); + }); + + it('dialog UI defaults - [C297558]', async () => { + await dataTable.selectItem(file, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version'); + expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?'); + expect(await uploadNewVersionDialog.isDescriptionDisplayed()).toBe(true, 'Description not displayed'); + expect(await uploadNewVersionDialog.isMinorOptionDisplayed()).toBe(true, 'Minor option not displayed'); + expect(await uploadNewVersionDialog.isMajorOptionDisplayed()).toBe(true, 'Major option not displayed'); + expect(await uploadNewVersionDialog.isCancelButtonEnabled()).toBe(true, 'Cancel button not enabled'); + expect(await uploadNewVersionDialog.isUploadButtonEnabled()).toBe(true, 'Update button not enabled'); + }); + + it('file is updated after uploading a new version - major - [C297559]', async () => { + await dataTable.selectItem(file1, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload1, parentRF)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file1Id)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file1Id)).toEqual('1.0', 'File has incorrect version label'); + }); + + it('file is updated after uploading a new version - minor - [C297560]', async () => { + await dataTable.selectItem(file2, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new minor version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload2, parentRF)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file2Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file2Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file is not updated when clicking Cancel - [C297561]', async () => { + await dataTable.selectItem(file3, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload3); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(file3, parentRF)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file3Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file3Id)).toEqual('', 'File has incorrect version label'); + }); + + it('upload new version fails when new file name already exists - [C297562]', async () => { + await dataTable.selectItem(file4, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(file); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + await page.refresh(); + + expect(await dataTable.isItemPresent(file4, parentRF)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file4Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file4Id)).toEqual('', 'File has incorrect version label'); + }); + + it('file is unlocked after uploading a new version - [C297563]', async () => { + await dataTable.selectItem(fileLocked1, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload4); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload4, parentRF)).toBe(true, 'File name was not changed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked1Id)).toBe(false, `${fileLocked1} is still locked`); + expect(await apis.user.nodes.getFileVersionType(fileLocked1Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLocked1Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file remains locked after canceling of uploading a new version - [C297564]', async () => { + await dataTable.selectItem(fileLocked2, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload5); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(fileToUpload5, parentRF)).toBe(false, 'File was updated'); + expect(await dataTable.isItemPresent(fileLocked2, parentRF)).toBe(true, 'File not displayed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked2Id)).toBe(true, `${fileLocked2} was unlocked`); + }); + }); + + describe('on Favorite Files', () => { + beforeAll(async (done) => { + fileId = (await apis.user.upload.uploadFile(file, parentFavId)).entry.id; + file1Id = (await apis.user.nodes.createFile(file1, parentFavId)).entry.id; + file2Id = (await apis.user.nodes.createFile(file2, parentFavId)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, parentFavId)).entry.id; + file4Id = (await apis.user.nodes.createFile(file4, parentFavId)).entry.id; + + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, parentFavId)).entry.id; + fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, parentFavId)).entry.id; + + await apis.user.nodes.lockFile(fileLocked1Id); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.favorites.addFavoritesByIds('file', [fileId, file1Id, file2Id, file3Id, file4Id, fileLocked1Id, fileLocked2Id]); + await apis.user.favorites.waitForApi({ expect: 7 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickFavoritesAndWait(); + done(); + }); + + afterEach(async (done) => { + // await Utils.pressEscape(); + await page.refresh(); + done(); + }); + + it('dialog UI defaults - [C297565]', async () => { + await dataTable.selectItem(file); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version'); + expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?'); + expect(await uploadNewVersionDialog.isDescriptionDisplayed()).toBe(true, 'Description not displayed'); + expect(await uploadNewVersionDialog.isMinorOptionDisplayed()).toBe(true, 'Minor option not displayed'); + expect(await uploadNewVersionDialog.isMajorOptionDisplayed()).toBe(true, 'Major option not displayed'); + expect(await uploadNewVersionDialog.isCancelButtonEnabled()).toBe(true, 'Cancel button not enabled'); + expect(await uploadNewVersionDialog.isUploadButtonEnabled()).toBe(true, 'Update button not enabled'); + }); + + it('file is updated after uploading a new version - major - [C297566]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload1)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file1Id)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file1Id)).toEqual('1.0', 'File has incorrect version label'); + }); + + it('file is updated after uploading a new version - minor - [C297567]', async () => { + await dataTable.selectItem(file2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new minor version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload2)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file2Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file2Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file is not updated when clicking Cancel - [C297568]', async () => { + await dataTable.selectItem(file3); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload3); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(file3)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file3Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file3Id)).toEqual('', 'File has incorrect version label'); + }); + + it('upload new version fails when new file name already exists - [C297569]', async () => { + await dataTable.selectItem(file4); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(file); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + await page.refresh(); + + expect(await dataTable.isItemPresent(file4)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file4Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file4Id)).toEqual('', 'File has incorrect version label'); + }); + + it('file is unlocked after uploading a new version - [C297570]', async () => { + await dataTable.selectItem(fileLocked1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload4); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload4)).toBe(true, 'File name was not changed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked1Id)).toBe(false, `${fileLocked1} is still locked`); + expect(await apis.user.nodes.getFileVersionType(fileLocked1Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLocked1Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file remains locked after canceling of uploading a new version - [C297571]', async () => { + await dataTable.selectItem(fileLocked2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload5); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(fileToUpload5)).toBe(false, 'File was updated'); + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, 'File not displayed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked2Id)).toBe(true, `${fileLocked2} was unlocked`); + }); + }); + +}); diff --git a/e2e/suites/list-views/tooltips.test.ts b/e2e/suites/list-views/tooltips.test.ts index 421e7a6f6..c9ae1105b 100755 --- a/e2e/suites/list-views/tooltips.test.ts +++ b/e2e/suites/list-views/tooltips.test.ts @@ -166,7 +166,7 @@ describe('File / folder tooltips', () => { }); // disabled until ACA-518 is done - describe('on Shared Files', () => { + xdescribe('on Shared Files', () => { beforeAll(async (done) => { await apis.user.shared.waitForApi({ expect: 8 }); await page.clickSharedFilesAndWait(); diff --git a/e2e/suites/viewer/viewer-actions.test.ts b/e2e/suites/viewer/viewer-actions.test.ts index 43145adb2..2355cabe0 100755 --- a/e2e/suites/viewer/viewer-actions.test.ts +++ b/e2e/suites/viewer/viewer-actions.test.ts @@ -31,11 +31,13 @@ import { Viewer } from '../../components/viewer/viewer'; import { CopyMoveDialog } from './../../components/dialog/copy-move-dialog'; import { ShareDialog } from './../../components/dialog/share-dialog'; import { ManageVersionsDialog } from './../../components/dialog/manage-versions-dialog'; +import { UploadNewVersionDialog } from './../../components/dialog/upload-new-version-dialog'; describe('Viewer actions', () => { const username = `user-${Utils.random()}`; const docxFile = FILES.docxFile; + const docxFile2 = FILES.docxFile2; const xlsxFileForMove = FILES.xlsxFile; const pdfFileForDelete = FILES.pdfFile; @@ -52,13 +54,14 @@ describe('Viewer actions', () => { const copyMoveDialog = new CopyMoveDialog(); const shareDialog = new ShareDialog(); const manageVersionsDialog = new ManageVersionsDialog(); + const uploadNewVersionDialog = new UploadNewVersionDialog(); beforeAll(async done => { await apis.admin.people.createUser({ username }); done(); }); - describe('file opened from Personal Files', () => { + describe('from Personal Files', () => { const parent = `parentPF-${Utils.random()}`; let parentId; const destination = `destPF-${Utils.random()}`; let destinationId; @@ -66,15 +69,28 @@ describe('Viewer actions', () => { const docxLockedPersonalFiles = `docxLockedPF-${Utils.random()}.docx`; let docxLockedId; const xlsxPersonalFiles = `xlsxPF-${Utils.random()}.xlsx`; const pdfPersonalFiles = `pdfPF-${Utils.random()}.pdf`; + const filePersonalFiles = docxFile2; let filePersonalFilesId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { parentId = (await apis.user.nodes.createFolder(parent)).entry.id; destinationId = (await apis.user.nodes.createFolder(destination)).entry.id; + docxFileId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxPersonalFiles)).entry.id; docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxLockedPersonalFiles)).entry.id; + filePersonalFilesId = (await apis.user.upload.uploadFile(docxFile2, parentId)).entry.id; await apis.user.upload.uploadFileWithRename(xlsxFileForMove, parentId, xlsxPersonalFiles); await apis.user.upload.uploadFileWithRename(pdfFileForDelete, parentId, pdfPersonalFiles); + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForUploadNewVersion)).entry.id; + + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); await apis.user.nodes.lockFile(docxLockedId); await loginPage.loginWith(username); @@ -121,11 +137,12 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); - it('Correct actions appear in the viewer toolbar for a locked file - []', async () => { + it('Correct actions appear in the viewer toolbar for a locked file - [C297583]', async () => { await dataTable.doubleClickOnRowByName(docxLockedPersonalFiles); await viewer.waitForViewerToOpen(); @@ -146,21 +163,23 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); it('Download action - [C268129]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await toolbar.clickDownload(); + expect(await Utils.fileExistsOnOS(docxPersonalFiles)).toBe(true, 'File not found in download location'); }); - it('Copy action - [C268130]', async (done) => { + it('Copy action - [C268130]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await toolbar.clickMoreActionsCopy(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); @@ -175,12 +194,11 @@ describe('Viewer actions', () => { expect(await dataTable.isItemPresent(docxPersonalFiles)).toBe(true, 'Item is not present in destination'); await apis.user.nodes.deleteNodeChildren(destinationId); - done(); }); it('Move action - [C268131]', async () => { await dataTable.doubleClickOnRowByName(xlsxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await toolbar.clickMoreActionsMove(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); @@ -197,7 +215,7 @@ describe('Viewer actions', () => { it('Favorite action - [C268132]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await toolbar.clickMoreActionsFavorite(); await viewer.clickClose(); @@ -208,7 +226,7 @@ describe('Viewer actions', () => { it('Delete action - [C268133]', async () => { await dataTable.doubleClickOnRowByName(pdfPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await toolbar.clickMoreActionsDelete(); expect(await page.getSnackBarMessage()).toContain(`${pdfPersonalFiles} deleted`); @@ -218,9 +236,46 @@ describe('Viewer actions', () => { expect(await dataTable.isItemPresent(pdfPersonalFiles)).toBe(true, 'Item is not present in Trash'); }); + it('Edit Offline action - [C297584]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297585]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297586]', async () => { + await dataTable.doubleClickOnRowByName(filePersonalFiles); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(filePersonalFilesId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(filePersonalFilesId)).toEqual('2.0', 'File has incorrect version label'); + }); + it('Full screen action - [C279282]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await Utils.getBrowserLog(); await toolbar.clickFullScreen(); @@ -232,7 +287,7 @@ describe('Viewer actions', () => { it('Share action - [C286313]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await toolbar.clickShare(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); @@ -241,7 +296,7 @@ describe('Viewer actions', () => { it('Manage Versions action - [C286316]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await toolbar.clickMoreActionsManageVersions(); expect(await manageVersionsDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); @@ -251,7 +306,7 @@ describe('Viewer actions', () => { // TODO: disabled until ACA-2176 is done xit('Pressing ESC in the viewer closes only the action dialog - [C286314]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await toolbar.clickShare(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); @@ -261,7 +316,7 @@ describe('Viewer actions', () => { }); }); - describe('file opened from File Libraries', () => { + describe('from File Libraries', () => { const siteName = `site-${Utils.random()}`; const destination = `destFL-${Utils.random()}`; let destinationId; @@ -269,6 +324,11 @@ describe('Viewer actions', () => { const docxLockedLibraries = `docxLockedFL-${Utils.random()}.docx`; let docxLockedId; const xlsxLibraries = `xlsxFL-${Utils.random()}.xlsx`; const pdfLibraries = `pdfFL-${Utils.random()}.pdf`; + const fileLibraries = docxFile2; let fileLibrariesId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { await apis.user.sites.createSite(siteName); @@ -276,10 +336,18 @@ describe('Viewer actions', () => { destinationId = (await apis.user.nodes.createFolder(destination)).entry.id; docxFileId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, docxLibraries)).entry.id; docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, docxLockedLibraries)).entry.id; + fileLibrariesId = (await apis.user.upload.uploadFile(docxFile2, docLibId)).entry.id; await apis.user.nodes.lockFile(docxLockedId); await apis.user.upload.uploadFileWithRename(xlsxFileForMove, docLibId, xlsxLibraries); await apis.user.upload.uploadFileWithRename(pdfFileForDelete, docLibId, pdfLibraries); + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, fileForUploadNewVersion)).entry.id; + + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); + await loginPage.loginWith(username); done(); }); @@ -303,7 +371,7 @@ describe('Viewer actions', () => { done(); }); - it('Correct actions appear in the viewer toolbar - []', async () => { + it('Correct actions appear in the viewer toolbar - [C297587]', async () => { await dataTable.doubleClickOnRowByName(docxLibraries); await viewer.waitForViewerToOpen(); @@ -324,11 +392,12 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); - it('Correct actions appear in the viewer toolbar for a locked file - []', async () => { + it('Correct actions appear in the viewer toolbar for a locked file - [C297588]', async () => { await dataTable.doubleClickOnRowByName(docxLockedLibraries); await viewer.waitForViewerToOpen(); @@ -349,6 +418,7 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); @@ -421,6 +491,43 @@ describe('Viewer actions', () => { expect(await dataTable.isItemPresent(pdfLibraries)).toBe(true, 'Item is not present in Trash'); }); + it('Edit Offline action - [C297589]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297590]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297591]', async () => { + await dataTable.doubleClickOnRowByName(fileLibraries); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(fileLibrariesId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLibrariesId)).toEqual('2.0', 'File has incorrect version label'); + }); + it('Share action - [C286374]', async () => { await dataTable.doubleClickOnRowByName(docxLibraries); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); @@ -440,7 +547,7 @@ describe('Viewer actions', () => { }); }); - describe('file opened from Recent Files', () => { + describe('from Recent Files', () => { const parent = `parentRF-${Utils.random()}`; let parentId; const destination = `destRF-${Utils.random()}`; let destinationId; @@ -448,6 +555,11 @@ describe('Viewer actions', () => { const docxLockedRecentFiles = `docxLockedRF-${Utils.random()}.docx`; let docxLockedId; const xlsxRecentFiles = `xlsxRF-${Utils.random()}.xlsx`; const pdfRecentFiles = `pdfRF-${Utils.random()}.pdf`; + const fileRecent = docxFile2; let fileRecentId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { await apis.user.search.waitForApi(username, {expect: 0}); @@ -455,11 +567,20 @@ describe('Viewer actions', () => { destinationId = (await apis.user.nodes.createFolder(destination)).entry.id; docxFileId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxRecentFiles)).entry.id; docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxLockedRecentFiles)).entry.id; + fileRecentId = (await apis.user.upload.uploadFile(docxFile2, parentId)).entry.id; + + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForUploadNewVersion)).entry.id; + + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); + await apis.user.nodes.lockFile(docxLockedId); await apis.user.upload.uploadFileWithRename(xlsxFileForMove, parentId, xlsxRecentFiles); await apis.user.upload.uploadFileWithRename(pdfFileForDelete, parentId, pdfRecentFiles); - await apis.user.search.waitForApi(username, {expect: 4}); + await apis.user.search.waitForApi(username, {expect: 8}); await loginPage.loginWith(username); done(); @@ -482,7 +603,7 @@ describe('Viewer actions', () => { done(); }); - it('Correct actions appear in the viewer toolbar - []', async () => { + it('Correct actions appear in the viewer toolbar - [C297592]', async () => { await dataTable.doubleClickOnRowByName(docxRecentFiles); await viewer.waitForViewerToOpen(); @@ -503,11 +624,12 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); - it('Correct actions appear in the viewer toolbar for a locked file - []', async () => { + it('Correct actions appear in the viewer toolbar for a locked file - [C297593]', async () => { await dataTable.doubleClickOnRowByName(docxLockedRecentFiles); await viewer.waitForViewerToOpen(); @@ -528,6 +650,7 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); @@ -601,6 +724,43 @@ describe('Viewer actions', () => { expect(await dataTable.isItemPresent(pdfRecentFiles)).toBe(true, 'Item is not present in Trash'); }); + it('Edit Offline action - [C297594]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297595]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297596]', async () => { + await dataTable.doubleClickOnRowByName(fileRecent); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(fileRecentId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileRecentId)).toEqual('2.0', 'File has incorrect version label'); + }); + it('Share action - [C286388]', async () => { await dataTable.doubleClickOnRowByName(docxRecentFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); @@ -620,7 +780,7 @@ describe('Viewer actions', () => { }); }); - describe('file opened from Shared Files', () => { + describe('from Shared Files', () => { const parent = `parentSF-${Utils.random()}`; let parentId; const destination = `destSF-${Utils.random()}`; let destinationId; @@ -628,6 +788,11 @@ describe('Viewer actions', () => { const docxLockedSharedFiles = `docxLockedSF-${Utils.random()}.docx`; let docxLockedId; const xlsxSharedFiles = `xlsxSF-${Utils.random()}.xlsx`; let xlsxFileId; const pdfSharedFiles = `pdfSF-${Utils.random()}.pdf`; let pdfFileId; + const fileShared = docxFile2; let fileSharedId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { parentId = (await apis.user.nodes.createFolder(parent)).entry.id; @@ -636,10 +801,18 @@ describe('Viewer actions', () => { docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxLockedSharedFiles)).entry.id; xlsxFileId = (await apis.user.upload.uploadFileWithRename(xlsxFileForMove, parentId, xlsxSharedFiles)).entry.id; pdfFileId = (await apis.user.upload.uploadFileWithRename(pdfFileForDelete, parentId, pdfSharedFiles)).entry.id; + fileSharedId = (await apis.user.upload.uploadFile(docxFile2, parentId)).entry.id; + + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForUploadNewVersion)).entry.id; + + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); await apis.user.nodes.lockFile(docxLockedId); - await apis.user.shared.shareFilesByIds([docxFileId, docxLockedId, xlsxFileId, pdfFileId]) - await apis.user.shared.waitForApi({expect: 4}); + await apis.user.shared.shareFilesByIds([docxFileId, docxLockedId, xlsxFileId, pdfFileId, fileForCancelEditingId, fileForEditOfflineId, fileForUploadNewVersionId, fileSharedId]) + await apis.user.shared.waitForApi({expect: 8}); await loginPage.loginWith(username); done(); @@ -662,7 +835,7 @@ describe('Viewer actions', () => { done(); }); - it('Correct actions appear in the viewer toolbar - []', async () => { + it('Correct actions appear in the viewer toolbar - [C297597]', async () => { await dataTable.doubleClickOnRowByName(docxSharedFiles); await viewer.waitForViewerToOpen(); @@ -683,11 +856,12 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); - it('Correct actions appear in the viewer toolbar for a locked file - []', async () => { + it('Correct actions appear in the viewer toolbar for a locked file - [C297598]', async () => { await dataTable.doubleClickOnRowByName(docxLockedSharedFiles); await viewer.waitForViewerToOpen(); @@ -708,6 +882,7 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); @@ -781,6 +956,43 @@ describe('Viewer actions', () => { expect(await dataTable.isItemPresent(pdfSharedFiles)).toBe(true, 'Item is not present in Trash'); }); + it('Edit Offline action - [C297601]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297602]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297603]', async () => { + await dataTable.doubleClickOnRowByName(fileShared); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(fileSharedId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileSharedId)).toEqual('2.0', 'File has incorrect version label'); + }); + it('Share action - [C286381]', async () => { await dataTable.doubleClickOnRowByName(docxSharedFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); @@ -800,7 +1012,7 @@ describe('Viewer actions', () => { }); }); - describe('file opened from Favorites', () => { + describe('from Favorites', () => { const parent = `parentFav-${Utils.random()}`; let parentId; const destination = `destFav-${Utils.random()}`; @@ -810,6 +1022,11 @@ describe('Viewer actions', () => { const docxLockedFavorites = `docxLockedFav-${Utils.random()}.docx`; let docxLockedId; const xlsxFavorites = `xlsxFav-${Utils.random()}.xlsx`; let xlsxFileId; const pdfFavorites = `pdfFav-${Utils.random()}.pdf`; let pdfFileId; + const fileFav = docxFile2; let fileFavId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { parentId = (await apis.user.nodes.createFolder(parent)).entry.id; @@ -818,10 +1035,18 @@ describe('Viewer actions', () => { docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxLockedFavorites)).entry.id; xlsxFileId = (await apis.user.upload.uploadFileWithRename(xlsxFileForMove, parentId, xlsxFavorites)).entry.id; pdfFileId = (await apis.user.upload.uploadFileWithRename(pdfFileForDelete, parentId, pdfFavorites)).entry.id; + fileFavId = (await apis.user.upload.uploadFile(docxFile2, parentId)).entry.id; + + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForUploadNewVersion)).entry.id; + + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); await apis.user.nodes.lockFile(docxLockedId); - await apis.user.favorites.addFavoritesByIds('file', [docxFileId, docxLockedId, xlsxFileId, pdfFileId]) - await apis.user.favorites.waitForApi({expect: 4}); + await apis.user.favorites.addFavoritesByIds('file', [docxFileId, docxLockedId, xlsxFileId, pdfFileId, fileForEditOfflineId, fileForCancelEditingId, fileForUploadNewVersionId, fileFavId]) + await apis.user.favorites.waitForApi({expect: 8}); await loginPage.loginWith(username); done(); @@ -844,7 +1069,7 @@ describe('Viewer actions', () => { done(); }); - it('Correct actions appear in the viewer toolbar - []', async () => { + it('Correct actions appear in the viewer toolbar - [C297599]', async () => { await dataTable.doubleClickOnRowByName(docxFavorites); await viewer.waitForViewerToOpen(); @@ -865,11 +1090,12 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); - it('Correct actions appear in the viewer toolbar for a locked file - []', async () => { + it('Correct actions appear in the viewer toolbar for a locked file - [C297600]', async () => { await dataTable.doubleClickOnRowByName(docxLockedFavorites); await viewer.waitForViewerToOpen(); @@ -890,6 +1116,7 @@ describe('Viewer actions', () => { expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); await toolbar.closeMoreMenu(); }); @@ -963,6 +1190,43 @@ describe('Viewer actions', () => { expect(await dataTable.isItemPresent(pdfFavorites)).toBe(true, 'Item is not present in Trash'); }); + it('Edit Offline action - [C297604]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297605]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297606]', async () => { + await dataTable.doubleClickOnRowByName(fileFav); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(fileFavId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileFavId)).toEqual('2.0', 'File has incorrect version label'); + }); + it('Share action - [C286395]', async () => { await dataTable.doubleClickOnRowByName(docxFavorites); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); diff --git a/e2e/utilities/repo-client/apis/nodes/nodes-api.ts b/e2e/utilities/repo-client/apis/nodes/nodes-api.ts index cc6bb1786..a42966463 100755 --- a/e2e/utilities/repo-client/apis/nodes/nodes-api.ts +++ b/e2e/utilities/repo-client/apis/nodes/nodes-api.ts @@ -58,6 +58,21 @@ export class NodesApi extends RepoApi { return ''; } + async getFileVersionType(nodeId: string) { + const prop = await this.getNodeProperty(nodeId, 'cm:versionType'); + if ( prop ) { + return prop; + } + return ''; + } + async getFileVersionLabel(nodeId: string) { + const prop = await this.getNodeProperty(nodeId, 'cm:versionLabel'); + if ( prop ) { + return prop; + } + return ''; + } + async getSharedId(nodeId: string) { return await this.getNodeProperty(nodeId, 'qshare:sharedId'); @@ -121,7 +136,7 @@ export class NodesApi extends RepoApi { return await this.createNode('cm:content', name, parentId, title, description, imageProps); } - async createNode(nodeType: string, name: string, parentId: string = '-my-', title: string = '', description: string = '', imageProps: any = null) { + async createNode(nodeType: string, name: string, parentId: string = '-my-', title: string = '', description: string = '', imageProps: any = null, majorVersion: boolean = true) { const nodeBody = { name, nodeType, @@ -135,11 +150,11 @@ export class NodesApi extends RepoApi { } await this.apiAuth(); - return await this.nodesApi.createNode(parentId, nodeBody); + return await this.nodesApi.createNode(parentId, nodeBody, { majorVersion: true }); } - async createFile(name: string, parentId: string = '-my-', title: string = '', description: string = '') { - return await this.createNode('cm:content', name, parentId, title, description); + async createFile(name: string, parentId: string = '-my-', title: string = '', description: string = '', majorVersion: boolean = true) { + return await this.createNode('cm:content', name, parentId, title, description, majorVersion); } async createImage(name: string, parentId: string = '-my-', title: string = '', description: string = '') { @@ -220,4 +235,17 @@ export class NodesApi extends RepoApi { await this.apiAuth(); return await this.nodesApi.unlockNode(nodeId); } + + async getLockType(nodeId: string) { + return await this.getNodeProperty(nodeId, 'cm:lockType'); + } + + async getLockOwner(nodeId: string) { + return await this.getNodeProperty(nodeId, 'cm:lockOwner'); + } + + async isFileLockedWrite(nodeId: string) { + await this.apiAuth(); + return (await this.getLockType(nodeId)) === 'WRITE_LOCK'; + } } diff --git a/e2e/utilities/utils.ts b/e2e/utilities/utils.ts index ec2c4c992..d77ed9196 100755 --- a/e2e/utilities/utils.ts +++ b/e2e/utilities/utils.ts @@ -23,11 +23,13 @@ * along with Alfresco. If not, see . */ -import { browser, protractor, promise, ElementFinder, ExpectedConditions as EC } from 'protractor'; +import { browser, protractor, promise, ElementFinder, ExpectedConditions as EC, by } from 'protractor'; import { BROWSER_WAIT_TIMEOUT, E2E_ROOT_PATH, EXTENSIBILITY_CONFIGS } from '../configs'; + const path = require('path'); const fs = require('fs'); + export class Utils { static string257 = 'assembly doctor offender limit clearance inspiration baker fraud active apples trait brainstorm concept breaks down presidential \ reluctance summary communication patience books opponent banana economist head develop project swear unanimous read conservation'; @@ -130,4 +132,10 @@ export class Utils { return new Date(date).toLocaleDateString('en-US'); } + + static async uploadFileNewVersion(fileFromOS: string) { + const el = browser.element(by.id('app-upload-file-version')); + await el.sendKeys(`${E2E_ROOT_PATH}/resources/test-files/${fileFromOS}`); + } + }