[E2E] add function manage test case (#8250)
parent
01936a660e
commit
4b58df9aa8
|
|
@ -87,6 +87,8 @@ jobs:
|
|||
class: org.apache.dolphinscheduler.e2e.cases.FileManageE2ETest
|
||||
- name: UdfManage
|
||||
class: org.apache.dolphinscheduler.e2e.cases.UdfManageE2ETest
|
||||
- name: FunctionManage
|
||||
class: org.apache.dolphinscheduler.e2e.cases.FunctionManageE2ETest
|
||||
- name: MysqlDataSource
|
||||
class: org.apache.dolphinscheduler.e2e.cases.MysqlDataSourceE2ETest
|
||||
- name: ClickhouseDataSource
|
||||
|
|
|
|||
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* 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.dolphinscheduler.e2e.cases;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
|
||||
import org.apache.dolphinscheduler.e2e.core.Constants;
|
||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||
import org.apache.dolphinscheduler.e2e.pages.resource.FunctionManagePage;
|
||||
import org.apache.dolphinscheduler.e2e.pages.resource.ResourcePage;
|
||||
import org.apache.dolphinscheduler.e2e.pages.resource.UdfManagePage;
|
||||
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 java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.Comparator;
|
||||
|
||||
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 org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
@DolphinScheduler(composeFiles = "docker/file-manage/docker-compose.yaml")
|
||||
public class FunctionManageE2ETest {
|
||||
private static RemoteWebDriver browser;
|
||||
|
||||
private static final String tenant = System.getProperty("user.name");
|
||||
|
||||
private static final String user = "admin";
|
||||
|
||||
private static final String password = "dolphinscheduler123";
|
||||
|
||||
private static final String email = "admin@gmail.com";
|
||||
|
||||
private static final String phone = "15800000000";
|
||||
|
||||
private static final String testUdfFunctionName = "test_function";
|
||||
|
||||
private static final String testRenameUdfFunctionName = "test_rename_function";
|
||||
|
||||
private static final String testUploadUdfFileName = "hive-jdbc-3.1.2.jar";
|
||||
|
||||
private static final String testClassName = "org.dolphinscheduler.UdfTest";
|
||||
|
||||
private static final String testDescription = "test_description";
|
||||
|
||||
private static final Path testUploadUdfFilePath = Constants.HOST_TMP_PATH.resolve(testUploadUdfFileName);
|
||||
|
||||
@BeforeAll
|
||||
@SneakyThrows
|
||||
public static void setup() {
|
||||
TenantPage tenantPage = new LoginPage(browser)
|
||||
.login(user, password)
|
||||
.create(tenant);
|
||||
|
||||
await().untilAsserted(() -> assertThat(tenantPage.tenantList())
|
||||
.as("Tenant list should contain newly-created tenant")
|
||||
.extracting(WebElement::getText)
|
||||
.anyMatch(it -> it.contains(tenant)));
|
||||
|
||||
downloadFile("https://repo1.maven.org/maven2/org/apache/hive/hive-jdbc/3.1.2/hive-jdbc-3.1.2.jar", testUploadUdfFilePath.toFile().getAbsolutePath());
|
||||
|
||||
UdfManagePage udfManagePage = tenantPage.goToNav(SecurityPage.class)
|
||||
.goToTab(UserPage.class)
|
||||
.update(user, user, password, email, phone)
|
||||
.goToNav(ResourcePage.class)
|
||||
.goToTab(UdfManagePage.class)
|
||||
.uploadFile(testUploadUdfFilePath.toFile().getAbsolutePath());
|
||||
|
||||
new WebDriverWait(browser, 10).until(ExpectedConditions.invisibilityOfElementLocated(By.id("fileUpdateDialog")));
|
||||
|
||||
udfManagePage.goToNav(ResourcePage.class)
|
||||
.goToTab(FunctionManagePage.class);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@SneakyThrows
|
||||
public static void cleanup() {
|
||||
Files.walk(Constants.HOST_CHROME_DOWNLOAD_PATH)
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.map(Path::toFile)
|
||||
.forEach(File::delete);
|
||||
|
||||
Files.deleteIfExists(testUploadUdfFilePath);
|
||||
}
|
||||
|
||||
static void downloadFile(String downloadUrl, String filePath) throws Exception {
|
||||
int byteRead;
|
||||
|
||||
URL url = new URL(downloadUrl);
|
||||
|
||||
URLConnection conn = url.openConnection();
|
||||
InputStream inStream = conn.getInputStream();
|
||||
FileOutputStream fs = new FileOutputStream(filePath);
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
while ((byteRead = inStream.read(buffer)) != -1) {
|
||||
fs.write(buffer, 0, byteRead);
|
||||
}
|
||||
|
||||
inStream.close();
|
||||
fs.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(10)
|
||||
void testCreateUdfFunction() {
|
||||
FunctionManagePage page = new FunctionManagePage(browser);
|
||||
|
||||
new WebDriverWait(page.driver(), 10)
|
||||
.until(ExpectedConditions.urlContains("/#/resource/func"));
|
||||
|
||||
page.createUdfFunction(testUdfFunctionName, testClassName, testUploadUdfFileName, testDescription);
|
||||
|
||||
await().untilAsserted(() -> assertThat(page.functionList())
|
||||
.as("Function list should contain newly-created file")
|
||||
.extracting(WebElement::getText)
|
||||
.anyMatch(it -> it.contains(testUdfFunctionName)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(20)
|
||||
void testRenameUdfFunction() {
|
||||
FunctionManagePage page = new FunctionManagePage(browser);
|
||||
|
||||
browser.navigate().refresh();
|
||||
|
||||
page.renameUdfFunction(testUdfFunctionName, testRenameUdfFunctionName);
|
||||
|
||||
await().pollDelay(Duration.ofSeconds(2)).untilAsserted(() -> assertThat(page.functionList())
|
||||
.as("Function list should contain newly-created file")
|
||||
.extracting(WebElement::getText)
|
||||
.anyMatch(it -> it.contains(testRenameUdfFunctionName)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(30)
|
||||
void testDeleteUdfFunction() {
|
||||
FunctionManagePage page = new FunctionManagePage(browser);
|
||||
|
||||
page.deleteUdfFunction(testRenameUdfFunctionName);
|
||||
|
||||
await().untilAsserted(() -> {
|
||||
browser.navigate().refresh();
|
||||
|
||||
assertThat(
|
||||
page.functionList()
|
||||
).noneMatch(
|
||||
it -> it.getText().contains(testRenameUdfFunctionName)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -24,11 +24,154 @@ import lombok.Getter;
|
|||
|
||||
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 org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
@Getter
|
||||
public class FunctionManagePage extends NavBarPage implements ResourcePage.Tab {
|
||||
@FindBy(id = "btnCreateUdfFunction")
|
||||
private WebElement buttonCreateUdfFunction;
|
||||
|
||||
@FindBy(className = "udf-function-items")
|
||||
private List<WebElement> functionList;
|
||||
|
||||
@FindBys({
|
||||
@FindBy(className = "el-popconfirm"),
|
||||
@FindBy(className = "el-button--primary"),
|
||||
})
|
||||
private List<WebElement> buttonConfirm;
|
||||
|
||||
private final CreateUdfFunctionBox createUdfFunctionBox;
|
||||
|
||||
private final RenameUdfFunctionBox renameUdfFunctionBox;
|
||||
|
||||
public FunctionManagePage(RemoteWebDriver driver) {
|
||||
super(driver);
|
||||
|
||||
createUdfFunctionBox = new CreateUdfFunctionBox();
|
||||
|
||||
renameUdfFunctionBox = new RenameUdfFunctionBox();
|
||||
}
|
||||
|
||||
public FunctionManagePage createUdfFunction(String udfFunctionName, String className, String udfResourceName, String description) {
|
||||
buttonCreateUdfFunction().click();
|
||||
|
||||
createUdfFunctionBox().inputFunctionName().sendKeys(udfFunctionName);
|
||||
|
||||
createUdfFunctionBox().inputClassName().sendKeys(className);
|
||||
|
||||
createUdfFunctionBox().inputDescription().sendKeys(description);
|
||||
|
||||
createUdfFunctionBox().buttonUdfResourceDropDown().click();
|
||||
|
||||
createUdfFunctionBox().selectUdfResource()
|
||||
.stream()
|
||||
.filter(it -> it.getText().contains(udfResourceName))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException(String.format("No %s in udf resource list", udfResourceName)))
|
||||
.click();
|
||||
|
||||
createUdfFunctionBox().buttonSubmit().click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FunctionManagePage renameUdfFunction(String currentName, String afterName) {
|
||||
functionList()
|
||||
.stream()
|
||||
.filter(it -> it.getText().contains(currentName))
|
||||
.flatMap(it -> it.findElements(By.id("btnRename")).stream())
|
||||
.filter(WebElement::isDisplayed)
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("No rename button in function manage list"))
|
||||
.click();
|
||||
|
||||
new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.id("createUdfDialog")));
|
||||
|
||||
renameUdfFunctionBox().inputFunctionName().clear();
|
||||
|
||||
renameUdfFunctionBox().inputFunctionName().sendKeys(afterName);
|
||||
|
||||
renameUdfFunctionBox.buttonSubmit().click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FunctionManagePage deleteUdfFunction(String udfFunctionName) {
|
||||
functionList()
|
||||
.stream()
|
||||
.filter(it -> it.getText().contains(udfFunctionName))
|
||||
.flatMap(it -> it.findElements(By.id("btnDelete")).stream())
|
||||
.filter(WebElement::isDisplayed)
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("No delete button in udf resource list"))
|
||||
.click();
|
||||
|
||||
buttonConfirm()
|
||||
.stream()
|
||||
.filter(WebElement::isDisplayed)
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("No confirm button when deleting in udf resource page"))
|
||||
.click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public class CreateUdfFunctionBox {
|
||||
CreateUdfFunctionBox() {
|
||||
PageFactory.initElements(driver, this);
|
||||
}
|
||||
|
||||
@FindBy(id = "inputFunctionName")
|
||||
private WebElement inputFunctionName;
|
||||
|
||||
@FindBy(id = "inputClassName")
|
||||
private WebElement inputClassName;
|
||||
|
||||
@FindBy(id = "btnUdfResourceDropDown")
|
||||
private WebElement buttonUdfResourceDropDown;
|
||||
|
||||
@FindBy(className = "vue-treeselect__menu")
|
||||
private List<WebElement> selectUdfResource;
|
||||
|
||||
@FindBy(id = "inputDescription")
|
||||
private WebElement inputDescription;
|
||||
|
||||
@FindBy(id = "btnSubmit")
|
||||
private WebElement buttonSubmit;
|
||||
|
||||
@FindBy(id = "btnCancel")
|
||||
private WebElement buttonCancel;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public class RenameUdfFunctionBox {
|
||||
RenameUdfFunctionBox() {
|
||||
PageFactory.initElements(driver, this);
|
||||
}
|
||||
|
||||
@FindBy(id = "inputFunctionName")
|
||||
private WebElement inputFunctionName;
|
||||
|
||||
@FindBy(id = "inputClassName")
|
||||
private WebElement inputClassName;
|
||||
|
||||
@FindBy(id = "inputDescription")
|
||||
private WebElement inputDescription;
|
||||
|
||||
@FindBy(id = "btnSubmit")
|
||||
private WebElement buttonSubmit;
|
||||
|
||||
@FindBy(id = "btnCancel")
|
||||
private WebElement buttonCancel;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
<template slot="name"><strong>*</strong>{{$t('UDF Resources')}}</template>
|
||||
<template slot="content">
|
||||
<treeselect id="btnUdfResourceDropDown" style="width:535px;float:left;" v-model="resourceId" maxHeight="200" :disable-branch-nodes="true" :options="udfResourceList" :disabled="isUpdate" :normalizer="normalizer" :placeholder="$t('Please select UDF resources directory')">
|
||||
<div class="options-udf-resource" slot="value-label" slot-scope="{ node }">{{ node.raw.fullName }}</div>
|
||||
<div slot="value-label" slot-scope="{ node }">{{ node.raw.fullName }}</div>
|
||||
</treeselect>
|
||||
<el-button type="primary" size="small" @click="_toggleUpdate" :disabled="upDisabled">{{$t('Upload Resources')}}</el-button>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<template>
|
||||
<div class="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="udf-function-items">
|
||||
<el-table-column type="index" :label="$t('#')" min-width="120"></el-table-column>
|
||||
<el-table-column :label="$t('UDF Function Name')">
|
||||
<template slot-scope="scope">
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
<el-table-column :label="$t('Operation')" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tooltip :content="$t('Rename')" placement="top" :enterable="false">
|
||||
<span><el-button type="primary" size="mini" icon="el-icon-edit-outline" @click="_edit(scope.row)" circle></el-button></span>
|
||||
<span><el-button id="btnRename" type="primary" size="mini" icon="el-icon-edit-outline" @click="_edit(scope.row)" circle></el-button></span>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="$t('Delete')" placement="top" :enterable="false">
|
||||
<el-popconfirm
|
||||
|
|
@ -56,7 +56,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 id="btnDelete" type="danger" size="mini" icon="el-icon-delete" circle slot="reference"></el-button>
|
||||
</el-popconfirm>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
|
@ -64,6 +64,7 @@
|
|||
</el-table>
|
||||
</div>
|
||||
<el-dialog
|
||||
id="createUdfDialog"
|
||||
:visible.sync="createUdfDialog"
|
||||
width="auto">
|
||||
<m-create-udf :item="item" @onUpdate="onUpdate" @close="close"></m-create-udf>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
<m-conditions @on-conditions="_onConditions">
|
||||
<template slot="button-group">
|
||||
<el-button-group>
|
||||
<el-button size="mini" @click="_create">{{$t('Create UDF Function')}}</el-button>
|
||||
<el-button id="btnCreateUdfFunction" size="mini" @click="_create">{{$t('Create UDF Function')}}</el-button>
|
||||
</el-button-group>
|
||||
<el-dialog
|
||||
:visible.sync="createUdfDialog"
|
||||
|
|
|
|||
Loading…
Reference in New Issue