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:
+


Reply via email to