Skip to content

Commit

Permalink
e2e: Add tests for hawtio-operator
Browse files Browse the repository at this point in the history
  • Loading branch information
mmuzikar authored and tadayosi committed Apr 16, 2024
1 parent d6ec10c commit 19adffb
Show file tree
Hide file tree
Showing 18 changed files with 1,104 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public static AppDeployment getAppDeploymentMethod() {
throw new RuntimeException("Containerized testsuite can't run maven application from inside the container, specify URL or a Docker image");
}

if (getBoolean(USE_OPENSHIFT)) {
if (useOpenshift()) {
deployment = new OpenshiftDeployment();
return deployment;
}
Expand Down Expand Up @@ -130,6 +130,10 @@ public static String getHawtioOnlineSHA() {
return getProperty("io.hawt.test.online.sha");
}

public static String getHawtioOnlineImageRepository() {
return getProperty("io.hawt.test.online.image.repository");
}

public static String getConnectAppUsername() {
return getProperty(CONNECT_APP_USERNAME, TestConfiguration::getAppUsername);
}
Expand All @@ -147,15 +151,15 @@ public static String getAppPassword() {
}

public static boolean useOpenshift() {
return getBoolean(USE_OPENSHIFT);
return getBoolean(USE_OPENSHIFT, false);
}

public static String getIndexImage() {
return getRequiredProperty(OPENSHIFT_INDEX_IMAGE);
return getProperty(OPENSHIFT_INDEX_IMAGE);
}

private static Boolean getBoolean(String name) {
return getOptionalProperty(name).map(Boolean::parseBoolean).orElse(false);
private static Boolean getBoolean(String name, boolean defaultValue) {
return getOptionalProperty(name).map(Boolean::parseBoolean).orElse(defaultValue);
}

public static String getOpenshiftUrl() {
Expand Down Expand Up @@ -184,7 +188,7 @@ public static Path openshiftKubeconfig() {
}

public static boolean openshiftNamespaceDelete() {
return getBoolean(OPENSHIFT_NAMESPACE_DELETE);
return getBoolean(OPENSHIFT_NAMESPACE_DELETE, true);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ public static void appSetup() {
app = TestConfiguration.getAppDeploymentMethod();
app.start();

Runtime.getRuntime().addShutdownHook(new Thread(app::stop));
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
LOG.info("Cleaning up");
app.stop();
}));
} catch (Throwable e) {
startupFailure = e;
LOG.error("Failed to start the test app", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@

import com.codeborne.selenide.Selenide;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;

import io.cucumber.java.AfterStep;
import io.cucumber.java.Scenario;
import io.hawt.tests.features.utils.Attachments;

public class ScreenshotHook {

Expand All @@ -18,9 +25,18 @@ public void afterStep(Scenario scenario) {
if (scenario.isFailed()) {
try {
scenario.attach(Selenide.screenshot(OutputType.BYTES), "image/png", "screenshot");
addScreenshotToReport(scenario.getName());
} catch (Exception e) {
LOG.error("Failed to take a screenshoot", e);
}
}
}

public static void addScreenshotToReport(String name) {
try {
Attachments.addAttachment(Path.of(new URL(URLDecoder.decode(Selenide.screenshot(name), StandardCharsets.UTF_8)).getPath()));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.openshift.api.model.operatorhub.lifecyclemanager.v1.PackageManifest;
import io.fabric8.openshift.api.model.operatorhub.v1.OperatorGroupBuilder;
import io.fabric8.openshift.api.model.operatorhub.v1alpha1.CatalogSource;
import io.fabric8.openshift.api.model.operatorhub.v1alpha1.CatalogSourceBuilder;
import io.fabric8.openshift.api.model.operatorhub.v1alpha1.ClusterServiceVersion;
import io.fabric8.openshift.api.model.operatorhub.v1alpha1.SubscriptionBuilder;
Expand All @@ -28,8 +29,6 @@ public class HawtioOnlineUtils {

private static final Logger LOG = LoggerFactory.getLogger(HawtioOnlineUtils.class);

private static final boolean OPERATOR_WORKAROUND = TestConfiguration.getHawtioOnlineSHA() != null;

public static Deployment deployApplication(String name, String runtime, String namespace, String tag) {
//@formatter:off
List<EnvVar> envVars = new LinkedList<>();
Expand Down Expand Up @@ -89,29 +88,34 @@ public static Deployment deployApplication(String name, String runtime, String n
}

public static void deployOperator() {
//@formatter:off
final OpenShiftOperatorHubAPIGroupDSL operatorhub = OpenshiftClient.get().operatorHub();
operatorhub.catalogSources().createOrReplace(new CatalogSourceBuilder()
.editOrNewMetadata()
.withName("hawtio-catalog")
.endMetadata()
.editOrNewSpec()
.withImage(TestConfiguration.getIndexImage())
.withSourceType("grpc")
.endSpec()
.build());

WaitUtils.waitFor(() -> operatorhub.catalogSources().withName("hawtio-catalog")
.get()
.getStatus()
.getConnectionState()
.getLastObservedState()
.equalsIgnoreCase("READY"),
"Waiting for the catalog to get ready", Duration.ofMinutes(2));

var catalog = operatorhub.catalogSources().withName("hawtio-catalog").get();
CatalogSource catalog = null;
if (TestConfiguration.getIndexImage() != null) {
//@formatter:off
operatorhub.catalogSources().createOrReplace(new CatalogSourceBuilder()
.editOrNewMetadata()
.withName("hawtio-catalog")
.endMetadata()
.editOrNewSpec()
.withImage(TestConfiguration.getIndexImage())
.withSourceType("grpc")
.endSpec()
.build());

WaitUtils.waitFor(() -> operatorhub.catalogSources().withName("hawtio-catalog")
.get()
.getStatus()
.getConnectionState()
.getLastObservedState()
.equalsIgnoreCase("READY"),
"Waiting for the catalog to get ready", Duration.ofMinutes(2));
catalog = operatorhub.catalogSources().withName("hawtio-catalog").get();
} else {
catalog = operatorhub.catalogSources().inNamespace("openshift-marketplace").withName("redhat-operators").get();
}
CatalogSource finalCatalog = catalog;
final PackageManifest packageManifest = WaitUtils.withRetry(() -> operatorhub.packageManifests()
.withLabel("catalog", "hawtio-catalog")
.withLabel("catalog", finalCatalog.getMetadata().getName())
.list()
.getItems()
.stream()
Expand Down Expand Up @@ -139,7 +143,7 @@ public static void deployOperator() {
.withName(subscriptonName)
.endMetadata()
.editOrNewSpec()
.withChannel("preview")
.withChannel(defaultChannel)
.withInstallPlanApproval("Automatic")
.withName(subscriptonName)
.withSource(catalog.getMetadata().getName())
Expand All @@ -159,11 +163,15 @@ public static void deployOperator() {
.getStatus().getPhase().equals("Complete");
}, "Waiting for the installplan to finish", Duration.ofMinutes(3));

if (OPERATOR_WORKAROUND) {
if (TestConfiguration.getHawtioOnlineSHA() != null) {
WaitUtils.withRetry(() -> {
final ClusterServiceVersion csv = operatorhub.clusterServiceVersions().withName(startingCSV).get();
csv.getSpec().getInstall().getSpec().getDeployments().get(0).getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()
.add(new EnvVar("IMAGE_VERSION", TestConfiguration.getHawtioOnlineSHA(), null));
if (TestConfiguration.getHawtioOnlineImageRepository() != null) {
csv.getSpec().getInstall().getSpec().getDeployments().get(0).getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()
.add(new EnvVar("IMAGE_REPOSITORY", TestConfiguration.getHawtioOnlineImageRepository(), null));
}
operatorhub.clusterServiceVersions().withName(startingCSV).patch(csv);
}, 5, Duration.ofSeconds(5));

Expand All @@ -175,6 +183,7 @@ public static void deployOperator() {
}

public static String deployHawtioCR(Hawtio hawtio) {
hawtio.getMetadata().getFinalizers().clear();
OpenshiftClient.get().resources(Hawtio.class).createOrReplace(hawtio);

WaitUtils.waitFor(() -> {
Expand All @@ -184,7 +193,6 @@ public static String deployHawtioCR(Hawtio hawtio) {
resource.get().getStatus().getURL() != null;
}, "Waiting for hawtio deployment to succeed", Duration.ofMinutes(2));

patchHawtioResource("e2e-hawtio", h -> h.getMetadata().getFinalizers().clear());
return OpenshiftClient.get().resources(Hawtio.class).withName(hawtio.getMetadata().getName()).get().getStatus()
.getURL();
}
Expand Down Expand Up @@ -225,4 +233,8 @@ public static void patchHawtioResource(String name, Hawtio value) {
OpenshiftClient.get().resources(Hawtio.class).withName(name).patch(value);
}, 5, Duration.ofMillis(500));
}

public static void deleteHawtio(Hawtio hawtio) {
OpenshiftClient.get().resource(hawtio).delete();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@
import static com.codeborne.selenide.Selenide.$$;
import static com.codeborne.selenide.Selenide.page;

import org.openqa.selenium.By;

import com.codeborne.selenide.ElementsCollection;
import com.codeborne.selenide.SelenideElement;

import java.time.Duration;

/**
* Represents Tree menu in Hawtio (e.g. Camel, JMX).
*/
Expand All @@ -35,6 +39,7 @@ public class Tree {
* @return the given page object class
*/
public <P> P expandSpecificFolder(Class<P> pageObjectClass, String folderPartialId) {
assureLoaded();
if (!$("[id*='" + folderPartialId + "']").has(cssClass("pf-m-expanded"))) {
$("[id*='" + folderPartialId + "']").$("[class$='node-toggle']").shouldBe(interactable).click();
}
Expand All @@ -47,6 +52,7 @@ public <P> P expandSpecificFolder(Class<P> pageObjectClass, String folderPartial
* @param itemPartialId of the item to be selected
*/
public void selectSpecificItem(String itemPartialId) {
assureLoaded();
$("[id*='" + itemPartialId + "']").$("[class$='node-text']").shouldBe(interactable).click();
}

Expand All @@ -56,6 +62,7 @@ public void selectSpecificItem(String itemPartialId) {
* @param fullId of the item to be selected.
*/
public void selectSpecificItemByExactId(String fullId) {
assureLoaded();
$(byId(fullId)).$("[class$='node-text']").shouldBe(interactable).click();
}

Expand Down Expand Up @@ -88,6 +95,7 @@ public void collapseTree() {
* Expand and collapse tree.
*/
private void toggleExpandCollapseTree() {
assureLoaded();
// there is only one button responsible for expanding and collapsing, it works as toggle button
expandCollapseBtn.shouldBe(enabled).click();
}
Expand All @@ -98,6 +106,7 @@ private void toggleExpandCollapseTree() {
* @param state of the tree nodes
*/
public void allTreeNodesState(String state) {
assureLoaded();
if (state.contains("expanded")) {
// when the tree is expanded, all list items should contain expanded class
camelTreeNodes.should(allMatch("Each node is expanded", e -> e.getAttribute("class").contains(state)));
Expand All @@ -114,6 +123,7 @@ public void allTreeNodesState(String state) {
* @param value to filter the tree
*/
public void filterTree(String value) {
assureLoaded();
$(byId("input-search")).shouldBe(enabled).setValue(value);
}

Expand All @@ -123,6 +133,11 @@ public void filterTree(String value) {
* @param value by which the tree is filtered
*/
public void treeIsFiltered(String value) {
assureLoaded();
$(byTagAndText("button", value)).should(exist).shouldBe(visible);
}

private void assureLoaded() {
$(By.className("pf-c-tree-view__list")).should(exist, Duration.ofSeconds(10));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,46 @@
import static com.codeborne.selenide.Selectors.byAttribute;
import static com.codeborne.selenide.Selenide.$;

import org.openqa.selenium.By;

import com.codeborne.selenide.SelenideElement;

import java.util.HashMap;
import java.util.Map;

/**
* Represents About modal window on Hawtio page.
*/
public class AboutModalWindow {


public static final By MODAL_DIALOG = By.className("pf-c-about-modal-box");

/**
* Click on Close button.
*/
public void close() {
$(byAttribute("aria-label", "Close Dialog")).shouldBe(enabled).click();
}

public String getHeaderText() {
return $("[id*='pf-about-modal-title']").text();
}

public Map<String, String> getAppComponents() {
Map<String, String> ret = new HashMap<>();
for (SelenideElement dt : $(By.id("hawtio-about-product-info")).$$(By.tagName("dt"))) {
ret.put(dt.getText(), dt.sibling(0).text());
}
return ret;
}

public String getCopyright() {
return $(MODAL_DIALOG).$(By.className("pf-c-about-modal-box__strapline")).getText();
}

public SelenideElement getBrandImage() {
return $(MODAL_DIALOG).$(By.className("pf-c-about-modal-box__brand-image"));
}

}
Loading

0 comments on commit 19adffb

Please sign in to comment.