diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 13c878dee7..329af9f441 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -106,6 +106,8 @@ jobs: class: org.apache.dolphinscheduler.e2e.cases.TokenE2ETest - name: Workflow class: org.apache.dolphinscheduler.e2e.cases.WorkflowE2ETest + - name: WorkflowHttp + class: org.apache.dolphinscheduler.e2e.cases.WorkflowHttpTaskE2ETest # - name: WorkflowForSwitch # class: org.apache.dolphinscheduler.e2e.cases.WorkflowSwitchE2ETest - name: FileManage diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowHttpTaskE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowHttpTaskE2ETest.java new file mode 100644 index 0000000000..0993e61b81 --- /dev/null +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowHttpTaskE2ETest.java @@ -0,0 +1,168 @@ +/* + * 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.common.NavBarPage; +import org.apache.dolphinscheduler.e2e.pages.project.ProjectDetailPage; +import org.apache.dolphinscheduler.e2e.pages.project.ProjectPage; +import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowDefinitionTab; +import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowForm; +import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowInstanceTab; +import org.apache.dolphinscheduler.e2e.pages.project.workflow.task.HttpTaskForm; +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.remote.RemoteWebDriver; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.testcontainers.shaded.org.awaitility.Awaitility; + +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; +@DolphinScheduler(composeFiles = "docker/workflow-http/docker-compose.yaml") +public class WorkflowHttpTaskE2ETest { + + + private static final String project = "test-workflow-1"; + + private static final String workflow = "test-workflow-1"; + + 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 tenant = System.getProperty("user.name"); + + private static final String mockServerUrl = "http://mockServer:1080/test"; + + private static RemoteWebDriver browser; + + @BeforeAll + public static void setup() { + UserPage userPage = new LoginPage(browser) + .login("admin", "dolphinscheduler123") + .goToNav(SecurityPage.class) + .goToTab(TenantPage.class) + .create(tenant) + .goToNav(SecurityPage.class) + .goToTab(UserPage.class); + + new WebDriverWait(userPage.driver(), Duration.ofSeconds(20)).until(ExpectedConditions.visibilityOfElementLocated( + new By.ByClassName("name"))); + + userPage.update(user, user, email, phone, tenant) + .goToNav(ProjectPage.class) + .create(project) + ; + } + + @AfterAll + public static void cleanup() { + new NavBarPage(browser) + .goToNav(ProjectPage.class) + .goTo(project) + .goToTab(WorkflowDefinitionTab.class) + .delete(workflow); + + new NavBarPage(browser) + .goToNav(ProjectPage.class) + .delete(project); + + browser.navigate().refresh(); + + new NavBarPage(browser) + .goToNav(SecurityPage.class) + .goToTab(TenantPage.class) + .delete(tenant); + } + + @Test + @Order(1) + void testCreateWorkflow() { + WorkflowDefinitionTab workflowDefinitionPage = + new ProjectPage(browser) + .goTo(project) + .goToTab(WorkflowDefinitionTab.class); + + workflowDefinitionPage + .createWorkflow() + . addTask(WorkflowForm.TaskType.HTTP) + .url(mockServerUrl) + .name("test-1") + .addParam("today", "${system.datetime}") + .submit() + + .submit() + .name(workflow) + .addGlobalParam("global_param", "hello world") + .submit() + ; + + Awaitility.await().untilAsserted(() -> assertThat(workflowDefinitionPage.workflowList()) + .as("Workflow list should contain newly-created workflow") + .anyMatch( + it -> it.getText().contains(workflow) + )); + workflowDefinitionPage.publish(workflow); + } + + + @Test + @Order(30) + void testRunWorkflow() { + final ProjectDetailPage projectPage = + new ProjectPage(browser) + .goToNav(ProjectPage.class) + .goTo(project); + + projectPage + .goToTab(WorkflowInstanceTab.class) + .deleteAll(); + projectPage + .goToTab(WorkflowDefinitionTab.class) + .run(workflow) + .submit(); + + Awaitility.await().untilAsserted(() -> { + browser.navigate().refresh(); + + final WorkflowInstanceTab.Row row = projectPage + .goToTab(WorkflowInstanceTab.class) + .instances() + .iterator() + .next(); + + assertThat(row.isSuccess()).isTrue(); + assertThat(row.executionTime()).isEqualTo(1); + }); + } +} diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/common/HttpInput.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/common/HttpInput.java new file mode 100644 index 0000000000..ce3f07c819 --- /dev/null +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/common/HttpInput.java @@ -0,0 +1,58 @@ +/* + * 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.pages.common; + +import lombok.Getter; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +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; + +@Getter +public class HttpInput { + @FindBys({ + @FindBy(className = "input-url-name"), + @FindBy(tagName = "input") + }) + private WebElement urlInput; + + private WebDriver driver; + + + + public HttpInput(WebDriver driver) { + PageFactory.initElements(driver, this); + this.driver = driver; + } + + public HttpInput content(String content) { + new WebDriverWait(this.driver, Duration.ofSeconds(20)).until(ExpectedConditions.elementToBeClickable(urlInput)); + urlInput().sendKeys(content); + return this; + } + +} diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/WorkflowForm.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/WorkflowForm.java index 772cb69dea..c04df11233 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/WorkflowForm.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/WorkflowForm.java @@ -19,6 +19,7 @@ */ package org.apache.dolphinscheduler.e2e.pages.project.workflow; +import org.apache.dolphinscheduler.e2e.pages.project.workflow.task.HttpTaskForm; import org.apache.dolphinscheduler.e2e.pages.project.workflow.task.ShellTaskForm; import org.apache.dolphinscheduler.e2e.pages.project.workflow.task.SubWorkflowTaskForm; @@ -82,6 +83,8 @@ public final class WorkflowForm { return (T) new SubWorkflowTaskForm(this); case SWITCH: return (T) new SwitchTaskForm(this); + case HTTP: + return (T) new HttpTaskForm(this); } throw new UnsupportedOperationException("Unknown task type"); } @@ -117,5 +120,6 @@ public final class WorkflowForm { SHELL, SUB_PROCESS, SWITCH, + HTTP, } } diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/task/HttpTaskForm.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/task/HttpTaskForm.java new file mode 100644 index 0000000000..5869c6de9c --- /dev/null +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/task/HttpTaskForm.java @@ -0,0 +1,43 @@ +/* + * 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.pages.project.workflow.task; + +import org.apache.dolphinscheduler.e2e.pages.common.HttpInput; +import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowForm; +import org.openqa.selenium.WebDriver; + +public class HttpTaskForm extends TaskNodeForm{ + private WebDriver driver; + + private HttpInput httpInput; + + + public HttpTaskForm(WorkflowForm parent) { + super(parent); + this.httpInput = new HttpInput(parent.driver()); + this.driver = parent.driver(); + } + + public HttpTaskForm url(String script) { + httpInput.content(script); + return this; + } +} diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/resources/docker/workflow-http/docker-compose.yaml b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/resources/docker/workflow-http/docker-compose.yaml new file mode 100644 index 0000000000..2591e3d74a --- /dev/null +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/resources/docker/workflow-http/docker-compose.yaml @@ -0,0 +1,54 @@ +# +# 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. +# + +version: "3.8" + +services: + dolphinscheduler: + image: apache/dolphinscheduler-standalone-server:ci + environment: + MASTER_MAX_CPU_LOAD_AVG: 400 + MASTER_RESERVED_MEMORY: 0.01 + WORKER_TENANT_AUTO_CREATE: 'true' + ports: + - "12345:12345" + networks: + - e2e + healthcheck: + test: [ "CMD", "curl", "http://localhost:12345/actuator/health" ] + interval: 5s + timeout: 5s + retries: 120 + mockServer: + image: mockserver/mockserver:5.14.0 + environment: + MOCKSERVER_INITIALIZATION_JSON_PATH: /config/mockserver-config.json + ports: + - "1080:1080" + networks: + - e2e + volumes: + - type: bind + source: ./ + target: /config + healthcheck: + test: [ "CMD", "curl", "http://localhost:1080/" ] + interval: 5s + timeout: 5s + retries: 120 +networks: + e2e: diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/resources/docker/workflow-http/mockserver-config.json b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/resources/docker/workflow-http/mockserver-config.json new file mode 100644 index 0000000000..589dc86bae --- /dev/null +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/resources/docker/workflow-http/mockserver-config.json @@ -0,0 +1,22 @@ + +[{ + "httpRequest": { + "path": "/test", + "method": "GET" + }, + "httpResponse": { + "body": [ + { + "name": "lzl", + "age": 18 + }, + { + "name": "pizz2", + "age": 19 + } + ], + "headers": { + "Content-Type": "application/json" + } + } +}] diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-http.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-http.ts index 9e3a9af921..8fd7c00cb5 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-http.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-http.ts @@ -43,6 +43,7 @@ export function useHttp(model: { [field: string]: any }): IJsonItem[] { return [ { type: 'input', + class: 'input-url-name', field: 'url', name: t('project.node.http_url'), props: {