diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index a4dfeb0a5b..b4e3791aad 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -38,6 +38,8 @@ jobs: class: org.apache.dolphinscheduler.e2e.cases.TenantE2ETest - name: User class: org.apache.dolphinscheduler.e2e.cases.UserE2ETest + - name: WorkerGroup + class: org.apache.dolphinscheduler.e2e.cases.WorkerGroupE2ETest - 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/WorkerGroupE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkerGroupE2ETest.java new file mode 100644 index 0000000000..fb75122afa --- /dev/null +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkerGroupE2ETest.java @@ -0,0 +1,131 @@ +/* + * 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 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.WorkerGroupPage; +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; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +@DolphinScheduler(composeFiles = "docker/basic/docker-compose.yaml") +class WorkerGroupE2ETest { + private static final String tenant = System.getProperty("user.name"); + private static final String workerGroupName = "test_worker_group"; + private static final String editWorkerGroupName = "edit_worker_group"; + + 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(WorkerGroupPage.class); + } + + @AfterAll + public static void cleanup() { + new SecurityPage(browser) + .goToTab(TenantPage.class) + .delete(tenant) + ; + } + + @Test + @Order(1) + void testCreateWorkerGroup() throws InterruptedException { + final WorkerGroupPage page = new WorkerGroupPage(browser); + + page.create(workerGroupName); + + await().untilAsserted(() -> { + browser.navigate().refresh(); + + assertThat(page.workerGroupList()) + .as("workerGroup list should contain newly-created workerGroup") + .extracting(WebElement::getText) + .anyMatch(it -> it.contains(workerGroupName)); + }); + } + + @Test + @Order(20) + void testCreateDuplicateWorkerGroup() throws InterruptedException { + final WorkerGroupPage page = new WorkerGroupPage(browser); + + page.create(workerGroupName); + + await().untilAsserted(() -> + assertThat(browser.findElement(By.tagName("body")).getText()) + .contains("already exists") + ); + + page.createWorkerForm().buttonCancel().click(); + } + + @Test + @Order(30) + void testEditWorkerGroup() { + final WorkerGroupPage page = new WorkerGroupPage(browser); + page.update(workerGroupName, editWorkerGroupName); + + await().untilAsserted(() -> { + browser.navigate().refresh(); + assertThat(page.workerGroupList()) + .as("workerGroup list should contain newly-modified workerGroup") + .extracting(WebElement::getText) + .anyMatch(it -> it.contains(editWorkerGroupName)); + }); + } + + + @Test + @Order(40) + void testDeleteWorkerGroup() { + final WorkerGroupPage page = new WorkerGroupPage(browser); + + page.delete(editWorkerGroupName); + + await().untilAsserted(() -> { + browser.navigate().refresh(); + + assertThat( + page.workerGroupList() + ).noneMatch( + it -> it.getText().contains(workerGroupName) || it.getText().contains(editWorkerGroupName) + ); + }); + } +} 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 920d171b0d..67edcadfa8 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 @@ -36,6 +36,9 @@ public class SecurityPage extends NavBarPage implements NavBarItem { @FindBy(className = "tab-user-manage") private WebElement menUserManage; + @FindBy(className = "tab-worker-group-manage") + private WebElement menWorkerGroupManage; + public SecurityPage(RemoteWebDriver driver) { super(driver); @@ -50,7 +53,10 @@ public class SecurityPage extends NavBarPage implements NavBarItem { menUserManage().click(); return tab.cast(new UserPage(driver)); } - + if (tab == WorkerGroupPage.class) { + menWorkerGroupManage().click(); + return tab.cast(new WorkerGroupPage(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/WorkerGroupPage.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/WorkerGroupPage.java new file mode 100644 index 0000000000..41a9b605d7 --- /dev/null +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/WorkerGroupPage.java @@ -0,0 +1,129 @@ +/* + * 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 lombok.Getter; +import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage; +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 java.util.List; + + +@Getter +public final class WorkerGroupPage extends NavBarPage implements SecurityPage.Tab { + @FindBy(id = "btnCreateWorkerGroup") + private WebElement buttonCreateWorkerGroup; + + @FindBy(className = "items") + private List workerGroupList; + + @FindBys({ + @FindBy(className = "el-popconfirm"), + @FindBy(className = "el-button--primary"), + }) + private List buttonConfirm; + + private final WorkerGroupForm createWorkerForm = new WorkerGroupForm(); + private final WorkerGroupForm editWorkerForm = new WorkerGroupForm(); + + + + public WorkerGroupPage(RemoteWebDriver driver) { + super(driver); + } + + public WorkerGroupPage create(String workerGroupName) { + buttonCreateWorkerGroup().click(); + + createWorkerForm().inputWorkerGroupName().sendKeys(workerGroupName); + createWorkerForm().selectWorkerAddress().click(); + createWorkerForm().workerAddressList().click(); + + createWorkerForm().buttonSubmit().click(); + + return this; + } + + public WorkerGroupPage update(String workerGroupName, String editWorkerGroupName) { + workerGroupList() + .stream() + .filter(it -> it.findElement(By.className("name")).getAttribute("innerHTML").contains(workerGroupName)) + .flatMap(it -> it.findElements(By.className("edit")).stream()) + .filter(WebElement::isDisplayed) + .findFirst() + .orElseThrow(() -> new RuntimeException("No edit button in workerGroup list")) + .click(); + + editWorkerForm().inputWorkerGroupName().clear(); + editWorkerForm().inputWorkerGroupName().sendKeys(editWorkerGroupName); + + editWorkerForm().buttonSubmit().click(); + + return this; + } + + + public WorkerGroupPage delete(String Worker) { + workerGroupList() + .stream() + .filter(it -> it.findElement(By.className("name")).getAttribute("innerHTML").contains(Worker)) + .flatMap(it -> it.findElements(By.className("delete")).stream()) + .filter(WebElement::isDisplayed) + .findFirst() + .orElseThrow(() -> new RuntimeException("No delete button in workerGroup list")) + .click(); + + buttonConfirm() + .stream() + .filter(WebElement::isDisplayed) + .findFirst() + .orElseThrow(() -> new RuntimeException("No confirm button when deleting")) + .click(); + + return this; + } + + @Getter + public class WorkerGroupForm { + WorkerGroupForm() { + PageFactory.initElements(driver, this); + } + + @FindBy(id = "inputWorkerGroupName") + private WebElement inputWorkerGroupName; + + @FindBy(id = "selectWorkerAddress") + private WebElement selectWorkerAddress; + + @FindBy(className = "vue-treeselect__menu") + private WebElement workerAddressList; + + @FindBy(id = "btnSubmit") + private WebElement buttonSubmit; + + @FindBy(id = "btnCancel") + private WebElement buttonCancel; + } +} diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/_source/createWorker.vue b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/_source/createWorker.vue index 37f9bd1895..5264965b42 100644 --- a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/_source/createWorker.vue +++ b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/workerGroups/_source/createWorker.vue @@ -16,6 +16,8 @@ */