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