From 15a0421ac4f5fcd6beb42397243da8640c107365 Mon Sep 17 00:00:00 2001 From: Victor Alfaro Date: Wed, 25 Sep 2024 15:44:02 -0600 Subject: [PATCH] feat(e2e): Introducing E2E tests to the CICD pipeline for both maven modules: `dotcms-e2e-java` and `dotcms-e2e-node` (#30071) Pipeline will run in a parallel way both maven E2E modules and adding test results to the test phase life cycle. For the moment E2E tests will run in regular PR-check as well. Refs: #29846 --- .github/filters.yaml | 4 +- .github/workflows/cicd_1-pr.yml | 2 + .github/workflows/cicd_3-trunk.yml | 1 + .github/workflows/cicd_comp_test-phase.yml | 39 ++++++++++++- dotcms-postman/index.js | 1 - e2e/dotcms-e2e-java/pom.xml | 41 +++++++++---- .../java/com/dotcms/e2e/E2eTestSuite.java | 4 +- .../e2e/playwright/PlaywrightSupport.java | 20 ++++++- .../e2e/service/EnvironmentService.java | 7 ++- .../dotcms/e2e/test/ContentPagesTests.java | 6 +- .../java/com/dotcms/e2e/test/LoginTests.java | 2 +- .../com/dotcms/e2e/util/StringToolbox.java | 2 +- .../frontend/playwright.config.ts | 9 ++- e2e/dotcms-e2e-node/pom.xml | 57 ++++++++++++++----- justfile | 6 +- 15 files changed, 159 insertions(+), 42 deletions(-) diff --git a/.github/filters.yaml b/.github/filters.yaml index 7bb7ad599670..7c8af5d27894 100644 --- a/.github/filters.yaml +++ b/.github/filters.yaml @@ -34,7 +34,7 @@ cli: &cli - *full_build_test - *backend -sdk_libs: &sdk_libs +sdk_libs: - 'core-web/libs/sdk/**' jvm_unit_test: @@ -44,4 +44,4 @@ jvm_unit_test: build: - *backend - *cli - - *frontend \ No newline at end of file + - *frontend diff --git a/.github/workflows/cicd_1-pr.yml b/.github/workflows/cicd_1-pr.yml index 239512bdc3dc..87ccaf520c88 100644 --- a/.github/workflows/cicd_1-pr.yml +++ b/.github/workflows/cicd_1-pr.yml @@ -68,6 +68,8 @@ jobs: postman: ${{ needs.initialize.outputs.backend == 'true' }} frontend: ${{ needs.initialize.outputs.frontend == 'true' }} cli: ${{ needs.initialize.outputs.cli == 'true' }} +# TODO: remove this param after testing E2E tests invocation + e2e: true secrets: DOTCMS_LICENSE: ${{ secrets.DOTCMS_LICENSE }} diff --git a/.github/workflows/cicd_3-trunk.yml b/.github/workflows/cicd_3-trunk.yml index 1d0c13796125..51f4b2f7e64b 100644 --- a/.github/workflows/cicd_3-trunk.yml +++ b/.github/workflows/cicd_3-trunk.yml @@ -65,6 +65,7 @@ jobs: with: run-all-tests: ${{ inputs.run-all-tests || false }} artifact-run-id: ${{ needs.initialize.outputs.artifact-run-id }} + e2e: true secrets: DOTCMS_LICENSE: ${{ secrets.DOTCMS_LICENSE }} permissions: diff --git a/.github/workflows/cicd_comp_test-phase.yml b/.github/workflows/cicd_comp_test-phase.yml index 6225c9e05001..7554c16e80aa 100644 --- a/.github/workflows/cicd_comp_test-phase.yml +++ b/.github/workflows/cicd_comp_test-phase.yml @@ -41,6 +41,10 @@ on: required: false type: boolean default: false + e2e: + required: false + type: boolean + default: false secrets: DOTCMS_LICENSE: required: true @@ -154,7 +158,7 @@ jobs: # Postman Tests linux-postman-tests: name: Run Postman Tests - ${{matrix.collection_group}} - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 if: inputs.postman || inputs.run-all-tests strategy: fail-fast: false @@ -175,4 +179,35 @@ jobs: needs-docker-image: true github-token: ${{ secrets.GITHUB_TOKEN }} artifacts-from: ${{ env.ARTIFACT_RUN_ID }} - cleanup-runner: true \ No newline at end of file + cleanup-runner: true + + # E2E Tests + linux-e2e-tests: + name: E2E Tests ${{matrix.suites.name}} + runs-on: ubuntu-24.04 + if: inputs.e2e || inputs.run-all-tests + timeout-minutes: 240 + env: + MAVEN_OPTS: -Xmx2048m + strategy: + fail-fast: false + matrix: + suites: + - { name: "JVM E2E Suite", pathName: "jvme2etestsuite", maven_args: '-Dit.test=E2eTestSuite -Dci=true -pl :dotcms-e2e-java' } + - { name: "Node.js E2E Suite", pathName: "nodee2etestsuite", maven_args: '-De2e.test.env=ci -pl :dotcms-e2e-node' } + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: ./.github/actions/core-cicd/maven-job + with: + stage-name: "E2E ${{ matrix.suites.name }}" + maven-args: "verify -Pcoverage -De2e.test.skip=false ${{ matrix.suites.maven_args}}" + generates-test-results: true + dotcms-license: ${{ secrets.DOTCMS_LICENSE }} + requires-node: true + needs-docker-image: true + github-token: ${{ secrets.GITHUB_TOKEN }} + artifacts-from: ${{ env.ARTIFACT_RUN_ID }} + cleanup-runner: true diff --git a/dotcms-postman/index.js b/dotcms-postman/index.js index e924d35aef6e..932dc81485fe 100644 --- a/dotcms-postman/index.js +++ b/dotcms-postman/index.js @@ -271,7 +271,6 @@ async function main() { if (summaryResults.failures > 0) { console.error('Some collections failed.'); process.exit(0); - //process.exit(1); } } catch (error) { console.error('An error occurred:', error); diff --git a/e2e/dotcms-e2e-java/pom.xml b/e2e/dotcms-e2e-java/pom.xml index 46834db84515..c8633b0c2817 100644 --- a/e2e/dotcms-e2e-java/pom.xml +++ b/e2e/dotcms-e2e-java/pom.xml @@ -150,6 +150,31 @@ true + + org.codehaus.mojo + exec-maven-plugin + + ${e2e.test.skip} + + + + install-playwright + generate-resources + + exec + + + ./mvnw + + exec:java + -e + -Dexec.mainClass=com.microsoft.playwright.CLI + -Dexec.args="install-deps" + + + + + org.apache.maven.plugins maven-failsafe-plugin @@ -165,7 +190,11 @@ - default + integration-test + none + + + verify integration-test verify @@ -247,16 +276,6 @@ verify - 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 4eb5dec399c8..c1cd24429d0d 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 @@ -21,10 +21,10 @@ */ @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/playwright/PlaywrightSupport.java b/e2e/dotcms-e2e-java/src/test/java/com/dotcms/e2e/playwright/PlaywrightSupport.java index 8a420ceb58db..096215344b07 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 @@ -39,20 +39,25 @@ *
  • {@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.
  • + *
  • {@link #assertVisibleTimeout(double)} - Creates visibility timeout options for assertions.
  • * * * @author vico */ public class PlaywrightSupport { + private static final double DEFAULT_TIMEOUT = 10000; + private static final PlaywrightSupport INSTANCE = new PlaywrightSupport(); public static PlaywrightSupport get() { return INSTANCE; } + private final boolean ci; + private PlaywrightSupport() { + ci = Boolean.parseBoolean(EnvironmentService.get().getProperty(E2eKeys.CI_KEY)); } /** @@ -70,7 +75,7 @@ public Playwright playwright() { * @return true if the current environment is a CI environment, false otherwise */ public boolean isCi() { - return Boolean.parseBoolean(EnvironmentService.get().getProperty(E2eKeys.CI_KEY)); + return ci; } /** @@ -153,8 +158,17 @@ public com.microsoft.playwright.BrowserType resolveBrowser(final Playwright play * @param timeout the timeout value in milliseconds * @return the visibility timeout options */ - public LocatorAssertions.IsVisibleOptions visibleTimeout(final double timeout) { + public LocatorAssertions.IsVisibleOptions assertVisibleTimeout(final double timeout) { return new LocatorAssertions.IsVisibleOptions().setTimeout(timeout); } + /** + * Creates visibility timeout options for assertions. + * + * @return the visibility timeout options + */ + public LocatorAssertions.IsVisibleOptions assertVisibleTimeout() { + return assertVisibleTimeout(DEFAULT_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 0bb8d6a1c895..d8a841cfc036 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 @@ -60,7 +60,12 @@ private EnvironmentService() { * @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); + String propValue = props.getProperty(key); + if (StringUtils.isNotBlank(propValue)) { + return propValue; + } + + propValue = System.getProperty(key); if (StringUtils.isNotBlank(propValue)) { return propValue; } 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 index 6f03c7be2c6d..81af674dc29a 100644 --- 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 @@ -7,6 +7,7 @@ import com.dotcms.e2e.page.MenuNavigation; import com.dotcms.e2e.page.PagesPage; import com.dotcms.e2e.page.ToolEntries; +import com.dotcms.e2e.playwright.PlaywrightSupport; import com.microsoft.playwright.Locator; import com.microsoft.playwright.Page; import com.microsoft.playwright.options.AriaRole; @@ -65,7 +66,8 @@ public void test_addPage() throws Exception { pagesPage.fillPagesForm(pagesDetailFrame, "Testing Page", "Default Template"); // validations assertThat(page.locator("li") - .filter(new Locator.FilterOptions().setHasText("Testing Page"))).isVisible(); + .filter(new Locator.FilterOptions().setHasText("Testing Page"))) + .isVisible(PlaywrightSupport.get().assertVisibleTimeout()); } @@ -104,7 +106,7 @@ public void test_removePage() throws Exception { new Page.GetByRoleOptions().setName("Status"))).isVisible(); //execute the delete action pagesPage.executePagesWorkflow("Testing Page", "Delete"); - assertThat(page.getByText("Workflow executed")).isVisible(); + assertThat(page.getByText("Workflow executed")).isVisible(PlaywrightSupport.get().assertVisibleTimeout()); } } 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 79f108484cf5..adcef7efa3e3 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 @@ -62,7 +62,7 @@ public void test_loginWrongUser() { @Test public void test_loginWrongPass() { loginPage.login("admin@dotcms.com", "winteriscoming"); - assertThat(page.getByTestId("message")).isVisible(PlaywrightSupport.get().visibleTimeout(10000)); + assertThat(page.getByTestId("message")).isVisible(PlaywrightSupport.get().assertVisibleTimeout()); } /** 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 4325a93dd9a6..b5486cccf31f 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 @@ -21,7 +21,7 @@ private StringToolbox() { * @return the converted snake_case string */ public static String camelToSnake(String str) { - return str.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase(); + return str.replaceAll("([a-z])([A-Z]+)", "$1_$2").toUpperCase(); } } diff --git a/e2e/dotcms-e2e-node/frontend/playwright.config.ts b/e2e/dotcms-e2e-node/frontend/playwright.config.ts index 6779a7d8d994..8ab823621469 100644 --- a/e2e/dotcms-e2e-node/frontend/playwright.config.ts +++ b/e2e/dotcms-e2e-node/frontend/playwright.config.ts @@ -2,6 +2,7 @@ import dotenv from 'dotenv'; import * as path from "node:path"; import { defineConfig, devices } from '@playwright/test'; + const resolveEnvs = () => { const envFiles = ['.env']; @@ -19,7 +20,12 @@ const resolveEnvs = () => { }); }; +const prepareForTesting = () => { + +}; + resolveEnvs(); +prepareForTesting(); /** * See https://playwright.dev/docs/test-configuration. @@ -35,12 +41,13 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: [['junit', { outputFile: '../target/failsafe-reports/failsafe-summary.xml' }]], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { baseURL: process.env.BASE_URL, /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', + headless: process.env.CI === 'true', }, /* Configure projects for major browsers */ projects: [ diff --git a/e2e/dotcms-e2e-node/pom.xml b/e2e/dotcms-e2e-node/pom.xml index eb6903f1bdea..2ff167ad7d19 100644 --- a/e2e/dotcms-e2e-node/pom.xml +++ b/e2e/dotcms-e2e-node/pom.xml @@ -16,18 +16,31 @@ UTF-8 + true false install --frozen-lockfile - global add playwright + global add playwright + playwright install + playwright install-deps true local + ./frontend run start-${e2e.test.env} 8080 http://localhost:${tomcat.port} + 1.10.6 + true + true + tomcat:9.0.74-jdk11 ${ext.wiremock.api.key} ${ext.docker.image.wiremock} ./src/test/resources /home/wiremock + ${project.build.directory}/testdata/fork- + ${it.test.fork-folder.prefix} + true + 8080 + false @@ -44,31 +57,55 @@ generate-resources + ${e2e.frontend.dir} ${skip.npm.install} ${yarn.install.cmd} - install-playwrigth + add-playwright yarn - generate-resources - ${skip.npm.install} + ${e2e.frontend.dir} + ${e2e.test.skip} + ${playwright.add.cmd} + + + + install-playwright + + yarn + + generate-resources + + ${e2e.frontend.dir} + ${e2e.test.skip} ${playwright.install.cmd} + + install-playwright-deps + + yarn + + generate-resources + + ${e2e.frontend.dir} + ${e2e.test.skip} + ${playwright.install.deps.cmd} + + run node script - yarn integration-test - ./frontend + ${e2e.frontend.dir} ${e2e.test.skip} ${e2e.test.cmd} @@ -86,14 +123,6 @@ integration-test none - - verify - - verify - - - - diff --git a/justfile b/justfile index 61a026e88707..dcb798d9abac 100644 --- a/justfile +++ b/justfile @@ -134,9 +134,13 @@ test-e2e-java: test-e2e-java-debug-suspend: ./mvnw -pl :dotcms-e2e-java verify -De2e.test.skip=false -Pdebug-suspend-e2e-tests +# Executes Node E2E tests +test-e2e-node: + ./mvnw -pl :dotcms-e2e-node verify -De2e.test.skip=false + # Stops E2E test services test-e2e-stop: - ./mvnw -pl :dotcms-e2e -Pdocker-stop -De2e.test.skip=false + ./mvnw -pl :dotcms-e2e-java,:dotcms-e2e-node -Pdocker-stop -De2e.test.skip=false # Docker Commands # Runs a published dotCMS Docker image on a dynamic port