From 7febda907e64124ef155658785f0a4c33c6d9bba Mon Sep 17 00:00:00 2001 From: BartChris Date: Mon, 29 Apr 2024 19:03:03 +0200 Subject: [PATCH] backport calendar tests handling for better stability of Selenium tests --- .../test/java/org/kitodo/MockDatabase.java | 3 +- .../java/org/kitodo/selenium/CalendarST.java | 5 +- .../testframework/pages/CalendarPage.java | 217 +++++++----------- .../selenium/testframework/pages/Page.java | 8 + .../testframework/pages/ProcessesPage.java | 16 +- 5 files changed, 106 insertions(+), 143 deletions(-) diff --git a/Kitodo/src/test/java/org/kitodo/MockDatabase.java b/Kitodo/src/test/java/org/kitodo/MockDatabase.java index f3f956a78b5..a63a7430192 100644 --- a/Kitodo/src/test/java/org/kitodo/MockDatabase.java +++ b/Kitodo/src/test/java/org/kitodo/MockDatabase.java @@ -725,7 +725,7 @@ public static void removeProcessesForHierarchyTests() throws DataException { } - public static void insertProcessForCalendarHierarchyTests() throws DAOException, DataException { + public static int insertProcessForCalendarHierarchyTests() throws DAOException, DataException { Ruleset fivthRuleset = new Ruleset(); fivthRuleset.setTitle("Newspaper"); fivthRuleset.setFile("newspaper.xml"); @@ -741,6 +741,7 @@ public static void insertProcessForCalendarHierarchyTests() throws DAOException, tenthProcess.setRuleset(ServiceManager.getRulesetService().getById(5)); tenthProcess.setTitle("NewspaperOverallProcess"); ServiceManager.getProcessService().save(tenthProcess); + return tenthProcess.getId(); } private static void insertTemplates() throws DAOException, DataException { diff --git a/Kitodo/src/test/java/org/kitodo/selenium/CalendarST.java b/Kitodo/src/test/java/org/kitodo/selenium/CalendarST.java index f3372173b75..4792055b03b 100644 --- a/Kitodo/src/test/java/org/kitodo/selenium/CalendarST.java +++ b/Kitodo/src/test/java/org/kitodo/selenium/CalendarST.java @@ -31,6 +31,7 @@ public class CalendarST extends BaseTestSelenium { private static ProcessesPage processesPage; private static CalendarPage calendarPage; + private static int newspaperTestProcessId = -1; @BeforeClass public static void setup() throws Exception { @@ -47,11 +48,11 @@ public void logout() throws Exception { @Test public void createProcessFromCalendar() throws Exception { // add process to access calendar - MockDatabase.insertProcessForCalendarHierarchyTests(); + newspaperTestProcessId = MockDatabase.insertProcessForCalendarHierarchyTests(); login(); processesPage.goTo(); - processesPage.goToCalendar(); + processesPage.goToCalendar(newspaperTestProcessId); calendarPage.addBlock(); calendarPage.addIssue("Morning issue"); calendarPage.addIssue("Evening issue"); diff --git a/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/CalendarPage.java b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/CalendarPage.java index 32475a38dfb..3b44cd1d56b 100644 --- a/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/CalendarPage.java +++ b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/CalendarPage.java @@ -22,15 +22,12 @@ import org.kitodo.selenium.testframework.Browser; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.FindBy; public class CalendarPage extends Page { private static final String BUTTON_CANCEL = "editForm:cancel"; private static final String BUTTON_ADD_BLOCK = "editForm:calendarTabView:addBlock"; private static final String DATEPICKER_FROM = "#editForm\\:calendarTabView\\:blockList td:first-child .p-datepicker input"; - private static final String DATEPICKER_FROM_LINK = "//div[@id='editForm:calendarTabView:blockList:0:blockFirstAppearance_panel']//" - + "a[text()='1']"; private static final String DATEPICKER_TO_LINK = "(//div[@id='editForm:calendarTabView:blockList:0:blockLastAppearance_panel']//" + "a[text()='7'])[last()]"; private static final String DATEPICKER_TO = "#editForm\\:calendarTabView\\:blockList td:last-child .p-datepicker input"; @@ -50,84 +47,10 @@ public class CalendarPage extends Page { private static final String METADATA_TYPE_PANEL = METADATA_TYPE + "_panel"; private static final String METADATA_VALUE = "calendarDayForm:issuesAccordion:0:metadataDataView:0:startValue"; private static final String CALENDAR_DIALOG_CLOSE_BUTTON = "calendarDayForm:close"; + private static final String CALENDAR = "editForm:calendarTabView:calendarTable"; + private static final String CALENDAR_ISSUES = ".issue.match"; - @SuppressWarnings("unused") - @FindBy(id = BUTTON_ADD_BLOCK) - private WebElement buttonAddBlock; - - @SuppressWarnings("unused") - @FindBy(id = BUTTON_CANCEL) - private WebElement buttonCancel; - - @SuppressWarnings("unused") - @FindBy(css = DATEPICKER_FROM) - private WebElement datepickerFrom; - - @SuppressWarnings("unused") - @FindBy(xpath = DATEPICKER_FROM_LINK) - private WebElement datepickerFromLink; - - @SuppressWarnings("unused") - @FindBy(css = DATEPICKER_TO) - private WebElement datepickerTo; - - @SuppressWarnings("unused") - @FindBy(xpath = DATEPICKER_TO_LINK) - private WebElement datepickerToLink; - - @SuppressWarnings("unused") - @FindBy(css = BUTTON_ADD_ISSUE) - private WebElement buttonAddIssue; - - @SuppressWarnings("unused") - @FindBy(css = INPUT_ISSUE) - private WebElement inputIssueName; - - @SuppressWarnings("unused") - @FindBy(id = HEADER_TEXT) - private WebElement headerText; - - @SuppressWarnings("unused") - @FindBy(css = CHECKBOX_MONDAY) - private WebElement checkboxMonday; - - @SuppressWarnings("unused") - @FindBy(css = CHECKBOX_TUESDAY) - private WebElement checkboxTuesday; - - @SuppressWarnings("unused") - @FindBy(xpath = CALENDAR_ENTRY) - private WebElement calendarEntry; - - @SuppressWarnings("unused") - @FindBy(xpath = CALENDAR_ENTRY_BUTTON) - private WebElement calendarEntryButton; - - @SuppressWarnings("unused") - @FindBy(id = BUTTON_ADD_METADATA_TO_THIS) - private WebElement buttonAddMetadataToThis; - - @SuppressWarnings("unused") - @FindBy(id = BUTTON_ADD_METADATA_TO_ALL) - private WebElement buttonAddMetadataToAll; - - @SuppressWarnings("unused") - @FindBy(id = METADATA_TYPE) - private WebElement metadataType; - - @SuppressWarnings("unused") - @FindBy(id = METADATA_TYPE_PANEL) - private WebElement metadataTypePanel; - - @SuppressWarnings("unused") - @FindBy(id = METADATA_VALUE) - private WebElement metadataValue; - - @SuppressWarnings("unused") - @FindBy(id = CALENDAR_DIALOG_CLOSE_BUTTON) - private WebElement calendarDialogCloseButton; - public CalendarPage() { super("pages/calendar.jsf"); } @@ -142,26 +65,35 @@ public CalendarPage goTo() { */ public void addBlock() { await("Wait for button to be displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(buttonAddBlock.isEnabled())); - buttonAddBlock.click(); + .untilAsserted(() -> assertTrue(getById(BUTTON_ADD_BLOCK).isEnabled())); + getById(BUTTON_ADD_BLOCK).click(); await("Wait for datepicker from being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(datepickerFrom.isEnabled())); - datepickerFrom.click(); - datepickerFromLink.click(); + .untilAsserted(() -> assertTrue(getByCSS(DATEPICKER_FROM).isEnabled())); + getByCSS(DATEPICKER_FROM).click(); + getByCSS(DATEPICKER_FROM).sendKeys("01.02.2023"); + getPageHeader().click(); await("Wait for datepicker to being displayed") - .pollDelay(3, TimeUnit.SECONDS) + .pollDelay(2, TimeUnit.SECONDS) + .pollInterval(400, TimeUnit.MILLISECONDS) + .atMost(10, TimeUnit.SECONDS) + .ignoreExceptions() + .untilAsserted(() -> assertTrue(getByXPath(DATEPICKER_TO_LINK).isEnabled())); + getByCSS(DATEPICKER_TO).click(); + await("Wait for datepicker to being displayed") + .pollDelay(2, TimeUnit.SECONDS) + .pollInterval(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(datepickerToLink.isEnabled())); - datepickerToLink.click(); + .untilAsserted(() -> assertTrue(getByXPath(DATEPICKER_TO_LINK).isEnabled())); + getByXPath(DATEPICKER_TO_LINK).click(); } /** @@ -170,47 +102,47 @@ public void addBlock() { */ public void addIssue(String title) { await("Wait for issue button being displayed") - .pollDelay(3, TimeUnit.SECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(buttonAddIssue.isEnabled())); - buttonAddIssue.click(); + .untilAsserted(() -> assertTrue(getByCSS(BUTTON_ADD_ISSUE).isEnabled())); + getByCSS(BUTTON_ADD_ISSUE).click(); await("Wait for issue input being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(inputIssueName.isEnabled())); - inputIssueName.click(); - inputIssueName.sendKeys(title); - headerText.click(); + .untilAsserted(() -> assertTrue(getByCSS(INPUT_ISSUE).isEnabled())); + getByCSS(INPUT_ISSUE).click(); + getByCSS(INPUT_ISSUE).sendKeys(title); + getById(HEADER_TEXT).click(); await("Wait for checkbox being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(checkboxMonday.isDisplayed())); - checkboxMonday.click(); + .untilAsserted(() -> assertTrue(getByCSS(CHECKBOX_MONDAY).isDisplayed())); + getByCSS(CHECKBOX_MONDAY).click(); await("Wait for checkbox being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(checkboxMonday.isDisplayed())); - checkboxTuesday.click(); + .untilAsserted(() -> assertTrue(getByCSS(CHECKBOX_MONDAY).isDisplayed())); + getByCSS(CHECKBOX_TUESDAY).click(); } /** * Add metadata to this issue. Type "Process title" and value "Test" will be inserted. */ public void addMetadataToThis() { - addMetadata("Process title", "Test", buttonAddMetadataToThis); + addMetadata("Process title", "Test", BUTTON_ADD_METADATA_TO_THIS); } /** * Add metadata to this and all following issues. Type "Signatur" and value "1234" will be used. */ public void addMetadataToAll() { - addMetadata("Signatur", "1234", buttonAddMetadataToAll); + addMetadata("Signatur", "1234", BUTTON_ADD_METADATA_TO_ALL); } /** @@ -220,21 +152,22 @@ public void addMetadataToAll() { */ public List getMetadata(String issueName) { await("Wait for calendar entry being displayed") - .pollDelay(3, TimeUnit.SECONDS) + .pollDelay(2, TimeUnit.SECONDS) + .pollInterval(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue( calendarEntry.isDisplayed())); - calendarEntryButton.click(); + .untilAsserted(() -> assertTrue(getByXPath(CALENDAR_ENTRY).isDisplayed())); + getByXPath(CALENDAR_ENTRY_BUTTON).click(); await("Wait for issue '" + issueName + "' being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() .untilAsserted(() -> assertTrue(getIssue(issueName).isDisplayed())); if (Objects.equals(getIssue(issueName).getAttribute("aria-expanded"), "false")) { - Browser.getDriver().findElementByXPath("//div[@aria-expanded='true']").click(); + getByXPath("//div[@aria-expanded='true']").click(); await("Wait for issue '" + issueName + "' being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() .untilAsserted(() -> assertTrue(getIssue(issueName).isDisplayed())); @@ -242,13 +175,13 @@ public List getMetadata(String issueName) { } await("Wait for issue content for '" + issueName + "' being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() .untilAsserted(() -> assertTrue(getIssueContent(issueName).isDisplayed())); List metadataList = readMetadataTypes(issueName); - calendarDialogCloseButton.click(); + getById(CALENDAR_DIALOG_CLOSE_BUTTON).click(); return metadataList; } @@ -257,46 +190,52 @@ public List getMetadata(String issueName) { * Click cancel button and leave calendar. */ public void closePage() { - buttonCancel.click(); + getById(BUTTON_CANCEL).click(); + } + + public int countIssues() { + await("Wait for calendar issues to be displayed") + .untilAsserted(() -> assertTrue(getById(CALENDAR).isDisplayed())); + return getById(CALENDAR).findElements(By.cssSelector(CALENDAR_ISSUES)).size(); } - private void addMetadata(String type, String value, WebElement addButton) { + private void addMetadata(String type, String value, String addButton) { await("Wait for calendar entry being displayed") - .pollDelay(3, TimeUnit.SECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue( calendarEntry.isDisplayed())); - calendarEntryButton.click(); + .untilAsserted(() -> assertTrue(getByXPath(CALENDAR_ENTRY).isDisplayed())); + getByXPath(CALENDAR_ENTRY_BUTTON).click(); await("Wait for button to add metadata to this issue being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(addButton.isEnabled())); - addButton.click(); + .untilAsserted(() -> assertTrue(getById(addButton).isEnabled())); + getById(addButton).click(); await("Wait for button to add metadata to this issue being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(metadataType.isEnabled())); - metadataType.click(); - metadataTypePanel.findElement(By.xpath("//li[text()='" + type + "']")).click(); + .untilAsserted(() -> assertTrue(getById(METADATA_TYPE).isEnabled())); + getById(METADATA_TYPE).click(); + getById(METADATA_TYPE_PANEL).findElement(By.xpath("//li[text()='" + type + "']")).click(); await("Wait for metadata input being displayed") - .pollDelay(700, TimeUnit.MILLISECONDS) + .pollDelay(400, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .ignoreExceptions() - .untilAsserted(() -> assertTrue(metadataValue.isEnabled())); - metadataValue.sendKeys(value); - calendarDialogCloseButton.click(); + .untilAsserted(() -> assertTrue(getById(METADATA_VALUE).isEnabled())); + getById(METADATA_VALUE).sendKeys(value); + getById(CALENDAR_DIALOG_CLOSE_BUTTON).click(); } - + private WebElement getIssue(String name) { - return Browser.getDriver().findElementByXPath( "//div[text()='" + name + " erschien']"); + return getByXPath( "//div[text()='" + name + " erschien']"); } private WebElement getIssueContent(String name) { - return Browser.getDriver().findElementByXPath("//div[text()='" + name + " erschien']/following-sibling::div"); + return getByXPath("//div[text()='" + name + " erschien']/following-sibling::div"); } private List readMetadataTypes(String issueName) { @@ -304,4 +243,16 @@ private List readMetadataTypes(String issueName) { + " erschien']/following-sibling::div[@aria-hidden='false']//div[@title='Art']/label"); return metadataTypeLabels.stream().map(WebElement::getText).collect(Collectors.toList()); } -} + + private WebElement getById(String id) { + return Browser.getDriver().findElementById(id); + } + + private WebElement getByCSS(String cssSelector) { + return Browser.getDriver().findElementByCssSelector(cssSelector); + } + + private WebElement getByXPath(String xpath) { + return Browser.getDriver().findElementByXPath(xpath); + } +} \ No newline at end of file diff --git a/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/Page.java b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/Page.java index b3fc4580c90..7b402f1bd33 100644 --- a/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/Page.java +++ b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/Page.java @@ -70,6 +70,10 @@ public abstract class Page { @FindBy(id = "search-form:search") private WebElement searchButton; + @SuppressWarnings("unused") + @FindBy(id = "portal-header") + private WebElement pageHeader; + private String URL; Page(String URL) { @@ -212,6 +216,10 @@ protected void clickElement(WebElement element) { .ignoreExceptions().until(() -> isButtonClicked.test(element)); } + public WebElement getPageHeader() { + return pageHeader; + } + /** * Get header text. * diff --git a/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/ProcessesPage.java b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/ProcessesPage.java index 9b6825b9810..ce89b1f3144 100644 --- a/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/ProcessesPage.java +++ b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/ProcessesPage.java @@ -50,8 +50,8 @@ public class ProcessesPage extends Page { private static final String WAIT_FOR_ACTIONS_MENU = "Wait for actions menu to open"; private static final String WAIT_FOR_COLUMN_SORT = "Wait for column sorting"; private static final String MULTI_VOLUME_WORK_PROCESS_TITLE = "Multi volume work test process"; - private static final String WAIT_FOR_SELECTION_MENU = "Wait for process selection menu to open"; + private static final String CALENDER_ACTION_XPATH = "//a[@href='/kitodo/pages/calendarEdit.jsf?id=%s']"; @SuppressWarnings("unused") @FindBy(id = PROCESSES_TAB_VIEW) @@ -494,15 +494,17 @@ public void clickProcessesTableHeaderForSorting(int column) { .until(() -> !columnHeader.getAttribute("aria-sort").equals(previousAriaSort)); } - public void goToCalendar() throws Exception { + /** + * Navigate to calendar page to create child processes for process with provided ID 'processId'. + * @param processId ID of process for which child processes are created using the calendar + * @throws Exception when navigating to the calendar page fails + */ + public void goToCalendar(int processId) throws Exception { + String xpath = String.format(CALENDER_ACTION_XPATH, processId); + WebElement openCalendarLink = Browser.getDriver().findElementByXPath(xpath); if (isNotAt()) { goTo(); } - - await("Wait for openCalendarLink to be clickable") - .pollDelay(100, TimeUnit.MILLISECONDS) - .atMost(5, TimeUnit.SECONDS) - .until(openCalendarLink::isDisplayed); openCalendarLink.click(); }