mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 09:28:31 +00:00
Merge branch 'appbuilder/sprint-12' into feat/steps-v2-alignment-style-improvement
This commit is contained in:
commit
8cd1ca26a4
34 changed files with 636 additions and 618 deletions
68
.github/workflows/cypress-appbuilder.yml
vendored
68
.github/workflows/cypress-appbuilder.yml
vendored
|
|
@ -13,16 +13,18 @@ jobs:
|
||||||
Cypress-App-Builder:
|
Cypress-App-Builder:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
if: |
|
if: |
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ce-app-builder') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-ce') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ee-app-builder') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-ee') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-cypress')
|
contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce')
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
edition: >-
|
edition: >-
|
||||||
${{
|
${{
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ce-app-builder') && fromJson('["ce"]') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-ce') && fromJson('["ce"]') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ee-app-builder') && fromJson('["ee"]') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce') && fromJson('["ce"]') ||
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-ee') && fromJson('["ee"]') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
||||||
fromJson('[]')
|
fromJson('[]')
|
||||||
}}
|
}}
|
||||||
|
|
@ -158,35 +160,35 @@ jobs:
|
||||||
name: screenshots-appbuilder-${{ matrix.edition }}
|
name: screenshots-appbuilder-${{ matrix.edition }}
|
||||||
path: cypress-tests/cypress/screenshots
|
path: cypress-tests/cypress/screenshots
|
||||||
|
|
||||||
Cypress-App-builder-Subpath:
|
# Cypress-App-builder-Subpath:
|
||||||
runs-on: ubuntu-22.04
|
# runs-on: ubuntu-22.04
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
# if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-subpath')
|
# contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-subpath')
|
||||||
|
|
||||||
steps:
|
# steps:
|
||||||
- name: Checkout
|
# - name: Checkout
|
||||||
uses: actions/checkout@v3
|
# uses: actions/checkout@v3
|
||||||
with:
|
# with:
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
# ref: ${{ github.event.pull_request.head.ref }}
|
||||||
|
|
||||||
- name: Create Cypress environment file
|
# - name: Create Cypress environment file
|
||||||
id: create-json
|
# id: create-json
|
||||||
uses: jsdaniell/create-json@1.1.2
|
# uses: jsdaniell/create-json@1.1.2
|
||||||
with:
|
# with:
|
||||||
name: "cypress.env.json"
|
# name: "cypress.env.json"
|
||||||
json: ${{ secrets.CYPRESS_SECRETS }}
|
# json: ${{ secrets.CYPRESS_SECRETS }}
|
||||||
dir: "./cypress-tests"
|
# dir: "./cypress-tests"
|
||||||
|
|
||||||
- name: App Builder subpath
|
# - name: App Builder subpath
|
||||||
uses: cypress-io/github-action@v5
|
# uses: cypress-io/github-action@v5
|
||||||
with:
|
# with:
|
||||||
working-directory: ./cypress-tests
|
# working-directory: ./cypress-tests
|
||||||
config: "baseUrl=http://localhost:80/apps/tooljet/"
|
# config: "baseUrl=http://localhost:80/apps/tooljet/"
|
||||||
config-file: cypress-app-builder.config.js
|
# config-file: cypress-app-builder.config.js
|
||||||
|
|
||||||
- name: Capture Screenshots
|
# - name: Capture Screenshots
|
||||||
uses: actions/upload-artifact@v4
|
# uses: actions/upload-artifact@v4
|
||||||
if: always()
|
# if: always()
|
||||||
with:
|
# with:
|
||||||
name: screenshots
|
# name: screenshots
|
||||||
path: cypress-tests/cypress/screenshots
|
# path: cypress-tests/cypress/screenshots
|
||||||
|
|
|
||||||
10
.github/workflows/cypress-marketplace.yml
vendored
10
.github/workflows/cypress-marketplace.yml
vendored
|
|
@ -15,16 +15,18 @@ jobs:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ce-cypress-marketplace') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-marketplace-ce') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ee-cypress-marketplace')
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-marketplace-ee') ||
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce')
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
edition: >-
|
edition: >-
|
||||||
${{
|
${{
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ce-cypress-marketplace') && fromJson('["ce"]') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce') && fromJson('["ce"]') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ee-cypress-marketplace') && fromJson('["ee"]') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-marketplace-ce') && fromJson('["ce"]') ||
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-marketplace-ee') && fromJson('["ee"]') ||
|
||||||
fromJson('[]')
|
fromJson('[]')
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
||||||
11
.github/workflows/cypress-platform.yml
vendored
11
.github/workflows/cypress-platform.yml
vendored
|
|
@ -13,15 +13,18 @@ jobs:
|
||||||
Cypress-Platform:
|
Cypress-Platform:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ce-cypress-platform') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ce') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ee-cypress-platform')
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ee') ||
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce')
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
edition: >-
|
edition: >-
|
||||||
${{
|
${{
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ce-cypress-platform') && fromJson('["ce"]') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce') && fromJson('["ce"]') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-ee-cypress-platform') && fromJson('["ee"]') ||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ce') && fromJson('["ce"]') ||
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ee') && fromJson('["ee"]') ||
|
||||||
fromJson('[]')
|
fromJson('[]')
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
||||||
116
.github/workflows/render-preview-deploy.yml
vendored
116
.github/workflows/render-preview-deploy.yml
vendored
|
|
@ -170,7 +170,7 @@ jobs:
|
||||||
"serviceDetails": {
|
"serviceDetails": {
|
||||||
"disk": {
|
"disk": {
|
||||||
"name": "tooljet-ce-pr-${{ env.PR_NUMBER }}-postgresql",
|
"name": "tooljet-ce-pr-${{ env.PR_NUMBER }}-postgresql",
|
||||||
"mountPath": "/data",
|
"mountPath": "/var/lib/postgresql/13/main",
|
||||||
"sizeGB": 10
|
"sizeGB": 10
|
||||||
},
|
},
|
||||||
"env": "docker",
|
"env": "docker",
|
||||||
|
|
@ -283,35 +283,35 @@ jobs:
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
- name: Install PostgreSQL client
|
# - name: Install PostgreSQL client
|
||||||
run: |
|
# run: |
|
||||||
sudo apt update
|
# sudo apt update
|
||||||
sudo apt install postgresql-client -y
|
# sudo apt install postgresql-client -y
|
||||||
|
|
||||||
- name: Wait after installing PostgreSQL
|
# - name: Wait after installing PostgreSQL
|
||||||
run: sleep 25
|
# run: sleep 25
|
||||||
|
|
||||||
- name: Drop PostgreSQL PR databases
|
# - name: Drop PostgreSQL PR databases
|
||||||
env:
|
# env:
|
||||||
PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
|
# PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
|
||||||
PGPORT: 5432
|
# PGPORT: 5432
|
||||||
PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
|
# PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
|
||||||
PGDATABASE: ${{ env.PR_NUMBER }}-ce
|
# PGDATABASE: ${{ env.PR_NUMBER }}-ce
|
||||||
PGTJBDATABASE: ${{ env.PR_NUMBER }}-ce-tjdb
|
# PGTJBDATABASE: ${{ env.PR_NUMBER }}-ce-tjdb
|
||||||
run: |
|
# run: |
|
||||||
if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
|
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
|
||||||
echo "Database $PGDATABASE exists, deleting..."
|
# echo "Database $PGDATABASE exists, deleting..."
|
||||||
PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
|
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
|
||||||
else
|
# else
|
||||||
echo "Database $PGDATABASE does not exist."
|
# echo "Database $PGDATABASE does not exist."
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
|
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
|
||||||
echo "Database $PGTJBDATABASE exists, deleting..."
|
# echo "Database $PGTJBDATABASE exists, deleting..."
|
||||||
PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
|
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
|
||||||
else
|
# else
|
||||||
echo "Database $PGTJBDATABASE does not exist."
|
# echo "Database $PGTJBDATABASE does not exist."
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
suspend-ce-review-app:
|
suspend-ce-review-app:
|
||||||
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-ce-review-app' }}
|
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-ce-review-app' }}
|
||||||
|
|
@ -321,7 +321,7 @@ jobs:
|
||||||
- name: Suspend service
|
- name: Suspend service
|
||||||
run: |
|
run: |
|
||||||
export SERVICE_ID=$(curl --request GET \
|
export SERVICE_ID=$(curl --request GET \
|
||||||
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
--url 'https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||||
--header 'accept: application/json' \
|
--header 'accept: application/json' \
|
||||||
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
||||||
jq -r '.[0].service.id')
|
jq -r '.[0].service.id')
|
||||||
|
|
@ -353,7 +353,7 @@ jobs:
|
||||||
- name: Resume service
|
- name: Resume service
|
||||||
run: |
|
run: |
|
||||||
export SERVICE_ID=$(curl --request GET \
|
export SERVICE_ID=$(curl --request GET \
|
||||||
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
--url 'https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||||
--header 'accept: application/json' \
|
--header 'accept: application/json' \
|
||||||
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
||||||
jq -r '.[0].service.id')
|
jq -r '.[0].service.id')
|
||||||
|
|
@ -542,7 +542,7 @@ jobs:
|
||||||
"serviceDetails": {
|
"serviceDetails": {
|
||||||
"disk": {
|
"disk": {
|
||||||
"name": "tooljet-ee-pr-${{ env.PR_NUMBER }}-postgresql",
|
"name": "tooljet-ee-pr-${{ env.PR_NUMBER }}-postgresql",
|
||||||
"mountPath": "/data",
|
"mountPath": "/var/lib/postgresql/13/main",
|
||||||
"sizeGB": 10
|
"sizeGB": 10
|
||||||
},
|
},
|
||||||
"env": "docker",
|
"env": "docker",
|
||||||
|
|
@ -655,35 +655,35 @@ jobs:
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
- name: Install PostgreSQL client
|
# - name: Install PostgreSQL client
|
||||||
run: |
|
# run: |
|
||||||
sudo apt update
|
# sudo apt update
|
||||||
sudo apt install postgresql-client -y
|
# sudo apt install postgresql-client -y
|
||||||
|
|
||||||
- name: Wait after installing PostgreSQL
|
# - name: Wait after installing PostgreSQL
|
||||||
run: sleep 25
|
# run: sleep 25
|
||||||
|
|
||||||
- name: Drop PostgreSQL PR databases
|
# - name: Drop PostgreSQL PR databases
|
||||||
env:
|
# env:
|
||||||
PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
|
# PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
|
||||||
PGPORT: 5432
|
# PGPORT: 5432
|
||||||
PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
|
# PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
|
||||||
PGDATABASE: ${{ env.PR_NUMBER }}-ee
|
# PGDATABASE: ${{ env.PR_NUMBER }}-ee
|
||||||
PGTJBDATABASE: ${{ env.PR_NUMBER }}-ee-tjdb
|
# PGTJBDATABASE: ${{ env.PR_NUMBER }}-ee-tjdb
|
||||||
run: |
|
# run: |
|
||||||
if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
|
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
|
||||||
echo "Database $PGDATABASE exists, deleting..."
|
# echo "Database $PGDATABASE exists, deleting..."
|
||||||
PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
|
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
|
||||||
else
|
# else
|
||||||
echo "Database $PGDATABASE does not exist."
|
# echo "Database $PGDATABASE does not exist."
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
|
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
|
||||||
echo "Database $PGTJBDATABASE exists, deleting..."
|
# echo "Database $PGTJBDATABASE exists, deleting..."
|
||||||
PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
|
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
|
||||||
else
|
# else
|
||||||
echo "Database $PGTJBDATABASE does not exist."
|
# echo "Database $PGTJBDATABASE does not exist."
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
suspend-ee-review-app:
|
suspend-ee-review-app:
|
||||||
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-ee-review-app' }}
|
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-ee-review-app' }}
|
||||||
|
|
@ -693,7 +693,7 @@ jobs:
|
||||||
- name: Suspend service
|
- name: Suspend service
|
||||||
run: |
|
run: |
|
||||||
export SERVICE_ID=$(curl --request GET \
|
export SERVICE_ID=$(curl --request GET \
|
||||||
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
--url 'https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||||
--header 'accept: application/json' \
|
--header 'accept: application/json' \
|
||||||
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
||||||
jq -r '.[0].service.id')
|
jq -r '.[0].service.id')
|
||||||
|
|
@ -725,7 +725,7 @@ jobs:
|
||||||
- name: Resume service
|
- name: Resume service
|
||||||
run: |
|
run: |
|
||||||
export SERVICE_ID=$(curl --request GET \
|
export SERVICE_ID=$(curl --request GET \
|
||||||
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
--url 'https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||||
--header 'accept: application/json' \
|
--header 'accept: application/json' \
|
||||||
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
||||||
jq -r '.[0].service.id')
|
jq -r '.[0].service.id')
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,11 @@ module.exports = defineConfig({
|
||||||
chromeWebSecurity: false,
|
chromeWebSecurity: false,
|
||||||
trashAssetsBeforeRuns: true,
|
trashAssetsBeforeRuns: true,
|
||||||
e2e: {
|
e2e: {
|
||||||
setupNodeEvents(on, config) {
|
setupNodeEvents (on, config) {
|
||||||
config.baseUrl = environment.baseUrl;
|
config.baseUrl = environment.baseUrl;
|
||||||
|
|
||||||
on("task", {
|
on("task", {
|
||||||
readPdf(pathToPdf) {
|
readPdf (pathToPdf) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const pdfPath = path.resolve(pathToPdf);
|
const pdfPath = path.resolve(pathToPdf);
|
||||||
let dataBuffer = fs.readFileSync(pdfPath);
|
let dataBuffer = fs.readFileSync(pdfPath);
|
||||||
|
|
@ -55,7 +55,7 @@ module.exports = defineConfig({
|
||||||
});
|
});
|
||||||
|
|
||||||
on("task", {
|
on("task", {
|
||||||
readXlsx(filePath) {
|
readXlsx (filePath) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
let dataBuffer = fs.readFileSync(filePath);
|
let dataBuffer = fs.readFileSync(filePath);
|
||||||
|
|
@ -69,7 +69,7 @@ module.exports = defineConfig({
|
||||||
});
|
});
|
||||||
|
|
||||||
on("task", {
|
on("task", {
|
||||||
deleteFolder(folderName) {
|
deleteFolder (folderName) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
rmdir(folderName, { maxRetries: 10, recursive: true }, (err) => {
|
rmdir(folderName, { maxRetries: 10, recursive: true }, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -83,7 +83,7 @@ module.exports = defineConfig({
|
||||||
});
|
});
|
||||||
|
|
||||||
on("task", {
|
on("task", {
|
||||||
dbConnection({ dbconfig, sql }) {
|
dbConnection ({ dbconfig, sql }) {
|
||||||
const client = new pg.Pool(dbconfig);
|
const client = new pg.Pool(dbconfig);
|
||||||
return client.query(sql);
|
return client.query(sql);
|
||||||
},
|
},
|
||||||
|
|
@ -97,9 +97,9 @@ module.exports = defineConfig({
|
||||||
baseUrl: environment.baseUrl,
|
baseUrl: environment.baseUrl,
|
||||||
configFile: environment.configFile,
|
configFile: environment.configFile,
|
||||||
specPattern: [
|
specPattern: [
|
||||||
"cypress/e2e/happyPath/platform/ceTestcases/userFlow/firstUserOnboarding.cy.js",
|
"cypress/e2e/happyPath/platform/firstUser/firstUserOnboarding.cy.js",
|
||||||
"cypress/e2e/happyPath/platform/commonTestcases/workspace/dashboard.cy.js",
|
"cypress/e2e/happyPath/platform/ceTestcases/apps/appSlug.cy.js",
|
||||||
"cypress/e2e/happyPath/platform/ceTestcases/!(userFlow)/**/*.cy.js",
|
"cypress/e2e/happyPath/platform/ceTestcases/**/!(*appSlug).cy.js",
|
||||||
"cypress/e2e/happyPath/platform/commonTestcases/**/*.cy.js",
|
"cypress/e2e/happyPath/platform/commonTestcases/**/*.cy.js",
|
||||||
],
|
],
|
||||||
numTestsKeptInMemory: 1,
|
numTestsKeptInMemory: 1,
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { passwordInputText } from "Texts/passwordInput";
|
||||||
import { importSelectors } from "Selectors/exportImport";
|
import { importSelectors } from "Selectors/exportImport";
|
||||||
import { importText } from "Texts/exportImport";
|
import { importText } from "Texts/exportImport";
|
||||||
import { onboardingSelectors } from "Selectors/onboarding";
|
import { onboardingSelectors } from "Selectors/onboarding";
|
||||||
|
import { selectAppCardOption } from "Support/utils/common";
|
||||||
|
|
||||||
const API_ENDPOINT =
|
const API_ENDPOINT =
|
||||||
Cypress.env("environment") === "Community"
|
Cypress.env("environment") === "Community"
|
||||||
|
|
@ -160,12 +161,10 @@ Cypress.Commands.add(
|
||||||
|
|
||||||
Cypress.Commands.add("deleteApp", (appName) => {
|
Cypress.Commands.add("deleteApp", (appName) => {
|
||||||
cy.intercept("DELETE", "/api/apps/*").as("appDeleted");
|
cy.intercept("DELETE", "/api/apps/*").as("appDeleted");
|
||||||
cy.get(commonSelectors.appCard(appName))
|
selectAppCardOption(
|
||||||
.realHover()
|
appName,
|
||||||
.find(commonSelectors.appCardOptionsButton)
|
commonSelectors.appCardOptions(commonText.deleteAppOption)
|
||||||
.realHover()
|
);
|
||||||
.click();
|
|
||||||
cy.get(commonSelectors.deleteAppOption).click();
|
|
||||||
cy.get(commonSelectors.buttonSelector(commonText.modalYesButton)).click();
|
cy.get(commonSelectors.buttonSelector(commonText.modalYesButton)).click();
|
||||||
cy.verifyToastMessage(
|
cy.verifyToastMessage(
|
||||||
commonSelectors.toastMessage,
|
commonSelectors.toastMessage,
|
||||||
|
|
@ -227,9 +226,9 @@ Cypress.Commands.add(
|
||||||
.invoke("text")
|
.invoke("text")
|
||||||
.then((text) => {
|
.then((text) => {
|
||||||
cy.wrap(subject).realType(createBackspaceText(text)),
|
cy.wrap(subject).realType(createBackspaceText(text)),
|
||||||
{
|
{
|
||||||
delay: 0,
|
delay: 0,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
@ -398,39 +397,38 @@ Cypress.Commands.add("getPosition", (componentName) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add("defaultWorkspaceLogin", () => {
|
Cypress.Commands.add("defaultWorkspaceLogin", () => {
|
||||||
cy.apiLogin();
|
cy.task("dbConnection", {
|
||||||
|
dbconfig: Cypress.env("app_db"),
|
||||||
|
sql: `
|
||||||
|
SELECT id FROM organizations WHERE name = 'My workspace';`,
|
||||||
|
}).then((resp) => {
|
||||||
|
const workspaceId = resp.rows[0].id;
|
||||||
|
|
||||||
// cy.intercept("GET", API_ENDPOINT).as("library_apps");
|
cy.apiLogin(
|
||||||
cy.visit("/my-workspace");
|
"dev@tooljet.io",
|
||||||
cy.wait(2000);
|
"password",
|
||||||
cy.get(commonSelectors.homePageLogo, { timeout: 10000 });
|
workspaceId,
|
||||||
// cy.wait("@library_apps");
|
"/my-workspace"
|
||||||
|
).then(() => {
|
||||||
|
cy.visit("/");
|
||||||
|
cy.wait(2000);
|
||||||
|
cy.get(commonSelectors.homePageLogo, { timeout: 10000 });
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add(
|
Cypress.Commands.add("visitSlug", ({ actualUrl }) => {
|
||||||
"visitSlug",
|
cy.visit(actualUrl);
|
||||||
({
|
cy.wait(1000);
|
||||||
actualUrl,
|
|
||||||
errorUrls = [
|
cy.url().then((currentUrl) => {
|
||||||
`${Cypress.config("baseUrl")}/error/unknown`,
|
if (currentUrl !== actualUrl) {
|
||||||
`${Cypress.config("baseUrl")}/error/restricted`,
|
cy.visit(actualUrl);
|
||||||
],
|
cy.wait(1000);
|
||||||
}) => {
|
|
||||||
if (!actualUrl) {
|
|
||||||
throw new Error("actualUrl is required for visitSlug command.");
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
cy.visit(actualUrl);
|
|
||||||
|
|
||||||
cy.url().then((url) => {
|
|
||||||
if (errorUrls.includes(url)) {
|
|
||||||
cy.log(`Navigation resulted in error URL: ${url}. Retrying...`);
|
|
||||||
cy.visit(actualUrl);
|
|
||||||
cy.wait(1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Cypress.Commands.add("releaseApp", () => {
|
Cypress.Commands.add("releaseApp", () => {
|
||||||
if (Cypress.env("environment") !== "Community") {
|
if (Cypress.env("environment") !== "Community") {
|
||||||
|
|
@ -551,7 +549,7 @@ Cypress.Commands.add("installMarketplacePlugin", (pluginName) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function installPlugin(pluginName) {
|
function installPlugin (pluginName) {
|
||||||
cy.get('[data-cy="-list-item"]').eq(1).click();
|
cy.get('[data-cy="-list-item"]').eq(1).click();
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ export const commonSelectors = {
|
||||||
toastMessage: ".go3958317564",
|
toastMessage: ".go3958317564",
|
||||||
oldToastMessage: ".go318386747",
|
oldToastMessage: ".go318386747",
|
||||||
appSlugAccept: '[data-cy="app-slug-accepted-label"]',
|
appSlugAccept: '[data-cy="app-slug-accepted-label"]',
|
||||||
newToastMessage: '.drawer-container > [style="position: fixed; z-index: 9999; inset: 16px; pointer-events: none;"] > .go4109123758 > .go2072408551 > .go3958317564',
|
newToastMessage:
|
||||||
|
'.drawer-container > [style="position: fixed; z-index: 9999; inset: 16px; pointer-events: none;"] > .go4109123758 > .go2072408551 > .go3958317564',
|
||||||
toastCloseButton: '[data-cy="toast-close-button"]',
|
toastCloseButton: '[data-cy="toast-close-button"]',
|
||||||
editButton: "[data-cy=edit-button]",
|
editButton: "[data-cy=edit-button]",
|
||||||
workspaceConstantNameInput: '[data-cy="name-input-field"]',
|
workspaceConstantNameInput: '[data-cy="name-input-field"]',
|
||||||
|
|
@ -18,7 +19,7 @@ export const commonSelectors = {
|
||||||
appCardOptionsButton: "[data-cy=app-card-menu-icon]",
|
appCardOptionsButton: "[data-cy=app-card-menu-icon]",
|
||||||
autoSave: "[data-cy=autosave-indicator]",
|
autoSave: "[data-cy=autosave-indicator]",
|
||||||
nameInputFieldd: "[data-cy=name-input-field]",
|
nameInputFieldd: "[data-cy=name-input-field]",
|
||||||
valueInputFieldd: '[data-cy=value-input-field]',
|
valueInputFieldd: "[data-cy=value-input-field]",
|
||||||
skipButton: ".driver-close-btn",
|
skipButton: ".driver-close-btn",
|
||||||
skipInstallationModal: "[data-cy=skip-button]",
|
skipInstallationModal: "[data-cy=skip-button]",
|
||||||
homePageLogo: "[data-cy=home-page-logo]",
|
homePageLogo: "[data-cy=home-page-logo]",
|
||||||
|
|
@ -395,7 +396,7 @@ export const commonWidgetSelector = {
|
||||||
modalCloseButton: '[data-cy="modal-close-button"]',
|
modalCloseButton: '[data-cy="modal-close-button"]',
|
||||||
iframeLinkLabel: '[data-cy="iframe-link-label"]',
|
iframeLinkLabel: '[data-cy="iframe-link-label"]',
|
||||||
ifameLinkCopyButton: '[data-cy="iframe-link-copy-button"]',
|
ifameLinkCopyButton: '[data-cy="iframe-link-copy-button"]',
|
||||||
appSlugLabel: '[data-cy="input-field-label"]',
|
appSlugLabel: '[data-cy="unique-app-slug-field-label"]',
|
||||||
appSlugInput: '[data-cy="app-slug-input-field"]',
|
appSlugInput: '[data-cy="app-slug-input-field"]',
|
||||||
appSlugInfoLabel: '[data-cy="helper-text"]',
|
appSlugInfoLabel: '[data-cy="helper-text"]',
|
||||||
appLinkLabel: '[data-cy="app-link-label"]',
|
appLinkLabel: '[data-cy="app-link-label"]',
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ export const restAPISelector = {
|
||||||
return `[data-cy="${cyParamName(header)}-delete-button-${cyParamName(index)}"]`;
|
return `[data-cy="${cyParamName(header)}-delete-button-${cyParamName(index)}"]`;
|
||||||
},
|
},
|
||||||
addMoreButton: (header) => {
|
addMoreButton: (header) => {
|
||||||
return `[data-cy="${cyParamName(header)}-add-more-button"]`;
|
return `[data-cy="${cyParamName(header)}-add-button"]`;
|
||||||
},
|
},
|
||||||
dropdownLabel: (label) => {
|
dropdownLabel: (label) => {
|
||||||
return `[data-cy="${cyParamName(label)}-dropdown-label"]`;
|
return `[data-cy="${cyParamName(label)}-dropdown-label"]`;
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,7 @@ export const editVersionText = {
|
||||||
|
|
||||||
export const deleteVersionText = {
|
export const deleteVersionText = {
|
||||||
deleteModalText: (text) => {
|
deleteModalText: (text) => {
|
||||||
// return `Are you sure you want to delete this version - ${cyParamName(
|
return `Are you sure you want to delete this version - ${cyParamName(
|
||||||
// text
|
|
||||||
// )}?`;
|
|
||||||
|
|
||||||
return `Deleting a version will permanently remove it from all environments.Are you sure you want to delete this version - ${cyParamName(
|
|
||||||
text
|
text
|
||||||
)}?`;
|
)}?`;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,7 @@ describe("App Export", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Verify the elements of export dialog box", () => {
|
it("Verify the elements of export dialog box", () => {
|
||||||
cy.window({ log: false }).then((win) => {
|
cy.skipWalkthrough()
|
||||||
win.localStorage.setItem("walkthroughCompleted", "true");
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.apiLogin();
|
cy.apiLogin();
|
||||||
cy.visit(`${data.workspaceSlug}`);
|
cy.visit(`${data.workspaceSlug}`);
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ describe("App Import Functionality", () => {
|
||||||
cy.apiLogin();
|
cy.apiLogin();
|
||||||
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
|
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
|
||||||
cy.apiLogout();
|
cy.apiLogout();
|
||||||
|
cy.skipWalkthrough()
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should verify app import functionality", () => {
|
it("should verify app import functionality", () => {
|
||||||
|
|
@ -100,12 +101,13 @@ describe("App Import Functionality", () => {
|
||||||
.and("have.text", importText.appImportedToastMessage);
|
.and("have.text", importText.appImportedToastMessage);
|
||||||
|
|
||||||
// Verify imported app
|
// Verify imported app
|
||||||
cy.get(".driver-close-btn").click();
|
cy.get(commonSelectors.toastCloseButton).click();
|
||||||
cy.wait(500);
|
cy.wait(500);
|
||||||
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
|
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
|
||||||
"contain.value",
|
"contain.value",
|
||||||
"three-versions"
|
"three-versions"
|
||||||
);
|
);
|
||||||
|
cy.get(appVersionSelectors.currentVersionField("v3")).should("be.visible");
|
||||||
|
|
||||||
// Configure app
|
// Configure app
|
||||||
cy.skipEditorPopover();
|
cy.skipEditorPopover();
|
||||||
|
|
|
||||||
|
|
@ -27,17 +27,21 @@ describe("App Slug", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Verify app slug cases in global settings", () => {
|
it("Verify app slug cases in global settings", () => {
|
||||||
cy.apiLogin();
|
|
||||||
const workspaceId = Cypress.env("workspaceId");
|
const workspaceId = Cypress.env("workspaceId");
|
||||||
const appId = Cypress.env("appId");
|
const appId = Cypress.env("appId");
|
||||||
|
const appUrl = `${host}/${Cypress.env("workspaceId")}/apps/${Cypress.env("appId")}/`;
|
||||||
|
|
||||||
cy.visit("/my-workspace");
|
cy.apiLogin();
|
||||||
cy.wait(1000);
|
cy.skipWalkthrough();
|
||||||
|
|
||||||
cy.window({ log: false }).then((win) => {
|
cy.visit(appUrl);
|
||||||
win.localStorage.setItem("walkthroughCompleted", "true");
|
cy.url().then((url) => {
|
||||||
|
if (url !== appUrl) {
|
||||||
|
cy.visit(appUrl);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
cy.visit(`/${Cypress.env("workspaceId")}/apps/${Cypress.env("appId")}/`);
|
cy.url().should("eq", appUrl);
|
||||||
|
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
|
|
||||||
cy.get(commonSelectors.leftSideBarSettingsButton).click();
|
cy.get(commonSelectors.leftSideBarSettingsButton).click();
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,11 @@ describe("Private and Public apps", {
|
||||||
|
|
||||||
// Test private access
|
// Test private access
|
||||||
logout();
|
logout();
|
||||||
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
|
|
||||||
|
|
||||||
cy.visitSlug({
|
cy.visitSlug({
|
||||||
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
|
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
|
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
|
||||||
cy.wait(2000);
|
cy.wait(2000);
|
||||||
cy.appUILogin();
|
cy.appUILogin();
|
||||||
|
|
@ -116,6 +116,9 @@ describe("Private and Public apps", {
|
||||||
|
|
||||||
inviteUserToWorkspace(data.firstName, data.email);
|
inviteUserToWorkspace(data.firstName, data.email);
|
||||||
logout();
|
logout();
|
||||||
|
cy.visit("/");
|
||||||
|
cy.wait(2000);
|
||||||
|
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
|
||||||
|
|
||||||
// Test private access
|
// Test private access
|
||||||
cy.visitSlug({
|
cy.visitSlug({
|
||||||
|
|
@ -141,6 +144,8 @@ describe("Private and Public apps", {
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.apiMakeAppPublic();
|
cy.apiMakeAppPublic();
|
||||||
logout();
|
logout();
|
||||||
|
cy.wait(1000);
|
||||||
|
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
|
||||||
|
|
||||||
cy.visitSlug({
|
cy.visitSlug({
|
||||||
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
|
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
|
||||||
|
|
@ -177,6 +182,9 @@ describe("Private and Public apps", {
|
||||||
cy.apiMakeAppPublic();
|
cy.apiMakeAppPublic();
|
||||||
logout();
|
logout();
|
||||||
|
|
||||||
|
cy.wait(1000);
|
||||||
|
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
|
||||||
|
|
||||||
cy.visitSlug({
|
cy.visitSlug({
|
||||||
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
|
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
|
||||||
});
|
});
|
||||||
|
|
@ -229,6 +237,8 @@ describe("Private and Public apps", {
|
||||||
|
|
||||||
cy.get('[data-cy="viewer-page-logo"]').click();
|
cy.get('[data-cy="viewer-page-logo"]').click();
|
||||||
logout();
|
logout();
|
||||||
|
cy.wait(1000);
|
||||||
|
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
|
||||||
|
|
||||||
// Setup new workspace and app
|
// Setup new workspace and app
|
||||||
cy.defaultWorkspaceLogin();
|
cy.defaultWorkspaceLogin();
|
||||||
|
|
@ -123,7 +123,7 @@ describe("App Version", () => {
|
||||||
releasedVersionAndVerify("v2");
|
releasedVersionAndVerify("v2");
|
||||||
});
|
});
|
||||||
|
|
||||||
it.only("should verify version management with components and queries", () => {
|
it("should verify version management with components and queries", () => {
|
||||||
// Initial setup with component and datasource
|
// Initial setup with component and datasource
|
||||||
cy.apiAddComponentToApp(
|
cy.apiAddComponentToApp(
|
||||||
data.appName,
|
data.appName,
|
||||||
|
|
@ -44,6 +44,164 @@ describe("dashboard", () => {
|
||||||
cy.visit(`${data.workspaceSlug}`);
|
cy.visit(`${data.workspaceSlug}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// it("Should verify app card elements and app card operations", () => {
|
||||||
|
// const customLayout = {
|
||||||
|
// desktop: { top: 100, left: 20 },
|
||||||
|
// mobile: { width: 8, height: 50 },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// cy.apiCreateApp(data.appName);
|
||||||
|
// cy.visit(`${data.workspaceSlug}`);
|
||||||
|
|
||||||
|
// cy.wait(2000);
|
||||||
|
// cy.get(commonSelectors.appCreationDetails).should("be.visible");
|
||||||
|
// cy.get(commonSelectors.appCard(data.appName)).should("be.visible");
|
||||||
|
// cy.get(commonSelectors.appTitle(data.appName)).verifyVisibleElement(
|
||||||
|
// "have.text",
|
||||||
|
// data.appName
|
||||||
|
// );
|
||||||
|
|
||||||
|
// viewAppCardOptions(data.appName);
|
||||||
|
// cy.get(
|
||||||
|
// commonSelectors.appCardOptions(commonText.changeIconOption)
|
||||||
|
// ).verifyVisibleElement("have.text", commonText.changeIconOption);
|
||||||
|
// cy.get(
|
||||||
|
// commonSelectors.appCardOptions(commonText.addToFolderOption)
|
||||||
|
// ).verifyVisibleElement("have.text", commonText.addToFolderOption);
|
||||||
|
// cy.get(
|
||||||
|
// commonSelectors.appCardOptions(commonText.cloneAppOption)
|
||||||
|
// ).verifyVisibleElement("have.text", commonText.cloneAppOption);
|
||||||
|
// cy.get(
|
||||||
|
// commonSelectors.appCardOptions(commonText.exportAppOption)
|
||||||
|
// ).verifyVisibleElement("have.text", commonText.exportAppOption);
|
||||||
|
// cy.get(
|
||||||
|
// commonSelectors.appCardOptions(commonText.deleteAppOption)
|
||||||
|
// ).verifyVisibleElement("have.text", commonText.deleteAppOption);
|
||||||
|
|
||||||
|
// modifyAndVerifyAppCardIcon(data.appName);
|
||||||
|
// createFolder(data.folderName);
|
||||||
|
|
||||||
|
// viewAppCardOptions(data.appName);
|
||||||
|
// cy.get(
|
||||||
|
// commonSelectors.appCardOptions(commonText.addToFolderOption)
|
||||||
|
// ).click();
|
||||||
|
// verifyModal(
|
||||||
|
// dashboardText.addToFolderTitle,
|
||||||
|
// dashboardText.addToFolderButton,
|
||||||
|
// dashboardSelector.selectFolder
|
||||||
|
// );
|
||||||
|
// cy.get(dashboardSelector.moveAppText).verifyVisibleElement(
|
||||||
|
// "have.text",
|
||||||
|
// dashboardText.moveAppText(data.appName)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// cy.get(dashboardSelector.selectFolder).click();
|
||||||
|
// cy.get(commonSelectors.folderList).contains(data.folderName).click();
|
||||||
|
// cy.get(dashboardSelector.addToFolderButton).click();
|
||||||
|
// cy.verifyToastMessage(
|
||||||
|
// commonSelectors.toastMessage,
|
||||||
|
// commonText.AddedToFolderToast,
|
||||||
|
// false
|
||||||
|
// );
|
||||||
|
|
||||||
|
// cy.get(dashboardSelector.folderName(data.folderName)).verifyVisibleElement(
|
||||||
|
// "have.text",
|
||||||
|
// dashboardText.folderName(`${data.folderName} (1)`)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// cy.get(dashboardSelector.folderName(data.folderName)).click();
|
||||||
|
// cy.get(commonSelectors.appCard(data.appName))
|
||||||
|
// .contains(data.appName)
|
||||||
|
// .should("be.visible");
|
||||||
|
|
||||||
|
// viewAppCardOptions(data.appName);
|
||||||
|
|
||||||
|
// cy.get(commonSelectors.appCardOptions(commonText.removeFromFolderOption))
|
||||||
|
// .verifyVisibleElement("have.text", commonText.removeFromFolderOption)
|
||||||
|
// .click();
|
||||||
|
// verifyConfirmationModal(commonText.appRemovedFromFolderMessage);
|
||||||
|
|
||||||
|
// cancelModal(commonText.cancelButton);
|
||||||
|
|
||||||
|
// viewAppCardOptions(data.appName);
|
||||||
|
// cy.get(
|
||||||
|
// commonSelectors.appCardOptions(commonText.removeFromFolderOption)
|
||||||
|
// ).click();
|
||||||
|
// cy.get(commonSelectors.buttonSelector(commonText.modalYesButton)).click();
|
||||||
|
// cy.verifyToastMessage(
|
||||||
|
// commonSelectors.toastMessage,
|
||||||
|
// commonText.appRemovedFromFolderTaost,
|
||||||
|
// false
|
||||||
|
// );
|
||||||
|
// cy.get(commonSelectors.modalComponent).should("not.exist");
|
||||||
|
// cy.get(commonSelectors.empytyFolderImage).should("be.visible");
|
||||||
|
// cy.get(commonSelectors.emptyFolderText).verifyVisibleElement(
|
||||||
|
// "have.text",
|
||||||
|
// commonText.emptyFolderText
|
||||||
|
// );
|
||||||
|
// cy.get(commonSelectors.allApplicationsLink).click();
|
||||||
|
// deleteFolder(data.folderName);
|
||||||
|
|
||||||
|
// cy.get(commonSelectors.allApplicationsLink).click();
|
||||||
|
|
||||||
|
// cy.wait(1000);
|
||||||
|
// viewAppCardOptions(data.appName);
|
||||||
|
// cy.wait(2000);
|
||||||
|
// cy.get(commonSelectors.appCardOptions(commonText.exportAppOption)).click();
|
||||||
|
// cy.get(commonSelectors.exportAllButton).click();
|
||||||
|
|
||||||
|
// cy.exec("ls ./cypress/downloads/").then((result) => {
|
||||||
|
// const downloadedAppExportFileName = result.stdout.split("\n")[0];
|
||||||
|
// expect(downloadedAppExportFileName).to.contain.string("app");
|
||||||
|
// });
|
||||||
|
|
||||||
|
// viewAppCardOptions(data.appName);
|
||||||
|
// cy.get(commonSelectors.appCardOptions(commonText.cloneAppOption)).click();
|
||||||
|
// cy.get('[data-cy="clone-app"]').click();
|
||||||
|
// cy.get(".go3958317564")
|
||||||
|
// .should("be.visible")
|
||||||
|
// .and("have.text", dashboardText.appClonedToast);
|
||||||
|
// cy.wait(3000);
|
||||||
|
|
||||||
|
// cy.renameApp(data.cloneAppName);
|
||||||
|
// cy.apiAddComponentToApp(data.cloneAppName, "button", 25, 25);
|
||||||
|
// cy.backToApps();
|
||||||
|
// cy.wait("@appLibrary");
|
||||||
|
// cy.wait(1000);
|
||||||
|
|
||||||
|
// cy.get(commonSelectors.appCard(data.cloneAppName)).should("be.visible");
|
||||||
|
|
||||||
|
// cy.wait(1000);
|
||||||
|
|
||||||
|
// viewAppCardOptions(data.cloneAppName);
|
||||||
|
// cy.get(commonSelectors.deleteAppOption).click();
|
||||||
|
// cy.get(commonSelectors.modalMessage).verifyVisibleElement(
|
||||||
|
// "have.text",
|
||||||
|
// commonText.deleteAppModalMessage(data.cloneAppName)
|
||||||
|
// );
|
||||||
|
// cy.get(
|
||||||
|
// commonSelectors.buttonSelector(commonText.cancelButton)
|
||||||
|
// ).verifyVisibleElement("have.text", commonText.cancelButton);
|
||||||
|
// cy.get(
|
||||||
|
// commonSelectors.buttonSelector(commonText.modalYesButton)
|
||||||
|
// ).verifyVisibleElement("have.text", commonText.modalYesButton);
|
||||||
|
// cancelModal(commonText.cancelButton);
|
||||||
|
|
||||||
|
// viewAppCardOptions(data.cloneAppName);
|
||||||
|
// cy.get(commonSelectors.deleteAppOption).click();
|
||||||
|
// cy.get(commonSelectors.buttonSelector(commonText.modalYesButton)).click();
|
||||||
|
// cy.verifyToastMessage(
|
||||||
|
// commonSelectors.toastMessage,
|
||||||
|
// commonText.appDeletedToast,
|
||||||
|
// false
|
||||||
|
// );
|
||||||
|
// verifyAppDelete(data.cloneAppName);
|
||||||
|
// cy.wait("@appLibrary");
|
||||||
|
|
||||||
|
// cy.deleteApp(data.appName);
|
||||||
|
// verifyAppDelete(data.appName);
|
||||||
|
// });
|
||||||
|
|
||||||
it("should verify the elements on empty dashboard", () => {
|
it("should verify the elements on empty dashboard", () => {
|
||||||
cy.intercept("GET", "/api/metadata", {
|
cy.intercept("GET", "/api/metadata", {
|
||||||
body: {
|
body: {
|
||||||
|
|
@ -171,181 +329,6 @@ describe("dashboard", () => {
|
||||||
verifyTooltip(dashboardSelector.modeToggle, "Mode");
|
verifyTooltip(dashboardSelector.modeToggle, "Mode");
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip("Should verify app card elements and app card operations", () => {
|
|
||||||
const customLayout = {
|
|
||||||
desktop: { top: 100, left: 20 },
|
|
||||||
mobile: { width: 8, height: 50 },
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.apiCreateApp(data.appName);
|
|
||||||
cy.openApp();
|
|
||||||
cy.apiAddComponentToApp(data.appName, "text1", customLayout);
|
|
||||||
|
|
||||||
cy.backToApps();
|
|
||||||
|
|
||||||
cy.wait(500);
|
|
||||||
cy.get(commonSelectors.appCard(data.appName))
|
|
||||||
.parent()
|
|
||||||
.within(() => {
|
|
||||||
cy.get(commonSelectors.appCard(data.appName)).should("be.visible");
|
|
||||||
cy.get(commonSelectors.appTitle(data.appName)).verifyVisibleElement(
|
|
||||||
"have.text",
|
|
||||||
data.appName
|
|
||||||
);
|
|
||||||
cy.get(commonSelectors.appCreationDetails).should("be.visible");
|
|
||||||
|
|
||||||
//Add the edited details
|
|
||||||
});
|
|
||||||
|
|
||||||
viewAppCardOptions(data.appName);
|
|
||||||
cy.get(
|
|
||||||
commonSelectors.appCardOptions(commonText.changeIconOption)
|
|
||||||
).verifyVisibleElement("have.text", commonText.changeIconOption);
|
|
||||||
cy.get(
|
|
||||||
commonSelectors.appCardOptions(commonText.addToFolderOption)
|
|
||||||
).verifyVisibleElement("have.text", commonText.addToFolderOption);
|
|
||||||
cy.get(
|
|
||||||
commonSelectors.appCardOptions(commonText.cloneAppOption)
|
|
||||||
).verifyVisibleElement("have.text", commonText.cloneAppOption);
|
|
||||||
cy.get(
|
|
||||||
commonSelectors.appCardOptions(commonText.exportAppOption)
|
|
||||||
).verifyVisibleElement("have.text", commonText.exportAppOption);
|
|
||||||
cy.get(
|
|
||||||
commonSelectors.appCardOptions(commonText.deleteAppOption)
|
|
||||||
).verifyVisibleElement("have.text", commonText.deleteAppOption);
|
|
||||||
|
|
||||||
modifyAndVerifyAppCardIcon(data.appName);
|
|
||||||
createFolder(data.folderName);
|
|
||||||
|
|
||||||
viewAppCardOptions(data.appName);
|
|
||||||
cy.get(
|
|
||||||
commonSelectors.appCardOptions(commonText.addToFolderOption)
|
|
||||||
).click();
|
|
||||||
verifyModal(
|
|
||||||
dashboardText.addToFolderTitle,
|
|
||||||
dashboardText.addToFolderButton,
|
|
||||||
dashboardSelector.selectFolder
|
|
||||||
);
|
|
||||||
cy.get(dashboardSelector.moveAppText).verifyVisibleElement(
|
|
||||||
"have.text",
|
|
||||||
dashboardText.moveAppText(data.appName)
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.get(dashboardSelector.selectFolder).click();
|
|
||||||
cy.get(commonSelectors.folderList).contains(data.folderName).click();
|
|
||||||
cy.get(dashboardSelector.addToFolderButton).click();
|
|
||||||
cy.verifyToastMessage(
|
|
||||||
commonSelectors.toastMessage,
|
|
||||||
commonText.AddedToFolderToast
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.get(dashboardSelector.folderName(data.folderName)).verifyVisibleElement(
|
|
||||||
"have.text",
|
|
||||||
dashboardText.folderName(`${data.folderName} (1)`)
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.get(dashboardSelector.folderName(data.folderName)).click();
|
|
||||||
cy.get(commonSelectors.appCard(data.appName))
|
|
||||||
.contains(data.appName)
|
|
||||||
.should("be.visible");
|
|
||||||
|
|
||||||
cy.wait(2000);
|
|
||||||
viewAppCardOptions(data.appName);
|
|
||||||
|
|
||||||
cy.get(commonSelectors.appCardOptions(commonText.removeFromFolderOption))
|
|
||||||
.verifyVisibleElement("have.text", commonText.removeFromFolderOption)
|
|
||||||
.click();
|
|
||||||
verifyConfirmationModal(commonText.appRemovedFromFolderMessage);
|
|
||||||
|
|
||||||
cancelModal(commonText.cancelButton);
|
|
||||||
|
|
||||||
cy.wait(3000);
|
|
||||||
viewAppCardOptions(data.appName);
|
|
||||||
cy.get(
|
|
||||||
commonSelectors.appCardOptions(commonText.removeFromFolderOption)
|
|
||||||
).click();
|
|
||||||
cy.get(commonSelectors.buttonSelector(commonText.modalYesButton)).click();
|
|
||||||
cy.verifyToastMessage(
|
|
||||||
commonSelectors.toastMessage,
|
|
||||||
commonText.appRemovedFromFolderTaost
|
|
||||||
);
|
|
||||||
cy.get(commonSelectors.modalComponent).should("not.exist");
|
|
||||||
cy.get(commonSelectors.empytyFolderImage).should("be.visible");
|
|
||||||
cy.get(commonSelectors.emptyFolderText).verifyVisibleElement(
|
|
||||||
"have.text",
|
|
||||||
commonText.emptyFolderText
|
|
||||||
);
|
|
||||||
cy.get(commonSelectors.allApplicationsLink).click();
|
|
||||||
deleteFolder(data.folderName);
|
|
||||||
|
|
||||||
cy.get(commonSelectors.allApplicationsLink).click();
|
|
||||||
|
|
||||||
cy.wait(3000);
|
|
||||||
viewAppCardOptions(data.appName);
|
|
||||||
cy.get(commonSelectors.appCardOptions(commonText.cloneAppOption)).click();
|
|
||||||
cy.get('[data-cy="clone-app"]').click();
|
|
||||||
cy.get(".go3958317564")
|
|
||||||
.should("be.visible")
|
|
||||||
.and("have.text", dashboardText.appClonedToast);
|
|
||||||
cy.wait(3000);
|
|
||||||
cy.renameApp(data.cloneAppName);
|
|
||||||
cy.apiAddComponentToApp(data.cloneAppName, "button", 25, 25);
|
|
||||||
cy.backToApps();
|
|
||||||
cy.wait("@appLibrary");
|
|
||||||
cy.wait(1000);
|
|
||||||
cy.reloadAppForTheElement(data.cloneAppName);
|
|
||||||
|
|
||||||
cy.get(commonSelectors.appCard(data.cloneAppName)).should("be.visible");
|
|
||||||
|
|
||||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
|
||||||
cy.get(commonSelectors.dashboardIcon).click();
|
|
||||||
cy.wait(3000);
|
|
||||||
cy.reloadAppForTheElement(data.cloneAppName);
|
|
||||||
viewAppCardOptions(data.cloneAppName);
|
|
||||||
cy.get(commonSelectors.appCardOptions(commonText.exportAppOption)).click();
|
|
||||||
cy.get(commonSelectors.exportAllButton).click();
|
|
||||||
|
|
||||||
cy.exec("ls ./cypress/downloads/").then((result) => {
|
|
||||||
const downloadedAppExportFileName = result.stdout.split("\n")[0];
|
|
||||||
expect(downloadedAppExportFileName).to.contain.string("app");
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.wait(3000);
|
|
||||||
cy.reloadAppForTheElement(data.cloneAppName);
|
|
||||||
viewAppCardOptions(data.cloneAppName);
|
|
||||||
cy.get(commonSelectors.deleteAppOption).click();
|
|
||||||
cy.get(commonSelectors.modalMessage).verifyVisibleElement(
|
|
||||||
"have.text",
|
|
||||||
commonText.deleteAppModalMessage(data.cloneAppName)
|
|
||||||
);
|
|
||||||
cy.get(
|
|
||||||
commonSelectors.buttonSelector(commonText.cancelButton)
|
|
||||||
).verifyVisibleElement("have.text", commonText.cancelButton);
|
|
||||||
cy.get(
|
|
||||||
commonSelectors.buttonSelector(commonText.modalYesButton)
|
|
||||||
).verifyVisibleElement("have.text", commonText.modalYesButton);
|
|
||||||
cancelModal(commonText.cancelButton);
|
|
||||||
|
|
||||||
cy.wait(3000);
|
|
||||||
cy.reloadAppForTheElement(data.cloneAppName);
|
|
||||||
viewAppCardOptions(data.cloneAppName);
|
|
||||||
cy.get(commonSelectors.deleteAppOption).click();
|
|
||||||
cy.get(commonSelectors.buttonSelector(commonText.modalYesButton)).click();
|
|
||||||
cy.verifyToastMessage(
|
|
||||||
commonSelectors.toastMessage,
|
|
||||||
commonText.appDeletedToast
|
|
||||||
);
|
|
||||||
verifyAppDelete(data.cloneAppName);
|
|
||||||
cy.wait("@appLibrary");
|
|
||||||
|
|
||||||
cy.deleteApp(data.appName);
|
|
||||||
cy.verifyToastMessage(
|
|
||||||
commonSelectors.toastMessage,
|
|
||||||
commonText.appDeletedToast
|
|
||||||
);
|
|
||||||
verifyAppDelete(data.appName);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Should verify the app CRUD operation", () => {
|
it("Should verify the app CRUD operation", () => {
|
||||||
const customLayout = {
|
const customLayout = {
|
||||||
desktop: { top: 100, left: 20 },
|
desktop: { top: 100, left: 20 },
|
||||||
|
|
@ -369,10 +352,7 @@ describe("dashboard", () => {
|
||||||
cy.wait("@appLibrary");
|
cy.wait("@appLibrary");
|
||||||
|
|
||||||
cy.deleteApp(data.appName);
|
cy.deleteApp(data.appName);
|
||||||
cy.verifyToastMessage(
|
|
||||||
commonSelectors.toastMessage,
|
|
||||||
commonText.appDeletedToast
|
|
||||||
);
|
|
||||||
verifyAppDelete(data.appName);
|
verifyAppDelete(data.appName);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -493,10 +473,7 @@ describe("dashboard", () => {
|
||||||
|
|
||||||
cy.get(commonSelectors.allApplicationsLink).click();
|
cy.get(commonSelectors.allApplicationsLink).click();
|
||||||
cy.deleteApp(data.appName);
|
cy.deleteApp(data.appName);
|
||||||
cy.verifyToastMessage(
|
|
||||||
commonSelectors.toastMessage,
|
|
||||||
commonText.appDeletedToast
|
|
||||||
);
|
|
||||||
verifyAppDelete(data.appName);
|
verifyAppDelete(data.appName);
|
||||||
logout();
|
logout();
|
||||||
});
|
});
|
||||||
|
|
@ -204,10 +204,7 @@ describe("Manage Groups", () => {
|
||||||
|
|
||||||
cy.wait(2500);
|
cy.wait(2500);
|
||||||
cy.deleteApp(data.appName);
|
cy.deleteApp(data.appName);
|
||||||
cy.verifyToastMessage(
|
|
||||||
commonSelectors.toastMessage,
|
|
||||||
commonText.appDeletedToast
|
|
||||||
);
|
|
||||||
|
|
||||||
// Folder operations
|
// Folder operations
|
||||||
createFolder(data.folderName);
|
createFolder(data.folderName);
|
||||||
|
|
@ -101,11 +101,14 @@ export const navigateToAppEditor = (appName) => {
|
||||||
|
|
||||||
export const viewAppCardOptions = (appName) => {
|
export const viewAppCardOptions = (appName) => {
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.reloadAppForTheElement(appName);
|
cy.get(commonSelectors.appCard(appName))
|
||||||
|
.realHover()
|
||||||
|
.find(commonSelectors.appCardOptionsButton)
|
||||||
|
.realHover()
|
||||||
cy.contains("div", appName)
|
cy.contains("div", appName)
|
||||||
.parent()
|
.parent()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get(commonSelectors.appCardOptionsButton).invoke("click");
|
cy.get(commonSelectors.appCardOptionsButton).click();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -185,8 +188,9 @@ export const searchUser = (email) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const selectAppCardOption = (appName, appCardOption) => {
|
export const selectAppCardOption = (appName, appCardOption) => {
|
||||||
|
cy.wait(1000);
|
||||||
viewAppCardOptions(appName);
|
viewAppCardOptions(appName);
|
||||||
cy.get(appCardOption).should("be.visible").click({ force: true });
|
cy.get(appCardOption).should("be.visible").click();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const navigateToDatabase = () => {
|
export const navigateToDatabase = () => {
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,8 @@ export const createRestAPIQuery = (
|
||||||
key = "",
|
key = "",
|
||||||
value = "",
|
value = "",
|
||||||
url = "",
|
url = "",
|
||||||
run = true
|
run = true,
|
||||||
|
kind = "restapi"
|
||||||
) => {
|
) => {
|
||||||
cy.getCookie("tj_auth_token").then((cookie) => {
|
cy.getCookie("tj_auth_token").then((cookie) => {
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
@ -247,7 +248,6 @@ export const createRestAPIQuery = (
|
||||||
Cookie: `tj_auth_token=${cookie.value}`,
|
Cookie: `tj_auth_token=${cookie.value}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
cy.log(Cypress.env("appId"));
|
|
||||||
cy.request({
|
cy.request({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: `${Cypress.env("server_host")}/api/apps/${Cypress.env("appId")}`,
|
url: `${Cypress.env("server_host")}/api/apps/${Cypress.env("appId")}`,
|
||||||
|
|
@ -255,13 +255,13 @@ export const createRestAPIQuery = (
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
const editingVersionId = response.body.editing_version.id;
|
const editingVersionId = response.body.editing_version.id;
|
||||||
|
|
||||||
const data_source_id = Cypress.env(`${dsName}-id`);
|
const data_source_id = Cypress.env(kind);
|
||||||
|
|
||||||
const requestBody = {
|
const requestBody = {
|
||||||
app_id: Cypress.env("appId"),
|
app_id: Cypress.env("appId"),
|
||||||
app_version_id: editingVersionId,
|
app_version_id: editingVersionId,
|
||||||
name: queryName,
|
name: queryName,
|
||||||
kind: "restapi",
|
kind: kind,
|
||||||
options: {
|
options: {
|
||||||
method: "get",
|
method: "get",
|
||||||
url: url,
|
url: url,
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,8 @@ export const verifyDuplicateVersion = (newVersion = [], version) => {
|
||||||
cy.get(appVersionSelectors.createNewVersionButton).click();
|
cy.get(appVersionSelectors.createNewVersionButton).click();
|
||||||
cy.verifyToastMessage(
|
cy.verifyToastMessage(
|
||||||
commonSelectors.toastMessage,
|
commonSelectors.toastMessage,
|
||||||
// appVersionText.versionNameAlreadyExists
|
appVersionText.versionNameAlreadyExists
|
||||||
"Already exists!"
|
// "Already exists!"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,13 +80,21 @@ RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-k
|
||||||
RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list
|
RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list
|
||||||
RUN apt update && apt -y install postgresql-13 postgresql-client-13 supervisor
|
RUN apt update && apt -y install postgresql-13 postgresql-client-13 supervisor
|
||||||
|
|
||||||
RUN mkdir -p /var/log/supervisor /var/run/postgresql && \
|
|
||||||
chown -R postgres:postgres /var/run/postgresql /var/log/supervisor
|
|
||||||
|
|
||||||
# Explicitly create PG main directory with correct ownership
|
# Explicitly create PG main directory with correct ownership
|
||||||
RUN mkdir -p /var/lib/postgresql/13/main && \
|
RUN mkdir -p /var/lib/postgresql/13/main && \
|
||||||
chown -R postgres:postgres /var/lib/postgresql
|
chown -R postgres:postgres /var/lib/postgresql
|
||||||
|
|
||||||
|
RUN mkdir -p /var/log/supervisor /var/run/postgresql && \
|
||||||
|
chown -R postgres:postgres /var/run/postgresql /var/log/supervisor
|
||||||
|
|
||||||
|
# Remove existing data and create directory with proper ownership
|
||||||
|
RUN rm -rf /var/lib/postgresql/13/main && \
|
||||||
|
mkdir -p /var/lib/postgresql/13/main && \
|
||||||
|
chown -R postgres:postgres /var/lib/postgresql
|
||||||
|
|
||||||
|
# Initialize PostgreSQL
|
||||||
|
RUN su - postgres -c "/usr/lib/postgresql/13/bin/initdb -D /var/lib/postgresql/13/main"
|
||||||
|
|
||||||
# Configure Supervisor to manage PostgREST, ToolJet, and Redis
|
# Configure Supervisor to manage PostgREST, ToolJet, and Redis
|
||||||
RUN echo "[supervisord] \n" \
|
RUN echo "[supervisord] \n" \
|
||||||
"nodaemon=true \n" \
|
"nodaemon=true \n" \
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ WORKDIR /app
|
||||||
ARG CUSTOM_GITHUB_TOKEN
|
ARG CUSTOM_GITHUB_TOKEN
|
||||||
ARG BRANCH_NAME
|
ARG BRANCH_NAME
|
||||||
|
|
||||||
# Clone and checkout the frontend repository
|
# Clone and checkout the frontend repositorys
|
||||||
RUN git config --global url."https://x-access-token:${CUSTOM_GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
|
RUN git config --global url."https://x-access-token:${CUSTOM_GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
|
||||||
|
|
||||||
RUN git config --global http.version HTTP/1.1
|
RUN git config --global http.version HTTP/1.1
|
||||||
|
|
@ -109,6 +109,14 @@ RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-k
|
||||||
RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list
|
RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list
|
||||||
RUN apt update && apt -y install postgresql-13 postgresql-client-13 supervisor --fix-missing
|
RUN apt update && apt -y install postgresql-13 postgresql-client-13 supervisor --fix-missing
|
||||||
|
|
||||||
|
|
||||||
|
# Explicitly create PG main directory with correct ownership
|
||||||
|
RUN mkdir -p /var/lib/postgresql/13/main && \
|
||||||
|
chown -R postgres:postgres /var/lib/postgresql
|
||||||
|
|
||||||
|
RUN mkdir -p /var/log/supervisor /var/run/postgresql && \
|
||||||
|
chown -R postgres:postgres /var/run/postgresql /var/log/supervisor
|
||||||
|
|
||||||
# Remove existing data and create directory with proper ownership
|
# Remove existing data and create directory with proper ownership
|
||||||
RUN rm -rf /var/lib/postgresql/13/main && \
|
RUN rm -rf /var/lib/postgresql/13/main && \
|
||||||
mkdir -p /var/lib/postgresql/13/main && \
|
mkdir -p /var/lib/postgresql/13/main && \
|
||||||
|
|
|
||||||
|
|
@ -216,248 +216,237 @@ const useAppData = (appId, moduleId, darkMode, mode = 'edit', { environmentId, v
|
||||||
}
|
}
|
||||||
|
|
||||||
// const appDataPromise = appService.fetchApp(appId);
|
// const appDataPromise = appService.fetchApp(appId);
|
||||||
appDataPromise
|
appDataPromise.then(async (result) => {
|
||||||
.then(async (result) => {
|
let appData = { ...result };
|
||||||
let appData = { ...result };
|
let editorEnvironment = result.editorEnvironment;
|
||||||
let editorEnvironment = result.editorEnvironment;
|
if (isPreviewForVersion) {
|
||||||
if (isPreviewForVersion) {
|
const rawDataQueries = appData?.data_queries;
|
||||||
const rawDataQueries = appData?.data_queries;
|
const rawEditingVersionDataQueries = appData?.editing_version?.data_queries;
|
||||||
const rawEditingVersionDataQueries = appData?.editing_version?.data_queries;
|
appData = convertAllKeysToSnakeCase(appData);
|
||||||
appData = convertAllKeysToSnakeCase(appData);
|
|
||||||
|
|
||||||
appData.data_queries = rawDataQueries;
|
appData.data_queries = rawDataQueries;
|
||||||
if (appData.editing_version && rawEditingVersionDataQueries) {
|
if (appData.editing_version && rawEditingVersionDataQueries) {
|
||||||
appData.editing_version.data_queries = rawEditingVersionDataQueries;
|
appData.editing_version.data_queries = rawEditingVersionDataQueries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editorEnvironment = {
|
||||||
|
id: environmentId,
|
||||||
|
name: queryParams.env,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let constantsResp;
|
||||||
|
if (mode !== 'edit') {
|
||||||
|
try {
|
||||||
|
const queryParams = { slug: slug };
|
||||||
|
const viewerEnvironment = await appEnvironmentService.getEnvironment(environmentId, queryParams);
|
||||||
editorEnvironment = {
|
editorEnvironment = {
|
||||||
id: environmentId,
|
id: viewerEnvironment?.environment?.id,
|
||||||
name: queryParams.env,
|
name: viewerEnvironment?.environment?.name,
|
||||||
};
|
};
|
||||||
|
constantsResp =
|
||||||
|
isPublicAccess && appData.is_public
|
||||||
|
? await orgEnvironmentConstantService.getConstantsFromPublicApp(slug, viewerEnvironment?.environment?.id)
|
||||||
|
: await orgEnvironmentConstantService.getConstantsFromApp(slug, viewerEnvironment?.environment?.id);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching viewer environment:', error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let constantsResp;
|
if (mode === 'edit') {
|
||||||
if (mode !== 'edit') {
|
constantsResp = await orgEnvironmentConstantService.getConstantsFromEnvironment(editorEnvironment?.id);
|
||||||
try {
|
}
|
||||||
const queryParams = { slug: slug };
|
// get the constants for specific environment
|
||||||
const viewerEnvironment = await appEnvironmentService.getEnvironment(environmentId, queryParams);
|
constantsResp.constants = extractEnvironmentConstantsFromConstantsList(
|
||||||
editorEnvironment = {
|
constantsResp?.constants,
|
||||||
id: viewerEnvironment?.environment?.id,
|
editorEnvironment?.name
|
||||||
name: viewerEnvironment?.environment?.name,
|
);
|
||||||
};
|
|
||||||
constantsResp =
|
|
||||||
isPublicAccess && appData.is_public
|
|
||||||
? await orgEnvironmentConstantService.getConstantsFromPublicApp(
|
|
||||||
slug,
|
|
||||||
viewerEnvironment?.environment?.id
|
|
||||||
)
|
|
||||||
: await orgEnvironmentConstantService.getConstantsFromApp(slug, viewerEnvironment?.environment?.id);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching viewer environment:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode === 'edit') {
|
setIsPublicAccess(isPublicAccess && mode !== 'edit' && appData.is_public);
|
||||||
constantsResp = await orgEnvironmentConstantService.getConstantsFromEnvironment(editorEnvironment?.id);
|
|
||||||
}
|
|
||||||
// get the constants for specific environment
|
|
||||||
constantsResp.constants = extractEnvironmentConstantsFromConstantsList(
|
|
||||||
constantsResp?.constants,
|
|
||||||
editorEnvironment?.name
|
|
||||||
);
|
|
||||||
|
|
||||||
setIsPublicAccess(isPublicAccess && mode !== 'edit' && appData.is_public);
|
fetchAndInjectCustomStyles(isPublicAccess && mode !== 'edit' && appData.is_public);
|
||||||
|
|
||||||
fetchAndInjectCustomStyles(isPublicAccess && mode !== 'edit' && appData.is_public);
|
const pages = appData.pages.map((page) => {
|
||||||
|
return page;
|
||||||
const pages = appData.pages.map((page) => {
|
|
||||||
return page;
|
|
||||||
});
|
|
||||||
const conversation = appData.ai_conversation;
|
|
||||||
const docsConversation = appData.ai_conversation_learn;
|
|
||||||
if (setConversation && setDocsConversation) {
|
|
||||||
setConversation(conversation);
|
|
||||||
setDocsConversation(docsConversation);
|
|
||||||
// important to control ai inputs
|
|
||||||
getCreditBalance();
|
|
||||||
}
|
|
||||||
|
|
||||||
let showWalkthrough = true;
|
|
||||||
// if app was created from propmt, and no earlier messages are present in the conversation, send the prompt message
|
|
||||||
|
|
||||||
// handles the getappdataby slug api call. Gets the homePageId from the appData.
|
|
||||||
const homePageId =
|
|
||||||
appData.editing_version?.homePageId || appData.editing_version?.home_page_id || appData.home_page_id;
|
|
||||||
|
|
||||||
setApp({
|
|
||||||
appName: appData.name,
|
|
||||||
appId: appData.id,
|
|
||||||
slug: appData.slug,
|
|
||||||
currentAppEnvironmentId: editorEnvironment.id,
|
|
||||||
isMaintenanceOn:
|
|
||||||
'is_maintenance_on' in result
|
|
||||||
? result.is_maintenance_on
|
|
||||||
: 'isMaintenanceOn' in result
|
|
||||||
? result.isMaintenanceOn
|
|
||||||
: false,
|
|
||||||
organizationId: appData.organizationId || appData.organization_id,
|
|
||||||
homePageId: homePageId,
|
|
||||||
isPublic: appData.is_public,
|
|
||||||
creationMode: appData.creation_mode,
|
|
||||||
});
|
|
||||||
setIsEditorFreezed(appData.should_freeze_editor);
|
|
||||||
const global_settings = mapKeys(
|
|
||||||
appData.editing_version?.global_settings || appData.global_settings,
|
|
||||||
(value, key) => camelCase(key)
|
|
||||||
);
|
|
||||||
if (!global_settings?.theme) {
|
|
||||||
global_settings.theme = baseTheme;
|
|
||||||
}
|
|
||||||
setGlobalSettings(global_settings);
|
|
||||||
setPages(pages, moduleId);
|
|
||||||
setPageSettings(
|
|
||||||
computePageSettings(deepCamelCase(appData?.editing_version?.page_settings ?? appData?.page_settings))
|
|
||||||
);
|
|
||||||
|
|
||||||
// set starting page as homepage initially
|
|
||||||
let startingPage = appData.pages.find((page) => page.id === homePageId);
|
|
||||||
|
|
||||||
//no access to homepage, set to the next available page
|
|
||||||
if (startingPage?.restricted) {
|
|
||||||
startingPage = appData.pages.find((page) => !page?.restricted);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (initialLoadRef.current) {
|
|
||||||
// if initial load, check if the path has a page handle and set that as the starting page
|
|
||||||
const initialLoadPath = location.pathname.split('/').pop();
|
|
||||||
|
|
||||||
const page = appData.pages.find((page) => page.handle === initialLoadPath && !page.isPageGroup);
|
|
||||||
if (page) {
|
|
||||||
// if page is disabled, and not editing redirect to home page
|
|
||||||
const shouldRedirect = page?.restricted || (mode !== 'edit' && page?.disabled);
|
|
||||||
|
|
||||||
if (shouldRedirect) {
|
|
||||||
const newUrl = window.location.href.replace(initialLoadPath, startingPage.handle);
|
|
||||||
window.history.replaceState(null, null, newUrl);
|
|
||||||
|
|
||||||
if (page?.restricted) {
|
|
||||||
toast.error('Access to this page is restricted. Contact admin to know more.', {
|
|
||||||
className: 'text-nowrap w-auto mw-100',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
startingPage = page;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// navigate(`/${getWorkspaceId()}/apps/${slug ?? appId}/${startingPage.handle}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add page id and handle to the state on initial load
|
|
||||||
const currentState = window.history.state || {};
|
|
||||||
const pageInfo = {
|
|
||||||
id: startingPage.id,
|
|
||||||
handle: startingPage.handle,
|
|
||||||
};
|
|
||||||
const newState = { ...currentState, ...pageInfo };
|
|
||||||
window.history.replaceState(newState, '', window.location.href);
|
|
||||||
|
|
||||||
setCurrentPageHandle(startingPage.handle);
|
|
||||||
updateFeatureAccess();
|
|
||||||
setCurrentPageId(startingPage.id, moduleId);
|
|
||||||
setResolvedPageConstants({
|
|
||||||
id: startingPage?.id,
|
|
||||||
handle: startingPage?.handle,
|
|
||||||
name: startingPage?.name,
|
|
||||||
});
|
|
||||||
setComponentNameIdMapping(moduleId);
|
|
||||||
updateEventsField('events', appData.events);
|
|
||||||
setCurrentVersionId(appData.editing_version?.id || appData.current_version_id);
|
|
||||||
setAppHomePageId(homePageId);
|
|
||||||
|
|
||||||
const queryData =
|
|
||||||
isPublicAccess || (mode !== 'edit' && appData.is_public)
|
|
||||||
? appData
|
|
||||||
: await dataqueryService.getAll(appData.editing_version?.id || appData.current_version_id);
|
|
||||||
const dataQueries = queryData.data_queries || queryData?.editing_version?.data_queries;
|
|
||||||
dataQueries.forEach((query) => normalizeQueryTransformationOptions(query));
|
|
||||||
setQueries(dataQueries);
|
|
||||||
if (dataQueries?.length > 0) {
|
|
||||||
setSelectedQuery(dataQueries[0]?.id);
|
|
||||||
initialiseResolvedQuery(dataQueries.map((query) => query.id));
|
|
||||||
}
|
|
||||||
const constants = constantsResp?.constants;
|
|
||||||
|
|
||||||
if (constants) {
|
|
||||||
const orgConstants = {};
|
|
||||||
const orgSecrets = {};
|
|
||||||
constants.map((constant) => {
|
|
||||||
if (constant.type !== 'Secret') {
|
|
||||||
orgConstants[constant.name] = constant.value;
|
|
||||||
} else {
|
|
||||||
orgSecrets[constant.name] = constant.value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setResolvedConstants(orgConstants);
|
|
||||||
setSecrets(orgSecrets);
|
|
||||||
}
|
|
||||||
setQueryMapping(moduleId);
|
|
||||||
|
|
||||||
setResolvedGlobals('environment', editorEnvironment);
|
|
||||||
setResolvedGlobals('mode', { value: mode });
|
|
||||||
setResolvedGlobals('currentUser', {
|
|
||||||
...user,
|
|
||||||
groups: currentSession?.groups,
|
|
||||||
role: currentSession?.role?.name,
|
|
||||||
ssoUserInfo: currentSession?.ssoUserInfo,
|
|
||||||
...(currentSession?.currentUser?.metadata && !isEmpty(currentSession?.currentUser?.metadata)
|
|
||||||
? { metadata: currentSession?.currentUser?.metadata }
|
|
||||||
: {}),
|
|
||||||
});
|
|
||||||
setResolvedGlobals('urlparams', JSON.parse(JSON.stringify(queryString.parse(location?.search))));
|
|
||||||
initDependencyGraph(moduleId);
|
|
||||||
setCurrentMode(mode); // TODO: set mode based on the slug/appDef
|
|
||||||
if (
|
|
||||||
state.ai &&
|
|
||||||
state?.prompt &&
|
|
||||||
initialLoadRef.current &&
|
|
||||||
(conversation?.aiConversationMessages || []).length === 0
|
|
||||||
) {
|
|
||||||
setSelectedSidebarItem('tooljetai');
|
|
||||||
toggleLeftSidebar('true');
|
|
||||||
sendMessage(state.prompt);
|
|
||||||
setConversationZeroState(true);
|
|
||||||
showWalkthrough = false;
|
|
||||||
}
|
|
||||||
// fetchDataSources(appData.editing_version.id, editorEnvironment.id);
|
|
||||||
if (!isPublicAccess) {
|
|
||||||
const envFromQueryParams = mode === 'view' && new URLSearchParams(location?.search)?.get('env');
|
|
||||||
useStore.getState().init(appData.editing_version?.id || appData.current_version_id, envFromQueryParams);
|
|
||||||
fetchGlobalDataSources(
|
|
||||||
appData.organization_id,
|
|
||||||
appData.editing_version?.id || appData.current_version_id,
|
|
||||||
editorEnvironment.id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
useStore.getState().updateEditingVersion(appData.editing_version?.id || appData.current_version_id); //check if this is needed
|
|
||||||
updateReleasedVersionId(appData.current_version_id);
|
|
||||||
|
|
||||||
setEditorLoading(false);
|
|
||||||
initialLoadRef.current = false;
|
|
||||||
// only show if app is not created from prompt
|
|
||||||
if (showWalkthrough) initEditorWalkThrough();
|
|
||||||
checkAndSetTrueBuildSuggestionsFlag();
|
|
||||||
return () => {
|
|
||||||
document.title = retrieveWhiteLabelText();
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
if (isPublicAccess) {
|
|
||||||
if (mode !== 'edit') {
|
|
||||||
handleError('view', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
const conversation = appData.ai_conversation;
|
||||||
|
const docsConversation = appData.ai_conversation_learn;
|
||||||
|
if (setConversation && setDocsConversation) {
|
||||||
|
setConversation(conversation);
|
||||||
|
setDocsConversation(docsConversation);
|
||||||
|
// important to control ai inputs
|
||||||
|
getCreditBalance();
|
||||||
|
}
|
||||||
|
|
||||||
|
let showWalkthrough = true;
|
||||||
|
// if app was created from propmt, and no earlier messages are present in the conversation, send the prompt message
|
||||||
|
|
||||||
|
// handles the getappdataby slug api call. Gets the homePageId from the appData.
|
||||||
|
const homePageId =
|
||||||
|
appData.editing_version?.homePageId || appData.editing_version?.home_page_id || appData.home_page_id;
|
||||||
|
|
||||||
|
setApp({
|
||||||
|
appName: appData.name,
|
||||||
|
appId: appData.id,
|
||||||
|
slug: appData.slug,
|
||||||
|
currentAppEnvironmentId: editorEnvironment.id,
|
||||||
|
isMaintenanceOn:
|
||||||
|
'is_maintenance_on' in result
|
||||||
|
? result.is_maintenance_on
|
||||||
|
: 'isMaintenanceOn' in result
|
||||||
|
? result.isMaintenanceOn
|
||||||
|
: false,
|
||||||
|
organizationId: appData.organizationId || appData.organization_id,
|
||||||
|
homePageId: homePageId,
|
||||||
|
isPublic: appData.is_public,
|
||||||
|
creationMode: appData.creation_mode,
|
||||||
|
});
|
||||||
|
setIsEditorFreezed(appData.should_freeze_editor);
|
||||||
|
const global_settings = mapKeys(
|
||||||
|
appData.editing_version?.global_settings || appData.global_settings,
|
||||||
|
(value, key) => camelCase(key)
|
||||||
|
);
|
||||||
|
if (!global_settings?.theme) {
|
||||||
|
global_settings.theme = baseTheme;
|
||||||
|
}
|
||||||
|
setGlobalSettings(global_settings);
|
||||||
|
setPages(pages, moduleId);
|
||||||
|
setPageSettings(
|
||||||
|
computePageSettings(deepCamelCase(appData?.editing_version?.page_settings ?? appData?.page_settings))
|
||||||
|
);
|
||||||
|
|
||||||
|
// set starting page as homepage initially
|
||||||
|
let startingPage = appData.pages.find((page) => page.id === homePageId);
|
||||||
|
|
||||||
|
//no access to homepage, set to the next available page
|
||||||
|
if (startingPage?.restricted) {
|
||||||
|
startingPage = appData.pages.find((page) => !page?.restricted);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialLoadRef.current) {
|
||||||
|
// if initial load, check if the path has a page handle and set that as the starting page
|
||||||
|
const initialLoadPath = location.pathname.split('/').pop();
|
||||||
|
|
||||||
|
const page = appData.pages.find((page) => page.handle === initialLoadPath && !page.isPageGroup);
|
||||||
|
if (page) {
|
||||||
|
// if page is disabled, and not editing redirect to home page
|
||||||
|
const shouldRedirect = page?.restricted || (mode !== 'edit' && page?.disabled);
|
||||||
|
|
||||||
|
if (shouldRedirect) {
|
||||||
|
const newUrl = window.location.href.replace(initialLoadPath, startingPage.handle);
|
||||||
|
window.history.replaceState(null, null, newUrl);
|
||||||
|
|
||||||
|
if (page?.restricted) {
|
||||||
|
toast.error('Access to this page is restricted. Contact admin to know more.', {
|
||||||
|
className: 'text-nowrap w-auto mw-100',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startingPage = page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// navigate(`/${getWorkspaceId()}/apps/${slug ?? appId}/${startingPage.handle}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add page id and handle to the state on initial load
|
||||||
|
const currentState = window.history.state || {};
|
||||||
|
const pageInfo = {
|
||||||
|
id: startingPage.id,
|
||||||
|
handle: startingPage.handle,
|
||||||
|
};
|
||||||
|
const newState = { ...currentState, ...pageInfo };
|
||||||
|
window.history.replaceState(newState, '', window.location.href);
|
||||||
|
|
||||||
|
setCurrentPageHandle(startingPage.handle);
|
||||||
|
updateFeatureAccess();
|
||||||
|
setCurrentPageId(startingPage.id, moduleId);
|
||||||
|
setResolvedPageConstants({
|
||||||
|
id: startingPage?.id,
|
||||||
|
handle: startingPage?.handle,
|
||||||
|
name: startingPage?.name,
|
||||||
|
});
|
||||||
|
setComponentNameIdMapping(moduleId);
|
||||||
|
updateEventsField('events', appData.events);
|
||||||
|
setCurrentVersionId(appData.editing_version?.id || appData.current_version_id);
|
||||||
|
setAppHomePageId(homePageId);
|
||||||
|
|
||||||
|
const queryData =
|
||||||
|
isPublicAccess || (mode !== 'edit' && appData.is_public)
|
||||||
|
? appData
|
||||||
|
: await dataqueryService.getAll(appData.editing_version?.id || appData.current_version_id);
|
||||||
|
const dataQueries = queryData.data_queries || queryData?.editing_version?.data_queries;
|
||||||
|
dataQueries.forEach((query) => normalizeQueryTransformationOptions(query));
|
||||||
|
setQueries(dataQueries);
|
||||||
|
if (dataQueries?.length > 0) {
|
||||||
|
setSelectedQuery(dataQueries[0]?.id);
|
||||||
|
initialiseResolvedQuery(dataQueries.map((query) => query.id));
|
||||||
|
}
|
||||||
|
const constants = constantsResp?.constants;
|
||||||
|
|
||||||
|
if (constants) {
|
||||||
|
const orgConstants = {};
|
||||||
|
const orgSecrets = {};
|
||||||
|
constants.map((constant) => {
|
||||||
|
if (constant.type !== 'Secret') {
|
||||||
|
orgConstants[constant.name] = constant.value;
|
||||||
|
} else {
|
||||||
|
orgSecrets[constant.name] = constant.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setResolvedConstants(orgConstants);
|
||||||
|
setSecrets(orgSecrets);
|
||||||
|
}
|
||||||
|
setQueryMapping(moduleId);
|
||||||
|
|
||||||
|
setResolvedGlobals('environment', editorEnvironment);
|
||||||
|
setResolvedGlobals('mode', { value: mode });
|
||||||
|
setResolvedGlobals('currentUser', {
|
||||||
|
...user,
|
||||||
|
groups: currentSession?.groups,
|
||||||
|
role: currentSession?.role?.name,
|
||||||
|
ssoUserInfo: currentSession?.ssoUserInfo,
|
||||||
|
...(currentSession?.currentUser?.metadata && !isEmpty(currentSession?.currentUser?.metadata)
|
||||||
|
? { metadata: currentSession?.currentUser?.metadata }
|
||||||
|
: {}),
|
||||||
|
});
|
||||||
|
setResolvedGlobals('urlparams', JSON.parse(JSON.stringify(queryString.parse(location?.search))));
|
||||||
|
initDependencyGraph(moduleId);
|
||||||
|
setCurrentMode(mode); // TODO: set mode based on the slug/appDef
|
||||||
|
if (
|
||||||
|
state.ai &&
|
||||||
|
state?.prompt &&
|
||||||
|
initialLoadRef.current &&
|
||||||
|
(conversation?.aiConversationMessages || []).length === 0
|
||||||
|
) {
|
||||||
|
setSelectedSidebarItem('tooljetai');
|
||||||
|
toggleLeftSidebar('true');
|
||||||
|
sendMessage(state.prompt);
|
||||||
|
setConversationZeroState(true);
|
||||||
|
showWalkthrough = false;
|
||||||
|
}
|
||||||
|
// fetchDataSources(appData.editing_version.id, editorEnvironment.id);
|
||||||
|
if (!isPublicAccess) {
|
||||||
|
const envFromQueryParams = mode === 'view' && new URLSearchParams(location?.search)?.get('env');
|
||||||
|
useStore.getState().init(appData.editing_version?.id || appData.current_version_id, envFromQueryParams);
|
||||||
|
fetchGlobalDataSources(
|
||||||
|
appData.organization_id,
|
||||||
|
appData.editing_version?.id || appData.current_version_id,
|
||||||
|
editorEnvironment.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
useStore.getState().updateEditingVersion(appData.editing_version?.id || appData.current_version_id); //check if this is needed
|
||||||
|
updateReleasedVersionId(appData.current_version_id);
|
||||||
|
|
||||||
|
setEditorLoading(false);
|
||||||
|
initialLoadRef.current = false;
|
||||||
|
// only show if app is not created from prompt
|
||||||
|
if (showWalkthrough) initEditorWalkThrough();
|
||||||
|
checkAndSetTrueBuildSuggestionsFlag();
|
||||||
|
return () => {
|
||||||
|
document.title = retrieveWhiteLabelText();
|
||||||
|
};
|
||||||
|
});
|
||||||
}, [setApp, setEditorLoading, currentSession]);
|
}, [setApp, setEditorLoading, currentSession]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import { Constants } from '@/_helpers/utils';
|
||||||
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
|
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
|
||||||
import Sharepoint from '@/_components/Sharepoint';
|
import Sharepoint from '@/_components/Sharepoint';
|
||||||
import AccordionForm from './AccordionForm';
|
import AccordionForm from './AccordionForm';
|
||||||
|
import { generateCypressDataCy } from '../modules/common/helpers/cypressHelpers';
|
||||||
|
|
||||||
const DynamicForm = ({
|
const DynamicForm = ({
|
||||||
schema,
|
schema,
|
||||||
|
|
@ -534,7 +535,7 @@ const DynamicForm = ({
|
||||||
const labelElement = (
|
const labelElement = (
|
||||||
<label
|
<label
|
||||||
className="form-label"
|
className="form-label"
|
||||||
data-cy={`label-${String(label).toLowerCase().replace(/\s+/g, '-')}`}
|
data-cy={`label-${generateCypressDataCy(label)}`}
|
||||||
style={{ textDecoration: tooltip ? 'underline 2px dashed' : 'none', textDecorationColor: 'var(--slate8)' }}
|
style={{ textDecoration: tooltip ? 'underline 2px dashed' : 'none', textDecorationColor: 'var(--slate8)' }}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
|
@ -572,7 +573,7 @@ const DynamicForm = ({
|
||||||
'd-flex': isHorizontalLayout,
|
'd-flex': isHorizontalLayout,
|
||||||
'dynamic-form-row': isHorizontalLayout,
|
'dynamic-form-row': isHorizontalLayout,
|
||||||
})}
|
})}
|
||||||
data-cy={`${key.replace(/_/g, '-')}-section`}
|
data-cy={`${generateCypressDataCy(key)}-section`}
|
||||||
key={key}
|
key={key}
|
||||||
>
|
>
|
||||||
{!isSpecificComponent && (
|
{!isSpecificComponent && (
|
||||||
|
|
@ -628,7 +629,7 @@ const DynamicForm = ({
|
||||||
<Element
|
<Element
|
||||||
{...getElementProps(obj[key])}
|
{...getElementProps(obj[key])}
|
||||||
{...computedProps[propertyKey]}
|
{...computedProps[propertyKey]}
|
||||||
data-cy={`${String(label).toLocaleLowerCase().replace(/\s+/g, '-')}-text-field`}
|
data-cy={`${generateCypressDataCy(label)}-text-field`}
|
||||||
dataCy={obj[key].key.replace(/_/g, '-')}
|
dataCy={obj[key].key.replace(/_/g, '-')}
|
||||||
//to be removed after whole ui is same
|
//to be removed after whole ui is same
|
||||||
isHorizontalLayout={isHorizontalLayout}
|
isHorizontalLayout={isHorizontalLayout}
|
||||||
|
|
@ -663,15 +664,16 @@ const DynamicForm = ({
|
||||||
{(flipComponentDropdown.label || isHorizontalLayout) && (
|
{(flipComponentDropdown.label || isHorizontalLayout) && (
|
||||||
<label
|
<label
|
||||||
className={cx('form-label')}
|
className={cx('form-label')}
|
||||||
data-cy={`${String(flipComponentDropdown.label)
|
data-cy={`${generateCypressDataCy(flipComponentDropdown.label)}-dropdown-label`}
|
||||||
.toLocaleLowerCase()
|
|
||||||
.replace(/\s+/g, '-')}-dropdown-label`}
|
|
||||||
>
|
>
|
||||||
{flipComponentDropdown.label}
|
{flipComponentDropdown.label}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div data-cy={`${String(flipComponentDropdown.label).toLocaleLowerCase().replace(/\s+/g, '-')}-select-dropdown`} className={cx({ 'flex-grow-1': isHorizontalLayout })}>
|
<div
|
||||||
|
data-cy={`${generateCypressDataCy(flipComponentDropdown.label)}-select-dropdown`}
|
||||||
|
className={cx({ 'flex-grow-1': isHorizontalLayout })}
|
||||||
|
>
|
||||||
<Select
|
<Select
|
||||||
{...getElementProps(flipComponentDropdown)}
|
{...getElementProps(flipComponentDropdown)}
|
||||||
styles={computeSelectStyles ? computeSelectStyles('100%') : {}}
|
styles={computeSelectStyles ? computeSelectStyles('100%') : {}}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { canDeleteDataSource, canUpdateDataSource } from '@/_helpers';
|
||||||
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
|
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
|
||||||
import { orgEnvironmentVariableService, orgEnvironmentConstantService } from '../_services';
|
import { orgEnvironmentVariableService, orgEnvironmentConstantService } from '../_services';
|
||||||
import { Constants } from '@/_helpers/utils';
|
import { Constants } from '@/_helpers/utils';
|
||||||
|
import { generateCypressDataCy } from '../modules/common/helpers/cypressHelpers.js';
|
||||||
|
|
||||||
const DynamicFormV2 = ({
|
const DynamicFormV2 = ({
|
||||||
schema,
|
schema,
|
||||||
|
|
@ -437,7 +438,7 @@ const DynamicFormV2 = ({
|
||||||
const labelElement = (
|
const labelElement = (
|
||||||
<label
|
<label
|
||||||
className="form-label"
|
className="form-label"
|
||||||
data-cy={`label-${String(label).toLowerCase().replace(/\s+/g, '-')}`}
|
data-cy={`label-${generateCypressDataCy(label)}`}
|
||||||
style={{ textDecoration: tooltip ? 'underline 2px dashed' : 'none', textDecorationColor: 'var(--slate8)' }}
|
style={{ textDecoration: tooltip ? 'underline 2px dashed' : 'none', textDecorationColor: 'var(--slate8)' }}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
|
@ -475,6 +476,7 @@ const DynamicFormV2 = ({
|
||||||
'd-flex': isHorizontalLayout,
|
'd-flex': isHorizontalLayout,
|
||||||
'dynamic-form-row': isHorizontalLayout,
|
'dynamic-form-row': isHorizontalLayout,
|
||||||
})}
|
})}
|
||||||
|
data-cy={`${generateCypressDataCy(key)}-section`}
|
||||||
key={key}
|
key={key}
|
||||||
>
|
>
|
||||||
{!isSpecificComponent && (
|
{!isSpecificComponent && (
|
||||||
|
|
@ -505,7 +507,8 @@ const DynamicFormV2 = ({
|
||||||
<Element
|
<Element
|
||||||
{...getElementProps(uiProperties[key])}
|
{...getElementProps(uiProperties[key])}
|
||||||
{...computedProps[propertyKey]}
|
{...computedProps[propertyKey]}
|
||||||
data-cy={`${String(label).toLocaleLowerCase().replace(/\s+/g, '-')}-text-field`}
|
data-cy={`${generateCypressDataCy(label)}-text-field`}
|
||||||
|
dataCy={uiProperties[key].key.replace(/_/g, '-')}
|
||||||
//to be removed after whole ui is same
|
//to be removed after whole ui is same
|
||||||
isHorizontalLayout={isHorizontalLayout}
|
isHorizontalLayout={isHorizontalLayout}
|
||||||
/>
|
/>
|
||||||
|
|
@ -539,15 +542,16 @@ const DynamicFormV2 = ({
|
||||||
{(flipComponentDropdown.label || isHorizontalLayout) && (
|
{(flipComponentDropdown.label || isHorizontalLayout) && (
|
||||||
<label
|
<label
|
||||||
className={cx('form-label')}
|
className={cx('form-label')}
|
||||||
data-cy={`${String(flipComponentDropdown.label)
|
data-cy={`${generateCypressDataCy(flipComponentDropdown.label)}-dropdown-label`}
|
||||||
.toLocaleLowerCase()
|
|
||||||
.replace(/\s+/g, '-')}-dropdown-label`}
|
|
||||||
>
|
>
|
||||||
{flipComponentDropdown.label}
|
{flipComponentDropdown.label}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div data-cy={'query-select-dropdown'} className={cx({ 'flex-grow-1': isHorizontalLayout })}>
|
<div
|
||||||
|
data-cy={`${generateCypressDataCy(flipComponentDropdown.label)}-select-dropdown`}
|
||||||
|
className={cx({ 'flex-grow-1': isHorizontalLayout })}
|
||||||
|
>
|
||||||
<Select {...getElementProps(flipComponentDropdown)} styles={{}} useCustomStyles={false} />
|
<Select {...getElementProps(flipComponentDropdown)} styles={{}} useCustomStyles={false} />
|
||||||
</div>
|
</div>
|
||||||
{flipComponentDropdown.helpText && (
|
{flipComponentDropdown.helpText && (
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,7 @@ export default ({
|
||||||
return (
|
return (
|
||||||
<div className="table-content-wrapper">
|
<div className="table-content-wrapper">
|
||||||
{options.length === 0 && (
|
{options.length === 0 && (
|
||||||
<div className="empty-key-value"
|
<div className="empty-key-value" data-cy="label-empty-key-value">
|
||||||
data-cy="label-empty-key-value">
|
|
||||||
<InfoIcon style={{ width: '16px', marginRight: '5px' }} />
|
<InfoIcon style={{ width: '16px', marginRight: '5px' }} />
|
||||||
<span>There are no key value pairs added</span>
|
<span>There are no key value pairs added</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -86,7 +85,7 @@ export default ({
|
||||||
|
|
||||||
<div className="d-flex mb-2" style={{ height: '16px' }}>
|
<div className="d-flex mb-2" style={{ height: '16px' }}>
|
||||||
<ButtonSolid
|
<ButtonSolid
|
||||||
data-cy={`${dataCy}-add-more-button`}
|
data-cy={`${dataCy}-add-button`}
|
||||||
variant="ghostBlue"
|
variant="ghostBlue"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => addNewKeyValuePair(options)}
|
onClick={() => addNewKeyValuePair(options)}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import NumberInput from './NumberInput';
|
||||||
import TextInput from './TextInput';
|
import TextInput from './TextInput';
|
||||||
import { HelperMessage, InputLabel, ValidationMessage } from '../InputUtils/InputUtils';
|
import { HelperMessage, InputLabel, ValidationMessage } from '../InputUtils/InputUtils';
|
||||||
import { ButtonSolid } from '../../../../_components/AppButton';
|
import { ButtonSolid } from '../../../../_components/AppButton';
|
||||||
|
import { generateCypressDataCy } from '../../../../modules/common/helpers/cypressHelpers.js';
|
||||||
|
|
||||||
const CommonInput = ({ label, helperText, disabled, required, onChange: change, ...restProps }) => {
|
const CommonInput = ({ label, helperText, disabled, required, onChange: change, ...restProps }) => {
|
||||||
const { type, encrypted, validation, isValidatedMessages, isDisabled } = restProps;
|
const { type, encrypted, validation, isValidatedMessages, isDisabled } = restProps;
|
||||||
|
|
@ -65,13 +66,14 @@ const CommonInput = ({ label, helperText, disabled, required, onChange: change,
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
onClick={toggleEditing}
|
onClick={toggleEditing}
|
||||||
|
data-cy={`button-${generateCypressDataCy(isEditing ? 'Cancel' : 'Edit')}`}
|
||||||
>
|
>
|
||||||
{isEditing ? 'Cancel' : 'Edit'}
|
{isEditing ? 'Cancel' : 'Edit'}
|
||||||
</ButtonSolid>
|
</ButtonSolid>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-auto mb-2">
|
<div className="col-auto mb-2">
|
||||||
<small className="text-green">
|
<small className="text-green" data-cy="encrypted-text">
|
||||||
<img className="mx-2 encrypted-icon" src="assets/images/icons/padlock.svg" width="12" height="12" />
|
<img className="mx-2 encrypted-icon" src="assets/images/icons/padlock.svg" width="12" height="12" />
|
||||||
Encrypted
|
Encrypted
|
||||||
</small>
|
</small>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { Label } from '../../Label/Label';
|
||||||
import ValidationIcon from './ValidationIcon';
|
import ValidationIcon from './ValidationIcon';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import HelperIcon from './HelperIcon';
|
import HelperIcon from './HelperIcon';
|
||||||
|
import { generateCypressDataCy } from '../../../../modules/common/helpers/cypressHelpers.js';
|
||||||
|
|
||||||
export const ValidationMessage = ({ response, validationMessage, className }) => (
|
export const ValidationMessage = ({ response, validationMessage, className }) => (
|
||||||
<div className={cn('tw-flex tw-pl-[2px] tw-items-start tw-my-[2px]', className)}>
|
<div className={cn('tw-flex tw-pl-[2px] tw-items-start tw-my-[2px]', className)}>
|
||||||
|
|
@ -14,7 +15,7 @@ export const ValidationMessage = ({ response, validationMessage, className }) =>
|
||||||
type="helper"
|
type="helper"
|
||||||
size="default"
|
size="default"
|
||||||
className={`tw-font-normal ${response === true ? 'tw-text-text-success' : '!tw-text-text-warning'}`}
|
className={`tw-font-normal ${response === true ? 'tw-text-text-success' : '!tw-text-text-warning'}`}
|
||||||
data-cy="validation-label"
|
data-cy={`${generateCypressDataCy(validationMessage)}-validation-label`}
|
||||||
>
|
>
|
||||||
{validationMessage}
|
{validationMessage}
|
||||||
</Label>
|
</Label>
|
||||||
|
|
@ -53,7 +54,7 @@ export const InputLabel = ({ disabled, label, required }) => (
|
||||||
type="label"
|
type="label"
|
||||||
size="default"
|
size="default"
|
||||||
className={`tw-font-medium tw-mb-[2px] ${disabled ? 'tw-text-text-disabled' : ''}`}
|
className={`tw-font-medium tw-mb-[2px] ${disabled ? 'tw-text-text-disabled' : ''}`}
|
||||||
data-cy="input-field-label"
|
data-cy={`${generateCypressDataCy(label)}-field-label`}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
{required && <RequiredIndicator disabled={disabled} />}
|
{required && <RequiredIndicator disabled={disabled} />}
|
||||||
|
|
|
||||||
6
frontend/src/modules/common/helpers/cypressHelpers.js
Normal file
6
frontend/src/modules/common/helpers/cypressHelpers.js
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
export function generateCypressDataCy(text) {
|
||||||
|
return String(text)
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9]+/g, "-")
|
||||||
|
.replace(/^-+|-+$/g, "");
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,7 @@ import './dataSourceManager.theme.scss';
|
||||||
import { canUpdateDataSource } from '@/_helpers';
|
import { canUpdateDataSource } from '@/_helpers';
|
||||||
import DataSourceSchemaManager from '@/_helpers/dataSourceSchemaManager';
|
import DataSourceSchemaManager from '@/_helpers/dataSourceSchemaManager';
|
||||||
import MultiEnvTabs from './MultiEnvTabs';
|
import MultiEnvTabs from './MultiEnvTabs';
|
||||||
|
import { generateCypressDataCy } from '../../../common/helpers/cypressHelpers';
|
||||||
|
|
||||||
class DataSourceManagerComponent extends React.Component {
|
class DataSourceManagerComponent extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|
@ -1127,7 +1128,11 @@ class DataSourceManagerComponent extends React.Component {
|
||||||
<div className="row w-100">
|
<div className="row w-100">
|
||||||
<div className="alert alert-danger" role="alert">
|
<div className="alert alert-danger" role="alert">
|
||||||
{validationError.map((error, index) => (
|
{validationError.map((error, index) => (
|
||||||
<div key={index} className="text-muted" data-cy="connection-alert-text">
|
<div
|
||||||
|
key={index}
|
||||||
|
className="text-muted"
|
||||||
|
data-cy={`${generateCypressDataCy(error)}-field-alert-text`}
|
||||||
|
>
|
||||||
{error}
|
{error}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue