From 63f7efa99374be3410aa7c9007ebbeb0cbe69a06 Mon Sep 17 00:00:00 2001 From: QuakeWang <45645138+QuakeWang@users.noreply.github.com> Date: Sun, 30 Jan 2022 12:34:50 +0800 Subject: [PATCH] [E2E] Add new test of token management (#8161) --- .github/workflows/e2e.yml | 2 + .../e2e/cases/TokenE2ETest.java | 99 +++++++++++++ .../e2e/pages/security/SecurityPage.java | 18 ++- .../e2e/pages/security/TokenPage.java | 138 ++++++++++++++++++ .../user/pages/token/_source/createToken.vue | 4 +- .../pages/user/pages/token/_source/list.vue | 10 +- .../home/pages/user/pages/token/index.vue | 3 +- .../components/secondaryMenu/_source/menu.js | 3 +- 8 files changed, 264 insertions(+), 13 deletions(-) create mode 100644 dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/TokenE2ETest.java create mode 100644 dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/TokenPage.java diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 118bf77237..d9ae393bc5 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -81,6 +81,8 @@ jobs: class: org.apache.dolphinscheduler.e2e.cases.QueueE2ETest - name: Environment class: org.apache.dolphinscheduler.e2e.cases.EnvironmentE2ETest + - name: Token + class: org.apache.dolphinscheduler.e2e.cases.TokenE2ETest - name: Workflow class: org.apache.dolphinscheduler.e2e.cases.WorkflowE2ETest - name: FileManage diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/TokenE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/TokenE2ETest.java new file mode 100644 index 0000000000..530f4930bb --- /dev/null +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/TokenE2ETest.java @@ -0,0 +1,99 @@ +/* + * 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.TokenPage; + +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; + +@DolphinScheduler(composeFiles = "docker/basic/docker-compose.yaml") +public class TokenE2ETest { + + private static final String userName = "admin"; + + private static RemoteWebDriver browser; + + @BeforeAll + public static void setup() { + new LoginPage(browser) + .login("admin", "dolphinscheduler123") + .goToNav(SecurityPage.class) + .goToTab(TokenPage.class) + ; + } + + @Test + @Order(10) + void testCreateToken() { + final TokenPage page = new TokenPage(browser); + page.create(); + + await().untilAsserted(() -> { + browser.navigate().refresh(); + + assertThat(page.tokenList()) + .as("Token list should contain newly-created token") + .extracting(WebElement::getText) + .anyMatch(it -> it.contains(userName)); + }); + } + + @Test + @Order(30) + void testEditToken() { + final TokenPage page = new TokenPage(browser); + String oldToken = page.getToken(userName); + page.update(userName); + + await().untilAsserted(() -> { + browser.navigate().refresh(); + + assertThat(page.tokenList()) + .as("Token list should contain newly-modified token") + .extracting(WebElement::getText) + .isNotEqualTo(oldToken); + }); + } + + @Test + @Order(40) + void testDeleteToken() { + final TokenPage page = new TokenPage(browser); + page.delete(userName); + + await().untilAsserted(() -> { + browser.navigate().refresh(); + + assertThat(page.tokenList()) + .noneMatch(it -> it.getText().contains(userName)); + }); + } + +} 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 942ae2cbc9..2bbdd7bd2b 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 @@ -17,6 +17,7 @@ * under the License. * */ + package org.apache.dolphinscheduler.e2e.pages.security; import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage; @@ -26,11 +27,11 @@ import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.support.FindBy; - -import lombok.Getter; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; +import lombok.Getter; + @Getter public class SecurityPage extends NavBarPage implements NavBarItem { @FindBy(className = "tab-tenant-manage") @@ -48,6 +49,9 @@ public class SecurityPage extends NavBarPage implements NavBarItem { @FindBy(className = "tab-environment-manage") private WebElement menuEnvironmentManage; + @FindBy(className = "tab-token-manage") + private WebElement menuTokenManage; + public SecurityPage(RemoteWebDriver driver) { super(driver); } @@ -56,20 +60,20 @@ public class SecurityPage extends NavBarPage implements NavBarItem { if (tab == TenantPage.class) { WebElement menuTenantManageElement = new WebDriverWait(driver, 60) .until(ExpectedConditions.elementToBeClickable(menuTenantManage)); - ((JavascriptExecutor)driver).executeScript("arguments[0].click();", menuTenantManageElement); + ((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuTenantManageElement); return tab.cast(new TenantPage(driver)); } if (tab == UserPage.class) { WebElement menUserManageElement = new WebDriverWait(driver, 60) .until(ExpectedConditions.elementToBeClickable(menUserManage)); - ((JavascriptExecutor)driver).executeScript("arguments[0].click();", menUserManageElement); + ((JavascriptExecutor) driver).executeScript("arguments[0].click();", menUserManageElement); new WebDriverWait(driver, 25).until(ExpectedConditions.urlContains("/#/security/users")); return tab.cast(new UserPage(driver)); } if (tab == WorkerGroupPage.class) { WebElement menWorkerGroupManageElement = new WebDriverWait(driver, 60) .until(ExpectedConditions.elementToBeClickable(menWorkerGroupManage)); - ((JavascriptExecutor)driver).executeScript("arguments[0].click();", menWorkerGroupManageElement); + ((JavascriptExecutor) driver).executeScript("arguments[0].click();", menWorkerGroupManageElement); return tab.cast(new WorkerGroupPage(driver)); } if (tab == QueuePage.class) { @@ -80,6 +84,10 @@ public class SecurityPage extends NavBarPage implements NavBarItem { menuEnvironmentManage().click(); return tab.cast(new EnvironmentPage(driver)); } + if (tab == TokenPage.class) { + menuTokenManage().click(); + return tab.cast(new TokenPage(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/TokenPage.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/TokenPage.java new file mode 100644 index 0000000000..a3873b6426 --- /dev/null +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/TokenPage.java @@ -0,0 +1,138 @@ +/* + * 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 org.apache.dolphinscheduler.e2e.pages.security.SecurityPage.Tab; + +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 org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; + +import lombok.Getter; + +import com.google.common.base.Strings; + +@Getter +public final class TokenPage extends NavBarPage implements Tab { + @FindBy(id = "btnCreateToken") + private WebElement buttonCreateToken; + + @FindBy(className = "items") + private List tokenList; + + @FindBys({ + @FindBy(className = "el-popconfirm"), + @FindBy(className = "el-button--primary"), + }) + private List buttonConfirm; + + @FindBy(className = "userName") + private List userName; + + @FindBy(className = "token") + private List token; + + private final TokenForm createTokenForm = new TokenForm(); + private final TokenForm editTokenForm = new TokenForm(); + + public TokenPage(RemoteWebDriver driver) { + super(driver); + } + + public TokenPage create() { + buttonCreateToken().click(); + createTokenForm().buttonGenerateToken().click(); + new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(createTokenForm.buttonGenerateToken)); + createTokenForm().buttonSubmit().click(); + return this; + } + + public TokenPage update(String userName) { + tokenList().stream() + .filter(it -> it.findElement(By.className("userName")).getAttribute("innerHTML").contains(userName)) + .flatMap(it -> it.findElements(By.className("edit")).stream()) + .filter(WebElement::isDisplayed) + .findFirst() + .orElseThrow(() -> new RuntimeException("No edit button in token list")) + .click(); + + TokenForm editTokenForm = new TokenForm(); + + editTokenForm.buttonGenerateToken().click(); + new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(createTokenForm.buttonGenerateToken)); + editTokenForm.buttonSubmit().click(); + return this; + } + + public String getToken(String userName) { + return tokenList().stream() + .filter(it -> it.findElement(By.className("userName")).getAttribute("innerHTML").contains(userName)) + .flatMap(it -> it.findElements(By.className("token")).stream()) + .filter(it -> !Strings.isNullOrEmpty(it.getAttribute("innerHTML"))) + .map(it -> it.getAttribute("innerHTML")) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("No token for such user: " + userName)); + } + + public TokenPage delete(String userName) { + tokenList() + .stream() + .filter(it -> it.getText().contains(userName)) + .flatMap(it -> it.findElements(By.className("delete")).stream()) + .filter(WebElement::isDisplayed) + .findFirst() + .orElseThrow(() -> new RuntimeException("No delete button in token list")) + .click(); + + buttonConfirm() + .stream() + .filter(WebElement::isDisplayed) + .findFirst() + .orElseThrow(() -> new RuntimeException("No confirm button when deleting")) + .click(); + + return this; + } + + @Getter + public class TokenForm { + TokenForm() { + PageFactory.initElements(driver, this); + } + + @FindBy(id = "btnGenerateToken") + private WebElement buttonGenerateToken; + + @FindBy(id = "btnSubmit") + private WebElement buttonSubmit; + + @FindBy(id = "btnCancel") + private WebElement buttonCancel; + + } +} diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/user/pages/token/_source/createToken.vue b/dolphinscheduler-ui/src/js/conf/home/pages/user/pages/token/_source/createToken.vue index a76283c555..f8cab2cb3f 100644 --- a/dolphinscheduler-ui/src/js/conf/home/pages/user/pages/token/_source/createToken.vue +++ b/dolphinscheduler-ui/src/js/conf/home/pages/user/pages/token/_source/createToken.vue @@ -16,6 +16,8 @@ */ diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/user/pages/token/_source/list.vue b/dolphinscheduler-ui/src/js/conf/home/pages/user/pages/token/_source/list.vue index 300e1efffe..d3b397b39f 100644 --- a/dolphinscheduler-ui/src/js/conf/home/pages/user/pages/token/_source/list.vue +++ b/dolphinscheduler-ui/src/js/conf/home/pages/user/pages/token/_source/list.vue @@ -17,10 +17,10 @@