From c005c29039729eddb10471e8a32efc2f05932216 Mon Sep 17 00:00:00 2001 From: jkraehemann <none@none> Date: Tue, 4 Sep 2012 16:34:05 +0200 Subject: [PATCH] OO-296: final fix of collecting blog artefact --- .../portfolio/FunctionalArtefactTest.java | 34 +++- .../org/olat/util/FunctionalCourseUtil.java | 190 +++++++++++++++--- .../util/FunctionalRepositorySiteUtil.java | 34 +++- .../java/org/olat/util/FunctionalUtil.java | 86 +++++++- .../java/org/olat/util/FunctionalVOUtil.java | 12 ++ .../olat/portfolio/Course_including_Blog.zip | Bin 0 -> 20281 bytes .../resources/org/olat/portfolio/blog.zip | Bin 7664 -> 9561 bytes 7 files changed, 322 insertions(+), 34 deletions(-) create mode 100644 src/test/resources/org/olat/portfolio/Course_including_Blog.zip diff --git a/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java b/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java index e15b60ee8ec..fe4b826ddd1 100644 --- a/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java +++ b/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java @@ -40,6 +40,7 @@ import org.olat.restapi.support.vo.RepositoryEntryVO; import org.olat.test.ArquillianDeployments; import org.olat.user.restapi.UserVO; import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalCourseUtil.AccessOption; import org.olat.util.FunctionalEPortfolioUtil; import org.olat.util.FunctionalHomeSiteUtil; import org.olat.util.FunctionalRepositorySiteUtil; @@ -165,7 +166,7 @@ public class FunctionalArtefactTest { /* create binder, page or structure if necessary */ Assert.assertTrue(functionalEportfolioUtil.createElements(browser, FORUM_BINDER, FORUM_PAGE, FORUM_STRUCTURE)); - + //FIXME:JK: really ugly try { Thread.sleep(500); @@ -194,7 +195,7 @@ public class FunctionalArtefactTest { /* create binder, page or structure if necessary */ Assert.assertTrue(functionalEportfolioUtil.createElements(browser, WIKI_BINDER, WIKI_PAGE, WIKI_STRUCTURE)); - + //FIXME:JK: really ugly try { Thread.sleep(500); @@ -202,7 +203,7 @@ public class FunctionalArtefactTest { // TODO Auto-generated catch block e.printStackTrace(); } - + /* create an article for the wiki */ Assert.assertTrue(functionalCourseUtil.createWikiArticle(browser, vo.getKey(), WIKI_ARTICLE_PAGENAME, WIKI_ARTICLE_CONTENT)); @@ -215,18 +216,35 @@ public class FunctionalArtefactTest { @Test @RunAsClient public void checkCollectBlogPost() throws URISyntaxException, IOException{ - /* import blog via rest */ - long repoKey = functionalRepositorySiteUtil.createBlog(browser, BLOG_TITLE, BLOG_DESCRIPTION); + /* deploy course with REST */ + CourseVO course = functionalVOUtil.importCourseIncludingBlog(deploymentUrl); + +// long repoKey = functionalRepositorySiteUtil.createBlog(browser, BLOG_TITLE, BLOG_DESCRIPTION); + + /* */ +// Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); +// Assert.assertTrue(functionalCourseUtil.openBlog(browser, repoKey)); +// Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); +// Assert.assertTrue(functionalCourseUtil.disableAccessOption(browser, AccessOption.BLOCKED_FOR_LEARNERS, 1)); //TODO:JK: don't use hard coded form index + /* login for test setup */ Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); - /* create binder, page or structure if necessary */ Assert.assertTrue(functionalEportfolioUtil.createElements(browser, BLOG_BINDER, BLOG_PAGE, BLOG_STRUCTURE)); + //FIXME:JK: really ugly + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + /* blog */ - Assert.assertTrue(functionalCourseUtil.createBlogEntry(browser, repoKey, BLOG_POST_TITLE, BLOG_POST_DESCRIPTION, BLOG_POST_CONTENT)); + Assert.assertTrue(functionalCourseUtil.createBlogEntry(browser, course.getRepoEntryKey(), 0, + BLOG_POST_TITLE, BLOG_POST_DESCRIPTION, BLOG_POST_CONTENT)); /* add artefact */ Assert.assertTrue(functionalCourseUtil.addToEportfolio(browser, BLOG_BINDER, BLOG_PAGE, BLOG_STRUCTURE, @@ -270,5 +288,7 @@ public class FunctionalArtefactTest { Assert.assertTrue(functionalEportfolioUtil.createLearningJournal(browser, LEARNING_JOURNAL_BINDER, LEARNING_JOURNAL_PAGE, LEARNING_JOURNAL_STRUCTURE, LEARNING_JOURNAL_TITLE, LEARNING_JOURNAL_DESCRIPTION, LEARNING_JOURNAL_TAGS)); + + System.out.println(); } } diff --git a/src/test/java/org/olat/util/FunctionalCourseUtil.java b/src/test/java/org/olat/util/FunctionalCourseUtil.java index d2220f4c7d6..b3fde027458 100644 --- a/src/test/java/org/olat/util/FunctionalCourseUtil.java +++ b/src/test/java/org/olat/util/FunctionalCourseUtil.java @@ -34,6 +34,7 @@ public class FunctionalCourseUtil { public final static String EPORTFOLIO_ADD_CSS = "b_eportfolio_add"; public final static String FORUM_ICON_CSS = "o_fo_icon"; + public final static String BLOG_ICON_CSS = "o_blog_icon"; public final static String FORUM_TOOLBAR_CSS = "o_forum_toolbar"; public final static String FORUM_THREAD_NEW_CSS = "o_sel_forum_thread_new"; @@ -45,12 +46,73 @@ public class FunctionalCourseUtil { public final static String WIKI_EDIT_FORM_WRAPPER_CSS = "o_wikimod_editform_wrapper"; public final static String BLOG_CREATE_ENTRY_CSS = "o_sel_feed_item_new"; + public final static String BLOG_FORM_CSS = "o_sel_blog_form"; + + public enum CourseNodeTab { + TITLE_AND_DESCRIPTION, + VISIBILITY, + ACCESS, + CONTENT; + }; + + public enum VisibilityOption { + BLOCKED_FOR_LEARNERS, + DEPENDING_ON_DATE, + DEPENDING_ON_GROUP, + DEPENDING_ON_ASSESSMENT, + APPLY_TO_OWNERS_AND_TUTORS(DEPENDING_ON_ASSESSMENT); + + private VisibilityOption requires; + + VisibilityOption(){ + this(null); + } + + VisibilityOption(VisibilityOption requires){ + setRequires(requires); + } + + public VisibilityOption getRequires() { + return requires; + } + + public void setRequires(VisibilityOption requires) { + this.requires = requires; + } + }; + + public enum AccessOption { + BLOCKED_FOR_LEARNERS, + DEPENDING_ON_DATE, + DEPENDING_ON_GROUP, + DEPENDING_ON_ASSESSMENT, + APPLY_TO_OWNERS_AND_TUTORS(DEPENDING_ON_ASSESSMENT); + + private AccessOption requires; + + AccessOption(){ + this(null); + } + + AccessOption(AccessOption requires){ + setRequires(requires); + } + + public AccessOption getRequires() { + return requires; + } + + public void setRequires(AccessOption requires) { + this.requires = requires; + } + } private String courseRunCss; private String eportfolioAddCss; private String forumIconCss; + private String blogIconCss; private String forumToolbarCss; private String forumThreadNewCss; @@ -62,6 +124,7 @@ public class FunctionalCourseUtil { private String wikiEditFormWrapperCss; private String blogCreateEntryCss; + private String blogFormCss; private FunctionalUtil functionalUtil; private FunctionalRepositorySiteUtil functionalRepositorySiteUtil; @@ -75,6 +138,7 @@ public class FunctionalCourseUtil { setEportfolioAddCss(EPORTFOLIO_ADD_CSS); setForumIconCss(FORUM_ICON_CSS); + setBlogIconCss(BLOG_ICON_CSS); setForumToolbarCss(FORUM_TOOLBAR_CSS); setForumThreadNewCss(FORUM_THREAD_NEW_CSS); @@ -86,6 +150,7 @@ public class FunctionalCourseUtil { setWikiEditFormWrapperCss(WIKI_EDIT_FORM_WRAPPER_CSS); setBlogCreateEntryCss(BLOG_CREATE_ENTRY_CSS); + setBlogFormCss(BLOG_FORM_CSS); } /** @@ -135,6 +200,45 @@ public class FunctionalCourseUtil { return(true); } + /** + * @param browser + * @return true on success + * + * Opens the course editor but the course must be open. + */ + public boolean openCourseEditor(Selenium browser){ + //TODO:JK: implement me + return(false); + } + + /** + * @param browser + * @param option + * @param nthForm + * @return true on success + * + * Disables the specified access option, the course editor should be open. + */ + public boolean disableAccessOption(Selenium browser, AccessOption option, int nthForm){ + //TODO:JK: implement me + + return(false); + } + + /** + * @param browser + * @param option + * @param nthForm + * @return true on success + * + * Enables the specified access option, the course editor should be open. + */ + public boolean enableAccessOption(Selenium browser, AccessOption option, int nthForm){ + //TODO:JK: implement me + + return(false); + } + /** * @param browser * @return true on success @@ -173,8 +277,7 @@ public class FunctionalCourseUtil { /* click finish */ functionalUtil.clickWizardFinish(browser); - - functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToUnloadElement(browser, selector); } return(true); @@ -272,7 +375,7 @@ public class FunctionalCourseUtil { * Opens the wiki specified by id. */ public boolean openWiki(Selenium browser, long id){ - browser.open(functionalUtil.getDeploymentUrl() + "url/RepositoryEntry/" + id); + browser.open(functionalUtil.getDeploymentPath() + "/url/RepositoryEntry/" + id); functionalUtil.waitForPageToLoad(browser); return(true); @@ -356,7 +459,36 @@ public class FunctionalCourseUtil { * Opens the blog specified by id. */ public boolean openBlog(Selenium browser, long id){ - browser.open(functionalUtil.getDeploymentUrl() + "url/RepositoryEntry/" + id); + browser.open(functionalUtil.getDeploymentPath() + "/url/RepositoryEntry/" + id); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param courseId + * @param nth + * @return + * + * Opens the course with courseId and nth blog within the specified + * course. + */ + public boolean openBlogWithoutBusinessPath(Selenium browser, long courseId, int nth){ + if(!functionalRepositorySiteUtil.openCourse(browser, courseId)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//ul//li//a[contains(@class, '") + .append(getBlogIconCss()) + .append("')])[") + .append(nth + 1) + .append("]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); return(true); @@ -372,8 +504,9 @@ public class FunctionalCourseUtil { * * Create a new blog entry. */ - public boolean createBlogEntry(Selenium browser, long blogId, String title, String description, String content){ - if(!openBlog(browser, blogId)) + public boolean createBlogEntry(Selenium browser, long courseId, int nth, + String title, String description, String content){ + if(!openBlogWithoutBusinessPath(browser, courseId, nth)) return(false); StringBuffer selectorBuffer = new StringBuffer(); @@ -387,40 +520,31 @@ public class FunctionalCourseUtil { /* fill in form - title */ selectorBuffer = new StringBuffer(); - selectorBuffer.append("xpath=//form//div[contains(@class, '") - .append(functionalUtil.getWizardCss()) - .append("')]//input[@type='text' and position = 1]"); + selectorBuffer.append("xpath=(//form//div[contains(@class, '") + .append(getBlogFormCss()) + .append("')]//input[@type='text'])[1]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); browser.type(selectorBuffer.toString(), title); /* fill in form - description */ - selectorBuffer = new StringBuffer(); - - selectorBuffer.append("xpath=//form//div[contains(@class, '") - .append(functionalUtil.getWizardCss()) - .append("')]//textarea[0]"); - - browser.type(selectorBuffer.toString(), description); + functionalUtil.typeMCE(browser, getBlogFormCss(), description); /* fill in form - content */ - selectorBuffer = new StringBuffer(); - - selectorBuffer.append("xpath=//form//div[contains(@class, '") - .append(functionalUtil.getWizardCss()) - .append("')]//textarea[1]"); - - browser.type(selectorBuffer.toString(), content); + functionalUtil.typeMCE(browser, getBlogFormCss(), content); /* save form */ selectorBuffer = new StringBuffer(); selectorBuffer.append("xpath=//form//div[contains(@class, '") - .append(functionalUtil.getWizardCss()) + .append(getBlogFormCss()) .append("')]//button[last()]"); browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); - return(false); + return(true); } public FunctionalUtil getFunctionalUtil() { @@ -464,6 +588,14 @@ public class FunctionalCourseUtil { this.forumIconCss = forumIconCss; } + public String getBlogIconCss() { + return blogIconCss; + } + + public void setBlogIconCss(String blogIconCss) { + this.blogIconCss = blogIconCss; + } + public String getForumToolbarCss() { return forumToolbarCss; } @@ -527,5 +659,13 @@ public class FunctionalCourseUtil { public void setBlogCreateEntryCss(String blogCreateEntryCss) { this.blogCreateEntryCss = blogCreateEntryCss; } + + public String getBlogFormCss() { + return blogFormCss; + } + + public void setBlogFormCss(String blogFormCss) { + this.blogFormCss = blogFormCss; + } } diff --git a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java index 886204a4627..5d72b25dbf4 100644 --- a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java +++ b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java @@ -126,6 +126,14 @@ public class FunctionalRepositorySiteUtil { GLOSSARY; } + public enum AccessSettings { + ONLY_OWNERS, + OWNERS_AND_AUTHORS, + USERS, + USERS_AND_GUESTS, + MEMBERS_ONLY; + } + public final static String TOOLBOX_CONTENT_CSS = "b_toolbox_content"; public final static String TOOLBOX_COURSE_CSS = "o_toolbox_course"; public final static String TOOLBOX_CONTENT_PACKAGE_CSS = "o_toolbox_content"; @@ -373,7 +381,7 @@ public class FunctionalRepositorySiteUtil { * Opens a course by using business path. */ public boolean openCourse(Selenium browser, long key){ - browser.open(functionalUtil.getDeploymentUrl() + "url/RepositoryEntry/" + key); + browser.open(functionalUtil.getDeploymentPath() + "/url/RepositoryEntry/" + key); functionalUtil.waitForPageToLoad(browser); return(true); @@ -425,6 +433,30 @@ public class FunctionalRepositorySiteUtil { return(true); } + /** + * @param browser + * @param key + * @return + * + * Opens the appropriate detailed view. + */ + public boolean openDetailedView(Selenium browser, Long key){ + //TODO:JK: implement me + + return(false); + } + + /** + * @param browser + * @param settings + * @return + */ + public boolean modifySettings(Selenium browser, AccessSettings settings){ + //TODO:JK: implement me + + return(false); + } + public String findCssClassOfCourseAlias(String descriptor){ //TODO:JK: implement me diff --git a/src/test/java/org/olat/util/FunctionalUtil.java b/src/test/java/org/olat/util/FunctionalUtil.java index 8e84818f57b..749a4dcefaa 100644 --- a/src/test/java/org/olat/util/FunctionalUtil.java +++ b/src/test/java/org/olat/util/FunctionalUtil.java @@ -43,7 +43,8 @@ import com.thoughtworks.selenium.Selenium; public class FunctionalUtil { private final static OLog log = Tracing.createLoggerFor(FunctionalUtil.class); - public final static String DEPLOYMENT_URL = "http://localhost:8080/olat"; + public final static String DEPLOYMENT_URL = "http://localhost:8080/openolat"; + public final static String DEPLOYMENT_PATH = "/openolat"; public final static String WAIT_LIMIT = "5000"; public final static String LOGIN_PAGE = "dmz"; @@ -109,6 +110,7 @@ public class FunctionalUtil { private String password; private String deploymentUrl; + private String deploymentPath; private String waitLimit; private String loginPage; @@ -165,6 +167,7 @@ public class FunctionalUtil { } deploymentUrl = DEPLOYMENT_URL; + deploymentPath = DEPLOYMENT_PATH; waitLimit = WAIT_LIMIT; loginPage = LOGIN_PAGE; @@ -284,6 +287,57 @@ public class FunctionalUtil { return(false); } + + /** + * @param browser + * @param locator + * @return true on success otherwise false + * + * Waits at most (waitLimit + WaitLimitAttribute.VERY_SAVE) amount of time for element to load + * specified by locator. + */ + public boolean waitForPageToUnloadElement(Selenium browser, String locator){ + return(waitForPageToUnloadElement(browser, locator, WaitLimitAttribute.VERY_SAVE)); + } + + /** + * @param browser + * @param locator + * @param wait + * @return true on success otherwise false + * + * Waits at most (waitLimit + wait) amount of time for element to load + * specified by locator. + */ + public boolean waitForPageToUnloadElement(Selenium browser, String locator, WaitLimitAttribute wait){ + long startTime = Calendar.getInstance().getTimeInMillis(); + long currentTime = startTime; + long waitLimit = Long.parseLong(getWaitLimit()) + Long.parseLong(wait.getExtend()); + + log.info("waiting for page to unload element"); + + do{ + if(!browser.isElementPresent(locator)){ + log.info("found element after " + (currentTime - startTime) + "ms"); + + return(true); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + + currentTime = Calendar.getInstance().getTimeInMillis(); + }while(waitLimit > currentTime - startTime); + + log.warn("giving up after " + waitLimit + "ms"); + + return(false); + } + /** * @param site * @return the matching CSS class @@ -735,6 +789,25 @@ public class FunctionalUtil { return(true); } + public boolean typeMCE(Selenium browser, String cssClass, String content){ + if(content == null) + return(true); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("dom=document.getElementsByClassName('") + .append(cssClass) + .append("')[0].getElementsByClassName('") + .append("mceIframeContainer") + .append("')[0].getElementsByTagName('iframe')[0].contentDocument.body"); + + waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.type(selectorBuffer.toString(), content); + + return(true); + } + /** * @param browser * @param entryCss @@ -814,6 +887,9 @@ public class FunctionalUtil { .append(getWizardFinishCss()) .append("')]"); + waitForPageToLoadElement(browser, locatorBuffer.toString()); + + browser.focus(locatorBuffer.toString()); browser.click(locatorBuffer.toString()); return(true); @@ -843,6 +919,14 @@ public class FunctionalUtil { this.deploymentUrl = deploymentUrl; } + public String getDeploymentPath() { + return deploymentPath; + } + + public void setDeploymentPath(String deploymentPath) { + this.deploymentPath = deploymentPath; + } + public String getWaitLimit() { return waitLimit; } diff --git a/src/test/java/org/olat/util/FunctionalVOUtil.java b/src/test/java/org/olat/util/FunctionalVOUtil.java index 82140b106e3..9d36fe070cb 100644 --- a/src/test/java/org/olat/util/FunctionalVOUtil.java +++ b/src/test/java/org/olat/util/FunctionalVOUtil.java @@ -216,6 +216,18 @@ public class FunctionalVOUtil { return(importCourse(deploymentUrl, "/org/olat/portfolio/Course_including_Forum.zip", "Course_including_Forum.zip", "Course including Forum", "Course including Forum")); } + /** + * @param deploymentUrl + * @return + * @throws URISyntaxException + * @throws IOException + * + * Imports the "Course including Blog" via REST. + */ + public CourseVO importCourseIncludingBlog(URL deploymentUrl) throws URISyntaxException, IOException{ + return(importCourse(deploymentUrl, "/org/olat/portfolio/Course_including_Blog.zip", "Course_including_Blog.zip", "Course including Blog", "Course including Blog")); + } + /** * @param deploymentUrl * @return diff --git a/src/test/resources/org/olat/portfolio/Course_including_Blog.zip b/src/test/resources/org/olat/portfolio/Course_including_Blog.zip new file mode 100644 index 0000000000000000000000000000000000000000..62ec56d7e6f1321396de9cc7e58a1a2969ca585e GIT binary patch literal 20281 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 M!2V_WMhNBq03+UB4FCWD literal 0 HcmV?d00001 diff --git a/src/test/resources/org/olat/portfolio/blog.zip b/src/test/resources/org/olat/portfolio/blog.zip index b7d10f9788d15a05f30964506dff03f298495d35..faac98707d2b2959672b11c56b4cd6f8f7c9134c 100644 GIT binary patch delta 2185 zcma)7O>Y}T7+!BuYEoJ#%AtfrozjxDA>L1a$5?IBN)1+mMbmRT-W_{K-rX^~<2X6_ z%mv9>IH3v&i5oXgz3>yLDsh0{fP@ed;=qM>cKwwlfsSQ+JoCKI`@YYNpZ$INmyfPA z8w-oeQWjnt2e<BxuDrAGBBPBqi<gUfp<FO4rHYX^^^vD79umtLefxe^eDAodGkSS* z6Wbp3X~+Z2Sx{4PpF1q5FCkQ;9`29>?2&q@T+HVS(Y4IR)k;pwBdt`;m#ez2l#52x z%seFm4-vpZ{Z8FGVLjqA7xO3jlk&6*Q!kh`b&L@SRLY6BXNUErn%XABt~VPOv!8DN z@cgHYB)x$5>CU2`GlfObVsusBPbMw-QC_S_bK^aj3*t~czmDib`NnQKaPt)c&A4Xe z*mE<_7F&OhKDd2d<cjs;l)I#UK=^<KUC;punGxvyuERLutVgX7;TG$2<WE7Pm#agI z`JDK?zV7mEM_=#o?S{_=KH6a%7=2=OL$ReMdrL9Q5U`zoyG??Y%P>y>@oEg{iT!;R zaug0Iw;TegeH#Ukodhrs2*MC-abgd*(7>Tks)xG-4FU$G<1p-dJx-aQ#I@o~qNyIX zx`c<&4?`|Ml{j;pZmzP2ICOHm%ynr99OyprDRy%ow{wq3a6~OgL%BnJVDYRW=BTiR zigAIZGaK3C>$u0l?GVBBfu!yU3W&u#kN7qL64dY6zycEt^*LmM7WA-w1TDv{loU-d zOvnY_W+6^kP=*CDX8|Hd#77S8I3!Te9&)MQMNm9O1JVlNm_eWu1XsM%Apr{epcqD& za}Xqf1;k^33Qt0~5@+kugufK}1pDwg)nu3!<zCzadU$x)M7m-s$8n*Ca;zMmsm?rJ z=nK`Q!h|x0Vkmm$)X8rl3c?Q0Ro0$L8;d-aF=jF}#M+2EaFQTSoOG_^nmW1D;(wla zN`su#4WnX~iW8R+E3iMTdCaD5N&>N<)ztZ)BEHk7_J5m7j1W*4hkQR_v+IVY8#%3< zGb%`{RJD9nFDZH<j~*ZH*3=m?dYZX7?Dbo4SDpKqlXRR})igy*qUK>D-+<cO5j7_h zvE&fAL0qhjXJXL~aGTfL*bPZdO@4ss#nvHA@4;U7x39lhl%!|yKJ9vQ&L-V{1&4}0 zmp2k~d@hge@(=kgN}JtVK;;peVs&ipZ!X-7!@e&r{B`ZJfKQz`s;=HCPY5oI3wmw7 zFlkAim~OL?k(Z^}^C<dibw%Elqn?bm(tCnp!guQw-xnfaJ-V~@#xR{&`1@@9I!%1O z+nZ`S@q;<Jh3(JA-GxabW4`WLkFn`fAWbZYCLM{>nvH5UMSKQtbYpG#e}w)LXp(bF zr;fa}75T?(^x4|=owR1+v}fb(*C!mw*(*K2^DnmV)>bwjPl2K3Fy<z}3-Qrkk}gSq Kg7^pVdHe&*jYy~f delta 515 zcmccV^}(7iz?+#xgn<JHV*~#=OyrYf>1QnXH@TNtLn<vbHN}ogLBS?7#m>Ui!oa}L z*u==d(%jNwVy*#)YeiyiK~Adf#D%KtQ1--g%Is-Hsd*)t6%+r7vlS<2<mcy1mS$8J zG}ARQQ!uc!GBvR>Fw--$w45Bwn4qC=$7Q1rwk5!uo#W2_>giJ$85sJ37}ZsiC74WE zK+c;S$m9!QEMf|VFcxz_rS5PzKtvQc#Wq)RK9t}E>3|zLIbBIp0VKiz1gsze2-qML zlsv^ad4rM&h9Wr>Ma)c-H!vw^2Y53wi7+4n4x|QVstSsRkjeVW#u$d8+Ps=+a)XLU zJi7A)Q4D&*#K4f7nv$8QZ(?R@Y+z=rSCE&E?vArRy*PGDFfeQbVgVHG8qAXoRi*gY P8Q2+i0z+6)1|$mroAPW~ -- GitLab