diff --git a/Kitodo/src/test/java/org/kitodo/MockDatabase.java b/Kitodo/src/test/java/org/kitodo/MockDatabase.java index bffb046d806..0eb237b7916 100644 --- a/Kitodo/src/test/java/org/kitodo/MockDatabase.java +++ b/Kitodo/src/test/java/org/kitodo/MockDatabase.java @@ -133,6 +133,8 @@ public class MockDatabase { public static final String MEDIA_REFERENCES_TEST_PROCESS_TITLE = "Media"; public static final String METADATA_LOCK_TEST_PROCESS_TITLE = "Metadata lock"; public static final String MEDIA_RENAMING_TEST_PROCESS_TITLE = "Rename media"; + public static final String DRAG_N_DROP_TEST_PROCESS_TITLE = "Drag'n'drop"; + public static final String CREATE_STRUCTURE_PROCESS_TITLE = "Create_Structure_Element"; public static final String HIERARCHY_PARENT = "HierarchyParent"; public static final String HIERARCHY_CHILD_TO_KEEP = "HierarchyChildToKeep"; public static final String HIERARCHY_CHILD_TO_REMOVE = "HierarchyChildToRemove"; @@ -1107,6 +1109,26 @@ public static int insertTestProcessForRenamingMediaTestIntoSecondProject() throw return insertTestProcessIntoSecondProject(MEDIA_RENAMING_TEST_PROCESS_TITLE); } + /** + * Add test process for moving pages via mouse drag'n'drop. + * @return ID of created test process + * @throws DAOException when retrieving project fails + * @throws DataException when saving test process fails + */ + public static int insertTestProcessForDragNDropTestIntoSecondProject() throws DAOException, DataException { + return insertTestProcessIntoSecondProject(DRAG_N_DROP_TEST_PROCESS_TITLE); + } + + /** + * Add test process for creating structure elements. + * @return ID of created test process + * @throws DAOException when retrieving project fails + * @throws DataException when saving test process fails + */ + public static int insertTestProcessForCreatingStructureElementIntoSecondProject() throws DAOException, DataException { + return insertTestProcessIntoSecondProject(CREATE_STRUCTURE_PROCESS_TITLE); + } + /** * Insert test process for media reference updates into database. * @return database ID of created test process diff --git a/Kitodo/src/test/java/org/kitodo/selenium/MetadataST.java b/Kitodo/src/test/java/org/kitodo/selenium/MetadataST.java index ff6e9843480..c20caaad108 100644 --- a/Kitodo/src/test/java/org/kitodo/selenium/MetadataST.java +++ b/Kitodo/src/test/java/org/kitodo/selenium/MetadataST.java @@ -11,6 +11,7 @@ package org.kitodo.selenium; +import static org.awaitility.Awaitility.await; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -21,6 +22,7 @@ import java.nio.file.Paths; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.TimeUnit; import org.junit.After; import org.junit.AfterClass; @@ -40,6 +42,11 @@ import org.kitodo.selenium.testframework.Browser; import org.kitodo.selenium.testframework.Pages; import org.kitodo.test.utils.ProcessTestUtils; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; /** * Tests for functions in the metadata editor. @@ -53,6 +60,8 @@ public class MetadataST extends BaseTestSelenium { private static int metadataLockProcessId = -1; private static int parentProcessId = -1; private static int renamingMediaProcessId = -1; + private static int dragndropProcessId = -1; + private static int createStructureProcessId = -1; private static final String PARENT_PROCESS_TITLE = "Parent process"; private static final String FIRST_CHILD_PROCESS_TITLE = "First child process"; private static final String SECOND_CHILD_PROCESS_TITLE = "Second child process"; @@ -84,6 +93,16 @@ private static void prepareMediaRenamingProcess() throws DAOException, DataExcep copyTestFilesForRenamingMediaFiles(); } + private static void prepareDragNDropProcess() throws DAOException, DataException, IOException { + insertTestProcessForDragAndDrop(); + copyTestFilesForDragAndDrop(); + } + + private static void prepareCreateStructureProcess() throws DAOException, DataException, IOException { + insertTestProcessForCreatingStructureElement(); + copyTestFilesForCreateStructure(); + } + /** * Prepare tests by inserting dummy processes into database and index for sub-folders of test metadata resources. * @throws DAOException when saving of dummy or test processes fails. @@ -97,6 +116,8 @@ public static void prepare() throws DAOException, DataException, IOException { prepareMediaReferenceProcess(); prepareProcessHierarchyProcesses(); prepareMediaRenamingProcess(); + prepareDragNDropProcess(); + prepareCreateStructureProcess(); } /** @@ -229,6 +250,100 @@ public void renameMediaFilesTest() throws Exception { SECOND_STRUCTURE_TREE_NODE_LABEL, Pages.getMetadataEditorPage().getSecondRootElementChildLabel()); } + /** + * Verifies drag and drop functionality in gallery. + * @throws Exception when page navigation or process saving fails. + */ + @Test + public void dragAndDropPageTest() throws Exception { + login("kowal"); + Pages.getProcessesPage().goTo().editMetadata(MockDatabase.DRAG_N_DROP_TEST_PROCESS_TITLE); + WebElement unstructuredMedia = Browser.getDriver().findElement(By.id("imagePreviewForm:unstructuredMedia")); + await().ignoreExceptions().pollDelay(300, TimeUnit.MILLISECONDS).atMost(3, TimeUnit.SECONDS) + .until(unstructuredMedia::isDisplayed); + // first page in unstructured media + WebElement firstThumbnail = Browser.getDriver() + .findElement(By.id("imagePreviewForm:unstructuredMediaList:0:unstructuredMediaPanel")); + await().ignoreExceptions().pollDelay(300, TimeUnit.MILLISECONDS).atMost(3, TimeUnit.SECONDS) + .until(firstThumbnail::isDisplayed); + // hover over second thumbnail to verify overlay text before drag'n'drop + Actions hoverAction = new Actions(Browser.getDriver()); + WebElement secondThumbnail = Browser.getDriver() + .findElement(By.id("imagePreviewForm:unstructuredMediaList:1:unstructuredMediaPanel")); + hoverAction.moveToElement(secondThumbnail).build().perform(); + WebElement thumbnailOverlay = secondThumbnail.findElement(By.className("thumbnail-overlay")); + await().ignoreExceptions().pollDelay(300, TimeUnit.MILLISECONDS).atMost(5, TimeUnit.SECONDS) + .until(thumbnailOverlay::isDisplayed); + Assert.assertEquals("Last thumbnail has wrong overlay before drag'n'drop action", + "Bild 1, Seite -", thumbnailOverlay.getText().strip()); + // drop position for drag'n'drop action + WebElement dropPosition = Browser.getDriver() + .findElement(By.id("imagePreviewForm:unstructuredMediaList:2:unstructuredPageDropArea")); + await().ignoreExceptions().pollDelay(300, TimeUnit.MILLISECONDS).atMost(3, TimeUnit.SECONDS) + .until(dropPosition::isDisplayed); + // drag'n'drop action + Actions dragAndDropAction = new Actions(Browser.getDriver()); + dragAndDropAction.dragAndDrop(firstThumbnail, dropPosition).build().perform(); + await().ignoreExceptions().pollDelay(300, TimeUnit.MILLISECONDS).atMost(5, TimeUnit.SECONDS) + .until(Browser.getDriver().findElement(By.id("buttonForm:saveExit"))::isEnabled); + Pages.getMetadataEditorPage().saveAndExit(); + // check whether new position has been saved correctly + Pages.getProcessesPage().goTo().editMetadata(MockDatabase.DRAG_N_DROP_TEST_PROCESS_TITLE); + secondThumbnail = Browser.getDriver() + .findElement(By.id("imagePreviewForm:unstructuredMediaList:1:unstructuredMediaPanel")); + hoverAction.moveToElement(secondThumbnail).build().perform(); + thumbnailOverlay = secondThumbnail.findElement(By.className("thumbnail-overlay")); + await().ignoreExceptions().pollDelay(300, TimeUnit.MILLISECONDS).atMost(5, TimeUnit.SECONDS) + .until(thumbnailOverlay::isDisplayed); + Assert.assertEquals("Last thumbnail has wrong overlay after drag'n'drop action", + "Bild 2, Seite -", thumbnailOverlay.getText().strip()); + } + + /** + * Verifies functionality of creating structure elements in the metadata editor using the structure tree context + * menu. + */ + @Test + public void createStructureElementTest() throws Exception { + login("kowal"); + Pages.getProcessesPage().goTo().editMetadata(MockDatabase.CREATE_STRUCTURE_PROCESS_TITLE); + await().ignoreExceptions().pollDelay(300, TimeUnit.MILLISECONDS).atMost(5, TimeUnit.SECONDS) + .until(Browser.getDriver().findElement(By.id("logicalTree"))::isDisplayed); + WebElement structureTree = Browser.getDriver().findElement(By.id("logicalTree")); + WebElement logicalRoot = structureTree.findElement(By.className("ui-tree-selectable")); + logicalRoot.click(); + await().ignoreExceptions().pollDelay(1000, TimeUnit.MILLISECONDS).pollInterval(500, TimeUnit.MILLISECONDS) + .atMost(5, TimeUnit.SECONDS).until(logicalRoot::isDisplayed); + // right click action + Actions rightClickAction = new Actions(Browser.getDriver()); + rightClickAction.contextClick(logicalRoot).build().perform(); + // wait for loading screen to disappear + await().ignoreExceptions().pollDelay(300, TimeUnit.MILLISECONDS).pollInterval(300, TimeUnit.MILLISECONDS) + .atMost(5, TimeUnit.SECONDS).until(Browser.getDriver() + .findElement(By.id("buttonForm:saveExit"))::isDisplayed); + WebElement contextMenu = Browser.getDriver().findElement(By.id("contextMenuLogicalTree")); + List menuItems = contextMenu.findElements(By.className("ui-menuitem")); + assertEquals("Wrong number of context menu items", 3, menuItems.size()); + // click "add element" option + menuItems.get(0).click(); + // open "structure element type selection" menu + clickItemWhenDisplayed(By.id("dialogAddDocStrucTypeForm:docStructAddTypeSelection"), 1000, 1000, 5); + // click first option + WebElement firstOption = Browser.getDriver().findElement(By.id("dialogAddDocStrucTypeForm:docStructAddTypeSelection_1")); + String structureType = firstOption.getText(); + clickItemWhenDisplayed(By.id("dialogAddDocStrucTypeForm:docStructAddTypeSelection_1"), 1000, 500, 3); + WebDriverWait wait = new WebDriverWait(Browser.getDriver(), 3); + wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("dialogAddDocStrucTypeForm:docStructAddTypeSelection_1"))); + // add structure element with selected type by clicking "accept"/"apply" button + Thread.sleep(1000); + clickItemWhenDisplayed(By.id("dialogAddDocStrucTypeForm:addDocStruc"), 500, 500, 5); + await().ignoreExceptions().pollDelay(300, TimeUnit.MILLISECONDS).atMost(5, TimeUnit.SECONDS) + .until(Browser.getDriver().findElement(By.id("buttonForm:saveExit"))::isEnabled); + structureTree = Browser.getDriver().findElement(By.id("logicalTree")); + WebElement firstChild = structureTree.findElement(By.id("logicalTree:0_0")); + Assert.assertEquals("Added structure element has wrong type!", structureType, firstChild.getText()); + } + /** * Close metadata editor and logout after every test. * @throws Exception when page navigation fails @@ -254,6 +369,8 @@ public static void cleanup() throws DAOException, CustomResponseException, DataE ProcessService.deleteProcess(mediaReferencesProcessId); ProcessService.deleteProcess(metadataLockProcessId); ProcessService.deleteProcess(renamingMediaProcessId); + ProcessService.deleteProcess(dragndropProcessId); + ProcessService.deleteProcess(createStructureProcessId); } private void login(String username) throws InstantiationException, IllegalAccessException, InterruptedException { @@ -273,6 +390,14 @@ private static void insertTestProcessForRenamingMediaFiles() throws DAOException renamingMediaProcessId = MockDatabase.insertTestProcessForRenamingMediaTestIntoSecondProject(); } + private static void insertTestProcessForDragAndDrop() throws DAOException, DataException { + dragndropProcessId = MockDatabase.insertTestProcessForDragNDropTestIntoSecondProject(); + } + + private static void insertTestProcessForCreatingStructureElement() throws DAOException, DataException { + createStructureProcessId = MockDatabase.insertTestProcessForCreatingStructureElementIntoSecondProject(); + } + /** * Creates dummy parent process and links first two test processes as child processes to parent process. * @throws DAOException if loading of processes fails @@ -304,6 +429,14 @@ private static void copyTestFilesForRenamingMediaFiles() throws IOException, DAO ProcessTestUtils.copyTestFiles(renamingMediaProcessId, TEST_RENAME_MEDIA_FILE); } + private static void copyTestFilesForDragAndDrop() throws IOException, DAOException, DataException { + ProcessTestUtils.copyTestFiles(dragndropProcessId, TEST_RENAME_MEDIA_FILE); + } + + private static void copyTestFilesForCreateStructure() throws DAOException, DataException, IOException { + ProcessTestUtils.copyTestFiles(createStructureProcessId, TEST_RENAME_MEDIA_FILE); + } + private static void copyTestParentProcessMetadataFile() throws IOException, DAOException, DataException { ProcessTestUtils.copyTestMetadataFile(parentProcessId, TEST_PARENT_PROCESS_METADATA_FILE); } @@ -318,4 +451,10 @@ private static void updateChildProcessIdsInParentProcessMetadataFile() throws IO xmlContent = xmlContent.replaceAll(SECOND_CHILD_ID, String.valueOf(secondChildId)); Files.write(metaXml, xmlContent.getBytes()); } + + private void clickItemWhenDisplayed(By selector, long delay, long intervall, long timeout) { + await().ignoreExceptions().pollDelay(delay, TimeUnit.MILLISECONDS).pollInterval(intervall, TimeUnit.MILLISECONDS) + .atMost(timeout, TimeUnit.SECONDS).until(Browser.getDriver().findElement(selector)::isDisplayed); + Browser.getDriver().findElement(selector).click(); + } }