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

kezhenxu94 pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 269a624  Add E2E case for user manage (#7652)
269a624 is described below

commit 269a62418f9b4374d036249f0a133dd377425f2e
Author: kezhenxu94 <[email protected]>
AuthorDate: Tue Dec 28 14:02:06 2021 +0800

    Add E2E case for user manage (#7652)
---
 .github/workflows/e2e.yml                          |   2 +
 .../dolphinscheduler/e2e/cases/TenantE2ETest.java  |  10 +-
 .../dolphinscheduler/e2e/cases/UserE2ETest.java    | 139 +++++++++++++++++++
 .../e2e/pages/security/SecurityPage.java           |   8 ++
 .../e2e/pages/security/TenantPage.java             |   8 --
 .../e2e/pages/security/UserPage.java               | 148 +++++++++++++++++++++
 .../e2e/core/DolphinSchedulerExtension.java        |   4 +-
 .../security/pages/users/_source/createUser.vue    |   6 +
 .../pages/security/pages/users/_source/list.vue    |   8 +-
 .../conf/home/pages/security/pages/users/index.vue |   2 +-
 .../components/secondaryMenu/_source/menu.js       |   3 +-
 11 files changed, 321 insertions(+), 17 deletions(-)

diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 87828b7..63df024 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -42,6 +42,8 @@ jobs:
         case:
           - name: Tenant
             class: org.apache.dolphinscheduler.e2e.cases.TenantE2ETest
+          - name: User
+            class: org.apache.dolphinscheduler.e2e.cases.UserE2ETest
           - name: Project
             class: org.apache.dolphinscheduler.e2e.cases.ProjectE2ETest
           - name: Workflow
diff --git 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/TenantE2ETest.java
 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/TenantE2ETest.java
index 4938a8b..254a2af 100644
--- 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/TenantE2ETest.java
+++ 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/TenantE2ETest.java
@@ -32,6 +32,7 @@ import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Order;
 import org.junit.jupiter.api.Test;
 import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
 import org.openqa.selenium.remote.RemoteWebDriver;
 
 @DolphinScheduler(composeFiles = "docker/basic/docker-compose.yaml")
@@ -52,7 +53,13 @@ class TenantE2ETest {
     @Test
     @Order(10)
     void testCreateTenant() {
-        new TenantPage(browser).create(tenant);
+        final TenantPage page = new TenantPage(browser);
+        page.create(tenant);
+
+        await().untilAsserted(() -> assertThat(page.tenantList())
+            .as("Tenant list should contain newly-created tenant")
+            .extracting(WebElement::getText)
+            .anyMatch(it -> it.contains(tenant)));
     }
 
     @Test
@@ -78,6 +85,7 @@ class TenantE2ETest {
 
         await().untilAsserted(() -> {
             browser.navigate().refresh();
+
             assertThat(
                 page.tenantList()
             ).noneMatch(
diff --git 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/UserE2ETest.java
 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/UserE2ETest.java
new file mode 100644
index 0000000..8b43e1b
--- /dev/null
+++ 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/UserE2ETest.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to 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. Apache Software Foundation (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.dolphinscheduler.e2e.cases;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+
+import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
+import org.apache.dolphinscheduler.e2e.pages.LoginPage;
+import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage;
+import org.apache.dolphinscheduler.e2e.pages.security.TenantPage;
+import org.apache.dolphinscheduler.e2e.pages.security.UserPage;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.remote.RemoteWebDriver;
+
+@DolphinScheduler(composeFiles = "docker/basic/docker-compose.yaml")
+class UserE2ETest {
+    private static final String tenant = System.getProperty("user.name");
+    private static final String user = "test_user";
+    private static final String password = "test_user123";
+    private static final String email = "[email protected]";
+    private static final String phone = "15800000000";
+
+    private static final String editUser = "edit_test_user";
+    private static final String editPassword = "edit_test_user123";
+    private static final String editEmail = "[email protected]";
+    private static final String editPhone = "15800000001";
+
+    private static RemoteWebDriver browser;
+
+    @BeforeAll
+    public static void setup() {
+        new LoginPage(browser)
+            .login("admin", "dolphinscheduler123")
+            .goToNav(SecurityPage.class)
+            .goToTab(TenantPage.class)
+            .create(tenant)
+            .goToNav(SecurityPage.class)
+            .goToTab(UserPage.class);
+    }
+
+    @AfterAll
+    public static void cleanup() {
+        new SecurityPage(browser)
+            .goToTab(TenantPage.class)
+            .delete(tenant)
+        ;
+    }
+
+    @Test
+    @Order(1)
+    void testCreateUser() {
+        final UserPage page = new UserPage(browser);
+
+        page.create(user, password, email, phone);
+
+        await().untilAsserted(() -> {
+            browser.navigate().refresh();
+
+            assertThat(page.userList())
+                .as("User list should contain newly-created user")
+                .extracting(WebElement::getText)
+                .anyMatch(it -> it.contains(user));
+        });
+    }
+
+    @Test
+    @Order(20)
+    void testCreateDuplicateUser() {
+        final UserPage page = new UserPage(browser);
+
+        page.create(user, password, email, phone);
+
+        await().untilAsserted(() ->
+            assertThat(browser.findElement(By.tagName("body")).getText())
+                .contains("already exists")
+        );
+
+        page.createUserForm().buttonCancel().click();
+    }
+
+    @Test
+    @Order(30)
+    void testEditUser() {
+        final UserPage page = new UserPage(browser);
+        page.update(user, editUser, editPassword, editEmail, editPhone);
+
+        await().untilAsserted(() -> {
+            browser.navigate().refresh();
+            assertThat(page.userList())
+                .as("User list should contain newly-modified User")
+                .extracting(WebElement::getText)
+                .anyMatch(it -> it.contains(editUser));
+        });
+    }
+
+
+    @Test
+    @Order(40)
+    void testDeleteUser() {
+        final UserPage page = new UserPage(browser);
+
+        page.delete(editUser);
+
+        await().untilAsserted(() -> {
+            browser.navigate().refresh();
+
+            assertThat(
+                page.userList()
+            ).noneMatch(
+                it -> it.getText().contains(user) || 
it.getText().contains(editUser)
+            );
+        });
+    }
+}
diff --git 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/SecurityPage.java
 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/SecurityPage.java
index 36f960c..920d171 100644
--- 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/SecurityPage.java
+++ 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/SecurityPage.java
@@ -33,6 +33,10 @@ public class SecurityPage extends NavBarPage implements 
NavBarItem {
     @FindBy(className = "tab-tenant-manage")
     private WebElement menuTenantManage;
 
+    @FindBy(className = "tab-user-manage")
+    private WebElement menUserManage;
+
+
     public SecurityPage(RemoteWebDriver driver) {
         super(driver);
     }
@@ -42,6 +46,10 @@ public class SecurityPage extends NavBarPage implements 
NavBarItem {
             menuTenantManage().click();
             return tab.cast(new TenantPage(driver));
         }
+        if (tab == UserPage.class) {
+            menUserManage().click();
+            return tab.cast(new UserPage(driver));
+        }
 
         throw new UnsupportedOperationException("Unknown tab: " + 
tab.getName());
     }
diff --git 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/TenantPage.java
 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/TenantPage.java
index 6fc70c6..eba9cce 100644
--- 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/TenantPage.java
+++ 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/TenantPage.java
@@ -19,9 +19,6 @@
 
 package org.apache.dolphinscheduler.e2e.pages.security;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
-
 import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
 
 import java.util.List;
@@ -67,11 +64,6 @@ public final class TenantPage extends NavBarPage implements 
SecurityPage.Tab {
         createTenantForm().inputDescription().sendKeys(description);
         createTenantForm().buttonSubmit().click();
 
-        await().untilAsserted(() -> assertThat(tenantList())
-            .as("Tenant list should contain newly-created tenant")
-            .extracting(WebElement::getText)
-            .anyMatch(it -> it.contains(tenant)));
-
         return this;
     }
 
diff --git 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/UserPage.java
 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/UserPage.java
new file mode 100644
index 0000000..b602404
--- /dev/null
+++ 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/UserPage.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to 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. Apache Software Foundation (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.dolphinscheduler.e2e.pages.security;
+
+import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
+
+import java.util.List;
+
+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 lombok.Getter;
+
+@Getter
+public final class UserPage extends NavBarPage implements SecurityPage.Tab {
+    @FindBy(id = "btnCreateUser")
+    private WebElement buttonCreateUser;
+
+    @FindBy(className = "items")
+    private List<WebElement> userList;
+
+    @FindBys({
+        @FindBy(className = "el-popconfirm"),
+        @FindBy(className = "el-button--primary"),
+    })
+    private List<WebElement> buttonConfirm;
+
+    private final UserForm createUserForm = new UserForm();
+    private final UserForm editUserForm = new UserForm();
+
+
+    public UserPage(RemoteWebDriver driver) {
+        super(driver);
+    }
+
+    public UserPage create(String user, String password, String email, String 
phone) {
+        buttonCreateUser().click();
+
+        createUserForm().inputUserName().sendKeys(user);
+        createUserForm().inputUserPassword().sendKeys(password);
+        createUserForm().inputEmail().sendKeys(email);
+        createUserForm().inputPhone().sendKeys(phone);
+        createUserForm().buttonSubmit().click();
+
+        return this;
+    }
+
+    public UserPage update(String user, String editUser, String editPassword, 
String editEmail, String editPhone) {
+        userList()
+            .stream()
+            .filter(it -> 
it.findElement(By.className("name")).getAttribute("innerHTML").contains(user))
+            .flatMap(it -> it.findElements(By.className("edit")).stream())
+            .filter(WebElement::isDisplayed)
+            .findFirst()
+            .orElseThrow(() -> new RuntimeException("No edit button in user 
list"))
+            .click();
+
+        editUserForm().inputUserName().clear();
+        editUserForm().inputUserName().sendKeys(editUser);
+        editUserForm().inputUserPassword().clear();
+        editUserForm().inputUserPassword().sendKeys(editPassword);
+        editUserForm().inputEmail().clear();
+        editUserForm().inputEmail().sendKeys(editEmail);
+        editUserForm().inputPhone().clear();
+        editUserForm().inputPhone().sendKeys(editPhone);
+        editUserForm().buttonSubmit().click();
+
+        return this;
+    }
+
+    public UserPage delete(String user) {
+        userList()
+            .stream()
+            .filter(it -> 
it.findElement(By.className("name")).getAttribute("innerHTML").contains(user))
+            .flatMap(it -> it.findElements(By.className("delete")).stream())
+            .filter(WebElement::isDisplayed)
+            .findFirst()
+            .orElseThrow(() -> new RuntimeException("No delete button in user 
list"))
+            .click();
+
+        buttonConfirm()
+            .stream()
+            .filter(WebElement::isDisplayed)
+            .findFirst()
+            .orElseThrow(() -> new RuntimeException("No confirm button when 
deleting"))
+            .click();
+
+        return this;
+    }
+
+    @Getter
+    public class UserForm {
+        UserForm() {
+            PageFactory.initElements(driver, this);
+        }
+
+        @FindBy(id = "inputUserName")
+        private WebElement inputUserName;
+
+        @FindBy(id = "inputUserPassword")
+        private WebElement inputUserPassword;
+
+        @FindBy(id = "selectTenant")
+        private WebElement selectTenant;
+
+        @FindBy(id = "selectQueue")
+        private WebElement selectQueue;
+
+        @FindBy(id = "inputEmail")
+        private WebElement inputEmail;
+
+        @FindBy(id = "inputPhone")
+        private WebElement inputPhone;
+
+        @FindBy(id = "radioStateEnable")
+        private WebElement radioStateEnable;
+
+        @FindBy(id = "radioStateDisable")
+        private WebElement radioStateDisable;
+
+        @FindBy(id = "btnSubmit")
+        private WebElement buttonSubmit;
+
+        @FindBy(id = "btnCancel")
+        private WebElement buttonCancel;
+    }
+}
diff --git 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-core/src/main/java/org/apache/dolphinscheduler/e2e/core/DolphinSchedulerExtension.java
 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-core/src/main/java/org/apache/dolphinscheduler/e2e/core/DolphinSchedulerExtension.java
index d6b1886..d43386f 100644
--- 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-core/src/main/java/org/apache/dolphinscheduler/e2e/core/DolphinSchedulerExtension.java
+++ 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-core/src/main/java/org/apache/dolphinscheduler/e2e/core/DolphinSchedulerExtension.java
@@ -73,8 +73,8 @@ final class DolphinSchedulerExtension
     @Override
     @SuppressWarnings("UnstableApiUsage")
     public void beforeAll(ExtensionContext context) throws IOException {
-        Awaitility.setDefaultTimeout(Duration.ofSeconds(10));
-        Awaitility.setDefaultPollInterval(Duration.ofSeconds(1));
+        Awaitility.setDefaultTimeout(Duration.ofSeconds(60));
+        Awaitility.setDefaultPollInterval(Duration.ofSeconds(10));
 
         Network network = null;
         HostAndPort address = null;
diff --git 
a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/_source/createUser.vue
 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/_source/createUser.vue
index 88f69fe..8f3adc0 100644
--- 
a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/_source/createUser.vue
+++ 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/_source/createUser.vue
@@ -16,6 +16,8 @@
  */
 <template>
   <m-popover
+          okId="btnSubmit"
+          cancelId="btnCancel"
           ref="popover"
           :ok-text="item ? $t('Edit') : $t('Submit')"
           @ok="_ok"
@@ -26,6 +28,7 @@
           <template slot="name"><strong>*</strong>{{$t('User 
Name')}}</template>
           <template slot="content">
             <el-input
+                    id="inputUserName"
                     type="input"
                     v-model="userName"
                     maxlength="60"
@@ -38,6 +41,7 @@
           <template slot="name"><strong>*</strong>{{$t('Password')}}</template>
           <template slot="content">
             <el-input
+                    id="inputUserPassword"
                     type="password"
                     v-model="userPassword"
                     size="small"
@@ -79,6 +83,7 @@
           <template slot="name"><strong>*</strong>{{$t('Email')}}</template>
           <template slot="content">
             <el-input
+                    id="inputEmail"
                     type="input"
                     v-model="email"
                     size="small"
@@ -90,6 +95,7 @@
           <template slot="name">{{$t('Phone')}}</template>
           <template slot="content">
             <el-input
+                    id="inputPhone"
                     type="input"
                     v-model="phone"
                     size="small"
diff --git 
a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/_source/list.vue
 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/_source/list.vue
index 615cf97..212060b 100644
--- 
a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/_source/list.vue
+++ 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/_source/list.vue
@@ -17,9 +17,9 @@
 <template>
   <div class="list-model user-list-model">
     <div class="table-box">
-      <el-table :data="list" size="mini" style="width: 100%">
+      <el-table :data="list" size="mini" style="width: 100%" 
row-class-name="items">
         <el-table-column type="index" :label="$t('#')" 
width="50"></el-table-column>
-        <el-table-column prop="userName" :label="$t('User 
Name')"></el-table-column>
+        <el-table-column prop="userName" :label="$t('User Name')" 
class-name="name"></el-table-column>
         <el-table-column :label="$t('User Type')" width="80">
           <template slot-scope="scope">
             {{scope.row.userType === 'GENERAL_USER' ? `${$t('Ordinary 
users')}` : `${$t('Administrator')}`}}
@@ -62,7 +62,7 @@
               </el-dropdown>
             </el-tooltip>
             <el-tooltip :content="$t('Edit')" placement="top">
-              <el-button type="primary" size="mini" 
icon="el-icon-edit-outline" @click="_edit(scope.row)" circle></el-button>
+              <el-button type="primary" size="mini" 
icon="el-icon-edit-outline" @click="_edit(scope.row)" circle 
class="edit"></el-button>
             </el-tooltip>
             <el-tooltip :content="$t('Delete')" placement="top">
               <el-popconfirm
@@ -73,7 +73,7 @@
                 :title="$t('Delete?')"
                 @onConfirm="_delete(scope.row,scope.row.id)"
               >
-                <el-button type="danger" size="mini" icon="el-icon-delete" 
circle slot="reference"></el-button>
+                <el-button type="danger" size="mini" icon="el-icon-delete" 
circle slot="reference" class="delete"></el-button>
               </el-popconfirm>
             </el-tooltip>
           </template>
diff --git 
a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/index.vue 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/index.vue
index 58bcb86..44f8adc 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/index.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/users/index.vue
@@ -19,7 +19,7 @@
     <template slot="conditions">
       <m-conditions @on-conditions="_onConditions">
         <template slot="button-group" v-if="userList.length">
-          <el-button size="mini" @click="_create('')">{{$t('Create 
User')}}</el-button>
+          <el-button id="btnCreateUser" size="mini" 
@click="_create('')">{{$t('Create User')}}</el-button>
           <el-dialog
             :title="item ? $t('Edit User') : $t('Create User')"
             v-if="createUserDialog"
diff --git 
a/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js 
b/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js
index 3eb7c9f..09395ca 100644
--- a/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js
+++ b/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js
@@ -107,7 +107,8 @@ const menu = {
       isOpen: true,
       enabled: true,
       icon: 'el-icon-user-solid',
-      children: []
+      children: [],
+      classNames: 'tab-user-manage'
     },
     {
       name: `${i18n.$t('Warning group manage')}`,

Reply via email to