Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
kubernetes-client = "7.3.0"
devtools-common = "1.9.11-SNAPSHOT"
jackson-core = "2.19.0"
commons-lang3 = "3.12.0"
commons-lang3 = "3.17.0"
assertj-core = "3.22.0"
mockito = "5.12.0"
mockito-kotlin = "2.2.0"
devtools-common-ui-test = "0.4.4-SNAPSHOT"
junit-platform = "1.11.3"
junit-jupiter = "5.11.3"
gson = "2.8.9"
mockito-kotlin = "5.4.0"
devtools-common-ui-test = "0.4.5-SNAPSHOT"
junit-platform = "1.12.2"
junit-jupiter = "5.12.2"
gson = "2.10.1"
snakeyaml = "2.2"
json = "20250517"
everit-json-schema = "1.14.6"
Expand All @@ -31,7 +31,7 @@ commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version.
kotlin-test-junit = { group = "org.jetbrains.kotlin", name = "kotlin-test-junit", version.ref = "kotlinJvm" }
assertj-core = { group = "org.assertj", name = "assertj-core", version.ref = "assertj-core" }
mockito = { group = "org.mockito", name = "mockito-core", version.ref = "mockito" }
mockito-kotlin = { group = "com.nhaarman.mockitokotlin2", name = "mockito-kotlin", version.ref = "mockito-kotlin" }
mockito-kotlin = { group = "org.mockito.kotlin", name = "mockito-kotlin", version.ref = "mockito-kotlin" }
devtools-common-ui-test = { group = "com.redhat.devtools.intellij", name = "intellij-common-ui-test-library", version.ref = "devtools-common-ui-test" }
junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform-launcher", version.ref = "junit-platform" }
junit-platform-suite = { group = "org.junit.platform", name = "junit-platform-suite", version.ref = "junit-platform" }
Expand Down
6 changes: 4 additions & 2 deletions scripts/build_local.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#!/usr/bin/env bash
#!/usr/bin/env bash

# Note: run from root
# This is used to run and connect minikube cluster

pgrep -f "[m]inikube" >/dev/null || minikube start || { echo 'Cannot start minikube.'; exit 1; }
eval "$(minikube docker-env)" || { echo 'Cannot switch to minikube docker'; exit 1; }
eval "$(./minikube docker-env)" || { echo 'Cannot switch to minikube docker'; exit 1; }
kubectl create deployment hello-minikube --image=kicbase/echo-server:1.0
kubectl expose deployment hello-minikube --type=NodePort --port=8080
kubectl config use-context minikube

# Check if cluster is in config, if not - here will be the empty labels
Expand Down
39 changes: 27 additions & 12 deletions src/it/java/org/jboss/tools/intellij/kubernetes/BasicTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,28 @@
import com.intellij.remoterobot.fixtures.ComponentFixture;
import com.intellij.remoterobot.fixtures.dataExtractor.RemoteText;
import com.redhat.devtools.intellij.commonuitest.UITestRunner;
import com.redhat.devtools.intellij.commonuitest.fixtures.dialogs.FlatWelcomeFrame;
import com.redhat.devtools.intellij.commonuitest.fixtures.mainidewindow.toolwindowspane.ToolWindowPane;
import com.redhat.devtools.intellij.commonuitest.utils.constants.XPathDefinitions;
import com.redhat.devtools.intellij.commonuitest.utils.project.CreateCloseUtils;
import com.redhat.devtools.intellij.commonuitest.utils.runner.IntelliJVersion;
import com.redhat.devtools.intellij.commonuitest.fixtures.mainidewindow.toolwindowspane.ToolWindowPane;
import com.redhat.devtools.intellij.commonuitest.utils.testextension.ScreenshotAfterTestFailExtension;
import org.jboss.tools.intellij.kubernetes.fixtures.mainidewindow.KubernetesToolsFixture;

import org.jboss.tools.intellij.kubernetes.tests.ClusterConnectedTest;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static com.intellij.remoterobot.search.locators.Locators.byXpath;
import static com.intellij.remoterobot.stepsProcessing.StepWorkerKt.step;
import static com.intellij.remoterobot.utils.RepeatUtilsKt.waitFor;

import org.jboss.tools.intellij.kubernetes.tests.ClusterConnectedTest;
import org.jboss.tools.intellij.kubernetes.tests.CreateResourceByEditTest;
import org.jboss.tools.intellij.kubernetes.tests.OpenResourceEditorTest;
import org.jboss.tools.intellij.kubernetes.tests.EditResourceTest;
import org.jboss.tools.intellij.kubernetes.tests.CreateAnotherTypeResourceByEditTest;
import org.junit.jupiter.api.extension.ExtendWith;

import java.time.Duration;
import java.util.List;
Expand All @@ -40,14 +45,21 @@
*
* @author olkornii@redhat.com
*/
@ExtendWith(ScreenshotAfterTestFailExtension.class)
public class BasicTests {

private static RemoteRobot robot;
private static ComponentFixture kubernetesViewTree;
private static final String CLUSTER_NAME = "minikube";

@BeforeAll
public static void connect() {
robot = UITestRunner.runIde(IntelliJVersion.COMMUNITY_V_2024_1, 8580);
robot = UITestRunner.runIde(IntelliJVersion.COMMUNITY_V_2023_1, 8580);

FlatWelcomeFrame flatWelcomeFrame = robot.find(FlatWelcomeFrame.class, Duration.ofSeconds(10));
flatWelcomeFrame.disableNotifications();
flatWelcomeFrame.preventTipDialogFromOpening();

CreateCloseUtils.createEmptyProject(robot, "test-project");
openKubernetesTab();

Expand All @@ -58,39 +70,42 @@ public static void connect() {

@AfterAll
public static void closeIde() {
CreateCloseUtils.closeProject(robot);
FlatWelcomeFrame flatWelcomeFrame = robot.find(FlatWelcomeFrame.class, Duration.ofSeconds(10));
flatWelcomeFrame.clearWorkspace();
UITestRunner.closeIde();
}

@Test
public void checkClusterConnected() {
step("New Empty Project", () -> ClusterConnectedTest.checkClusterConnected(kubernetesViewTree));
step("New Empty Project", () -> new ClusterConnectedTest(CLUSTER_NAME, kubernetesViewTree, robot).checkClusterConnected());
}

@Test
public void openResourceEditor() {
step("open Resource Editor", () -> OpenResourceEditorTest.checkResourceEditor(robot, kubernetesViewTree));
step("Open Resource Editor", () -> new OpenResourceEditorTest(CLUSTER_NAME, kubernetesViewTree, robot).checkResourceEditor());
}

@Test
public void editResource() {
step("edit Resource", () -> EditResourceTest.editResource(robot, kubernetesViewTree));
step("Edit Resource", () -> new EditResourceTest(CLUSTER_NAME, kubernetesViewTree, robot).editResource());
}

@Test
public void createResourceByEdit() {
step("create Resource", () -> CreateResourceByEditTest.createResourceByEdit(robot, kubernetesViewTree));
step("Create Resource", () -> new CreateResourceByEditTest(CLUSTER_NAME, kubernetesViewTree, robot).createResourceByEdit());

step("delete Resource", () -> CreateResourceByEditTest.deleteResource(robot, kubernetesViewTree));
step("Delete Resource", () -> new CreateResourceByEditTest(CLUSTER_NAME, kubernetesViewTree, robot).deleteResource());
}

// @Test
@Test
public void createAnotherResourceTypeByEdit() {
step("create another type of Resource", () -> CreateAnotherTypeResourceByEditTest.createAnotherTypeResourceByEdit(robot, kubernetesViewTree));
step("Create another type of Resource", () -> new CreateAnotherTypeResourceByEditTest(CLUSTER_NAME, kubernetesViewTree, robot).createAnotherTypeResourceByEdit());
}

private static void openKubernetesTab(){
final ToolWindowPane toolWindowPane = robot.find(ToolWindowPane.class, Duration.ofSeconds(5));
toolWindowPane.stripeButton("Kubernetes", false).click();
ToolWindowPane toolWindowToolbar = robot.find(ToolWindowPane.class, Duration.ofSeconds(10));
toolWindowToolbar.button(byXpath(XPathDefinitions.label("Kubernetes"))).click();
}

private static boolean isKubernetesViewTreeAvailable(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,162 +14,113 @@
import com.intellij.remoterobot.fixtures.ComponentFixture;
import com.intellij.remoterobot.fixtures.dataExtractor.RemoteText;
import com.intellij.remoterobot.utils.Keyboard;
import com.intellij.remoterobot.utils.WaitForConditionTimeoutException;
import com.redhat.devtools.intellij.commonuitest.fixtures.dialogs.errors.IdeFatalErrorsDialog;
import org.assertj.swing.core.MouseButton;
import org.jboss.tools.intellij.kubernetes.fixtures.mainidewindow.IdeStatusBarFixture;

import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.event.KeyEvent;
import java.time.Duration;
import java.util.List;
import java.util.Optional;

import static com.intellij.remoterobot.search.locators.Locators.byXpath;
import static com.intellij.remoterobot.utils.RepeatUtilsKt.waitFor;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

/**
* @author olkornii@redhat.com
*/
public abstract class AbstractKubernetesTest {

public static void openResourceContentList(String[] path, ComponentFixture kubernetesViewTree){
openClusterContent(kubernetesViewTree);
for (String resourceForOpen : path){
kubernetesViewTree.findText(resourceForOpen).doubleClick(MouseButton.LEFT_BUTTON); // open Nodes content
try {
Thread.sleep(3000); // sleep for few seconds, cluster need some time to reload nodes
} catch (InterruptedException e) {
e.printStackTrace();
}
waitFor(Duration.ofSeconds(15), Duration.ofSeconds(1), "Resources is not available.", () -> isResourcesLoaded(kubernetesViewTree));
}
}
protected static final String NODES = "Nodes";
protected static final String resourceName = "hello-minikube"; // resource created in script
protected final ComponentFixture kubernetesViewTree;
protected final RemoteRobot robot;
protected final String clusterName;

public static boolean isResourcesLoaded(ComponentFixture kubernetesViewTree){
List<RemoteText> allTextFromTree = kubernetesViewTree.findAllText();
for (RemoteText actualText : allTextFromTree){
if (actualText.getText().contains("loading...")){
return false;
}
}
return true;
AbstractKubernetesTest(String clusterName, ComponentFixture kubernetesViewTree, RemoteRobot remoteRobot) {
this.clusterName = clusterName;
this.kubernetesViewTree = kubernetesViewTree;
this.robot = remoteRobot;
}

public static void openClusterContent(ComponentFixture kubernetesViewTree){
List<RemoteText> kubernetesToolsText = kubernetesViewTree.findAllText();
boolean needClickOnMinikube = true;
for (RemoteText findNodes : kubernetesToolsText){
if (findNodes.getText().contains("Nodes")){
needClickOnMinikube = false;
break;
public void openResourceContentList(String[] path){
for (String resourceToOpen : path){
List<RemoteText> findings = kubernetesViewTree.findAllText(resourceToOpen);
if (findings.isEmpty()){
fail("Can't find resource " + resourceToOpen);
}
kubernetesViewTree.findText(resourceToOpen).doubleClick(MouseButton.LEFT_BUTTON); // open resource content
waitFor(Duration.ofSeconds(15), Duration.ofSeconds(1), "Resource to be available.", this::isResourcesLoaded);
}
if (needClickOnMinikube){
String clusterText = kubernetesViewTree.findAllText().get(0).getText();
kubernetesViewTree.findText(clusterText).doubleClick(MouseButton.LEFT_BUTTON);
}
waitFor(Duration.ofSeconds(15), Duration.ofSeconds(1), "Kubernetes Tree View is not available.", () -> isNodesOpened(kubernetesViewTree));
}

public static boolean isNodesOpened(ComponentFixture kubernetesViewTree){
List<RemoteText> allTextFromTree = kubernetesViewTree.findAllText();
for (RemoteText actualText : allTextFromTree){
if (actualText.getText().contains("Nodes")){
return true;
}
}
return false;
public boolean isResourcesLoaded(){
return kubernetesViewTree.findAllText().stream().noneMatch(remoteText -> remoteText.getText().contains("loading..."));
}

public static RemoteText getResourceByIdInParent(String parentName, int id, ComponentFixture kubernetesViewTree){
List<RemoteText> kubernetesToolsText = kubernetesViewTree.findAllText();
int parentId = 0;
for (RemoteText findParent : kubernetesToolsText){
if (findParent.getText().contains(parentName)){
break;
}
parentId++;
}
return kubernetesViewTree.findAllText().get(parentId + id + 1);
protected void openClusterContent(){
kubernetesViewTree.findText(clusterName).doubleClick(MouseButton.LEFT_BUTTON);
waitFor(Duration.ofSeconds(15), Duration.ofSeconds(1), "Kubernetes Tree View to be available.", this::isNodesOpened);
}

public static void hideClusterContent(ComponentFixture kubernetesViewTree){
String clusterText = kubernetesViewTree.findAllText().get(0).getText();
kubernetesViewTree.findText(clusterText).doubleClick(); // hide cluster content
public boolean isNodesOpened(){
return kubernetesViewTree.findAllText().stream().anyMatch(remoteText -> remoteText.getText().equals(NODES));
}

public static boolean isResourceCreated(ComponentFixture kubernetesViewTree, String resourceName, boolean hardCompare){
List<RemoteText> kubernetesToolsText = kubernetesViewTree.findAllText();
public RemoteText getFirstResourceInNodes(){
openClusterContent();
openResourceContentList(new String[]{NODES});
List<RemoteText> allVisibleElements = kubernetesViewTree.findAllText();
Optional<RemoteText> resourceText = allVisibleElements.stream().filter(remoteText -> remoteText.getText().equals(NODES)).findFirst();
assertTrue(resourceText.isPresent());
return allVisibleElements.get(allVisibleElements.indexOf(resourceText.get())+1);
}

if (hardCompare){
for (RemoteText findNewResource : kubernetesToolsText){
if (resourceName.equals(findNewResource.getText())){
return true;
}
}
} else {
for (RemoteText findNewResource : kubernetesToolsText){
if (findNewResource.getText().contains(resourceName)){
return true;
}
}
}
return false;
/**
* open a resource under the 'Nodes' item
* @param resourceName the resource to open
* @return the remoteText found with that name
*/
public RemoteText getNamedResourceInNodes(String resourceName){
openClusterContent();
openResourceContentList(new String[]{NODES});
return getResource(resourceName);
}

public static boolean isResourceDeleted(ComponentFixture kubernetesViewTree, String resourceName){
List<RemoteText> kubernetesToolsText = kubernetesViewTree.findAllText();
for (RemoteText findNewResource : kubernetesToolsText){
if (resourceName.equals(findNewResource.getText())){
return false;
}
}
return true;
protected RemoteText getResource(String resourceName){
waitFor(Duration.ofSeconds(15), Duration.ofSeconds(1), "Resource to be available.", () -> kubernetesViewTree.findAllText().stream().anyMatch(remoteText -> remoteText.getText().startsWith(resourceName)));
List<RemoteText> allVisibleElements = kubernetesViewTree.findAllText();
Optional<RemoteText> resourceText = allVisibleElements.stream().filter(remoteText -> remoteText.getText().startsWith(resourceName)).findFirst();
assertTrue(resourceText.isPresent());
assertTrue(allVisibleElements.contains(resourceText.get()));
assertTrue(allVisibleElements.lastIndexOf(resourceText.get()) < allVisibleElements.size());
return allVisibleElements.get(allVisibleElements.indexOf(resourceText.get()));
}

public static boolean isError(RemoteRobot robot){
IdeStatusBarFixture ideStatusBar = robot.find(IdeStatusBarFixture.class);
try {
ideStatusBar.ideErrorsIcon();
} catch (WaitForConditionTimeoutException e) {
return false;
}
return true;
public void hideClusterContent(){
kubernetesViewTree.findText(clusterName).doubleClick(MouseButton.LEFT_BUTTON);
}

public static void clearErrors(RemoteRobot robot){
IdeStatusBarFixture statusBar = robot.find(IdeStatusBarFixture.class);
try {
statusBar.ideErrorsIcon().click();
} catch (WaitForConditionTimeoutException e) {
e.printStackTrace();
public boolean isResourceCreated(String resourceName, boolean hardCompare){
List<RemoteText> kubernetesToolsText = kubernetesViewTree.findAllText();

Optional<RemoteText> resourceText;
if (hardCompare){
resourceText = kubernetesToolsText.stream().filter(remoteText -> remoteText.getText().equals(resourceName)).findFirst();
} else {
resourceText = kubernetesToolsText.stream().filter(remoteText -> remoteText.getText().contains(resourceName)).findFirst();
}
IdeFatalErrorsDialog ideErrorsDialog = robot.find(IdeFatalErrorsDialog.class);
ideErrorsDialog.clearAll();
return resourceText.isPresent();
}

public static Clipboard getSystemClipboard()
{
Toolkit defaultToolkit = Toolkit.getDefaultToolkit();
return defaultToolkit.getSystemClipboard();
public boolean isResourceDeleted(String resourceName){
return kubernetesViewTree.findAllText().stream().noneMatch(remoteText -> remoteText.getText().equals(resourceName));
}

public static void scrollToVisible(String text, RemoteRobot robot) {
public void scrollToVisible(String text) {
Keyboard myKeyboard = new Keyboard(robot);
myKeyboard.hotKey(KeyEvent.VK_CONTROL, KeyEvent.VK_F);
robot.find(ComponentFixture.class, byXpath("//div[@class='SearchTextArea']")).click();

clearSearchField(robot);

myKeyboard.enterText(text);
}

private static void clearSearchField(RemoteRobot robot) {
try {
robot.find(ComponentFixture.class, byXpath("//div[@myaction='null (null)']")).click();
} catch (WaitForConditionTimeoutException e) {
e.printStackTrace();
}
}
}
Loading
Loading