From cfd6a1dd247ecf710478c5884d762d7b10ee4f6f Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 20 Jan 2025 19:25:18 -0500 Subject: [PATCH 1/4] Check if no Liberty projects are detected in workspace when creating a Run/Debug config Signed-off-by: Paul Gooderham --- .../openliberty/tools/intellij/it/UIBotTestUtils.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java b/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java index 3868b9c05..0284ad6d5 100644 --- a/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java +++ b/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java @@ -2009,6 +2009,15 @@ public static void createLibertyConfiguration(RemoteRobot remoteRobot, String cf DialogFixture.byTitle("Run/Debug Configurations"), Duration.ofSeconds(10)); + // The new configuration should refer to one of the Liberty projects by default. + // If there are no Liberty projects detected in the workspace then the combobox + // will have zero values. + Locator projectComboLocator = byXpath("//div[@class='ComboBox']"); + ComboBoxFixture projectCombo = addProjectDialog.comboBox(projectComboLocator); + if (projectCombo.listValues().isEmpty()) { + throw new NoSuchElementException("Liberty project field contains no elements"); + } + // Find the new configuration's name text field and give it a name. Locator locator = byXpath("//div[@class='JTextField']"); @@ -2048,6 +2057,8 @@ public static void createLibertyConfiguration(RemoteRobot remoteRobot, String cf "The Apply button on the add config dialog was not enabled", applyButton::isEnabled); applyButton.click(); + + // Change which button we click to complete the operation exitButtonText = "OK"; } finally { // Exit the Run/Debug Configurations dialog. From 65e8ec1dae2f54309d4f10c81fdb97edf0a2c771 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 21 Jan 2025 14:17:54 -0500 Subject: [PATCH 2/4] Update comments to clarify meaning of class variables Signed-off-by: Paul Gooderham --- .../tools/intellij/it/GradleSingleModMPSIDProjectTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPSIDProjectTest.java b/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPSIDProjectTest.java index 65a4e30e5..660acc625 100644 --- a/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPSIDProjectTest.java +++ b/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPSIDProjectTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2024 IBM Corporation. + * Copyright (c) 2024, 2025 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -25,12 +25,12 @@ public class GradleSingleModMPSIDProjectTest extends SingleModMPProjectTestCommon { /** - * Single module Microprofile project name. + * Single module Microprofile project name specified in file settings.gradle. */ private static final String SM_MP_PROJECT_NAME = "singleModGradleMP"; /** - * Single module Microprofile project name with space. + * Project name of Microprofile single module in file settings-copy.gradle. */ private static final String SM_MP_PROJECT_NAME_NEW = "singleMod GradleMP"; From eb1497035cd48d75b29a700a49a37e625d264cfb Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 21 Jan 2025 14:21:36 -0500 Subject: [PATCH 3/4] Add new test case to create new run config for issue 1202 Signed-off-by: Paul Gooderham --- .../it/GradleSingleModMPCfgProjectTest.java | 101 ++++++++++ .../it/MavenSingleModMPCfgProjectTest.java | 78 ++++++++ .../it/SingleModMPProjectCfgTestCommon.java | 189 ++++++++++++++++++ 3 files changed, 368 insertions(+) create mode 100644 src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPCfgProjectTest.java create mode 100755 src/test/java/io/openliberty/tools/intellij/it/MavenSingleModMPCfgProjectTest.java create mode 100644 src/test/java/io/openliberty/tools/intellij/it/SingleModMPProjectCfgTestCommon.java diff --git a/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPCfgProjectTest.java b/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPCfgProjectTest.java new file mode 100644 index 000000000..89086496e --- /dev/null +++ b/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPCfgProjectTest.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package io.openliberty.tools.intellij.it; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +/** + * Test Liberty Tools creation of a Run/Debug configuration without a null pointer exception. + */ +public class GradleSingleModMPCfgProjectTest extends SingleModMPProjectCfgTestCommon { + + /** + * Single module Microprofile project name specified in file settings.gradle. + */ + private static final String SM_MP_PROJECT_NAME = "singleModGradleMP"; + + /** + * Project name of Microprofile single module in file settings-copy.gradle. + */ + private static final String SM_MP_PROJECT_NAME_NEW = "singleMod GradleMP"; + + /** + * The path to the folder containing the test projects. + */ + private static final String PROJECTS_PATH = Paths.get("src", "test", "resources", "projects", "gradle").toAbsolutePath().toString(); + + /** + * The path to the folder containing the test projects, including directories with spaces. + */ + private static final String PROJECTS_PATH_NEW = Paths.get("src", "test", "resources", "projects", "gsample2").toAbsolutePath().toString(); + + /** + * Prepares the environment for test execution. + */ + @BeforeAll + public static void setup() { + try { + // Copy the directory to allow renaming. + TestUtils.copyDirectory(PROJECTS_PATH, PROJECTS_PATH_NEW); + + Path pathNew = Path.of(PROJECTS_PATH_NEW); + Path projectDirPath = pathNew.resolve(SM_MP_PROJECT_NAME); + + // Define paths for the original and copy of settings.gradle + Path originalPath = projectDirPath.resolve("settings.gradle"); + Path originalPathCopy = projectDirPath.resolve("settings-copy.gradle"); + + // Rename settings.gradle to settings-duplicate.gradle + Files.move(originalPath, originalPath.resolveSibling("settings-duplicate.gradle")); + // Rename settings-copy.gradle to settings.gradle + Files.move(originalPathCopy, originalPathCopy.resolveSibling("settings.gradle")); + + Path projectDirNewPath = pathNew.resolve(SM_MP_PROJECT_NAME_NEW); + + // Rename the project directory to a new name, replacing it if it already exists + Files.move(projectDirPath, projectDirNewPath, StandardCopyOption.REPLACE_EXISTING); + + // Prepare the environment with the new project path and name + prepareEnv(PROJECTS_PATH_NEW, SM_MP_PROJECT_NAME_NEW); + + } catch (IOException e) { + System.err.println("Setup failed: " + e.getMessage()); + e.printStackTrace(); + Assertions.fail("Test setup failed due to an IOException: " + e.getMessage()); + } + } + + /** + * Cleanup includes deleting the created project path. + */ + @AfterAll + public static void cleanup() { + try { + closeProjectView(); + } finally { + deleteDirectoryIfExists(PROJECTS_PATH_NEW); + } + } + + GradleSingleModMPCfgProjectTest() { + // set the new locations for the test, not the original locations + setProjectsDirPath(PROJECTS_PATH_NEW); + setSmMPProjectName(SM_MP_PROJECT_NAME_NEW); + setWLPInstallPath("build"); + } +} \ No newline at end of file diff --git a/src/test/java/io/openliberty/tools/intellij/it/MavenSingleModMPCfgProjectTest.java b/src/test/java/io/openliberty/tools/intellij/it/MavenSingleModMPCfgProjectTest.java new file mode 100755 index 000000000..52054c850 --- /dev/null +++ b/src/test/java/io/openliberty/tools/intellij/it/MavenSingleModMPCfgProjectTest.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package io.openliberty.tools.intellij.it; + +import com.intellij.remoterobot.stepsProcessing.StepLogger; +import com.intellij.remoterobot.stepsProcessing.StepWorker; +import io.openliberty.tools.intellij.it.SingleModMPProjectTestCommon; +import io.openliberty.tools.intellij.it.TestUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Tests Liberty Tools actions using a single module MicroProfile Maven project. + */ +public class MavenSingleModMPCfgProjectTest extends SingleModMPProjectCfgTestCommon { + + /** + * Single module Microprofile project name. + */ + private static final String SM_MP_PROJECT_NAME = "singleModMavenMP"; + + /** + * The path to the folder containing the test projects. + */ + private static final String PROJECTS_PATH = Paths.get("src", "test", "resources", "projects", "maven").toAbsolutePath().toString(); + + /** + * The path to the folder containing the test projects, including directories with spaces. + */ + private static final String PROJECTS_PATH_NEW = Paths.get("src", "test", "resources", "projects", "msample2").toAbsolutePath().toString(); + + /** + * Prepares the environment for test execution. + */ + @BeforeAll + public static void setup() { + try { + StepWorker.registerProcessor(new StepLogger()); + // Copy the directory from PROJECTS_PATH to PROJECTS_PATH_NEW + TestUtils.copyDirectory(PROJECTS_PATH, PROJECTS_PATH_NEW); + prepareEnv(PROJECTS_PATH_NEW, SM_MP_PROJECT_NAME); + } catch (IOException e) { + System.err.println("Setup failed: " + e.getMessage()); + e.printStackTrace(); + Assertions.fail("Test setup failed due to an IOException: " + e.getMessage()); + } + } + + /** + * Cleanup includes deleting the created project path. + */ + @AfterAll + public static void cleanup() { + try { + closeProjectView(); + } finally { + deleteDirectoryIfExists(PROJECTS_PATH_NEW); + } + } + + MavenSingleModMPCfgProjectTest() { + setProjectsDirPath(PROJECTS_PATH_NEW); + setSmMPProjectName(SM_MP_PROJECT_NAME); + setWLPInstallPath(Paths.get("target", "liberty").toString()); + } +} diff --git a/src/test/java/io/openliberty/tools/intellij/it/SingleModMPProjectCfgTestCommon.java b/src/test/java/io/openliberty/tools/intellij/it/SingleModMPProjectCfgTestCommon.java new file mode 100644 index 000000000..fecc6f27c --- /dev/null +++ b/src/test/java/io/openliberty/tools/intellij/it/SingleModMPProjectCfgTestCommon.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package io.openliberty.tools.intellij.it; + +import com.automation.remarks.junit5.Video; +import com.intellij.remoterobot.RemoteRobot; +import org.junit.jupiter.api.*; + +import java.io.File; +import java.nio.file.Paths; +import java.time.Duration; + +import static com.intellij.remoterobot.utils.RepeatUtilsKt.waitForIgnoringError; + +/** + * Holds common tests that use a single module MicroProfile project. + */ +public abstract class SingleModMPProjectCfgTestCommon { + + // In this test case the environment has been set up so that there is a new project + // that has not been used in a previous execution of IntelliJ. Also, the Liberty explorer + // or dashboard has not been opened as it is in all other tests. This means the LibertyModules + // object is not yet populated. + // When we create a new Run/Debug configuration, the "Liberty project" field is populated by + // default with one of the build files from one of the Liberty projects in the workspace. If + // there is no default build file then there will be a Null Pointer Exception if we press Run. + // The following method will throw a NoSuchElementException if there are no Liberty projects + // detected when the Edit Liberty Run/Debug Configuration dialog is opened. + + /** + * URL to display the UI Component hierarchy. This is used to obtain xPath related + * information to find UI components. + */ + public static final String REMOTE_BOT_URL = "http://localhost:8082"; + + /** + * The remote robot object. + */ + public static final RemoteRobot remoteRobot = new RemoteRobot(REMOTE_BOT_URL); + + /** + * Single module Microprofile project name. + */ + private String smMpProjectName = null; + + /** + * The path to the folder containing the test projects. + */ + private String projectsPath = null; + + /** + * Relative location of the WLP installation. + */ + private String wlpInstallPath = null; + + /** + * Returns the path where the Liberty server was installed. + * + * @return The path where the Liberty server was installed. + */ + public String getWLPInstallPath() { + return wlpInstallPath; + } + public void setWLPInstallPath(String path) { + wlpInstallPath = path; + } + + /** + * Returns the projects directory path. + * + * @return The projects directory path. + */ + public String getProjectsDirPath() { + return projectsPath; + } + public void setProjectsDirPath(String path) { + projectsPath = path; + } + + /** + * Returns the name of the single module MicroProfile project. + * + * @return The name of the single module MicroProfile project. + */ + public String getSmMPProjectName() { + return smMpProjectName; + } + public void setSmMPProjectName(String name) { + smMpProjectName = name; + } + + /** + * Processes actions before each test. + * + * @param info Test information. + */ + @BeforeEach + public void beforeEach(TestInfo info) { + TestUtils.printTrace(TestUtils.TraceSevLevel.INFO, this.getClass().getSimpleName() + "." + info.getDisplayName() + ". Entry"); + } + + /** + * Processes actions after each test. + * + * @param info Test information. + */ + @AfterEach + public void afterEach(TestInfo info) { + TestUtils.printTrace(TestUtils.TraceSevLevel.INFO, this.getClass().getSimpleName() + "." + info.getDisplayName() + ". Exit"); + TestUtils.detectFatalError(); + } + + /** + * Cleanup. + */ + @AfterAll + public static void cleanup() { + closeProjectView(); + } + + /** + * Close project. + */ + protected static void closeProjectView() { + if (!remoteRobot.isMac()) { + UIBotTestUtils.runActionFromSearchEverywherePanel(remoteRobot, "Close All Tabs", 3); + UIBotTestUtils.runActionFromSearchEverywherePanel(remoteRobot, "Compact Mode", 3); + } + UIBotTestUtils.closeLibertyToolWindow(remoteRobot); + UIBotTestUtils.closeProjectView(remoteRobot); + UIBotTestUtils.closeProjectFrame(remoteRobot); + UIBotTestUtils.validateProjectFrameClosed(remoteRobot); + } + + /** + * Create a run configuration and see if it caused a null pointer exception + */ + @Test + @Video + public void testCreateRunConfigAction() { + String testName = "testCreateRunConfigAction"; + // Remove all other configurations first. + UIBotTestUtils.deleteLibertyRunConfigurations(remoteRobot); + + // Add a new Liberty configurations. Throws an exception if there is an error. + UIBotTestUtils.createLibertyConfiguration(remoteRobot, "newCfg1"); + } + + /** + * Prepares the environment to run the tests. + * + * @param projectPath The path of the project. + * @param projectName The name of the project being used. + */ + public static void prepareEnv(String projectPath, String projectName) { + TestUtils.printTrace(TestUtils.TraceSevLevel.INFO, + "prepareEnv. Entry. ProjectPath: " + projectPath + ". ProjectName: " + projectName); + waitForIgnoringError(Duration.ofMinutes(4), Duration.ofSeconds(5), "Wait for IDE to start", "IDE did not start", () -> remoteRobot.callJs("true")); + UIBotTestUtils.findWelcomeFrame(remoteRobot); + UIBotTestUtils.importProject(remoteRobot, projectPath, projectName); + UIBotTestUtils.openProjectView(remoteRobot); + if (!remoteRobot.isMac()) { + UIBotTestUtils.runActionFromSearchEverywherePanel(remoteRobot, "Compact Mode", 3); + } + // IntelliJ does not start building and indexing until the Project View is open + UIBotTestUtils.waitForIndexing(remoteRobot); + TestUtils.printTrace(TestUtils.TraceSevLevel.INFO, + "prepareEnv. Exit. ProjectName: " + projectName); + } + + /** + * Deletes the directory specified by dirPath if it exists. + * + * @param dirPath The path to the directory that may be deleted. + */ + public static void deleteDirectoryIfExists(String dirPath) { + File dir = new File(dirPath); + if (dir.exists()) { + TestUtils.deleteDirectory(dir); + } + } +} \ No newline at end of file From 2640e281e8d5883a362b8aa344bbbc3a606abbf9 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 23 Jan 2025 16:34:24 -0500 Subject: [PATCH 4/4] Update the comments for code review Signed-off-by: Paul Gooderham --- .../tools/intellij/it/GradleSingleModMPCfgProjectTest.java | 5 +++-- .../tools/intellij/it/MavenSingleModMPCfgProjectTest.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPCfgProjectTest.java b/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPCfgProjectTest.java index 89086496e..2e725bf7c 100644 --- a/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPCfgProjectTest.java +++ b/src/test/java/io/openliberty/tools/intellij/it/GradleSingleModMPCfgProjectTest.java @@ -20,7 +20,8 @@ import java.nio.file.StandardCopyOption; /** - * Test Liberty Tools creation of a Run/Debug configuration without a null pointer exception. + * Test Liberty Tools creation of a Run/Debug configuration without a null pointer exception + * using a single module MicroProfile Gradle project. */ public class GradleSingleModMPCfgProjectTest extends SingleModMPProjectCfgTestCommon { @@ -40,7 +41,7 @@ public class GradleSingleModMPCfgProjectTest extends SingleModMPProjectCfgTestCo private static final String PROJECTS_PATH = Paths.get("src", "test", "resources", "projects", "gradle").toAbsolutePath().toString(); /** - * The path to the folder containing the test projects, including directories with spaces. + * The path to the folder containing the copy of the test project. */ private static final String PROJECTS_PATH_NEW = Paths.get("src", "test", "resources", "projects", "gsample2").toAbsolutePath().toString(); diff --git a/src/test/java/io/openliberty/tools/intellij/it/MavenSingleModMPCfgProjectTest.java b/src/test/java/io/openliberty/tools/intellij/it/MavenSingleModMPCfgProjectTest.java index 52054c850..3bddf7bf1 100755 --- a/src/test/java/io/openliberty/tools/intellij/it/MavenSingleModMPCfgProjectTest.java +++ b/src/test/java/io/openliberty/tools/intellij/it/MavenSingleModMPCfgProjectTest.java @@ -22,7 +22,8 @@ import java.nio.file.Paths; /** - * Tests Liberty Tools actions using a single module MicroProfile Maven project. + * Test Liberty Tools creation of a Run/Debug configuration without a null pointer exception + * using a single module MicroProfile Maven project. */ public class MavenSingleModMPCfgProjectTest extends SingleModMPProjectCfgTestCommon { @@ -37,7 +38,7 @@ public class MavenSingleModMPCfgProjectTest extends SingleModMPProjectCfgTestCom private static final String PROJECTS_PATH = Paths.get("src", "test", "resources", "projects", "maven").toAbsolutePath().toString(); /** - * The path to the folder containing the test projects, including directories with spaces. + * The path to the folder containing the copy of the test project. */ private static final String PROJECTS_PATH_NEW = Paths.get("src", "test", "resources", "projects", "msample2").toAbsolutePath().toString();