[Fix-16224] Add Shell using file E2E case (#16220)
* Add Shell E2E case * Add shell using resource file e2e case * Upgrade checkout from v2 to v4 * Change interval to 500ms * Upgrade actions/upload-artifact --------- Co-authored-by: xiangzihao <460888207@qq.com>
This commit is contained in:
parent
02bef74296
commit
46eff34e69
|
|
@ -35,7 +35,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
|
|
@ -49,7 +49,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Sanity Check
|
- name: Sanity Check
|
||||||
|
|
@ -73,7 +73,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
docker save apache/dolphinscheduler-standalone-server:ci -o /tmp/standalone-image.tar \
|
docker save apache/dolphinscheduler-standalone-server:ci -o /tmp/standalone-image.tar \
|
||||||
&& du -sh /tmp/standalone-image.tar
|
&& du -sh /tmp/standalone-image.tar
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
name: Upload Docker Images
|
name: Upload Docker Images
|
||||||
with:
|
with:
|
||||||
name: standalone-image
|
name: standalone-image
|
||||||
|
|
@ -104,7 +104,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
RECORDING_PATH: /tmp/recording-${{ matrix.case.name }}
|
RECORDING_PATH: /tmp/recording-${{ matrix.case.name }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Cache local Maven repository
|
- name: Cache local Maven repository
|
||||||
|
|
@ -113,7 +113,7 @@ jobs:
|
||||||
path: ~/.m2/repository
|
path: ~/.m2/repository
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-api-test
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-api-test
|
||||||
restore-keys: ${{ runner.os }}-maven-
|
restore-keys: ${{ runner.os }}-maven-
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v4
|
||||||
name: Download Docker Images
|
name: Download Docker Images
|
||||||
with:
|
with:
|
||||||
name: standalone-image
|
name: standalone-image
|
||||||
|
|
@ -127,7 +127,7 @@ jobs:
|
||||||
-DfailIfNoTests=false \
|
-DfailIfNoTests=false \
|
||||||
-Dspotless.skip=false \
|
-Dspotless.skip=false \
|
||||||
-Dtest=${{ matrix.case.class }} test
|
-Dtest=${{ matrix.case.class }} test
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
name: Upload Recording
|
name: Upload Recording
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ jobs:
|
||||||
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
||||||
db-schema: ${{ steps.filter.outputs.db-schema }}
|
db-schema: ${{ steps.filter.outputs.db-schema }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
|
|
@ -63,7 +63,7 @@ jobs:
|
||||||
java: [ '8', '11' ]
|
java: [ '8', '11' ]
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Set up JDK ${{ matrix.java }}
|
- name: Set up JDK ${{ matrix.java }}
|
||||||
|
|
@ -91,7 +91,7 @@ jobs:
|
||||||
-Dmaven.wagon.httpconnectionManager.ttlSeconds=120
|
-Dmaven.wagon.httpconnectionManager.ttlSeconds=120
|
||||||
- name: Check dependency license
|
- name: Check dependency license
|
||||||
run: tools/dependencies/check-LICENSE.sh
|
run: tools/dependencies/check-LICENSE.sh
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ matrix.java == '8' }}
|
if: ${{ matrix.java == '8' }}
|
||||||
name: Upload Binary Package
|
name: Upload Binary Package
|
||||||
with:
|
with:
|
||||||
|
|
@ -115,10 +115,10 @@ jobs:
|
||||||
- name: cluster-test-postgresql-with-postgresql-registry
|
- name: cluster-test-postgresql-with-postgresql-registry
|
||||||
script: .github/workflows/cluster-test/postgresql_with_postgresql_registry/start-job.sh
|
script: .github/workflows/cluster-test/postgresql_with_postgresql_registry/start-job.sh
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v4
|
||||||
name: Download Binary Package
|
name: Download Binary Package
|
||||||
with:
|
with:
|
||||||
# Only run cluster test on jdk8
|
# Only run cluster test on jdk8
|
||||||
|
|
@ -165,7 +165,7 @@ jobs:
|
||||||
mkdir -p dolphinscheduler/dev dolphinscheduler/${{ matrix.version }}
|
mkdir -p dolphinscheduler/dev dolphinscheduler/${{ matrix.version }}
|
||||||
curl -sSf https://atlasgo.sh | sh
|
curl -sSf https://atlasgo.sh | sh
|
||||||
- name: Download Tarball
|
- name: Download Tarball
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: binary-package-8
|
name: binary-package-8
|
||||||
path: dolphinscheduler/dev
|
path: dolphinscheduler/dev
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ jobs:
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Style Check
|
- name: Style Check
|
||||||
run: ./mvnw spotless:check
|
run: ./mvnw spotless:check
|
||||||
img-check:
|
img-check:
|
||||||
|
|
@ -40,7 +40,7 @@ jobs:
|
||||||
run:
|
run:
|
||||||
working-directory: docs
|
working-directory: docs
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Set up Python 3.9
|
- name: Set up Python 3.9
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
|
|
@ -54,7 +54,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- run: sudo npm install -g markdown-link-check@3.11.2
|
- run: sudo npm install -g markdown-link-check@3.11.2
|
||||||
- run: sudo apt install plocate -y
|
- run: sudo apt install plocate -y
|
||||||
# NOTE: Change command from `find . -name "*.md"` to `find . -not -path "*/node_modules/*" -not -path "*/.tox/*" -name "*.md"`
|
# NOTE: Change command from `find . -name "*.md"` to `find . -not -path "*/node_modules/*" -not -path "*/.tox/*" -name "*.md"`
|
||||||
|
|
@ -70,7 +70,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
helm-doc: ${{ steps.filter.outputs.helm-doc }}
|
helm-doc: ${{ steps.filter.outputs.helm-doc }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
|
|
@ -84,7 +84,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Generating helm-doc
|
- name: Generating helm-doc
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
|
|
@ -49,7 +49,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Build Image
|
- name: Build Image
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
|
|
@ -49,7 +49,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Sanity Check
|
- name: Sanity Check
|
||||||
|
|
@ -74,7 +74,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
docker save apache/dolphinscheduler-standalone-server:ci -o /tmp/standalone-image.tar \
|
docker save apache/dolphinscheduler-standalone-server:ci -o /tmp/standalone-image.tar \
|
||||||
&& du -sh /tmp/standalone-image.tar
|
&& du -sh /tmp/standalone-image.tar
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
name: Upload Docker Images
|
name: Upload Docker Images
|
||||||
with:
|
with:
|
||||||
name: standalone-image
|
name: standalone-image
|
||||||
|
|
@ -120,10 +120,12 @@ jobs:
|
||||||
class: org.apache.dolphinscheduler.e2e.cases.ClickhouseDataSourceE2ETest
|
class: org.apache.dolphinscheduler.e2e.cases.ClickhouseDataSourceE2ETest
|
||||||
- name: PostgresDataSource
|
- name: PostgresDataSource
|
||||||
class: org.apache.dolphinscheduler.e2e.cases.PostgresDataSourceE2ETest
|
class: org.apache.dolphinscheduler.e2e.cases.PostgresDataSourceE2ETest
|
||||||
|
- name: ShellTaskE2ETest
|
||||||
|
class: org.apache.dolphinscheduler.e2e.cases.tasks.ShellTaskE2ETest
|
||||||
env:
|
env:
|
||||||
RECORDING_PATH: /tmp/recording-${{ matrix.case.name }}
|
RECORDING_PATH: /tmp/recording-${{ matrix.case.name }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Cache local Maven repository
|
- name: Cache local Maven repository
|
||||||
|
|
@ -132,7 +134,7 @@ jobs:
|
||||||
path: ~/.m2/repository
|
path: ~/.m2/repository
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-e2e
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-e2e
|
||||||
restore-keys: ${{ runner.os }}-maven-
|
restore-keys: ${{ runner.os }}-maven-
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v4
|
||||||
name: Download Docker Images
|
name: Download Docker Images
|
||||||
with:
|
with:
|
||||||
name: standalone-image
|
name: standalone-image
|
||||||
|
|
@ -145,7 +147,7 @@ jobs:
|
||||||
./mvnw -B -f dolphinscheduler-e2e/pom.xml -am \
|
./mvnw -B -f dolphinscheduler-e2e/pom.xml -am \
|
||||||
-DfailIfNoTests=false \
|
-DfailIfNoTests=false \
|
||||||
-Dtest=${{ matrix.case.class }} test
|
-Dtest=${{ matrix.case.class }} test
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
name: Upload Recording
|
name: Upload Recording
|
||||||
with:
|
with:
|
||||||
|
|
@ -167,7 +169,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
RECORDING_PATH: /tmp/recording-${{ matrix.case.name }}
|
RECORDING_PATH: /tmp/recording-${{ matrix.case.name }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Cache local Maven repository
|
- name: Cache local Maven repository
|
||||||
|
|
@ -176,7 +178,7 @@ jobs:
|
||||||
path: ~/.m2/repository
|
path: ~/.m2/repository
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-e2e
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-e2e
|
||||||
restore-keys: ${{ runner.os }}-maven-
|
restore-keys: ${{ runner.os }}-maven-
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v4
|
||||||
name: Download Docker Images
|
name: Download Docker Images
|
||||||
with:
|
with:
|
||||||
name: standalone-image
|
name: standalone-image
|
||||||
|
|
@ -189,7 +191,7 @@ jobs:
|
||||||
./mvnw -B -f dolphinscheduler-e2e/pom.xml -am \
|
./mvnw -B -f dolphinscheduler-e2e/pom.xml -am \
|
||||||
-DfailIfNoTests=false \
|
-DfailIfNoTests=false \
|
||||||
-Dtest=${{ matrix.case.class }} test
|
-Dtest=${{ matrix.case.class }} test
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
name: Upload Recording
|
name: Upload Recording
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
|
|
@ -58,7 +58,7 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-latest, macos-latest ]
|
os: [ ubuntu-latest, macos-latest ]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- if: matrix.os == 'ubuntu-latest'
|
- if: matrix.os == 'ubuntu-latest'
|
||||||
|
|
@ -82,7 +82,7 @@ jobs:
|
||||||
needs: [ build, paths-filter ]
|
needs: [ build, paths-filter ]
|
||||||
if: always()
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Status
|
- name: Status
|
||||||
run: |
|
run: |
|
||||||
if [[ ${{ needs.paths-filter.outputs.not-ignore }} == 'false' && ${{ github.event_name }} == 'pull_request' ]]; then
|
if [[ ${{ needs.paths-filter.outputs.not-ignore }} == 'false' && ${{ github.event_name }} == 'pull_request' ]]; then
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout ${{ github.ref }}"
|
- name: "Checkout ${{ github.ref }}"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Set up JDK 8
|
- name: Set up JDK 8
|
||||||
|
|
@ -42,7 +42,7 @@ jobs:
|
||||||
- name: Run OWASP Dependency Check
|
- name: Run OWASP Dependency Check
|
||||||
run: ./mvnw -B clean install verify dependency-check:check -DskipDepCheck=false -Dmaven.test.skip=true -Dspotless.skip=true
|
run: ./mvnw -B clean install verify dependency-check:check -DskipDepCheck=false -Dmaven.test.skip=true -Dspotless.skip=true
|
||||||
- name: Upload report
|
- name: Upload report
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
if: ${{ cancelled() || failure() }}
|
if: ${{ cancelled() || failure() }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ jobs:
|
||||||
packages: write
|
packages: write
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Cache local Maven repository
|
- name: Cache local Maven repository
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ jobs:
|
||||||
packages: write
|
packages: write
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Set environment variables
|
- name: Set environment variables
|
||||||
run: |
|
run: |
|
||||||
if [[ ${{ github.event_name }} == "release" ]]; then
|
if [[ ${{ github.event_name }} == "release" ]]; then
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
not-ignore: ${{ steps.filter.outputs.not-ignore }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
|
|
@ -57,7 +57,7 @@ jobs:
|
||||||
java: ['8', '11']
|
java: ['8', '11']
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Sanity Check
|
- name: Sanity Check
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,16 @@ public class ResourcesController extends BaseController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ResourcesService resourceService;
|
private ResourcesService resourceService;
|
||||||
|
|
||||||
|
@Operation(summary = "queryResourceList", description = "QUERY_RESOURCE_LIST_NOTES")
|
||||||
|
@Parameter(name = "type", description = "RESOURCE_TYPE", required = true, schema = @Schema(implementation = ResourceType.class))
|
||||||
|
@GetMapping(value = "/list")
|
||||||
|
@ResponseStatus(HttpStatus.OK)
|
||||||
|
@ApiException(QUERY_RESOURCES_LIST_ERROR)
|
||||||
|
public Result<List<ResourceComponent>> queryResourceList(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||||
|
@RequestParam(value = "type") ResourceType type) {
|
||||||
|
return Result.success(resourceService.queryResourceFiles(loginUser, type));
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "createDirectory", description = "CREATE_RESOURCE_NOTES")
|
@Operation(summary = "createDirectory", description = "CREATE_RESOURCE_NOTES")
|
||||||
@Parameters({
|
@Parameters({
|
||||||
@Parameter(name = "type", description = "RESOURCE_TYPE", required = true, schema = @Schema(implementation = ResourceType.class)),
|
@Parameter(name = "type", description = "RESOURCE_TYPE", required = true, schema = @Schema(implementation = ResourceType.class)),
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package org.apache.dolphinscheduler.e2e.cases;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
||||||
|
|
||||||
|
|
@ -82,7 +83,7 @@ public class ClickhouseDataSourceE2ETest {
|
||||||
|
|
||||||
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, pgPassword, database, jdbcParams);
|
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, pgPassword, database, jdbcParams);
|
||||||
|
|
||||||
new WebDriverWait(page.driver(), Duration.ofSeconds(20)).until(ExpectedConditions.invisibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(page.driver()).until(ExpectedConditions.invisibilityOfElementLocated(
|
||||||
new By.ByClassName("dialog-create-data-source")));
|
new By.ByClassName("dialog-create-data-source")));
|
||||||
|
|
||||||
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.Constants;
|
import org.apache.dolphinscheduler.e2e.core.Constants;
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.resource.FileManagePage;
|
import org.apache.dolphinscheduler.e2e.pages.resource.FileManagePage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.resource.ResourcePage;
|
import org.apache.dolphinscheduler.e2e.pages.resource.ResourcePage;
|
||||||
|
|
@ -98,7 +99,7 @@ public class FileManageE2ETest {
|
||||||
UserPage userPage = tenantPage.goToNav(SecurityPage.class)
|
UserPage userPage = tenantPage.goToNav(SecurityPage.class)
|
||||||
.goToTab(UserPage.class);
|
.goToTab(UserPage.class);
|
||||||
|
|
||||||
new WebDriverWait(userPage.driver(), Duration.ofSeconds(20)).until(ExpectedConditions.visibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(userPage.driver()).until(ExpectedConditions.visibilityOfElementLocated(
|
||||||
new By.ByClassName("name")));
|
new By.ByClassName("name")));
|
||||||
|
|
||||||
userPage.update(user, user, email, phone, tenant)
|
userPage.update(user, user, email, phone, tenant)
|
||||||
|
|
@ -285,7 +286,7 @@ public class FileManageE2ETest {
|
||||||
|
|
||||||
page.uploadFile(testUnder1GBFilePath.toFile().getAbsolutePath());
|
page.uploadFile(testUnder1GBFilePath.toFile().getAbsolutePath());
|
||||||
|
|
||||||
new WebDriverWait(browser, Duration.ofSeconds(20)).until(ExpectedConditions.invisibilityOfElementLocated(By.id("fileUpdateDialog")));
|
WebDriverWaitFactory.createWebDriverWait(browser).until(ExpectedConditions.invisibilityOfElementLocated(By.id("fileUpdateDialog")));
|
||||||
|
|
||||||
Awaitility.await().untilAsserted(() -> {
|
Awaitility.await().untilAsserted(() -> {
|
||||||
assertThat(page.fileList())
|
assertThat(page.fileList())
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package org.apache.dolphinscheduler.e2e.cases;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
||||||
|
|
||||||
|
|
@ -82,7 +83,7 @@ public class HiveDataSourceE2ETest {
|
||||||
|
|
||||||
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, hivePassword, database, jdbcParams);
|
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, hivePassword, database, jdbcParams);
|
||||||
|
|
||||||
new WebDriverWait(page.driver(), Duration.ofSeconds(20)).until(ExpectedConditions.invisibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(page.driver()).until(ExpectedConditions.invisibilityOfElementLocated(
|
||||||
new By.ByClassName("dialog-create-data-source")));
|
new By.ByClassName("dialog-create-data-source")));
|
||||||
|
|
||||||
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package org.apache.dolphinscheduler.e2e.cases;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
||||||
|
|
||||||
|
|
@ -82,7 +83,7 @@ public class MysqlDataSourceE2ETest {
|
||||||
|
|
||||||
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, mysqlPassword, database, jdbcParams);
|
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, mysqlPassword, database, jdbcParams);
|
||||||
|
|
||||||
new WebDriverWait(page.driver(), Duration.ofSeconds(20)).until(ExpectedConditions.invisibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(page.driver()).until(ExpectedConditions.invisibilityOfElementLocated(
|
||||||
new By.ByClassName("dialog-create-data-source")));
|
new By.ByClassName("dialog-create-data-source")));
|
||||||
|
|
||||||
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package org.apache.dolphinscheduler.e2e.cases;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
||||||
|
|
||||||
|
|
@ -82,7 +83,7 @@ public class PostgresDataSourceE2ETest {
|
||||||
|
|
||||||
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, pgPassword, database, jdbcParams);
|
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, pgPassword, database, jdbcParams);
|
||||||
|
|
||||||
new WebDriverWait(page.driver(), Duration.ofSeconds(20)).until(ExpectedConditions.invisibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(page.driver()).until(ExpectedConditions.invisibilityOfElementLocated(
|
||||||
new By.ByClassName("dialog-create-data-source")));
|
new By.ByClassName("dialog-create-data-source")));
|
||||||
|
|
||||||
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package org.apache.dolphinscheduler.e2e.cases;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
||||||
|
|
||||||
|
|
@ -82,7 +83,7 @@ public class SqlServerDataSourceE2ETest {
|
||||||
|
|
||||||
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, pgPassword, database, jdbcParams);
|
page.createDataSource(dataSourceType, dataSourceName, dataSourceDescription, ip, port, userName, pgPassword, database, jdbcParams);
|
||||||
|
|
||||||
new WebDriverWait(page.driver(), Duration.ofSeconds(20)).until(ExpectedConditions.invisibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(page.driver()).until(ExpectedConditions.invisibilityOfElementLocated(
|
||||||
new By.ByClassName("dialog-create-data-source")));
|
new By.ByClassName("dialog-create-data-source")));
|
||||||
|
|
||||||
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
Awaitility.await().untilAsserted(() -> assertThat(page.dataSourceItemsList())
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package org.apache.dolphinscheduler.e2e.cases;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage;
|
import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage;
|
||||||
|
|
@ -119,7 +120,7 @@ class UserE2ETest {
|
||||||
void testEditUser() {
|
void testEditUser() {
|
||||||
UserPage page = new UserPage(browser);
|
UserPage page = new UserPage(browser);
|
||||||
|
|
||||||
new WebDriverWait(browser, Duration.ofSeconds(20)).until(ExpectedConditions.visibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(browser).until(ExpectedConditions.visibilityOfElementLocated(
|
||||||
new By.ByClassName("name")));
|
new By.ByClassName("name")));
|
||||||
|
|
||||||
browser.navigate().refresh();
|
browser.navigate().refresh();
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package org.apache.dolphinscheduler.e2e.cases;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage;
|
import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.security.WorkerGroupPage;
|
import org.apache.dolphinscheduler.e2e.pages.security.WorkerGroupPage;
|
||||||
|
|
@ -59,7 +60,7 @@ class WorkerGroupE2ETest {
|
||||||
void testCreateWorkerGroup() {
|
void testCreateWorkerGroup() {
|
||||||
final WorkerGroupPage page = new WorkerGroupPage(browser);
|
final WorkerGroupPage page = new WorkerGroupPage(browser);
|
||||||
|
|
||||||
new WebDriverWait(page.driver(), Duration.ofSeconds(20))
|
WebDriverWaitFactory.createWebDriverWait(page.driver())
|
||||||
.until(ExpectedConditions.urlContains("/security/worker-group-manage"));
|
.until(ExpectedConditions.urlContains("/security/worker-group-manage"));
|
||||||
|
|
||||||
page.create(workerGroupName);
|
page.create(workerGroupName);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
package org.apache.dolphinscheduler.e2e.cases;
|
package org.apache.dolphinscheduler.e2e.cases;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.ProjectDetailPage;
|
import org.apache.dolphinscheduler.e2e.pages.project.ProjectDetailPage;
|
||||||
|
|
@ -76,7 +77,7 @@ class WorkflowE2ETest {
|
||||||
.goToNav(SecurityPage.class)
|
.goToNav(SecurityPage.class)
|
||||||
.goToTab(UserPage.class);
|
.goToTab(UserPage.class);
|
||||||
|
|
||||||
new WebDriverWait(userPage.driver(), Duration.ofSeconds(20)).until(ExpectedConditions.visibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(userPage.driver()).until(ExpectedConditions.visibilityOfElementLocated(
|
||||||
new By.ByClassName("name")));
|
new By.ByClassName("name")));
|
||||||
|
|
||||||
userPage.update(user, user, email, phone, tenant)
|
userPage.update(user, user, email, phone, tenant)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
package org.apache.dolphinscheduler.e2e.cases;
|
package org.apache.dolphinscheduler.e2e.cases;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.ProjectDetailPage;
|
import org.apache.dolphinscheduler.e2e.pages.project.ProjectDetailPage;
|
||||||
|
|
@ -76,7 +77,7 @@ public class WorkflowHttpTaskE2ETest {
|
||||||
.goToNav(SecurityPage.class)
|
.goToNav(SecurityPage.class)
|
||||||
.goToTab(UserPage.class);
|
.goToTab(UserPage.class);
|
||||||
|
|
||||||
new WebDriverWait(userPage.driver(), Duration.ofSeconds(20)).until(ExpectedConditions.visibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(userPage.driver()).until(ExpectedConditions.visibilityOfElementLocated(
|
||||||
new By.ByClassName("name")));
|
new By.ByClassName("name")));
|
||||||
|
|
||||||
userPage.update(user, user, email, phone, tenant)
|
userPage.update(user, user, email, phone, tenant)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
package org.apache.dolphinscheduler.e2e.cases;
|
package org.apache.dolphinscheduler.e2e.cases;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.ProjectDetailPage;
|
import org.apache.dolphinscheduler.e2e.pages.project.ProjectDetailPage;
|
||||||
|
|
@ -92,7 +93,7 @@ public class WorkflowJavaTaskE2ETest {
|
||||||
.goToNav(SecurityPage.class)
|
.goToNav(SecurityPage.class)
|
||||||
.goToTab(UserPage.class);
|
.goToTab(UserPage.class);
|
||||||
|
|
||||||
new WebDriverWait(userPage.driver(), Duration.ofSeconds(20))
|
WebDriverWaitFactory.createWebDriverWait(userPage.driver())
|
||||||
.until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName("name")));
|
.until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName("name")));
|
||||||
|
|
||||||
userPage.update(user, user, email, phone, tenant)
|
userPage.update(user, user, email, phone, tenant)
|
||||||
|
|
|
||||||
|
|
@ -178,8 +178,8 @@ class WorkflowSwitchE2ETest {
|
||||||
|
|
||||||
Awaitility.await().untilAsserted(() -> {
|
Awaitility.await().untilAsserted(() -> {
|
||||||
assertThat(taskInstances.size()).isEqualTo(3);
|
assertThat(taskInstances.size()).isEqualTo(3);
|
||||||
assertThat(taskInstances.stream().filter(row -> row.name().contains(ifBranchName)).count()).isEqualTo(1);
|
assertThat(taskInstances.stream().filter(row -> row.taskInstanceName().contains(ifBranchName)).count()).isEqualTo(1);
|
||||||
assertThat(taskInstances.stream().noneMatch(row -> row.name().contains(elseBranchName))).isTrue();
|
assertThat(taskInstances.stream().noneMatch(row -> row.taskInstanceName().contains(elseBranchName))).isTrue();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,260 @@
|
||||||
|
/*
|
||||||
|
* 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.tasks;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.cases.workflow.BaseWorkflowE2ETest;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler;
|
||||||
|
import org.apache.dolphinscheduler.e2e.pages.project.ProjectPage;
|
||||||
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.TaskInstanceTab;
|
||||||
|
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.ShellTaskForm;
|
||||||
|
import org.apache.dolphinscheduler.e2e.pages.resource.FileManagePage;
|
||||||
|
import org.apache.dolphinscheduler.e2e.pages.resource.ResourcePage;
|
||||||
|
import org.junit.FixMethodOrder;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.runners.MethodSorters;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import org.testcontainers.shaded.org.awaitility.Awaitility;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.testcontainers.shaded.org.awaitility.Awaitility.await;
|
||||||
|
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
@DolphinScheduler(composeFiles = "docker/basic/docker-compose.yaml")
|
||||||
|
public class ShellTaskE2ETest extends BaseWorkflowE2ETest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRunShellTasks_SuccessCase() {
|
||||||
|
WorkflowDefinitionTab workflowDefinitionPage =
|
||||||
|
new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName)
|
||||||
|
.goToTab(WorkflowDefinitionTab.class);
|
||||||
|
|
||||||
|
// todo: use yaml to define the workflow
|
||||||
|
String workflowName = "SuccessCase";
|
||||||
|
String taskName = "ShellSuccess";
|
||||||
|
workflowDefinitionPage
|
||||||
|
.createWorkflow()
|
||||||
|
.<ShellTaskForm>addTask(WorkflowForm.TaskType.SHELL)
|
||||||
|
.script("echo hello world\n")
|
||||||
|
.name(taskName)
|
||||||
|
.submit()
|
||||||
|
|
||||||
|
.submit()
|
||||||
|
.name(workflowName)
|
||||||
|
.submit();
|
||||||
|
|
||||||
|
untilWorkflowDefinitionExist(workflowName);
|
||||||
|
|
||||||
|
workflowDefinitionPage.publish(workflowName);
|
||||||
|
|
||||||
|
runWorkflow(workflowName);
|
||||||
|
untilWorkflowInstanceExist(workflowName);
|
||||||
|
WorkflowInstanceTab.Row workflowInstance = untilWorkflowInstanceSuccess(workflowName);
|
||||||
|
assertThat(workflowInstance.executionTime()).isEqualTo(1);
|
||||||
|
|
||||||
|
TaskInstanceTab.Row taskInstance = untilTaskInstanceSuccess(workflowName, taskName);
|
||||||
|
assertThat(taskInstance.retryTimes()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRunShellTasks_WorkflowParamsCase() {
|
||||||
|
WorkflowDefinitionTab workflowDefinitionPage =
|
||||||
|
new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName)
|
||||||
|
.goToTab(WorkflowDefinitionTab.class);
|
||||||
|
|
||||||
|
// todo: use yaml to define the workflow
|
||||||
|
String workflowName = "WorkflowParamsCase";
|
||||||
|
String taskName = "ShellSuccess";
|
||||||
|
workflowDefinitionPage
|
||||||
|
.createWorkflow()
|
||||||
|
.<ShellTaskForm>addTask(WorkflowForm.TaskType.SHELL)
|
||||||
|
.script("[ \"${name}\" = \"tom\" ] && echo \"success\" || { echo \"failed\"; exit 1; }")
|
||||||
|
.name(taskName)
|
||||||
|
.submit()
|
||||||
|
|
||||||
|
.submit()
|
||||||
|
.name(workflowName)
|
||||||
|
.addGlobalParam("name", "tom")
|
||||||
|
.submit();
|
||||||
|
|
||||||
|
untilWorkflowDefinitionExist(workflowName);
|
||||||
|
|
||||||
|
workflowDefinitionPage.publish(workflowName);
|
||||||
|
|
||||||
|
runWorkflow(workflowName);
|
||||||
|
untilWorkflowInstanceExist(workflowName);
|
||||||
|
WorkflowInstanceTab.Row workflowInstance = untilWorkflowInstanceSuccess(workflowName);
|
||||||
|
assertThat(workflowInstance.executionTime()).isEqualTo(1);
|
||||||
|
|
||||||
|
TaskInstanceTab.Row taskInstance = untilTaskInstanceSuccess(workflowName, taskName);
|
||||||
|
assertThat(taskInstance.retryTimes()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRunShellTasks_LocalParamsCase() {
|
||||||
|
WorkflowDefinitionTab workflowDefinitionPage =
|
||||||
|
new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName)
|
||||||
|
.goToTab(WorkflowDefinitionTab.class);
|
||||||
|
|
||||||
|
String workflowName = "LocalParamsCase";
|
||||||
|
String taskName = "ShellSuccess";
|
||||||
|
workflowDefinitionPage
|
||||||
|
.createWorkflow()
|
||||||
|
.<ShellTaskForm>addTask(WorkflowForm.TaskType.SHELL)
|
||||||
|
.script("[ \"${name}\" = \"tom\" ] && echo \"success\" || { echo \"failed\"; exit 1; }")
|
||||||
|
.name(taskName)
|
||||||
|
.addParam("name", "tom")
|
||||||
|
.submit()
|
||||||
|
|
||||||
|
.submit()
|
||||||
|
.name(workflowName)
|
||||||
|
.submit();
|
||||||
|
|
||||||
|
untilWorkflowDefinitionExist(workflowName);
|
||||||
|
|
||||||
|
workflowDefinitionPage.publish(workflowName);
|
||||||
|
|
||||||
|
runWorkflow(workflowName);
|
||||||
|
untilWorkflowInstanceExist(workflowName);
|
||||||
|
WorkflowInstanceTab.Row workflowInstance = untilWorkflowInstanceSuccess(workflowName);
|
||||||
|
assertThat(workflowInstance.executionTime()).isEqualTo(1);
|
||||||
|
|
||||||
|
TaskInstanceTab.Row taskInstance = untilTaskInstanceSuccess(workflowName, taskName);
|
||||||
|
assertThat(taskInstance.retryTimes()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRunShellTasks_GlobalParamsOverrideLocalParamsCase() {
|
||||||
|
WorkflowDefinitionTab workflowDefinitionPage =
|
||||||
|
new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName)
|
||||||
|
.goToTab(WorkflowDefinitionTab.class);
|
||||||
|
|
||||||
|
String workflowName = "LocalParamsOverrideWorkflowParamsCase";
|
||||||
|
String taskName = "ShellSuccess";
|
||||||
|
workflowDefinitionPage
|
||||||
|
.createWorkflow()
|
||||||
|
.<ShellTaskForm>addTask(WorkflowForm.TaskType.SHELL)
|
||||||
|
.script("[ \"${name}\" = \"jerry\" ] && echo \"success\" || { echo \"failed\"; exit 1; }")
|
||||||
|
.name(taskName)
|
||||||
|
.addParam("name", "tom")
|
||||||
|
.submit()
|
||||||
|
|
||||||
|
.submit()
|
||||||
|
.name(workflowName)
|
||||||
|
.addGlobalParam("name", "jerry")
|
||||||
|
.submit();
|
||||||
|
|
||||||
|
untilWorkflowDefinitionExist(workflowName);
|
||||||
|
|
||||||
|
workflowDefinitionPage.publish(workflowName);
|
||||||
|
|
||||||
|
runWorkflow(workflowName);
|
||||||
|
untilWorkflowInstanceExist(workflowName);
|
||||||
|
WorkflowInstanceTab.Row workflowInstance = untilWorkflowInstanceSuccess(workflowName);
|
||||||
|
assertThat(workflowInstance.executionTime()).isEqualTo(1);
|
||||||
|
|
||||||
|
TaskInstanceTab.Row taskInstance = untilTaskInstanceSuccess(workflowName, taskName);
|
||||||
|
assertThat(taskInstance.retryTimes()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRunShellTasks_UsingResourceFile() {
|
||||||
|
String testFileName = "echo";
|
||||||
|
new ResourcePage(browser)
|
||||||
|
.goToNav(ResourcePage.class)
|
||||||
|
.goToTab(FileManagePage.class)
|
||||||
|
.createFileUntilSuccess(testFileName, "echo 123");
|
||||||
|
|
||||||
|
final WorkflowDefinitionTab workflowDefinitionPage =
|
||||||
|
new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName)
|
||||||
|
.goToTab(WorkflowDefinitionTab.class);
|
||||||
|
|
||||||
|
String workflowName = "UsingResourceFile";
|
||||||
|
String taskName = "ShellSuccess";
|
||||||
|
workflowDefinitionPage
|
||||||
|
.createWorkflow()
|
||||||
|
.<ShellTaskForm>addTask(WorkflowForm.TaskType.SHELL)
|
||||||
|
.script("cat " + testFileName + ".sh")
|
||||||
|
.name(taskName)
|
||||||
|
.selectResource(testFileName)
|
||||||
|
.submit()
|
||||||
|
|
||||||
|
.submit()
|
||||||
|
.name(workflowName)
|
||||||
|
.submit();
|
||||||
|
|
||||||
|
untilWorkflowDefinitionExist(workflowName);
|
||||||
|
|
||||||
|
workflowDefinitionPage.publish(workflowName);
|
||||||
|
|
||||||
|
runWorkflow(workflowName);
|
||||||
|
untilWorkflowInstanceExist(workflowName);
|
||||||
|
WorkflowInstanceTab.Row workflowInstance = untilWorkflowInstanceSuccess(workflowName);
|
||||||
|
assertThat(workflowInstance.executionTime()).isEqualTo(1);
|
||||||
|
|
||||||
|
TaskInstanceTab.Row taskInstance = untilTaskInstanceSuccess(workflowName, taskName);
|
||||||
|
assertThat(taskInstance.retryTimes()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRunShellTasks_FailedCase() {
|
||||||
|
WorkflowDefinitionTab workflowDefinitionPage =
|
||||||
|
new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName)
|
||||||
|
.goToTab(WorkflowDefinitionTab.class);
|
||||||
|
|
||||||
|
String workflowName = "FailedCase";
|
||||||
|
String taskName = "ShellFailed";
|
||||||
|
workflowDefinitionPage
|
||||||
|
.createWorkflow()
|
||||||
|
.<ShellTaskForm>addTask(WorkflowForm.TaskType.SHELL)
|
||||||
|
.script("echo 'I am failed'\n exit1\n")
|
||||||
|
.name(taskName)
|
||||||
|
.submit()
|
||||||
|
|
||||||
|
.submit()
|
||||||
|
.name(workflowName)
|
||||||
|
.submit();
|
||||||
|
|
||||||
|
untilWorkflowDefinitionExist(workflowName);
|
||||||
|
|
||||||
|
workflowDefinitionPage.publish(workflowName);
|
||||||
|
|
||||||
|
runWorkflow(workflowName);
|
||||||
|
untilWorkflowInstanceExist(workflowName);
|
||||||
|
WorkflowInstanceTab.Row workflowInstance = untilWorkflowInstanceFailed(workflowName);
|
||||||
|
assertThat(workflowInstance.executionTime()).isEqualTo(1);
|
||||||
|
|
||||||
|
TaskInstanceTab.Row taskInstance = untilTaskInstanceFailed(workflowName, taskName);
|
||||||
|
assertThat(taskInstance.retryTimes()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* 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.workflow;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverHolder;
|
||||||
|
import org.apache.dolphinscheduler.e2e.models.tenant.DefaultTenant;
|
||||||
|
import org.apache.dolphinscheduler.e2e.models.users.AdminUser;
|
||||||
|
import org.apache.dolphinscheduler.e2e.models.users.IUser;
|
||||||
|
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.TaskInstanceTab;
|
||||||
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowDefinitionTab;
|
||||||
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowInstanceTab;
|
||||||
|
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.openqa.selenium.remote.RemoteWebDriver;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.testcontainers.shaded.org.awaitility.Awaitility.await;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public abstract class BaseWorkflowE2ETest {
|
||||||
|
|
||||||
|
protected static String projectName = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
protected static final AdminUser adminUser = new AdminUser();
|
||||||
|
|
||||||
|
protected static RemoteWebDriver browser;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void setup() {
|
||||||
|
browser = WebDriverHolder.getWebDriver();
|
||||||
|
|
||||||
|
TenantPage tenantPage = new LoginPage(browser)
|
||||||
|
.login(adminUser)
|
||||||
|
.goToNav(SecurityPage.class)
|
||||||
|
.goToTab(TenantPage.class);
|
||||||
|
|
||||||
|
if (tenantPage.tenants().stream().noneMatch(tenant -> tenant.tenantCode().equals(adminUser.getTenant()))) {
|
||||||
|
tenantPage
|
||||||
|
.create(adminUser.getTenant())
|
||||||
|
.goToNav(SecurityPage.class)
|
||||||
|
.goToTab(UserPage.class)
|
||||||
|
.update(adminUser);
|
||||||
|
}
|
||||||
|
tenantPage
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.createProjectUntilSuccess(projectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void untilWorkflowDefinitionExist(String workflowName) {
|
||||||
|
WorkflowDefinitionTab workflowDefinitionPage = new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName)
|
||||||
|
.goToTab(WorkflowDefinitionTab.class);
|
||||||
|
|
||||||
|
await().untilAsserted(() -> assertThat(workflowDefinitionPage.workflowList())
|
||||||
|
.as("Workflow list should contain newly-created workflow: %s", workflowName)
|
||||||
|
.anyMatch(
|
||||||
|
it -> it.getText().contains(workflowName)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runWorkflow(String workflowName) {
|
||||||
|
final ProjectDetailPage projectPage = new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName);
|
||||||
|
|
||||||
|
projectPage
|
||||||
|
.goToTab(WorkflowDefinitionTab.class)
|
||||||
|
.run(workflowName)
|
||||||
|
.submit();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WorkflowInstanceTab.Row untilWorkflowInstanceExist(String workflowName) {
|
||||||
|
final ProjectDetailPage projectPage = new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName);
|
||||||
|
|
||||||
|
return await()
|
||||||
|
.until(() -> {
|
||||||
|
browser.navigate().refresh();
|
||||||
|
return projectPage
|
||||||
|
.goToTab(WorkflowInstanceTab.class)
|
||||||
|
.instances()
|
||||||
|
.stream()
|
||||||
|
.filter(it -> it.workflowInstanceName().startsWith(workflowName))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}, Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WorkflowInstanceTab.Row untilWorkflowInstanceSuccess(String workflowName) {
|
||||||
|
final ProjectDetailPage projectPage = new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName);
|
||||||
|
return await()
|
||||||
|
.until(() -> {
|
||||||
|
browser.navigate().refresh();
|
||||||
|
return projectPage
|
||||||
|
.goToTab(WorkflowInstanceTab.class)
|
||||||
|
.instances()
|
||||||
|
.stream()
|
||||||
|
.filter(it -> it.workflowInstanceName().startsWith(workflowName))
|
||||||
|
.filter(WorkflowInstanceTab.Row::isSuccess)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}, Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WorkflowInstanceTab.Row untilWorkflowInstanceFailed(String workflowName) {
|
||||||
|
final ProjectDetailPage projectPage = new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName);
|
||||||
|
return await()
|
||||||
|
.until(() -> {
|
||||||
|
browser.navigate().refresh();
|
||||||
|
List<WorkflowInstanceTab.Row> workflowInstances = projectPage
|
||||||
|
.goToTab(WorkflowInstanceTab.class)
|
||||||
|
.instances()
|
||||||
|
.stream()
|
||||||
|
.filter(it -> it.workflowInstanceName().startsWith(workflowName))
|
||||||
|
.filter(WorkflowInstanceTab.Row::isFailed)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (workflowInstances.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (workflowInstances.size() > 1) {
|
||||||
|
throw new RuntimeException("More than one failed workflow instance found: " +
|
||||||
|
workflowInstances.stream()
|
||||||
|
.map(WorkflowInstanceTab.Row::workflowInstanceName).collect(Collectors.joining(", ")));
|
||||||
|
}
|
||||||
|
return workflowInstances.get(0);
|
||||||
|
}, Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TaskInstanceTab.Row untilTaskInstanceSuccess(String workflowName, String taskName) {
|
||||||
|
final ProjectDetailPage projectPage = new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName);
|
||||||
|
return await()
|
||||||
|
.until(() -> {
|
||||||
|
browser.navigate().refresh();
|
||||||
|
List<TaskInstanceTab.Row> taskInstances = projectPage
|
||||||
|
.goToTab(TaskInstanceTab.class)
|
||||||
|
.instances()
|
||||||
|
.stream()
|
||||||
|
.filter(it -> it.taskInstanceName().startsWith(taskName))
|
||||||
|
.filter(it -> it.workflowInstanceName().startsWith(workflowName))
|
||||||
|
.filter(TaskInstanceTab.Row::isSuccess)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (taskInstances.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (taskInstances.size() > 1) {
|
||||||
|
throw new RuntimeException("More than one failed task instance found: " +
|
||||||
|
taskInstances.stream()
|
||||||
|
.map(TaskInstanceTab.Row::taskInstanceName).collect(Collectors.joining(", ")));
|
||||||
|
}
|
||||||
|
return taskInstances.get(0);
|
||||||
|
}, Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TaskInstanceTab.Row untilTaskInstanceFailed(String workflowName, String taskName) {
|
||||||
|
final ProjectDetailPage projectPage = new ProjectPage(browser)
|
||||||
|
.goToNav(ProjectPage.class)
|
||||||
|
.goTo(projectName);
|
||||||
|
return await()
|
||||||
|
.until(() -> {
|
||||||
|
browser.navigate().refresh();
|
||||||
|
List<TaskInstanceTab.Row> taskInstances = projectPage
|
||||||
|
.goToTab(TaskInstanceTab.class)
|
||||||
|
.instances()
|
||||||
|
.stream()
|
||||||
|
.filter(it -> it.taskInstanceName().startsWith(taskName))
|
||||||
|
.filter(it -> it.workflowInstanceName().startsWith(workflowName))
|
||||||
|
.filter(TaskInstanceTab.Row::isFailed)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (taskInstances.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (taskInstances.size() > 1) {
|
||||||
|
throw new RuntimeException("More than one failed task instance found: " +
|
||||||
|
taskInstances.stream()
|
||||||
|
.map(TaskInstanceTab.Row::taskInstanceName).collect(Collectors.joining(", ")));
|
||||||
|
}
|
||||||
|
return taskInstances.get(0);
|
||||||
|
}, Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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.models.tenant;
|
||||||
|
|
||||||
|
public class BootstrapTenant implements ITenant {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTenantCode() {
|
||||||
|
return System.getProperty("user.name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "bootstrap tenant";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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.models.tenant;
|
||||||
|
|
||||||
|
public class DefaultTenant implements ITenant {
|
||||||
|
@Override
|
||||||
|
public String getTenantCode() {
|
||||||
|
return "default";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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.models.tenant;
|
||||||
|
|
||||||
|
public interface ITenant {
|
||||||
|
|
||||||
|
String getTenantCode();
|
||||||
|
|
||||||
|
String getDescription();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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.models.users;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.apache.dolphinscheduler.e2e.models.tenant.BootstrapTenant;
|
||||||
|
import org.apache.dolphinscheduler.e2e.models.tenant.ITenant;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AdminUser implements IUser {
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
private ITenant tenant;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUserName() {
|
||||||
|
return "admin";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return "dolphinscheduler123";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEmail() {
|
||||||
|
return "admin@gmail.com";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPhone() {
|
||||||
|
return "15800000000";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTenant() {
|
||||||
|
return new BootstrapTenant().getTenantCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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.models.users;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.models.tenant.ITenant;
|
||||||
|
|
||||||
|
public interface IUser {
|
||||||
|
|
||||||
|
String getUserName();
|
||||||
|
|
||||||
|
String getPassword();
|
||||||
|
|
||||||
|
String getEmail();
|
||||||
|
|
||||||
|
String getPhone();
|
||||||
|
|
||||||
|
String getTenant();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.e2e.pages;
|
package org.apache.dolphinscheduler.e2e.pages;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
|
import org.apache.dolphinscheduler.e2e.models.users.IUser;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.security.TenantPage;
|
import org.apache.dolphinscheduler.e2e.pages.security.TenantPage;
|
||||||
|
|
||||||
|
|
@ -59,17 +61,20 @@ public final class LoginPage extends NavBarPage {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public NavBarPage login(String username, String password) {
|
public NavBarPage login(IUser user) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(30)).until(ExpectedConditions.elementToBeClickable(buttonSwitchLanguage));
|
return login(user.getUserName(), user.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public NavBarPage login(String username, String password) {
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(buttonSwitchLanguage));
|
||||||
buttonSwitchLanguage().click();
|
buttonSwitchLanguage().click();
|
||||||
|
|
||||||
inputUsername().sendKeys(username);
|
inputUsername().sendKeys(username);
|
||||||
inputPassword().sendKeys(password);
|
inputPassword().sendKeys(password);
|
||||||
buttonLogin().click();
|
buttonLogin().click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(30))
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/home"));
|
||||||
.until(ExpectedConditions.urlContains("/home"));
|
|
||||||
|
|
||||||
return new NavBarPage(driver);
|
return new NavBarPage(driver);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,10 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dolphinscheduler.e2e.pages.common;
|
package org.apache.dolphinscheduler.e2e.pages.common;
|
||||||
|
|
||||||
import org.openqa.selenium.By;
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.openqa.selenium.WebDriver;
|
import org.openqa.selenium.WebDriver;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.interactions.Actions;
|
import org.openqa.selenium.interactions.Actions;
|
||||||
import org.openqa.selenium.remote.RemoteWebDriver;
|
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.FindBys;
|
import org.openqa.selenium.support.FindBys;
|
||||||
import org.openqa.selenium.support.PageFactory;
|
import org.openqa.selenium.support.PageFactory;
|
||||||
|
|
@ -51,7 +50,7 @@ public final class CodeEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeEditor content(String content) {
|
public CodeEditor content(String content) {
|
||||||
new WebDriverWait(this.driver, Duration.ofSeconds(20)).until(ExpectedConditions.elementToBeClickable(editor));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(editor));
|
||||||
|
|
||||||
editor.click();
|
editor.click();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
package org.apache.dolphinscheduler.e2e.pages.common;
|
package org.apache.dolphinscheduler.e2e.pages.common;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.openqa.selenium.WebDriver;
|
import org.openqa.selenium.WebDriver;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
@ -50,7 +51,7 @@ public class HttpInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpInput content(String content) {
|
public HttpInput content(String content) {
|
||||||
new WebDriverWait(this.driver, Duration.ofSeconds(20)).until(ExpectedConditions.elementToBeClickable(urlInput));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(urlInput));
|
||||||
urlInput().sendKeys(content);
|
urlInput().sendKeys(content);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.e2e.pages.common;
|
package org.apache.dolphinscheduler.e2e.pages.common;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
import org.apache.dolphinscheduler.e2e.pages.datasource.DataSourcePage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.ProjectPage;
|
import org.apache.dolphinscheduler.e2e.pages.project.ProjectPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.resource.ResourcePage;
|
import org.apache.dolphinscheduler.e2e.pages.resource.ResourcePage;
|
||||||
|
|
@ -64,26 +65,30 @@ public class NavBarPage {
|
||||||
|
|
||||||
public <T extends NavBarItem> T goToNav(Class<T> nav) {
|
public <T extends NavBarItem> T goToNav(Class<T> nav) {
|
||||||
if (nav == ProjectPage.class) {
|
if (nav == ProjectPage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(projectTab));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(projectTab));
|
||||||
projectTab.click();
|
projectTab.click();
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/projects/list"));
|
||||||
return nav.cast(new ProjectPage(driver));
|
return nav.cast(new ProjectPage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nav == SecurityPage.class) {
|
if (nav == SecurityPage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(securityTab));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(securityTab));
|
||||||
securityTab.click();
|
securityTab.click();
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/security/tenant-manage"));
|
||||||
return nav.cast(new SecurityPage(driver));
|
return nav.cast(new SecurityPage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nav == ResourcePage.class) {
|
if (nav == ResourcePage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(resourceTab));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(resourceTab));
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", resourceTab());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", resourceTab());
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/resource/file-manage"));
|
||||||
return nav.cast(new ResourcePage(driver));
|
return nav.cast(new ResourcePage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nav == DataSourcePage.class) {
|
if (nav == DataSourcePage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(dataSourceTab));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(dataSourceTab));
|
||||||
dataSourceTab.click();
|
dataSourceTab.click();
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/datasource"));
|
||||||
return nav.cast(new DataSourcePage(driver));
|
return nav.cast(new DataSourcePage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ package org.apache.dolphinscheduler.e2e.pages.datasource;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
|
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
|
|
@ -74,12 +75,12 @@ public class DataSourcePage extends NavBarPage implements NavBarPage.NavBarItem
|
||||||
String jdbcParams) {
|
String jdbcParams) {
|
||||||
buttonCreateDataSource().click();
|
buttonCreateDataSource().click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.visibilityOfElementLocated(
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.visibilityOfElementLocated(
|
||||||
new By.ByClassName("dialog-source-modal")));
|
new By.ByClassName("dialog-source-modal")));
|
||||||
|
|
||||||
dataSourceModal().findElement(By.className(dataSourceType.toUpperCase()+"-box")).click();
|
dataSourceModal().findElement(By.className(dataSourceType.toUpperCase()+"-box")).click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.textToBePresentInElement(driver.findElement(By.className("dialog-create-data-source")), dataSourceType.toUpperCase()));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.textToBePresentInElement(driver.findElement(By.className("dialog-create-data-source")), dataSourceType.toUpperCase()));
|
||||||
|
|
||||||
createDataSourceForm().inputDataSourceName().sendKeys(dataSourceName);
|
createDataSourceForm().inputDataSourceName().sendKeys(dataSourceName);
|
||||||
createDataSourceForm().inputDataSourceDescription().sendKeys(dataSourceDescription);
|
createDataSourceForm().inputDataSourceDescription().sendKeys(dataSourceDescription);
|
||||||
|
|
|
||||||
|
|
@ -19,16 +19,22 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dolphinscheduler.e2e.pages.project;
|
package org.apache.dolphinscheduler.e2e.pages.project;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.workflow.TaskInstanceTab;
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.TaskInstanceTab;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowDefinitionTab;
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowDefinitionTab;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowInstanceTab;
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowInstanceTab;
|
||||||
|
|
||||||
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.remote.RemoteWebDriver;
|
import org.openqa.selenium.remote.RemoteWebDriver;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public final class ProjectDetailPage extends NavBarPage {
|
public final class ProjectDetailPage extends NavBarPage {
|
||||||
|
|
@ -45,17 +51,21 @@ public final class ProjectDetailPage extends NavBarPage {
|
||||||
super(driver);
|
super(driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
public <T extends Tab> T goToTab(Class<T> tab) {
|
public <T extends Tab> T goToTab(Class<T> tab) {
|
||||||
if (tab == WorkflowDefinitionTab.class) {
|
if (tab == WorkflowDefinitionTab.class) {
|
||||||
menuProcessDefinition().click();
|
menuProcessDefinition().click();
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/workflow-definition"));
|
||||||
return tab.cast(new WorkflowDefinitionTab(driver));
|
return tab.cast(new WorkflowDefinitionTab(driver));
|
||||||
}
|
}
|
||||||
if (tab == WorkflowInstanceTab.class) {
|
if (tab == WorkflowInstanceTab.class) {
|
||||||
menuProcessInstances().click();
|
menuProcessInstances().click();
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/workflow/instances"));
|
||||||
return tab.cast(new WorkflowInstanceTab(driver));
|
return tab.cast(new WorkflowInstanceTab(driver));
|
||||||
}
|
}
|
||||||
if (tab == TaskInstanceTab.class) {
|
if (tab == TaskInstanceTab.class) {
|
||||||
menuTaskInstances().click();
|
menuTaskInstances().click();
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/task/instances"));
|
||||||
return tab.cast(new TaskInstanceTab(driver));
|
return tab.cast(new TaskInstanceTab(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.testcontainers.shaded.org.awaitility.Awaitility.await;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public final class ProjectPage extends NavBarPage implements NavBarItem {
|
public final class ProjectPage extends NavBarPage implements NavBarItem {
|
||||||
|
|
@ -64,17 +66,25 @@ public final class ProjectPage extends NavBarPage implements NavBarItem {
|
||||||
buttonCreateProject().click();
|
buttonCreateProject().click();
|
||||||
createProjectForm().inputProjectName().sendKeys(project);
|
createProjectForm().inputProjectName().sendKeys(project);
|
||||||
createProjectForm().buttonSubmit().click();
|
createProjectForm().buttonSubmit().click();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProjectPage createProjectUntilSuccess(String project) {
|
||||||
|
create(project);
|
||||||
|
await().untilAsserted(() -> assertThat(projectList())
|
||||||
|
.as("project list should contain newly-created project")
|
||||||
|
.anyMatch(it -> it.getText().contains(project)));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public ProjectPage delete(String project) {
|
public ProjectPage delete(String project) {
|
||||||
projectList()
|
projectList()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(it -> it.getText().contains(project))
|
.filter(it -> it.getText().contains(project))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new RuntimeException("Cannot find project: " + project))
|
.orElseThrow(() -> new RuntimeException("Cannot find project: " + project))
|
||||||
.findElement(By.className("delete")).click();
|
.findElement(By.className("delete")).click();
|
||||||
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", buttonConfirm());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", buttonConfirm());
|
||||||
|
|
||||||
|
|
@ -83,11 +93,11 @@ public final class ProjectPage extends NavBarPage implements NavBarItem {
|
||||||
|
|
||||||
public ProjectDetailPage goTo(String project) {
|
public ProjectDetailPage goTo(String project) {
|
||||||
projectList().stream()
|
projectList().stream()
|
||||||
.filter(it -> it.getText().contains(project))
|
.filter(it -> it.getText().contains(project))
|
||||||
.map(it -> it.findElement(By.className("project-name")).findElement(new By.ByTagName("button")))
|
.map(it -> it.findElement(By.className("project-name")).findElement(new By.ByTagName("button")))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new RuntimeException("Cannot click the project item"))
|
.orElseThrow(() -> new RuntimeException("Cannot click the project item"))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
return new ProjectDetailPage(driver);
|
return new ProjectDetailPage(driver);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public final class TaskInstanceTab extends NavBarPage implements ProjectDetailPage.Tab {
|
public final class TaskInstanceTab extends NavBarPage implements ProjectDetailPage.Tab {
|
||||||
@FindBy(className = "items-task-instances")
|
|
||||||
|
@FindBy(className = "batch-task-instance-items")
|
||||||
private List<WebElement> instanceList;
|
private List<WebElement> instanceList;
|
||||||
|
|
||||||
public TaskInstanceTab(RemoteWebDriver driver) {
|
public TaskInstanceTab(RemoteWebDriver driver) {
|
||||||
|
|
@ -47,7 +48,6 @@ public final class TaskInstanceTab extends NavBarPage implements ProjectDetailPa
|
||||||
.stream()
|
.stream()
|
||||||
.filter(WebElement::isDisplayed)
|
.filter(WebElement::isDisplayed)
|
||||||
.map(Row::new)
|
.map(Row::new)
|
||||||
.filter(row -> !row.name().isEmpty())
|
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,12 +55,25 @@ public final class TaskInstanceTab extends NavBarPage implements ProjectDetailPa
|
||||||
public static class Row {
|
public static class Row {
|
||||||
private final WebElement row;
|
private final WebElement row;
|
||||||
|
|
||||||
public String state() {
|
public String taskInstanceName() {
|
||||||
return row.findElement(By.className("task-instance-state")).getText();
|
return row.findElement(By.cssSelector("td[data-col-key=name]")).getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String name() {
|
public String workflowInstanceName() {
|
||||||
return row.findElement(By.className("task-instance-name")).getText();
|
return row.findElement(By.cssSelector("td[data-col-key=processInstanceName]")).getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int retryTimes() {
|
||||||
|
return Integer.parseInt(row.findElement(By.cssSelector("td[data-col-key=retryTimes]")).getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return !row.findElements(By.className("success")).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFailed() {
|
||||||
|
return !row.findElements(By.className("failed")).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dolphinscheduler.e2e.pages.project.workflow;
|
package org.apache.dolphinscheduler.e2e.pages.project.workflow;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.workflow.task.HttpTaskForm;
|
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.ShellTaskForm;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.workflow.task.SubWorkflowTaskForm;
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.task.SubWorkflowTaskForm;
|
||||||
|
|
@ -93,7 +94,7 @@ public final class WorkflowForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebElement getTask(String taskName) {
|
public WebElement getTask(String taskName) {
|
||||||
List<WebElement> tasks = new WebDriverWait(driver, Duration.ofSeconds(20))
|
List<WebElement> tasks = WebDriverWaitFactory.createWebDriverWait(driver)
|
||||||
.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("svg > g > g[class^='x6-graph-svg-stage'] > g[data-shape^='dag-task']")));
|
.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("svg > g > g[class^='x6-graph-svg-stage'] > g[data-shape^='dag-task']")));
|
||||||
|
|
||||||
WebElement task = tasks.stream()
|
WebElement task = tasks.stream()
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,10 @@ public final class WorkflowInstanceTab extends NavBarPage implements ProjectDeta
|
||||||
public static class Row {
|
public static class Row {
|
||||||
private final WebElement row;
|
private final WebElement row;
|
||||||
|
|
||||||
|
public String workflowInstanceName() {
|
||||||
|
return row.findElement(By.className("workflow-name")).getText();
|
||||||
|
}
|
||||||
|
|
||||||
public WebElement rerunButton() {
|
public WebElement rerunButton() {
|
||||||
return row.findElement(By.className("btn-rerun"));
|
return row.findElement(By.className("btn-rerun"));
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +98,10 @@ public final class WorkflowInstanceTab extends NavBarPage implements ProjectDeta
|
||||||
return !row.findElements(By.className("success")).isEmpty();
|
return !row.findElements(By.className("success")).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isFailed() {
|
||||||
|
return !row.findElements(By.className("failed")).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
public int executionTime() {
|
public int executionTime() {
|
||||||
return Integer.parseInt(row.findElement(By.className("workflow-run-times")).getText());
|
return Integer.parseInt(row.findElement(By.className("workflow-run-times")).getText());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dolphinscheduler.e2e.pages.project.workflow;
|
package org.apache.dolphinscheduler.e2e.pages.project.workflow;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.PageFactory;
|
import org.openqa.selenium.support.PageFactory;
|
||||||
|
|
@ -44,7 +45,7 @@ public final class WorkflowRunDialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkflowDefinitionTab submit() {
|
public WorkflowDefinitionTab submit() {
|
||||||
new WebDriverWait(parent().driver(), Duration.ofSeconds(20)).until(ExpectedConditions.elementToBeClickable(buttonSubmit()));
|
WebDriverWaitFactory.createWebDriverWait(parent.driver()).until(ExpectedConditions.elementToBeClickable(buttonSubmit()));
|
||||||
|
|
||||||
buttonSubmit().click();
|
buttonSubmit().click();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dolphinscheduler.e2e.pages.project.workflow.task;
|
package org.apache.dolphinscheduler.e2e.pages.project.workflow.task;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowForm;
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowForm;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
@ -54,11 +55,11 @@ public final class SubWorkflowTaskForm extends TaskNodeForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubWorkflowTaskForm childNode(String node) {
|
public SubWorkflowTaskForm childNode(String node) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(5)).until(ExpectedConditions.elementToBeClickable(btnSelectChildNodeDropdown));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(btnSelectChildNodeDropdown));
|
||||||
|
|
||||||
btnSelectChildNodeDropdown().click();
|
btnSelectChildNodeDropdown().click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(5)).until(ExpectedConditions.visibilityOfElementLocated(By.className(
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.visibilityOfElementLocated(By.className(
|
||||||
"n-base-select-option__content")));
|
"n-base-select-option__content")));
|
||||||
|
|
||||||
selectChildNode()
|
selectChildNode()
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
package org.apache.dolphinscheduler.e2e.pages.project.workflow.task;
|
package org.apache.dolphinscheduler.e2e.pages.project.workflow.task;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowForm;
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowForm;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.JavascriptExecutor;
|
import org.openqa.selenium.JavascriptExecutor;
|
||||||
|
|
@ -54,7 +55,7 @@ public final class SwitchTaskForm extends TaskNodeForm {
|
||||||
|
|
||||||
final By optionsLocator = By.className("option-else-branches");
|
final By optionsLocator = By.className("option-else-branches");
|
||||||
|
|
||||||
new WebDriverWait(parent().driver(), Duration.ofSeconds(10))
|
WebDriverWaitFactory.createWebDriverWait(parent().driver())
|
||||||
.until(ExpectedConditions.visibilityOfElementLocated(optionsLocator));
|
.until(ExpectedConditions.visibilityOfElementLocated(optionsLocator));
|
||||||
|
|
||||||
List<WebElement> webElements = parent().driver().findElements(optionsLocator);
|
List<WebElement> webElements = parent().driver().findElements(optionsLocator);
|
||||||
|
|
@ -79,7 +80,7 @@ public final class SwitchTaskForm extends TaskNodeForm {
|
||||||
|
|
||||||
final By optionsLocator = By.className("option-if-branches");
|
final By optionsLocator = By.className("option-if-branches");
|
||||||
|
|
||||||
new WebDriverWait(parent().driver(), Duration.ofSeconds(10))
|
WebDriverWaitFactory.createWebDriverWait(parent().driver())
|
||||||
.until(ExpectedConditions.visibilityOfElementLocated(optionsLocator));
|
.until(ExpectedConditions.visibilityOfElementLocated(optionsLocator));
|
||||||
|
|
||||||
List<WebElement> webElements = parent().driver().findElements(optionsLocator);
|
List<WebElement> webElements = parent().driver().findElements(optionsLocator);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
package org.apache.dolphinscheduler.e2e.pages.project.workflow.task;
|
package org.apache.dolphinscheduler.e2e.pages.project.workflow.task;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowForm;
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowForm;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.JavascriptExecutor;
|
import org.openqa.selenium.JavascriptExecutor;
|
||||||
|
|
@ -28,13 +29,11 @@ import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.FindBys;
|
import org.openqa.selenium.support.FindBys;
|
||||||
import org.openqa.selenium.support.PageFactory;
|
import org.openqa.selenium.support.PageFactory;
|
||||||
import org.openqa.selenium.support.pagefactory.ByChained;
|
|
||||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public abstract class TaskNodeForm {
|
public abstract class TaskNodeForm {
|
||||||
|
|
@ -48,14 +47,14 @@ public abstract class TaskNodeForm {
|
||||||
private WebElement buttonSubmit;
|
private WebElement buttonSubmit;
|
||||||
|
|
||||||
@FindBys({
|
@FindBys({
|
||||||
@FindBy(className = "input-param-key"),
|
@FindBy(className = "input-param-key"),
|
||||||
@FindBy(tagName = "input"),
|
@FindBy(tagName = "input"),
|
||||||
})
|
})
|
||||||
private List<WebElement> inputParamKey;
|
private List<WebElement> inputParamKey;
|
||||||
|
|
||||||
@FindBys({
|
@FindBys({
|
||||||
@FindBy(className = "input-param-value"),
|
@FindBy(className = "input-param-value"),
|
||||||
@FindBy(tagName = "input"),
|
@FindBy(tagName = "input"),
|
||||||
})
|
})
|
||||||
private List<WebElement> inputParamValue;
|
private List<WebElement> inputParamValue;
|
||||||
|
|
||||||
|
|
@ -80,6 +79,13 @@ public abstract class TaskNodeForm {
|
||||||
@FindBy(className = "btn-create-custom-parameter")
|
@FindBy(className = "btn-create-custom-parameter")
|
||||||
private WebElement buttonCreateCustomParameters;
|
private WebElement buttonCreateCustomParameters;
|
||||||
|
|
||||||
|
@FindBys({
|
||||||
|
@FindBy(className = "resource-select"),
|
||||||
|
@FindBy(className = "n-base-selection"),
|
||||||
|
})
|
||||||
|
private WebElement selectResource;
|
||||||
|
|
||||||
|
|
||||||
private final WorkflowForm parent;
|
private final WorkflowForm parent;
|
||||||
|
|
||||||
TaskNodeForm(WorkflowForm parent) {
|
TaskNodeForm(WorkflowForm parent) {
|
||||||
|
|
@ -118,15 +124,15 @@ public abstract class TaskNodeForm {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaskNodeForm selectEnv(String envName){
|
public TaskNodeForm selectEnv(String envName) {
|
||||||
((JavascriptExecutor)parent().driver()).executeScript("arguments[0].click();", selectEnv);
|
((JavascriptExecutor) parent().driver()).executeScript("arguments[0].click();", selectEnv);
|
||||||
|
|
||||||
final By optionsLocator = By.className("n-base-selection-input__content");
|
final By optionsLocator = By.className("n-base-selection-input__content");
|
||||||
|
|
||||||
new WebDriverWait(parent.driver(), Duration.ofSeconds(20))
|
WebDriverWaitFactory.createWebDriverWait(parent().driver())
|
||||||
.until(ExpectedConditions.visibilityOfElementLocated(optionsLocator));
|
.until(ExpectedConditions.visibilityOfElementLocated(optionsLocator));
|
||||||
|
|
||||||
List<WebElement> webElements = parent.driver().findElements(optionsLocator);
|
List<WebElement> webElements = parent.driver().findElements(optionsLocator);
|
||||||
|
|
||||||
webElements.stream()
|
webElements.stream()
|
||||||
.filter(it -> it.getText().contains(envName))
|
.filter(it -> it.getText().contains(envName))
|
||||||
|
|
@ -138,14 +144,14 @@ public abstract class TaskNodeForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaskNodeForm preTask(String preTaskName) {
|
public TaskNodeForm preTask(String preTaskName) {
|
||||||
((JavascriptExecutor)parent().driver()).executeScript("arguments[0].click();", selectPreTasks);
|
((JavascriptExecutor) parent().driver()).executeScript("arguments[0].click();", selectPreTasks);
|
||||||
|
|
||||||
final By optionsLocator = By.className("option-pre-tasks");
|
final By optionsLocator = By.className("option-pre-tasks");
|
||||||
|
|
||||||
new WebDriverWait(parent.driver(), Duration.ofSeconds(20))
|
WebDriverWaitFactory.createWebDriverWait(parent.driver())
|
||||||
.until(ExpectedConditions.visibilityOfElementLocated(optionsLocator));
|
.until(ExpectedConditions.visibilityOfElementLocated(optionsLocator));
|
||||||
|
|
||||||
List<WebElement> webElements = parent.driver().findElements(optionsLocator);
|
List<WebElement> webElements = parent.driver().findElements(optionsLocator);
|
||||||
webElements.stream()
|
webElements.stream()
|
||||||
.filter(it -> it.getText().contains(preTaskName))
|
.filter(it -> it.getText().contains(preTaskName))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
|
|
@ -157,6 +163,23 @@ public abstract class TaskNodeForm {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TaskNodeForm selectResource(String resourceName) {
|
||||||
|
((JavascriptExecutor) parent().driver()).executeScript("arguments[0].click();", selectResource);
|
||||||
|
|
||||||
|
final By optionsLocator = By.className("n-tree-node-content__text");
|
||||||
|
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(parent().driver()).until(ExpectedConditions.visibilityOfElementLocated(optionsLocator));
|
||||||
|
|
||||||
|
parent().driver()
|
||||||
|
.findElements(optionsLocator)
|
||||||
|
.stream()
|
||||||
|
.filter(it -> it.getText().startsWith(resourceName))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new RuntimeException("No such resource: " + resourceName))
|
||||||
|
.click();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public WorkflowForm submit() {
|
public WorkflowForm submit() {
|
||||||
buttonSubmit.click();
|
buttonSubmit.click();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ package org.apache.dolphinscheduler.e2e.pages.resource;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.CodeEditor;
|
import org.apache.dolphinscheduler.e2e.pages.common.CodeEditor;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
|
|
||||||
|
|
@ -42,6 +43,8 @@ import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.testcontainers.shaded.org.awaitility.Awaitility.await;
|
||||||
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
|
@ -92,6 +95,7 @@ public class FileManagePage extends NavBarPage implements ResourcePage.Tab {
|
||||||
uploadFileBox = new UploadFileBox();
|
uploadFileBox = new UploadFileBox();
|
||||||
|
|
||||||
editFileBox = new EditFileBox();
|
editFileBox = new EditFileBox();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileManagePage createDirectory(String name) {
|
public FileManagePage createDirectory(String name) {
|
||||||
|
|
@ -114,13 +118,13 @@ public class FileManagePage extends NavBarPage implements ResourcePage.Tab {
|
||||||
|
|
||||||
public FileManagePage rename(String currentName, String AfterName) {
|
public FileManagePage rename(String currentName, String AfterName) {
|
||||||
fileList()
|
fileList()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(it -> it.getText().contains(currentName))
|
.filter(it -> it.getText().contains(currentName))
|
||||||
.flatMap(it -> it.findElements(By.className("btn-rename")).stream())
|
.flatMap(it -> it.findElements(By.className("btn-rename")).stream())
|
||||||
.filter(WebElement::isDisplayed)
|
.filter(WebElement::isDisplayed)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new RuntimeException("No rename button in file manage list"))
|
.orElseThrow(() -> new RuntimeException("No rename button in file manage list"))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
renameBox().inputName().sendKeys(Keys.CONTROL + "a");
|
renameBox().inputName().sendKeys(Keys.CONTROL + "a");
|
||||||
renameBox().inputName().sendKeys(Keys.BACK_SPACE);
|
renameBox().inputName().sendKeys(Keys.BACK_SPACE);
|
||||||
|
|
@ -132,12 +136,12 @@ public class FileManagePage extends NavBarPage implements ResourcePage.Tab {
|
||||||
|
|
||||||
public FileManagePage createSubDirectory(String directoryName, String subDirectoryName) {
|
public FileManagePage createSubDirectory(String directoryName, String subDirectoryName) {
|
||||||
fileList()
|
fileList()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(it -> it.getText().contains(directoryName))
|
.filter(it -> it.getText().contains(directoryName))
|
||||||
.filter(WebElement::isDisplayed)
|
.filter(WebElement::isDisplayed)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new RuntimeException(String.format("No %s in file manage list", directoryName)))
|
.orElseThrow(() -> new RuntimeException(String.format("No %s in file manage list", directoryName)))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
buttonCreateDirectory().click();
|
buttonCreateDirectory().click();
|
||||||
|
|
||||||
|
|
@ -149,42 +153,61 @@ public class FileManagePage extends NavBarPage implements ResourcePage.Tab {
|
||||||
|
|
||||||
public FileManagePage delete(String name) {
|
public FileManagePage delete(String name) {
|
||||||
fileList()
|
fileList()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(it -> it.getText().contains(name))
|
.filter(it -> it.getText().contains(name))
|
||||||
.flatMap(it -> it.findElements(By.className("btn-delete")).stream())
|
.flatMap(it -> it.findElements(By.className("btn-delete")).stream())
|
||||||
.filter(WebElement::isDisplayed)
|
.filter(WebElement::isDisplayed)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new RuntimeException("No delete button in file manage list"))
|
.orElseThrow(() -> new RuntimeException("No delete button in file manage list"))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", buttonConfirm());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", buttonConfirm());
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: add file type
|
||||||
public FileManagePage createFile(String fileName, String scripts) {
|
public FileManagePage createFile(String fileName, String scripts) {
|
||||||
|
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(buttonCreateFile()));
|
||||||
|
|
||||||
buttonCreateFile().click();
|
buttonCreateFile().click();
|
||||||
|
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/resource/file/create"));
|
||||||
|
|
||||||
createFileBox().inputFileName().sendKeys(fileName);
|
createFileBox().inputFileName().sendKeys(fileName);
|
||||||
createFileBox().codeEditor().content(scripts);
|
createFileBox().codeEditor().content(scripts);
|
||||||
createFileBox().buttonSubmit().click();
|
createFileBox().buttonSubmit().click();
|
||||||
|
// todo: check if the operation is successful
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileManagePage createFileUntilSuccess(String fileName, String scripts) {
|
||||||
|
|
||||||
|
createFile(fileName, scripts);
|
||||||
|
|
||||||
|
await()
|
||||||
|
.untilAsserted(() ->
|
||||||
|
assertThat(fileList())
|
||||||
|
.as("File list should contain newly-created file: " + fileName)
|
||||||
|
.extracting(WebElement::getText)
|
||||||
|
.anyMatch(it -> it.contains(fileName)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileManagePage editFile(String fileName, String scripts) {
|
public FileManagePage editFile(String fileName, String scripts) {
|
||||||
fileList()
|
fileList()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(it -> it.getText().contains(fileName))
|
.filter(it -> it.getText().contains(fileName))
|
||||||
.flatMap(it -> it.findElements(By.className("btn-edit")).stream())
|
.flatMap(it -> it.findElements(By.className("btn-edit")).stream())
|
||||||
.filter(WebElement::isDisplayed)
|
.filter(WebElement::isDisplayed)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new RuntimeException("No edit button in file manage list"))
|
.orElseThrow(() -> new RuntimeException("No edit button in file manage list"))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.urlContains("/edit"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/edit"));
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.textToBePresentInElement(driver.findElement(By.tagName("body")), fileName));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.textToBePresentInElement(driver.findElement(By.tagName("body")), fileName));
|
||||||
|
|
||||||
editFileBox().codeEditor().content(scripts);
|
editFileBox().codeEditor().content(scripts);
|
||||||
editFileBox().buttonSubmit().click();
|
editFileBox().buttonSubmit().click();
|
||||||
|
|
@ -205,13 +228,13 @@ public class FileManagePage extends NavBarPage implements ResourcePage.Tab {
|
||||||
|
|
||||||
public FileManagePage downloadFile(String fileName) {
|
public FileManagePage downloadFile(String fileName) {
|
||||||
fileList()
|
fileList()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(it -> it.getText().contains(fileName))
|
.filter(it -> it.getText().contains(fileName))
|
||||||
.flatMap(it -> it.findElements(By.className("btn-download")).stream())
|
.flatMap(it -> it.findElements(By.className("btn-download")).stream())
|
||||||
.filter(WebElement::isDisplayed)
|
.filter(WebElement::isDisplayed)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new RuntimeException("No download button in file manage list"))
|
.orElseThrow(() -> new RuntimeException("No download button in file manage list"))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dolphinscheduler.e2e.pages.resource;
|
package org.apache.dolphinscheduler.e2e.pages.resource;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
@ -27,6 +28,7 @@ import org.openqa.selenium.JavascriptExecutor;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.remote.RemoteWebDriver;
|
import org.openqa.selenium.remote.RemoteWebDriver;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
import org.openqa.selenium.support.PageFactory;
|
||||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
|
|
@ -40,14 +42,16 @@ public class ResourcePage extends NavBarPage implements NavBarPage.NavBarItem {
|
||||||
|
|
||||||
public ResourcePage(RemoteWebDriver driver) {
|
public ResourcePage(RemoteWebDriver driver) {
|
||||||
super(driver);
|
super(driver);
|
||||||
|
|
||||||
|
PageFactory.initElements(driver, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends ResourcePage.Tab> T goToTab(Class<T> tab) {
|
public <T extends ResourcePage.Tab> T goToTab(Class<T> tab) {
|
||||||
if (tab == FileManagePage.class) {
|
if (tab == FileManagePage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.urlContains("/resource"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/resource"));
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.elementToBeClickable(fileManageTab));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(fileManageTab));
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", fileManageTab());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", fileManageTab());
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.urlContains("/file-manage"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/file-manage"));
|
||||||
return tab.cast(new FileManagePage(driver));
|
return tab.cast(new FileManagePage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.e2e.pages.security;
|
package org.apache.dolphinscheduler.e2e.pages.security;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
@ -67,7 +68,7 @@ public final class EnvironmentPage extends NavBarPage implements SecurityPage.Ta
|
||||||
createEnvironmentForm().inputEnvironmentDesc().sendKeys(desc);
|
createEnvironmentForm().inputEnvironmentDesc().sendKeys(desc);
|
||||||
|
|
||||||
editEnvironmentForm().btnSelectWorkerGroupDropdown().click();
|
editEnvironmentForm().btnSelectWorkerGroupDropdown().click();
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
||||||
"n-base-select-option__content")));
|
"n-base-select-option__content")));
|
||||||
editEnvironmentForm().selectWorkerGroupList()
|
editEnvironmentForm().selectWorkerGroupList()
|
||||||
.stream()
|
.stream()
|
||||||
|
|
@ -106,7 +107,7 @@ public final class EnvironmentPage extends NavBarPage implements SecurityPage.Ta
|
||||||
|
|
||||||
if (editEnvironmentForm().selectedWorkerGroup().getAttribute("innerHTML").equals(workerGroup)) {
|
if (editEnvironmentForm().selectedWorkerGroup().getAttribute("innerHTML").equals(workerGroup)) {
|
||||||
editEnvironmentForm().btnSelectWorkerGroupDropdown().click();
|
editEnvironmentForm().btnSelectWorkerGroupDropdown().click();
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
||||||
"n-base-select-option__content")));
|
"n-base-select-option__content")));
|
||||||
editEnvironmentForm().selectWorkerGroupList()
|
editEnvironmentForm().selectWorkerGroupList()
|
||||||
.stream()
|
.stream()
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.e2e.pages.security;
|
package org.apache.dolphinscheduler.e2e.pages.security;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage.NavBarItem;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage.NavBarItem;
|
||||||
|
|
||||||
|
|
@ -67,59 +68,60 @@ public class SecurityPage extends NavBarPage implements NavBarItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends SecurityPage.Tab> T goToTab(Class<T> tab) {
|
public <T extends SecurityPage.Tab> T goToTab(Class<T> tab) {
|
||||||
|
|
||||||
if (tab == TenantPage.class) {
|
if (tab == TenantPage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.urlContains("/security"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(menuTenantManage));
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(menuTenantManage));
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuTenantManage());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuTenantManage());
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/security/tenant-manage"));
|
||||||
return tab.cast(new TenantPage(driver));
|
return tab.cast(new TenantPage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab == UserPage.class) {
|
if (tab == UserPage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.urlContains("/security"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(menUserManage));
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(menUserManage));
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menUserManage());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menUserManage());
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/security/user-manage"));
|
||||||
return tab.cast(new UserPage(driver));
|
return tab.cast(new UserPage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab == WorkerGroupPage.class) {
|
if (tab == WorkerGroupPage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.urlContains("/security"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(menWorkerGroupManage));
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(menWorkerGroupManage));
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menWorkerGroupManage());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menWorkerGroupManage());
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/security/worker-group-manage"));
|
||||||
return tab.cast(new WorkerGroupPage(driver));
|
return tab.cast(new WorkerGroupPage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab == QueuePage.class) {
|
if (tab == QueuePage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.urlContains("/security"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(menuQueueManage));
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(menuQueueManage));
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuQueueManage());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuQueueManage());
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/security/yarn-queue-manage"));
|
||||||
return tab.cast(new QueuePage(driver));
|
return tab.cast(new QueuePage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab == EnvironmentPage.class) {
|
if (tab == EnvironmentPage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.urlContains("/security"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(menuEnvironmentManage));
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(menuEnvironmentManage));
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuEnvironmentManage());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuEnvironmentManage());
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/security/environment-manage"));
|
||||||
return tab.cast(new EnvironmentPage(driver));
|
return tab.cast(new EnvironmentPage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab == ClusterPage.class) {
|
if (tab == ClusterPage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.urlContains("/security"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(menuClusterManage));
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(menuClusterManage));
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuClusterManage());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuClusterManage());
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/security/cluster-manage"));
|
||||||
return tab.cast(new ClusterPage(driver));
|
return tab.cast(new ClusterPage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab == TokenPage.class) {
|
if (tab == TokenPage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.urlContains("/security"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(menuTokenManage));
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(menuTokenManage));
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuTokenManage());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuTokenManage());
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/security/token-manage"));
|
||||||
return tab.cast(new TokenPage(driver));
|
return tab.cast(new TokenPage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab == NamespacePage.class) {
|
if (tab == NamespacePage.class) {
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.urlContains("/security"));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(menuNamespaceManage));
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(60)).until(ExpectedConditions.elementToBeClickable(menuNamespaceManage));
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuNamespaceManage());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", menuNamespaceManage());
|
||||||
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.urlContains("/security/k8s-namespace-manage"));
|
||||||
return tab.cast(new NamespacePage(driver));
|
return tab.cast(new NamespacePage(driver));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,14 @@
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.e2e.pages.security;
|
package org.apache.dolphinscheduler.e2e.pages.security;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.dolphinscheduler.e2e.models.tenant.ITenant;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowInstanceTab;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.JavascriptExecutor;
|
import org.openqa.selenium.JavascriptExecutor;
|
||||||
import org.openqa.selenium.Keys;
|
import org.openqa.selenium.Keys;
|
||||||
|
|
@ -33,6 +37,9 @@ import org.openqa.selenium.support.FindBys;
|
||||||
import org.openqa.selenium.support.PageFactory;
|
import org.openqa.selenium.support.PageFactory;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.openqa.selenium.support.pagefactory.ByChained;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.testcontainers.shaded.org.awaitility.Awaitility.await;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public final class TenantPage extends NavBarPage implements SecurityPage.Tab {
|
public final class TenantPage extends NavBarPage implements SecurityPage.Tab {
|
||||||
|
|
@ -43,8 +50,8 @@ public final class TenantPage extends NavBarPage implements SecurityPage.Tab {
|
||||||
private List<WebElement> tenantList;
|
private List<WebElement> tenantList;
|
||||||
|
|
||||||
@FindBys({
|
@FindBys({
|
||||||
@FindBy(className = "n-popconfirm__action"),
|
@FindBy(className = "n-popconfirm__action"),
|
||||||
@FindBy(className = "n-button--primary-type"),
|
@FindBy(className = "n-button--primary-type"),
|
||||||
})
|
})
|
||||||
private WebElement buttonConfirm;
|
private WebElement buttonConfirm;
|
||||||
|
|
||||||
|
|
@ -61,11 +68,28 @@ public final class TenantPage extends NavBarPage implements SecurityPage.Tab {
|
||||||
editTenantForm = new TenantForm();
|
editTenantForm = new TenantForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Row> tenants() {
|
||||||
|
return tenantList.stream()
|
||||||
|
.filter(WebElement::isDisplayed)
|
||||||
|
.map(Row::new)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsTenant(String tenant) {
|
||||||
|
return tenantList.stream()
|
||||||
|
.anyMatch(it -> it.findElement(By.className("tenant-code")).getText().contains(tenant));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TenantPage create(ITenant tenant) {
|
||||||
|
return create(tenant.getTenantCode(), tenant.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
public TenantPage create(String tenant) {
|
public TenantPage create(String tenant) {
|
||||||
return create(tenant, "");
|
return create(tenant, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public TenantPage create(String tenant, String description) {
|
public TenantPage create(String tenant, String description) {
|
||||||
|
|
||||||
buttonCreateTenant().click();
|
buttonCreateTenant().click();
|
||||||
tenantForm().inputTenantCode().sendKeys(tenant);
|
tenantForm().inputTenantCode().sendKeys(tenant);
|
||||||
tenantForm().inputDescription().sendKeys(description);
|
tenantForm().inputDescription().sendKeys(description);
|
||||||
|
|
@ -76,12 +100,12 @@ public final class TenantPage extends NavBarPage implements SecurityPage.Tab {
|
||||||
|
|
||||||
public TenantPage update(String tenant, String description) {
|
public TenantPage update(String tenant, String description) {
|
||||||
tenantList().stream()
|
tenantList().stream()
|
||||||
.filter(it -> it.findElement(By.className("tenant-code")).getAttribute("innerHTML").contains(tenant))
|
.filter(it -> it.findElement(By.className("tenant-code")).getAttribute("innerHTML").contains(tenant))
|
||||||
.flatMap(it -> it.findElements(By.className("edit")).stream())
|
.flatMap(it -> it.findElements(By.className("edit")).stream())
|
||||||
.filter(WebElement::isDisplayed)
|
.filter(WebElement::isDisplayed)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new RuntimeException("No edit button in tenant list"))
|
.orElseThrow(() -> new RuntimeException("No edit button in tenant list"))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
editTenantForm().inputDescription().sendKeys(Keys.CONTROL + "a");
|
editTenantForm().inputDescription().sendKeys(Keys.CONTROL + "a");
|
||||||
editTenantForm().inputDescription().sendKeys(Keys.BACK_SPACE);
|
editTenantForm().inputDescription().sendKeys(Keys.BACK_SPACE);
|
||||||
|
|
@ -93,13 +117,13 @@ public final class TenantPage extends NavBarPage implements SecurityPage.Tab {
|
||||||
|
|
||||||
public TenantPage delete(String tenant) {
|
public TenantPage delete(String tenant) {
|
||||||
tenantList()
|
tenantList()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(it -> it.getText().contains(tenant))
|
.filter(it -> it.getText().contains(tenant))
|
||||||
.flatMap(it -> it.findElements(By.className("delete")).stream())
|
.flatMap(it -> it.findElements(By.className("delete")).stream())
|
||||||
.filter(WebElement::isDisplayed)
|
.filter(WebElement::isDisplayed)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new RuntimeException("No delete button in user list"))
|
.orElseThrow(() -> new RuntimeException("No delete button in user list"))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].click();", buttonConfirm());
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", buttonConfirm());
|
||||||
|
|
||||||
|
|
@ -133,4 +157,14 @@ public final class TenantPage extends NavBarPage implements SecurityPage.Tab {
|
||||||
@FindBy(className = "btn-cancel")
|
@FindBy(className = "btn-cancel")
|
||||||
private WebElement buttonCancel;
|
private WebElement buttonCancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public static class Row {
|
||||||
|
private final WebElement row;
|
||||||
|
|
||||||
|
public String tenantCode() {
|
||||||
|
return row.findElement(By.cssSelector("td[data-col-key=tenantCode]")).getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.e2e.pages.security;
|
package org.apache.dolphinscheduler.e2e.pages.security;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage.Tab;
|
import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage.Tab;
|
||||||
|
|
||||||
|
|
@ -69,9 +70,9 @@ public final class TokenPage extends NavBarPage implements Tab {
|
||||||
public TokenPage create(String userName) {
|
public TokenPage create(String userName) {
|
||||||
buttonCreateToken().click();
|
buttonCreateToken().click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(30)).until(ExpectedConditions.elementToBeClickable(createTokenForm().selectUserNameDropdown()));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(createTokenForm().selectUserNameDropdown()));
|
||||||
createTokenForm().selectUserNameDropdown().click();
|
createTokenForm().selectUserNameDropdown().click();
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(30)).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
||||||
"n-base-select-option__content")));
|
"n-base-select-option__content")));
|
||||||
createTokenForm().selectUserNameList()
|
createTokenForm().selectUserNameList()
|
||||||
.stream()
|
.stream()
|
||||||
|
|
@ -81,7 +82,7 @@ public final class TokenPage extends NavBarPage implements Tab {
|
||||||
userName)))
|
userName)))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(30)).until(ExpectedConditions.elementToBeClickable(createTokenForm().buttonGenerateToken()));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(createTokenForm().buttonGenerateToken()));
|
||||||
createTokenForm().buttonGenerateToken().click();
|
createTokenForm().buttonGenerateToken().click();
|
||||||
|
|
||||||
createTokenForm().buttonSubmit().click();
|
createTokenForm().buttonSubmit().click();
|
||||||
|
|
@ -98,9 +99,9 @@ public final class TokenPage extends NavBarPage implements Tab {
|
||||||
.orElseThrow(() -> new RuntimeException("No edit button in token list"))
|
.orElseThrow(() -> new RuntimeException("No edit button in token list"))
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(30)).until(ExpectedConditions.elementToBeClickable(editTokenForm().buttonGenerateToken()));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(editTokenForm().buttonGenerateToken()));
|
||||||
editTokenForm().buttonGenerateToken().click();
|
editTokenForm().buttonGenerateToken().click();
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(30)).until(ExpectedConditions.elementToBeClickable(editTokenForm().buttonGenerateToken()));
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.elementToBeClickable(editTokenForm().buttonGenerateToken()));
|
||||||
|
|
||||||
editTokenForm().buttonSubmit().click();
|
editTokenForm().buttonSubmit().click();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.e2e.pages.security;
|
package org.apache.dolphinscheduler.e2e.pages.security;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory;
|
||||||
|
import org.apache.dolphinscheduler.e2e.models.users.IUser;
|
||||||
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
@ -67,7 +69,7 @@ public final class UserPage extends NavBarPage implements SecurityPage.Tab {
|
||||||
|
|
||||||
createUserForm().btnSelectTenantDropdown().click();
|
createUserForm().btnSelectTenantDropdown().click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(30)).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
||||||
"n-base-select-option__content")));
|
"n-base-select-option__content")));
|
||||||
|
|
||||||
createUserForm().selectTenant()
|
createUserForm().selectTenant()
|
||||||
|
|
@ -84,7 +86,19 @@ public final class UserPage extends NavBarPage implements SecurityPage.Tab {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserPage update(String user, String editUser, String editEmail, String editPhone,
|
public UserPage update(IUser user) {
|
||||||
|
return update(
|
||||||
|
user.getUserName(),
|
||||||
|
user.getUserName(),
|
||||||
|
user.getEmail(),
|
||||||
|
user.getPhone(),
|
||||||
|
user.getTenant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserPage update(String user,
|
||||||
|
String editUser,
|
||||||
|
String editEmail,
|
||||||
|
String editPhone,
|
||||||
String tenant) {
|
String tenant) {
|
||||||
userList().stream()
|
userList().stream()
|
||||||
.filter(it -> it.findElement(By.className("name")).getAttribute("innerHTML").contains(user))
|
.filter(it -> it.findElement(By.className("name")).getAttribute("innerHTML").contains(user))
|
||||||
|
|
@ -100,7 +114,7 @@ public final class UserPage extends NavBarPage implements SecurityPage.Tab {
|
||||||
|
|
||||||
createUserForm().btnSelectTenantDropdown().click();
|
createUserForm().btnSelectTenantDropdown().click();
|
||||||
|
|
||||||
new WebDriverWait(driver, Duration.ofSeconds(30)).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
WebDriverWaitFactory.createWebDriverWait(driver).until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName(
|
||||||
"n-base-select-option__content")));
|
"n-base-select-option__content")));
|
||||||
|
|
||||||
createUserForm().selectTenant()
|
createUserForm().selectTenant()
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ final class DolphinSchedulerExtension implements BeforeAllCallback, AfterAllCall
|
||||||
@SuppressWarnings("UnstableApiUsage")
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
public void beforeAll(ExtensionContext context) throws IOException {
|
public void beforeAll(ExtensionContext context) throws IOException {
|
||||||
Awaitility.setDefaultTimeout(Duration.ofSeconds(60));
|
Awaitility.setDefaultTimeout(Duration.ofSeconds(60));
|
||||||
Awaitility.setDefaultPollInterval(Duration.ofSeconds(2));
|
Awaitility.setDefaultPollInterval(Duration.ofMillis(500));
|
||||||
|
|
||||||
setRecordPath();
|
setRecordPath();
|
||||||
|
|
||||||
|
|
@ -115,6 +115,7 @@ final class DolphinSchedulerExtension implements BeforeAllCallback, AfterAllCall
|
||||||
.filter(it -> Modifier.isStatic(it.getModifiers()))
|
.filter(it -> Modifier.isStatic(it.getModifiers()))
|
||||||
.filter(f -> WebDriver.class.isAssignableFrom(f.getType()))
|
.filter(f -> WebDriver.class.isAssignableFrom(f.getType()))
|
||||||
.forEach(it -> setDriver(clazz, it));
|
.forEach(it -> setDriver(clazz, it));
|
||||||
|
WebDriverHolder.setWebDriver(driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runInLocal() {
|
private void runInLocal() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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.core;
|
||||||
|
|
||||||
|
import org.openqa.selenium.remote.RemoteWebDriver;
|
||||||
|
|
||||||
|
public class WebDriverHolder {
|
||||||
|
|
||||||
|
public static RemoteWebDriver browser;
|
||||||
|
|
||||||
|
public static void setWebDriver(RemoteWebDriver driver) {
|
||||||
|
browser = driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RemoteWebDriver getWebDriver() {
|
||||||
|
return browser;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.core;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
|
public class WebDriverWaitFactory {
|
||||||
|
|
||||||
|
private static final Duration DEFAULT_INTERVAL = Duration.ofMillis(500);
|
||||||
|
|
||||||
|
private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(60);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a WebDriverWait instance with default timeout 60s and interval 100ms.
|
||||||
|
*/
|
||||||
|
public static WebDriverWait createWebDriverWait(WebDriver driver) {
|
||||||
|
return createWebDriverWait(driver, DEFAULT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebDriverWait createWebDriverWait(WebDriver driver, Duration timeout) {
|
||||||
|
return new WebDriverWait(driver, timeout, DEFAULT_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebDriverWait createWebDriverWait(WebDriver driver, Duration timeout, Duration interval) {
|
||||||
|
return new WebDriverWait(driver, timeout, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -28,7 +28,7 @@ import com.baomidou.mybatisplus.annotation.EnumValue;
|
||||||
public enum ResourceType {
|
public enum ResourceType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0 file, 1 udf
|
* 0 file
|
||||||
*/
|
*/
|
||||||
FILE(0, "file"),
|
FILE(0, "file"),
|
||||||
ALL(2, "all");
|
ALL(2, "all");
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ export function useResources(
|
||||||
return {
|
return {
|
||||||
type: 'tree-select',
|
type: 'tree-select',
|
||||||
field: 'resourceList',
|
field: 'resourceList',
|
||||||
|
class: 'resource-select',
|
||||||
name: t('project.node.resources'),
|
name: t('project.node.resources'),
|
||||||
span: span,
|
span: span,
|
||||||
options: resourcesOptions,
|
options: resourcesOptions,
|
||||||
|
|
|
||||||
|
|
@ -283,6 +283,7 @@ const BatchTaskInstance = defineComponent({
|
||||||
<Card title={t('project.task.batch_task')}>
|
<Card title={t('project.task.batch_task')}>
|
||||||
<NSpace vertical>
|
<NSpace vertical>
|
||||||
<NDataTable
|
<NDataTable
|
||||||
|
row-class-name='batch-task-instance-items'
|
||||||
loading={loadingRef}
|
loading={loadingRef}
|
||||||
columns={this.columns}
|
columns={this.columns}
|
||||||
data={this.tableData}
|
data={this.tableData}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue