From 491fdfb3709fc283a34f28f1b84037cde4619149 Mon Sep 17 00:00:00 2001 From: Victor Alfaro Date: Wed, 18 Sep 2024 20:17:21 -0600 Subject: [PATCH] No issue: adding E2E missing javadoc --- .../main/java/com/dotcms/DummyInterface.java | 8 +- .../src/test/java/com/dotcms/e2e/E2eKeys.java | 6 + .../java/com/dotcms/e2e/E2eTestSuite.java | 19 ++- .../com/dotcms/e2e/browser/BrowserType.java | 13 ++ .../java/com/dotcms/e2e/logging/Logger.java | 71 ++++++++ .../com/dotcms/e2e/page/ContainersPage.java | 103 ++++++++++++ .../com/dotcms/e2e/page/GroupEntries.java | 10 +- .../java/com/dotcms/e2e/page/LoginPage.java | 23 ++- .../com/dotcms/e2e/page/MenuNavigation.java | 7 + .../java/com/dotcms/e2e/page/PagesPage.java | 95 +++++++++++ .../java/com/dotcms/e2e/page/ToolEntries.java | 7 + .../e2e/playwright/PlaywrightSupport.java | 75 +++++++++ .../e2e/service/EnvironmentService.java | 36 ++++ .../java/com/dotcms/e2e/test/BaseE2eTest.java | 62 +++++++ .../dotcms/e2e/test/ContentPagesTests.java | 110 +++++++++++++ .../dotcms/e2e/test/ContentSearchTests.java | 154 ++++++++++++++++++ .../java/com/dotcms/e2e/test/LoginTests.java | 58 +++++-- .../e2e/test/SiteLayoutContainersTests.java | 99 +++++++++++ .../com/dotcms/e2e/util/StdOutErrLog.java | 20 +++ .../com/dotcms/e2e/util/StringToolbox.java | 15 ++ 20 files changed, 964 insertions(+), 27 deletions(-) create mode 100644 e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/ContainersPage.java create mode 100644 e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/PagesPage.java create mode 100644 e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/ContentPagesTests.java create mode 100644 e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/ContentSearchTests.java create mode 100644 e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/SiteLayoutContainersTests.java diff --git a/e2e/dotcms-e2e-java/src/main/java/com/dotcms/DummyInterface.java b/e2e/dotcms-e2e-java/src/main/java/com/dotcms/DummyInterface.java index ec9371012d5c..3b58ccb63ad0 100644 --- a/e2e/dotcms-e2e-java/src/main/java/com/dotcms/DummyInterface.java +++ b/e2e/dotcms-e2e-java/src/main/java/com/dotcms/DummyInterface.java @@ -1,8 +1,10 @@ package com.dotcms; -/* -This interface is here as a placeholder of non test code that is part of the dotcms-e2e module -Without something in main to compile tests will not run. +/** + * This interface is here as a placeholder of not test code that is part of the dotcms-e2e-java module + * Without something in main to compile tests will not run. + * + * @author vico */ public interface DummyInterface { public void aMethod(); diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/E2eKeys.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/E2eKeys.java index dc72cd205616..c8ebfa9f86fd 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/E2eKeys.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/E2eKeys.java @@ -1,5 +1,11 @@ package com.dotcms.e2e; +/** + * This class defines a set of constant keys used in the end-to-end tests for the dotCMS application. + * These keys are used to retrieve configuration values such as URLs, browser types, and user credentials. + * + * @author vico + */ public class E2eKeys { public static final String CI_KEY = "ci"; diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/E2eTestSuite.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/E2eTestSuite.java index c667e05f7353..4eb5dec399c8 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/E2eTestSuite.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/E2eTestSuite.java @@ -1,15 +1,30 @@ package com.dotcms.e2e; +import com.dotcms.e2e.test.ContentPagesTests; +import com.dotcms.e2e.test.ContentSearchTests; import com.dotcms.e2e.test.LoginTests; +import com.dotcms.e2e.test.SiteLayoutContainersTests; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; +/** + * This class defines a test suite for end-to-end tests in the dotCMS application. + * It uses JUnit 5's @Suite and @SelectClasses annotations to specify the test classes + * that should be included in the suite. + * + * To run this suite, simply execute: + *
+ *  ./mvnw -pl :dotcms-e2e-java verify -De2e.test.skip=false -Dit.test=E2eTestSuite
+ * 
+ * + * @author vico + */ @Suite @SelectClasses({ - LoginTests.class/*, + LoginTests.class, ContentPagesTests.class, ContentSearchTests.class, - SiteLayoutContainersTests.class*/ + SiteLayoutContainersTests.class }) public class E2eTestSuite { } diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/browser/BrowserType.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/browser/BrowserType.java index 164dd9ab88c6..803e8eaca0da 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/browser/BrowserType.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/browser/BrowserType.java @@ -2,10 +2,23 @@ import java.util.stream.Stream; +/** + * Enum representing different types of browsers. + * + * This enum provides a method to get a browser type from a string value. + * + * @author vico + */ public enum BrowserType { CHROMIUM, FIREFOX, WEBKIT; + /** + * Returns the BrowserType corresponding to the given string value. + * + * @param value the string representation of the browser type + * @return the BrowserType corresponding to the given value, or null if no match is found + */ public static BrowserType fromString(final String value) { return Stream.of(values()).filter(element -> element.name().equals(value)).findFirst().orElse(null); } diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/logging/Logger.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/logging/Logger.java index 9762cbba6283..620ae8835ed7 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/logging/Logger.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/logging/Logger.java @@ -4,52 +4,123 @@ import java.util.function.Supplier; +/** + * Logger utility class for logging messages with different levels of severity. + * + * This class provides static methods to log info, warn, and error messages. + * + * @author vico + */ public class Logger { private Logger() { } + /** + * Logs an info message. + * + * @param clazz the class from which the log is made + * @param message the message to log + */ public static void info(final Class clazz, final String message) { final org.slf4j.Logger logger = LoggerFactory.getLogger(clazz); logger.info(message); } + /** + * Logs an info message. + * + * @param clazz the class from which the log is made + * @param message the supplier of the message to log + */ public static void info(final Class clazz, final Supplier message) { info(clazz, message.get()); } + /** + * Logs a warning message. + * + * @param clazz the class from which the log is made + * @param message the message to log + */ public static void warn(final Class clazz, final String message) { final org.slf4j.Logger logger = LoggerFactory.getLogger(clazz); logger.warn(message); } + /** + * Logs a warning message. + * + * @param clazz the class from which the log is made + * @param message the supplier of the message to log + */ public static void warn(final Class clazz, final Supplier message) { warn(clazz, message.get()); } + /** + * Logs a warning message with a throwable. + * + * @param clazz the class from which the log is made + * @param message the message to log + * @param throwable the throwable to log + */ public static void warn(final Class clazz, final String message, final Throwable throwable) { final org.slf4j.Logger logger = LoggerFactory.getLogger(clazz); logger.warn(message, throwable); } + /** + * Logs a warning message with a throwable. + * + * @param clazz the class from which the log is made + * @param message the supplier of the message to log + * @param throwable the throwable to log + */ public static void warn(final Class clazz, final Supplier message, final Throwable throwable) { warn(clazz, message.get(), throwable); } + /** + * Logs an error message. + * + * @param clazz the class from which the log is made + * @param message the message to log + */ public static void error(final Class clazz, final String message) { final org.slf4j.Logger logger = LoggerFactory.getLogger(clazz); logger.error(message); } + /** + * Logs an error message. + * + * @param clazz the class from which the log is made + * @param message the supplier of the message to log + */ public static void error(final Class clazz, final Supplier message) { error(clazz, message.get()); } + /** + * Logs an error message with a throwable. + * + * @param clazz the class from which the log is made + * @param message the message to log + * @param throwable the throwable to log + */ public static void error(final Class clazz, final String message, final Throwable throwable) { final org.slf4j.Logger logger = LoggerFactory.getLogger(clazz); logger.error(message, throwable); } + /** + * Logs an error message with a throwable. + * + * @param clazz the class from which the log is made + * @param message the supplier of the message to log + * @param throwable the throwable to log + */ public static void error(final Class clazz, final Supplier message, final Throwable throwable) { error(clazz, message.get(), throwable); } diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/ContainersPage.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/ContainersPage.java new file mode 100644 index 000000000000..2d3b21628506 --- /dev/null +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/ContainersPage.java @@ -0,0 +1,103 @@ +package com.dotcms.e2e.page; + +import com.microsoft.playwright.Locator; +import com.microsoft.playwright.Page; +import com.microsoft.playwright.options.AriaRole; + +/** + * Page class for interacting with the Containers page. + * + * This class provides methods to fill the containers form, find a container by title, + * and execute workflow actions on a container. + * + * @author vico + */ +public class ContainersPage { + + private final Page containersPage; + + public ContainersPage(final Page containersPage) { + this.containersPage = containersPage; + } + + /** + * Fills the containers form with the provided details. + * + * @param title the title of the container + * @param description the description of the container + * @param maxContents the maximum number of contents + * @param contentType the content type + * @param contentTypeCode the content type code + */ + public void fillContainersForm(final String title, + final String description, + final String maxContents, + final String contentType, + final String contentTypeCode) { + containersPage.getByTestId("title").fill(title); + containersPage.getByTestId("description").fill(description); + containersPage.getByTestId("max-contents").fill(maxContents); + containersPage.getByRole(AriaRole.TAB, new Page.GetByRoleOptions().setName("")).click(); + containersPage.getByRole(AriaRole.MENUITEM, + new Page.GetByRoleOptions().setName(contentType)).click(); + containersPage.getByRole(AriaRole.TAB, new Page.GetByRoleOptions().setName(contentType)) + .click(); + containersPage.getByTestId("2a3e91e4-fbbf-4876-8c5b-2233c1739b05") + .getByLabel("Editor content;Press Alt+F1").fill(contentTypeCode + "\n"); + containersPage.getByTestId("saveBtn").click(); + } + + /** + * Finds a container by its title. + * + * @param containerTitle the title of the container to find + * @return the row ID of the container if found, otherwise an empty string + */ + public String findContainer(final String containerTitle) { + String rowId = ""; + + // Locate the table + Locator table = containersPage.locator("tbody"); // Adjust the selector if necessary + + // Locate all rows within the table + Locator rows = table.locator("tr"); + // Iterate through each row + int rowCount = rows.count(); + for (int i = 0; i < rowCount; i++) { + Locator row = rows.nth(i); + + // Locate all cells within the current row + Locator cells = row.locator("td"); + + // Check the content of each cell + int cellCount = cells.count(); + for (int j = 0; j < cellCount; j++) { + String cellText = cells.nth(j).textContent().trim(); + if (cellText.equals(containerTitle)) { + rowId = rows.nth(i).getAttribute("data-testrowid"); + return rowId; + } + } + } + return rowId; + } + + /** + * Executes a workflow action on a container. + * + * @param containerTitle the title of the container + * @param action the workflow action to execute + */ + public void executeContainerWorkflow(final String containerTitle, final String action) { + String rowId = findContainer(containerTitle); + containersPage.getByTestId(rowId) + .getByRole(AriaRole.BUTTON, new Locator.GetByRoleOptions().setName(" p")).click(); + containersPage.getByRole(AriaRole.MENUITEM, new Page.GetByRoleOptions().setName(action)) + .click(); + if (action.equals("Delete")) { + containersPage.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Accept")) + .click(); + } + } + +} diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/GroupEntries.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/GroupEntries.java index fec5750f8e50..8b425896f100 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/GroupEntries.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/GroupEntries.java @@ -1,5 +1,11 @@ package com.dotcms.e2e.page; +/** + * Enum representing group entries for different menus and layouts. + * This enum provides constants for various group entries and a method to retrieve the group string. + * + * @author vico + */ public enum GroupEntries { CONTENT_MENU(":text('format_align_leftContentarrow_drop_up')"), @@ -13,9 +19,9 @@ public enum GroupEntries { } /** - * Get the group entries + * Retrieves the group string. * - * @return the group entries + * @return the group string */ public String getGroup() { return group; diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/LoginPage.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/LoginPage.java index ac8e0495346b..6fa2bad6f1d2 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/LoginPage.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/LoginPage.java @@ -4,6 +4,13 @@ import com.dotcms.e2e.service.EnvironmentService; import com.microsoft.playwright.Page; +/** + * Page class for interacting with the Login page. + * + * This class provides methods to perform login actions and switch the language of the login page. + * + * @author vico + */ public class LoginPage { private static final String USERNAME_LOCATOR = "input[id=inputtext]"; @@ -13,15 +20,16 @@ public class LoginPage { private final Page loginPage; - /** - * Constructor - * - * @param loginPage the page object - */ public LoginPage(final Page loginPage) { this.loginPage = loginPage; } + /** + * Logs in with the provided username and password. + * + * @param user the username + * @param password the password + */ public void login(final String user, final String password) { loginPage.locator(USERNAME_LOCATOR).fill(user); loginPage.locator(PASSWORD_LOCATOR).click(); @@ -29,6 +37,9 @@ public void login(final String user, final String password) { loginPage.getByTestId(LOGIN_BUTTON).click(); } + /** + * Logs in with the default username and password from environment properties. + */ public void successfulLogin() { final EnvironmentService environmentService = EnvironmentService.get(); login( @@ -37,7 +48,7 @@ public void successfulLogin() { } /** - * Switch the language of the login page + * Switches the language of the login page. * * @param language the language to switch to */ diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/MenuNavigation.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/MenuNavigation.java index 92c0cea2cfa1..cbb657a16207 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/MenuNavigation.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/MenuNavigation.java @@ -2,6 +2,13 @@ import com.microsoft.playwright.Page; +/** + * Class for navigating through the menu. + * + * This class provides methods to navigate to different group and tool entries in the menu. + * + * @author vico + */ public class MenuNavigation { private final Page menuNavigation; diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/PagesPage.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/PagesPage.java new file mode 100644 index 000000000000..e622fd436828 --- /dev/null +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/PagesPage.java @@ -0,0 +1,95 @@ +package com.dotcms.e2e.page; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; + +import com.microsoft.playwright.FrameLocator; +import com.microsoft.playwright.Locator; +import com.microsoft.playwright.Page; +import com.microsoft.playwright.options.AriaRole; + +/** + * Page class for interacting with the Pages page. + * + * This class provides methods to fill the pages form, find a page by title, + * and execute workflow actions on a page. + * + * @author vico + */ +public class PagesPage { + + private final Page pagesPage; + + public PagesPage(final Page pagesPage) { + this.pagesPage = pagesPage; + } + + /** + * Fill the Pages form with the given data and template and save it as a draft or publish it + * depending on the action selected (Save/Publish) + * + * @param pagesDetailFrame page detail frame locator + * @param pageTitle page title + * @param template page template + */ + public void fillPagesForm(final String pagesDetailFrame, final String pageTitle, final String template) { + pagesPage.frameLocator(pagesDetailFrame).locator("#titleBox").fill(pageTitle); + pagesPage.frameLocator(pagesDetailFrame).locator("#text60Checkbox").check(); + pagesPage.frameLocator(pagesDetailFrame).locator("#widget_templateSel div").first().click(); + assertThat(pagesPage.frameLocator(pagesDetailFrame).getByText(template)).isVisible(); + pagesPage.frameLocator(pagesDetailFrame).getByText(template).click(); + pagesPage.frameLocator(pagesDetailFrame) + .getByLabel("Content", new FrameLocator.GetByLabelOptions().setExact(true)) + .getByLabel("", new Locator.GetByLabelOptions().setExact(true)).check(); + //Select the WF action (Save/Publish) + pagesPage.frameLocator(pagesDetailFrame).getByText("Publish").click(); + } + + /** + * Find the page in the iframe with the given title and return the row id of the page + * + * @param pageTitle the title of the page to find in the iframe + * @return the row id of the page + */ + public String findPage(final String pageTitle) { + String rowId = ""; + + // Locate the table + Locator table = pagesPage.locator("tbody"); // Adjust the selector if necessary + + // Locate all rows within the table + Locator rows = table.locator("tr"); + // Iterate through each row + int rowCount = rows.count(); + for (int i = 0; i < rowCount; i++) { + Locator row = rows.nth(i); + + // Locate all cells within the current row + Locator cells = row.locator("td"); + + // Check the content of each cell + int cellCount = cells.count(); + for (int j = 0; j < cellCount; j++) { + String cellText = cells.nth(j).textContent().trim(); + if (cellText.equals(pageTitle)) { + rowId = rows.nth(i).getAttribute("id"); + return rowId; + } + } + } + return rowId; + } + + /** + * Execute the action on the page with the given title + * + * @param pageTitle the title of the page to execute the action on + * @param action the action to execute on the page + */ + public void executePagesWorkflow(final String pageTitle, final String action) { + String rowLocator = "#" + "pageActionButton-" + findPage(pageTitle).replaceAll("\\D+", ""); + pagesPage.locator(rowLocator).click(); + assertThat(pagesPage.locator(rowLocator)).isVisible(); + pagesPage.getByRole(AriaRole.MENUITEM, new Page.GetByRoleOptions().setName(action)).click(); + } + +} \ No newline at end of file diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/ToolEntries.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/ToolEntries.java index 782e8541632d..61a1e9c58cd9 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/ToolEntries.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/page/ToolEntries.java @@ -1,5 +1,12 @@ package com.dotcms.e2e.page; +/** + * Enum representing tool entries for different menus and layouts. + * + * This enum provides constants for various tool entries and a method to retrieve the tool string. + * + * @author vico + */ public enum ToolEntries { GETTING_WELCOME("[href='#/starter']"), diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/playwright/PlaywrightSupport.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/playwright/PlaywrightSupport.java index e0312ba7b04e..3cded144b381 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/playwright/PlaywrightSupport.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/playwright/PlaywrightSupport.java @@ -15,6 +15,35 @@ import java.util.Objects; import java.util.stream.Stream; +/** + * Support class for Playwright operations. + * + * This singleton class provides methods to interact with Playwright, including launching browsers, + * creating contexts and pages, and closing resources. + * + * Example usage: + *
+ *  PlaywrightSupport support = PlaywrightSupport.get();
+ *  Playwright playwright = support.playwright();
+ *  Browser browser = support.launchBrowser(playwright);
+ *  Tuple2 contextAndPage = support.createContextAndPage(browser);
+ * 
+ * + * Methods: + *
    + *
  • {@link #get()} - Returns the singleton instance of the support class.
  • + *
  • {@link #playwright()} - Creates a new Playwright instance.
  • + *
  • {@link #isCi()} - Checks if the current environment is a CI environment.
  • + *
  • {@link #getBrowser()} - Retrieves the browser type from the environment properties.
  • + *
  • {@link #launchBrowser(Playwright)} - Launches a browser based on the environment properties.
  • + *
  • {@link #close(AutoCloseable...)} - Closes the provided resources.
  • + *
  • {@link #createContextAndPage(Browser)} - Creates a new browser context and page.
  • + *
  • {@link #resolveBrowser(Playwright, String)} - Resolves the browser type from a string.
  • + *
  • {@link #visibleTimeout(double)} - Creates visibility timeout options for assertions.
  • + *
+ * + * @author vico + */ public class PlaywrightSupport { private static final PlaywrightSupport INSTANCE = new PlaywrightSupport(); @@ -26,23 +55,50 @@ public static PlaywrightSupport get() { private PlaywrightSupport() { } + /** + * Creates a new Playwright instance. + * + * @return a new Playwright instance + */ public Playwright playwright() { return Playwright.create(); } + /** + * Checks if the current environment is a CI environment. + * + * @return true if the current environment is a CI environment, false otherwise + */ public boolean isCi() { return Boolean.parseBoolean(EnvironmentService.get().getProperty(E2eKeys.CI_KEY)); } + /** + * Retrieves the browser type from the environment properties. + * + * @return the browser type as a String + */ public String getBrowser() { return EnvironmentService.get().getProperty(E2eKeys.E2E_BROWSER_KEY); } + /** + * Launches a browser based on the environment properties. + * + * @param playwright the Playwright instance + * @return the launched Browser instance + */ public Browser launchBrowser(final Playwright playwright) { return resolveBrowser(playwright, getBrowser().toUpperCase()) .launch(new com.microsoft.playwright.BrowserType.LaunchOptions().setHeadless(isCi())); } + /** + * Closes the provided resources. + * + * @param stuffToClose the resources to be closed + * @param the type of AutoCloseable resources + */ public void close(C... stuffToClose) { Stream.of(stuffToClose) .filter(Objects::nonNull) @@ -54,12 +110,25 @@ public void close(C... stuffToClose) { ex))); } + /** + * Creates a new browser context and page. + * + * @param browser the Browser instance + * @return a tuple containing the BrowserContext and Page + */ public Tuple2 createContextAndPage(final com.microsoft.playwright.Browser browser) { final BrowserContext context = browser.newContext(); final Page page = context.newPage(); return new Tuple2<>(context, page); } + /** + * Resolves the browser type from a string. + * + * @param playwright the Playwright instance + * @param browser the browser type as a string + * @return the resolved BrowserType + */ public com.microsoft.playwright.BrowserType resolveBrowser(final Playwright playwright, final String browser) { final com.microsoft.playwright.BrowserType resolved; switch (BrowserType.fromString(browser)) { @@ -77,6 +146,12 @@ public com.microsoft.playwright.BrowserType resolveBrowser(final Playwright play return resolved; } + /** + * Creates visibility timeout options for assertions. + * + * @param timeout the timeout value in milliseconds + * @return the visibility timeout options + */ public LocatorAssertions.IsVisibleOptions visibleTimeout(final double timeout) { return new LocatorAssertions.IsVisibleOptions().setTimeout(timeout); } diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/service/EnvironmentService.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/service/EnvironmentService.java index 3d219e959291..0bb8d6a1c895 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/service/EnvironmentService.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/service/EnvironmentService.java @@ -6,6 +6,29 @@ import java.io.IOException; import java.util.Properties; +/** + * Service class for managing environment properties. + * + * This singleton class loads properties from a specified environment file and provides methods + * to retrieve these properties. If a property is not found in the file, it attempts to retrieve + * it from the system environment variables. + * + * Example usage: + *
+ *  String value = EnvironmentService.get().getProperty("someKey", "defaultValue");
+ * 
+ * + * Methods: + *
    + *
  • {@link #get()} - Returns the singleton instance of the service.
  • + *
  • {@link #getProperty(String, String)} - Retrieves a property value with a default.
  • + *
  • {@link #getProperty(String)} - Retrieves a property value without a default.
  • + *
+ * + * The {@link StringToolbox} class is used to convert camelCase keys to snake_case for environment variable lookup. + * + * @author vico + */ public class EnvironmentService { private static final EnvironmentService INSTANCE = new EnvironmentService(); @@ -29,6 +52,13 @@ private EnvironmentService() { } } + /** + * Retrieves a property value with a default. + * + * @param key the property key + * @param defaultValue the default value if the property is not found + * @return the property value or the default value if not found + */ public String getProperty(final String key, final String defaultValue) { final String propValue = props.getProperty(key); if (StringUtils.isNotBlank(propValue)) { @@ -38,6 +68,12 @@ public String getProperty(final String key, final String defaultValue) { return StringUtils.defaultString(System.getenv(StringToolbox.camelToSnake(key)), defaultValue); } + /** + * Retrieves a property value without a default. + * + * @param key the property key + * @return the property value or null if not found + */ public String getProperty(final String key) { return getProperty(key, null); } diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/BaseE2eTest.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/BaseE2eTest.java index 18c406ebbc33..a226177e5e7f 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/BaseE2eTest.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/BaseE2eTest.java @@ -13,6 +13,33 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +/** + * Base class for end-to-end tests. + * + * This class provides setup and teardown methods for Playwright browser contexts and pages, + * as well as utility methods for retrieving environment properties and navigating to the base URL. + * + * Example usage: + *
+ *  public class MyE2eTest extends BaseE2eTest {
+ *      // Test methods here
+ *  }
+ * 
+ * + * Methods: + *
    + *
  • {@link #launchBrowser()} - Launches the Playwright browser.
  • + *
  • {@link #closeBrowser()} - Closes the Playwright browser.
  • + *
  • {@link #createContextAndPage()} - Creates a new browser context and page.
  • + *
  • {@link #closeContextAndPage()} - Closes the current browser context and page.
  • + *
  • {@link #getProperty(String)} - Retrieves a property value by key.
  • + *
  • {@link #getProperty(String, String)} - Retrieves a property value by key with a default value.
  • + *
  • {@link #getBaseUrl()} - Retrieves the base URL for the tests.
  • + *
  • {@link #navigateToBaseUrl()} - Navigates to the base URL.
  • + *
+ * + * @author vico + */ public abstract class BaseE2eTest { protected static Playwright playwright; @@ -21,17 +48,26 @@ public abstract class BaseE2eTest { protected BrowserContext context; protected Page page; + /** + * Launches the Playwright browser. + */ @BeforeAll public static void launchBrowser() { playwright = PlaywrightSupport.get().playwright(); browser = PlaywrightSupport.get().launchBrowser(playwright); } + /** + * Closes the Playwright browser. + */ @AfterAll public static void closeBrowser() { PlaywrightSupport.get().close(browser, playwright); } + /** + * Creates a new browser context and page. + */ @BeforeEach void createContextAndPage() { final Tuple2 contextAndPage = PlaywrightSupport.get().createContextAndPage(browser); @@ -39,23 +75,49 @@ void createContextAndPage() { page = contextAndPage._2; } + /** + * Closes the current browser context and page. + */ @AfterEach void closeContextAndPage() { PlaywrightSupport.get().close(page, context); } + /** + * Retrieves a property value by key. + * + * @param key the property key + * @return the property value + */ public String getProperty(final String key) { return EnvironmentService.get().getProperty(key); } + /** + * Retrieves a property value by key with a default value. + * + * @param key the property key + * @param defaultValue the default value if the property is not found + * @return the property value + */ public String getProperty(final String key, final String defaultValue) { return EnvironmentService.get().getProperty(key, defaultValue); } + /** + * Retrieves the base URL for the tests. + * + * @return the base URL + */ public String getBaseUrl() { return getProperty(E2eKeys.E2E_BASE_URL_KEY, E2eKeys.DEFAULT_BASE_URL); } + /** + * Retrieves the base URL for the tests. + * + * @return the base URL + */ public void navigateToBaseUrl() { page.navigate(getBaseUrl()); } diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/ContentPagesTests.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/ContentPagesTests.java new file mode 100644 index 000000000000..0a8376fc148a --- /dev/null +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/ContentPagesTests.java @@ -0,0 +1,110 @@ +package com.dotcms.e2e.test; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; + +import com.dotcms.e2e.page.GroupEntries; +import com.dotcms.e2e.page.LoginPage; +import com.dotcms.e2e.page.MenuNavigation; +import com.dotcms.e2e.page.PagesPage; +import com.dotcms.e2e.page.ToolEntries; +import com.microsoft.playwright.Locator; +import com.microsoft.playwright.Page; +import com.microsoft.playwright.options.AriaRole; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * Test class for content pages. + * + * This class provides test methods to add and remove pages, ensuring the environment is clean for each test case execution. + * + * @author vico + */ +@DisplayName("Pages Testing") +public class ContentPagesTests extends BaseE2eTest { + + private MenuNavigation menuNavigation; + private PagesPage pagesPage; + + @BeforeEach + public void setup() { + final LoginPage loginPage = new LoginPage(page); + menuNavigation = new MenuNavigation(page); + pagesPage = new PagesPage(page); + + page.navigate(getBaseUrl()); + loginPage.successfulLogin(); + assertThat(page.getByRole(AriaRole.IMG)).isVisible(); + } + + /** + * Scenario: Add a new page and validate its creation + * Given the user is on the content pages section + * When the user adds a new page with the title "Testing Page" + * Then the page should be created successfully + * And the page should be visible in the list + */ + @Test + public void test_addPage() throws Exception { + menuNavigation.navigateTo(GroupEntries.CONTENT_MENU, ToolEntries.CONTENT_PAGES); + assertThat(page.getByText("ContentPages")).isVisible(); + assertThat(page.locator("span").filter(new Locator.FilterOptions().setHasText("Bookmarks")) + .first()).isVisible(); + + boolean exist = page.getByText("Testing Page").isVisible(); + if (exist) { + removePage(); + } + + page.getByTestId("createPageButton").click(); + page.getByText("description Page").click(); + + final String pagesDetailFrame = "iframe[name='detailFrame']"; + // fill the page form + pagesPage.fillPagesForm(pagesDetailFrame, "Testing Page", "Default Template"); + // validations + assertThat(page.locator("li") + .filter(new Locator.FilterOptions().setHasText("Testing Page"))).isVisible(); + } + + + /** + * Scenario: Remove a page to clean up the environment + * Given the user is on the content pages section + * When the user removes the page with the title "Testing Page" + * Then the page should be removed successfully + * And the page should no longer be visible in the list + */ + @Test + public void test_removePage() throws Exception { + menuNavigation.navigateTo(GroupEntries.CONTENT_MENU, ToolEntries.CONTENT_PAGES); + assertThat(page.getByText("ContentPages")).isVisible(); + page.getByTestId("dot-pages-listing-header__keyword-input").click(); + + boolean exist = page.getByText("Testing Page").isVisible(); + if (!exist) { + addPage(); + } + + //menuNavigation.navigateTo(GroupEntries.CONTENT_MENU, ToolEntries.CONTENT_PAGES); + assertThat(page.getByText("ContentPages")).isVisible(); + page.getByTestId("dot-pages-listing-header__keyword-input").click(); + //execute the unpublish action + pagesPage.executePagesWorkflow("Testing Page", "Unpublish"); + assertThat(page.getByText("Workflow executed")).isVisible(); + assertThat(page.getByText("Workflow executed")).not().isVisible(); + //execute the archived action + pagesPage.executePagesWorkflow("Testing Page", "Archive"); + assertThat(page.getByText("Workflow executed")).isVisible(); + assertThat(page.getByText("Workflow executed")).not().isVisible(); + page.locator("p-checkbox div").nth(2).click(); + // Enable the show archived check + assertThat(page.getByRole(AriaRole.COLUMNHEADER, + new Page.GetByRoleOptions().setName("Status"))).isVisible(); + //execute the delete action + pagesPage.executePagesWorkflow("Testing Page", "Delete"); + assertThat(page.getByText("Workflow executed")).isVisible(); + } + +} diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/ContentSearchTests.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/ContentSearchTests.java new file mode 100644 index 000000000000..a336258190af --- /dev/null +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/ContentSearchTests.java @@ -0,0 +1,154 @@ +package com.dotcms.e2e.test; + +import com.dotcms.e2e.page.LoginPage; +import com.dotcms.e2e.page.MenuNavigation; +import com.microsoft.playwright.FrameLocator; +import com.microsoft.playwright.Locator; +import com.microsoft.playwright.options.AriaRole; +import com.microsoft.playwright.options.MouseButton; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import com.dotcms.e2e.page.GroupEntries; +import com.dotcms.e2e.page.ToolEntries; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; + +/** + * Test class for content search. + * + * This class provides test methods to add and remove content, ensuring the environment is clean for each test case execution. + * + * @author + */ +@SuppressWarnings("deprecation") +@DisplayName("Content Search testing") +public class ContentSearchTests extends BaseE2eTest { + + private LoginPage loginPage; + private MenuNavigation menuNavigation; + + @BeforeEach + public void setup() { + loginPage = new LoginPage(page); + menuNavigation = new MenuNavigation(page); + } + + /** + * Scenario: Add a new content and validate its creation + * Given the user is on the content search section + * When the user adds a new content with the title "Demo Test" + * Then the content should be created successfully + * And the content should be visible in the list + */ + @Test + public void test_addContent() { + page.navigate(getBaseUrl()); + loginPage.successfulLogin(); + assertThat( page.getByRole(AriaRole.IMG)).isVisible(); + + // Navigate to some specific portlet + menuNavigation.navigateTo(GroupEntries.CONTENT_MENU, ToolEntries.CONTENT_SEARCH); + + // Wait until the contents table is loaded + final String mainFrame = "iframe[id='detailFrame']"; + assertThat(page.frameLocator(mainFrame).locator("[id=nextDiv]")).isVisible(); + + // Delete content if it exists + deleteContentIfExist(mainFrame); + + //Click + button + page.frameLocator(mainFrame).locator("[id=dijit_form_DropDownButton_0]").click(); + assertThat(page.frameLocator(mainFrame).locator("[id=dijit_MenuItem_2_text]")).isEnabled(); + + // Select Add New Content + page.frameLocator(mainFrame).first().locator("[id=dijit_MenuItem_2_text]").click(); + assertThat(page.frameLocator(mainFrame).locator("[id=sType799f176a-d32e-4844-a07c-1b5fcd107578]")).isVisible(); + + //Select Blog + page.frameLocator(mainFrame).locator("[id=sType799f176a-d32e-4844-a07c-1b5fcd107578]").click(); + + final String contentDetailFrame = "dot-iframe-dialog iframe[id='detailFrame']"; + assertThat(page.frameLocator(contentDetailFrame).locator("#contentHost_field")).isVisible(); + fillContentForm(contentDetailFrame); + assertThat(page.frameLocator(mainFrame).locator("[id=dijit_MenuItem_2_text]")).isEnabled(); + + //Validate the content was created successfully + page.frameLocator(mainFrame).locator("#widget_structure_inode div").first().click(); + page.frameLocator(mainFrame).locator("[id=structure_inode_popup3]").click(); + //page.frameLocator(mainFrame).getByRole(AriaRole.OPTION, new FrameLocator.GetByRoleOptions().setName("All")).click(); + assertThat(page.frameLocator(mainFrame).locator("[id=results_table]")).containsText("Demo Test" + "en-us" + "lock_open"); + + + //Archive and Destroy the new content + deleteContentIfExist(mainFrame); + } + + private void fillContentForm(final String contentDetailFrame) { + // Fill the blog content form + page.frameLocator(contentDetailFrame).locator("[id=title]").type("Demo Test"); + page.frameLocator(contentDetailFrame).locator("[id=dijit_form_ComboButton_0_arrow]").click(); + page.frameLocator(contentDetailFrame).locator("[id=dijit_MenuItem_1_text]").click(); + + // Relate to author + assertThat(page.frameLocator(contentDetailFrame).locator("[id=dijit_Dialog_4]").getByText("Search x")).isVisible(); + page.frameLocator(contentDetailFrame).locator("[id=dijit_form_CheckBox_0]").check(); + page.frameLocator(contentDetailFrame).locator("[id=dijit_form_Button_14]").click(); + + //Continue the form + assertThat(page.frameLocator(contentDetailFrame).locator("[id=teaser]")).isVisible(); + page.frameLocator(contentDetailFrame).locator("[id=teaser]").type("This is a demo content "); + + //Date field + page.frameLocator(contentDetailFrame).locator("[id=postingDateDate]").fill("8/25/2023"); + + //Adding tags + page.frameLocator(contentDetailFrame).locator("#tags").click(); + page.frameLocator(contentDetailFrame).locator("#tags").fill("tag1"); + page.frameLocator(contentDetailFrame).locator("#tags").press("Enter"); + page.frameLocator(contentDetailFrame).locator("#tags").fill("tag2"); + page.frameLocator(contentDetailFrame).locator("#tags").press("Enter"); + + //Adding content to blog field + page.frameLocator(contentDetailFrame).locator("#block-editor-blogContent div").nth(1).fill("test1"); + + //Set image + // page.frameLocator(contentDetailFrame).getByTestId("choose-file-btn").setInputFiles(Paths.get("files/logo.png")); + + //Select the WF action (Save/Publish) + page.frameLocator(contentDetailFrame).getByText("Save and Publish").click(); + assertThat(page.frameLocator(contentDetailFrame).getByText("Lock for Editing")).isVisible(); + //assertThat(page.getByText("The content was saved successfully but cannot be published because it is schedule")).isVisible(); + assertThat(page.frameLocator(contentDetailFrame).getByText("Content saved")).isVisible(); + assertThat(page.frameLocator(contentDetailFrame).getByText("Content saved")).not().isVisible(); + + //Close the content iframe + page.getByTestId("close-button").click(); + } + + private void deleteContentIfExist(final String mainFrame) { + if (page.frameLocator(mainFrame).getByText("Demo Test").count() <= 0) { + System.out.println("Validating if content exist... Content does not exist"); + return; + } + + page.frameLocator(mainFrame).getByText("Demo Test").first().click(new Locator.ClickOptions().setButton(MouseButton.RIGHT)); + page.frameLocator(mainFrame).getByRole(AriaRole.MENUITEM).getByText("Archive").click(); + // Validate the Workflow Execution Status + assertThat(page.frameLocator(mainFrame).getByText("Workflow executed")).isEnabled(); + assertThat(page.frameLocator(mainFrame).getByText("Workflow executed")).not().isVisible(); + // Go to archived contents and Destroy if exist + page.frameLocator(mainFrame).locator("#widget_structure_inode div").first().click(); + page.frameLocator(mainFrame).getByText("file_copyBlog").click(); + page.frameLocator(mainFrame).getByRole(AriaRole.LINK, new FrameLocator.GetByRoleOptions().setName("Advanced")).click(); + page.frameLocator(mainFrame).locator("#widget_showingSelect div").first().click(); + page.frameLocator(mainFrame).getByRole(AriaRole.OPTION, new FrameLocator.GetByRoleOptions().setName("Archived")).click(); + page.frameLocator(mainFrame).getByText("Demo Test").first().click(new Locator.ClickOptions().setButton(MouseButton.RIGHT)); + page.frameLocator(mainFrame).getByRole(AriaRole.MENUITEM).getByText("Destroy").click(); + + //Validate the workflow has been executed + assertThat(page.frameLocator(mainFrame).getByText("Workflow executed")).isEnabled(); + assertThat(page.frameLocator(mainFrame).getByText("Workflow executed")).not().isVisible(); + } +} + diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/LoginTests.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/LoginTests.java index 68467b4deedc..79f108484cf5 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/LoginTests.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/LoginTests.java @@ -9,6 +9,14 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +/** + * Test class for login functionality. + * + * This class provides test methods to validate the login functionality with different scenarios. + * Ensures the environment is set up before each test case execution. + * + * @author vico + */ @DisplayName("Login portlet tests") public class LoginTests extends BaseE2eTest { @@ -21,64 +29,86 @@ public void setup() { } /** - * Test the login functionality with the default user + * Scenario: Successful login with the default user + * Given the user is on the login page + * When the user logs in with valid credentials + * Then the user should be logged in successfully + * And the user should see the dashboard */ @Test - public void loginSuccess() { + public void test_loginSuccess() { loginPage.successfulLogin(); assertThat(page.getByRole(AriaRole.IMG)).isVisible(); } /** - * Test the login functionality with a wrong user + * Scenario: Unsuccessful login with a wrong user + * Given the user is on the login page + * When the user logs in with an invalid username + * Then the user should see an error message */ @Test - public void loginWrongUser() { + public void test_loginWrongUser() { loginPage.login("jon.snow@got.com", "admin"); assertThat(page.getByTestId("message")).isVisible(); } /** - * Test the login functionality with a wrong password + * Scenario: Unsuccessful login with a wrong password + * Given the user is on the login page + * When the user logs in with an invalid password + * Then the user should see an error message */ @Test - public void loginWrongPass() { + public void test_loginWrongPass() { loginPage.login("admin@dotcms.com", "winteriscoming"); assertThat(page.getByTestId("message")).isVisible(PlaywrightSupport.get().visibleTimeout(10000)); } /** - * Test the login functionality with Spanish language + * Scenario: Successful login with Spanish language + * Given the user is on the login page + * When the user switches the language to Spanish + * Then the user should see the login page in Spanish */ @Test - public void loginSpanishLanguage() { + public void test_loginSpanishLanguage() { loginPage.switchLanguage("español (España)"); assertThat(page.getByText("¡Bienvenido!")).isVisible(); } /** - * Test the login functionality with Italian language + * Scenario: Successful login with Italian language + * Given the user is on the login page + * When the user switches the language to Italian + * Then the user should see the login page in Italian */ @Test - public void loginItalianLanguage() { + public void test_loginItalianLanguage() { loginPage.switchLanguage("italiano (Italia)"); assertThat(page.getByText("Benvenuto! ")).isVisible(); } /** - * Test the login functionality with French language + * Scenario: Successful login with French language + * Given the user is on the login page + * When the user switches the language to French + * Then the user should see the login page in French */ @Test - public void loginFrenchLanguage() { + public void test_loginFrenchLanguage() { loginPage.switchLanguage("français (France)"); assertThat(page.getByText("Bienvenue !")).isVisible(); } /** - * Test the login functionality with Dutch language + * Scenario: Successful login with Dutch language + * Given the user is on the login page + * When the user switches the language to Dutch + * Then the user should see the login page in Dutch */ @Test - public void loginDutchLanguage() { + public void test_loginDutchLanguage() { loginPage.switchLanguage("Deutsch (Deutschland)"); assertThat(page.getByText("Willkommen! ")).isVisible(); } diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/SiteLayoutContainersTests.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/SiteLayoutContainersTests.java new file mode 100644 index 000000000000..a5907141afa5 --- /dev/null +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/test/SiteLayoutContainersTests.java @@ -0,0 +1,99 @@ +package com.dotcms.e2e.test; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; + +import com.dotcms.e2e.page.ContainersPage; +import com.dotcms.e2e.page.GroupEntries; +import com.dotcms.e2e.page.LoginPage; +import com.dotcms.e2e.page.MenuNavigation; +import com.dotcms.e2e.page.ToolEntries; +import com.microsoft.playwright.Page; +import com.microsoft.playwright.options.AriaRole; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * Test class for site layout containers. + * + * This class provides test methods to add and remove containers, ensuring the environment is clean for each test case execution. + * + * @author vico + */ + @DisplayName("Containers Testing") +public class SiteLayoutContainersTests extends BaseE2eTest { + + private LoginPage loginPage; + private MenuNavigation menuNavigation; + private ContainersPage containersPage; + + @BeforeEach + public void setup() { + loginPage = new LoginPage(page); + menuNavigation = new MenuNavigation(page); + containersPage = new ContainersPage(page); + + navigateToBaseUrl(); + loginPage.successfulLogin(); + assertThat(page.getByRole(AriaRole.IMG)).isVisible(); + } + + /** + * Scenario: Add a new container and validate its creation + * Given the user is on the site layout containers section + * When the user adds a new container with the title "test-container" + * Then the container should be created successfully + * And the container should be visible in the list + * + * @throws Exception if an error occurs + */ + @Test + public void addContainer() throws Exception { + //Validates if exists, and delete + boolean exist = page.getByText("test-container").isVisible(); + if (exist) { + deleteContainer(); + } + + menuNavigation.navigateTo(GroupEntries.SITE_LAYOUT, ToolEntries.LAYOUT_CONTAINERS); + assertThat(page.getByText("Site LayoutContainers")).isVisible(); + page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(" p")).click(); + containersPage.fillContainersForm("test-container", + "this is a container created by the automated test", "2", "Rich Text", + "$!{dotContentMap.title}\n" + "$!{dotContentMap.body}"); + assertThat(page.getByText("test-container").first()).isVisible(); + } + + /** + * Scenario: Remove a container to clean up the environment + * Given the user is on the site layout containers section + * When the user removes the container with the title "test-container" + * Then the container should be removed successfully + * And the container should no longer be visible in the list + * + * @throws Exception if an error occurs + */ + @Test + public void deleteContainer() throws Exception { + menuNavigation.navigateTo(GroupEntries.SITE_LAYOUT, ToolEntries.LAYOUT_CONTAINERS); + assertThat(page.getByText("Site LayoutContainers")).isVisible(); + + //Validates if exists, if not create a new one + boolean exist = page.getByText("test-container").isVisible(); + if (!exist) { + addContainer(); + } + + assertThat(page.getByText("test-container")).isVisible(); + containersPage.executeContainerWorkflow("test-container", "Unpublish"); + assertThat(page.getByText("Container unpublished")).isEnabled(); + assertThat(page.getByText("test-container").first()).isVisible(); + containersPage.executeContainerWorkflow("test-container", "Archive"); + assertThat(page.getByText("Container archived")).isEnabled(); + page.getByText("Show Archived").click(); + assertThat(page.getByText("test-container").first()).isVisible(); + containersPage.executeContainerWorkflow("test-container", "Delete"); + assertThat(page.getByText("Container deleted")).isEnabled(); + } + +} \ No newline at end of file diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/util/StdOutErrLog.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/util/StdOutErrLog.java index 6440f8cd9ed0..44bea9a4b4a5 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/util/StdOutErrLog.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/util/StdOutErrLog.java @@ -4,13 +4,33 @@ import java.io.PrintStream; +/** + * This class provides utility methods to redirect the standard output and error streams + * to a custom logging mechanism. + * + * The main purpose of this class is to tie the System.out and System.err streams to a logger, + * so that all output can be captured and logged appropriately. + * + * The {@link Logger} class is used to log the messages. + * + * @author vico + */ public class StdOutErrLog { + /** + * Redirects System.out and System.err to the logger. + */ public static void tieSystemOutAndErrToLog() { System.setOut(createLoggingProxy(System.out)); System.setErr(createLoggingProxy(System.err)); } + /** + * Creates a proxy for the given PrintStream that logs all output. + * + * @param realPrintStream the original PrintStream to be proxied + * @return a new PrintStream that logs all output + */ public static PrintStream createLoggingProxy(final PrintStream realPrintStream) { return new PrintStream(realPrintStream) { public void print(final String string) { diff --git a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/util/StringToolbox.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/util/StringToolbox.java index f869fef3ed73..4325a93dd9a6 100644 --- a/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/util/StringToolbox.java +++ b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/util/StringToolbox.java @@ -1,10 +1,25 @@ package com.dotcms.e2e.util; +/** + * Utility class for string manipulation methods. + * + * This class provides static methods to perform common string transformations. + * It is designed to be used as a utility class and therefore has a private constructor + * to prevent instantiation. + * + * @author vico + */ public class StringToolbox { private StringToolbox() { } + /** + * Converts a camelCase string to snake_case. + * + * @param str the camelCase string to be converted + * @return the converted snake_case string + */ public static String camelToSnake(String str) { return str.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase(); }