This is an automated email from the ASF dual-hosted git repository.
zihaoxiang pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampark.git
The following commit(s) were added to refs/heads/dev by this push:
new ab5cc1f38 [Feature] Introduce environment e2e test (#3911)
ab5cc1f38 is described below
commit ab5cc1f38f0169680150f3a4f5293a316da50ad8
Author: Zhengke Zhou <[email protected]>
AuthorDate: Fri Aug 9 09:36:18 2024 +0800
[Feature] Introduce environment e2e test (#3911)
---
.github/workflows/e2e.yml | 2 +
.../streampark/e2e/cases/EnvironmentTest.java | 199 +++++++++++++++++++++
.../streampark/e2e/pages/common/CommonFactory.java | 12 +-
.../streampark/e2e/pages/setting/SettingPage.java | 11 ++
.../e2e/pages/setting/env/CommonForm.java | 36 ++++
.../e2e/pages/setting/env/DockerSettingForm.java | 85 +++++++++
.../e2e/pages/setting/env/EmailSettingForm.java | 100 +++++++++++
.../pages/setting/env/EnvironmentDetailForm.java | 68 +++++++
.../e2e/pages/setting/env/EnvironmentPage.java | 91 ++++++++++
.../e2e/pages/setting/env/IngressSettingForm.java | 54 ++++++
.../e2e/pages/setting/env/MavenSettingForm.java | 103 +++++++++++
.../test/resources/docker/environment/Dockerfile | 18 ++
.../docker/environment/docker-compose.yaml | 60 +++++++
13 files changed, 838 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 78991717c..b32b860b6 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -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
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/cases/EnvironmentTest.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/cases/EnvironmentTest.java
new file mode 100644
index 000000000..52ea9a1f1
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/cases/EnvironmentTest.java
@@ -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();
+ }
+}
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/common/CommonFactory.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/common/CommonFactory.java
index 4a4769c04..0007ae24b 100644
---
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/common/CommonFactory.java
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/common/CommonFactory.java
@@ -29,9 +29,19 @@ import java.time.Duration;
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) {
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/SettingPage.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/SettingPage.java
index 36df07cb7..886ed4b03 100644
---
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/SettingPage.java
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/SettingPage.java
@@ -20,6 +20,7 @@ package org.apache.streampark.e2e.pages.setting;
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;
@@ -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);
}
@@ -66,6 +70,13 @@ public class SettingPage extends NavBarPage implements
NavBarPage.NavBarItem {
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());
}
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/CommonForm.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/CommonForm.java
new file mode 100644
index 000000000..7b0603bc5
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/CommonForm.java
@@ -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;
+ }
+}
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/DockerSettingForm.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/DockerSettingForm.java
new file mode 100644
index 000000000..b02042983
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/DockerSettingForm.java
@@ -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;
+ }
+}
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/EmailSettingForm.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/EmailSettingForm.java
new file mode 100644
index 000000000..2eb8b044d
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/EmailSettingForm.java
@@ -0,0 +1,100 @@
+/*
+ * 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 EmailSettingForm extends CommonForm {
+
+ private WebDriver driver;
+
+ @FindBy(id = "SettingForm_host")
+ private WebElement inputSmtpHost;
+
+ @FindBy(xpath = "//input[@placeholder='Smtp Port']")
+ private WebElement inputSmtpPort;
+
+ @FindBy(id = "SettingForm_from")
+ private WebElement inputAddress;
+
+ @FindBy(id = "SettingForm_userName")
+ private WebElement inputUsername;
+
+ @FindBy(xpath = "//input[@placeholder='Email Password']")
+ private WebElement inputPassword;
+
+ @FindBy(id = "SettingForm_ssl")
+ private WebElement btnEnableSSL;
+
+ @FindBy(xpath = "//div[contains(@class, 'ant-modal-title') and contains(.,
'Sender Email Setting')]/../..//button[contains(@class,
'ant-btn')]//span[contains(text(), 'OK')]")
+ private WebElement buttonOk;
+
+ @FindBy(xpath = "//div[contains(@class, 'ant-modal-title') and contains(.,
'Sender Email Setting')]/../..//button[contains(@class,
'ant-btn')]//span[contains(text(), 'Cancel')]")
+ private WebElement buttonCancel;
+
+ EmailSettingForm(EnvironmentDetailForm environmentDetailForm) {
+ super(environmentDetailForm);
+ this.driver = environmentDetailForm.driver();
+ }
+
+ public EmailSettingForm host(String host) {
+ WebElementDeleteAndInput(inputSmtpHost, host);
+ return this;
+ }
+
+ public EmailSettingForm port(String port) {
+ WebElementDeleteAndInput(inputSmtpPort, port);
+ return this;
+ }
+
+ public EmailSettingForm address(String address) {
+ WebElementDeleteAndInput(inputAddress, address);
+ return this;
+ }
+ public EmailSettingForm user(String user) {
+ WebElementDeleteAndInput(inputUsername, user);
+ return this;
+ }
+
+ public EmailSettingForm password(String password) {
+ WebElementDeleteAndInput(inputPassword, password);
+ return this;
+ }
+
+ public EmailSettingForm ssl() {
+ WebElementClick(driver, btnEnableSSL);
+ return this;
+ }
+
+ public EmailSettingForm ok() {
+ WebElementClick(driver, buttonOk);
+ return this;
+ }
+
+ public EmailSettingForm cancel() {
+ WebElementClick(driver, buttonCancel);
+ return this;
+ }
+}
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/EnvironmentDetailForm.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/EnvironmentDetailForm.java
new file mode 100644
index 000000000..5b2188ee0
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/EnvironmentDetailForm.java
@@ -0,0 +1,68 @@
+/*
+ * 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 org.apache.streampark.e2e.pages.common.Constants;
+
+import lombok.Getter;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.support.PageFactory;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+@Getter
+public class EnvironmentDetailForm {
+
+ private WebDriver driver;
+
+ public EnvironmentDetailForm(WebDriver driver) {
+ PageFactory.initElements(driver, this);
+ this.driver = driver;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T addSetting(EnvSettingTypeEnum envSettingTypeEnum) {
+ new WebDriverWait(driver, Constants.DEFAULT_WEBDRIVER_WAIT_DURATION);
+ switch (envSettingTypeEnum) {
+ case Maven:
+ return (T) new MavenSettingForm(this);
+ case Email:
+ return (T) new EmailSettingForm(this);
+ case Docker:
+ return (T) new DockerSettingForm(this);
+ case Ingress:
+ return (T) new IngressSettingForm(this);
+ default:
+ throw new UnsupportedOperationException(
+ String.format("Unsupported Environment setting type %s",
envSettingTypeEnum.desc()));
+ }
+ }
+
+ @Getter
+ public enum EnvSettingTypeEnum {
+
+ Maven("Maven"),
+ Docker("Docker"),
+ Email("Email"),
+ Ingress("Ingress");
+ private final String desc;
+
+ EnvSettingTypeEnum(String desc) {
+ this.desc = desc;
+ }
+ }
+}
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/EnvironmentPage.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/EnvironmentPage.java
new file mode 100644
index 000000000..447774c2b
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/EnvironmentPage.java
@@ -0,0 +1,91 @@
+/*
+ * 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 org.apache.streampark.e2e.pages.common.Constants;
+import org.apache.streampark.e2e.pages.common.NavBarPage;
+import org.apache.streampark.e2e.pages.setting.SettingPage;
+
+import lombok.Getter;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.remote.RemoteWebDriver;
+import org.openqa.selenium.support.FindBy;
+import org.openqa.selenium.support.FindBys;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+import static
org.apache.streampark.e2e.pages.common.CommonFactory.WebElementClick;
+
+@Getter
+public class EnvironmentPage extends NavBarPage implements SettingPage.Tab {
+
+ private static final Logger log =
LoggerFactory.getLogger(EnvironmentPage.class);
+
+ public EnvironmentPage(RemoteWebDriver driver) {
+ super(driver);
+ }
+
+ @FindBys({
+ @FindBy(xpath = "//h4[text()='Docker Setting']"),
+ @FindBy(xpath =
"./ancestor::li[@class='ant-list-item']//button[contains(@class, 'ant-btn') and
contains(@class, 'ant-btn-primary') and contains(@class, 'ant-btn-circle')]")
+ })
+ private WebElement btnCreateDockerSetting;
+
+ @FindBys({
+ @FindBy(xpath = "//h4[text()='Alert Mailbox Setting']"),
+ @FindBy(xpath =
"./ancestor::li[@class='ant-list-item']//button[contains(@class, 'ant-btn') and
contains(@class, 'ant-btn-primary') and contains(@class, 'ant-btn-circle')]")
+ })
+ private WebElement btnCreateEmailSetting;
+
+ @FindBy(xpath = "//div[contains(@class, 'system-setting')]")
+ private List<WebElement> settingList;
+
+ @FindBy(className = "swal2-container")
+ private List<WebElement> errorMessageList;
+
+ @FindBy(xpath = "//button[contains(@class, 'swal2-confirm') and
contains(@class, 'swal2-styled') and text()='OK']")
+ private WebElement errorMessageConfirmButton;
+
+ public EnvironmentDetailForm
createEnvironment(EnvironmentDetailForm.EnvSettingTypeEnum envSettingTypeEnum) {
+ waitForPageLoading();
+ switch (envSettingTypeEnum) {
+ case Docker:
+ WebElementClick(driver, btnCreateDockerSetting);
+ break;
+ case Email:
+ WebElementClick(driver, btnCreateEmailSetting);
+ break;
+ case Maven:
+ case Ingress:
+ break;
+ default:
+ throw new UnsupportedOperationException(
+ String.format("Unsupported environment type %s",
envSettingTypeEnum.desc()));
+ }
+ return new EnvironmentDetailForm(driver);
+ }
+
+ private void waitForPageLoading() {
+ new WebDriverWait(driver, Constants.DEFAULT_WEBDRIVER_WAIT_DURATION)
+ .until(ExpectedConditions.urlContains("/setting/system"));
+ }
+}
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/IngressSettingForm.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/IngressSettingForm.java
new file mode 100644
index 000000000..6e9d11d7d
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/IngressSettingForm.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.openqa.selenium.support.FindBys;
+
+import static
org.apache.streampark.e2e.pages.common.CommonFactory.WebElementClick;
+import static
org.apache.streampark.e2e.pages.common.CommonFactory.WebElementDeleteAndInput;
+
+@Getter
+public class IngressSettingForm extends CommonForm {
+
+ private WebDriver driver;
+
+ @FindBys({
+ @FindBy(xpath = "//h4[text()='Ingress domain address Setting']"),
+ @FindBy(xpath =
"./ancestor::li[@class='ant-list-item']//button[contains(@class, 'ant-btn') and
contains(@class, 'ant-btn-primary') and contains(@class, 'ant-btn-circle')]")
+ })
+ private WebElement btnDomainAddressSetting;
+
+ @FindBy(className = "ingress_mode_default")
+ private WebElement inputDomainAddress;
+
+ IngressSettingForm(EnvironmentDetailForm environmentDetailForm) {
+ super(environmentDetailForm);
+ this.driver = environmentDetailForm.driver();
+ }
+
+ public IngressSettingForm domainAddress(String domainAddress) {
+ WebElementClick(driver, btnDomainAddressSetting);
+ WebElementDeleteAndInput(inputDomainAddress, domainAddress);
+ WebElementClick(driver, btnDomainAddressSetting);
+ return this;
+ }
+}
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/MavenSettingForm.java
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/MavenSettingForm.java
new file mode 100644
index 000000000..3000a2c14
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/setting/env/MavenSettingForm.java
@@ -0,0 +1,103 @@
+/*
+ * 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 org.openqa.selenium.support.FindBys;
+
+import static
org.apache.streampark.e2e.pages.common.CommonFactory.WebElementClick;
+import static
org.apache.streampark.e2e.pages.common.CommonFactory.WebElementDeleteAndInput;
+
+@Getter
+public class MavenSettingForm extends CommonForm {
+
+ private WebDriver driver;
+ @FindBys({
+ @FindBy(xpath = "//h4[text()='Maven Settings File Path']"),
+ @FindBy(xpath =
"./ancestor::li[@class='ant-list-item']//button[contains(@class,
'ant-btn-primary')]")
+ })
+ private WebElement btnSettingsFilePath;
+
+ @FindBys({
+ @FindBy(xpath = "//h4[text()='Maven Central Repository']"),
+ @FindBy(xpath =
"./ancestor::li[@class='ant-list-item']//button[contains(@class,
'ant-btn-primary')]")
+ })
+ private WebElement btnCentralRepository;
+
+ @FindBys({
+ @FindBy(xpath = "//h4[text()='Maven Central Repository Auth
User']"),
+ @FindBy(xpath =
"./ancestor::li[@class='ant-list-item']//button[contains(@class,
'ant-btn-primary')]")
+ })
+ // Maven central repository authentication username.
+ private WebElement btnAuthUser;
+
+ @FindBys({
+ @FindBy(xpath = "//h4[text()='Maven Central Repository Auth
Password']"),
+ @FindBy(xpath =
"./ancestor::li[@class='ant-list-item']//button[contains(@class,
'ant-btn-primary')]")
+ })
+ // Maven central repository authentication password.
+ private WebElement btnAuthPassword;
+
+ @FindBy(className = "streampark_maven_settings")
+ private WebElement inputSettingsFilePath;
+
+ @FindBy(className = "streampark_maven_central_repository")
+ private WebElement inputCentralRepository;
+
+ @FindBy(className = "streampark_maven_auth_user")
+ private WebElement inputAuthUser;
+
+ @FindBy(className = "streampark_maven_auth_password")
+ private WebElement inputAuthPassword;
+
+ MavenSettingForm(EnvironmentDetailForm environmentDetailForm) {
+ super(environmentDetailForm);
+ this.driver = environmentDetailForm.driver();
+ }
+
+ public MavenSettingForm filePath(String filePath) {
+ WebElementClick(driver, btnSettingsFilePath);
+ WebElementDeleteAndInput(inputSettingsFilePath, filePath);
+ WebElementClick(driver, btnSettingsFilePath);
+ return this;
+ }
+
+ public MavenSettingForm centralRepository(String repository) {
+ WebElementClick(driver, btnCentralRepository);
+ WebElementDeleteAndInput(inputCentralRepository, repository);
+ WebElementClick(driver, btnCentralRepository);
+ return this;
+ }
+
+ public MavenSettingForm authUser(String user) {
+ WebElementClick(driver, btnAuthUser);
+ WebElementDeleteAndInput(inputAuthUser, user);
+ WebElementClick(driver, btnAuthUser);
+ return this;
+ }
+
+ public MavenSettingForm authPassword(String password) {
+ WebElementClick(driver, btnAuthPassword);
+ WebElementDeleteAndInput(inputAuthPassword, password);
+ WebElementClick(driver, btnAuthPassword);
+ return this;
+ }
+}
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/resources/docker/environment/Dockerfile
b/streampark-e2e/streampark-e2e-case/src/test/resources/docker/environment/Dockerfile
new file mode 100644
index 000000000..9443edc26
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/resources/docker/environment/Dockerfile
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+FROM apache/streampark:ci
diff --git
a/streampark-e2e/streampark-e2e-case/src/test/resources/docker/environment/docker-compose.yaml
b/streampark-e2e/streampark-e2e-case/src/test/resources/docker/environment/docker-compose.yaml
new file mode 100644
index 000000000..934a0ffd1
--- /dev/null
+++
b/streampark-e2e/streampark-e2e-case/src/test/resources/docker/environment/docker-compose.yaml
@@ -0,0 +1,60 @@
+#
+# 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.
+#
+
+services:
+ postfix:
+ image: boky/postfix
+ container_name: postfix
+ hostname: testmail
+ domainname: email.com
+ environment:
+ - maildomain=email.com
+ - smtp_user=admin:streampark
+ - ALLOW_EMPTY_SENDER_DOMAINS=true
+ ports:
+ - "25:25"
+ privileged: true
+ restart: unless-stopped
+ networks:
+ - e2e
+ streampark:
+ image: apache/streampark:ci-basic
+ command: bash bin/streampark.sh start_docker
+ build:
+ context: ./
+ dockerfile: ./Dockerfile
+ ports:
+ - 10000:10000
+ - 10030:10030
+ environment:
+ - SPRING_PROFILES_ACTIVE=h2
+ - TZ=Asia/Shanghai
+ privileged: true
+ restart: unless-stopped
+ networks:
+ - e2e
+ volumes:
+ - ${HOME}/streampark_build_logs:/tmp/streampark/logs/build_logs/
+ - /var/run/docker.sock:/var/run/docker.sock
+ healthcheck:
+ test: [ "CMD", "curl", "http://localhost:10000" ]
+ interval: 5s
+ timeout: 5s
+ retries: 120
+networks:
+ e2e:
+