Skip to content

Commit

Permalink
[Feature] Introduce environment e2e test (#3911)
Browse files Browse the repository at this point in the history
  • Loading branch information
zzzk1 authored Aug 9, 2024
1 parent 33c64e8 commit ab5cc1f
Show file tree
Hide file tree
Showing 13 changed files with 838 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ jobs:
strategy:
matrix:
case:
- name: EnvironmentTest
class: org.apache.streampark.e2e.cases.EnvironmentTest
- name: AlarmTest
class: org.apache.streampark.e2e.cases.AlarmTest
- name: ExternalLinkTest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.streampark.e2e.cases;

import org.apache.streampark.e2e.core.StreamPark;
import org.apache.streampark.e2e.pages.LoginPage;
import org.apache.streampark.e2e.pages.common.Constants;
import org.apache.streampark.e2e.pages.setting.SettingPage;
import org.apache.streampark.e2e.pages.setting.env.DockerSettingForm;
import org.apache.streampark.e2e.pages.setting.env.EmailSettingForm;
import org.apache.streampark.e2e.pages.setting.env.EnvironmentDetailForm;
import org.apache.streampark.e2e.pages.setting.env.EnvironmentPage;
import org.apache.streampark.e2e.pages.setting.env.IngressSettingForm;
import org.apache.streampark.e2e.pages.setting.env.MavenSettingForm;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testcontainers.shaded.org.awaitility.Awaitility;

import static org.apache.streampark.e2e.pages.common.CommonFactory.WebElementClick;
import static org.assertj.core.api.Assertions.assertThat;

@StreamPark(composeFiles = "docker/environment/docker-compose.yaml")
public class EnvironmentTest {

private static RemoteWebDriver browser;

private static final String userName = "admin";

private static final String password = "streampark";

private static final String teamName = "default";

// maven
final String mavenFilePath = "/maven/file/path";
final String mavenCentralRepository = "https://mvnrepository.com/";
final String mavenAuthUser = "maven_user";
final String mavenAuthPassword = "maven_password";

// ingress
final String ingressDomainAddress = "https://localhost";

// docker
final String dockerAddress = "https://hub.docker.com/v2/";
final String dockerNamespace = "hello";
final String dockerUser = "docker_user";
final String dockerPassword = "docker_password";

// email
final String emailHost = "smtp.163.com";
final String editEmailHost = "postfix";
final String emailPort = "25";
final String emailAddress = "[email protected]";
final String editEmailAddress = "[email protected]";
final String emailUser = "email_password";
final String emailPassword = "email_password";

@BeforeAll
public static void setup() {
new LoginPage(browser)
.login(userName, password, teamName)
.goToNav(SettingPage.class)
.goToTab(EnvironmentPage.class);
}

@Test
@Order(10)
public void testCreateEnvironment() {
final EnvironmentPage environmentPage = new EnvironmentPage(browser);

environmentPage.createEnvironment(EnvironmentDetailForm.EnvSettingTypeEnum.Maven)
.<MavenSettingForm>addSetting(EnvironmentDetailForm.EnvSettingTypeEnum.Maven)
.filePath(mavenFilePath)
.centralRepository(mavenCentralRepository)
.authUser(mavenAuthUser)
.authPassword(mavenAuthPassword);

environmentPage.createEnvironment(EnvironmentDetailForm.EnvSettingTypeEnum.Ingress)
.<IngressSettingForm>addSetting(EnvironmentDetailForm.EnvSettingTypeEnum.Ingress)
.domainAddress(ingressDomainAddress);

Awaitility.await()
.untilAsserted(
() -> assertThat(environmentPage.settingList())
.as("Setting list should contain newly-created setting")
.extracting(WebElement::getText)
.anyMatch(it -> it.contains(mavenFilePath))
.anyMatch(it -> it.contains(mavenCentralRepository))
.anyMatch(it -> it.contains(mavenAuthUser))
.anyMatch(it -> it.contains(ingressDomainAddress)));
}

@Test
@Order(20)
public void testCreateEmailSettingFailedWithAuth() {
final EnvironmentPage environmentPage = new EnvironmentPage(browser);

EmailSettingForm emailSettingForm =
environmentPage.createEnvironment(EnvironmentDetailForm.EnvSettingTypeEnum.Email)
.<EmailSettingForm>addSetting(EnvironmentDetailForm.EnvSettingTypeEnum.Email)
.host(emailHost)
.port(emailPort)
.address(emailAddress)
.user(emailUser)
.password(emailPassword)
.ok();

String expectedErrorMessage =
"connect to target mail server failed: 535 Error: authentication failed";
Awaitility.await()

.untilAsserted(
() -> {
new WebDriverWait(browser, Constants.DEFAULT_WEBDRIVER_WAIT_DURATION);
assertThat(environmentPage.errorMessageList())
.as("Connect failed error message should be displayed")
.extracting(WebElement::getText)
.anyMatch(it -> it.contains(expectedErrorMessage));
});

WebElementClick(browser, environmentPage.errorMessageConfirmButton());
emailSettingForm.cancel();
}

@Test
@Order(30)
public void testCreateEmailSettingSuccessful() {
final EnvironmentPage environmentPage = new EnvironmentPage(browser);

EmailSettingForm emailSettingForm =
environmentPage.createEnvironment(EnvironmentDetailForm.EnvSettingTypeEnum.Email)
.<EmailSettingForm>addSetting(EnvironmentDetailForm.EnvSettingTypeEnum.Email)
.host(editEmailHost)
.port(emailPort)
.address(editEmailAddress)
.user(emailUser)
.password(emailPassword)
.ok();

emailSettingForm.buttonOk().click();

Awaitility.await()
.untilAsserted(
() -> assertThat(environmentPage.settingList())
.as("Setting list should contain newly-created email setting")
.extracting(WebElement::getText)
.anyMatch(it -> it.contains(editEmailAddress)));
}

@Test
@Order(40)
public void testCreateDockerSettingFailed() {
final EnvironmentPage environmentPage = new EnvironmentPage(browser);
DockerSettingForm dockerSettingForm =
environmentPage.createEnvironment(EnvironmentDetailForm.EnvSettingTypeEnum.Docker)
.<DockerSettingForm>addSetting(EnvironmentDetailForm.EnvSettingTypeEnum.Docker)
.address(dockerAddress)
.namespace(dockerNamespace)
.user(dockerUser)
.password(dockerPassword)
.ok();

String expectedErrorMessage = String.format(
"Failed to validate Docker registry, error: Status 500: {\"message\":\"login attempt to %s failed with status: 404 Not Found\"}",
dockerAddress);
Awaitility.await()

.untilAsserted(
() -> {
new WebDriverWait(browser, Constants.DEFAULT_WEBDRIVER_WAIT_DURATION);
assertThat(environmentPage.errorMessageList())
.as("Failed to validate docker registry error message should be displayed")
.extracting(WebElement::getText)
.anyMatch(it -> it.contains(expectedErrorMessage));
});

WebElementClick(browser, environmentPage.errorMessageConfirmButton());
dockerSettingForm.cancel();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,19 @@
public class CommonFactory {

public static void WebElementDeleteAndInput(WebElement element, String value) {
WebElementDelete(element);
element.sendKeys(value);
}

public static void WebElementDelete(WebElement element) {
element.sendKeys(Keys.CONTROL + "a");
element.sendKeys(Keys.BACK_SPACE);
element.sendKeys(value);
}

public static void WebElementClick(WebDriver driver, WebElement clickableElement) {
new WebDriverWait(driver, Constants.DEFAULT_WEBDRIVER_WAIT_DURATION)
.until(ExpectedConditions.elementToBeClickable(clickableElement));
clickableElement.click();
}

public static void WebDriverWaitForElementVisibilityAndInvisibility(WebDriver driver, String msg) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.apache.streampark.e2e.pages.common.Constants;
import org.apache.streampark.e2e.pages.common.NavBarPage;
import org.apache.streampark.e2e.pages.setting.alarm.AlarmPage;
import org.apache.streampark.e2e.pages.setting.env.EnvironmentPage;

import lombok.Getter;
import org.openqa.selenium.WebElement;
Expand All @@ -40,6 +41,9 @@ public class SettingPage extends NavBarPage implements NavBarPage.NavBarItem {
@FindBy(xpath = "//span[contains(@class, 'streampark-simple-menu-sub-title') and contains(text(), 'Alarms')]//..")
private WebElement menuAlarmManagement;

@FindBy(xpath = "//span[contains(@class, 'streampark-simple-menu-sub-title') and contains(text(), 'Environments')]//..")
private WebElement menuEnvManagement;

public SettingPage(RemoteWebDriver driver) {
super(driver);
}
Expand All @@ -66,6 +70,13 @@ public <T extends SettingPage.Tab> T goToTab(Class<T> tab) {
return tab.cast(new AlarmPage(driver));
}

if (tab == EnvironmentPage.class) {
new WebDriverWait(driver, Constants.DEFAULT_WEBDRIVER_WAIT_DURATION)
.until(ExpectedConditions.elementToBeClickable(menuEnvManagement));
menuEnvManagement.click();
return tab.cast(new EnvironmentPage(driver));
}

throw new UnsupportedOperationException("Unknown tab: " + tab.getName());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.streampark.e2e.pages.setting.env;

import lombok.Getter;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;

@Getter
public abstract class CommonForm {

private WebDriver driver;

private final EnvironmentDetailForm parent;

public CommonForm(EnvironmentDetailForm environmentDetailForm) {
final WebDriver driver = environmentDetailForm.driver();
PageFactory.initElements(driver, this);
this.parent = environmentDetailForm;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.streampark.e2e.pages.setting.env;

import lombok.Getter;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

import static org.apache.streampark.e2e.pages.common.CommonFactory.WebElementClick;
import static org.apache.streampark.e2e.pages.common.CommonFactory.WebElementDeleteAndInput;

@Getter
public class DockerSettingForm extends CommonForm {

private WebDriver driver;

@FindBy(id = "SettingForm_address")
private WebElement inputAddress;

@FindBy(id = "SettingForm_namespace")
private WebElement inputNamespace;

@FindBy(id = "SettingForm_username")
private WebElement inputUsername;

@FindBy(xpath = "//input[@placeholder='Docker Password']")
private WebElement inputPassword;

@FindBy(xpath = "//div[contains(@class, 'ant-modal-title') and contains(., 'Docker Setting')]/../..//button[contains(@class, 'ant-btn')]//span[contains(text(), 'OK')]")
private WebElement buttonOk;

@FindBy(xpath = "//div[contains(@class, 'ant-modal-title') and contains(., 'Docker Setting')]/../..//button[contains(@class, 'ant-btn')]//span[contains(text(), 'Cancel')]")
private WebElement buttonCancel;

DockerSettingForm(EnvironmentDetailForm environmentDetailForm) {
super(environmentDetailForm);
this.driver = environmentDetailForm.driver();
}

public DockerSettingForm address(String address) {
WebElementDeleteAndInput(inputAddress, address);
return this;
}

public DockerSettingForm namespace(String namespace) {
WebElementDeleteAndInput(inputNamespace, namespace);
return this;
}

public DockerSettingForm user(String user) {
WebElementDeleteAndInput(inputUsername, user);
return this;
}

public DockerSettingForm password(String password) {
WebElementDeleteAndInput(inputPassword, password);
return this;
}

public DockerSettingForm ok() {
WebElementClick(driver, buttonOk);
return this;
}

public DockerSettingForm cancel() {
WebElementClick(driver, buttonCancel);
return this;
}
}
Loading

0 comments on commit ab5cc1f

Please sign in to comment.