diff --git a/Kitodo/src/main/java/org/kitodo/constants/StringConstants.java b/Kitodo/src/main/java/org/kitodo/constants/StringConstants.java index 9d83b6e5b53..28fed62d1a6 100644 --- a/Kitodo/src/main/java/org/kitodo/constants/StringConstants.java +++ b/Kitodo/src/main/java/org/kitodo/constants/StringConstants.java @@ -14,5 +14,6 @@ public class StringConstants { public static String COMMA_DELIMITER = ", "; + public static String SEMICOLON_DELIMITER = "; "; } diff --git a/Kitodo/src/test/java/org/kitodo/production/forms/MassImportFormIT.java b/Kitodo/src/test/java/org/kitodo/production/forms/MassImportFormIT.java new file mode 100644 index 00000000000..b8842dfea14 --- /dev/null +++ b/Kitodo/src/test/java/org/kitodo/production/forms/MassImportFormIT.java @@ -0,0 +1,64 @@ +/* + * (c) Kitodo. Key to digital objects e. V. + * + * This file is part of the Kitodo project. + * + * It is licensed under GNU General Public License version 3 or later. + * + * For the full copyright and license information, please read the + * GPL3-License.txt file that was distributed with this source code. + */ + +package org.kitodo.production.forms; + +import java.util.List; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.kitodo.MockDatabase; +import org.kitodo.SecurityTestUtils; +import org.kitodo.data.database.beans.User; +import org.kitodo.production.forms.createprocess.ProcessDetail; +import org.kitodo.production.forms.massimport.AddMetadataDialog; +import org.kitodo.production.forms.massimport.MassImportForm; +import org.kitodo.production.services.ServiceManager; + +/** + * Test for process mass import form. + */ +public class MassImportFormIT { + + private static final int PROJECT_ID = 1; + private static final int TEMPLATE_ID = 1; + private static final String FIRST_TEMPLATE_TITLE = "First template"; + private static final String TSL_ATS = "TSL/ATS"; + + @BeforeClass + public static void prepareDatabase() throws Exception { + MockDatabase.startNode(); + MockDatabase.insertProcessesFull(); + User userOne = ServiceManager.getUserService().getById(1); + SecurityTestUtils.addUserDataToSecurityContext(userOne, 1); + } + + @AfterClass + public static void cleanup() throws Exception { + MockDatabase.stopNode(); + MockDatabase.cleanDatabase(); + } + + @Test + public void shouldPrepareMassImport() { + MassImportForm massImportForm = new MassImportForm(); + massImportForm.prepareMassImport(TEMPLATE_ID, PROJECT_ID); + Assert.assertEquals("Wrong template title", FIRST_TEMPLATE_TITLE, massImportForm.getTemplateTitle()); + AddMetadataDialog addMetadataDialog = massImportForm.getAddMetadataDialog(); + Assert.assertNotNull("'Add metadata' dialog should not be null", addMetadataDialog); + List metadataTypes = addMetadataDialog.getAllMetadataTypes(); + Assert.assertFalse("List of metadata types should not be empty", metadataTypes.isEmpty()); + ProcessDetail firstDetail = metadataTypes.get(0); + Assert.assertEquals(String.format("First metadata type should be '%s'", TSL_ATS), TSL_ATS, firstDetail.getLabel()); + } +} diff --git a/Kitodo/src/test/java/org/kitodo/production/services/catalogimport/MassImportTest.java b/Kitodo/src/test/java/org/kitodo/production/services/catalogimport/MassImportTest.java new file mode 100644 index 00000000000..062a884099e --- /dev/null +++ b/Kitodo/src/test/java/org/kitodo/production/services/catalogimport/MassImportTest.java @@ -0,0 +1,103 @@ +/* + * (c) Kitodo. Key to digital objects e. V. + * + * This file is part of the Kitodo project. + * + * It is licensed under GNU General Public License version 3 or later. + * + * For the full copyright and license information, please read the + * GPL3-License.txt file that was distributed with this source code. + */ + + +package org.kitodo.production.services.catalogimport; + +import org.junit.Assert; +import org.junit.Test; +import org.kitodo.constants.StringConstants; +import org.kitodo.exceptions.ImportException; +import org.kitodo.production.forms.CsvCell; +import org.kitodo.production.forms.CsvRecord; +import org.kitodo.production.services.ServiceManager; +import org.kitodo.production.services.data.MassImportService; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class MassImportTest { + + private static final String ID = "ID"; + private static final String TITLE = "Title"; + private static final String PLACE = "Place"; + private static final List METADATA_KEYS = Arrays.asList(ID, TITLE, PLACE); + private static final String CSV_FIRST_LINE = "123, Band 1, Hamburg"; + private static final String CSV_SECOND_LINE = "456, Band 2, Dresden"; + private static final String CSV_THIRD_LINE = "789, Band 3, Berlin"; + private static final List CSV_LINES = Arrays.asList(CSV_FIRST_LINE, CSV_SECOND_LINE, CSV_THIRD_LINE); + + /** + * Tests parsing CSV lines into CSV records with multiple cells. + */ + @Test + public void shouldParseLines() { + MassImportService service = ServiceManager.getMassImportService(); + // test parsing CSV lines with correct delimiter + List csvRecords = service.parseLines(CSV_LINES, StringConstants.COMMA_DELIMITER); + Assert.assertEquals("Wrong number of CSV records", 3, csvRecords.size()); + List cells = csvRecords.get(0).getCsvCells(); + Assert.assertEquals("Wrong number of cells in first CSV record", 3, cells.size()); + Assert.assertEquals("Wrong value in first cell of first CSV record", "123", cells.get(0).getValue()); + Assert.assertEquals("Wrong value in second cell of first CSV record", "Band 1", cells.get(1).getValue()); + Assert.assertEquals("Wrong value in third cell of first CSV record", "Hamburg", cells.get(2).getValue()); + cells = csvRecords.get(1).getCsvCells(); + Assert.assertEquals("Wrong number of cells in second CSV record", 3, cells.size()); + Assert.assertEquals("Wrong value in first cell of second CSV record", "456", cells.get(0).getValue()); + Assert.assertEquals("Wrong value in second cell of second CSV record", "Band 2", cells.get(1).getValue()); + Assert.assertEquals("Wrong value in third cell of second CSV record", "Dresden", cells.get(2).getValue()); + cells = csvRecords.get(2).getCsvCells(); + Assert.assertEquals("Wrong number of cells in second CSV record", 3, cells.size()); + Assert.assertEquals("Wrong value in first cell of third CSV record", "789", cells.get(0).getValue()); + Assert.assertEquals("Wrong value in second cell of third CSV record", "Band 3", cells.get(1).getValue()); + Assert.assertEquals("Wrong value in third cell of third CSV record", "Berlin", cells.get(2).getValue()); + // test parsing CSV lines with incorrect delimiter + csvRecords = service.parseLines(CSV_LINES, ";"); + cells = csvRecords.get(0).getCsvCells(); + Assert.assertEquals("Wrong number of cells in first CSV record", 1, cells.size()); + cells = csvRecords.get(1).getCsvCells(); + Assert.assertEquals("Wrong number of cells in second CSV record", 1, cells.size()); + cells = csvRecords.get(2).getCsvCells(); + Assert.assertEquals("Wrong number of cells in third CSV record", 1, cells.size()); + } + + /** + * Tests whether updating CSV separator character from incorrect character to correct character keeps number of + * CSV records, but changes number of cells per record. + */ + @Test + public void shouldUpdateSeparator() { + MassImportService service = ServiceManager.getMassImportService(); + List oldCsvRecords = service.parseLines(CSV_LINES, StringConstants.SEMICOLON_DELIMITER); + Assert.assertTrue("CSV lines should not be separated into multiple records when using incorrect separator character", + oldCsvRecords.stream().noneMatch(csvRecord -> csvRecord.getCsvCells().size() > 1)); + List newCsvRecords = service.updateSeparator(oldCsvRecords, StringConstants.SEMICOLON_DELIMITER, StringConstants.COMMA_DELIMITER); + Assert.assertEquals("Updating separator character should not alter number of CSV records", oldCsvRecords.size(), newCsvRecords.size()); + Assert.assertTrue("CSV lines be separated into multiple records when using correct separator character", + newCsvRecords.stream().allMatch(csvRecord -> csvRecord.getCsvCells().size() > 1)); + } + + /** + * Tests whether parsing data entered in mass import form succeeds or not. + */ + @Test + public void shouldPrepareMetadata() throws ImportException { + MassImportService service = ServiceManager.getMassImportService(); + List csvRecords = service.parseLines(CSV_LINES, StringConstants.COMMA_DELIMITER); + Map> metadata = service.prepareMetadata(METADATA_KEYS, csvRecords); + Assert.assertEquals("Wrong number of metadata sets prepared", 3, metadata.size()); + Map metadataSet = metadata.get("123"); + Assert.assertNotNull("Metadata for record with ID 123 is null", metadataSet); + Assert.assertTrue("Metadata for record with ID 123 does not contain title metadata", metadataSet.containsKey(TITLE)); + Assert.assertEquals("Metadata for record with ID 123 contains wrong title", "Band 1", metadataSet.get(TITLE)); + } +} diff --git a/Kitodo/src/test/java/org/kitodo/production/services/data/MassImportServiceIT.java b/Kitodo/src/test/java/org/kitodo/production/services/data/MassImportServiceIT.java new file mode 100644 index 00000000000..19cf1c8bfe4 --- /dev/null +++ b/Kitodo/src/test/java/org/kitodo/production/services/data/MassImportServiceIT.java @@ -0,0 +1,103 @@ +/* + * (c) Kitodo. Key to digital objects e. V. + * + * This file is part of the Kitodo project. + * + * It is licensed under GNU General Public License version 3 or later. + * + * For the full copyright and license information, please read the + * GPL3-License.txt file that was distributed with this source code. + */ + +package org.kitodo.production.services.data; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.kitodo.MockDatabase; +import org.kitodo.api.Metadata; +import org.kitodo.api.MetadataEntry; +import org.kitodo.api.dataeditor.rulesetmanagement.RulesetManagementInterface; +import org.kitodo.api.dataeditor.rulesetmanagement.StructuralElementViewInterface; +import org.kitodo.data.database.beans.Ruleset; +import org.kitodo.data.database.exceptions.DAOException; +import org.kitodo.production.forms.createprocess.ProcessDetail; +import org.kitodo.production.services.ServiceManager; + +import java.io.IOException; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +public class MassImportServiceIT { + + /** + * Prepare database before tests are run. + * + * @throws Exception when preparing database fails + */ + @BeforeClass + public static void prepareDatabase() throws Exception { + MockDatabase.startNode(); + MockDatabase.insertProcessesFull(); + } + + /** + * Cleanup database after all tests have been completed. + * + * @throws Exception when cleaning up database fails + */ + @AfterClass + public static void cleanupDatabase() throws Exception { + MockDatabase.stopNode(); + MockDatabase.cleanDatabase(); + } + + /** + * Tests whether preparing addable metadata depending on already entered metadata and divisions defined in ruleset + * works or not. + * + * @throws DAOException when retrieving list of divisions defined in test ruleset fails + * @throws IOException when loading test ruleset file fails + */ + @Test + public void shouldGetAddableMetadataTable() throws DAOException, IOException { + Collection enteredMetadata = createPresetMetadata(); + List divisions = retrieveDivisions(); + List addableMetadata = ServiceManager.getMassImportService().getAddableMetadataTable(divisions, enteredMetadata); + Assert.assertFalse("List of addable metadata should not be empty", + addableMetadata.isEmpty()); + Assert.assertTrue("List of addable metadata should contain 'TSL/ATS'", + addableMetadata.stream().anyMatch(m -> "TSL/ATS".equals(m.getLabel()))); + } + + private List retrieveDivisions() throws DAOException, IOException { + Ruleset ruleset = ServiceManager.getRulesetService().getById(1); + RulesetManagementInterface rulesetInterface = ServiceManager.getRulesetService().openRuleset(ruleset); + List priorityList = Locale.LanguageRange.parse("en"); + return rulesetInterface.getStructuralElements(priorityList).keySet().stream() + .map(key -> rulesetInterface.getStructuralElementView(key, "create", priorityList)) + .collect(Collectors.toList()); + } + + private Collection createPresetMetadata() { + Collection presetMetadata = new LinkedList<>(); + MetadataEntry titleMetadata = new MetadataEntry(); + titleMetadata.setKey("title"); + titleMetadata.setValue("Historische Zeitung"); + presetMetadata.add(titleMetadata); + MetadataEntry placeMetadata = new MetadataEntry(); + placeMetadata.setKey("place"); + placeMetadata.setValue("Hamburg"); + presetMetadata.add(placeMetadata); + MetadataEntry authorMetadata = new MetadataEntry(); + authorMetadata.setKey("author"); + authorMetadata.setValue("Hans Meier"); + presetMetadata.add(authorMetadata); + return presetMetadata; + } + +} diff --git a/Kitodo/src/test/java/org/kitodo/selenium/MassImportST.java b/Kitodo/src/test/java/org/kitodo/selenium/MassImportST.java new file mode 100644 index 00000000000..7b868a275bb --- /dev/null +++ b/Kitodo/src/test/java/org/kitodo/selenium/MassImportST.java @@ -0,0 +1,112 @@ +/* + * (c) Kitodo. Key to digital objects e. V. + * + * This file is part of the Kitodo project. + * + * It is licensed under GNU General Public License version 3 or later. + * + * For the full copyright and license information, please read the + * GPL3-License.txt file that was distributed with this source code. + */ + +package org.kitodo.selenium; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.kitodo.MockDatabase; +import org.kitodo.constants.StringConstants; +import org.kitodo.selenium.testframework.BaseTestSelenium; +import org.kitodo.selenium.testframework.Browser; +import org.kitodo.selenium.testframework.Pages; +import org.kitodo.selenium.testframework.pages.MassImportPage; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +public class MassImportST extends BaseTestSelenium { + + private static final String ID = "ID"; + private static final String TITLE = "Title"; + private static final String PLACE = "Place"; + private static final List METADATA_KEYS = Arrays.asList(ID, TITLE, PLACE); + private static File csvUploadFile; + private static MassImportPage massImportPage; + private static final String CSV_UPLOAD_FILENAME = "test_import"; + private static final String CSV_UPLOAD_FILE_EXTENSION = ".csv"; + private static final String CSV_CELL_SELECTOR = "#editForm\\:recordsTable_data tr .ui-cell-editor-output"; + + @BeforeClass + public static void setup() throws Exception { + massImportPage = Pages.getMassImportPage(); + csvUploadFile = createCsvFile(); + MockDatabase.insertMappingFiles(); + MockDatabase.insertImportConfigurations(); + } + + @Before + public void login() throws Exception { + Pages.getLoginPage().goTo().performLoginAsAdmin(); + Pages.getProjectsPage().goTo(); + Pages.getProjectsPage().clickMassImportAction(); + } + + @After + public void logout() throws Exception { + Pages.getTopNavigation().logout(); + if (Browser.isAlertPresent()) { + Browser.getDriver().switchTo().alert().accept(); + } + } + + @AfterClass + public static void cleanup() throws IOException { + deleteCsvFile(); + } + + /** + * Tests whether uploaded CSV files in mass import form are parsed correctly or not. + */ + @Test + public void handleCsvFileUpload() throws InterruptedException { + massImportPage.uploadTestCsvFile(csvUploadFile.getAbsolutePath()); + Thread.sleep(Browser.getDelayAfterLogout()); + List csvRows = Browser.getDriver().findElement(By.id("editForm:recordsTable_data")) + .findElements(By.tagName("tr")); + Assert.assertEquals("CSV file not parsed correctly", 3, csvRows.size()); + List csvCells = Browser.getDriver().findElements(By.cssSelector(CSV_CELL_SELECTOR)); + Assert.assertEquals("CSV lines should not be segmented correctly into multiple cells when using wrong CSV " + + "separator", 3, csvCells.size()); + massImportPage.updateSeparator(StringConstants.COMMA_DELIMITER.trim()); + List updatedCsvCells = Browser.getDriver().findElements(By.cssSelector(CSV_CELL_SELECTOR)); + Assert.assertEquals("CSV lines should be segmented correctly into multiple cells when using correct CSV " + + "separator", 9, updatedCsvCells.size()); + } + + private static File createCsvFile() throws IOException { + File csvFile = File.createTempFile(CSV_UPLOAD_FILENAME, CSV_UPLOAD_FILE_EXTENSION); + try (FileWriter writer = new FileWriter(csvFile)) { + writer.write(String.join(StringConstants.COMMA_DELIMITER, METADATA_KEYS) + "\n"); + writer.write("123, Band 1, Hamburg\n"); + writer.write("456, Band 2, Dresden\n"); + writer.write("789, Band 3, Berlin"); + } + return csvFile; + } + + private static void deleteCsvFile() throws IOException { + boolean successfullyDeleted = csvUploadFile.delete(); + if (!successfullyDeleted) { + throw new IOException(String.format("Error deleting CSV test file '%s'", csvUploadFile.getName())); + } + } + +} diff --git a/Kitodo/src/test/java/org/kitodo/selenium/testframework/Pages.java b/Kitodo/src/test/java/org/kitodo/selenium/testframework/Pages.java index 292ce9cf456..8fe9d3e6dd7 100644 --- a/Kitodo/src/test/java/org/kitodo/selenium/testframework/Pages.java +++ b/Kitodo/src/test/java/org/kitodo/selenium/testframework/Pages.java @@ -21,6 +21,7 @@ import org.kitodo.selenium.testframework.pages.ImportConfigurationEditPage; import org.kitodo.selenium.testframework.pages.LdapGroupEditPage; import org.kitodo.selenium.testframework.pages.LoginPage; +import org.kitodo.selenium.testframework.pages.MassImportPage; import org.kitodo.selenium.testframework.pages.MetadataEditorPage; import org.kitodo.selenium.testframework.pages.PostLoginChecksPage; import org.kitodo.selenium.testframework.pages.ProcessEditPage; @@ -161,4 +162,8 @@ public static UsersPage getUsersPage() throws InstantiationException, IllegalAcc public static CalendarPage getCalendarPage() throws InstantiationException, IllegalAccessException { return getPage(CalendarPage.class); } + + public static MassImportPage getMassImportPage() throws IllegalAccessException, InstantiationException { + return getPage(MassImportPage.class); + } } diff --git a/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/MassImportPage.java b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/MassImportPage.java new file mode 100644 index 00000000000..716da67f416 --- /dev/null +++ b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/MassImportPage.java @@ -0,0 +1,61 @@ +/* + * (c) Kitodo. Key to digital objects e. V. + * + * This file is part of the Kitodo project. + * + * It is licensed under GNU General Public License version 3 or later. + * + * For the full copyright and license information, please read the + * GPL3-License.txt file that was distributed with this source code. + */ + +package org.kitodo.selenium.testframework.pages; + +import org.kitodo.selenium.testframework.Browser; +import org.openqa.selenium.By; + +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; + +public class MassImportPage extends Page { + private static final String CATALOG_SELECTION = "editForm:catalogueSelect"; + private static final String RECORDS_TABLE = "editForm:recordsTable"; + private static final String SELECT_FILE_BUTTON_BAR = ".ui-fileupload-buttonbar .ui-button"; + private static final String UPLOAD_FILE_INPUT = "editForm:csvFileUpload_input"; + private static final String GBV = "GBV"; + private static final String CSV_SEPARATOR = "editForm:csvSeparator"; + + public MassImportPage() { + super("pages/massImport.jsf"); + } + + @Override + public MassImportPage goTo() throws Exception { + return null; + } + + public void uploadTestCsvFile(String filepath) { + clickElement(Browser.getDriver().findElement(By.id(CATALOG_SELECTION))); + clickElement(Browser.getDriver().findElement(By.cssSelector("li[data-label='" + GBV + "']"))); + Browser.getDriver().findElement(By.id(UPLOAD_FILE_INPUT)).sendKeys(filepath); + await("Wait for 'Upload' button to become displayed").pollDelay(300, TimeUnit.MILLISECONDS) + .atMost(3, TimeUnit.SECONDS).ignoreExceptions().until(() -> Browser.getDriver() + .findElements(By.cssSelector(SELECT_FILE_BUTTON_BAR)).get(1).isDisplayed()); + Browser.getDriver().findElements(By.cssSelector(SELECT_FILE_BUTTON_BAR)).get(1).click(); + } + + public void updateSeparator(String separator) { + await("Wait for CSV separator menu to be displayed").pollDelay(300, TimeUnit.MILLISECONDS) + .atMost(3, TimeUnit.SECONDS).ignoreExceptions().until(() -> Browser.getDriver() + .findElement(By.id(CSV_SEPARATOR)).isDisplayed()); + Browser.getDriver().findElement(By.id(CSV_SEPARATOR)).click(); + await("Wait for CSV separator menu option to be displayed").pollDelay(300, TimeUnit.MILLISECONDS) + .atMost(3, TimeUnit.SECONDS).ignoreExceptions().until(() -> Browser.getDriver() + .findElement(By.cssSelector("li[data-label='" + separator + "']")).isDisplayed()); + Browser.getDriver().findElement(By.cssSelector("li[data-label='" + separator + "']")).click(); + await("Wait for records table to update").pollDelay(300, TimeUnit.MILLISECONDS) + .atMost(3, TimeUnit.SECONDS).ignoreExceptions().until(() -> Browser.getDriver() + .findElement(By.id(RECORDS_TABLE)).isDisplayed()); + } +} diff --git a/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/ProjectsPage.java b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/ProjectsPage.java index ef3c8f300c3..c7af6400aed 100644 --- a/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/ProjectsPage.java +++ b/Kitodo/src/test/java/org/kitodo/selenium/testframework/pages/ProjectsPage.java @@ -43,6 +43,8 @@ public class ProjectsPage extends Page { private static final String IMPORT_CONFIGURATIONS_TABLE = "configurationTable"; private static final String MAPPING_FILE_TABLE = "mappingTable"; private static final String MAPPING_FILE_FORMAT_DIALOG = "mappingFileFormatsDialog"; + private static final String FIRST_TEMPLATE = "First template"; + private static final String MASS_IMPORT_LINK = "a.ui-commandlink:has(i.fa-stack-overflow)"; @SuppressWarnings("unused") @FindBy(id = PROJECTS_TAB_VIEW) @@ -656,4 +658,41 @@ public void toggleHiddenTemplates() { .atMost(3, TimeUnit.SECONDS) .until(() -> filterMenu.isEnabled()); } + + /** + * Go to mass import page for a project and select appropriate template. + */ + public void clickMassImportAction() { + // click "mass import" icon + List massImportLinks = Browser.getDriver().findElementsByCssSelector(MASS_IMPORT_LINK); + assert(!massImportLinks.isEmpty()); + WebElement massImportLink = massImportLinks.get(0); + massImportLink.click(); + + // open template selection menu + WebElement templateSelection = Browser.getDriver().findElement(By.id("selectTemplateForm:templateMenu")); + await("Wait for 'template selection dialog' to be displayed").pollDelay(300, TimeUnit.MILLISECONDS) + .atMost(3, TimeUnit.SECONDS).ignoreExceptions().until(templateSelection::isDisplayed); + templateSelection.click(); + + // select template + await("Wait for 'template pull down menu' to be displayed") + .pollDelay(1, TimeUnit.SECONDS) + .pollInterval(1, TimeUnit.SECONDS) + .atMost(3, TimeUnit.SECONDS).ignoreExceptions() + .until(() -> Browser.getDriver() + .findElement(By.cssSelector("li[data-label='" + FIRST_TEMPLATE + "']")).isDisplayed()); + Browser.getDriver() + .findElement(By.cssSelector("li[data-label='" + FIRST_TEMPLATE + "']")).click(); + + // submit template selection + await("Wait for 'select button' to become displayed") + .pollDelay(1, TimeUnit.SECONDS) + .pollInterval(1, TimeUnit.SECONDS) + .atMost(3, TimeUnit.SECONDS).ignoreExceptions() + .until(() -> Browser.getDriver() + .findElement(By.id("selectTemplateForm:setTemplateButton")).isEnabled()); + Browser.getDriver() + .findElement(By.id("selectTemplateForm:setTemplateButton")).click(); + } }