This is an automated email from the ASF dual-hosted git repository.

benjobs 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 3ff81eb2f Introduce member management e2e test (#3829)
3ff81eb2f is described below

commit 3ff81eb2fe5380b39305ffc9e0355ea43a3af4a7
Author: Zhengke Zhou <[email protected]>
AuthorDate: Sat Jul 6 22:35:41 2024 +0800

    Introduce member management e2e test (#3829)
    
    Co-authored-by: benjobs <[email protected]>
---
 .github/workflows/e2e.yml                          |   2 +
 .../streampark/e2e/cases/MemberManagementTest.java | 128 +++++++++++++++
 .../e2e/pages/system/MemberManagementPage.java     | 178 +++++++++++++++++++++
 .../streampark/e2e/pages/system/SystemPage.java    |   7 +
 4 files changed, 315 insertions(+)

diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 853f431b5..6a5d088ca 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -105,6 +105,8 @@ jobs:
     strategy:
       matrix:
         case:
+          - name: MemberManagementTest
+            class: org.apache.streampark.e2e.cases.MemberManagementTest
           - name: VariableManagementTest
             class: 
org.apache.streampark.e2e.pages.resource.VariableManagementTest
           - name: RoleManagementTest
diff --git 
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/cases/MemberManagementTest.java
 
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/cases/MemberManagementTest.java
new file mode 100644
index 000000000..d56c1bb19
--- /dev/null
+++ 
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/cases/MemberManagementTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.system.MemberManagementPage;
+import org.apache.streampark.e2e.pages.system.SystemPage;
+
+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.testcontainers.shaded.org.awaitility.Awaitility;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@StreamPark(composeFiles = "docker/basic/docker-compose.yaml")
+public class MemberManagementTest {
+
+    private static RemoteWebDriver browser;
+
+    private static final String userName = "admin";
+
+    private static final String password = "streampark";
+
+    private static final String teamName = "default";
+
+    private static final String existUserName = "test3";
+
+    private static final String existRole = "developer";
+
+    @BeforeAll
+    public static void setup() {
+        new LoginPage(browser)
+                .login(userName, password, teamName)
+                .goToNav(SystemPage.class)
+                .goToTab(MemberManagementPage.class);
+    }
+
+    @Test
+    @Order(10)
+    void testCreateMember() {
+        final MemberManagementPage memberManagementPage = new 
MemberManagementPage(browser);
+
+        memberManagementPage.createMember(existUserName, existRole);
+
+        Awaitility.await()
+                .untilAsserted(
+                        () -> assertThat(memberManagementPage.memberList())
+                                .as("Member list should contain newly-created 
member")
+                                .extracting(WebElement::getText)
+                                .anyMatch(it -> it.contains(existUserName)));
+    }
+
+    @Test
+    @Order(20)
+    void testCreateDuplicateMember() {
+        final MemberManagementPage memberManagementPage = new 
MemberManagementPage(browser);
+
+        memberManagementPage.createMember(existUserName, existRole);
+
+        Awaitility.await()
+                .untilAsserted(
+                        () -> 
assertThat(memberManagementPage.errorMessageList())
+                                .as("Member Duplicated Error message should be 
displayed")
+                                .extracting(WebElement::getText)
+                                .anyMatch(it -> it.contains(
+                                        String.format(
+                                                "The user [%s] has been added 
the team [%s], please don't add it again.",
+                                                existUserName, teamName))));
+
+        memberManagementPage.errorMessageConfirmButton().click();
+        memberManagementPage.createMemberForm().buttonCancel().click();
+    }
+
+    @Test
+    @Order(30)
+    void testEditMember() {
+        final MemberManagementPage memberManagementPage = new 
MemberManagementPage(browser);
+        String anotherRole = "team admin";
+
+        memberManagementPage.editMember(existUserName, anotherRole);
+
+        Awaitility.await()
+                .untilAsserted(
+                        () -> assertThat(memberManagementPage.memberList())
+                                .as("Team list should contain edited team")
+                                .extracting(WebElement::getText)
+                                .anyMatch(
+                                        it -> it.contains(existUserName)));
+    }
+
+    @Test
+    @Order(40)
+    void testDeleteMember() {
+        final MemberManagementPage memberManagementPage = new 
MemberManagementPage(browser);
+
+        memberManagementPage.deleteMember(existUserName);
+
+        Awaitility.await()
+                .untilAsserted(
+                        () -> {
+                            browser.navigate().refresh();
+
+                            assertThat(memberManagementPage.memberList())
+                                    .noneMatch(it -> 
it.getText().contains(existUserName));
+                        });
+    }
+}
diff --git 
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/system/MemberManagementPage.java
 
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/system/MemberManagementPage.java
new file mode 100644
index 000000000..a0bb92a67
--- /dev/null
+++ 
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/system/MemberManagementPage.java
@@ -0,0 +1,178 @@
+/*
+ * 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.system;
+
+import org.apache.streampark.e2e.pages.common.NavBarPage;
+
+import lombok.Getter;
+import org.openqa.selenium.By;
+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.PageFactory;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.time.Duration;
+import java.util.List;
+
+@Getter
+public class MemberManagementPage extends NavBarPage implements SystemPage.Tab 
{
+
+    @FindBy(xpath = "//span[contains(., 'Member 
List')]/..//button[contains(@class, 'ant-btn-primary')]/span[contains(text(), 
'Add New')]")
+    private WebElement buttonCreateMember;
+
+    @FindBy(xpath = "//tbody[contains(@class, 'ant-table-tbody')]")
+    private List<WebElement> memberList;
+
+    @FindBy(className = "swal2-html-container")
+    private List<WebElement> errorMessageList;
+
+    @FindBy(xpath = "//button[contains(text(), 'OK')]")
+    private WebElement errorMessageConfirmButton;
+
+    @FindBy(xpath = "//button[contains(@class, 'ant-btn')]/span[contains(., 
'OK')]")
+    private WebElement deleteConfirmButton;
+
+    private final CreateMemberForm createMemberForm = new CreateMemberForm();
+
+    public MemberManagementPage(RemoteWebDriver driver) {
+        super(driver);
+    }
+
+    public MemberManagementPage createMember(String userName, String role) {
+        waitForPageLoading();
+
+        new WebDriverWait(driver, Duration.ofSeconds(10))
+                
.until(ExpectedConditions.elementToBeClickable(buttonCreateMember));
+        buttonCreateMember.click();
+
+        createMemberForm.btnSelectUserNameDropDown().click();
+
+        new WebDriverWait(driver, Duration.ofSeconds(10))
+                
.until(ExpectedConditions.visibilityOfAllElements(createMemberForm.selectUserName));
+        createMemberForm.selectUserName.stream()
+                .filter(e -> e.getText().equals(userName))
+                .findFirst()
+                .orElseThrow(
+                        () -> new RuntimeException(
+                                String.format("No %s in username dropdown 
list", userName)))
+                .click();
+
+        createMemberForm().btnSelectRoleDropDown().click();
+        new WebDriverWait(driver, Duration.ofSeconds(10))
+                
.until(ExpectedConditions.visibilityOfAllElements(createMemberForm.selectRole));
+        createMemberForm.selectRole.stream()
+                .filter(e -> e.getText().equals(role))
+                .findFirst()
+                .orElseThrow(
+                        () -> new RuntimeException(
+                                String.format("No %s in role dropdown list", 
role)))
+                .click();
+
+        createMemberForm.buttonSubmit.click();
+        return this;
+    }
+
+    public MemberManagementPage editMember(String userName, String role) {
+        waitForPageLoading();
+
+        memberList().stream()
+                .filter(it -> it.getText().contains(userName))
+                .flatMap(
+                        it -> 
it.findElements(By.xpath("//button[contains(@tooltip,'Modify 
Member')]")).stream())
+                .filter(WebElement::isDisplayed)
+                .findFirst()
+                .orElseThrow(() -> new RuntimeException("No edit button in 
member list"))
+                .click();
+
+        createMemberForm().btnSelectRoleDropDown().click();
+        new WebDriverWait(driver, Duration.ofSeconds(10))
+                
.until(ExpectedConditions.visibilityOfAllElements(createMemberForm.selectRole));
+        createMemberForm.selectRole.stream()
+                .filter(e -> e.getText().equals(role))
+                .findFirst()
+                .orElseThrow(
+                        () -> new RuntimeException(
+                                String.format("No %s in role dropdown list", 
role)))
+                .click();
+
+        createMemberForm.buttonSubmit.click();
+
+        return this;
+    }
+    public MemberManagementPage deleteMember(String userName) {
+        waitForPageLoading();
+
+        memberList().stream()
+                .filter(it -> it.getText().contains(userName))
+                .flatMap(
+                        it -> 
it.findElements(By.xpath("//button[contains(@tooltip,'Delete 
Member')]")).stream())
+                .filter(WebElement::isDisplayed)
+                .findFirst()
+                .orElseThrow(() -> new RuntimeException("No delete button in 
member list"))
+                .click();
+
+        new WebDriverWait(driver, Duration.ofSeconds(10))
+                
.until(ExpectedConditions.elementToBeClickable(deleteConfirmButton));
+
+        deleteConfirmButton.click();
+
+        return this;
+    }
+
+    private void waitForPageLoading() {
+        new WebDriverWait(driver, Duration.ofSeconds(10))
+                .until(ExpectedConditions.urlContains("/system/member"));
+    }
+
+    @Getter
+    public class CreateMemberForm {
+
+        CreateMemberForm() {
+            PageFactory.initElements(driver, this);
+        }
+
+        @FindBy(css = 
"div[optionfiltergroup='username'][codefield='userName']")
+        private WebElement btnSelectUserNameDropDown;
+
+        @FindBys({
+                @FindBy(css = "[codefield='userName']"),
+                @FindBy(className = "ant-select-item-option-content")
+        })
+        private List<WebElement> selectUserName;
+
+        @FindBy(css = "[codefield='roleId']")
+        private WebElement btnSelectRoleDropDown;
+
+        @FindBys({
+                @FindBy(css = "[codefield='roleId']"),
+                @FindBy(className = "ant-select-item-option-content")
+        })
+        private List<WebElement> selectRole;
+
+        @FindBy(xpath = "//button[contains(@class, 
'ant-btn')]//span[contains(., 'Submit')]")
+        private WebElement buttonSubmit;
+
+        @FindBy(xpath = "//button[contains(@class, 
'ant-btn')]//span[contains(., 'Cancel')]")
+        private WebElement buttonCancel;
+    }
+}
diff --git 
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/system/SystemPage.java
 
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/system/SystemPage.java
index b008063a4..eff871e75 100644
--- 
a/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/system/SystemPage.java
+++ 
b/streampark-e2e/streampark-e2e-case/src/test/java/org/apache/streampark/e2e/pages/system/SystemPage.java
@@ -75,6 +75,13 @@ public final class SystemPage extends NavBarPage implements 
NavBarItem {
             return tab.cast(new RoleManagementPage(driver));
         }
 
+        if (tab == MemberManagementPage.class) {
+            new WebDriverWait(driver, Duration.ofSeconds(10))
+                    
.until(ExpectedConditions.elementToBeClickable(menuMemberManagement));
+            menuMemberManagement.click();
+            return tab.cast(new MemberManagementPage(driver));
+        }
+
         throw new UnsupportedOperationException("Unknown tab: " + 
tab.getName());
     }
 

Reply via email to