Repository: jhipster/jhipster-lite (java)

Issue:
Cypress/Playwright: split current module in two modules: e2e tests and component-tests
The current `cypress` module generates something that looks like frontend component tests (using the Martin Folwer definition, not the Cypress definition of component tests): things are generated in `src/test/webapp/component`, npm script is `test:component`, ...

We should probably improve the current module to also automatically start the frontend server, so component tests can be launched without prerequisites by launching `npm run test:component` (see current generator configuration).

And create a new one that would generate Cypress configuration for running E2E.

Pull request:
Cypress/Playwright: split current module in two modules: e2e tests and component-tests
- Fixes #10613

Patch:
diff --git a/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/application/CypressApplicationService.java b/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/application/CypressApplicationService.java
index 58a80aace..7e69f81a5 100644
--- a/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/application/CypressApplicationService.java
+++ b/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/application/CypressApplicationService.java
@@ -14,7 +14,11 @@ public class CypressApplicationService {
     factory = new CypressModuleFactory();
   }
 
-  public JHipsterModule buildModule(JHipsterModuleProperties properties) {
-    return factory.buildModule(properties);
+  public JHipsterModule buildComponentTestsModule(JHipsterModuleProperties properties) {
+    return factory.buildComponentTestsModule(properties);
+  }
+
+  public JHipsterModule buildE2ETestsModule(JHipsterModuleProperties properties) {
+    return factory.buildE2ETestsModule(properties);
   }
 }
diff --git a/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/domain/CypressModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/domain/CypressModuleFactory.java
index 02cb1b2df..7162dda8f 100644
--- a/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/domain/CypressModuleFactory.java
+++ b/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/domain/CypressModuleFactory.java
@@ -2,6 +2,7 @@ package tech.jhipster.lite.generator.client.tools.cypress.domain;
 
 import static tech.jhipster.lite.module.domain.JHipsterModule.*;
 
+import java.util.function.Function;
 import java.util.regex.Pattern;
 import tech.jhipster.lite.module.domain.JHipsterModule;
 import tech.jhipster.lite.module.domain.file.JHipsterDestination;
@@ -15,79 +16,111 @@ public class CypressModuleFactory {
 
   private static final JHipsterSource SOURCE = from("client/common/cypress");
 
-  private static final String CYPRESS_TEST = "src/test/webapp/component";
-
-  private static final JHipsterDestination CYPRESS_DESTINATION = to(CYPRESS_TEST);
+  private static final JHipsterDestination CYPRESS_COMPONENT_TESTS = to("src/test/webapp/component");
+  private static final JHipsterDestination CYPRESS_E2E_TESTS = to("src/test/webapp/e2e");
 
   private static final String PRIMARY_APP = "common/primary/app";
   private static final String UTILS = "utils";
 
-  private static final String CYPRESS_EXCLUSION = "\"src/test/webapp/component/**/*.ts\"";
+  private static final String CYPRESS_COMPONENT_TESTS_EXCLUSION = "\"src/test/webapp/component/**/*.ts\"";
+  private static final String CYPRESS_E2E_TESTS_EXCLUSION = "\"src/test/webapp/e2e/**/*.ts\"";
   private static final String EXCLUDE_KEY = "\"exclude\"";
   private static final RegexReplacer NEW_EXCLUSION_REPLACER = new RegexReplacer(
     (currentContent, replacement) -> !currentContent.contains(EXCLUDE_KEY),
     Pattern.compile("\\n.*}\\s*$")
   );
 
-  private static final RegexReplacer EXISTING_EXCLUSION_REPLACER = new RegexReplacer(
-    (currentContent, replacement) -> currentContent.contains(EXCLUDE_KEY) && !currentContent.contains(CYPRESS_EXCLUSION),
-    Pattern.compile("(" + EXCLUDE_KEY + "\\s*:\\s*\\[[^]]+)]")
-  );
+  private static final Function<String, RegexReplacer> EXISTING_EXCLUSION_REPLACER_PROVIDER = (String exclusion) ->
+    new RegexReplacer(
+      (currentContent, replacement) -> currentContent.contains(EXCLUDE_KEY) && !currentContent.contains(exclusion),
+      Pattern.compile("(" + EXCLUDE_KEY + "\\s*:\\s*\\[[^]]+)]")
+    );
 
-  private static final RegexReplacer EMPTY_EXCLUSION_REPLACER = new RegexReplacer(
-    (currentContent, replacement) -> currentContent.contains(EXCLUDE_KEY) && !currentContent.contains(CYPRESS_EXCLUSION),
-    Pattern.compile("(" + EXCLUDE_KEY + "\\s*:\\s*\\[\\s*)]")
-  );
+  private static final Function<String, RegexReplacer> EMPTY_EXCLUSION_REPLACER_PROVIDER = (String exclusion) ->
+    new RegexReplacer(
+      (currentContent, replacement) -> currentContent.contains(EXCLUDE_KEY) && !currentContent.contains(exclusion),
+      Pattern.compile("(" + EXCLUDE_KEY + "\\s*:\\s*\\[\\s*)]")
+    );
 
-  public JHipsterModule buildModule(JHipsterModuleProperties properties) {
+  public JHipsterModule buildComponentTestsModule(JHipsterModuleProperties properties) {
     Assert.notNull("properties", properties);
 
     //@formatter:off
-    return moduleBuilder(properties)
+    return commonCypressModuleBuilder(properties, CYPRESS_COMPONENT_TESTS, CYPRESS_COMPONENT_TESTS_EXCLUSION)
       .packageJson()
-        .addDevDependency(packageName("cypress"), VersionSource.COMMON)
-        .addDevDependency(packageName("eslint-plugin-cypress"), VersionSource.COMMON)
         .addDevDependency(packageName("start-server-and-test"), VersionSource.COMMON)
-        .addScript(scriptKey("e2e"), scriptCommand("npm run test:component"))
-        .addScript(scriptKey("e2e:headless"), scriptCommand("npm run test:component:headless"))
         .addScript(scriptKey("test:component"), scriptCommand("start-server-and-test start http://localhost:9000 'cypress open --e2e --config-file src/test/webapp/component/cypress-config.ts'"))
         .addScript(
           scriptKey("test:component:headless"),
           scriptCommand("start-server-and-test start http://localhost:9000 'cypress run --headless --config-file src/test/webapp/component/cypress-config.ts'")
         )
         .and()
+      .context()
+        .put("cypressTestDirectory", "component")
+        .and()
+      .build();
+    //@formatter:on
+  }
+
+  public JHipsterModule buildE2ETestsModule(JHipsterModuleProperties properties) {
+    Assert.notNull("properties", properties);
+
+    //@formatter:off
+    return commonCypressModuleBuilder(properties, CYPRESS_E2E_TESTS, CYPRESS_E2E_TESTS_EXCLUSION)
+      .packageJson()
+        .addScript(scriptKey("e2e"), scriptCommand("cypress open --e2e --config-file src/test/webapp/e2e/cypress-config.ts"))
+        .addScript(scriptKey("e2e:headless"), scriptCommand("cypress run --headless --config-file src/test/webapp/e2e/cypress-config.ts"))
+        .and()
+      .context()
+        .put("cypressTestDirectory", "e2e")
+        .and()
+      .build();
+    //@formatter:on
+  }
+
+  private static JHipsterModuleBuilder commonCypressModuleBuilder(
+    JHipsterModuleProperties properties,
+    JHipsterDestination destinationFolder,
+    String tsconfigExclusion
+  ) {
+    //@formatter:off
+    return moduleBuilder(properties)
+      .packageJson()
+        .addDevDependency(packageName("cypress"), VersionSource.COMMON)
+        .addDevDependency(packageName("eslint-plugin-cypress"), VersionSource.COMMON)
+        .and()
       .files()
-        .batch(SOURCE.append(CYPRESS_TEST), CYPRESS_DESTINATION)
-          .addFile("cypress-config.ts")
+        .batch(SOURCE, destinationFolder)
+          .addTemplate("cypress-config.ts")
           .addFile(".eslintrc.cjs")
           .addFile("tsconfig.json")
           .and()
         .add(
-          SOURCE.append(CYPRESS_TEST).append(PRIMARY_APP).file("Home.spec.ts"),
-          CYPRESS_DESTINATION.append(PRIMARY_APP).append("Home.spec.ts")
+          SOURCE.append(PRIMARY_APP).file("Home.spec.ts"),
+          destinationFolder.append(PRIMARY_APP).append("Home.spec.ts")
         )
-        .batch(SOURCE.append(CYPRESS_TEST).append(UTILS), CYPRESS_DESTINATION.append(UTILS))
+        .batch(SOURCE.append(UTILS), destinationFolder.append(UTILS))
           .addFile("Interceptor.ts")
           .addFile("DataSelector.ts")
           .and()
         .and()
       .optionalReplacements()
         .in(path("tsconfig.json"))
-        .add(EXISTING_EXCLUSION_REPLACER, "$1, "+CYPRESS_EXCLUSION+"]")
-        .add(EMPTY_EXCLUSION_REPLACER, "$1"+CYPRESS_EXCLUSION+"]")
-        .add(NEW_EXCLUSION_REPLACER, newExclusionNode(properties))
+        .add(EXISTING_EXCLUSION_REPLACER_PROVIDER.apply(tsconfigExclusion), "$1, "+tsconfigExclusion+"]")
+        .add(EMPTY_EXCLUSION_REPLACER_PROVIDER.apply(tsconfigExclusion), "$1"+tsconfigExclusion+"]")
+        .add(NEW_EXCLUSION_REPLACER, newExclusionNode(properties, tsconfigExclusion))
         .and()
         .and()
-      .build();
+      ;
     //@formatter:on
   }
 
-  private String newExclusionNode(JHipsterModuleProperties properties) {
+  private static String newExclusionNode(JHipsterModuleProperties properties, String exclusion) {
     return new StringBuilder()
       .append(",")
       .append(LINE_BREAK)
       .append(properties.indentation().spaces())
-      .append("\"exclude\": [" + CYPRESS_EXCLUSION + "]")
+      .append("\"exclude\": [" + exclusion + "]")
       .append(LINE_BREAK)
       .append("}")
       .toString();
diff --git a/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/infrastructure/primary/CypressModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/infrastructure/primary/CypressModuleConfiguration.java
index e0d9cba3a..d100f8fa3 100644
--- a/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/infrastructure/primary/CypressModuleConfiguration.java
+++ b/src/main/java/tech/jhipster/lite/generator/client/tools/cypress/infrastructure/primary/CypressModuleConfiguration.java
@@ -14,13 +14,24 @@ import tech.jhipster.lite.module.domain.resource.JHipsterModuleResource;
 class CypressModuleConfiguration {
 
   @Bean
-  JHipsterModuleResource cypressModule(CypressApplicationService cypress) {
+  JHipsterModuleResource cypressComponentTestsModule(CypressApplicationService cypress) {
     return JHipsterModuleResource.builder()
-      .slug(CYPRESS)
+      .slug(CYPRESS_COMPONENT_TESTS)
       .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().addIndentation().build())
-      .apiDoc("E2e", "Add Cypress")
-      .organization(JHipsterModuleOrganization.builder().feature(FRONT_BROWSER_TEST).addDependency(CLIENT_CORE).build())
+      .apiDoc("Frontend - Component tests", "Setup frontend component tests using Cypress")
+      .organization(JHipsterModuleOrganization.builder().feature(FRONTEND_COMPONENT_TESTS).addDependency(CLIENT_CORE).build())
+      .tags("client", "test", "cypress", "frontend")
+      .factory(cypress::buildComponentTestsModule);
+  }
+
+  @Bean
+  JHipsterModuleResource cypressE2ETestsModule(CypressApplicationService cypress) {
+    return JHipsterModuleResource.builder()
+      .slug(CYPRESS_E2E)
+      .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().addIndentation().build())
+      .apiDoc("E2E", "Setup E2E tests using Cypress")
+      .organization(JHipsterModuleOrganization.builder().feature(E2E_TESTS).addDependency(CLIENT_CORE).build())
       .tags("client", "test", "cypress", "e2e")
-      .factory(cypress::buildModule);
+      .factory(cypress::buildE2ETestsModule);
   }
 }
diff --git a/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/application/PlaywrightApplicationService.java b/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/application/PlaywrightApplicationService.java
index 040da5170..4969a5938 100644
--- a/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/application/PlaywrightApplicationService.java
+++ b/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/application/PlaywrightApplicationService.java
@@ -14,7 +14,11 @@ public class PlaywrightApplicationService {
     factory = new PlaywrightModuleFactory();
   }
 
-  public JHipsterModule buildModule(JHipsterModuleProperties properties) {
-    return factory.buildModule(properties);
+  public JHipsterModule buildComponentTestsModule(JHipsterModuleProperties properties) {
+    return factory.buildComponentTestsModule(properties);
+  }
+
+  public JHipsterModule buildE2ETestsModule(JHipsterModuleProperties properties) {
+    return factory.buildE2ETestsModule(properties);
   }
 }
diff --git a/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/domain/PlaywrightModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/domain/PlaywrightModuleFactory.java
index 1d67b656f..3d771a978 100644
--- a/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/domain/PlaywrightModuleFactory.java
+++ b/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/domain/PlaywrightModuleFactory.java
@@ -3,6 +3,7 @@ package tech.jhipster.lite.generator.client.tools.playwright.domain;
 import static tech.jhipster.lite.module.domain.JHipsterModule.*;
 
 import tech.jhipster.lite.module.domain.JHipsterModule;
+import tech.jhipster.lite.module.domain.file.JHipsterDestination;
 import tech.jhipster.lite.module.domain.file.JHipsterSource;
 import tech.jhipster.lite.module.domain.packagejson.VersionSource;
 import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
@@ -12,28 +13,61 @@ public class PlaywrightModuleFactory {
 
   private static final JHipsterSource SOURCE = from("client/common/playwright");
 
-  private static final String WEBAPP_COMPONENT_TESTS = "src/test/webapp/component/";
-  private static final String PLAYWRIGHT_TESTS = WEBAPP_COMPONENT_TESTS + "common/primary/app";
+  private static final JHipsterDestination WEBAPP_COMPONENT_TESTS = to("src/test/webapp/component/");
+  private static final JHipsterDestination WEBAPP_E2E_TESTS = to("src/test/webapp/e2e/");
+  private static final String PLAYWRIGHT_TESTS = "common/primary/app";
 
-  public JHipsterModule buildModule(JHipsterModuleProperties properties) {
+  public JHipsterModule buildComponentTestsModule(JHipsterModuleProperties properties) {
     Assert.notNull("properties", properties);
 
     //@formatter:off
-    return moduleBuilder(properties)
+    return commonPlaywrightModuleBuilder(properties, WEBAPP_COMPONENT_TESTS)
       .packageJson()
-        .addDevDependency(packageName("@playwright/test"), VersionSource.COMMON)
         .addDevDependency(packageName("start-server-and-test"), VersionSource.COMMON)
         .addScript(scriptKey("test:component"), scriptCommand("start-server-and-test start http://localhost:9000 'playwright test --ui --config src/test/webapp/component/playwright.config.ts'"))
         .addScript(scriptKey("test:component:headless"), scriptCommand("start-server-and-test start http://localhost:9000 'playwright test --config src/test/webapp/component/playwright.config.ts'"))
         .and()
+      .context()
+        .put("reportSubDirectory", "component-tests")
+        .put("resultsSubDirectory", "component-tests")
+        .and()
+      .build();
+    //@formatter:on
+  }
+
+  public JHipsterModule buildE2ETestsModule(JHipsterModuleProperties properties) {
+    Assert.notNull("properties", properties);
+
+    //@formatter:off
+    return commonPlaywrightModuleBuilder(properties, WEBAPP_E2E_TESTS)
+      .packageJson()
+        .addScript(scriptKey("e2e"), scriptCommand("playwright test --ui --config src/test/webapp/e2e/playwright.config.ts"))
+        .addScript(scriptKey("e2e:headless"), scriptCommand("playwright test --config src/test/webapp/e2e/playwright.config.ts"))
+        .and()
+      .context()
+        .put("reportSubDirectory", "e2e-tests")
+        .put("resultsSubDirectory", "e2e-tests")
+        .and()
+      .build();
+    //@formatter:on
+  }
+
+  private static JHipsterModuleBuilder commonPlaywrightModuleBuilder(
+    JHipsterModuleProperties properties,
+    JHipsterDestination destinationFolder
+  ) {
+    //@formatter:off
+    return moduleBuilder(properties)
+      .packageJson()
+        .addDevDependency(packageName("@playwright/test"), VersionSource.COMMON)
+        .and()
       .files()
-        .add(SOURCE.template("playwright.config.ts"), to(WEBAPP_COMPONENT_TESTS + "playwright.config.ts"))
-        .batch(SOURCE.append(PLAYWRIGHT_TESTS), to(PLAYWRIGHT_TESTS))
+        .add(SOURCE.template("playwright.config.ts"), destinationFolder.append("playwright.config.ts"))
+        .batch(SOURCE.append(PLAYWRIGHT_TESTS), destinationFolder.append(PLAYWRIGHT_TESTS))
           .addFile("Home.spec.ts")
           .addFile("Home-Page.ts")
           .and()
-        .and()
-      .build();
-    //@formatter:off
+      .and();
+    //@formatter:on
   }
 }
diff --git a/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/infrastructure/primary/PlaywrightModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/infrastructure/primary/PlaywrightModuleConfiguration.java
index f6b0b4645..479c95a95 100644
--- a/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/infrastructure/primary/PlaywrightModuleConfiguration.java
+++ b/src/main/java/tech/jhipster/lite/generator/client/tools/playwright/infrastructure/primary/PlaywrightModuleConfiguration.java
@@ -14,13 +14,24 @@ import tech.jhipster.lite.module.domain.resource.JHipsterModuleResource;
 class PlaywrightModuleConfiguration {
 
   @Bean
-  JHipsterModuleResource playwrightModule(PlaywrightApplicationService playwright) {
+  JHipsterModuleResource playwrightComponentTestsModule(PlaywrightApplicationService playwright) {
     return JHipsterModuleResource.builder()
-      .slug(PLAYWRIGHT)
+      .slug(PLAYWRIGHT_COMPONENT_TESTS)
       .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().build())
-      .apiDoc("E2e", "Add Playwright")
-      .organization(JHipsterModuleOrganization.builder().feature(FRONT_BROWSER_TEST).addDependency(CLIENT_CORE).build())
+      .apiDoc("E2E", "Configure frontend component tests using Playwright")
+      .organization(JHipsterModuleOrganization.builder().feature(FRONTEND_COMPONENT_TESTS).addDependency(CLIENT_CORE).build())
+      .tags("client", "test", "playwright", "frontend")
+      .factory(playwright::buildComponentTestsModule);
+  }
+
+  @Bean
+  JHipsterModuleResource playwrightE2ETestsModule(PlaywrightApplicationService playwright) {
+    return JHipsterModuleResource.builder()
+      .slug(PLAYWRIGHT_E2E)
+      .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().build())
+      .apiDoc("E2E", "Configure E2E tests using Playwright")
+      .organization(JHipsterModuleOrganization.builder().feature(E2E_TESTS).addDependency(CLIENT_CORE).build())
       .tags("client", "test", "playwright", "e2e")
-      .factory(playwright::buildModule);
+      .factory(playwright::buildE2ETestsModule);
   }
 }
diff --git a/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteFeatureSlug.java b/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteFeatureSlug.java
index 7432d9bc5..16dd8c579 100644
--- a/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteFeatureSlug.java
+++ b/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteFeatureSlug.java
@@ -11,7 +11,8 @@ public enum JHLiteFeatureSlug implements JHipsterFeatureSlugFactory {
   CUCUMBER_AUTHENTICATION("cucumber-authentication"),
   DATABASE_MIGRATION("database-migration"),
   DOCKERFILE("dockerfile"),
-  FRONT_BROWSER_TEST("front-browser-test"),
+  E2E_TESTS("e2e-tests"),
+  FRONTEND_COMPONENT_TESTS("frontend-component-tests"),
   FRONTEND_JAVA_BUILD_TOOL_PLUGIN("frontend-java-build-tool-plugin"),
   GITHUB_ACTIONS("github-actions"),
   GITLAB_CI("gitlab-ci"),
diff --git a/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteModuleSlug.java b/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteModuleSlug.java
index a7326069b..df7bf7031 100644
--- a/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteModuleSlug.java
+++ b/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteModuleSlug.java
@@ -20,7 +20,8 @@ public enum JHLiteModuleSlug implements JHipsterModuleSlugFactory {
   CHECKSTYLE("checkstyle"),
   CONSUL("consul"),
   CUSTOM_JHLITE("custom-jhlite"),
-  CYPRESS("cypress"),
+  CYPRESS_COMPONENT_TESTS("cypress-component-tests"),
+  CYPRESS_E2E("cypress-e2e"),
   DOCKERFILE_MAVEN("dockerfile-maven"),
   DOCKERFILE_GRADLE("dockerfile-gradle"),
   EHCACHE_JAVA_CONFIG("ehcache-java-config"),
@@ -81,7 +82,8 @@ public enum JHLiteModuleSlug implements JHipsterModuleSlugFactory {
   NEO4J_MIGRATIONS("neo4j-migrations"),
   OPTIONAL_TYPESCRIPT("optional-typescript"),
   PAGINATION_DOMAIN("pagination-domain"),
-  PLAYWRIGHT("playwright"),
+  PLAYWRIGHT_COMPONENT_TESTS("playwright-component-tests"),
+  PLAYWRIGHT_E2E("playwright-e2e"),
   POSTGRESQL("postgresql"),
   PRETTIER("prettier"),
   PROTOBUF("protobuf"),
diff --git a/src/main/resources/generator/client/common/cypress/src/test/webapp/component/tsconfig.json b/src/main/resources/generator/client/common/cypress/tsconfig.json
similarity index 100%
rename from src/main/resources/generator/client/common/cypress/src/test/webapp/component/tsconfig.json
rename to src/main/resources/generator/client/common/cypress/tsconfig.json
diff --git a/src/main/resources/generator/client/common/cypress/src/test/webapp/component/utils/DataSelector.ts b/src/main/resources/generator/client/common/cypress/utils/DataSelector.ts
similarity index 100%
rename from src/main/resources/generator/client/common/cypress/src/test/webapp/component/utils/DataSelector.ts
rename to src/main/resources/generator/client/common/cypress/utils/DataSelector.ts
diff --git a/src/main/resources/generator/client/common/cypress/src/test/webapp/component/utils/Interceptor.ts b/src/main/resources/generator/client/common/cypress/utils/Interceptor.ts
similarity index 100%
rename from src/main/resources/generator/client/common/cypress/src/test/webapp/component/utils/Interceptor.ts
rename to src/main/resources/generator/client/common/cypress/utils/Interceptor.ts
diff --git a/src/main/resources/generator/client/common/playwright/src/test/webapp/component/common/primary/app/Home-Page.ts b/src/main/resources/generator/client/common/playwright/common/primary/app/Home-Page.ts
similarity index 100%
rename from src/main/resources/generator/client/common/playwright/src/test/webapp/component/common/primary/app/Home-Page.ts
rename to src/main/resources/generator/client/common/playwright/common/primary/app/Home-Page.ts
diff --git a/src/main/resources/generator/client/common/playwright/src/test/webapp/component/common/primary/app/Home.spec.ts b/src/main/resources/generator/client/common/playwright/common/primary/app/Home.spec.ts
similarity index 100%
rename from src/main/resources/generator/client/common/playwright/src/test/webapp/component/common/primary/app/Home.spec.ts
rename to src/main/resources/generator/client/common/playwright/common/primary/app/Home.spec.ts
diff --git a/src/main/resources/generator/client/common/playwright/playwright.config.ts.mustache b/src/main/resources/generator/client/common/playwright/playwright.config.ts.mustache
index 2bab1d44d..2ddee0405 100644
--- a/src/main/resources/generator/client/common/playwright/playwright.config.ts.mustache
+++ b/src/main/resources/generator/client/common/playwright/playwright.config.ts.mustache
@@ -27,7 +27,7 @@ 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: [['list'], ['html', { outputFolder: '../../../../{{ projectBuildDirectory }}/playwright-report/component-tests' }]],
+  reporter: [['list'], ['html', { outputFolder: '../../../../{{ projectBuildDirectory }}/playwright-report/{{ reportSubDirectory }}' }]],
   /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
   use: {
     /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
@@ -92,5 +92,5 @@ export default defineConfig({
   ],
 
   /* Folder for test artifacts such as screenshots, videos, traces, etc. */
-  outputDir: '../../../../{{ projectBuildDirectory }}/playwright-results/component-tests',
+  outputDir: '../../../../{{ projectBuildDirectory }}/playwright-results/{{ resultsSubDirectory }}',
 });


Test patch:
diff --git a/src/main/resources/generator/client/common/cypress/src/test/webapp/component/.eslintrc.cjs b/src/main/resources/generator/client/common/cypress/.eslintrc.cjs
similarity index 100%
rename from src/main/resources/generator/client/common/cypress/src/test/webapp/component/.eslintrc.cjs
rename to src/main/resources/generator/client/common/cypress/.eslintrc.cjs
diff --git a/src/main/resources/generator/client/common/cypress/src/test/webapp/component/common/primary/app/Home.spec.ts b/src/main/resources/generator/client/common/cypress/common/primary/app/Home.spec.ts
similarity index 100%
rename from src/main/resources/generator/client/common/cypress/src/test/webapp/component/common/primary/app/Home.spec.ts
rename to src/main/resources/generator/client/common/cypress/common/primary/app/Home.spec.ts
diff --git a/src/main/resources/generator/client/common/cypress/src/test/webapp/component/cypress-config.ts b/src/main/resources/generator/client/common/cypress/cypress-config.ts.mustache
similarity index 70%
rename from src/main/resources/generator/client/common/cypress/src/test/webapp/component/cypress-config.ts
rename to src/main/resources/generator/client/common/cypress/cypress-config.ts.mustache
index cacb2b408..a239063c1 100644
--- a/src/main/resources/generator/client/common/cypress/src/test/webapp/component/cypress-config.ts
+++ b/src/main/resources/generator/client/common/cypress/cypress-config.ts.mustache
@@ -3,7 +3,7 @@ import { defineConfig } from 'cypress';
 export default defineConfig({
   e2e: {
     baseUrl: 'http://localhost:9000',
-    specPattern: 'src/test/webapp/component/**/*.(spec|cy).ts',
+    specPattern: 'src/test/webapp/{{ cypressTestDirectory }}/**/*.(spec|cy).ts',
     fixturesFolder: false,
     supportFile: false,
     video: false,
diff --git a/src/test/features/client/browser-test/cypress.feature b/src/test/features/client/browser-test/cypress.feature
index a95e22922..be92dce1c 100644
--- a/src/test/features/client/browser-test/cypress.feature
+++ b/src/test/features/client/browser-test/cypress.feature
@@ -1,7 +1,13 @@
 Feature: Cypress module
 
-  Scenario: Should apply cypress module
-    When I apply "cypress" module to default project with package json
+  Scenario: Should apply cypress-component-tests module
+    When I apply "cypress-component-tests" module to default project with package json
       | serverPort | 9000 |
     Then I should have files in "src/test/webapp/component"
       | .eslintrc.cjs |
+
+  Scenario: Should apply cypress-e2e module
+    When I apply "cypress-e2e" module to default project with package json
+      | serverPort | 9000 |
+    Then I should have files in "src/test/webapp/e2e"
+      | .eslintrc.cjs |
diff --git a/src/test/features/client/browser-test/playwright.feature b/src/test/features/client/browser-test/playwright.feature
index 59ec6c311..f69fb32a7 100644
--- a/src/test/features/client/browser-test/playwright.feature
+++ b/src/test/features/client/browser-test/playwright.feature
@@ -1,7 +1,13 @@
 Feature: Playwright module
 
-  Scenario: Should apply Playwright module
-    When I apply "playwright" module to default project with package json
+  Scenario: Should apply Playwright component tests module
+    When I apply "playwright-component-tests" module to default project with package json
       | serverPort | 9000 |
     Then I should have files in "src/test/webapp/component/common/primary/app"
       | Home.spec.ts |
+
+  Scenario: Should apply Playwright E2E module
+    When I apply "playwright-e2e" module to default project with package json
+      | serverPort | 9000 |
+    Then I should have files in "src/test/webapp/e2e/common/primary/app"
+      | Home.spec.ts |
diff --git a/src/test/java/tech/jhipster/lite/generator/client/tools/cypress/domain/CypressModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/client/tools/cypress/domain/CypressModuleFactoryTest.java
index f0a61966a..b65bf32d5 100644
--- a/src/test/java/tech/jhipster/lite/generator/client/tools/cypress/domain/CypressModuleFactoryTest.java
+++ b/src/test/java/tech/jhipster/lite/generator/client/tools/cypress/domain/CypressModuleFactoryTest.java
@@ -2,6 +2,7 @@ package tech.jhipster.lite.generator.client.tools.cypress.domain;
 
 import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.*;
 
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import tech.jhipster.lite.TestFileUtils;
 import tech.jhipster.lite.UnitTest;
@@ -14,80 +15,168 @@ class CypressModuleFactoryTest {
 
   private static final CypressModuleFactory factory = new CypressModuleFactory();
 
-  @Test
-  void shouldBuildModuleOnProjectWithoutTsConfig() {
-    assertCypressModule(packageJsonFile());
-  }
+  @Nested
+  class ComponentTests {
 
-  @Test
-  void shouldBuildModuleOnProjectWithEmptyTsConfig() {
-    assertCypressModule(packageJsonFile(), file("src/test/resources/projects/empty-ts-config/tsconfig.json", "tsconfig.json"))
-      .hasFile("tsconfig.json")
-      .containing(
-        """
-          },
-          "exclude": ["src/test/webapp/component/**/*.ts"]
-        }\
-        """
-      );
-  }
+    @Test
+    void shouldBuildComponentTestsModuleOnProjectWithoutTsConfig() {
+      assertCypressComponentTestsModule(packageJsonFile());
+    }
 
-  @Test
-  void shouldBuildModuleOnProjectWithTsConfigWithEmptyExclusions() {
-    assertCypressModule(
-      packageJsonFile(),
-      file("src/test/resources/projects/ts-config-with-empty-exclusions/tsconfig.json", "tsconfig.json")
-    )
-      .hasFile("tsconfig.json")
-      .containing("\"exclude\": [\"src/test/webapp/component/**/*.ts\"]");
-  }
+    @Test
+    void shouldBuildComponentTestsModuleOnProjectWithEmptyTsConfig() {
+      assertCypressComponentTestsModule(
+        packageJsonFile(),
+        file("src/test/resources/projects/empty-ts-config/tsconfig.json", "tsconfig.json")
+      )
+        .hasFile("tsconfig.json")
+        .containing(
+          """
+            },
+            "exclude": ["src/test/webapp/component/**/*.ts"]
+          }\
+          """
+        );
+    }
 
-  @Test
-  void shouldBuildModuleOnProjectWithTsConfigWithExistingExclusions() {
-    assertCypressModule(packageJsonFile(), file("src/test/resources/projects/ts-config-with-exclusions/tsconfig.json", "tsconfig.json"))
-      .hasFile("tsconfig.json")
-      .containing("  \"exclude\": [\"src/test/webapp/component/**/*spec.ts\", \"node_modules\", \"src/test/webapp/component/**/*.ts\"]");
-  }
+    @Test
+    void shouldBuildComponentTestsModuleOnProjectWithTsConfigWithEmptyExclusions() {
+      assertCypressComponentTestsModule(
+        packageJsonFile(),
+        file("src/test/resources/projects/ts-config-with-empty-exclusions/tsconfig.json", "tsconfig.json")
+      )
+        .hasFile("tsconfig.json")
+        .containing("\"exclude\": [\"src/test/webapp/component/**/*.ts\"]");
+    }
 
-  @Test
-  void shouldNotDuplicateCypressExclusion() {
-    assertCypressModule(
-      packageJsonFile(),
-      file("src/test/resources/projects/ts-config-with-cypress-exclusions/tsconfig.json", "tsconfig.json")
-    )
-      .hasFile("tsconfig.json")
-      .containing("  \"exclude\": [\"src/test/webapp/component/**/*spec.ts\", \"node_modules\", \"src/test/webapp/component/**/*.ts\"]");
-  }
+    @Test
+    void shouldBuildComponentTestsModuleOnProjectWithTsConfigWithExistingExclusions() {
+      assertCypressComponentTestsModule(
+        packageJsonFile(),
+        file("src/test/resources/projects/ts-config-with-exclusions/tsconfig.json", "tsconfig.json")
+      )
+        .hasFile("tsconfig.json")
+        .containing(
+          "  \"exclude\": [\"src/test/webapp/integration/**/*spec.ts\", \"node_modules\", \"src/test/webapp/component/**/*.ts\"]"
+        );
+    }
 
-  private static JHipsterModuleAsserter assertCypressModule(ModuleFile... files) {
-    JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest()).build();
-
-    JHipsterModule module = factory.buildModule(properties);
-
-    return assertThatModuleWithFiles(module, files)
-      .hasFile("package.json")
-      .containing(nodeDependency("cypress"))
-      .containing(nodeDependency("eslint-plugin-cypress"))
-      .containing(nodeScript("e2e", "npm run test:component"))
-      .containing(nodeScript("e2e:headless", "npm run test:component:headless"))
-      .containing(
-        nodeScript(
-          "test:component",
-          "start-server-and-test start http://localhost:9000 'cypress open --e2e --config-file src/test/webapp/component/cypress-config.ts'"
-        )
+    @Test
+    void shouldNotDuplicateCypressExclusion() {
+      assertCypressComponentTestsModule(
+        packageJsonFile(),
+        file("src/test/resources/projects/ts-config-with-cypress-component-exclusions/tsconfig.json", "tsconfig.json")
       )
-      .containing(
-        nodeScript(
-          "test:component:headless",
-          "start-server-and-test start http://localhost:9000 'cypress run --headless --config-file src/test/webapp/component/cypress-config.ts'"
+        .hasFile("tsconfig.json")
+        .containing("  \"exclude\": [\"src/test/webapp/component/**/*spec.ts\", \"node_modules\", \"src/test/webapp/component/**/*.ts\"]");
+    }
+
+    private static JHipsterModuleAsserter assertCypressComponentTestsModule(ModuleFile... files) {
+      JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest()).build();
+
+      JHipsterModule module = factory.buildComponentTestsModule(properties);
+
+      return assertThatModuleWithFiles(module, files)
+        .hasFile("package.json")
+        .containing(nodeDependency("cypress"))
+        .containing(nodeDependency("eslint-plugin-cypress"))
+        .notContaining(nodeScript("e2e"))
+        .notContaining(nodeScript("e2e:headless"))
+        .containing(
+          nodeScript(
+            "test:component",
+            "start-server-and-test start http://localhost:9000 'cypress open --e2e --config-file src/test/webapp/component/cypress-config.ts'"
+          )
+        )
+        .containing(
+          nodeScript(
+            "test:component:headless",
+            "start-server-and-test start http://localhost:9000 'cypress run --headless --config-file src/test/webapp/component/cypress-config.ts'"
+          )
         )
+        .and()
+        .hasFile("src/test/webapp/component/cypress-config.ts")
+        .containing("baseUrl: 'http://localhost:9000',")
+        .containing("specPattern: 'src/test/webapp/component/**/*.(spec|cy).ts',")
+        .and()
+        .hasPrefixedFiles("src/test/webapp/component", ".eslintrc.cjs", "tsconfig.json")
+        .hasFiles("src/test/webapp/component/common/primary/app/Home.spec.ts")
+        .hasPrefixedFiles("src/test/webapp/component/utils", "Interceptor.ts", "DataSelector.ts");
+    }
+  }
+
+  @Nested
+  class E2ETests {
+
+    @Test
+    void shouldBuildE2eTestsModuleOnProjectWithoutTsConfig() {
+      assertCypressE2ETestsModule(packageJsonFile());
+    }
+
+    @Test
+    void shouldBuildE2eTestsModuleOnProjectWithEmptyTsConfig() {
+      assertCypressE2ETestsModule(packageJsonFile(), file("src/test/resources/projects/empty-ts-config/tsconfig.json", "tsconfig.json"))
+        .hasFile("tsconfig.json")
+        .containing(
+          """
+            },
+            "exclude": ["src/test/webapp/e2e/**/*.ts"]
+          }\
+          """
+        );
+    }
+
+    @Test
+    void shouldBuildE2eTestsModuleOnProjectWithTsConfigWithEmptyExclusions() {
+      assertCypressE2ETestsModule(
+        packageJsonFile(),
+        file("src/test/resources/projects/ts-config-with-empty-exclusions/tsconfig.json", "tsconfig.json")
+      )
+        .hasFile("tsconfig.json")
+        .containing("\"exclude\": [\"src/test/webapp/e2e/**/*.ts\"]");
+    }
+
+    @Test
+    void shouldBuildE2eTestsModuleOnProjectWithTsConfigWithExistingExclusions() {
+      assertCypressE2ETestsModule(
+        packageJsonFile(),
+        file("src/test/resources/projects/ts-config-with-exclusions/tsconfig.json", "tsconfig.json")
+      )
+        .hasFile("tsconfig.json")
+        .containing("  \"exclude\": [\"src/test/webapp/integration/**/*spec.ts\", \"node_modules\", \"src/test/webapp/e2e/**/*.ts\"]");
+    }
+
+    @Test
+    void shouldNotDuplicateCypressExclusion() {
+      assertCypressE2ETestsModule(
+        packageJsonFile(),
+        file("src/test/resources/projects/ts-config-with-cypress-e2e-exclusions/tsconfig.json", "tsconfig.json")
       )
-      .and()
-      .hasFile("src/test/webapp/component/cypress-config.ts")
-      .containing("baseUrl: 'http://localhost:9000',")
-      .and()
-      .hasPrefixedFiles("src/test/webapp/component", ".eslintrc.cjs", "tsconfig.json")
-      .hasFiles("src/test/webapp/component/common/primary/app/Home.spec.ts")
-      .hasPrefixedFiles("src/test/webapp/component/utils", "Interceptor.ts", "DataSelector.ts");
+        .hasFile("tsconfig.json")
+        .containing("  \"exclude\": [\"src/test/webapp/e2e/**/*spec.ts\", \"node_modules\", \"src/test/webapp/e2e/**/*.ts\"]");
+    }
+
+    private static JHipsterModuleAsserter assertCypressE2ETestsModule(ModuleFile... files) {
+      JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest()).build();
+
+      JHipsterModule module = factory.buildE2ETestsModule(properties);
+
+      return assertThatModuleWithFiles(module, files)
+        .hasFile("package.json")
+        .containing(nodeDependency("cypress"))
+        .containing(nodeDependency("eslint-plugin-cypress"))
+        .notContaining(nodeScript("test:component"))
+        .notContaining(nodeScript("test:component:headless"))
+        .containing(nodeScript("e2e", "cypress open --e2e --config-file src/test/webapp/e2e/cypress-config.ts"))
+        .containing(nodeScript("e2e:headless", "cypress run --headless --config-file src/test/webapp/e2e/cypress-config.ts"))
+        .and()
+        .hasFile("src/test/webapp/e2e/cypress-config.ts")
+        .containing("baseUrl: 'http://localhost:9000',")
+        .containing("specPattern: 'src/test/webapp/e2e/**/*.(spec|cy).ts',")
+        .and()
+        .hasPrefixedFiles("src/test/webapp/e2e", ".eslintrc.cjs", "tsconfig.json")
+        .hasFiles("src/test/webapp/e2e/common/primary/app/Home.spec.ts")
+        .hasPrefixedFiles("src/test/webapp/e2e/utils", "Interceptor.ts", "DataSelector.ts");
+    }
   }
 }
diff --git a/src/test/java/tech/jhipster/lite/generator/client/tools/playwright/domain/PlaywrightModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/client/tools/playwright/domain/PlaywrightModuleFactoryTest.java
index 7c35e2400..618f29ebd 100644
--- a/src/test/java/tech/jhipster/lite/generator/client/tools/playwright/domain/PlaywrightModuleFactoryTest.java
+++ b/src/test/java/tech/jhipster/lite/generator/client/tools/playwright/domain/PlaywrightModuleFactoryTest.java
@@ -15,10 +15,10 @@ class PlaywrightModuleFactoryTest {
   private static final PlaywrightModuleFactory factory = new PlaywrightModuleFactory();
 
   @Test
-  void shouldBuildModule() {
+  void shouldBuildComponentTestsModule() {
     JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest()).build();
 
-    JHipsterModule module = factory.buildModule(properties);
+    JHipsterModule module = factory.buildComponentTestsModule(properties);
 
     assertThatModuleWithFiles(module, packageJsonFile())
       .hasFile("package.json")
@@ -44,4 +44,24 @@ class PlaywrightModuleFactoryTest {
       .and()
       .hasPrefixedFiles("src/test/webapp/component/common/primary/app", "Home.spec.ts", "Home-Page.ts");
   }
+
+  @Test
+  void shouldBuildE2ETestsModule() {
+    JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest()).build();
+
+    JHipsterModule module = factory.buildE2ETestsModule(properties);
+
+    assertThatModuleWithFiles(module, packageJsonFile())
+      .hasFile("package.json")
+      .containing(nodeDependency("@playwright/test"))
+      .containing(nodeScript("e2e", "playwright test --ui --config src/test/webapp/e2e/playwright.config.ts"))
+      .containing(nodeScript("e2e:headless", "playwright test --config src/test/webapp/e2e/playwright.config.ts"))
+      .and()
+      .hasFile("src/test/webapp/e2e/playwright.config.ts")
+      .containing("baseURL: process.env.URL || 'http://localhost:9000',")
+      .containing("outputFolder: '../../../../target/playwright-report/e2e-tests'")
+      .containing("outputDir: '../../../../target/playwright-results/e2e-tests'")
+      .and()
+      .hasPrefixedFiles("src/test/webapp/e2e/common/primary/app", "Home.spec.ts", "Home-Page.ts");
+  }
 }
diff --git a/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/JHipsterModulesAssertions.java b/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/JHipsterModulesAssertions.java
index 52bce75b0..67587d576 100644
--- a/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/JHipsterModulesAssertions.java
+++ b/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/JHipsterModulesAssertions.java
@@ -100,8 +100,12 @@ public final class JHipsterModulesAssertions {
     return "\"" + dependency + "\": \"";
   }
 
+  public static String nodeScript(String key) {
+    return "\"" + key + "\": \"";
+  }
+
   public static String nodeScript(String key, String command) {
-    return "\"" + key + "\": \"" + command + "\"";
+    return nodeScript(key) + command + "\"";
   }
 
   private static void addFilesToProject(JHipsterProjectFolder project, ModuleFile... files) {
diff --git a/src/test/resources/projects/ts-config-with-cypress-exclusions/tsconfig.json b/src/test/resources/projects/ts-config-with-cypress-component-exclusions/tsconfig.json
similarity index 100%
rename from src/test/resources/projects/ts-config-with-cypress-exclusions/tsconfig.json
rename to src/test/resources/projects/ts-config-with-cypress-component-exclusions/tsconfig.json
diff --git a/src/test/resources/projects/ts-config-with-cypress-e2e-exclusions/tsconfig.json b/src/test/resources/projects/ts-config-with-cypress-e2e-exclusions/tsconfig.json
new file mode 100644
index 000000000..dad7641ec
--- /dev/null
+++ b/src/test/resources/projects/ts-config-with-cypress-e2e-exclusions/tsconfig.json
@@ -0,0 +1,26 @@
+{
+  "compilerOptions": {
+    "target": "ESNext",
+    "useDefineForClassFields": true,
+    "lib": ["DOM", "DOM.Iterable", "ESNext"],
+    "allowJs": false,
+    "skipLibCheck": true,
+    "esModuleInterop": false,
+    "allowSyntheticDefaultImports": true,
+    "strict": true,
+    "forceConsistentCasingInFileNames": true,
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "noEmit": true,
+    "jsx": "react-jsx",
+    "composite": false,
+    "module": "esnext",
+    "moduleResolution": "node",
+    "baseUrl": "src",
+    "paths": {
+      "@/*": ["main/webapp/app/*"]
+    }
+  },
+  "include": ["vite.config.ts", "src"],
+  "exclude": ["src/test/webapp/e2e/**/*spec.ts", "node_modules", "src/test/webapp/e2e/**/*.ts"]
+}
diff --git a/src/test/resources/projects/ts-config-with-exclusions/tsconfig.json b/src/test/resources/projects/ts-config-with-exclusions/tsconfig.json
index 459c2b27e..6008450b0 100644
--- a/src/test/resources/projects/ts-config-with-exclusions/tsconfig.json
+++ b/src/test/resources/projects/ts-config-with-exclusions/tsconfig.json
@@ -22,5 +22,5 @@
     }
   },
   "include": ["vite.config.ts", "src"],
-  "exclude": ["src/test/webapp/component/**/*spec.ts", "node_modules"]
+  "exclude": ["src/test/webapp/integration/**/*spec.ts", "node_modules"]
 }
diff --git a/tests-ci/generate.sh b/tests-ci/generate.sh
index 95d2cb61e..1d77d8701 100755
--- a/tests-ci/generate.sh
+++ b/tests-ci/generate.sh
@@ -182,7 +182,10 @@ elif [[ $application == 'fullapp' ]]; then
   applyModules "hibernate-2nd-level-cache"
 
   frontend_server_plugin
-  applyModules "vue-core" "cypress"
+  applyModules \
+    "vue-core" \
+    "cypress-component-tests" \
+    "playwright-e2e"
 
 elif [[ $application == 'oauth2app' ]]; then
   init_server
@@ -365,7 +368,7 @@ elif [[ $application == 'angularapp' ]]; then
   frontend_server_plugin
   applyModules \
     "angular-core" \
-    "cypress"
+    "cypress-component-tests"
 
   cucumber_with_jwt
 
@@ -398,7 +401,7 @@ elif [[ $application == 'reactapp' ]]; then
   frontend_server_plugin
   applyModules \
   "react-core" \
-  "cypress"
+  "cypress-component-tests"
 
   cucumber_with_jwt
 
@@ -413,7 +416,8 @@ elif [[ $application == 'vueapp' ]]; then
   applyModules \
   "vue-core" \
   "vue-pinia" \
-  "playwright"
+  "playwright-component-tests" \
+  "cypress-e2e"
 
 elif [[ $application == 'svelteapp' ]]; then
   init_server