Merge branch 'main' into release/marketplace-sprint-12

This commit is contained in:
Ganesh Kumar 2025-06-26 12:42:23 +05:30
commit c7faf6b1df
578 changed files with 36803 additions and 55066 deletions

View file

@ -33,7 +33,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Set up Git authentication for private submodules
run: |
@ -160,9 +160,9 @@ jobs:
name: screenshots-appbuilder-${{ matrix.edition }}
path: cypress-tests/cypress/screenshots
# Cypress-App-builder-Subpath:
# Cypress-App-builder-Subpath:
# 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')
# steps:

View file

@ -37,21 +37,9 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.ref }}
# Create Docker Buildx builder with platform configuration
- name: Set up Docker Buildx
run: |
mkdir -p ~/.docker/cli-plugins
curl -SL https://github.com/docker/buildx/releases/download/v0.11.0/buildx-v0.11.0.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
chmod a+x ~/.docker/cli-plugins/docker-buildx
docker buildx create --name mybuilder --platform linux/arm64,linux/amd64
docker buildx use mybuilder
- name: Set DOCKER_CLI_EXPERIMENTAL
run: echo "DOCKER_CLI_EXPERIMENTAL=enabled" >> $GITHUB_ENV
- name: use mybuilder buildx
run: docker buildx use mybuilder
- name: Docker Login
uses: docker/login-action@v2
with:
@ -228,7 +216,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Set up Git authentication for private submodules
run: |
@ -364,7 +352,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Set up Git authentication for private submodules
run: |
@ -512,7 +500,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Set up Git authentication for private submodules
run: |

109
.github/workflows/merging-pr.yml vendored Normal file
View file

@ -0,0 +1,109 @@
name: Merge Submodule PRs
on:
pull_request:
types: [closed, labeled]
jobs:
merge-submodules:
if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
runs-on: ubuntu-latest
steps:
- name: Extract Branch Name
run: echo "BRANCH_NAME=${{ github.event.pull_request.head.ref }}" >> $GITHUB_ENV
- name: Merge PR in ee-server (if exists)
run: |
PR=$(gh pr list -R ToolJet/ee-server --head "$BRANCH_NAME" --state open --json number -q '.[0].number')
if [ -n "$PR" ]; then
echo "Found ee-server PR: #$PR"
gh pr merge -R ToolJet/ee-server "$PR" --merge --admin
else
echo "No open ee-server PR for branch $BRANCH_NAME"
fi
env:
GH_TOKEN: ${{ secrets.TOKEN_PR }}
- name: Merge PR in ee-frontend (if exists)
run: |
PR=$(gh pr list -R ToolJet/ee-frontend --head "$BRANCH_NAME" --state open --json number -q '.[0].number')
if [ -n "$PR" ]; then
echo "Found ee-frontend PR: #$PR"
gh pr merge -R ToolJet/ee-frontend "$PR" --merge --admin
else
echo "No open ee-frontend PR for branch $BRANCH_NAME"
fi
env:
GH_TOKEN: ${{ secrets.TOKEN_PR }}
update-submodule-sha:
needs: merge-submodules
if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
runs-on: ubuntu-latest
steps:
- name: Checkout base repo
uses: actions/checkout@v4
with:
repository: ToolJet/ToolJet
token: ${{ secrets.TOKEN_PR }}
ref: main
submodules: recursive
- name: Update submodules to latest main
run: |
git config user.name "adishM98 Bot"
git config user.email "adish.madhu@gmail.com"
git submodule update --remote frontend/ee
git submodule update --remote server/ee
git add frontend/ee server/ee
if git diff --cached --quiet; then
echo "No submodule updates found."
else
git commit -m "🔄 chore: update submodules to latest main after auto-merge"
git push origin main
fi
env:
GH_TOKEN: ${{ secrets.TOKEN_PR }}
check-submodule-prs:
if: github.event.action == 'labeled' && github.event.label.name == 'ready-to-merge'
runs-on: ubuntu-latest
steps:
- name: Extract Branch Name
run: echo "BRANCH_NAME=${{ github.event.pull_request.head.ref }}" >> $GITHUB_ENV
- name: Check and Comment Linked Submodule PRs
run: |
echo "🔍 Checking linked submodule PRs for \`$BRANCH_NAME\`:" > comment.md
echo "" >> comment.md
SERVER_URL=$(gh pr list -R ToolJet/ee-server --head "$BRANCH_NAME" --state open --json url -q '.[0].url')
FRONTEND_URL=$(gh pr list -R ToolJet/ee-frontend --head "$BRANCH_NAME" --state open --json url -q '.[0].url')
if [ -n "$SERVER_URL" ]; then
echo "✅ ee-server PR - $SERVER_URL" >> comment.md
else
echo "❌ No open PR in ee-server" >> comment.md
fi
if [ -n "$FRONTEND_URL" ]; then
echo "✅ ee-frontend PR - $FRONTEND_URL" >> comment.md
else
echo "❌ No open PR in ee-frontend" >> comment.md
fi
echo "" >> comment.md
echo "📝 **Note**: The submodule PRs will be auto-merged once you merge this base PR-$PR_NUMBER into \`main\`." >> comment.md
gh pr comment "$PR_NUMBER" --repo ToolJet/ToolJet --body-file comment.md
env:
GH_TOKEN: ${{ secrets.TOKEN_PR }}
PR_NUMBER: ${{ github.event.pull_request.number }}

View file

@ -24,10 +24,10 @@ jobs:
with:
ref: refs/heads/main
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix frontend install
@ -75,10 +75,10 @@ jobs:
with:
ref: refs/heads/main
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix server install
@ -106,7 +106,7 @@ jobs:
- name: Send Slack Notification
run: |
message="### Periodic Security Audit Report Of Server directory\n
message="Periodic Security Audit Report Of Server directory\n
Node module vulnerabilities summary:\n
🔴 Critical: ${{ steps.parse-audit.outputs.critical }}\n
🟠 High: ${{ steps.parse-audit.outputs.high }}\n
@ -126,10 +126,10 @@ jobs:
with:
ref: refs/heads/main
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix marketplace install
@ -177,10 +177,10 @@ jobs:
with:
ref: refs/heads/main
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix plugins install
@ -228,10 +228,10 @@ jobs:
with:
ref: refs/heads/main
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix cypress-tests install
@ -279,10 +279,10 @@ jobs:
with:
ref: refs/heads/main
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm install
@ -330,10 +330,10 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix frontend install
@ -385,10 +385,10 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix server install
@ -440,10 +440,10 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix marketplace install
@ -494,10 +494,10 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix plugins install
@ -550,10 +550,10 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm --prefix cypress-tests install
@ -606,10 +606,10 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Use Node.js 18.18.2
- name: Use Node.js 22.15.1
uses: actions/setup-node@v3
with:
node-version: 18.18.2
node-version: 22.15.1
- name: Install dependencies
run: npm install
@ -648,4 +648,4 @@ jobs:
🟠 High: ${{ steps.parse-audit.outputs.high }}
🟡 Moderate: ${{ steps.parse-audit.outputs.moderate }}
Please find the JSON file in the [summary page](${{ github.root_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).
Please find the JSON file in the [summary page](${{ github.root_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).

View file

@ -1 +1 @@
3.14.0
3.15.1

View file

@ -8,8 +8,8 @@
"typescript",
"typescriptreact"
],
"eslint.format.enable": true,
"editor.formatOnSave": true,
"eslint.format.enable": false,
"editor.formatOnSave": false,
"json.schemas": [
{
"fileMatch": [

View file

@ -76,8 +76,9 @@ module.exports = defineConfig({
experimentalRunAllSpecs: true,
baseUrl: "http://localhost:8082",
specPattern: [
"cypress/e2e/happyPath/appbuilder/commonTestcases/newSuits/**/*.cy.js",
// "cypress/e2e/happyPath/appbuilder/ceTestcases/**/*.cy.js"
// "cypress/e2e/happyPath/appbuilder/commonTestcases/newSuits/**/*.cy.js",
// "cypress/e2e/happyPath/appbuilder/ceTestcases/**/*.cy.js",
"cypress/e2e/happyPath/appbuilder/commonTestcases/newSuits/globalSetingsHappyPath.cy.js"
],
numTestsKeptInMemory: 1,
redirectionLimit: 7,

View file

@ -98,7 +98,7 @@ module.exports = defineConfig({
configFile: environment.configFile,
specPattern: [
"cypress/e2e/happyPath/platform/firstUser/firstUserOnboarding.cy.js",
"cypress/e2e/happyPath/platform/commonTestcases/**/*.cy.js",
"cypress/e2e/happyPath/platform/commonTestcases/userManagment/*.cy.js",
"cypress/e2e/happyPath/platform/eeTestcases/**/*.cy.js",
],
numTestsKeptInMemory: 1,

View file

@ -1,4 +1,4 @@
FROM node:18.18.2-buster AS builder
FROM node:22.15.1 AS builder
# Fix for JS heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
@ -50,10 +50,11 @@ ENV TOOLJET_EDITION=ee
COPY ./server/package.json ./server/package-lock.json ./server/
RUN npm --prefix server install
COPY ./server/ ./server/
RUN npm install -g @nestjs/cli
RUN npm install -g @nestjs/cli
RUN npm install -g copyfiles
RUN npm --prefix server run build
FROM node:18.18.2-bullseye
FROM node:22.15.1
RUN apt-get update -yq \
&& apt-get install curl wget gnupg zip -yq \

View file

@ -221,21 +221,21 @@ Cypress.Commands.add(
const requestBody =
envVar === "Enterprise"
? {
email: userEmail,
firstName: userName,
groups: [],
lastName: "",
role: userRole,
userMetadata: metaData,
}
email: userEmail,
firstName: userName,
groups: [],
lastName: "",
role: userRole,
userMetadata: metaData,
}
: {
email: userEmail,
firstName: userName,
groups: [],
lastName: "",
role: userRole,
userMetadata: metaData,
};
email: userEmail,
firstName: userName,
groups: [],
lastName: "",
role: userRole,
userMetadata: metaData,
};
cy.getCookie("tj_auth_token").then((cookie) => {
cy.request(
@ -509,7 +509,7 @@ Cypress.Commands.add("apiDeleteGranularPermission", (groupName) => {
// Delete the granular permission
cy.request({
method: "DELETE",
url: `${Cypress.env("server_host")}/api/v2/group-permissions/granular-permissions/${granularPermissionId}`,
url: `${Cypress.env("server_host")}/api/v2/group-permissions/granular-permissions/app/${granularPermissionId}`,
headers,
log: false,
}).then((deleteResponse) => {

View file

@ -11,7 +11,7 @@ import { selectAppCardOption } from "Support/utils/common";
const API_ENDPOINT =
Cypress.env("environment") === "Community"
? "/api/library_apps"
: "/api/library_apps/";
: "/api/library_apps";
Cypress.Commands.add(
"appUILogin",
@ -226,9 +226,9 @@ Cypress.Commands.add(
.invoke("text")
.then((text) => {
cy.wrap(subject).realType(createBackspaceText(text)),
{
delay: 0,
};
{
delay: 0,
};
});
}
);
@ -548,7 +548,7 @@ Cypress.Commands.add("installMarketplacePlugin", (pluginName) => {
}
});
function installPlugin(pluginName) {
function installPlugin (pluginName) {
cy.get('[data-cy="-list-item"]').eq(1).click();
cy.wait(1000);
@ -621,3 +621,12 @@ Cypress.Commands.add(
.and("have.text", `${fieldName} is required`);
}
);
Cypress.Commands.add('ifEnv', (expectedEnvs, callback) => {
const actualEnv = Cypress.env("environment");
const envArray = Array.isArray(expectedEnvs) ? expectedEnvs : [expectedEnvs];
if (envArray.includes(actualEnv)) {
callback();
}
});

View file

@ -18,7 +18,7 @@ export const commonSelectors = {
canvas: "[data-cy=real-canvas]",
appCardOptionsButton: "[data-cy=app-card-menu-icon]",
autoSave: "[data-cy=autosave-indicator]",
nameInputFieldd: "[data-cy=name-input-field]",
inputFieldName: "[data-cy=name-input-field]",
valueInputFieldd: "[data-cy=value-input-field]",
skipButton: ".driver-close-btn",
skipInstallationModal: "[data-cy=skip-button]",
@ -353,7 +353,7 @@ export const commonWidgetSelector = {
buttonCloseEditorSideBar: "[data-cy='inspector-close-icon']",
buttonStylesEditorSideBar: "#inspector-tab-styles",
WidgetNameInputField: "[data-cy=edit-widget-name]",
constantInspectorIcon: '[data-cy="inspector-node-constants"] > .node-key',
constantInspectorIcon: '[data-cy="inspector-constants-expand-button"]',
inspectorIcon: '[data-cy="left-sidebar-inspect-button"]',
tooltipInputField: "[data-cy='tooltip-input-field']",
tooltipLabel: "[id=button-tooltip]",

View file

@ -0,0 +1,202 @@
import { cyParamName } from "./common";
export const commonEeSelectors = {
instanceSettingIcon: '[data-cy="instance-settings-option"]',
auditLogIcon: '[data-cy="audit-log-option"]',
cancelButton: '[data-cy="cancel-button"]',
saveButton: '[data-cy="save-button"]',
pageTitle: '[data-cy="dashboard-section-header"]',
modalTitle: '[data-cy="modal-title"]',
modalCloseButton: '[data-cy="modal-close-button"]',
saveButton: '[data-cy="save-button"]',
cardTitle: '[data-cy="card-title"]',
AddQueryButton: '[data-cy="show-ds-popover-button"]',
promoteButton: '[data-cy="promote-button"]',
settingsIcon: '[data-cy="icon-settings"]',
gitSyncIcon: '[data-cy="git-sync-icon"]',
confirmButton: '[data-cy="confirm-button"]',
importFromGit: '[data-cy="import-from-git-button"]',
searchBar: '[data-cy="query-manager-search-bar"]',
nameHeader: '[data-cy="name-header"]',
modalMessage: '[data-cy="modal-message"]',
paginationSection: '[data-cy="pagination-section"]',
};
export const ssoEeSelector = {
oidc: '[data-cy="openid-connect-sso-card"]',
statusLabel: '[data-cy="status-label"]',
oidcToggle: '[data-cy="openid-toggle-input"] > .slider',
oidcPageElements: {
oidcToggleLabel: '[data-cy="openid-toggle-label"]',
nameLabel: '[data-cy="name-label"]',
clientIdLabel: '[data-cy="client-id-label"]',
clientSecretLabel: '[data-cy="client-secret-label"]',
encryptedLabel: '[data-cy="encripted-label"]',
WellKnownUrlLabel: '[data-cy="well-known-url-label"]',
// redirectUrlLabel: '[data-cy="redirect-url-label"]',
},
nameInput: '[data-cy="name-input"]',
clientIdInput: '[data-cy="client-id-input"]',
clientSecretInput: '[data-cy="client-secret-input"]',
WellKnownUrlInput: '[data-cy="well-known-url-input"]',
redirectUrl: '[data-cy="redirect-url"]',
copyIcon: '[data-cy="copy-icon]',
oidcSSOText: '[data-cy="oidc-sso-button-text"]',
oidcSSOIcon: '[data-cy="oidc-so-icon"]',
ldapPageElements: {
ldapToggleLabel: '[data-cy="ldap-toggle-label"]',
nameLabel: '[data-cy="name-label"]',
hostLabel: '[data-cy="host-label"]',
portLabel: '[data-cy="port-label"]',
baseDnLabel: '[data-cy="base-dn-label"]',
baseDnHelperText: '[data-cy="base-dn-helper-text"]',
sslLabel: '[data-cy="ssl-label"]',
},
ldapToggle: '[data-cy="ldap-toggle-input"] > .slider',
hostInput: '[data-cy="host-input"]',
portInput: '[data-cy="port-input"]',
baseDnInput: '[data-cy="base-dn-input"]',
sslToggleInput: '[data-cy="ssl-toggle-input"]',
ldapSSOText: '[data-cy="ldap-sso-button-text"]',
userNameInputLabel: '[data-cy="user-name-input-label"]',
passwordInputLabel: '[data-cy="password-label"]',
passwordInputField: '[data-cy="password-input-field"]',
samlModalElements: {
toggleLabel: '[data-cy="saml-toggle-label"]',
NameLabel: '[data-cy="name-label"]',
metaDataLabel: '[data-cy="idp-metadata-label"]',
baseDNHelperText: '[data-cy="base-dn-helper-text"]',
groupAttributeLabel: '[data-cy="group-attribute-label"]',
groupAttributeHelperText: '[data-cy="group-attribute-helper-text"]',
}
};
export const eeGroupsSelector = {
resourceDs: '[data-cy="resource-datasources"]',
dsCreateCheck: '[data-cy="checkbox-create-ds"]',
dsDeleteCheck: '[data-cy="checkbox-delete-ds"]',
datasourceLink: '[data-cy="datasource-link"]',
dsSearch: '[data-cy="datasource-select-search"]',
AddDsButton: '[data-cy="datasource-add-button"]',
dsNameHeader: '[data-cy="datasource-name-header"]',
};
export const instanceSettingsSelector = {
allUsersTab: '[data-cy="all-users-list-item"]',
manageInstanceSettings: '[data-cy="manage-instance-settings-list-item"]',
typeColumnHeader: '[data-cy="users-table-type-column-header"]',
workspaceColumnHeader: '[data-cy="users-table-workspaces-column-header"]',
userName: (userName) => {
return `[data-cy="${cyParamName(userName)}-user-name"]`;
},
userEmail: (userName) => {
return `[data-cy="${cyParamName(userName)}-user-email"]`;
},
userType: (userName) => {
return `[data-cy="${cyParamName(userName)}-user-type"]`;
},
userStatus: (userName) => {
return `[data-cy="${cyParamName(userName)}-user-status"]`;
},
viewButton: (userName) => {
return `[data-cy="${cyParamName(userName)}-user-view-button"]`;
},
editButton: (userName) => {
return `[data-cy="${cyParamName(userName)}-user-edit-button"]`;
},
viewModalNoColumnHeader: '[data-cy="number-column-header"]',
viewModalNameColumnHeader: '[data-cy="name-column-header"]',
viewModalStatusColumnHeader: '[data-cy="status-column-header"]',
archiveAllButton: '[data-cy="archive-all-button"]',
viewModalRow: (workspaceName) => {
return `[data-cy="${cyParamName(workspaceName)}-workspace-row"]>`;
},
workspaceName: (workspaceName) => {
return `[data-cy="${cyParamName(workspaceName)}-workspace-name"]`;
},
userStatusChangeButton: '[data-cy="user-state-change-button"]',
superAdminToggle: '[data-cy="super-admin-form-check-input"]',
superAdminToggleLabel: '[data-cy="super-admin-form-check-label"]',
allowWorkspaceToggle: '[data-cy="form-check-input"]',
allowWorkspaceToggleLabel: '[data-cy="form-check-label"]',
allowWorkspaceHelperText: '[data-cy="instance-settings-help-text"]',
allWorkspaceTab: '[data-cy="all-workspaces-list-item"]',
};
export const multiEnvSelector = {
envContainer: '[data-cy="env-container"]',
currentEnvName: '[data-cy="list-current-env-name"]',
envArrow: '[data-cy="env-arrow"]',
selectedEnvName: '[data-cy="selected-current-env-name"]',
envNameList: '[data-cy="env-name-list"]',
appVersionLabel: '[data-cy="app-version-label"]',
currentVersion: '[data-cy="current-version"]',
createNewVersionButton: '[data-cy="create-new-version-button"]',
fromLabel: '[data-cy="from-label"]',
toLabel: '[data-cy="to-label"]',
currEnvName: '[data-cy="current-env-name"]',
targetEnvName: '[data-cy="target-env-name"]',
stagingLabel: '[data-cy="staging-label"]',
productionLabel: '[data-cy="production-label"]',
};
export const whiteLabellingSelectors = {
whiteLabelList: '[data-cy="white-labelling-list-item"]',
appLogoLabel: '[data-cy="app-logo-label"]',
appLogoInput: '[data-cy="input-field-app-logo"]',
appLogoHelpText: '[data-cy="app-logo-help-text"]',
pageTitleLabel: '[data-cy="page-title-label"]',
pageTitleInput: '[data-cy="input-field-page-title"]',
pageTitleHelpText: '[data-cy="page-title-help-text"]',
favIconLabel: '[data-cy="fav-icon-label"]',
favIconInput: '[data-cy="input-field-fav-icon"]',
favIconHelpText: '[data-cy="fav-icon-help-text"]',
};
export const gitSyncSelector = {
gitCommitInput: '[data-cy="git-commit-input"]',
commitHelperText: '[data-cy="commit-helper-text"]',
gitRepoInput: '[data-cy="git-repo-input"]',
commitMessageInput: '[data-cy="commit-message-input"]',
lastCommitInput: '[data-cy="las-commit-message"]',
lastCommitVersion: '[data-cy="last-commit-version"]',
autherInfo: '[data-cy="auther-info"]',
commitButton: '[data-cy="commit-button"]',
gitSyncToggleInput: '[data-cy="git-sync-toggle-input"]',
gitSyncApphelperText: '[data-cy="sync-app-helper-text"]',
connectRepoButton: '[data-cy="connect-repo-button"]',
toggleMessage: '[data-cy="toggle-message"]',
sshInput: '[data-cy="git-ssh-input"]',
generateSshButton: '[data-cy="generate-ssh-key-button"',
sshInputHelperText: '[data-cy="git-ssh-input-helper-text"]',
configDeleteButton: '[data-cy="button-config-delete"]',
testConnectionButton: '[data-cy="test-connection-button"]',
sshKey: '[data-cy="ssh-key"]',
deployKeyHelperText: '[data-cy="deploy-key-helper-text"]',
gitRepoLink: '[data-cy="git-repo-link"]',
appNameField: '[data-cy="app-name-field"]',
gitRepoInfo: '[data-cy="git-repo-info"]',
pullButton: '[data-cy="pull-button"]'
}
export const workspaceSelector = {
activelink: '[data-cy="active-link"]',
archivedLik: '[data-cy="archived-link"]',
userStatusChange: '[data-cy="button-user-status-change"]',
workspaceStatusChange: '[data-cy="button-ws-status-change"]',
switchWsModalTitle: '[data-cy="switch-modal-title"]',
switchWsModalMessage: '[data-cy="switch-modal-message"]',
workspaceName: (workspaceName) => {
return `[data-cy="${workspaceName}-workspace-name"]`
},
workspaceInput: (workspaceName) => {
return `[data-cy="${workspaceName}-workspace-input"]`
},
}

View file

@ -40,7 +40,7 @@ export const groupsSelector = {
resourceLabel: '[data-cy="resource-label"]',
allAppsRadio: '[data-cy="all-apps-radio"]',
allAppsLabel: '[data-cy="all-apps-label"]',
allAppsHelperText: '[data-cy="all-apps-info-text"]',
allAppsHelperText: '[data-cy="this-will-select-all-apps-in-the-workspace-including-any-new-apps-created-info-text"]',
customradio: '[data-cy="custom-radio"]',
customLabel: '[data-cy="custom-label"]',
customHelperText: '[data-cy="custom-info-text"]',

View file

@ -54,8 +54,8 @@ export const onboardingSelectors = {
basicPlanTitle: '[data-cy="basic-plan-title"]',
planPrice: '[data-cy="plan-price"]',
pricePeriod: '[data-cy="price-period"]',
flexibleTitle: '[data-cy="flexible-title"]',
businessTitle: '[data-cy="business-title"]',
flexibleTitle: '[data-cy="pro-title"]',
businessTitle: '[data-cy="team-title"]',
enterpriseTitle: '[data-cy="enterprise-title"]',
customPricingHeader: '[data-cy="custom-pricing-header"]',
noCreditCardBanner: '[data-cy="no-credit-card-banner"]',

View file

@ -0,0 +1,75 @@
export const commonEeText = {
cancelButton: "Cancel",
saveButton: "Save changes",
closeButton: "Close",
defaultWorkspace: "My workspace",
};
export const ssoEeText = {
statusLabel: "Disabled",
enabledLabel: "Enabled",
disabledLabel: "Disabled",
oidcPageElements: {
oidcToggleLabel: "OpenID Connect",
nameLabel: "Name",
clientIdLabel: "Client ID",
clientSecretLabel: "Client secretEncrypted",
encryptedLabel: "Encrypted",
WellKnownUrlLabel: "Well known URL",
// redirectUrlLabel: "Redirect URL",
},
oidcEnabledToast: "Enabled OpenId SSO",
oidcDisabledToast: "Disabled OpenId SSO",
oidcUpdatedToast: "updated SSO configurations",
testName: "Tooljet OIDC",
testclientId: "24567098-mklj8t20za1smb2if.apps.googleusercontent.com",
testclientSecret: "2345-client-id-.apps.googleusercontent.com",
testWellknownUrl: "google.com",
oidcSSOText: "Sign in with Tooljet OIDC",
ldapPageElements: {
ldapToggleLabel: "LDAP",
nameLabel: "Name",
hostLabel: "Host name",
portLabel: "Port",
baseDnLabel: "Base DN",
baseDnHelperText: "Location without UID or CN",
sslLabel: "SSL",
},
ldapSSOText: "Sign in with Tooljet LDAP Auth",
userNameInputLabel: "Username",
samlModalElements: {
toggleLabel: "SAML",
NameLabel: "Name",
metaDataLabel: "Identity provider metadata",
baseDNHelperText:
"Ensure the Identity provider metadata is in XML format. You can download it from your IdP's site",
groupAttributeLabel: "Group attribute",
groupAttributeHelperText:
"Define attribute for user-to-group mapping based on the IdP",
},
};
export const eeGroupsText = {
resourceDs: "Datasources",
AddDsButton: "Add",
dsNameHeader: "Datasource name",
};
export const instanceSettingsText = {
pageTitle: "Settings",
allUsersTab: "All users",
manageInstanceSettings: "Manage instance settings",
typeColumnHeader: "Type",
workspaceColumnHeader: "Workspaces",
superAdminType: "instance",
viewModalTitle: "Workspaces of The Developer",
archiveAllButton: "Archive All",
archiveState: "Archive",
editModalTitle: "Edit user details",
superAdminToggleLabel: "Super admin",
allowWorkspaceToggleLabel: "Allow personal workspace",
allowWorkspaceHelperText:
"This feature will enable users to create their own workspace",
saveButton: "Save",
untitledWorkspace: "Untitled workspace",
};

View file

@ -78,7 +78,7 @@ export const groupsText = {
allAppsLabel: 'All apps',
allAppsHelperText: 'This will select all apps in the workspace including any new apps created',
customLabel: 'Custom',
customHelperText: 'Select specific applications you want to add to the group',
customHelperText: 'Select specific apps you want to add to the group',
updateButtonText: 'Update',
addButtonText: 'Add',
userRole: 'User role',

View file

@ -59,4 +59,9 @@ export const ssoText = {
alertText: "Danger zone",
disablePasswordHelperText:
"Disable password login only if your SSO is configured otherwise you will get locked out",
disablePasswordHelperText:
"Disable password login only if your SSO is configured otherwise you will get locked out",
toggleUpdateToast: (toggle) => {
return `Saved ${toggle} SSO configurations`
}
};

View file

@ -23,8 +23,8 @@ export const onboardingText = {
endUserPriceText: "$10",
comparePlansText: "Compare plans",
basicPlanText: "Basic Plan",
flexibleText: "Flexible",
businessText: "Business",
flexibleText: "Pro",
businessText: "Team",
enterpriseText: "Enterprise",
customPricingText: "Custom pricing",
noCreditCardText: "No credit card required!",

View file

@ -1,34 +1,5 @@
import { fake } from "Fixtures/fake";
import { textInputText } from "Texts/textInput";
import { commonWidgetText, widgetValue, customValidation } from "Texts/common";
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import { buttonText } from "Texts/button";
import {
verifyControlComponentAction,
randomString,
} from "Support/utils/editor/textInput";
import {
openAccordion,
verifyAndModifyParameter,
openEditorSidebar,
verifyAndModifyToggleFx,
addDefaultEventHandler,
verifyComponentValueFromInspector,
selectColourFromColourPicker,
verifyBoxShadowCss,
verifyLayout,
verifyTooltip,
editAndVerifyWidgetName,
verifyPropertiesGeneralAccordion,
verifyStylesGeneralAccordion,
randomNumber,
closeAccordions,
} from "Support/utils/commonWidget";
import {
selectCSA,
selectEvent,
addSupportCSAData,
} from "Support/utils/events";
import { commonWidgetSelector } from "Selectors/common";
describe("Editor title", () => {
const data = {};
@ -42,10 +13,10 @@ describe("Editor title", () => {
afterEach(() => {
cy.apiDeleteApp();
});
it("should verify titles", () => {
it.skip("should verify titles", () => {
cy.url().should("include", "/tooljets-workspace");
// cy.title().should("eq", "Dashboard | ToolJet");
cy.title().should("eq", "ToolJet");
cy.title().should("eq", "Dashboard | ToolJet");
// cy.title().should("eq", "ToolJet");
cy.log(data.appName);
@ -57,7 +28,7 @@ describe("Editor title", () => {
cy.url().should("include", `/applications/${Cypress.env("appId")}`);
// cy.title().should("eq", `${data.appName} | ToolJet`);
// cy.title().should("eq", `Preview - ${data.appName} | ToolJet`);
cy.title().should("eq", `Preview - ${data.appName} | ToolJet`);
cy.go("back");
cy.releaseApp();

View file

@ -5,7 +5,7 @@ import {
verifyCSA
} from "Support/utils/editor/textInput";
import { addMultiEventsWithAlert } from "Support/utils/events";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyValue } from "Support/utils/inspector";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyNodeData } from "Support/utils/inspector";
describe('Button Component Tests', () => {
@ -75,22 +75,21 @@ describe('Button Component Tests', () => {
cy.apiLogin();
cy.apiCreateApp(`${fake.companyName}-Button-App`);
cy.openApp();
cy.dragAndDropWidget("Button", 50, 50);
cy.dragAndDropWidget("Button", 500, 500);
cy.get('[data-cy="query-manager-toggle-button"]').click();
});
it('should verify all the exposed values on inspector', () => {
cy.get(commonWidgetSelector.sidebarinspector).click();
cy.get(".tooltip-inner").invoke("hide");
openNode("components");
openAndVerifyNode("button1", exposedValues, verifyValue);
verifyNodes(functions, verifyfunctions);
openAndVerifyNode("button1", exposedValues, verifyNodeData);
verifyNodes(functions, verifyNodeData);
//id is pending
});
it.skip('should verify all the events from the button', () => {
it('should verify all the events from the button', () => {
const events = [
{ event: "On hover", message: "On hover Event" },
{ event: "On Click", message: "On Click Event" },

View file

@ -5,7 +5,7 @@ import {
verifyCSA
} from "Support/utils/editor/textInput";
import { addMultiEventsWithAlert } from "Support/utils/events";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyValue } from "Support/utils/inspector";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyNodeData } from "Support/utils/inspector";
describe('Checkbox Component Tests', () => {
@ -83,7 +83,7 @@ describe('Checkbox Component Tests', () => {
cy.apiLogin();
cy.apiCreateApp(`${fake.companyName}-Checkbox-App`);
cy.openApp();
cy.dragAndDropWidget("Checkbox", 50, 50);
cy.dragAndDropWidget("Checkbox", 500, 500);
cy.get('[data-cy="query-manager-toggle-button"]').click();
});
@ -92,8 +92,8 @@ describe('Checkbox Component Tests', () => {
cy.get(".tooltip-inner").invoke("hide");
openNode("components");
openAndVerifyNode("checkbox1", exposedValues, verifyValue);
verifyNodes(functions, verifyfunctions);
openAndVerifyNode("checkbox1", exposedValues, verifyNodeData);
verifyNodes(functions, verifyNodeData);
//id is pending
});

View file

@ -5,7 +5,7 @@ import {
verifyCSA
} from "Support/utils/editor/textInput";
import { addMultiEventsWithAlert } from "Support/utils/events";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyValue } from "Support/utils/inspector";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyNodeData } from "Support/utils/inspector";
describe('Dropdown Component Tests', () => {
@ -101,7 +101,7 @@ describe('Dropdown Component Tests', () => {
cy.get(".tooltip-inner").invoke("hide");
openNode("components");
openAndVerifyNode("dropdown1", exposedValues, verifyValue);
openAndVerifyNode("dropdown1", exposedValues, verifyNodeData);
verifyNodes(functions, verifyfunctions);
//id is pending

View file

@ -15,7 +15,7 @@ import { deleteDownloadsFolder } from "Support/utils/common";
import {
resizeQueryPanel
} from "Support/utils/dataSource";
import { openNode, verifyNodeData, verifyValue } from "Support/utils/inspector";
import { openNode, verifyNodeData } from "Support/utils/inspector";
import {
addNewPage
} from "Support/utils/multipage";
@ -49,11 +49,11 @@ describe("Global Actions", () => {
verifyNodeData("variables", "Object", "1 entry ");
openNode("variables", 0);
verifyValue("var", "String", `"test"`);
verifyNodeData("var", "String", `"test"`);
openNode("page");
openNode("variables", 1);
verifyValue("pageVar", "String", `"pageTest"`);
verifyNodeData("pageVar", "String", `"pageTest"`);
addInputOnQueryField(
"runjs",

View file

@ -5,7 +5,7 @@ import {
verifyCSA
} from "Support/utils/editor/textInput";
import { addMultiEventsWithAlert } from "Support/utils/events";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyValue } from "Support/utils/inspector";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyNodeData } from "Support/utils/inspector";
describe('Multiselect Component Tests', () => {
@ -104,7 +104,7 @@ describe('Multiselect Component Tests', () => {
cy.get(".tooltip-inner").invoke("hide");
openNode("components");
openAndVerifyNode("multiselect1", exposedValues, verifyValue);
openAndVerifyNode("multiselect1", exposedValues, verifyNodeData);
verifyNodes(functions, verifyfunctions);
//id is pending

View file

@ -5,7 +5,7 @@ import {
verifyCSA
} from "Support/utils/editor/textInput";
import { addMultiEventsWithAlert } from "Support/utils/events";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyValue } from "Support/utils/inspector";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyNodeData } from "Support/utils/inspector";
describe('Number Input Component Tests', () => {
@ -86,7 +86,7 @@ describe('Number Input Component Tests', () => {
cy.apiLogin();
cy.apiCreateApp(`${fake.companyName}-Numberinput-App`);
cy.openApp();
cy.dragAndDropWidget("Number Input", 50, 50);
cy.dragAndDropWidget("Number Input", 500, 500);
cy.get('[data-cy="query-manager-toggle-button"]').click();
});
@ -95,8 +95,8 @@ describe('Number Input Component Tests', () => {
cy.get(".tooltip-inner").invoke("hide");
openNode("components");
openAndVerifyNode("numberinput1", exposedValues, verifyValue);
verifyNodes(functions, verifyfunctions);
openAndVerifyNode("numberinput1", exposedValues, verifyNodeData);
verifyNodes(functions, verifyNodeData);
//id is pending
});

View file

@ -5,7 +5,7 @@ import {
verifyCSA
} from "Support/utils/editor/textInput";
import { addMultiEventsWithAlert } from "Support/utils/events";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyValue } from "Support/utils/inspector";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyNodeData } from "Support/utils/inspector";
describe('Password Input Component Tests', () => {
@ -95,7 +95,7 @@ describe('Password Input Component Tests', () => {
cy.get(".tooltip-inner").invoke("hide");
openNode("components");
openAndVerifyNode("passwordinput1", exposedValues, verifyValue);
openAndVerifyNode("passwordinput1", exposedValues, verifyNodeData);
verifyNodes(functions, verifyfunctions);
//id is pending

View file

@ -5,7 +5,7 @@ import {
verifyCSA
} from "Support/utils/editor/textInput";
import { addMultiEventsWithAlert } from "Support/utils/events";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyValue } from "Support/utils/inspector";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyNodeData } from "Support/utils/inspector";
describe('Text Input Component Tests', () => {
@ -27,14 +27,14 @@ describe('Text Input Component Tests', () => {
"key": "setBlur",
"type": "Function"
},
{
"key": "disable",
"type": "Function"
},
{
"key": "visibility",
"type": "Function"
},
// {
// "key": "disable",
// "type": "Function"
// },
// {
// "key": "visibility",
// "type": "Function"
// },
{
"key": "setVisibility",
"type": "Function"
@ -94,17 +94,17 @@ describe('Text Input Component Tests', () => {
cy.apiLogin();
cy.apiCreateApp(`${fake.companyName}-Textinput-App`);
cy.openApp();
cy.dragAndDropWidget("Text Input", 50, 50);
cy.dragAndDropWidget("Text Input", 500, 500);
cy.get('[data-cy="query-manager-toggle-button"]').click();
});
it.skip('should verify all the exposed values on inspector', () => {
it('should verify all the exposed values on inspector', () => {
cy.get(commonWidgetSelector.sidebarinspector).click();
cy.get(".tooltip-inner").invoke("hide");
openNode("components");
openAndVerifyNode("textinput1", exposedValues, verifyValue);
verifyNodes(functions, verifyfunctions);
openAndVerifyNode("textinput1", exposedValues, verifyNodeData);
verifyNodes(functions, verifyNodeData);
//id is pending
});

View file

@ -5,7 +5,7 @@ import {
verifyCSA
} from "Support/utils/editor/textInput";
import { addMultiEventsWithAlert } from "Support/utils/events";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyValue } from "Support/utils/inspector";
import { openAndVerifyNode, openNode, verifyfunctions, verifyNodes, verifyNodeData } from "Support/utils/inspector";
describe('ToggleSwitch Component Tests', () => {
@ -88,7 +88,7 @@ describe('ToggleSwitch Component Tests', () => {
cy.get(".tooltip-inner").invoke("hide");
openNode("components");
openAndVerifyNode("toggleswitch1", exposedValues, verifyValue);
openAndVerifyNode("toggleswitch1", exposedValues, verifyNodeData);
verifyNodes(functions, verifyfunctions);
//id is pending

View file

@ -10,7 +10,7 @@ import {
selectColourFromColourPicker,
verifyWidgetColorCss,
} from "Support/utils/commonWidget";
import { verifyNodeData, openNode, verifyValue } from "Support/utils/inspector";
// import { verifyNodeData, openNode, verifyNodeData } from "Support/utils/inspector";
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import {
commonText,

View file

@ -3,7 +3,7 @@ import { commonWidgetSelector } from "Selectors/common";
import { multipageSelector } from "Selectors/multipage";
import { addSupportCSAData, selectEvent } from "Support/utils/events";
import { createNewVersion } from "Support/utils/exportImport";
import { deleteComponentFromInspector, openNode, verifyNodeData, verifyValue, verifyNodes, openAndVerifyNode } from "Support/utils/inspector";
import { deleteComponentFromInspector, openNode, verifyNodeData, verifyNodes, openAndVerifyNode } from "Support/utils/inspector";
import { addNewPage } from "Support/utils/multipage";
import { navigateToCreateNewVersionModal } from "Support/utils/version";
import testData from "Fixtures/inspectorItems.json";
@ -20,15 +20,15 @@ describe("Editor- Inspector", () => {
cy.viewport(1800, 1800);
});
it("should verify the values of inspector", () => {
it.skip("should verify the values of inspector", () => {
cy.get(commonWidgetSelector.sidebarinspector).click();
cy.get(".tooltip-inner").invoke("hide");
openAndVerifyNode("globals", testData.globalsNodes, verifyNodeData);
openAndVerifyNode("currentUser", testData.currentUserNodes, verifyValue);
openAndVerifyNode("theme", testData.themeNodes, verifyValue);
openAndVerifyNode("mode", testData.modeNodes, verifyValue);
openAndVerifyNode("urlparams", testData.urlparamsNode, verifyValue);
openAndVerifyNode("currentUser", testData.currentUserNodes, verifyNodeData);
openAndVerifyNode("theme", testData.themeNodes, verifyNodeData);
openAndVerifyNode("mode", testData.modeNodes, verifyNodeData);
openAndVerifyNode("urlparams", testData.urlparamsNode, verifyNodeData);
if (Cypress.env("environment") !== "Community") {
const ssoUserInfoNode = '[data-cy="inspector-node-ssouserinfo"]';
@ -39,7 +39,7 @@ describe("Editor- Inspector", () => {
openNode("theme");
openNode("environment");
verifyValue("name", "String", `"development"`);
verifyNodeData("name", "String", `"development"`);
cy.get(`${inspectorNodeId} > .node-key`).should("have.text", "id");
}
@ -92,7 +92,7 @@ describe("Editor- Inspector", () => {
cy.get(commonWidgetSelector.draggableWidget("button3")).click();
cy.get(commonWidgetSelector.sidebarinspector).click();
openAndVerifyNode("variables", testData.variablesNodes, verifyValue);
openAndVerifyNode("variables", testData.variablesNodes, verifyNodeData);
cy.forceClickOnCanvas()
cy.wait(500)
@ -101,9 +101,9 @@ describe("Editor- Inspector", () => {
// openNode("page");
openAndVerifyNode("page", testData.testPageNodes, verifyValue);
openAndVerifyNode("page", testData.testPageNodes, verifyNodeData);
openNode("variables", 1);
verifyValue("pageVar", "String", `"pageVar"`);
verifyNodeData("pageVar", "String", `"pageVar"`);
openAndVerifyNode("components", testData.componentsNodes, verifyNodeData);
@ -111,10 +111,10 @@ describe("Editor- Inspector", () => {
cy.get(commonWidgetSelector.draggableWidget("button1")).click();
cy.get(commonWidgetSelector.sidebarinspector).click();
openAndVerifyNode("page", testData.pageNodes, verifyValue);
openAndVerifyNode("page", testData.pageNodes, verifyNodeData);
openNode("globals");
openNode("urlparams");
verifyValue("key", "String", `"value"`);
verifyNodeData("key", "String", `"value"`);
cy.get(`[data-cy="inspector-node-key"] > .mx-1`)
.realHover()

View file

@ -104,6 +104,7 @@ describe("Chaining of queries", () => {
cy.wait(1000)
cy.get('[data-cy="query-tab-setup"]').click();
cy.wait(1500);
openEditorSidebar(buttonText.defaultWidgetName);
selectEvent("On Click", "Run Query", 0, `[data-cy="add-event-handler"]`, 0);
cy.wait(500);
@ -122,7 +123,7 @@ describe("Chaining of queries", () => {
// cy.verifyToastMessage(commonSelectors.toastMessage, "Hello World");
});
it.skip("should verify query duplication", () => {
it("should verify query duplication", () => {
const data = {};
let dsName = fake.companyName;
@ -146,6 +147,7 @@ describe("Chaining of queries", () => {
chainQuery("runjs", "runpy");
addSuccessNotification("runjs");
cy.wait(1500);
openEditorSidebar(buttonText.defaultWidgetName);
selectEvent("On Click", "Run Query", 0, `[data-cy="add-event-handler"]`, 0);
cy.wait(500);
@ -170,6 +172,8 @@ describe("Chaining of queries", () => {
"have.text",
"runjs_copy "
);
cy.get('[data-cy="query-tab-settings"]').click();
cy.get('[data-cy="notification-on-success-toggle-switch"]').should(
"have.value",
"on"
@ -184,7 +188,7 @@ describe("Chaining of queries", () => {
});
cy.get(
`[data-cy="action-selection"] > .select-search > .react-select__control > .react-select__value-container > `
).should("have.text", "Run Query");
).should("have.text", "Run query");
cy.get('[data-cy="query-selection-field"]').should("have.text", "runpy");
});
});

View file

@ -23,7 +23,7 @@ import {
resizeQueryPanel,
verifypreview
} from "Support/utils/dataSource";
import { openNode, verifyValue } from "Support/utils/inspector";
import { openNode, verifyNodeData } from "Support/utils/inspector";
describe("RunJS", () => {
beforeEach(() => {
@ -42,15 +42,15 @@ describe("RunJS", () => {
selectQueryFromLandingPage("runjs", "JavaScript");
addInputOnQueryField("runjs", "return true");
query("preview");
query("run");
verifypreview("raw", "true");
query("run");
cy.get(commonWidgetSelector.sidebarinspector).click();
cy.get(".tooltip-inner").invoke("hide");
openNode("queries");
openNode("runjs1");
verifyValue("data", "Boolean", "true");
verifyValue("rawData", "Boolean", "true");
verifyNodeData("data", "Boolean", "true");
verifyNodeData("rawData", "Boolean", "true");
cy.apiDeleteApp();
});
@ -60,11 +60,11 @@ describe("RunJS", () => {
selectQueryFromLandingPage("runjs", "JavaScript");
addInputOnQueryField("runjs", "return [page.handle,page.name]");
query("preview");
query("run");
verifypreview("raw", `["home","Home"]`);
addInputOnQueryField("runjs", "return globals.theme");
query("preview");
query("run");
verifypreview("raw", `{"name":"light"}`);
// addInputOnQueryField("runjs", "return globals.currentUser");

View file

@ -24,7 +24,7 @@ import {
resizeQueryPanel,
verifypreview
} from "Support/utils/dataSource";
import { openNode, verifyNodeData, verifyValue } from "Support/utils/inspector";
import { openNode, verifyNodeData } from "Support/utils/inspector";
import {
addNewPage
} from "Support/utils/multipage";
@ -54,8 +54,8 @@ describe("runpy", () => {
cy.get(".tooltip-inner").invoke("hide");
openNode("queries");
openNode("runpy1");
verifyValue("data", "Boolean", "true");
verifyValue("rawData", "Boolean", "true");
verifyNodeData("data", "Boolean", "true");
verifyNodeData("rawData", "Boolean", "true");
cy.apiDeleteApp();
});
@ -76,11 +76,11 @@ actions.setPageVariable('pageVar', 'pageTest')`
verifyNodeData("variables", "Object", "1 entry ");
openNode("variables", 0);
verifyValue("var", "String", `"test"`);
verifyNodeData("var", "String", `"test"`);
openNode("page");
openNode("variables", 1);
verifyValue("pageVar", "String", `"pageTest"`);
verifyNodeData("pageVar", "String", `"pageTest"`);
addInputOnQueryField(
"runpy",

View file

@ -337,7 +337,7 @@ describe("Data source Rest API", () => {
`cypress-${data.dataSourceName}-restapi`,
"restapi",
[
{ key: "url", value: Cypress.env("restAPI_BaseURL") },
{ key: "url", value: "https://jsonplaceholder.typicode.com" },
{ key: "auth_type", value: "none" },
{ key: "grant_type", value: "authorization_code" },
{ key: "add_token_to", value: "header" },
@ -370,62 +370,100 @@ describe("Data source Rest API", () => {
cy.apiCreateApp(`${fake.companyName}-restAPI-CURD-App`);
cy.openApp();
createAndRunRestAPIQuery({
queryName: "get_beeceptor_data",
queryName: "get_all_users",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "GET",
urlSuffix: "/api/users",
urlSuffix: "/users",
run: true,
expectedResponseShape: {
"0.id": true,
"0.name": true,
"0.email": true,
},
});
createAndRunRestAPIQuery({
queryName: "post_restapi",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "POST",
headersList: [["Content-Type", "application/json"]],
rawBody: '{"price": 200,"name": "Violin"}',
urlSuffix: "/api/users",
expectedResponseShape: { price: 200, name: "Violin", id: true },
rawBody: `{
"name": "Test User",
"username": "testuser",
"email": "test@example.com",
"address": {
"street": "123 Test St",
"city": "Testville",
"zipcode": "12345"
}
}`,
urlSuffix: "/users",
run: true,
expectedResponseShape: {
id: true,
name: "Test User",
email: "test@example.com",
},
});
cy.readFile("cypress/fixtures/restAPI/storedId.json").then(
(postResponseID) => {
const id1 = postResponseID.id;
const id1 = 1;
createAndRunRestAPIQuery({
queryName: "put_restapi_id",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "PUT",
headersList: [["Content-Type", "application/json"]],
rawBody: '{"price": 500,"name": "Guitar"}',
urlSuffix: `/api/users/${id1}`,
expectedResponseShape: { price: 500, name: "Guitar", id: id1 },
});
createAndRunRestAPIQuery({
queryName: "patch_restapi_id",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "PATCH",
headersList: [["Content-Type", "application/json"]],
rawBody: '{"price": 999 }',
urlSuffix: `/api/users/${id1}`,
run: true,
expectedResponseShape: { price: 999, id: id1 },
});
createAndRunRestAPIQuery({
queryName: "get_restapi_id",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "GET",
urlSuffix: `/api/users/${id1}`,
run: true,
expectedResponseShape: { price: 999, name: "Guitar", id: id1 },
});
createAndRunRestAPIQuery({
queryName: "delete_restapi_id",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "DELETE",
urlSuffix: `/api/users/${id1}`,
run: true,
expectedResponseShape: { success: true },
});
}
);
createAndRunRestAPIQuery({
queryName: "put_restapi_id",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "PUT",
headersList: [["Content-Type", "application/json"]],
rawBody: `{
"id": 1,
"name": "Fully Updated User",
"username": "updateduser",
"email": "updated@example.com",
"address": {
"street": "456 Updated St",
"city": "Updatedville",
"zipcode": "54321"
}
}`,
urlSuffix: `/users/${id1}`,
run: true,
expectedResponseShape: {
id: id1,
name: "Fully Updated User",
email: "updated@example.com",
},
});
createAndRunRestAPIQuery({
queryName: "patch_restapi_id",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "PATCH",
headersList: [["Content-Type", "application/json"]],
rawBody: `{
"email": "partially.updated@example.com"
}`,
urlSuffix: `/users/${id1}`,
run: true,
expectedResponseShape: {
id: id1,
email: "partially.updated@example.com",
},
});
createAndRunRestAPIQuery({
queryName: "get_restapi_id",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "GET",
urlSuffix: `/users/${id1}`,
run: true,
expectedResponseShape: {
id: id1,
email: "Sincere@april.biz",
},
});
createAndRunRestAPIQuery({
queryName: "delete_restapi_id",
dsName: `cypress-${data.dataSourceName}-restapi`,
method: "DELETE",
urlSuffix: `/users/${id1}`,
run: true,
expectedResponseShape: {},
});
cy.apiDeleteApp(`${fake.companyName}-restAPI-CURD-App`);
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-restapi`);
});

View file

@ -5,213 +5,214 @@ import { commonText } from "Texts/common";
import { exportAppModalText } from "Texts/exportImport";
import {
clickOnExportButtonAndVerify,
exportAllVersionsAndVerify,
verifyElementsOfExportModal,
clickOnExportButtonAndVerify,
exportAllVersionsAndVerify,
verifyElementsOfExportModal,
} from "Support/utils/exportImport";
import { selectAppCardOption, closeModal } from "Support/utils/common";
describe("App Export", () => {
const TEST_DATA = {
appFiles: {
multiVersion: "cypress/fixtures/templates/three-versions.json",
singleVersion: "cypress/fixtures/templates/one_version.json",
},
};
const TEST_DATA = {
appFiles: {
multiVersion: "cypress/fixtures/templates/three-versions.json",
singleVersion: "cypress/fixtures/templates/one_version.json",
},
};
let data;
let data;
data = {
workspaceName: fake.firstName,
workspaceSlug: fake.firstName.toLowerCase().replace(/\s+/g, "-"),
appName: `${fake.companyName}-IE-App`,
appReName: `${fake.companyName}-${fake.companyName}-IE-App`,
dsName: fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""),
};
beforeEach(() => {
data = {
workspaceName: fake.firstName,
workspaceSlug: fake.firstName.toLowerCase().replace(/\s+/g, "-"),
appName: `${fake.companyName}-IE-App`,
appReName: `${fake.companyName}-${fake.companyName}-IE-App`,
dsName: fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""),
workspaceName: fake.firstName,
workspaceSlug: fake.firstName.toLowerCase().replace(/\s+/g, "-"),
appName: `${fake.companyName}-IE-App`,
appReName: `${fake.companyName}-${fake.companyName}-IE-App`,
dsName: fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""),
};
cy.exec("mkdir -p ./cypress/downloads/");
cy.exec("cd ./cypress/downloads/ && rm -rf *");
cy.exec("mkdir -p ./cypress/downloads/");
cy.wait(3000);
beforeEach(() => {
data = {
workspaceName: fake.firstName,
workspaceSlug: fake.firstName.toLowerCase().replace(/\s+/g, "-"),
appName: `${fake.companyName}-IE-App`,
appReName: `${fake.companyName}-${fake.companyName}-IE-App`,
dsName: fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""),
};
cy.exec("mkdir -p ./cypress/downloads/");
cy.wait(3000);
cy.apiLogin();
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
cy.apiLogout();
});
cy.apiLogin();
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
cy.apiLogout();
});
it("Verify the elements of export dialog box", () => {
cy.skipWalkthrough();
it("Verify the elements of export dialog box", () => {
cy.skipWalkthrough()
cy.apiLogin();
cy.visit(`${data.workspaceSlug}`);
cy.get(importSelectors.importOptionInput)
.eq(0)
.selectFile(TEST_DATA.appFiles.multiVersion, { force: true });
cy.wait(2000);
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(importSelectors.importAppButton).click();
cy.wait(3000);
cy.backToApps();
cy.apiLogin();
cy.visit(`${data.workspaceSlug}`);
cy.get(importSelectors.importOptionInput)
.eq(0)
.selectFile(TEST_DATA.appFiles.multiVersion, {
force: true,
});
cy.wait(1500);
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(importSelectors.importAppButton).click();
cy.wait(3000);
cy.backToApps();
// Select the app card option to export the app
selectAppCardOption(
data.appName,
commonSelectors.appCardOptions(commonText.exportAppOption)
);
// Select the app card option to export the app
selectAppCardOption(
data.appName,
commonSelectors.appCardOptions(commonText.exportAppOption)
// Verify the elements of the export modal
verifyElementsOfExportModal("v3", ["v2", "v1"], [true, false, false]);
// Close the modal
closeModal(exportAppModalText.modalCloseButton);
// Ensure the modal title is no longer visible
cy.get(
commonSelectors.modalTitle(exportAppModalText.selectVersionTitle)
).should("not.exist");
// Re-open the export modal and click the export button
cy.wait(2000);
selectAppCardOption(
data.appName,
commonSelectors.appCardOptions(commonText.exportAppOption)
);
clickOnExportButtonAndVerify(exportAppModalText.exportAll, data.appName);
cy.exec("ls ./cypress/downloads/").then((result) => {
const downloadedAppExportFileName = result.stdout.split("\n")[0];
const filePath = `./cypress/downloads/${downloadedAppExportFileName}`;
// Ensure the file name contains the expected app export name
expect(downloadedAppExportFileName).to.contain(
data.appName.toLowerCase()
);
// Read and validate the exported JSON file
cy.readFile(filePath).then((appData) => {
// Validate the app name
const appNameFromFile = appData.app[0].definition.appV2.name;
expect(appNameFromFile).to.equal(data.appName);
// Validate the schema for the student table in tooljetdb
const tooljetDatabase = appData.tooljet_database.find(
(db) => db.table_name === "student"
);
expect(tooljetDatabase).to.exist;
expect(tooljetDatabase.schema).to.exist;
// Validate components and queries
const components = appData.app[0].definition.appV2.components;
const text2Component = components.find(
(component) => component.name === "text2"
);
expect(text2Component).to.exist;
expect(text2Component.properties.text.value).to.equal(
"{{constants.pageHeader}}"
);
// Verify the elements of the export modal
verifyElementsOfExportModal("v3", ["v2", "v1"], [true, false, false]);
// Close the modal
closeModal(exportAppModalText.modalCloseButton);
// Ensure the modal title is no longer visible
cy.get(
commonSelectors.modalTitle(exportAppModalText.selectVersionTitle)
).should("not.exist");
// Re-open the export modal and click the export button
selectAppCardOption(
data.appName,
commonSelectors.appCardOptions(commonText.exportAppOption)
const textinput1 = components.find(
(component) => component.name === "textinput1"
);
clickOnExportButtonAndVerify(exportAppModalText.exportAll, data.appName);
expect(textinput1).to.exist;
expect(textinput1.properties.value.value).to.include("queries");
cy.exec("ls ./cypress/downloads/").then((result) => {
const downloadedAppExportFileName = result.stdout.split("\n")[0];
const filePath = `./cypress/downloads/${downloadedAppExportFileName}`;
// Ensure the file name contains the expected app export name
expect(downloadedAppExportFileName).to.contain(
data.appName.toLowerCase()
);
// Read and validate the exported JSON file
cy.readFile(filePath).then((appData) => {
// Validate the app name
const appNameFromFile = appData.app[0].definition.appV2.name;
expect(appNameFromFile).to.equal(data.appName);
// Validate the schema for the student table in tooljetdb
const tooljetDatabase = appData.tooljet_database.find(
(db) => db.table_name === "student"
);
expect(tooljetDatabase).to.exist;
expect(tooljetDatabase.schema).to.exist;
// Validate components and queries
const components = appData.app[0].definition.appV2.components;
const text2Component = components.find(
(component) => component.name === "text2"
);
expect(text2Component).to.exist;
expect(text2Component.properties.text.value).to.equal(
"{{constants.pageHeader}}"
);
const textinput1 = components.find(
(component) => component.name === "textinput1"
);
expect(textinput1).to.exist;
expect(textinput1.properties.value.value).to.include("queries");
const textinput2 = components.find(
(component) => component.name === "textinput2"
);
expect(textinput2).to.exist;
expect(textinput2.properties.value.value).to.include("queries");
const textinput3 = components.find(
(component) => component.name === "textinput3"
);
expect(textinput3).to.exist;
expect(textinput3.properties.value.value).to.include("queries");
// Validate the data queries
const dataQueries = appData.app[0].definition.appV2.dataQueries;
const postgresqlQuery = dataQueries.find(
(query) => query.name === "postgresql1"
);
expect(postgresqlQuery).to.exist;
expect(postgresqlQuery.options.query).to.include(
"Select * from {{secrets.db_name}}"
);
const restapiQuery = dataQueries.find(
(query) => query.name === "restapi1"
);
expect(restapiQuery).to.exist;
expect(restapiQuery.options.url).to.equal(
"https://jsonplaceholder.typicode.com/users/1"
);
const tooljetdbQuery = dataQueries.find(
(query) => query.name === "tooljetdb1"
);
expect(tooljetdbQuery).to.exist;
expect(tooljetdbQuery.options.operation).to.equal("list_rows");
// Ensure appVersions exists
const appVersions = appData.app[0].definition.appV2.appVersions;
expect(appVersions).to.exist;
// Map and verify app version names
const versionNames = appVersions.map((version) => version.name);
expect(versionNames).to.include.members(["v1", "v2", "v3"]);
});
});
cy.exec("cd ./cypress/downloads/ && rm -rf *");
selectAppCardOption(
data.appName,
commonSelectors.appCardOptions(commonText.exportAppOption)
const textinput2 = components.find(
(component) => component.name === "textinput2"
);
cy.get(`[data-cy="v1-radio-button"]`).check();
cy.get(
commonSelectors.buttonSelector(exportAppModalText.exportSelectedVersion)
).click();
expect(textinput2).to.exist;
expect(textinput2.properties.value.value).to.include("queries");
cy.exec("ls ./cypress/downloads/").then((result) => {
const downloadedAppExportFileName = result.stdout.split("\n")[0];
const filePath = `./cypress/downloads/${downloadedAppExportFileName}`;
const textinput3 = components.find(
(component) => component.name === "textinput3"
);
expect(textinput3).to.exist;
expect(textinput3.properties.value.value).to.include("queries");
// Ensure the file name contains the expected app export name
expect(downloadedAppExportFileName).to.contain(
data.appName.toLowerCase()
);
// Validate the data queries
const dataQueries = appData.app[0].definition.appV2.dataQueries;
// Read and validate the exported JSON file
cy.readFile(filePath).then((appData) => {
// Validate the app name
const appNameFromFile = appData.app[0].definition.appV2.name;
expect(appNameFromFile).to.equal(data.appName);
});
});
const postgresqlQuery = dataQueries.find(
(query) => query.name === "postgresql1"
);
expect(postgresqlQuery).to.exist;
expect(postgresqlQuery.options.query).to.include(
"Select * from {{secrets.db_name}}"
);
const restapiQuery = dataQueries.find(
(query) => query.name === "restapi1"
);
expect(restapiQuery).to.exist;
expect(restapiQuery.options.url).to.equal(
"https://jsonplaceholder.typicode.com/users/1"
);
const tooljetdbQuery = dataQueries.find(
(query) => query.name === "tooljetdb1"
);
expect(tooljetdbQuery).to.exist;
expect(tooljetdbQuery.options.operation).to.equal("list_rows");
// Ensure appVersions exists
const appVersions = appData.app[0].definition.appV2.appVersions;
expect(appVersions).to.exist;
// Map and verify app version names
const versionNames = appVersions.map((version) => version.name);
expect(versionNames).to.include.members(["v1", "v2", "v3"]);
});
});
it.skip("Verify 'Export app' functionality of an application inside app editor", () => {
data.appName2 = `${fake.companyName}-App`;
cy.apiCreateApp(data.appName2);
cy.openApp(data.appName2);
cy.exec("cd ./cypress/downloads/ && rm -rf *");
cy.dragAndDropWidget("Text Input", 50, 50);
selectAppCardOption(
data.appName,
commonSelectors.appCardOptions(commonText.exportAppOption)
);
cy.get(`[data-cy="v1-radio-button"]`).check();
cy.get(
commonSelectors.buttonSelector(exportAppModalText.exportSelectedVersion)
).click();
cy.get('[data-cy="left-sidebar-settings-button"]').click();
cy.get('[data-cy="button-user-status-change"]').click();
cy.exec("ls ./cypress/downloads/").then((result) => {
const downloadedAppExportFileName = result.stdout.split("\n")[0];
const filePath = `./cypress/downloads/${downloadedAppExportFileName}`;
verifyElementsOfExportModal("v1");
// Ensure the file name contains the expected app export name
expect(downloadedAppExportFileName).to.contain(
data.appName.toLowerCase()
);
exportAllVersionsAndVerify(data.appName1, "v1");
// Read and validate the exported JSON file
cy.readFile(filePath).then((appData) => {
// Validate the app name
const appNameFromFile = appData.app[0].definition.appV2.name;
expect(appNameFromFile).to.equal(data.appName);
});
});
});
it.skip("Verify 'Export app' functionality of an application inside app editor", () => {
data.appName2 = `${fake.companyName}-App`;
cy.apiCreateApp(data.appName2);
cy.openApp(data.appName2);
cy.dragAndDropWidget("Text Input", 50, 50);
cy.get('[data-cy="left-sidebar-settings-button"]').click();
cy.get('[data-cy="button-user-status-change"]').click();
verifyElementsOfExportModal("v1");
exportAllVersionsAndVerify(data.appName1, "v1");
});
});

View file

@ -84,7 +84,7 @@ describe("App Slug", () => {
// Release and verify URLs
releaseApp();
verifyURLs(workspaceId, data.slug, false);
verifyURLs(workspaceId, data.slug, true);
// Verify duplicate slug validation
cy.visit("/my-workspace");

View file

@ -5,10 +5,7 @@ import { inviteUserToWorkspace } from "Support/utils/manageUsers";
import { setSignupStatus } from "Support/utils/manageSSO";
import { onboardingSelectors } from "Selectors/onboarding";
import { commonText } from "Texts/common";
import {
userSignUp,
addNewUser,
} from "Support/utils/onboarding";
import { userSignUp, addNewUser } from "Support/utils/onboarding";
import {
setUpSlug,
setupAppWithSlug,
@ -16,347 +13,371 @@ import {
onboardUserFromAppLink,
} from "Support/utils/apps";
describe(
"Private and Public apps",
{
retries: { runMode: 2 },
},
() => {
let data;
describe("Private and Public apps", {
retries: { runMode: 2 },
}, () => {
let data;
beforeEach(() => {
data = {
appName: `${fake.companyName} P P App`,
slug: `${fake.companyName} P P App`.toLowerCase().replace(/\s+/g, "-"),
firstName: fake.firstName,
email: fake.email.toLowerCase(),
workspaceName: fake.firstName,
workspaceSlug: fake.firstName.toLowerCase().replace(/\s+/g, "-"),
};
beforeEach(() => {
data = {
appName: `${fake.companyName} P P App`,
slug: `${fake.companyName} P P App`.toLowerCase().replace(/\s+/g, "-"),
firstName: fake.firstName,
email: fake.email.toLowerCase(),
workspaceName: fake.firstName,
workspaceSlug: fake.firstName.toLowerCase().replace(/\s+/g, "-"),
}
cy.defaultWorkspaceLogin();
cy.skipWalkthrough();
});
it("Verify private and public app share functionality", () => {
cy.apiCreateApp(data.appName);
cy.openApp();
cy.apiAddComponentToApp(data.appName, "text1");
// Check unreleased version state
cy.get('[data-cy="share-button-link"]>span').should("be.visible").click();
cy.contains("This version has not been released yet").should("be.visible");
cy.get(commonWidgetSelector.modalCloseButton).click();
// Release and verify share modal
releaseApp();
cy.get(commonWidgetSelector.shareAppButton).click();
for (const elements in commonWidgetSelector.shareModalElements) {
cy.get(commonWidgetSelector.shareModalElements[elements])
.verifyVisibleElement("have.text", commonText.shareModalElements[elements]);
}
// Verify share modal elements
const shareModalSelectors = [
'copyAppLinkButton',
'makePublicAppToggle',
'appLink',
'appNameSlugInput',
'modalCloseButton'
];
shareModalSelectors.forEach(selector => {
cy.get(commonWidgetSelector[selector]).should("be.visible");
cy.defaultWorkspaceLogin();
cy.skipWalkthrough();
});
// Configure and verify slug
cy.clearAndType(commonWidgetSelector.appNameSlugInput, data.slug);
cy.get('[data-cy="app-slug-accepted-label"]')
.should("be.visible")
.and("have.text", "Slug accepted!");
it("Verify private and public app share functionality", () => {
cy.apiCreateApp(data.appName);
cy.openApp();
cy.apiAddComponentToApp(data.appName, "text1");
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.forceClickOnCanvas();
cy.backToApps();
// Check unreleased version state
cy.get('[data-cy="share-button-link"]>span').should("be.visible").click();
cy.contains("This version has not been released yet").should(
"be.visible"
);
cy.get(commonWidgetSelector.modalCloseButton).click();
// Test private access
logout();
// Release and verify share modal
releaseApp();
cy.get(commonWidgetSelector.shareAppButton).click();
for (const elements in commonWidgetSelector.shareModalElements) {
cy.get(
commonWidgetSelector.shareModalElements[elements]
).verifyVisibleElement(
"have.text",
commonText.shareModalElements[elements]
);
}
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
// Verify share modal elements
const shareModalSelectors = [
"copyAppLinkButton",
"makePublicAppToggle",
"appLink",
"appNameSlugInput",
"modalCloseButton",
];
shareModalSelectors.forEach((selector) => {
cy.get(commonWidgetSelector[selector]).should("be.visible");
});
// Configure and verify slug
cy.clearAndType(commonWidgetSelector.appNameSlugInput, data.slug);
cy.get('[data-cy="app-slug-accepted-label"]')
.should("be.visible")
.and("have.text", "Slug accepted!");
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.forceClickOnCanvas();
cy.backToApps();
// Test private access
logout();
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
cy.wait(2000);
cy.appUILogin();
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
// Test public access
cy.get(commonSelectors.viewerPageLogo).click();
cy.openApp(
"appSlug",
Cypress.env("workspaceId"),
Cypress.env("appId"),
commonWidgetSelector.draggableWidget("text1")
);
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get(commonWidgetSelector.makePublicAppToggle).check();
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.backToApps();
logout();
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
});
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
cy.wait(2000);
cy.appUILogin();
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
it("Verify app private and public app visibility for the same workspace user", () => {
setupAppWithSlug(data.appName, data.slug);
inviteUserToWorkspace(data.firstName, data.email);
logout();
cy.visit("/");
cy.wait(2000);
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
// Test public access
cy.get(commonSelectors.viewerPageLogo).click();
cy.openApp(
"appSlug",
Cypress.env("workspaceId"),
Cypress.env("appId"),
commonWidgetSelector.draggableWidget("text1")
);
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get(commonWidgetSelector.makePublicAppToggle).check();
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.backToApps();
// Test private access
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
logout();
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
cy.wait(2000);
cy.appUILogin(data.email, "password");
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
});
// Test with private app valid session
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
it("Verify app private and public app visibility for the same workspace user", () => {
setupAppWithSlug(data.appName, data.slug);
cy.get(commonSelectors.viewerPageLogo).click();
inviteUserToWorkspace(data.firstName, data.email);
logout();
cy.visit("/");
cy.wait(2000);
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
// Test public access
cy.defaultWorkspaceLogin();
cy.wait(1000);
cy.apiMakeAppPublic();
logout();
cy.wait(1000);
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
// Test private access
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
// Test with public app with valid session
cy.apiLogin(data.email, "password");
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
});
cy.wait(2000);
cy.appUILogin(data.email, "password");
it("Verify app private and public app visibility for the same instance user", () => {
setupAppWithSlug(data.appName, data.slug);
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
cy.apiLogout();
userSignUp(data.firstName, data.email, data.workspaceName);
cy.wait(1000);
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
// Test with private app valid session
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
cy.visit("/");
logout();
// Test public access
cy.defaultWorkspaceLogin();
cy.apiMakeAppPublic();
logout();
cy.get(commonSelectors.viewerPageLogo).click();
cy.wait(1000);
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
// Test public access
cy.defaultWorkspaceLogin();
cy.wait(1000);
cy.apiMakeAppPublic();
logout();
cy.wait(1000);
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
// Test with public app with valid session
cy.apiLogin(data.email, "password");
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
});
it("Verify app private and public app visibility for the same instance user", () => {
setupAppWithSlug(data.appName, data.slug);
cy.apiLogout();
userSignUp(data.firstName, data.email, data.workspaceName);
cy.wait(1000);
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
// Verify public app with valid session
cy.apiLogin(data.email, "password");
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
});
cy.visit("/");
logout();
it("Should redirect to workspace login and handle signup flow of existing and non-existing user", () => {
setSignupStatus(true);
setupAppWithSlug(data.appName, data.slug);
// Test public access
cy.defaultWorkspaceLogin();
cy.apiMakeAppPublic();
logout();
cy.apiLogout();
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.wait(1000);
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
"My workspace"
);
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
// Test signup flow
cy.intercept("POST", "/api/onboarding/signup").as("signup");
cy.get(commonSelectors.createAnAccountLink).click();
cy.wait(3000);
cy.clearAndType(commonSelectors.inputFieldFullName, data.firstName);
cy.clearAndType(commonSelectors.inputFieldEmailAddress, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "password");
cy.get(commonSelectors.signUpButton).click();
cy.wait("@signup").then((interception) => {
expect(interception.response.statusCode).to.eq(201);
});
// Process invitation
onboardUserFromAppLink(data.email, data.slug);
// Verify public app with valid session
cy.apiLogin(data.email, "password");
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
cy.get('[data-cy="viewer-page-logo"]').click();
logout();
cy.wait(1000);
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
});
// Setup new workspace and app
cy.defaultWorkspaceLogin();
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
cy.apiLogout();
cy.apiLogin();
cy.visit(`${data.workspaceSlug}`);
setSignupStatus(true, data.workspaceName);
it("Should redirect to workspace login and handle signup flow of existing and non-existing user", () => {
setSignupStatus(true);
setupAppWithSlug(data.appName, data.slug);
data.slug = fake.firstName.toLowerCase().replace(/\s+/g, "-");
cy.apiLogout();
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
cy.createApp(data.appName);
cy.dragAndDropWidget("Text", 500, 500);
releaseApp();
setUpSlug(data.slug);
cy.forceClickOnCanvas();
cy.backToApps();
// Test signup flow in new workspace
cy.apiLogout();
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
data.workspaceName
);
cy.get(commonSelectors.createAnAccountLink).click();
cy.wait(3000);
cy.clearAndType(commonSelectors.inputFieldFullName, data.firstName);
cy.clearAndType(commonSelectors.inputFieldEmailAddress, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "password");
cy.get(commonSelectors.signUpButton).click();
cy.wait("@signup").then((interception) => {
expect(interception.response.statusCode).to.eq(201);
});
onboardUserFromAppLink(data.email, data.slug, data.workspaceName, false);
cy.get(commonWidgetSelector.draggableWidget("text1")).should(
"be.visible"
);
});
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
"My workspace"
);
it("Should verify restricted app access", () => {
data.workspaceName = fake.firstName;
data.workspaceSlug = fake.firstName.toLowerCase().replace(/\s+/g, "-");
// Test signup flow
cy.intercept("POST", "/api/onboarding/signup").as("signup");
cy.get(commonSelectors.createAnAccountLink).click();
cy.wait(3000);
cy.clearAndType(commonSelectors.inputFieldFullName, data.firstName);
cy.clearAndType(commonSelectors.inputFieldEmailAddress, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "password");
cy.get(commonSelectors.signUpButton).click();
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
cy.apiLogout();
cy.apiLogin();
cy.visit(`${data.workspaceSlug}`);
cy.apiDeleteGranularPermission("end-user");
setSignupStatus(true, data.workspaceName);
cy.wait('@signup').then((interception) => {
expect(interception.response.statusCode).to.eq(201);
setupAppWithSlug(data.appName, data.slug);
inviteUserToWorkspace(data.firstName, data.email);
// Verify restricted access
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
verifyRestrictedAccess();
cy.get('[data-cy="back-to-home-button"]').click();
cy.get(commonSelectors.homePageLogo).should("be.visible");
cy.apiLogout();
});
// Process invitation
onboardUserFromAppLink(data.email, data.slug);
it.skip("Should verify private app access for different workspace users", () => {
const firstName1 = fake.firstName;
const email1 = fake.email.toLowerCase();
const permissionName = fake.firstName.toLowerCase(); // Defined but not used in original
const urls = {
editor: `${Cypress.config("baseUrl")}/my-workspace/apps/${data.slug}/home`,
preview: `${Cypress.config("baseUrl")}/applications/${data.slug}/home?version=v1`,
released: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
};
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
// Setup workspace and app
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
cy.apiLogout();
cy.apiLogin();
cy.visit(`${data.workspaceSlug}`);
setupAppWithSlug(data.appName, data.slug);
// Invite workspace user
addNewUser(data.firstName, data.email);
cy.wait(500);
cy.get('[data-cy="viewer-page-logo"]').click();
logout();
cy.wait(1000);
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should("be.visible");
// Verify access restrictions
cy.visitSlug({ actualUrl: urls.editor });
verifyRestrictedAccess();
cy.get('[data-cy="back-to-home-button"]').click();
cy.get(commonSelectors.homePageLogo).should("be.visible");
// Setup new workspace and app
cy.defaultWorkspaceLogin();
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
cy.apiLogout();
cy.apiLogin();
cy.visit(`${data.workspaceSlug}`);
setSignupStatus(true, data.workspaceName);
cy.visitSlug({ actualUrl: urls.preview });
data.slug = fake.firstName.toLowerCase().replace(/\s+/g, "-");
// Switch users and verify access
cy.apiLogout();
cy.apiLogin();
cy.apiDeleteGranularPermission("end-user");
cy.createApp(data.appName);
cy.dragAndDropWidget("Text", 500, 500);
releaseApp();
setUpSlug(data.slug);
cy.forceClickOnCanvas();
cy.backToApps();
cy.apiLogin(data.email, "password");
cy.visitSlug({ actualUrl: urls.editor });
verifyRestrictedAccess();
cy.get('[data-cy="back-to-home-button"]').click();
cy.get(commonSelectors.homePageLogo).should("be.visible");
cy.visitSlug({ actualUrl: urls.preview });
// Test signup flow in new workspace
cy.apiLogout();
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
cy.apiLogout();
// Test with new user
userSignUp(firstName1, email1, data.workspaceName);
cy.visitSlug({ actualUrl: urls.editor });
cy.visitSlug({ actualUrl: urls.preview });
cy.visitSlug({ actualUrl: urls.released });
});
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
data.workspaceName
);
cy.get(commonSelectors.createAnAccountLink).click();
cy.wait(3000);
cy.clearAndType(commonSelectors.inputFieldFullName, data.firstName);
cy.clearAndType(commonSelectors.inputFieldEmailAddress, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "password");
cy.get(commonSelectors.signUpButton).click();
cy.wait('@signup').then((interception) => {
expect(interception.response.statusCode).to.eq(201);
});
onboardUserFromAppLink(data.email, data.slug, data.workspaceName, false);
cy.get(commonWidgetSelector.draggableWidget("text1")).should("be.visible");
});
it("Should verify restricted app access", () => {
data.workspaceName = fake.firstName;
data.workspaceSlug = fake.firstName.toLowerCase().replace(/\s+/g, "-");
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
cy.apiLogout();
cy.apiLogin();
cy.visit(`${data.workspaceSlug}`);
cy.apiDeleteGranularPermission("end-user");
setSignupStatus(true, data.workspaceName);
setupAppWithSlug(data.appName, data.slug);
inviteUserToWorkspace(data.firstName, data.email);
// Verify restricted access
cy.visitSlug({
actualUrl: `${Cypress.config("baseUrl")}/applications/${data.slug}`,
});
verifyRestrictedAccess();
cy.get('[data-cy="back-to-home-button"]').click();
cy.get(commonSelectors.homePageLogo).should("be.visible");
cy.apiLogout();
});
it.skip("Should verify private app access for different workspace users", () => {
const firstName1 = fake.firstName;
const email1 = fake.email.toLowerCase();
const permissionName = fake.firstName.toLowerCase(); // Defined but not used in original
const urls = {
editor: `${Cypress.config("baseUrl")}/my-workspace/apps/${data.slug}/home`,
preview: `${Cypress.config("baseUrl")}/applications/${data.slug}/home?version=v1`,
released: `${Cypress.config("baseUrl")}/applications/${data.slug}`
};
// Setup workspace and app
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
cy.apiLogout();
cy.apiLogin();
cy.visit(`${data.workspaceSlug}`);
setupAppWithSlug(data.appName, data.slug);
// Invite workspace user
addNewUser(data.firstName, data.email);
cy.wait(500);
// Verify access restrictions
cy.visitSlug({ actualUrl: urls.editor });
verifyRestrictedAccess();
cy.get('[data-cy="back-to-home-button"]').click();
cy.get(commonSelectors.homePageLogo).should("be.visible");
cy.visitSlug({ actualUrl: urls.preview });
// Switch users and verify access
cy.apiLogout();
cy.apiLogin();
cy.apiDeleteGranularPermission("end-user");
cy.apiLogin(data.email, "password");
cy.visitSlug({ actualUrl: urls.editor });
verifyRestrictedAccess();
cy.get('[data-cy="back-to-home-button"]').click();
cy.get(commonSelectors.homePageLogo).should("be.visible");
cy.visitSlug({ actualUrl: urls.preview });
cy.apiLogout();
// Test with new user
userSignUp(firstName1, email1, data.workspaceName);
cy.visitSlug({ actualUrl: urls.editor });
cy.visitSlug({ actualUrl: urls.preview });
cy.visitSlug({ actualUrl: urls.released });
});
});
}
);

View file

@ -19,6 +19,7 @@ import {
} from "Support/utils/common";
import { inviteUserBasedOnRole } from "Support/utils/manageGroups";
import { resolveHost } from "Support/utils/apps";
import { addSuccessNotification } from "Support/utils/queries";
const data = {};
data.firstName = fake.firstName.toLowerCase().replaceAll("[^A-Za-z]", "");
@ -32,7 +33,7 @@ describe("Datasource Manager", () => {
beforeEach(() => {
cy.apiLogin();
cy.visit(`${workspaceSlug}`);
cy.viewport(1200, 1300);
cy.viewport(1800, 1800);
cy.skipWalkthrough();
});
@ -199,7 +200,7 @@ describe("Datasource Manager", () => {
cy.apiCreateApp(data.appName);
cy.openApp();
pinInspector();
// pinInspector();
addQuery(
"table_preview",
@ -212,9 +213,11 @@ describe("Datasource Manager", () => {
"table_preview "
);
cy.get(commonWidgetSelector.sidebarinspector).click();
cy.get('[data-cy="query-tab-settings"]').click();
addSuccessNotification("table_preview");
cy.get(dataSourceSelector.queryCreateAndRunButton).click();
verifyValueOnInspector("table_preview", "10 items ");
cy.verifyToastMessage(commonSelectors.toastMessage, "table_preview");
cy.get('[data-cy="show-ds-popover-button"]').click();
cy.get(".p-2 > .tj-base-btn")
@ -247,9 +250,13 @@ describe("Datasource Manager", () => {
cy.get("#react-select-4-listbox")
.contains(`cypress-${data.dsName2}-postgresql`)
.click();
cy.get('[data-cy="query-tab-settings"]').click();
addSuccessNotification("postgresql");
cy.waitForAutoSave();
cy.get(dataSourceSelector.queryCreateAndRunButton).click();
verifyValueOnInspector("table_preview", "4 items ");
cy.verifyToastMessage(commonSelectors.toastMessage, "postgresql");
});
it.skip("Should verify the query creation and scope changing functionality.", () => {

View file

@ -143,11 +143,11 @@ describe("Workspace constants", () => {
cy.get(dataSourceSelector.previewTabRawContainer).contains("secrets is not defined");
//verify global const should be visible, secrets and deleted const are not in Inspector
cy.get(commonWidgetSelector.inspectorIcon).click();
cy.get(commonWidgetSelector.constantInspectorIcon).click();
cy.get('[data-cy="inspector-node-restapiheaderkey"]').should('exist');
cy.get('[data-cy="inspector-node-deleteconst"]').should('not.exist');
cy.get('[data-cy="inspector-node-sconst"]').should('not.exist');
// cy.get(commonWidgetSelector.sidebarinspector).click();
// cy.get(commonWidgetSelector.constantInspectorIcon).click();
// cy.get('[data-cy="inspector-node-restapiheaderkey"]').should('exist');
// cy.get('[data-cy="inspector-node-deleteconst"]').should('not.exist');
// cy.get('[data-cy="inspector-node-sconst"]').should('not.exist');
//Preview app and verify components
cy.openInCurrentTab(commonWidgetSelector.previewButton);

View file

@ -50,9 +50,6 @@ describe("Login functionality", () => {
it("Should be able to login with valid credentials", () => {
cy.appUILogin(user.email, user.password);
if (envVar === "Enterprise") {
cy.get(".btn-close").click();
}
cy.get(commonSelectors.settingsIcon).click();
cy.get(dashboardSelector.logoutLink);
});

View file

@ -15,11 +15,19 @@ import {
} from "Support/utils/selfHostSignUp";
import { onboardingSelectors } from "Selectors/onboarding";
import { logout } from "Support/utils/common";
import { enableInstanceSignup } from "Support/utils/manageSSO";
describe("User signup", () => {
const data = {};
let invitationLink = "";
before(() => {
cy.ifEnv("Enterprise", () => {
enableInstanceSignup()
});
});
it("Verify the signup flow and UI elements", () => {
data.fullName = fake.fullName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");

View file

@ -23,6 +23,8 @@ import {
import { groupsSelector } from "Selectors/manageGroups";
import { groupsText } from "Texts/manageGroups";
import { onboardingSelectors } from "Selectors/onboarding";
import { enableInstanceSignup } from "Support/utils/manageSSO";
let invitationToken,
organizationToken,
@ -36,9 +38,9 @@ const envVar = Cypress.env("environment");
describe("user invite flow cases", () => {
beforeEach(() => {
cy.defaultWorkspaceLogin();
if (envVar === "Enterprise") {
cy.get(".btn-close").click();
}
cy.ifEnv("Enterprise", () => {
enableInstanceSignup()
});
});
it("Should verify the Manage users page", () => {

View file

@ -1,59 +1,126 @@
import { commonSelectors } from "Selectors/common";
import { usersText } from "Texts/manageUsers";
import { usersSelector } from "Selectors/manageUsers";
import { groupsSelector } from "Selectors/manageGroups";
import { fake } from "Fixtures/fake";
import * as common from "Support/utils/common";
import { bulkUserUpload } from "Support/utils/manageUsers";
// Helper to resolve correct test data based on env
const getFile = (fileGroup) => {
const env = Cypress.env("environment");
return env === "Community" ? fileGroup.default : fileGroup.alt;
};
describe("Bulk User Upload", () => {
// Test data configuration
const TEST_FILES = {
MISSING_NAME: {
path: "cypress/fixtures/bulkUser/without_name.csv",
fileName: "without_name",
error:
"Missing first_name,last_name,groups information in 2 row(s);. No users were uploaded, please update and try again.",
default: {
path: "cypress/fixtures/bulkUser/missing_name.csv",
fileName: "missing_name",
error:
"Missing first_name,last_name,groups information in 2 row(s);. No users were uploaded, please update and try again.",
},
alt: {
path: "cypress/fixtures/bulkUser/missing_name_ee.csv",
fileName: "missing_name_ee",
error:
"Missing first_name,last_name,groups,metadata,userMetadata information in 2 row(s);. No users were uploaded, please update and try again.",
},
},
MISSING_EMAIL: {
path: "cypress/fixtures/bulkUser/without_email.csv",
fileName: "without_email",
error:
"Missing email,groups information in 2 row(s);. No users were uploaded, please update and try again.",
default: {
path: "cypress/fixtures/bulkUser/missing_email.csv",
fileName: "missing_email",
error:
"Missing email,groups information in 2 row(s);. No users were uploaded, please update and try again.",
},
alt: {
path: "cypress/fixtures/bulkUser/missing_email_ee.csv",
fileName: "missing_email_ee",
error:
"Missing first_name,last_name,groups,metadata,userMetadata information in 2 row(s);. No users were uploaded, please update and try again.",
},
},
DUPLICATE_EMAIL: {
path: "cypress/fixtures/bulkUser/same_email.csv",
fileName: "same_email",
error: "Duplicate email found. Please provide a unique email address.",
isDuplicate: true,
default: {
path: "cypress/fixtures/bulkUser/same_email.csv",
fileName: "same_email",
error: "Duplicate email found. Please provide a unique email address.",
isDuplicate: true,
},
alt: {
path: "cypress/fixtures/bulkUser/same_email_ee.csv",
fileName: "same_email_ee",
error: "Duplicate email found. Please provide a unique email address.",
isDuplicate: true,
},
},
EMPTY_NAMES: {
path: "cypress/fixtures/bulkUser/empty_first_and_last_name.csv",
fileName: "empty_first_and_last_name",
error:
"Missing first_name,last_name,groups information in 1 row(s);. No users were uploaded, please update and try again.",
default: {
path: "cypress/fixtures/bulkUser/empty_names.csv",
fileName: "empty_names",
error:
"Missing first_name,last_name,groups information in 1 row(s);. No users were uploaded, please update and try again.",
},
alt: {
path: "cypress/fixtures/bulkUser/empty_names_ee.csv",
fileName: "empty_names_ee",
error:
"Missing first_name,last_name,groups,metadata,userMetadata information in 1 row(s);. No users were uploaded, please update and try again.",
},
},
LIMIT_EXCEEDED: {
path: "cypress/fixtures/bulkUser/500_invite_users.csv",
fileName: "500_invite_users",
error: "You can only invite 250 users at a time",
default: {
path: "cypress/fixtures/bulkUser/limit_exceeded.csv",
fileName: "limit_exceeded",
error: "You can only invite 250 users at a time",
},
alt: {
path: "cypress/fixtures/bulkUser/limit_exceeded_ee.csv",
fileName: "limit_exceeded_ee",
error: "You can only invite 250 users at a time",
},
},
MISSING_ROLE: {
path: "cypress/fixtures/bulkUser/without_role.csv",
fileName: "without_role",
error:
"Missing user_role,groups information in 2 row(s);. No users were uploaded, please update and try again.",
default: {
path: "cypress/fixtures/bulkUser/missing_role.csv",
fileName: "missing_role",
error:
"Missing user_role,groups information in 2 row(s);. No users were uploaded, please update and try again.",
},
alt: {
path: "cypress/fixtures/bulkUser/missing_role_ee.csv",
fileName: "missing_role_ee",
error:
"Missing user_role,groups,metadata,userMetadata information in 2 row(s);. No users were uploaded, please update and try again.",
},
},
NONEXISTENT_GROUP: {
path: "cypress/fixtures/bulkUser/non_existing_group.csv",
fileName: "non_existing_group",
error: "2 groups doesn't exist. No users were uploaded",
default: {
path: "cypress/fixtures/bulkUser/non_existing_group.csv",
fileName: "non_existing_group",
error: "2 groups doesn't exist. No users were uploaded",
},
alt: {
path: "cypress/fixtures/bulkUser/non_existing_group_ee.csv",
fileName: "non_existing_group_ee",
error: "2 groups doesn't exist. No users were uploaded",
},
},
VALID_USERS: {
path: "cypress/fixtures/bulkUser/3usersupload.csv",
fileName: "3usersupload",
testEmail: "test12@gmail.com",
successMessage: "3 users are being added",
default: {
path: "cypress/fixtures/bulkUser/3_users_upload.csv",
fileName: "3_users_upload",
successMessage: "3 users are being added",
email: "test12@gmail.com",
},
alt: {
path: "cypress/fixtures/bulkUser/3_users_upload_ee.csv",
fileName: "3_users_upload_ee",
successMessage: "3 users are being added",
email: "test12@gmail.com",
},
},
};
@ -70,7 +137,6 @@ describe("Bulk User Upload", () => {
cy.get(usersSelector.buttonAddUsers).click();
cy.get(usersSelector.buttonUploadCsvFile).click();
// Test all error cases
[
TEST_FILES.MISSING_ROLE,
TEST_FILES.MISSING_NAME,
@ -79,7 +145,8 @@ describe("Bulk User Upload", () => {
TEST_FILES.EMPTY_NAMES,
TEST_FILES.NONEXISTENT_GROUP,
TEST_FILES.LIMIT_EXCEEDED,
].forEach((testCase) => {
].forEach((testCaseGroup) => {
const testCase = getFile(testCaseGroup);
bulkUserUpload(
testCase.path,
testCase.fileName,
@ -90,32 +157,30 @@ describe("Bulk User Upload", () => {
});
it("Should successfully upload valid users", () => {
const file = getFile(TEST_FILES.VALID_USERS);
cy.get(usersSelector.buttonAddUsers).click();
cy.get(usersSelector.buttonUploadCsvFile).click();
cy.get(usersSelector.inputFieldBulkUpload).selectFile(
TEST_FILES.VALID_USERS.path,
{
force: true,
}
);
cy.get(commonSelectors.fileSelector).should(
"contain",
TEST_FILES.VALID_USERS.fileName
);
cy.get(usersSelector.inputFieldBulkUpload).selectFile(file.path, {
force: true,
});
cy.get(commonSelectors.fileSelector).should("contain", file.fileName);
cy.get(usersSelector.buttonUploadUsers).click();
cy.get(".go2072408551")
.should("be.visible")
.and("have.text", TEST_FILES.VALID_USERS.successMessage);
common.searchUser("test12@gmail.com");
cy.contains("td", "test12@gmail.com")
.and("have.text", file.successMessage);
common.searchUser(file.email);
cy.contains("td", file.email)
.parent()
.within(() => {
cy.get("td small").should("have.text", "invited");
});
common.navigateToManageGroups();
cy.get(groupsSelector.groupLink("Admin")).click();
cy.get(groupsSelector.usersLink).click();
cy.contains("test12@gmail.com").should("be.visible");
cy.contains(file.email).should("be.visible");
});
});

View file

@ -21,6 +21,7 @@ import {
} from "Support/utils/common";
import { onboardingSelectors } from "Selectors/onboarding";
import { enableInstanceSignup } from "Support/utils/manageSSO";
const data = {};
const envVar = Cypress.env("environment");
@ -28,9 +29,9 @@ const envVar = Cypress.env("environment");
describe("inviteflow edge cases", () => {
beforeEach(() => {
cy.defaultWorkspaceLogin();
if (envVar === "Enterprise") {
cy.get(".btn-close").click();
}
cy.ifEnv("Enterprise", () => {
enableInstanceSignup();
});
});
it("Should verify exisiting user invite flow", () => {
@ -69,55 +70,6 @@ describe("inviteflow edge cases", () => {
});
});
it("should verify the user signup after invited in a workspace", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.signUpName = fake.firstName;
data.workspaceName = fake.companyName;
enableInstanceSignUp();
setSignupStatus(true);
navigateToManageUsers();
fillUserInviteForm(data.firstName, data.email);
cy.get(usersSelector.buttonInviteUsers).click();
cy.apiLogout();
cy.visit("/");
cy.get(commonSelectors.createAnAccountLink).click();
SignUpPageElements();
cy.wait(3000);
cy.clearAndType(onboardingSelectors.nameInput, data.signUpName);
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(
onboardingSelectors.loginPasswordInput,
commonText.password
);
cy.get(commonSelectors.signUpButton).click();
cy.wait(1000);
signUpLink(data.email);
if (envVar === "Enterprise") {
verifyOnboardingQuestions(data.workspaceName);
cy.wait(1000);
cy.get(commonSelectors.skipbutton).click();
cy.backToApps();
}
cy.wait(1000);
visitWorkspaceInvitation(data.email, "My workspace");
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, usersText.password);
cy.get(onboardingSelectors.signInButton).click();
cy.wait(3000);
cy.get(commonSelectors.invitedUserName).verifyVisibleElement(
"have.text",
data.signUpName
);
cy.get(commonSelectors.acceptInviteButton).click();
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
"My workspace"
);
});
it("should verify the user signup with same creds after invited in a workspace", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");

View file

@ -0,0 +1,250 @@
import { commonSelectors } from "Selectors/common";
import { commonEeSelectors, ssoEeSelector } from "Selectors/eeCommon";
import { ssoEeText } from "Texts/eeCommon";
import { setSSOStatus, setSignupStatus } from "Support/utils/manageSSO";
import { usersText } from "Texts/manageUsers";
import { fake } from "Fixtures/fake";
import {
logout,
navigateToManageSSO,
navigateToManageUsers,
searchUser,
pinInspector,
navigateToAppEditor,
navigateToManageGroups,
} from "Support/utils/common";
import { ssoText } from "Texts/manageSSO";
import { enableToggle, disableToggle } from "Support/utils/platform/eeCommon";
import { setupAndUpdateRole } from "Support/utils/manageGroups";
describe("LDAP flow", () => {
const TEST_DATA = {
appName: `${fake.companyName} App`,
ldapUser: {
username: "Hubert J. Farnsworth",
password: "professor",
email: "professor@planetexpress.com",
},
ldapConfig: {
name: "Tooljet LDAP Auth",
host: Cypress.env("ldap_host"),
port: "10389",
baseDn: Cypress.env("ldap_base_dn"),
},
};
const ldapLogin = (
username = TEST_DATA.ldapUser.username,
password = TEST_DATA.ldapUser.password
) => {
cy.get(ssoEeSelector.ldapSSOText).click();
cy.clearAndType(commonSelectors.inputFieldName, username);
cy.clearAndType(ssoEeSelector.passwordInputField, password);
cy.get(commonSelectors.signUpButton).click();
};
const toggleUserArchiveStatus = (shouldArchive = true) => {
navigateToManageUsers();
searchUser(TEST_DATA.ldapUser.email);
cy.get('[data-cy="user-actions-button"]').click();
cy.get('[data-cy="archive-button"]').click();
const expectedToast = shouldArchive
? usersText.archivedToast
: usersText.unarchivedToast;
cy.verifyToastMessage(commonSelectors.toastMessage, expectedToast);
if (shouldArchive) {
cy.contains("td", TEST_DATA.ldapUser.email)
.parent()
.within(() => {
cy.get("td small").should("have.text", usersText.archivedStatus);
});
}
};
beforeEach(() => {
cy.visit("/");
cy.appUILogin();
});
it("Verify complete LDAP flow: UI, user onboarding, inspector SSO info, and archive functionality", () => {
cy.intercept("GET", "api/library_apps").as("apps");
// ========== SECTION 1: LDAP Configuration and UI Verification ==========
setSSOStatus("My workspace", "ldap", false);
navigateToManageSSO();
cy.wait(1000);
cy.get('[data-cy="ldap-sso-card"]')
.verifyVisibleElement("have.text", "LDAP")
.click();
cy.get(ssoEeSelector.ldapToggle).should("be.visible");
for (const element in ssoEeSelector.ldapPageElements) {
cy.get(ssoEeSelector.ldapPageElements[element]).verifyVisibleElement(
"have.text",
ssoEeText.ldapPageElements[element]
);
}
const formElements = [
ssoEeSelector.statusLabel,
ssoEeSelector.nameInput,
ssoEeSelector.hostInput,
ssoEeSelector.portInput,
ssoEeSelector.baseDnInput,
ssoEeSelector.sslToggleInput,
];
formElements.forEach((selector) => {
cy.get(selector).should("be.visible");
});
cy.get(commonSelectors.cancelButton)
.eq(1)
.verifyVisibleElement("have.text", "Cancel");
cy.get(commonEeSelectors.saveButton)
.eq(1)
.verifyVisibleElement("have.text", "Save changes");
enableToggle(ssoEeSelector.sslToggleInput);
cy.get(ssoEeSelector.ldapPageElements.sslLabel)
.eq(1)
.verifyVisibleElement("have.text", "SSL certificate");
cy.get(".css-1x65k0v-control").should("be.visible");
cy.clearAndType(ssoEeSelector.nameInput, TEST_DATA.ldapConfig.name);
cy.clearAndType(ssoEeSelector.hostInput, TEST_DATA.ldapConfig.host);
cy.clearAndType(ssoEeSelector.portInput, TEST_DATA.ldapConfig.port);
cy.clearAndType(ssoEeSelector.baseDnInput, TEST_DATA.ldapConfig.baseDn);
cy.get(ssoEeSelector.sslToggleInput).uncheck();
cy.get(ssoEeSelector.ldapToggle).click();
disableToggle(ssoEeSelector.sslToggleInput);
cy.get(commonEeSelectors.saveButton).eq(1).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
ssoText.toggleUpdateToast("LDAP")
);
cy.get(commonSelectors.cancelButton).eq(1).click();
logout();
// ========== SECTION 2: LDAP Login Page and User Onboarding ==========
cy.get(ssoEeSelector.ldapSSOText).verifyVisibleElement(
"have.text",
ssoEeText.ldapSSOText
);
cy.get(ssoEeSelector.ldapSSOText).click();
const loginPageElements = [
{ selector: '[data-cy="key-logo"]', assertion: "be.visible" },
{
selector: ssoEeSelector.userNameInputLabel,
text: ssoEeText.userNameInputLabel,
},
{ selector: commonSelectors.inputFieldName, assertion: "be.visible" },
{ selector: ssoEeSelector.passwordInputLabel, text: "Password" },
{ selector: ssoEeSelector.passwordInputField, assertion: "be.visible" },
{ selector: commonSelectors.signUpButton, text: "Sign in" },
];
loginPageElements.forEach((element) => {
if (element.text) {
cy.get(element.selector).verifyVisibleElement(
"have.text",
element.text
);
} else {
cy.get(element.selector).should(element.assertion);
}
});
// Test failed login (user doesn't exist in workspace)
cy.clearAndType(
commonSelectors.inputFieldName,
TEST_DATA.ldapUser.username
);
cy.clearAndType(
ssoEeSelector.passwordInputField,
TEST_DATA.ldapUser.password
);
cy.get(commonSelectors.signUpButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"LDAP login failed - User does not exist in the workspace"
);
cy.defaultWorkspaceLogin();
setSignupStatus(true);
logout();
ldapLogin();
cy.get(commonSelectors.pageSectionHeader).verifyVisibleElement(
"have.text",
"Applications"
);
logout();
// ========== SECTION 3: Setup App and User Permissions for Inspector Test ==========
cy.defaultWorkspaceLogin();
cy.apiCreateApp(TEST_DATA.appName);
navigateToManageGroups();
setupAndUpdateRole("End-user", "Builder", TEST_DATA.ldapUser.email);
logout();
// ========== SECTION 4: Verify SSO User Info in Inspector ==========
ldapLogin();
cy.wait("@apps");
cy.wait(1000);
navigateToAppEditor(TEST_DATA.appName);
pinInspector();
const inspectorPath = [
'[data-cy="inspector-node-globals"] > .node-key',
'[data-cy="inspector-node-currentuser"] > .node-key',
'[data-cy="inspector-node-ssouserinfo"] > .node-key',
'[data-cy="inspector-node-mail"] > .node-key',
];
inspectorPath.forEach((selector) => cy.get(selector).click());
cy.get('[data-cy="inspector-node-0"] > .mx-2').verifyVisibleElement(
"have.text",
`"${TEST_DATA.ldapUser.email}"`
);
cy.backToApps();
logout();
// ========== SECTION 5: Archive/Unarchive Functionality ==========
cy.defaultWorkspaceLogin();
// Archive user and verify status
toggleUserArchiveStatus(true);
logout();
ldapLogin();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"LDAP login failed - User is archived in the workspace"
);
// Unarchive user
cy.go("back");
cy.appUILogin();
toggleUserArchiveStatus(false);
logout();
ldapLogin();
cy.get(commonSelectors.pageSectionHeader).verifyVisibleElement(
"have.text",
"Applications"
);
});
});

View file

@ -0,0 +1,239 @@
import * as common from "Support/utils/common";
import { ssoText } from "Texts/manageSSO";
import {
inviteUser,
WorkspaceInvitationLink,
} from "Support/utils/platform/eeCommon.js";
import { commonSelectors } from "Selectors/common";
import {
commonEeSelectors,
ssoEeSelector,
instanceSettingsSelector,
} from "Selectors/eeCommon";
import { commonEeText } from "Texts/eeCommon";
import {
setSignupStatus,
defaultSSO,
deleteOrganisationSSO,
} from "Support/utils/manageSSO";
import { confirmInviteElements } from "Support/utils/manageUsers";
import { usersText } from "Texts/manageUsers";
import { usersSelector } from "Selectors/manageUsers";
import { fetchAndVisitInviteLink } from "Support/utils/manageUsers";
import { enableInstanceSignup } from "Support/utils/manageSSO";
describe("Verify OIDC user onboarding", () => {
const envVar = Cypress.env("environment");
beforeEach(() => {
cy.defaultWorkspaceLogin();
cy.intercept("GET", "api/library_apps").as("apps");
cy.wait(2000);
defaultSSO(true);
});
it("Verify user onboarding using workspace OIDC", () => {
deleteOrganisationSSO("My workspace", ["openid"]);
common.navigateToManageSSO();
defaultSSO(false);
setSignupStatus(false);
cy.wait(1000);
cy.get(ssoEeSelector.oidc).click();
cy.get(ssoEeSelector.oidcToggle).click();
cy.clearAndType(ssoEeSelector.nameInput, "Tooljet OIDC");
cy.clearAndType(
ssoEeSelector.clientIdInput,
Cypress.env("SSO_OPENID_CLIENT_ID")
);
cy.clearAndType(
ssoEeSelector.clientSecretInput,
Cypress.env("SSO_OPENID_CLIENT_SECRET")
);
cy.clearAndType(
ssoEeSelector.WellKnownUrlInput,
Cypress.env("SSO_OPENID_WELL_KNOWN_URL")
);
cy.get(commonEeSelectors.saveButton).eq(1).click();
cy.get('[data-cy="enable-button"]').click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
ssoText.toggleUpdateToast("OpenID")
);
cy.apiLogout();
cy.visit("/login/my-workspace");
cy.get(ssoEeSelector.oidcSSOText).verifyVisibleElement(
"have.text",
"Sign in with Tooljet OIDC"
);
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".superadmin-button").click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Open ID login failed - User does not exist in the workspace"
);
cy.apiLogin();
setSignupStatus(true);
cy.apiLogout();
cy.visit("/login/my-workspace");
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".superadmin-button").click();
common.logout();
cy.defaultWorkspaceLogin();
common.navigateToManageUsers();
common.searchUser("superadmin@tooljet.com");
cy.contains("td", "superadmin@tooljet.com")
.parent()
.within(() => {
cy.get("td small").should("have.text", usersText.activeStatus);
});
cy.apiLogout();
cy.visit("/my-workspace");
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".superadmin-button").click();
});
it("Verify invited user onboarding using instance level OIDC", () => {
setSignupStatus(true);
cy.ifEnv("Enterprise", () => {
enableInstanceSignup();
});
common.navigateToManageUsers();
inviteUser("user", "user@tooljet.com");
confirmInviteElements("user@tooljet.com");
cy.wait(2000);
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".user-button").click();
cy.wait(1000);
cy.get(commonSelectors.acceptInviteButton).click();
cy.wait("@apps");
cy.contains("My workspace").should("be.visible");
common.logout();
cy.defaultWorkspaceLogin();
setSignupStatus(false);
common.navigateToManageUsers();
cy.wait(500);
inviteUser("user", "userthree@tooljet.com");
cy.wait(2000);
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".user-four-button").click();
cy.get(commonSelectors.toastMessage)
.should("be.visible")
.and(
"have.text",
"Open ID login failed - Invalid Email: Please use the email address provided in the invitation."
);
cy.wait(500);
cy.defaultWorkspaceLogin();
setSignupStatus(true);
fetchAndVisitInviteLink("userthree@tooljet.com");
cy.wait(2000);
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".user-four-button").click();
cy.get(commonSelectors.toastMessage)
.should("be.visible")
.and(
"have.text",
"Open ID login failed - Invalid Email: Please use the email address provided in the invitation."
);
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".superadmin-button").click();
cy.get(commonSelectors.toastMessage)
.should("be.visible")
.and(
"have.text",
"Open ID login failed - Invalid Email: Please use the email address provided in the invitation."
);
});
if (envVar === "Enterprise") {
it("Verify user onboarding using instance level OIDC", () => {
enableInstanceSignup();
cy.apiLogout();
cy.visit("/");
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".admin-button").click();
cy.wait(3000);
common.logout();
cy.defaultWorkspaceLogin();
cy.get(commonSelectors.settingsIcon).click();
cy.get(commonEeSelectors.instanceSettingIcon).click();
cy.clearAndType(commonSelectors.inputUserSearch, "admin@tooljet.com");
cy.get(instanceSettingsSelector.userStatus("admin")).verifyVisibleElement(
"have.text",
usersText.activeStatus
);
cy.apiLogout();
cy.visit("/");
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".admin-button").click();
});
}
it("Verify archived user login using OIDC", () => {
setSignupStatus(true);
cy.ifEnv("Enterprise", () => {
enableInstanceSignup();
});
common.navigateToManageUsers();
cy.get(usersSelector.buttonAddUsers).click();
cy.get(commonSelectors.inputFieldFullName).type("user two");
cy.get(commonSelectors.inputFieldEmailAddress).type("usertwo@tooljet.com");
cy.get(usersSelector.buttonInviteUsers).click();
WorkspaceInvitationLink("usertwo@tooljet.com");
cy.wait(2000);
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".user-two-button").click();
cy.get(commonSelectors.acceptInviteButton).click();
cy.wait("@apps");
cy.contains("My workspace").should("be.visible");
common.logout();
cy.defaultWorkspaceLogin();
common.navigateToManageUsers();
common.searchUser("usertwo@tooljet.com");
cy.get('[data-cy="user-actions-button"]').click();
cy.get('[data-cy="archive-button"]').click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
usersText.archivedToast
);
cy.get(instanceSettingsSelector.userStatus("user two"), {
timeout: 9000,
}).should("have.text", usersText.archivedStatus);
cy.apiLogout();
cy.visit("/my-workspace");
cy.wait(2000);
cy.get(ssoEeSelector.oidcSSOText).realClick();
cy.get(".user-two-button").click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Open ID login failed - User is archived in the workspace"
);
});
});

View file

@ -18,7 +18,7 @@ describe("Self host onboarding", () => {
});
it("verify elements on self host onboarding page", () => {
if (envVar === "Enterprise") {
cy.ifEnv("Enterprise", () => {
cy.get(commonSelectors.HostBanner).should("be.visible");
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get('[data-cy="welcome-to-tooljet!-header"]').verifyVisibleElement(
@ -34,7 +34,7 @@ describe("Self host onboarding", () => {
"Set up ToolJet"
);
cy.get('[data-cy="set-up-tooljet-button"]').click();
}
});
const commonElements = [
{ selector: commonSelectors.HostBanner },
@ -76,20 +76,22 @@ describe("Self host onboarding", () => {
cy.get(check.selector).verifyVisibleElement("have.text", check.text);
});
if (envVar === "Community") {
cy.ifEnv("Community", () => {
cy.get(commonSelectors.signUpTermsHelperText).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
// commonText.selfHostSignUpTermsHelperText
"By signing up you are agreeing to the"
);
});
} else if (envVar === "Enterprise") {
});
cy.ifEnv("Enterprise", () => {
cy.get(commonSelectors.signUpTermsHelperText).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
"By signing up you are agreeing to the"
);
});
}
});
const links = [
{
@ -116,20 +118,15 @@ describe("Self host onboarding", () => {
cy.get(onboardingSelectors.passwordInput).type("password");
cy.get(commonSelectors.continueButton).click();
if (envVar === "Enterprise") {
cy.ifEnv("Enterprise", () => {
bannerElementsVerification();
onboardingStepOne();
}
});
bannerElementsVerification();
onboardingStepTwo();
// if (envVar === "Enterprise") {
// bannerElementsVerification();
// onboardingStepTwo();
// }
if (envVar === "Enterprise") {
cy.ifEnv("Enterprise", () => {
bannerElementsVerification();
const trialPageTexts = [
@ -173,7 +170,7 @@ describe("Self host onboarding", () => {
cy.get(onboardingSelectors.onPremiseLink)
.verifyVisibleElement("have.text", "Click here")
.and("have.attr", "href")
.and("equal", "https://www.tooljet.com/pricing?payment=onpremise");
.and("equal", "https://tooljet.ai/pricing?payment=onpremise");
const planTitles = [
{
@ -196,66 +193,59 @@ describe("Self host onboarding", () => {
const prices = [
{ selector: `${onboardingSelectors.planPrice}:eq(0)`, text: "$0" },
{ selector: `${onboardingSelectors.planPrice}:eq(1)`, text: "$30" },
{
selector: '[data-cy="pro-plan-price"]:eq(0)',
text: "$79/monthper builder",
},
{
selector: '[data-cy="pro-plan-price"]:eq(1)',
text: "$199/monthper builder",
},
{
selector: `${onboardingSelectors.planToggleLabel}:eq(0)`,
text: "Yearly20% off",
},
{
selector: `${onboardingSelectors.planToggleLabel}:eq(1)`,
text: "Yearly20% off",
},
];
prices.forEach((item) => {
cy.get(item.selector).should("be.visible").and("have.text", item.text);
});
cy.get(onboardingSelectors.planToggleInput).should("be.visible");
cy.get(onboardingSelectors.planToggleLabel).verifyVisibleElement(
"have.text",
"Yearly20% off"
);
cy.get(onboardingSelectors.discountDetails).verifyVisibleElement(
"have.text",
"20% off"
);
cy.get(onboardingSelectors.planToggleInput).eq(0).should("be.visible");
cy.get(onboardingSelectors.planToggleInput).eq(1).should("be.visible");
cy.get(onboardingSelectors.builderPrice).verifyVisibleElement(
"have.text",
"$24"
);
cy.get('[data-cy="builder-price-period"]').verifyVisibleElement(
"have.text",
onboardingText.priceMonthlyText
);
cy.get('[data-cy="builder-price-description"]').verifyVisibleElement(
"have.text",
"per builder"
);
cy.get(onboardingSelectors.endUserPrice).verifyVisibleElement(
"have.text",
"$8"
);
cy.get('[data-cy="enduser-price-period"]').verifyVisibleElement(
"have.text",
onboardingText.priceMonthlyText
);
cy.get('[data-cy="enduser-price-description"]').verifyVisibleElement(
"have.text",
"per end user"
);
cy.get(onboardingSelectors.pricingPlanToggle).uncheck({ force: true });
cy.get(onboardingSelectors.pricingPlanToggle)
.eq(0)
.uncheck({ force: true });
cy.get(onboardingSelectors.planToggleLabel)
.first()
.eq(0)
.verifyVisibleElement("have.text", "Monthly20% off");
cy.get(onboardingSelectors.discountDetails)
.should("have.css", "text-decoration")
.and("include", "line-through");
cy.get(onboardingSelectors.builderPrice).verifyVisibleElement(
"have.text",
"$30"
);
cy.get(onboardingSelectors.endUserPrice).verifyVisibleElement(
"have.text",
"$10"
);
cy.get('[data-cy="pro-plan-price"]')
.eq(0)
.verifyVisibleElement("have.text", "$99/monthper builder");
cy.get(onboardingSelectors.pricingPlanToggle)
.eq(1)
.uncheck({ force: true });
cy.get(onboardingSelectors.planToggleLabel)
.eq(1)
.verifyVisibleElement("have.text", "Monthly20% off");
cy.get(onboardingSelectors.discountDetails)
.should("have.css", "text-decoration")
.and("include", "line-through");
cy.get('[data-cy="pro-plan-price"]')
.eq(1)
.verifyVisibleElement("have.text", "$249/monthper builder");
cy.get(onboardingSelectors.enterpriseTitle).verifyVisibleElement(
"have.text",
@ -274,19 +264,11 @@ describe("Self host onboarding", () => {
bannerElementsVerification();
onboardingStepThree();
}
});
cy.get(commonSelectors.skipbutton).click();
cy.backToApps();
if (envVar === "Enterprise") {
cy.get(".btn-close").click();
}
if (envVar === "Enterprise") {
cy.get(".btn-close").click();
}
logout();
cy.appUILogin();

View file

@ -0,0 +1,4 @@
First Name,Last Name,Email,User Role,Group
test1,user,test1@gmail.com,Builder,
test2,user,test3@gmail.com,End User,
Test3,Example,test12@gmail.com,Admin,
1 First Name Last Name Email User Role Group
2 test1 user test1@gmail.com Builder
3 test2 user test3@gmail.com End User
4 Test3 Example test12@gmail.com Admin

View file

@ -0,0 +1,4 @@
First Name,Last Name,Email,User Role,Group,Metadata
test1,user,test1@gmail.com,Builder,,
test2,user,test3@gmail.com,End User,,
Test3,Example,test12@gmail.com,Admin,,
1 First Name Last Name Email User Role Group Metadata
2 test1 user test1@gmail.com Builder
3 test2 user test3@gmail.com End User
4 Test3 Example test12@gmail.com Admin

View file

@ -0,0 +1,3 @@
First Name,Last Name,Email,User Role,Group
,,test12empty@gmail.com,Admin,Admin
Test,Example,test12empty@gmail.com,Builder,Builder
1 First Name Last Name Email User Role Group
2 test12empty@gmail.com Admin Admin
3 Test Example test12empty@gmail.com Builder Builder

View file

@ -0,0 +1,3 @@
First Name,Last Name,Email,User Role,Group,Metadata
,,test12empty@gmail.com,Admin,Admin,
Test,Example,test12empty@gmail.com,Builder,Builder,
1 First Name Last Name Email User Role Group Metadata
2 test12empty@gmail.com Admin Admin
3 Test Example test12empty@gmail.com Builder Builder

View file

@ -0,0 +1,252 @@
First Name,Last Name,Email,User Role,Group
Vijay,Yadav,vjyaav1@gmail.com,Admin,
Vijay,Yadav,vjyaav2@gmail.com,Builder,
Vijay,Yadav,vjyaav3@gmail.com,Builder,
Vijay,Yadav,vjyaav4@gmail.com,End User,
Vijay,Yadav,vjyaav5@gmail.com,End User,
Vijay,Yadav,vjyaav6@gmail.com,End User,
Vijay,Yadav,vjyaav7@gmail.com,End User,
Vijay,Yadav,vjyaav8@gmail.com,End User,
Vijay,Yadav,vjyaav9@gmail.com,End User,
Vijay,Yadav,vjyaav10@gmail.com,End User,
Vijay,Yadav,vjyaav11@gmail.com,End User,
Vijay,Yadav,vjyaav12@gmail.com,End User,
Vijay,Yadav,vjyaav13@gmail.com,End User,
Vijay,Yadav,vjyaav14@gmail.com,End User,
Vijay,Yadav,vjyaav15@gmail.com,End User,
Vijay,Yadav,vjyaav16@gmail.com,End User,
Vijay,Yadav,vjyaav17@gmail.com,End User,
Vijay,Yadav,vjyaav18@gmail.com,End User,
Vijay,Yadav,vjyaav19@gmail.com,End User,
Vijay,Yadav,vjyaav20@gmail.com,End User,
Vijay,Yadav,vjyaav21@gmail.com,End User,
Vijay,Yadav,vjyaav22@gmail.com,End User,
Vijay,Yadav,vjyaav23@gmail.com,End User,
Vijay,Yadav,vjyaav24@gmail.com,End User,
Vijay,Yadav,vjyaav25@gmail.com,End User,
Vijay,Yadav,vjyaav26@gmail.com,End User,
Vijay,Yadav,vjyaav27@gmail.com,End User,
Vijay,Yadav,vjyaav28@gmail.com,End User,
Vijay,Yadav,vjyaav29@gmail.com,End User,
Vijay,Yadav,vjyaav30@gmail.com,End User,
Vijay,Yadav,vjyaav31@gmail.com,End User,
Vijay,Yadav,vjyaav32@gmail.com,End User,
Vijay,Yadav,vjyaav33@gmail.com,End User,
Vijay,Yadav,vjyaav34@gmail.com,End User,
Vijay,Yadav,vjyaav35@gmail.com,End User,
Vijay,Yadav,vjyaav36@gmail.com,End User,
Vijay,Yadav,vjyaav37@gmail.com,End User,
Vijay,Yadav,vjyaav38@gmail.com,End User,
Vijay,Yadav,vjyaav39@gmail.com,End User,
Vijay,Yadav,vjyaav40@gmail.com,End User,
Vijay,Yadav,vjyaav41@gmail.com,End User,
Vijay,Yadav,vjyaav42@gmail.com,End User,
Vijay,Yadav,vjyaav43@gmail.com,End User,
Vijay,Yadav,vjyaav44@gmail.com,End User,
Vijay,Yadav,vjyaav45@gmail.com,End User,
Vijay,Yadav,vjyaav46@gmail.com,End User,
Vijay,Yadav,vjyaav47@gmail.com,End User,
Vijay,Yadav,vjyaav48@gmail.com,End User,
Vijay,Yadav,vjyaav49@gmail.com,End User,
Vijay,Yadav,vjyaav50@gmail.com,End User,
Vijay,Yadav,vjyaav51@gmail.com,End User,
Vijay,Yadav,vjyaav52@gmail.com,End User,
Vijay,Yadav,vjyaav53@gmail.com,End User,
Vijay,Yadav,vjyaav54@gmail.com,End User,
Vijay,Yadav,vjyaav55@gmail.com,End User,
Vijay,Yadav,vjyaav56@gmail.com,End User,
Vijay,Yadav,vjyaav57@gmail.com,End User,
Vijay,Yadav,vjyaav58@gmail.com,End User,
Vijay,Yadav,vjyaav59@gmail.com,End User,
Vijay,Yadav,vjyaav60@gmail.com,End User,
Vijay,Yadav,vjyaav61@gmail.com,End User,
Vijay,Yadav,vjyaav62@gmail.com,End User,
Vijay,Yadav,vjyaav63@gmail.com,End User,
Vijay,Yadav,vjyaav64@gmail.com,End User,
Vijay,Yadav,vjyaav65@gmail.com,End User,
Vijay,Yadav,vjyaav66@gmail.com,End User,
Vijay,Yadav,vjyaav67@gmail.com,End User,
Vijay,Yadav,vjyaav68@gmail.com,End User,
Vijay,Yadav,vjyaav69@gmail.com,End User,
Vijay,Yadav,vjyaav70@gmail.com,End User,
Vijay,Yadav,vjyaav71@gmail.com,End User,
Vijay,Yadav,vjyaav72@gmail.com,End User,
Vijay,Yadav,vjyaav73@gmail.com,End User,
Vijay,Yadav,vjyaav74@gmail.com,End User,
Vijay,Yadav,vjyaav75@gmail.com,End User,
Vijay,Yadav,vjyaav76@gmail.com,End User,
Vijay,Yadav,vjyaav77@gmail.com,End User,
Vijay,Yadav,vjyaav78@gmail.com,End User,
Vijay,Yadav,vjyaav79@gmail.com,End User,
Vijay,Yadav,vjyaav80@gmail.com,End User,
Vijay,Yadav,vjyaav81@gmail.com,End User,
Vijay,Yadav,vjyaav82@gmail.com,End User,
Vijay,Yadav,vjyaav83@gmail.com,End User,
Vijay,Yadav,vjyaav84@gmail.com,End User,
Vijay,Yadav,vjyaav85@gmail.com,End User,
Vijay,Yadav,vjyaav86@gmail.com,End User,
Vijay,Yadav,vjyaav87@gmail.com,End User,
Vijay,Yadav,vjyaav88@gmail.com,End User,
Vijay,Yadav,vjyaav89@gmail.com,End User,
Vijay,Yadav,vjyaav90@gmail.com,End User,
Vijay,Yadav,vjyaav91@gmail.com,End User,
Vijay,Yadav,vjyaav92@gmail.com,End User,
Vijay,Yadav,vjyaav93@gmail.com,End User,
Vijay,Yadav,vjyaav94@gmail.com,End User,
Vijay,Yadav,vjyaav95@gmail.com,End User,
Vijay,Yadav,vjyaav96@gmail.com,End User,
Vijay,Yadav,vjyaav97@gmail.com,End User,
Vijay,Yadav,vjyaav98@gmail.com,End User,
Vijay,Yadav,vjyaav99@gmail.com,End User,
Vijay,Yadav,vjyaav100@gmail.com,End User,
Vijay,Yadav,vjyaav101@gmail.com,End User,
Vijay,Yadav,vjyaav102@gmail.com,End User,
Vijay,Yadav,vjyaav103@gmail.com,End User,
Vijay,Yadav,vjyaav104@gmail.com,End User,
Vijay,Yadav,vjyaav105@gmail.com,End User,
Vijay,Yadav,vjyaav106@gmail.com,End User,
Vijay,Yadav,vjyaav107@gmail.com,End User,
Vijay,Yadav,vjyaav108@gmail.com,End User,
Vijay,Yadav,vjyaav109@gmail.com,End User,
Vijay,Yadav,vjyaav110@gmail.com,End User,
Vijay,Yadav,vjyaav111@gmail.com,End User,
Vijay,Yadav,vjyaav112@gmail.com,End User,
Vijay,Yadav,vjyaav113@gmail.com,End User,
Vijay,Yadav,vjyaav114@gmail.com,End User,
Vijay,Yadav,vjyaav115@gmail.com,End User,
Vijay,Yadav,vjyaav116@gmail.com,End User,
Vijay,Yadav,vjyaav117@gmail.com,End User,
Vijay,Yadav,vjyaav118@gmail.com,End User,
Vijay,Yadav,vjyaav119@gmail.com,End User,
Vijay,Yadav,vjyaav120@gmail.com,End User,
Vijay,Yadav,vjyaav121@gmail.com,End User,
Vijay,Yadav,vjyaav122@gmail.com,End User,
Vijay,Yadav,vjyaav123@gmail.com,End User,
Vijay,Yadav,vjyaav124@gmail.com,End User,
Vijay,Yadav,vjyaav125@gmail.com,End User,
Vijay,Yadav,vjyaav126@gmail.com,End User,
Vijay,Yadav,vjyaav127@gmail.com,End User,
Vijay,Yadav,vjyaav128@gmail.com,End User,
Vijay,Yadav,vjyaav129@gmail.com,End User,
Vijay,Yadav,vjyaav130@gmail.com,End User,
Vijay,Yadav,vjyaav131@gmail.com,End User,
Vijay,Yadav,vjyaav132@gmail.com,End User,
Vijay,Yadav,vjyaav133@gmail.com,End User,
Vijay,Yadav,vjyaav134@gmail.com,End User,
Vijay,Yadav,vjyaav135@gmail.com,End User,
Vijay,Yadav,vjyaav136@gmail.com,End User,
Vijay,Yadav,vjyaav137@gmail.com,End User,
Vijay,Yadav,vjyaav138@gmail.com,End User,
Vijay,Yadav,vjyaav139@gmail.com,End User,
Vijay,Yadav,vjyaav140@gmail.com,End User,
Vijay,Yadav,vjyaav141@gmail.com,End User,
Vijay,Yadav,vjyaav142@gmail.com,End User,
Vijay,Yadav,vjyaav143@gmail.com,End User,
Vijay,Yadav,vjyaav144@gmail.com,End User,
Vijay,Yadav,vjyaav145@gmail.com,End User,
Vijay,Yadav,vjyaav146@gmail.com,End User,
Vijay,Yadav,vjyaav147@gmail.com,End User,
Vijay,Yadav,vjyaav148@gmail.com,End User,
Vijay,Yadav,vjyaav149@gmail.com,End User,
Vijay,Yadav,vjyaav150@gmail.com,End User,
Vijay,Yadav,vjyaav151@gmail.com,End User,
Vijay,Yadav,vjyaav152@gmail.com,End User,
Vijay,Yadav,vjyaav153@gmail.com,End User,
Vijay,Yadav,vjyaav154@gmail.com,End User,
Vijay,Yadav,vjyaav155@gmail.com,End User,
Vijay,Yadav,vjyaav156@gmail.com,End User,
Vijay,Yadav,vjyaav157@gmail.com,End User,
Vijay,Yadav,vjyaav158@gmail.com,End User,
Vijay,Yadav,vjyaav159@gmail.com,End User,
Vijay,Yadav,vjyaav160@gmail.com,End User,
Vijay,Yadav,vjyaav161@gmail.com,End User,
Vijay,Yadav,vjyaav162@gmail.com,End User,
Vijay,Yadav,vjyaav163@gmail.com,End User,
Vijay,Yadav,vjyaav164@gmail.com,End User,
Vijay,Yadav,vjyaav165@gmail.com,End User,
Vijay,Yadav,vjyaav166@gmail.com,End User,
Vijay,Yadav,vjyaav167@gmail.com,End User,
Vijay,Yadav,vjyaav168@gmail.com,End User,
Vijay,Yadav,vjyaav169@gmail.com,End User,
Vijay,Yadav,vjyaav170@gmail.com,End User,
Vijay,Yadav,vjyaav171@gmail.com,End User,
Vijay,Yadav,vjyaav172@gmail.com,End User,
Vijay,Yadav,vjyaav173@gmail.com,End User,
Vijay,Yadav,vjyaav174@gmail.com,End User,
Vijay,Yadav,vjyaav175@gmail.com,End User,
Vijay,Yadav,vjyaav176@gmail.com,End User,
Vijay,Yadav,vjyaav177@gmail.com,End User,
Vijay,Yadav,vjyaav178@gmail.com,End User,
Vijay,Yadav,vjyaav179@gmail.com,End User,
Vijay,Yadav,vjyaav180@gmail.com,End User,
Vijay,Yadav,vjyaav181@gmail.com,End User,
Vijay,Yadav,vjyaav182@gmail.com,End User,
Vijay,Yadav,vjyaav183@gmail.com,End User,
Vijay,Yadav,vjyaav184@gmail.com,End User,
Vijay,Yadav,vjyaav185@gmail.com,End User,
Vijay,Yadav,vjyaav186@gmail.com,End User,
Vijay,Yadav,vjyaav187@gmail.com,End User,
Vijay,Yadav,vjyaav188@gmail.com,End User,
Vijay,Yadav,vjyaav189@gmail.com,End User,
Vijay,Yadav,vjyaav190@gmail.com,End User,
Vijay,Yadav,vjyaav191@gmail.com,End User,
Vijay,Yadav,vjyaav192@gmail.com,End User,
Vijay,Yadav,vjyaav193@gmail.com,End User,
Vijay,Yadav,vjyaav194@gmail.com,End User,
Vijay,Yadav,vjyaav195@gmail.com,End User,
Vijay,Yadav,vjyaav196@gmail.com,End User,
Vijay,Yadav,vjyaav197@gmail.com,End User,
Vijay,Yadav,vjyaav198@gmail.com,End User,
Vijay,Yadav,vjyaav199@gmail.com,End User,
Vijay,Yadav,vjyaav200@gmail.com,End User,
Vijay,Yadav,vjyaav201@gmail.com,End User,
Vijay,Yadav,vjyaav202@gmail.com,End User,
Vijay,Yadav,vjyaav203@gmail.com,End User,
Vijay,Yadav,vjyaav204@gmail.com,End User,
Vijay,Yadav,vjyaav205@gmail.com,End User,
Vijay,Yadav,vjyaav206@gmail.com,End User,
Vijay,Yadav,vjyaav207@gmail.com,End User,
Vijay,Yadav,vjyaav208@gmail.com,End User,
Vijay,Yadav,vjyaav209@gmail.com,End User,
Vijay,Yadav,vjyaav210@gmail.com,End User,
Vijay,Yadav,vjyaav211@gmail.com,End User,
Vijay,Yadav,vjyaav212@gmail.com,End User,
Vijay,Yadav,vjyaav213@gmail.com,End User,
Vijay,Yadav,vjyaav214@gmail.com,End User,
Vijay,Yadav,vjyaav215@gmail.com,End User,
Vijay,Yadav,vjyaav216@gmail.com,End User,
Vijay,Yadav,vjyaav217@gmail.com,End User,
Vijay,Yadav,vjyaav218@gmail.com,End User,
Vijay,Yadav,vjyaav219@gmail.com,End User,
Vijay,Yadav,vjyaav220@gmail.com,End User,
Vijay,Yadav,vjyaav221@gmail.com,End User,
Vijay,Yadav,vjyaav222@gmail.com,End User,
Vijay,Yadav,vjyaav223@gmail.com,End User,
Vijay,Yadav,vjyaav224@gmail.com,End User,
Vijay,Yadav,vjyaav225@gmail.com,End User,
Vijay,Yadav,vjyaav226@gmail.com,End User,
Vijay,Yadav,vjyaav227@gmail.com,End User,
Vijay,Yadav,vjyaav228@gmail.com,End User,
Vijay,Yadav,vjyaav229@gmail.com,End User,
Vijay,Yadav,vjyaav230@gmail.com,End User,
Vijay,Yadav,vjyaav231@gmail.com,End User,
Vijay,Yadav,vjyaav232@gmail.com,End User,
Vijay,Yadav,vjyaav233@gmail.com,End User,
Vijay,Yadav,vjyaav234@gmail.com,End User,
Vijay,Yadav,vjyaav235@gmail.com,End User,
Vijay,Yadav,vjyaav236@gmail.com,End User,
Vijay,Yadav,vjyaav237@gmail.com,End User,
Vijay,Yadav,vjyaav238@gmail.com,End User,
Vijay,Yadav,vjyaav239@gmail.com,End User,
Vijay,Yadav,vjyaav240@gmail.com,End User,
Vijay,Yadav,vjyaav241@gmail.com,End User,
Vijay,Yadav,vjyaav242@gmail.com,End User,
Vijay,Yadav,vjyaav243@gmail.com,End User,
Vijay,Yadav,vjyaav244@gmail.com,End User,
Vijay,Yadav,vjyaav245@gmail.com,End User,
Vijay,Yadav,vjyaav246@gmail.com,End User,
Vijay,Yadav,vjyaav247@gmail.com,End User,
Vijay,Yadav,vjyaav248@gmail.com,End User,
Vijay,Yadav,vjyaav249@gmail.com,End User,
Vijay,Yadav,vjyaav250@gmail.com,End User,
Vijay,Yadav,vjyaav251@gmail.com,End User,
1 First Name Last Name Email User Role Group
2 Vijay Yadav vjyaav1@gmail.com Admin
3 Vijay Yadav vjyaav2@gmail.com Builder
4 Vijay Yadav vjyaav3@gmail.com Builder
5 Vijay Yadav vjyaav4@gmail.com End User
6 Vijay Yadav vjyaav5@gmail.com End User
7 Vijay Yadav vjyaav6@gmail.com End User
8 Vijay Yadav vjyaav7@gmail.com End User
9 Vijay Yadav vjyaav8@gmail.com End User
10 Vijay Yadav vjyaav9@gmail.com End User
11 Vijay Yadav vjyaav10@gmail.com End User
12 Vijay Yadav vjyaav11@gmail.com End User
13 Vijay Yadav vjyaav12@gmail.com End User
14 Vijay Yadav vjyaav13@gmail.com End User
15 Vijay Yadav vjyaav14@gmail.com End User
16 Vijay Yadav vjyaav15@gmail.com End User
17 Vijay Yadav vjyaav16@gmail.com End User
18 Vijay Yadav vjyaav17@gmail.com End User
19 Vijay Yadav vjyaav18@gmail.com End User
20 Vijay Yadav vjyaav19@gmail.com End User
21 Vijay Yadav vjyaav20@gmail.com End User
22 Vijay Yadav vjyaav21@gmail.com End User
23 Vijay Yadav vjyaav22@gmail.com End User
24 Vijay Yadav vjyaav23@gmail.com End User
25 Vijay Yadav vjyaav24@gmail.com End User
26 Vijay Yadav vjyaav25@gmail.com End User
27 Vijay Yadav vjyaav26@gmail.com End User
28 Vijay Yadav vjyaav27@gmail.com End User
29 Vijay Yadav vjyaav28@gmail.com End User
30 Vijay Yadav vjyaav29@gmail.com End User
31 Vijay Yadav vjyaav30@gmail.com End User
32 Vijay Yadav vjyaav31@gmail.com End User
33 Vijay Yadav vjyaav32@gmail.com End User
34 Vijay Yadav vjyaav33@gmail.com End User
35 Vijay Yadav vjyaav34@gmail.com End User
36 Vijay Yadav vjyaav35@gmail.com End User
37 Vijay Yadav vjyaav36@gmail.com End User
38 Vijay Yadav vjyaav37@gmail.com End User
39 Vijay Yadav vjyaav38@gmail.com End User
40 Vijay Yadav vjyaav39@gmail.com End User
41 Vijay Yadav vjyaav40@gmail.com End User
42 Vijay Yadav vjyaav41@gmail.com End User
43 Vijay Yadav vjyaav42@gmail.com End User
44 Vijay Yadav vjyaav43@gmail.com End User
45 Vijay Yadav vjyaav44@gmail.com End User
46 Vijay Yadav vjyaav45@gmail.com End User
47 Vijay Yadav vjyaav46@gmail.com End User
48 Vijay Yadav vjyaav47@gmail.com End User
49 Vijay Yadav vjyaav48@gmail.com End User
50 Vijay Yadav vjyaav49@gmail.com End User
51 Vijay Yadav vjyaav50@gmail.com End User
52 Vijay Yadav vjyaav51@gmail.com End User
53 Vijay Yadav vjyaav52@gmail.com End User
54 Vijay Yadav vjyaav53@gmail.com End User
55 Vijay Yadav vjyaav54@gmail.com End User
56 Vijay Yadav vjyaav55@gmail.com End User
57 Vijay Yadav vjyaav56@gmail.com End User
58 Vijay Yadav vjyaav57@gmail.com End User
59 Vijay Yadav vjyaav58@gmail.com End User
60 Vijay Yadav vjyaav59@gmail.com End User
61 Vijay Yadav vjyaav60@gmail.com End User
62 Vijay Yadav vjyaav61@gmail.com End User
63 Vijay Yadav vjyaav62@gmail.com End User
64 Vijay Yadav vjyaav63@gmail.com End User
65 Vijay Yadav vjyaav64@gmail.com End User
66 Vijay Yadav vjyaav65@gmail.com End User
67 Vijay Yadav vjyaav66@gmail.com End User
68 Vijay Yadav vjyaav67@gmail.com End User
69 Vijay Yadav vjyaav68@gmail.com End User
70 Vijay Yadav vjyaav69@gmail.com End User
71 Vijay Yadav vjyaav70@gmail.com End User
72 Vijay Yadav vjyaav71@gmail.com End User
73 Vijay Yadav vjyaav72@gmail.com End User
74 Vijay Yadav vjyaav73@gmail.com End User
75 Vijay Yadav vjyaav74@gmail.com End User
76 Vijay Yadav vjyaav75@gmail.com End User
77 Vijay Yadav vjyaav76@gmail.com End User
78 Vijay Yadav vjyaav77@gmail.com End User
79 Vijay Yadav vjyaav78@gmail.com End User
80 Vijay Yadav vjyaav79@gmail.com End User
81 Vijay Yadav vjyaav80@gmail.com End User
82 Vijay Yadav vjyaav81@gmail.com End User
83 Vijay Yadav vjyaav82@gmail.com End User
84 Vijay Yadav vjyaav83@gmail.com End User
85 Vijay Yadav vjyaav84@gmail.com End User
86 Vijay Yadav vjyaav85@gmail.com End User
87 Vijay Yadav vjyaav86@gmail.com End User
88 Vijay Yadav vjyaav87@gmail.com End User
89 Vijay Yadav vjyaav88@gmail.com End User
90 Vijay Yadav vjyaav89@gmail.com End User
91 Vijay Yadav vjyaav90@gmail.com End User
92 Vijay Yadav vjyaav91@gmail.com End User
93 Vijay Yadav vjyaav92@gmail.com End User
94 Vijay Yadav vjyaav93@gmail.com End User
95 Vijay Yadav vjyaav94@gmail.com End User
96 Vijay Yadav vjyaav95@gmail.com End User
97 Vijay Yadav vjyaav96@gmail.com End User
98 Vijay Yadav vjyaav97@gmail.com End User
99 Vijay Yadav vjyaav98@gmail.com End User
100 Vijay Yadav vjyaav99@gmail.com End User
101 Vijay Yadav vjyaav100@gmail.com End User
102 Vijay Yadav vjyaav101@gmail.com End User
103 Vijay Yadav vjyaav102@gmail.com End User
104 Vijay Yadav vjyaav103@gmail.com End User
105 Vijay Yadav vjyaav104@gmail.com End User
106 Vijay Yadav vjyaav105@gmail.com End User
107 Vijay Yadav vjyaav106@gmail.com End User
108 Vijay Yadav vjyaav107@gmail.com End User
109 Vijay Yadav vjyaav108@gmail.com End User
110 Vijay Yadav vjyaav109@gmail.com End User
111 Vijay Yadav vjyaav110@gmail.com End User
112 Vijay Yadav vjyaav111@gmail.com End User
113 Vijay Yadav vjyaav112@gmail.com End User
114 Vijay Yadav vjyaav113@gmail.com End User
115 Vijay Yadav vjyaav114@gmail.com End User
116 Vijay Yadav vjyaav115@gmail.com End User
117 Vijay Yadav vjyaav116@gmail.com End User
118 Vijay Yadav vjyaav117@gmail.com End User
119 Vijay Yadav vjyaav118@gmail.com End User
120 Vijay Yadav vjyaav119@gmail.com End User
121 Vijay Yadav vjyaav120@gmail.com End User
122 Vijay Yadav vjyaav121@gmail.com End User
123 Vijay Yadav vjyaav122@gmail.com End User
124 Vijay Yadav vjyaav123@gmail.com End User
125 Vijay Yadav vjyaav124@gmail.com End User
126 Vijay Yadav vjyaav125@gmail.com End User
127 Vijay Yadav vjyaav126@gmail.com End User
128 Vijay Yadav vjyaav127@gmail.com End User
129 Vijay Yadav vjyaav128@gmail.com End User
130 Vijay Yadav vjyaav129@gmail.com End User
131 Vijay Yadav vjyaav130@gmail.com End User
132 Vijay Yadav vjyaav131@gmail.com End User
133 Vijay Yadav vjyaav132@gmail.com End User
134 Vijay Yadav vjyaav133@gmail.com End User
135 Vijay Yadav vjyaav134@gmail.com End User
136 Vijay Yadav vjyaav135@gmail.com End User
137 Vijay Yadav vjyaav136@gmail.com End User
138 Vijay Yadav vjyaav137@gmail.com End User
139 Vijay Yadav vjyaav138@gmail.com End User
140 Vijay Yadav vjyaav139@gmail.com End User
141 Vijay Yadav vjyaav140@gmail.com End User
142 Vijay Yadav vjyaav141@gmail.com End User
143 Vijay Yadav vjyaav142@gmail.com End User
144 Vijay Yadav vjyaav143@gmail.com End User
145 Vijay Yadav vjyaav144@gmail.com End User
146 Vijay Yadav vjyaav145@gmail.com End User
147 Vijay Yadav vjyaav146@gmail.com End User
148 Vijay Yadav vjyaav147@gmail.com End User
149 Vijay Yadav vjyaav148@gmail.com End User
150 Vijay Yadav vjyaav149@gmail.com End User
151 Vijay Yadav vjyaav150@gmail.com End User
152 Vijay Yadav vjyaav151@gmail.com End User
153 Vijay Yadav vjyaav152@gmail.com End User
154 Vijay Yadav vjyaav153@gmail.com End User
155 Vijay Yadav vjyaav154@gmail.com End User
156 Vijay Yadav vjyaav155@gmail.com End User
157 Vijay Yadav vjyaav156@gmail.com End User
158 Vijay Yadav vjyaav157@gmail.com End User
159 Vijay Yadav vjyaav158@gmail.com End User
160 Vijay Yadav vjyaav159@gmail.com End User
161 Vijay Yadav vjyaav160@gmail.com End User
162 Vijay Yadav vjyaav161@gmail.com End User
163 Vijay Yadav vjyaav162@gmail.com End User
164 Vijay Yadav vjyaav163@gmail.com End User
165 Vijay Yadav vjyaav164@gmail.com End User
166 Vijay Yadav vjyaav165@gmail.com End User
167 Vijay Yadav vjyaav166@gmail.com End User
168 Vijay Yadav vjyaav167@gmail.com End User
169 Vijay Yadav vjyaav168@gmail.com End User
170 Vijay Yadav vjyaav169@gmail.com End User
171 Vijay Yadav vjyaav170@gmail.com End User
172 Vijay Yadav vjyaav171@gmail.com End User
173 Vijay Yadav vjyaav172@gmail.com End User
174 Vijay Yadav vjyaav173@gmail.com End User
175 Vijay Yadav vjyaav174@gmail.com End User
176 Vijay Yadav vjyaav175@gmail.com End User
177 Vijay Yadav vjyaav176@gmail.com End User
178 Vijay Yadav vjyaav177@gmail.com End User
179 Vijay Yadav vjyaav178@gmail.com End User
180 Vijay Yadav vjyaav179@gmail.com End User
181 Vijay Yadav vjyaav180@gmail.com End User
182 Vijay Yadav vjyaav181@gmail.com End User
183 Vijay Yadav vjyaav182@gmail.com End User
184 Vijay Yadav vjyaav183@gmail.com End User
185 Vijay Yadav vjyaav184@gmail.com End User
186 Vijay Yadav vjyaav185@gmail.com End User
187 Vijay Yadav vjyaav186@gmail.com End User
188 Vijay Yadav vjyaav187@gmail.com End User
189 Vijay Yadav vjyaav188@gmail.com End User
190 Vijay Yadav vjyaav189@gmail.com End User
191 Vijay Yadav vjyaav190@gmail.com End User
192 Vijay Yadav vjyaav191@gmail.com End User
193 Vijay Yadav vjyaav192@gmail.com End User
194 Vijay Yadav vjyaav193@gmail.com End User
195 Vijay Yadav vjyaav194@gmail.com End User
196 Vijay Yadav vjyaav195@gmail.com End User
197 Vijay Yadav vjyaav196@gmail.com End User
198 Vijay Yadav vjyaav197@gmail.com End User
199 Vijay Yadav vjyaav198@gmail.com End User
200 Vijay Yadav vjyaav199@gmail.com End User
201 Vijay Yadav vjyaav200@gmail.com End User
202 Vijay Yadav vjyaav201@gmail.com End User
203 Vijay Yadav vjyaav202@gmail.com End User
204 Vijay Yadav vjyaav203@gmail.com End User
205 Vijay Yadav vjyaav204@gmail.com End User
206 Vijay Yadav vjyaav205@gmail.com End User
207 Vijay Yadav vjyaav206@gmail.com End User
208 Vijay Yadav vjyaav207@gmail.com End User
209 Vijay Yadav vjyaav208@gmail.com End User
210 Vijay Yadav vjyaav209@gmail.com End User
211 Vijay Yadav vjyaav210@gmail.com End User
212 Vijay Yadav vjyaav211@gmail.com End User
213 Vijay Yadav vjyaav212@gmail.com End User
214 Vijay Yadav vjyaav213@gmail.com End User
215 Vijay Yadav vjyaav214@gmail.com End User
216 Vijay Yadav vjyaav215@gmail.com End User
217 Vijay Yadav vjyaav216@gmail.com End User
218 Vijay Yadav vjyaav217@gmail.com End User
219 Vijay Yadav vjyaav218@gmail.com End User
220 Vijay Yadav vjyaav219@gmail.com End User
221 Vijay Yadav vjyaav220@gmail.com End User
222 Vijay Yadav vjyaav221@gmail.com End User
223 Vijay Yadav vjyaav222@gmail.com End User
224 Vijay Yadav vjyaav223@gmail.com End User
225 Vijay Yadav vjyaav224@gmail.com End User
226 Vijay Yadav vjyaav225@gmail.com End User
227 Vijay Yadav vjyaav226@gmail.com End User
228 Vijay Yadav vjyaav227@gmail.com End User
229 Vijay Yadav vjyaav228@gmail.com End User
230 Vijay Yadav vjyaav229@gmail.com End User
231 Vijay Yadav vjyaav230@gmail.com End User
232 Vijay Yadav vjyaav231@gmail.com End User
233 Vijay Yadav vjyaav232@gmail.com End User
234 Vijay Yadav vjyaav233@gmail.com End User
235 Vijay Yadav vjyaav234@gmail.com End User
236 Vijay Yadav vjyaav235@gmail.com End User
237 Vijay Yadav vjyaav236@gmail.com End User
238 Vijay Yadav vjyaav237@gmail.com End User
239 Vijay Yadav vjyaav238@gmail.com End User
240 Vijay Yadav vjyaav239@gmail.com End User
241 Vijay Yadav vjyaav240@gmail.com End User
242 Vijay Yadav vjyaav241@gmail.com End User
243 Vijay Yadav vjyaav242@gmail.com End User
244 Vijay Yadav vjyaav243@gmail.com End User
245 Vijay Yadav vjyaav244@gmail.com End User
246 Vijay Yadav vjyaav245@gmail.com End User
247 Vijay Yadav vjyaav246@gmail.com End User
248 Vijay Yadav vjyaav247@gmail.com End User
249 Vijay Yadav vjyaav248@gmail.com End User
250 Vijay Yadav vjyaav249@gmail.com End User
251 Vijay Yadav vjyaav250@gmail.com End User
252 Vijay Yadav vjyaav251@gmail.com End User

View file

@ -0,0 +1,252 @@
First Name,Last Name,Email,User Role,Group,Metadata
Vijay,Yadav,vjyaav1@gmail.com,Admin,,
Vijay,Yadav,vjyaav2@gmail.com,Builder,,
Vijay,Yadav,vjyaav3@gmail.com,Builder,,
Vijay,Yadav,vjyaav4@gmail.com,End User,,
Vijay,Yadav,vjyaav5@gmail.com,End User,,
Vijay,Yadav,vjyaav6@gmail.com,End User,,
Vijay,Yadav,vjyaav7@gmail.com,End User,,
Vijay,Yadav,vjyaav8@gmail.com,End User,,
Vijay,Yadav,vjyaav9@gmail.com,End User,,
Vijay,Yadav,vjyaav10@gmail.com,End User,,
Vijay,Yadav,vjyaav11@gmail.com,End User,,
Vijay,Yadav,vjyaav12@gmail.com,End User,,
Vijay,Yadav,vjyaav13@gmail.com,End User,,
Vijay,Yadav,vjyaav14@gmail.com,End User,,
Vijay,Yadav,vjyaav15@gmail.com,End User,,
Vijay,Yadav,vjyaav16@gmail.com,End User,,
Vijay,Yadav,vjyaav17@gmail.com,End User,,
Vijay,Yadav,vjyaav18@gmail.com,End User,,
Vijay,Yadav,vjyaav19@gmail.com,End User,,
Vijay,Yadav,vjyaav20@gmail.com,End User,,
Vijay,Yadav,vjyaav21@gmail.com,End User,,
Vijay,Yadav,vjyaav22@gmail.com,End User,,
Vijay,Yadav,vjyaav23@gmail.com,End User,,
Vijay,Yadav,vjyaav24@gmail.com,End User,,
Vijay,Yadav,vjyaav25@gmail.com,End User,,
Vijay,Yadav,vjyaav26@gmail.com,End User,,
Vijay,Yadav,vjyaav27@gmail.com,End User,,
Vijay,Yadav,vjyaav28@gmail.com,End User,,
Vijay,Yadav,vjyaav29@gmail.com,End User,,
Vijay,Yadav,vjyaav30@gmail.com,End User,,
Vijay,Yadav,vjyaav31@gmail.com,End User,,
Vijay,Yadav,vjyaav32@gmail.com,End User,,
Vijay,Yadav,vjyaav33@gmail.com,End User,,
Vijay,Yadav,vjyaav34@gmail.com,End User,,
Vijay,Yadav,vjyaav35@gmail.com,End User,,
Vijay,Yadav,vjyaav36@gmail.com,End User,,
Vijay,Yadav,vjyaav37@gmail.com,End User,,
Vijay,Yadav,vjyaav38@gmail.com,End User,,
Vijay,Yadav,vjyaav39@gmail.com,End User,,
Vijay,Yadav,vjyaav40@gmail.com,End User,,
Vijay,Yadav,vjyaav41@gmail.com,End User,,
Vijay,Yadav,vjyaav42@gmail.com,End User,,
Vijay,Yadav,vjyaav43@gmail.com,End User,,
Vijay,Yadav,vjyaav44@gmail.com,End User,,
Vijay,Yadav,vjyaav45@gmail.com,End User,,
Vijay,Yadav,vjyaav46@gmail.com,End User,,
Vijay,Yadav,vjyaav47@gmail.com,End User,,
Vijay,Yadav,vjyaav48@gmail.com,End User,,
Vijay,Yadav,vjyaav49@gmail.com,End User,,
Vijay,Yadav,vjyaav50@gmail.com,End User,,
Vijay,Yadav,vjyaav51@gmail.com,End User,,
Vijay,Yadav,vjyaav52@gmail.com,End User,,
Vijay,Yadav,vjyaav53@gmail.com,End User,,
Vijay,Yadav,vjyaav54@gmail.com,End User,,
Vijay,Yadav,vjyaav55@gmail.com,End User,,
Vijay,Yadav,vjyaav56@gmail.com,End User,,
Vijay,Yadav,vjyaav57@gmail.com,End User,,
Vijay,Yadav,vjyaav58@gmail.com,End User,,
Vijay,Yadav,vjyaav59@gmail.com,End User,,
Vijay,Yadav,vjyaav60@gmail.com,End User,,
Vijay,Yadav,vjyaav61@gmail.com,End User,,
Vijay,Yadav,vjyaav62@gmail.com,End User,,
Vijay,Yadav,vjyaav63@gmail.com,End User,,
Vijay,Yadav,vjyaav64@gmail.com,End User,,
Vijay,Yadav,vjyaav65@gmail.com,End User,,
Vijay,Yadav,vjyaav66@gmail.com,End User,,
Vijay,Yadav,vjyaav67@gmail.com,End User,,
Vijay,Yadav,vjyaav68@gmail.com,End User,,
Vijay,Yadav,vjyaav69@gmail.com,End User,,
Vijay,Yadav,vjyaav70@gmail.com,End User,,
Vijay,Yadav,vjyaav71@gmail.com,End User,,
Vijay,Yadav,vjyaav72@gmail.com,End User,,
Vijay,Yadav,vjyaav73@gmail.com,End User,,
Vijay,Yadav,vjyaav74@gmail.com,End User,,
Vijay,Yadav,vjyaav75@gmail.com,End User,,
Vijay,Yadav,vjyaav76@gmail.com,End User,,
Vijay,Yadav,vjyaav77@gmail.com,End User,,
Vijay,Yadav,vjyaav78@gmail.com,End User,,
Vijay,Yadav,vjyaav79@gmail.com,End User,,
Vijay,Yadav,vjyaav80@gmail.com,End User,,
Vijay,Yadav,vjyaav81@gmail.com,End User,,
Vijay,Yadav,vjyaav82@gmail.com,End User,,
Vijay,Yadav,vjyaav83@gmail.com,End User,,
Vijay,Yadav,vjyaav84@gmail.com,End User,,
Vijay,Yadav,vjyaav85@gmail.com,End User,,
Vijay,Yadav,vjyaav86@gmail.com,End User,,
Vijay,Yadav,vjyaav87@gmail.com,End User,,
Vijay,Yadav,vjyaav88@gmail.com,End User,,
Vijay,Yadav,vjyaav89@gmail.com,End User,,
Vijay,Yadav,vjyaav90@gmail.com,End User,,
Vijay,Yadav,vjyaav91@gmail.com,End User,,
Vijay,Yadav,vjyaav92@gmail.com,End User,,
Vijay,Yadav,vjyaav93@gmail.com,End User,,
Vijay,Yadav,vjyaav94@gmail.com,End User,,
Vijay,Yadav,vjyaav95@gmail.com,End User,,
Vijay,Yadav,vjyaav96@gmail.com,End User,,
Vijay,Yadav,vjyaav97@gmail.com,End User,,
Vijay,Yadav,vjyaav98@gmail.com,End User,,
Vijay,Yadav,vjyaav99@gmail.com,End User,,
Vijay,Yadav,vjyaav100@gmail.com,End User,,
Vijay,Yadav,vjyaav101@gmail.com,End User,,
Vijay,Yadav,vjyaav102@gmail.com,End User,,
Vijay,Yadav,vjyaav103@gmail.com,End User,,
Vijay,Yadav,vjyaav104@gmail.com,End User,,
Vijay,Yadav,vjyaav105@gmail.com,End User,,
Vijay,Yadav,vjyaav106@gmail.com,End User,,
Vijay,Yadav,vjyaav107@gmail.com,End User,,
Vijay,Yadav,vjyaav108@gmail.com,End User,,
Vijay,Yadav,vjyaav109@gmail.com,End User,,
Vijay,Yadav,vjyaav110@gmail.com,End User,,
Vijay,Yadav,vjyaav111@gmail.com,End User,,
Vijay,Yadav,vjyaav112@gmail.com,End User,,
Vijay,Yadav,vjyaav113@gmail.com,End User,,
Vijay,Yadav,vjyaav114@gmail.com,End User,,
Vijay,Yadav,vjyaav115@gmail.com,End User,,
Vijay,Yadav,vjyaav116@gmail.com,End User,,
Vijay,Yadav,vjyaav117@gmail.com,End User,,
Vijay,Yadav,vjyaav118@gmail.com,End User,,
Vijay,Yadav,vjyaav119@gmail.com,End User,,
Vijay,Yadav,vjyaav120@gmail.com,End User,,
Vijay,Yadav,vjyaav121@gmail.com,End User,,
Vijay,Yadav,vjyaav122@gmail.com,End User,,
Vijay,Yadav,vjyaav123@gmail.com,End User,,
Vijay,Yadav,vjyaav124@gmail.com,End User,,
Vijay,Yadav,vjyaav125@gmail.com,End User,,
Vijay,Yadav,vjyaav126@gmail.com,End User,,
Vijay,Yadav,vjyaav127@gmail.com,End User,,
Vijay,Yadav,vjyaav128@gmail.com,End User,,
Vijay,Yadav,vjyaav129@gmail.com,End User,,
Vijay,Yadav,vjyaav130@gmail.com,End User,,
Vijay,Yadav,vjyaav131@gmail.com,End User,,
Vijay,Yadav,vjyaav132@gmail.com,End User,,
Vijay,Yadav,vjyaav133@gmail.com,End User,,
Vijay,Yadav,vjyaav134@gmail.com,End User,,
Vijay,Yadav,vjyaav135@gmail.com,End User,,
Vijay,Yadav,vjyaav136@gmail.com,End User,,
Vijay,Yadav,vjyaav137@gmail.com,End User,,
Vijay,Yadav,vjyaav138@gmail.com,End User,,
Vijay,Yadav,vjyaav139@gmail.com,End User,,
Vijay,Yadav,vjyaav140@gmail.com,End User,,
Vijay,Yadav,vjyaav141@gmail.com,End User,,
Vijay,Yadav,vjyaav142@gmail.com,End User,,
Vijay,Yadav,vjyaav143@gmail.com,End User,,
Vijay,Yadav,vjyaav144@gmail.com,End User,,
Vijay,Yadav,vjyaav145@gmail.com,End User,,
Vijay,Yadav,vjyaav146@gmail.com,End User,,
Vijay,Yadav,vjyaav147@gmail.com,End User,,
Vijay,Yadav,vjyaav148@gmail.com,End User,,
Vijay,Yadav,vjyaav149@gmail.com,End User,,
Vijay,Yadav,vjyaav150@gmail.com,End User,,
Vijay,Yadav,vjyaav151@gmail.com,End User,,
Vijay,Yadav,vjyaav152@gmail.com,End User,,
Vijay,Yadav,vjyaav153@gmail.com,End User,,
Vijay,Yadav,vjyaav154@gmail.com,End User,,
Vijay,Yadav,vjyaav155@gmail.com,End User,,
Vijay,Yadav,vjyaav156@gmail.com,End User,,
Vijay,Yadav,vjyaav157@gmail.com,End User,,
Vijay,Yadav,vjyaav158@gmail.com,End User,,
Vijay,Yadav,vjyaav159@gmail.com,End User,,
Vijay,Yadav,vjyaav160@gmail.com,End User,,
Vijay,Yadav,vjyaav161@gmail.com,End User,,
Vijay,Yadav,vjyaav162@gmail.com,End User,,
Vijay,Yadav,vjyaav163@gmail.com,End User,,
Vijay,Yadav,vjyaav164@gmail.com,End User,,
Vijay,Yadav,vjyaav165@gmail.com,End User,,
Vijay,Yadav,vjyaav166@gmail.com,End User,,
Vijay,Yadav,vjyaav167@gmail.com,End User,,
Vijay,Yadav,vjyaav168@gmail.com,End User,,
Vijay,Yadav,vjyaav169@gmail.com,End User,,
Vijay,Yadav,vjyaav170@gmail.com,End User,,
Vijay,Yadav,vjyaav171@gmail.com,End User,,
Vijay,Yadav,vjyaav172@gmail.com,End User,,
Vijay,Yadav,vjyaav173@gmail.com,End User,,
Vijay,Yadav,vjyaav174@gmail.com,End User,,
Vijay,Yadav,vjyaav175@gmail.com,End User,,
Vijay,Yadav,vjyaav176@gmail.com,End User,,
Vijay,Yadav,vjyaav177@gmail.com,End User,,
Vijay,Yadav,vjyaav178@gmail.com,End User,,
Vijay,Yadav,vjyaav179@gmail.com,End User,,
Vijay,Yadav,vjyaav180@gmail.com,End User,,
Vijay,Yadav,vjyaav181@gmail.com,End User,,
Vijay,Yadav,vjyaav182@gmail.com,End User,,
Vijay,Yadav,vjyaav183@gmail.com,End User,,
Vijay,Yadav,vjyaav184@gmail.com,End User,,
Vijay,Yadav,vjyaav185@gmail.com,End User,,
Vijay,Yadav,vjyaav186@gmail.com,End User,,
Vijay,Yadav,vjyaav187@gmail.com,End User,,
Vijay,Yadav,vjyaav188@gmail.com,End User,,
Vijay,Yadav,vjyaav189@gmail.com,End User,,
Vijay,Yadav,vjyaav190@gmail.com,End User,,
Vijay,Yadav,vjyaav191@gmail.com,End User,,
Vijay,Yadav,vjyaav192@gmail.com,End User,,
Vijay,Yadav,vjyaav193@gmail.com,End User,,
Vijay,Yadav,vjyaav194@gmail.com,End User,,
Vijay,Yadav,vjyaav195@gmail.com,End User,,
Vijay,Yadav,vjyaav196@gmail.com,End User,,
Vijay,Yadav,vjyaav197@gmail.com,End User,,
Vijay,Yadav,vjyaav198@gmail.com,End User,,
Vijay,Yadav,vjyaav199@gmail.com,End User,,
Vijay,Yadav,vjyaav200@gmail.com,End User,,
Vijay,Yadav,vjyaav201@gmail.com,End User,,
Vijay,Yadav,vjyaav202@gmail.com,End User,,
Vijay,Yadav,vjyaav203@gmail.com,End User,,
Vijay,Yadav,vjyaav204@gmail.com,End User,,
Vijay,Yadav,vjyaav205@gmail.com,End User,,
Vijay,Yadav,vjyaav206@gmail.com,End User,,
Vijay,Yadav,vjyaav207@gmail.com,End User,,
Vijay,Yadav,vjyaav208@gmail.com,End User,,
Vijay,Yadav,vjyaav209@gmail.com,End User,,
Vijay,Yadav,vjyaav210@gmail.com,End User,,
Vijay,Yadav,vjyaav211@gmail.com,End User,,
Vijay,Yadav,vjyaav212@gmail.com,End User,,
Vijay,Yadav,vjyaav213@gmail.com,End User,,
Vijay,Yadav,vjyaav214@gmail.com,End User,,
Vijay,Yadav,vjyaav215@gmail.com,End User,,
Vijay,Yadav,vjyaav216@gmail.com,End User,,
Vijay,Yadav,vjyaav217@gmail.com,End User,,
Vijay,Yadav,vjyaav218@gmail.com,End User,,
Vijay,Yadav,vjyaav219@gmail.com,End User,,
Vijay,Yadav,vjyaav220@gmail.com,End User,,
Vijay,Yadav,vjyaav221@gmail.com,End User,,
Vijay,Yadav,vjyaav222@gmail.com,End User,,
Vijay,Yadav,vjyaav223@gmail.com,End User,,
Vijay,Yadav,vjyaav224@gmail.com,End User,,
Vijay,Yadav,vjyaav225@gmail.com,End User,,
Vijay,Yadav,vjyaav226@gmail.com,End User,,
Vijay,Yadav,vjyaav227@gmail.com,End User,,
Vijay,Yadav,vjyaav228@gmail.com,End User,,
Vijay,Yadav,vjyaav229@gmail.com,End User,,
Vijay,Yadav,vjyaav230@gmail.com,End User,,
Vijay,Yadav,vjyaav231@gmail.com,End User,,
Vijay,Yadav,vjyaav232@gmail.com,End User,,
Vijay,Yadav,vjyaav233@gmail.com,End User,,
Vijay,Yadav,vjyaav234@gmail.com,End User,,
Vijay,Yadav,vjyaav235@gmail.com,End User,,
Vijay,Yadav,vjyaav236@gmail.com,End User,,
Vijay,Yadav,vjyaav237@gmail.com,End User,,
Vijay,Yadav,vjyaav238@gmail.com,End User,,
Vijay,Yadav,vjyaav239@gmail.com,End User,,
Vijay,Yadav,vjyaav240@gmail.com,End User,,
Vijay,Yadav,vjyaav241@gmail.com,End User,,
Vijay,Yadav,vjyaav242@gmail.com,End User,,
Vijay,Yadav,vjyaav243@gmail.com,End User,,
Vijay,Yadav,vjyaav244@gmail.com,End User,,
Vijay,Yadav,vjyaav245@gmail.com,End User,,
Vijay,Yadav,vjyaav246@gmail.com,End User,,
Vijay,Yadav,vjyaav247@gmail.com,End User,,
Vijay,Yadav,vjyaav248@gmail.com,End User,,
Vijay,Yadav,vjyaav249@gmail.com,End User,,
Vijay,Yadav,vjyaav250@gmail.com,End User,,
Vijay,Yadav,vjyaav251@gmail.com,End User,,
1 First Name Last Name Email User Role Group Metadata
2 Vijay Yadav vjyaav1@gmail.com Admin
3 Vijay Yadav vjyaav2@gmail.com Builder
4 Vijay Yadav vjyaav3@gmail.com Builder
5 Vijay Yadav vjyaav4@gmail.com End User
6 Vijay Yadav vjyaav5@gmail.com End User
7 Vijay Yadav vjyaav6@gmail.com End User
8 Vijay Yadav vjyaav7@gmail.com End User
9 Vijay Yadav vjyaav8@gmail.com End User
10 Vijay Yadav vjyaav9@gmail.com End User
11 Vijay Yadav vjyaav10@gmail.com End User
12 Vijay Yadav vjyaav11@gmail.com End User
13 Vijay Yadav vjyaav12@gmail.com End User
14 Vijay Yadav vjyaav13@gmail.com End User
15 Vijay Yadav vjyaav14@gmail.com End User
16 Vijay Yadav vjyaav15@gmail.com End User
17 Vijay Yadav vjyaav16@gmail.com End User
18 Vijay Yadav vjyaav17@gmail.com End User
19 Vijay Yadav vjyaav18@gmail.com End User
20 Vijay Yadav vjyaav19@gmail.com End User
21 Vijay Yadav vjyaav20@gmail.com End User
22 Vijay Yadav vjyaav21@gmail.com End User
23 Vijay Yadav vjyaav22@gmail.com End User
24 Vijay Yadav vjyaav23@gmail.com End User
25 Vijay Yadav vjyaav24@gmail.com End User
26 Vijay Yadav vjyaav25@gmail.com End User
27 Vijay Yadav vjyaav26@gmail.com End User
28 Vijay Yadav vjyaav27@gmail.com End User
29 Vijay Yadav vjyaav28@gmail.com End User
30 Vijay Yadav vjyaav29@gmail.com End User
31 Vijay Yadav vjyaav30@gmail.com End User
32 Vijay Yadav vjyaav31@gmail.com End User
33 Vijay Yadav vjyaav32@gmail.com End User
34 Vijay Yadav vjyaav33@gmail.com End User
35 Vijay Yadav vjyaav34@gmail.com End User
36 Vijay Yadav vjyaav35@gmail.com End User
37 Vijay Yadav vjyaav36@gmail.com End User
38 Vijay Yadav vjyaav37@gmail.com End User
39 Vijay Yadav vjyaav38@gmail.com End User
40 Vijay Yadav vjyaav39@gmail.com End User
41 Vijay Yadav vjyaav40@gmail.com End User
42 Vijay Yadav vjyaav41@gmail.com End User
43 Vijay Yadav vjyaav42@gmail.com End User
44 Vijay Yadav vjyaav43@gmail.com End User
45 Vijay Yadav vjyaav44@gmail.com End User
46 Vijay Yadav vjyaav45@gmail.com End User
47 Vijay Yadav vjyaav46@gmail.com End User
48 Vijay Yadav vjyaav47@gmail.com End User
49 Vijay Yadav vjyaav48@gmail.com End User
50 Vijay Yadav vjyaav49@gmail.com End User
51 Vijay Yadav vjyaav50@gmail.com End User
52 Vijay Yadav vjyaav51@gmail.com End User
53 Vijay Yadav vjyaav52@gmail.com End User
54 Vijay Yadav vjyaav53@gmail.com End User
55 Vijay Yadav vjyaav54@gmail.com End User
56 Vijay Yadav vjyaav55@gmail.com End User
57 Vijay Yadav vjyaav56@gmail.com End User
58 Vijay Yadav vjyaav57@gmail.com End User
59 Vijay Yadav vjyaav58@gmail.com End User
60 Vijay Yadav vjyaav59@gmail.com End User
61 Vijay Yadav vjyaav60@gmail.com End User
62 Vijay Yadav vjyaav61@gmail.com End User
63 Vijay Yadav vjyaav62@gmail.com End User
64 Vijay Yadav vjyaav63@gmail.com End User
65 Vijay Yadav vjyaav64@gmail.com End User
66 Vijay Yadav vjyaav65@gmail.com End User
67 Vijay Yadav vjyaav66@gmail.com End User
68 Vijay Yadav vjyaav67@gmail.com End User
69 Vijay Yadav vjyaav68@gmail.com End User
70 Vijay Yadav vjyaav69@gmail.com End User
71 Vijay Yadav vjyaav70@gmail.com End User
72 Vijay Yadav vjyaav71@gmail.com End User
73 Vijay Yadav vjyaav72@gmail.com End User
74 Vijay Yadav vjyaav73@gmail.com End User
75 Vijay Yadav vjyaav74@gmail.com End User
76 Vijay Yadav vjyaav75@gmail.com End User
77 Vijay Yadav vjyaav76@gmail.com End User
78 Vijay Yadav vjyaav77@gmail.com End User
79 Vijay Yadav vjyaav78@gmail.com End User
80 Vijay Yadav vjyaav79@gmail.com End User
81 Vijay Yadav vjyaav80@gmail.com End User
82 Vijay Yadav vjyaav81@gmail.com End User
83 Vijay Yadav vjyaav82@gmail.com End User
84 Vijay Yadav vjyaav83@gmail.com End User
85 Vijay Yadav vjyaav84@gmail.com End User
86 Vijay Yadav vjyaav85@gmail.com End User
87 Vijay Yadav vjyaav86@gmail.com End User
88 Vijay Yadav vjyaav87@gmail.com End User
89 Vijay Yadav vjyaav88@gmail.com End User
90 Vijay Yadav vjyaav89@gmail.com End User
91 Vijay Yadav vjyaav90@gmail.com End User
92 Vijay Yadav vjyaav91@gmail.com End User
93 Vijay Yadav vjyaav92@gmail.com End User
94 Vijay Yadav vjyaav93@gmail.com End User
95 Vijay Yadav vjyaav94@gmail.com End User
96 Vijay Yadav vjyaav95@gmail.com End User
97 Vijay Yadav vjyaav96@gmail.com End User
98 Vijay Yadav vjyaav97@gmail.com End User
99 Vijay Yadav vjyaav98@gmail.com End User
100 Vijay Yadav vjyaav99@gmail.com End User
101 Vijay Yadav vjyaav100@gmail.com End User
102 Vijay Yadav vjyaav101@gmail.com End User
103 Vijay Yadav vjyaav102@gmail.com End User
104 Vijay Yadav vjyaav103@gmail.com End User
105 Vijay Yadav vjyaav104@gmail.com End User
106 Vijay Yadav vjyaav105@gmail.com End User
107 Vijay Yadav vjyaav106@gmail.com End User
108 Vijay Yadav vjyaav107@gmail.com End User
109 Vijay Yadav vjyaav108@gmail.com End User
110 Vijay Yadav vjyaav109@gmail.com End User
111 Vijay Yadav vjyaav110@gmail.com End User
112 Vijay Yadav vjyaav111@gmail.com End User
113 Vijay Yadav vjyaav112@gmail.com End User
114 Vijay Yadav vjyaav113@gmail.com End User
115 Vijay Yadav vjyaav114@gmail.com End User
116 Vijay Yadav vjyaav115@gmail.com End User
117 Vijay Yadav vjyaav116@gmail.com End User
118 Vijay Yadav vjyaav117@gmail.com End User
119 Vijay Yadav vjyaav118@gmail.com End User
120 Vijay Yadav vjyaav119@gmail.com End User
121 Vijay Yadav vjyaav120@gmail.com End User
122 Vijay Yadav vjyaav121@gmail.com End User
123 Vijay Yadav vjyaav122@gmail.com End User
124 Vijay Yadav vjyaav123@gmail.com End User
125 Vijay Yadav vjyaav124@gmail.com End User
126 Vijay Yadav vjyaav125@gmail.com End User
127 Vijay Yadav vjyaav126@gmail.com End User
128 Vijay Yadav vjyaav127@gmail.com End User
129 Vijay Yadav vjyaav128@gmail.com End User
130 Vijay Yadav vjyaav129@gmail.com End User
131 Vijay Yadav vjyaav130@gmail.com End User
132 Vijay Yadav vjyaav131@gmail.com End User
133 Vijay Yadav vjyaav132@gmail.com End User
134 Vijay Yadav vjyaav133@gmail.com End User
135 Vijay Yadav vjyaav134@gmail.com End User
136 Vijay Yadav vjyaav135@gmail.com End User
137 Vijay Yadav vjyaav136@gmail.com End User
138 Vijay Yadav vjyaav137@gmail.com End User
139 Vijay Yadav vjyaav138@gmail.com End User
140 Vijay Yadav vjyaav139@gmail.com End User
141 Vijay Yadav vjyaav140@gmail.com End User
142 Vijay Yadav vjyaav141@gmail.com End User
143 Vijay Yadav vjyaav142@gmail.com End User
144 Vijay Yadav vjyaav143@gmail.com End User
145 Vijay Yadav vjyaav144@gmail.com End User
146 Vijay Yadav vjyaav145@gmail.com End User
147 Vijay Yadav vjyaav146@gmail.com End User
148 Vijay Yadav vjyaav147@gmail.com End User
149 Vijay Yadav vjyaav148@gmail.com End User
150 Vijay Yadav vjyaav149@gmail.com End User
151 Vijay Yadav vjyaav150@gmail.com End User
152 Vijay Yadav vjyaav151@gmail.com End User
153 Vijay Yadav vjyaav152@gmail.com End User
154 Vijay Yadav vjyaav153@gmail.com End User
155 Vijay Yadav vjyaav154@gmail.com End User
156 Vijay Yadav vjyaav155@gmail.com End User
157 Vijay Yadav vjyaav156@gmail.com End User
158 Vijay Yadav vjyaav157@gmail.com End User
159 Vijay Yadav vjyaav158@gmail.com End User
160 Vijay Yadav vjyaav159@gmail.com End User
161 Vijay Yadav vjyaav160@gmail.com End User
162 Vijay Yadav vjyaav161@gmail.com End User
163 Vijay Yadav vjyaav162@gmail.com End User
164 Vijay Yadav vjyaav163@gmail.com End User
165 Vijay Yadav vjyaav164@gmail.com End User
166 Vijay Yadav vjyaav165@gmail.com End User
167 Vijay Yadav vjyaav166@gmail.com End User
168 Vijay Yadav vjyaav167@gmail.com End User
169 Vijay Yadav vjyaav168@gmail.com End User
170 Vijay Yadav vjyaav169@gmail.com End User
171 Vijay Yadav vjyaav170@gmail.com End User
172 Vijay Yadav vjyaav171@gmail.com End User
173 Vijay Yadav vjyaav172@gmail.com End User
174 Vijay Yadav vjyaav173@gmail.com End User
175 Vijay Yadav vjyaav174@gmail.com End User
176 Vijay Yadav vjyaav175@gmail.com End User
177 Vijay Yadav vjyaav176@gmail.com End User
178 Vijay Yadav vjyaav177@gmail.com End User
179 Vijay Yadav vjyaav178@gmail.com End User
180 Vijay Yadav vjyaav179@gmail.com End User
181 Vijay Yadav vjyaav180@gmail.com End User
182 Vijay Yadav vjyaav181@gmail.com End User
183 Vijay Yadav vjyaav182@gmail.com End User
184 Vijay Yadav vjyaav183@gmail.com End User
185 Vijay Yadav vjyaav184@gmail.com End User
186 Vijay Yadav vjyaav185@gmail.com End User
187 Vijay Yadav vjyaav186@gmail.com End User
188 Vijay Yadav vjyaav187@gmail.com End User
189 Vijay Yadav vjyaav188@gmail.com End User
190 Vijay Yadav vjyaav189@gmail.com End User
191 Vijay Yadav vjyaav190@gmail.com End User
192 Vijay Yadav vjyaav191@gmail.com End User
193 Vijay Yadav vjyaav192@gmail.com End User
194 Vijay Yadav vjyaav193@gmail.com End User
195 Vijay Yadav vjyaav194@gmail.com End User
196 Vijay Yadav vjyaav195@gmail.com End User
197 Vijay Yadav vjyaav196@gmail.com End User
198 Vijay Yadav vjyaav197@gmail.com End User
199 Vijay Yadav vjyaav198@gmail.com End User
200 Vijay Yadav vjyaav199@gmail.com End User
201 Vijay Yadav vjyaav200@gmail.com End User
202 Vijay Yadav vjyaav201@gmail.com End User
203 Vijay Yadav vjyaav202@gmail.com End User
204 Vijay Yadav vjyaav203@gmail.com End User
205 Vijay Yadav vjyaav204@gmail.com End User
206 Vijay Yadav vjyaav205@gmail.com End User
207 Vijay Yadav vjyaav206@gmail.com End User
208 Vijay Yadav vjyaav207@gmail.com End User
209 Vijay Yadav vjyaav208@gmail.com End User
210 Vijay Yadav vjyaav209@gmail.com End User
211 Vijay Yadav vjyaav210@gmail.com End User
212 Vijay Yadav vjyaav211@gmail.com End User
213 Vijay Yadav vjyaav212@gmail.com End User
214 Vijay Yadav vjyaav213@gmail.com End User
215 Vijay Yadav vjyaav214@gmail.com End User
216 Vijay Yadav vjyaav215@gmail.com End User
217 Vijay Yadav vjyaav216@gmail.com End User
218 Vijay Yadav vjyaav217@gmail.com End User
219 Vijay Yadav vjyaav218@gmail.com End User
220 Vijay Yadav vjyaav219@gmail.com End User
221 Vijay Yadav vjyaav220@gmail.com End User
222 Vijay Yadav vjyaav221@gmail.com End User
223 Vijay Yadav vjyaav222@gmail.com End User
224 Vijay Yadav vjyaav223@gmail.com End User
225 Vijay Yadav vjyaav224@gmail.com End User
226 Vijay Yadav vjyaav225@gmail.com End User
227 Vijay Yadav vjyaav226@gmail.com End User
228 Vijay Yadav vjyaav227@gmail.com End User
229 Vijay Yadav vjyaav228@gmail.com End User
230 Vijay Yadav vjyaav229@gmail.com End User
231 Vijay Yadav vjyaav230@gmail.com End User
232 Vijay Yadav vjyaav231@gmail.com End User
233 Vijay Yadav vjyaav232@gmail.com End User
234 Vijay Yadav vjyaav233@gmail.com End User
235 Vijay Yadav vjyaav234@gmail.com End User
236 Vijay Yadav vjyaav235@gmail.com End User
237 Vijay Yadav vjyaav236@gmail.com End User
238 Vijay Yadav vjyaav237@gmail.com End User
239 Vijay Yadav vjyaav238@gmail.com End User
240 Vijay Yadav vjyaav239@gmail.com End User
241 Vijay Yadav vjyaav240@gmail.com End User
242 Vijay Yadav vjyaav241@gmail.com End User
243 Vijay Yadav vjyaav242@gmail.com End User
244 Vijay Yadav vjyaav243@gmail.com End User
245 Vijay Yadav vjyaav244@gmail.com End User
246 Vijay Yadav vjyaav245@gmail.com End User
247 Vijay Yadav vjyaav246@gmail.com End User
248 Vijay Yadav vjyaav247@gmail.com End User
249 Vijay Yadav vjyaav248@gmail.com End User
250 Vijay Yadav vjyaav249@gmail.com End User
251 Vijay Yadav vjyaav250@gmail.com End User
252 Vijay Yadav vjyaav251@gmail.com End User

View file

@ -0,0 +1,3 @@
First Name,Last Name,Email,User Role,Group
test,test,,Admin,Admin
test,test,,Builder,Builder
1 First Name Last Name Email User Role Group
2 test test Admin Admin
3 test test Builder Builder

View file

@ -0,0 +1,3 @@
First Name,Last Name,Email,User Role,Group,Metadata
,,withoutname1@gmail.com,Admin,Admin,
,,withoutname2@gmail.com,Builder,Builder,
1 First Name Last Name Email User Role Group Metadata
2 withoutname1@gmail.com Admin Admin
3 withoutname2@gmail.com Builder Builder

View file

@ -0,0 +1,3 @@
First Name,Last Name,Email,User Role,Group
,,withoutname1@gmail.com,Admin,Admin
,,withoutname2@gmail.com,Builder,Builder
1 First Name Last Name Email User Role Group
2 withoutname1@gmail.com Admin Admin
3 withoutname2@gmail.com Builder Builder

View file

@ -0,0 +1,3 @@
First Name,Last Name,Email,User Role,Group,Metadata
,,withoutname1@gmail.com,Admin,Admin,
,,withoutname2@gmail.com,Builder,Builder,
1 First Name Last Name Email User Role Group Metadata
2 withoutname1@gmail.com Admin Admin
3 withoutname2@gmail.com Builder Builder

View file

@ -0,0 +1,3 @@
First Name,Last Name,Email,User Role,Group
Test,Example,test12@gmail.com,,
Test,Example,test13@gmail.com,,
1 First Name Last Name Email User Role Group
2 Test Example test12@gmail.com
3 Test Example test13@gmail.com

View file

@ -0,0 +1,3 @@
First Name,Last Name,Email,User Role,Group,Metadata
Test,Example,test12@gmail.com,,,
Test,Example,test13@gmail.com,,,
1 First Name Last Name Email User Role Group Metadata
2 Test Example test12@gmail.com
3 Test Example test13@gmail.com

View file

@ -0,0 +1,3 @@
First Name,Last Name,Email,User Role,Group,Metadata
test,test,demo1@gmail.com,Admin,test,
test,test,demo2@gmail.com,Builder,abc,
1 First Name Last Name Email User Role Group Metadata
2 test test demo1@gmail.com Admin test
3 test test demo2@gmail.com Builder abc

View file

@ -0,0 +1,4 @@
First Name,Last Name,Email,User Role,Group,Metadata
test,test,demo11@gmail.com,Admin,,
test,test,demo11@gmail.com,Builder,,
1 First Name Last Name Email User Role Group Metadata
2 test test demo11@gmail.com Admin
3 test test demo11@gmail.com Builder

View file

@ -135,6 +135,7 @@ export const resolveHost = () => {
const baseUrl = Cypress.config("baseUrl");
const urlMapping = {
"http://localhost:8082": "http://localhost:8082",
"http://localhost:3000": "http://localhost:3000",
"http://localhost:3000/apps": "http://localhost:3000/apps",
"http://localhost:4001": "http://localhost:3000",

View file

@ -31,8 +31,11 @@ export const verifyAndModifyParameter = (paramName, value) => {
export const openEditorSidebar = (widgetName = "") => {
cy.hideTooltip();
cy.get(`${commonWidgetSelector.draggableWidget(widgetName)}:eq(0)`).realHover()
cy.get(commonWidgetSelector.widgetConfigHandle(widgetName)).click();
cy.get(`${commonWidgetSelector.draggableWidget(widgetName)}:eq(0)`).realHover().then(() => {
cy.wait(1000);
cy.get(commonWidgetSelector.widgetConfigHandle(widgetName)).click();
})
};
export const verifyAndModifyToggleFx = (

View file

@ -25,7 +25,7 @@ export const query = (operation) => {
};
export const verifypreview = (type, data) => {
cy.get(`[data-cy="preview-tab-${type}"]`).click();
cy.get(`[data-cy="preview-tab-${type}"]`, { timeout: 15000 }).click();
cy.get(`[data-cy="preview-${type}-data-container"]`).verifyVisibleElement(
"contain.text",
data,

View file

@ -1,60 +1,49 @@
export const verifyNodeData = (node, type, children, index = 0) => {
cy.get(
`[data-cy="inspector-node-${node.toLowerCase()}"] > .node-length-color`
)
.eq(index)
.realHover()
.verifyVisibleElement("have.text", `${children}`);
cy.get(`[data-cy="inspector-node-${node.toLowerCase()}"] > .node-key`)
.eq(index)
.verifyVisibleElement("have.text", node);
cy.get(`[data-cy="inspector-node-${node.toLowerCase()}"] > .node-type`)
.eq(index)
.verifyVisibleElement("have.text", type);
};
import { commonWidgetSelector } from "Selectors/common";
export const openNode = (node, index = 0, time = 1000) => {
cy.get(`[data-cy="inspector-node-${node.toLowerCase()}"] > .node-key`)
.eq(index)
.click();
cy.wait(time);
};
export const verifyValue = (node, type, children, index = 0) => {
cy.get(`[data-cy="inspector-node-${node.toLowerCase()}"] > .mx-2`)
.eq(index)
.realHover()
.verifyVisibleElement("contain.text", `${children}`);
cy.get(`[data-cy="inspector-node-${node.toLowerCase()}"] > .node-key`)
.eq(index)
.verifyVisibleElement("contain.text", node);
cy.get(`[data-cy="inspector-node-${node.toLowerCase()}"] > .mx-1`)
.eq(index)
.verifyVisibleElement("contain.text", type);
};
export const deleteComponentFromInspector = (node) => {
cy.get('[data-cy="inspector-node-components"] > .node-key').click();
cy.get(`[data-cy="inspector-node-${node}"] > .node-key`).realHover().parent().find('[style="height: 13px; width: 13px;"] > img').last().click();
};
export const verifyfunctions = (node, type, index = 0) => {
cy.get(`[data-cy="inspector-node-${node.toLowerCase()}"] > .fs-10`)
.eq(index)
.realHover()
.verifyVisibleElement("contain.text", `${type}`);
cy.get(`[data-cy="inspector-node-${node.toLowerCase()}"] > .node-key`)
.eq(index)
.verifyVisibleElement("contain.text", node);
// cy.get(`[data-cy="inspector-node-${node.toLowerCase()}"] > .mx-1`)
// .eq(index)
// .verifyVisibleElement("contain.text", type);
export const openAndVerifyNode = (nodeName, nodes, verificationFunction) => {
openStateFromComponent(nodeName);
verifyNodes(nodes, verificationFunction);
};
export const verifyNodes = (nodes, verificationFunction) => {
nodes.forEach(node => verificationFunction(node.key, node.type, node.value));
};
export const openAndVerifyNode = (nodeName, nodes, verificationFunction) => {
openNode(nodeName);
verifyNodes(nodes, verificationFunction);
export const openNode = (node, index = 0, time = 1000) => {
cy.get(`[data-cy="inspector-${node.toLowerCase()}-expand-button"]`, { timeout: time })
.eq(index)
.click();
};
export const openStateFromComponent = (widgetName) => {
cy.get(commonWidgetSelector.draggableWidget(widgetName))
.realHover()
.realHover();
cy.get(commonWidgetSelector.draggableWidget(widgetName))
.realHover()
.then(() => {
cy.get(`[data-cy="${widgetName}-inspect-button"]`)
.realHover({ position: "topRight" })
.last()
.realClick();
});
}
export const verifyNodeData = (node, type, value, index = 0) => {
cy.get(
`[data-cy="inspector-${node.toLowerCase()}-label"]`
)
.eq(index)
.realHover()
.verifyVisibleElement("have.text", `${node}`);
cy.get(`[data-cy="inspector-${node.toLowerCase()}-value"]`)
.eq(index)
.verifyVisibleElement("have.text", type == 'Function' ? 'function' : value);
};
export const deleteComponentFromInspector = (node) => {
cy.get('[data-cy="inspector-menu-icon"]').click();
cy.get(`[data-cy="inspector-delete-component-action"`).realHover().parent().find('[style="height: 13px; width: 13px;"] > img').last().click();
};

View file

@ -658,7 +658,7 @@ export const createGroupAddAppAndUserToGroup = (groupName, email) => {
cy.request({
method: "POST",
url: `${Cypress.env("server_host")}/api/v2/group-permissions/${groupId}/granular-permissions`,
url: `${Cypress.env("server_host")}/api/v2/group-permissions/${groupId}/granular-permissions/app`,
headers: headers,
body: {
name: "Apps",
@ -676,7 +676,6 @@ export const createGroupAddAppAndUserToGroup = (groupName, email) => {
],
},
},
}).then((response) => {
expect(response.status).to.equal(201);
});
@ -727,7 +726,7 @@ export const duplicateMultipleGroups = (groupNames) => {
cy.get(commonSelectors.duplicateOption).click(); // Click on the duplicate option
cy.get(commonSelectors.confirmDuplicateButton).click(); // Confirm duplication if needed
});
}
};
export const verifyGroupCardOptions = (groupName) => {
cy.get(groupsSelector.groupLink(groupName)).click();
@ -865,7 +864,7 @@ export const addUserInGroup = (groupName, email) => {
commonSelectors.toastMessage,
groupsText.userAddedToast
);
}
};
export const inviteUserBasedOnRole = (firstName, email, role = "end-user") => {
fillUserInviteForm(firstName, email);
@ -891,7 +890,13 @@ export const verifyBasicPermissions = (canCreate = true) => {
);
};
export const setupWorkspaceAndInviteUser = (workspaceName, workspaceSlug, firstName, email, role = "end-user") => {
export const setupWorkspaceAndInviteUser = (
workspaceName,
workspaceSlug,
firstName,
email,
role = "end-user"
) => {
cy.apiCreateWorkspace(workspaceName, workspaceSlug);
cy.visit(workspaceSlug);
cy.wait(1000);
@ -907,7 +912,10 @@ export const verifySettingsAccess = (shouldExist = true) => {
);
};
export const verifyUserPrivileges = (expectedButtonState, shouldHaveWorkspaceSettings) => {
export const verifyUserPrivileges = (
expectedButtonState,
shouldHaveWorkspaceSettings
) => {
cy.get(commonSelectors.dashboardAppCreateButton).should(expectedButtonState);
cy.get(commonSelectors.settingsIcon).click();
@ -923,4 +931,4 @@ export const setupAndUpdateRole = (currentRole, endRole, email) => {
updateRole(currentRole, endRole, email);
cy.wait(1000);
cy.apiLogout();
};
};

View file

@ -371,7 +371,7 @@ export const defaultSSO = (enable) => {
});
};
export const setSignupStatus = (enable, workspaceName = 'My workspace') => {
export const setSignupStatus = (enable, workspaceName = "My workspace") => {
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `SELECT id FROM organizations WHERE name = '${workspaceName}'`,
@ -429,3 +429,23 @@ export const resetDomain = () => {
});
});
};
export const enableInstanceSignup = (
allowPersonalWorkspace = true,
enableLoginConfig = true,
allowedDomains = ""
) => {
const allowValue = allowPersonalWorkspace ? "true" : "false";
const loginConfigValue = enableLoginConfig ? "true" : "false";
const sql = `
UPDATE instance_settings SET value = '${allowValue}' WHERE key = 'ALLOW_PERSONAL_WORKSPACE';
UPDATE instance_settings SET value = '${loginConfigValue}' WHERE key = 'ENABLE_SIGNUP';
UPDATE instance_settings SET value = '${allowedDomains}' WHERE key = 'ALLOWED_DOMAINS';
`;
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql,
});
};

View file

@ -0,0 +1,591 @@
import {
commonEeSelectors,
ssoEeSelector,
instanceSettingsSelector,
multiEnvSelector,
workspaceSelector,
} from "Selectors/eeCommon";
import { ssoEeText } from "Texts/eeCommon";
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import * as common from "Support/utils/common";
import { groupsSelector } from "Selectors/manageGroups";
import { groupsText } from "Texts/manageGroups";
import { eeGroupsSelector } from "Selectors/eeCommon";
import { eeGroupsText } from "Texts/eeCommon";
import {
// verifyOnboardingQuestions,
// verifyCloudOnboardingQuestions,
fetchAndVisitInviteLink,
} from "Support/utils/manageUsers";
import { commonText } from "Texts/common";
import { dashboardText } from "Texts/dashboard";
import { usersText } from "Texts/manageUsers";
import { usersSelector } from "Selectors/manageUsers";
import { ssoSelector } from "Selectors/manageSSO";
import { ssoText } from "Texts/manageSSO";
// import { appPromote } from "Support/utils/multiEnv";
export const oidcSSOPageElements = () => {
cy.get(ssoEeSelector.oidcToggle).click();
cy.get(ssoSelector.saveButton).eq(1).click();
cy.get('[data-cy="modal-title"]').verifyVisibleElement(
"have.text",
"Enable OpenID Connect"
);
cy.get('[data-cy="modal-close-button"]').should("be.visible");
cy.get('[data-cy="modal-message"]').verifyVisibleElement(
"have.text",
"Enabling OpenID Connect at the workspace level will override any OpenID Connect configurations set at the instance level."
);
cy.get('[data-cy="confirmation-text"]').verifyVisibleElement(
"have.text",
"Are you sure you want to continue?"
);
cy.get('[data-cy="cancel-button"]')
.eq(2)
.verifyVisibleElement("have.text", "Cancel");
cy.get('[data-cy="enable-button"]').verifyVisibleElement(
"have.text",
"Enable"
);
cy.get('[data-cy="cancel-button"]').eq(2).click();
cy.get('[data-cy="status-label"]').verifyVisibleElement(
"have.text",
ssoText.disabledLabel
);
cy.get(ssoEeSelector.oidcToggle).click();
cy.get(ssoSelector.saveButton).eq(1).click();
cy.get('[data-cy="enable-button"]').click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
ssoText.toggleUpdateToast("OpenID")
);
cy.get(ssoEeSelector.statusLabel).verifyVisibleElement(
"have.text",
ssoEeText.enabledLabel
);
cy.get('[data-cy="redirect-url-label"]').verifyVisibleElement(
"have.text",
ssoText.redirectUrlLabel
);
cy.get('[data-cy="redirect-url"]').should("be.visible");
cy.get('[data-cy="copy-icon"]').should("be.visible");
cy.get(ssoEeSelector.oidcToggle).click();
cy.get(ssoSelector.saveButton).eq(1).click();
// cy.get('[data-cy="enable-button"]').click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
ssoText.toggleUpdateToast("OpenID")
);
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
"have.text",
ssoText.disabledLabel
);
cy.get(ssoEeSelector.oidcToggle).click();
cy.clearAndType(ssoEeSelector.nameInput, ssoEeText.testName);
cy.clearAndType(ssoEeSelector.clientIdInput, ssoEeText.testclientId);
cy.clearAndType(ssoEeSelector.clientSecretInput, ssoEeText.testclientSecret);
cy.clearAndType(ssoEeSelector.WellKnownUrlInput, ssoEeText.testWellknownUrl);
cy.get(ssoSelector.saveButton).eq(1).click();
cy.get('[data-cy="enable-button"]').click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
ssoText.toggleUpdateToast("OpenID")
);
cy.get(ssoEeSelector.nameInput).should("have.value", ssoEeText.testName);
cy.get(ssoEeSelector.clientIdInput).should(
"have.value",
ssoEeText.testclientId
);
cy.get(ssoEeSelector.clientSecretInput).should(
"have.value",
ssoEeText.testclientSecret
);
cy.get(ssoEeSelector.WellKnownUrlInput).should(
"have.value",
ssoEeText.testWellknownUrl
);
};
export const resetDsPermissions = () => {
common.navigateToManageGroups();
cy.wait(200);
cy.get(groupsSelector.permissionsLink).click();
cy.get(groupsSelector.appsCreateCheck).then(($el) => {
if ($el.is(":checked")) {
cy.get(groupsSelector.appsCreateCheck).uncheck();
}
});
cy.get(eeGroupsSelector.dsCreateCheck).then(($el) => {
if ($el.is(":checked")) {
cy.get(eeGroupsSelector.dsCreateCheck).uncheck();
}
});
cy.get(eeGroupsSelector.dsDeleteCheck).then(($el) => {
if ($el.is(":checked")) {
cy.get(eeGroupsSelector.dsDeleteCheck).uncheck();
}
});
};
export const deleteAssignedDatasources = () => {
common.navigateToManageGroups();
cy.get('[data-cy="datasource-link"]').click();
cy.get("body").then(($body) => {
const removeAllButtons = $body.find('[data-cy="remove-button"]');
if (removeAllButtons.length > 0) {
cy.get('[data-cy="remove-button"]').click({ multiple: true });
}
});
};
export const userSignUp = (fullName, email, workspaceName) => {
const verificationFunction =
Cypress.env("environment") === "Enterprise"
? verifyOnboardingQuestions
: verifyCloudOnboardingQuestions;
let invitationLink = "";
cy.visit("/");
cy.wait(500);
cy.get(commonSelectors.createAnAccountLink).realClick();
cy.clearAndType(commonSelectors.nameInputField, fullName);
cy.clearAndType(commonSelectors.emailInputField, email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.get(commonSelectors.signUpButton).click();
cy.wait(500);
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `select invitation_token from users where email='${email}';`,
}).then((resp) => {
invitationLink = `/invitations/${resp.rows[0].invitation_token}`;
cy.visit(invitationLink);
cy.get(commonSelectors.setUpToolJetButton).click();
cy.wait(4000);
verificationFunction(fullName, workspaceName);
});
};
export const allowPersonalWorkspace = (allow = true) => {
const value = allow ? "true" : "false";
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `UPDATE instance_settings SET value = '${value}' WHERE key = 'ALLOW_PERSONAL_WORKSPACE';`,
});
};
export const addNewUserEE = (firstName, email) => {
common.navigateToManageUsers();
cy.get(usersSelector.buttonAddUsers).click();
cy.get(commonSelectors.inputFieldFullName).type(firstName);
cy.get(commonSelectors.inputFieldEmailAddress).type(email);
cy.get(usersSelector.buttonInviteUsers).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
usersText.userCreatedToast
);
WorkspaceInvitationLink(email);
cy.clearAndType(commonSelectors.passwordInputField, usersText.password);
cy.get(commonSelectors.signUpButton).click();
cy.wait(2000);
cy.get(commonSelectors.acceptInviteButton).click();
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
"My workspace"
);
};
export const inviteUser = (firstName, email) => {
cy.get(usersSelector.buttonAddUsers).click();
cy.get(commonSelectors.inputFieldFullName).type(firstName);
cy.get(commonSelectors.inputFieldEmailAddress).type(email);
cy.get(usersSelector.buttonInviteUsers).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
usersText.userCreatedToast
);
fetchAndVisitInviteLink(email);
};
export const defaultWorkspace = () => {
cy.get(".org-select-container").then(($title) => {
if (!$title.text().includes("My workspace")) {
cy.get(commonSelectors.workspaceName).realClick();
cy.contains("My workspace").realClick();
cy.wait(2000);
defaultWorkspace();
}
});
};
export const trunOffAllowPersonalWorkspace = () => {
cy.get(commonSelectors.settingsIcon).click();
cy.get(commonEeSelectors.instanceSettingIcon).click();
cy.get(instanceSettingsSelector.manageInstanceSettings).click();
cy.get(instanceSettingsSelector.allowWorkspaceToggle)
.eq(0)
.then(($el) => {
if ($el.is(":checked")) {
cy.get(instanceSettingsSelector.allowWorkspaceToggle).eq(0).uncheck();
cy.get(commonEeSelectors.saveButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Instance settings have been updated"
);
}
});
};
export const verifySSOSignUpPageElements = () => {
cy.get(commonSelectors.invitePageHeader).verifyVisibleElement(
"have.text",
"Join ToolJet"
);
cy.get(commonSelectors.invitePageSubHeader).verifyVisibleElement(
"have.text",
"You are invited to ToolJet."
);
cy.get(commonSelectors.userNameInputLabel).verifyVisibleElement(
"have.text",
commonText.userNameInputLabel
);
cy.get(commonSelectors.invitedUserName).should("be.visible");
cy.get(commonSelectors.emailInputLabel).verifyVisibleElement(
"have.text",
commonText.emailInputLabel
);
cy.get(commonSelectors.invitedUserEmail).should("be.visible");
cy.get(commonSelectors.acceptInviteButton).verifyVisibleElement(
"have.text",
commonText.acceptInviteButton
);
cy.get(commonSelectors.signUpTermsHelperText).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
commonText.signUpTermsHelperText
);
});
cy.get(commonSelectors.termsOfServiceLink)
.verifyVisibleElement("have.text", commonText.termsOfServiceLink)
.and("have.attr", "href")
.and("equal", "https://www.tooljet.com/terms");
cy.get(commonSelectors.privacyPolicyLink)
.verifyVisibleElement("have.text", commonText.privacyPolicyLink)
.and("have.attr", "href")
.and("equal", "https://www.tooljet.com/privacy");
};
export const VerifyWorkspaceInvitePageElements = () => {
cy.get(commonSelectors.invitePageHeader).verifyVisibleElement(
"have.text",
commonText.invitePageHeader
);
cy.get(commonSelectors.invitePageSubHeader).verifyVisibleElement(
"have.text",
commonText.invitePageSubHeader
);
cy.verifyLabel(commonText.userNameInputLabel);
cy.get(commonSelectors.invitedUserName).should("be.visible");
cy.verifyLabel(commonText.emailInputLabel);
cy.get(commonSelectors.invitedUserEmail).should("be.visible");
cy.get(commonSelectors.acceptInviteButton).verifyVisibleElement(
"have.text",
commonText.acceptInviteButton
);
cy.get(commonSelectors.signUpTermsHelperText).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
commonText.signUpTermsHelperText
);
});
cy.get(commonSelectors.termsOfServiceLink)
.verifyVisibleElement("have.text", commonText.termsOfServiceLink)
.and("have.attr", "href")
.and("equal", "https://www.tooljet.com/terms");
cy.get(commonSelectors.privacyPolicyLink)
.verifyVisibleElement("have.text", commonText.privacyPolicyLink)
.and("have.attr", "href")
.and("equal", "https://www.tooljet.com/privacy");
cy.get("body").then(($el) => {
if ($el.text().includes("Google")) {
cy.get(ssoSelector.googleSSOText).verifyVisibleElement(
"have.text",
ssoText.googleSignUpText
);
cy.get(ssoSelector.gitSSOText).verifyVisibleElement(
"have.text",
ssoText.gitSignUpText
);
cy.get(commonSelectors.onboardingSeperator).should("be.visible");
}
});
};
export const WorkspaceInvitationLink = (email) => {
let invitationToken,
organizationToken,
workspaceId,
userId,
url = "";
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `select invitation_token from users where email='${email}';`,
}).then((resp) => {
invitationToken = resp.rows[0].invitation_token;
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: "select id from organizations where name='My workspace';",
}).then((resp) => {
workspaceId = resp.rows[0].id;
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `select id from users where email='${email}';`,
}).then((resp) => {
userId = resp.rows[0].id;
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `select invitation_token from organization_users where user_id='${userId}';`,
}).then((resp) => {
organizationToken = resp.rows[0].invitation_token;
url = `/invitations/${invitationToken}/workspaces/${organizationToken}?oid=${workspaceId}`;
common.logout();
cy.visit(url);
});
});
});
});
};
export const enableDefaultSSO = () => {
common.navigateToManageSSO();
cy.get("body").then(($el) => {
if (!$el.text().includes("Allowed domains")) {
cy.get(ssoSelector.generalSettingsElements.generalSettings).click();
}
});
cy.get(ssoSelector.allowDefaultSSOToggle).then(($el) => {
if (!$el.is(":checked")) {
cy.get(ssoSelector.allowDefaultSSOToggle).check();
cy.get(ssoSelector.saveButton).click();
cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.ssoToast);
}
});
};
export const disableSSO = (ssoSelector, toggleSelector) => {
cy.wait(1000);
cy.get(ssoSelector).click();
cy.get(toggleSelector).then(($el) => {
if ($el.is(":checked")) {
cy.get(toggleSelector).uncheck();
}
});
};
export const AddDataSourceToGroup = (groupName, dsName) => {
common.navigateToManageGroups();
cy.get(groupsSelector.groupLink(groupName)).click();
cy.get(eeGroupsSelector.datasourceLink).click();
cy.wait(500);
cy.get(
'[data-cy="datasource-select-search"] >> .rmsc > .dropdown-container > .dropdown-heading > .dropdown-heading-value > .gray'
).click();
cy.contains(dsName).realClick();
cy.get(eeGroupsSelector.AddDsButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Datasources added to the group"
);
};
export const enableToggle = (toggleSelector) => {
cy.get(toggleSelector).then(($el) => {
if (!$el.is(":checked")) {
cy.get(toggleSelector).check();
}
});
};
export const disableToggle = (toggleSelector) => {
cy.get(toggleSelector).then(($el) => {
if ($el.is(":checked")) {
cy.get(toggleSelector).uncheck();
}
});
};
export const verifyPromoteModalUI = (versionName, currEnv, targetEnv) => {
cy.get(commonEeSelectors.promoteButton)
.verifyVisibleElement("have.text", " Promote ")
.click();
cy.get(commonEeSelectors.modalTitle).verifyVisibleElement(
"have.text",
`Promote ${versionName}`
);
cy.get(commonSelectors.closeButton).should("be.visible");
cy.get(multiEnvSelector.fromLabel).verifyVisibleElement("have.text", "FROM");
cy.get(multiEnvSelector.toLabel).verifyVisibleElement("have.text", "TO");
cy.get(multiEnvSelector.currEnvName).verifyVisibleElement(
"have.text",
currEnv
);
cy.get('[data-cy="target-env-name"]').verifyVisibleElement(
"have.text",
targetEnv
);
cy.get('[data-cy="cancel-button"]').verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get(commonEeSelectors.promoteButton)
.eq(1)
.verifyVisibleElement("have.text", "Promote ");
};
export const resetPassword = (email) => {
cy.visit("/");
cy.get(commonSelectors.forgotPasswordLink).click();
cy.clearAndType(commonSelectors.emailInputField, email);
cy.get(commonSelectors.resetPasswordLinkButton).click();
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `select forgot_password_token from users where email='${email}';`,
}).then((resp) => {
const passwordResetLink = `/reset-password/${resp.rows[0].forgot_password_token}`;
cy.visit(passwordResetLink);
});
cy.wait(500);
cy.clearAndType(commonSelectors.newPasswordInputField, "Password");
cy.clearAndType(commonSelectors.confirmPasswordInputField, "Password");
cy.wait(4000);
cy.get(commonSelectors.resetPasswordButton).click();
cy.get(commonSelectors.backToLoginButton).click();
};
export const verifyTooltipDisabled = (selector, message) => {
cy.get(selector)
.trigger("mouseover", { force: true })
.then(() => {
cy.get(".tooltip-inner").last().should("have.text", message);
});
};
export const createAnAppWithSlug = (appName, slug) => {
cy.apiCreateApp(appName);
cy.openApp();
cy.dragAndDropWidget("Table", 250, 250);
appPromote("development", "release");
cy.get(commonWidgetSelector.shareAppButton).click();
cy.clearAndType(commonWidgetSelector.appNameSlugInput, `${slug}`);
cy.wait(2000);
cy.get(commonWidgetSelector.modalCloseButton).click();
};
export const updateLicense = (key) => {
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `update instance_settings set value='${key}', updated_at= NOW() where key='LICENSE_KEY';`,
});
};
export const openInstanceSettings = () => {
cy.get(commonSelectors.settingsIcon).click();
cy.get(commonEeSelectors.instanceSettingIcon).click();
};
export const openUserActionMenu = (email) => {
cy.clearAndType(commonSelectors.inputUserSearch, email);
cy.wait(1000);
cy.get('[data-cy="user-actions-button"]').eq(0).click();
cy.wait(2000);
};
export const archiveWorkspace = (workspaceName) => {
cy.get(instanceSettingsSelector.allWorkspaceTab).click();
cy.clearAndType(commonEeSelectors.searchBar, workspaceName);
cy.get(workspaceSelector.workspaceStatusChange).eq(0).click();
cy.get(commonEeSelectors.confirmButton).click();
};
export const passwordToggle = (enable) => {
cy.getCookie("tj_auth_token").then((cookie) => {
cy.request(
{
method: "PATCH",
url: "http://localhost:3000/api/organizations/configs",
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token=${cookie.value}`,
},
body: { type: "form", enabled: enable },
},
{ log: false }
).then((response) => {
expect(response.status).to.equal(200);
});
});
};
export const InstanceSSO = (personalWorkspace, enableSignup, workspaceSSO) => {
allowPersonalWorkspace(personalWorkspace);
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `UPDATE instance_settings SET value = '${enableSignup}' WHERE key = 'ENABLE_SIGNUP';UPDATE instance_settings SET value = '${workspaceSSO}' WHERE key = 'ENABLE_WORKSPACE_LOGIN_CONFIGURATION';`,
});
};
export const resetInstanceDomain = () => {
cy.getCookie("tj_auth_token").then((cookie) => {
cy.request(
{
method: "PATCH",
url: "http://localhost:3000/api/instance-login-configs",
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token=${cookie.value}`,
},
body: { allowedDomains: "" },
},
{ log: false }
).then((response) => {
expect(response.status).to.equal(200);
});
});
};
export const instanceSSOConfig = (allow = true) => {
const value = allow ? "true" : "false";
cy.task("dbConnection", {
dbconfig: Cypress.env("app_db"),
sql: `UPDATE sso_configs SET enabled = ${allow} WHERE sso IN ('google', 'git', 'openid')AND organization_id IS NULL;`,
});
};
export const updateInstanceSettings = (key, value) => {
cy.task("updateSetting", {
dbconfig: Cypress.env("app_db"),
sql: `UPDATE instance_settings SET value = ${value} WHERE key = ${key};`,
});
};

View file

@ -122,10 +122,11 @@ export const createAndRunRestAPIQuery = ({
}
if (Array.isArray(responseData)) {
responseData.forEach((item) => {
expect(item).to.have.any.keys("id", "name", "price");
expect(item).to.have.any.keys("id", "name", "username", "email", "address");
});
}
if (responseData?.id) {
cy.log(responseData.id)
cy.writeFile("cypress/fixtures/restAPI/storedId.json", {
id: responseData.id,
});

View file

@ -7,10 +7,12 @@ sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates apt-u
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install 18.18.2
nvm install 22.15.1
sudo ln -s "$(which node)" /usr/bin/node
sudo ln -s "$(which npm)" /usr/bin/npm
sudo npm i -g npm@10.9.2
# Setup openresty
wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
echo "deb http://openresty.org/package/ubuntu bionic main" > openresty.list
@ -56,10 +58,10 @@ envsubst "${VARS_TO_SUBSTITUTE}" < /tmp/nginx.conf > /tmp/nginx-substituted.conf
sudo cp /tmp/nginx-substituted.conf /usr/local/openresty/nginx/conf/nginx.conf
# Download and setup postgrest binary
curl -OL https://github.com/PostgREST/postgrest/releases/download/v10.1.1/postgrest-v10.1.1-linux-static-x64.tar.xz
tar xJf postgrest-v10.1.1-linux-static-x64.tar.xz
curl -OL https://github.com/PostgREST/postgrest/releases/download/v12.2.0/postgrest-v12.2.0-linux-static-x64.tar.xz
tar xJf postgrest-v12.2.0-linux-static-x64.tar.xz
sudo mv ./postgrest /bin/postgrest
sudo rm postgrest-v10.1.1-linux-static-x64.tar.xz
sudo rm postgrest-v12.2.0-linux-static-x64.tar.xz
# Setup app and postgrest as systemd service
sudo cp /tmp/nest.service /lib/systemd/system/nest.service
@ -74,7 +76,7 @@ mv /tmp/.env ~/app/.env
mv /tmp/setup_app ~/app/setup_app
sudo chmod +x ~/app/setup_app
npm install -g npm@9.8.1
npm install -g npm@10.9.2
# Building ToolJet app
npm install -g @nestjs/cli

View file

@ -7,11 +7,11 @@ sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates apt-u
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install 18.18.2
nvm install 22.15.1
sudo ln -s "$(which node)" /usr/bin/node
sudo ln -s "$(which npm)" /usr/bin/npm
sudo npm i -g npm@9.8.1
sudo npm i -g npm@10.9.2
# Setup openresty
wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
@ -58,10 +58,10 @@ envsubst "${VARS_TO_SUBSTITUTE}" < /tmp/nginx.conf > /tmp/nginx-substituted.conf
sudo cp /tmp/nginx-substituted.conf /usr/local/openresty/nginx/conf/nginx.conf
# Download and setup postgrest binary
curl -OL https://github.com/PostgREST/postgrest/releases/download/v12.0.2/postgrest-v12.0.2-linux-static-x64.tar.xz
tar xJf postgrest-v12.0.2-linux-static-x64.tar.xz
curl -OL https://github.com/PostgREST/postgrest/releases/download/v12.2.0/postgrest-v12.2.0-linux-static-x64.tar.xz
tar xJf postgrest-v12.2.0-linux-static-x64.tar.xz
sudo mv ./postgrest /bin/postgrest
sudo rm postgrest-v12.0.2-linux-static-x64.tar.xz
sudo rm postgrest-v12.2.0-linux-static-x64.tar.xz
# Add the Redis APT repository
sudo add-apt-repository ppa:redislabs/redis -y
@ -92,7 +92,7 @@ mv /tmp/.env ~/app/.env
mv /tmp/setup_app ~/app/setup_app
sudo chmod +x ~/app/setup_app
npm install -g npm@9.8.1
npm install -g npm@10.9.2
# Building ToolJet app
npm install -g @nestjs/cli

View file

@ -1,4 +1,4 @@
FROM node:18.18.2-buster AS builder
FROM node:22.15.1 AS builder
# Fix for JS heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
@ -30,9 +30,10 @@ COPY ./server/package.json ./server/package-lock.json ./server/
RUN npm --prefix server install
COPY ./server/ ./server/
RUN npm install -g @nestjs/cli
RUN npm install -g copyfiles
RUN npm --prefix server run build
FROM node:18.18.2-bullseye
FROM node:22.15.1-bullseye
# copy postgrest executable
COPY --from=postgrest/postgrest:v12.2.0 /bin/postgrest /bin

View file

@ -1,9 +1,9 @@
FROM node:18.18.2-buster AS builder
FROM node:22.15.1 AS builder
# Fix for JS heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
ENV NODE_OPTIONS="--max-old-space-size=8096"
RUN npm i -g npm@9.8.1
RUN npm i -g npm@10.9.2
RUN mkdir -p /app
WORKDIR /app
@ -31,10 +31,11 @@ ENV NODE_ENV=production
COPY ./server/package.json ./server/package-lock.json ./server/
RUN npm --prefix server install
COPY ./server/ ./server/
RUN npm install -g @nestjs/cli
RUN npm install -g @nestjs/cli
RUN npm install -g copyfiles
RUN npm --prefix server run build
FROM debian:11
FROM debian:12
RUN apt-get update -yq \
&& apt-get install curl gnupg zip -yq \
@ -42,12 +43,12 @@ RUN apt-get update -yq \
&& apt-get clean -y
RUN curl -O https://nodejs.org/dist/v18.18.2/node-v18.18.2-linux-x64.tar.xz \
&& tar -xf node-v18.18.2-linux-x64.tar.xz \
&& mv node-v18.18.2-linux-x64 /usr/local/lib/nodejs \
RUN curl -O https://nodejs.org/dist/v22.15.1/node-v22.15.1-linux-x64.tar.xz \
&& tar -xf node-v22.15.1-linux-x64.tar.xz \
&& mv node-v22.15.1-linux-x64 /usr/local/lib/nodejs \
&& echo 'export PATH="/usr/local/lib/nodejs/bin:$PATH"' >> /etc/profile.d/nodejs.sh \
&& /bin/bash -c "source /etc/profile.d/nodejs.sh" \
&& rm node-v18.18.2-linux-x64.tar.xz
&& rm node-v22.15.1-linux-x64.tar.xz
ENV PATH=/usr/local/lib/nodejs/bin:$PATH
ENV NODE_ENV=production

View file

@ -0,0 +1,31 @@
#!/bin/bash
set -e
npm cache clean --force
if [ -d "./server/dist" ]; then
SETUP_CMD='npm run cloud:setup:prod'
else
SETUP_CMD='npm run cloud:setup'
fi
npm cache clean --force
if [ -f "./.env" ]; then
declare $(grep -v '^#' ./.env | xargs)
fi
if [ -z "$DATABASE_URL" ]; then
./server/scripts/wait-for-it.sh $PG_HOST:${PG_PORT:-5432} --strict --timeout=300 -- $SETUP_CMD
else
PG_HOST=$(echo "$DATABASE_URL" | awk -F'[/:@?]' '{print $6}')
PG_PORT=$(echo "$DATABASE_URL" | awk -F'[/:@?]' '{print $7}')
if [ -z "$DATABASE_PORT" ]; then
DATABASE_PORT="5432"
fi
./server/scripts/wait-for-it.sh "$PG_HOST:$PG_PORT" --strict --timeout=300 -- $SETUP_CMD
fi
exec "$@"

View file

@ -0,0 +1,121 @@
FROM node:18.18.2-buster AS builder
# Fix for JS heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN npm i -g npm@9.8.1
RUN mkdir -p /app
# RUN npm cache clean --force
WORKDIR /app
# Scripts for building
COPY ./package.json ./package.json
# Build plugins
COPY ./plugins/package.json ./plugins/package-lock.json ./plugins/
RUN npm --prefix plugins install
COPY ./plugins/ ./plugins/
RUN NODE_ENV=production npm --prefix plugins run build
RUN npm --prefix plugins prune --production
# Build frontend
COPY ./frontend/package.json ./frontend/package-lock.json ./frontend/
RUN npm --prefix frontend install
COPY ./frontend/ ./frontend/
RUN npm --prefix frontend run build --production
RUN npm --prefix frontend prune --production
ENV NODE_ENV=production
# Build server
COPY ./server/package.json ./server/package-lock.json ./server/
RUN npm --prefix server install
COPY ./server/ ./server/
RUN npm install -g @nestjs/cli
RUN npm --prefix server run build
FROM debian:11
RUN apt-get update -yq \
&& apt-get install curl gnupg zip -yq \
&& apt-get install -yq build-essential \
&& apt-get clean -y
RUN curl -O https://nodejs.org/dist/v18.18.2/node-v18.18.2-linux-x64.tar.xz \
&& tar -xf node-v18.18.2-linux-x64.tar.xz \
&& mv node-v18.18.2-linux-x64 /usr/local/lib/nodejs \
&& echo 'export PATH="/usr/local/lib/nodejs/bin:$PATH"' >> /etc/profile.d/nodejs.sh \
&& /bin/bash -c "source /etc/profile.d/nodejs.sh" \
&& rm node-v18.18.2-linux-x64.tar.xz
ENV PATH=/usr/local/lib/nodejs/bin:$PATH
ENV NODE_ENV=production
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN apt-get update && \
apt-get install -y postgresql-client freetds-dev libaio1 wget && \
apt-get -o Dpkg::Options::="--force-confold" upgrade -q -y --force-yes && \
apt-get -y autoremove && \
apt-get -y autoclean
# Install Instantclient Basic Light Oracle and Dependencies
WORKDIR /opt/oracle
RUN wget https://tooljet-plugins-production.s3.us-east-2.amazonaws.com/marketplace-assets/oracledb/instantclients/instantclient-basiclite-linuxx64.zip && \
wget https://tooljet-plugins-production.s3.us-east-2.amazonaws.com/marketplace-assets/oracledb/instantclients/instantclient-basiclite-linux.x64-11.2.0.4.0.zip && \
unzip instantclient-basiclite-linuxx64.zip && rm -f instantclient-basiclite-linuxx64.zip && \
unzip instantclient-basiclite-linux.x64-11.2.0.4.0.zip && rm -f instantclient-basiclite-linux.x64-11.2.0.4.0.zip && \
cd /opt/oracle/instantclient_21_10 && rm -f *jdbc* *occi* *mysql* *mql1* *ipc1* *jar uidrvci genezi adrci && \
cd /opt/oracle/instantclient_11_2 && rm -f *jdbc* *occi* *mysql* *mql1* *ipc1* *jar uidrvci genezi adrci && \
echo /opt/oracle/instantclient* > /etc/ld.so.conf.d/oracle-instantclient.conf && ldconfig
# Set the Instant Client library paths
ENV LD_LIBRARY_PATH="/opt/oracle/instantclient_11_2:/opt/oracle/instantclient_21_10:${LD_LIBRARY_PATH}"
WORKDIR /
RUN mkdir -p /app
# copy npm scripts
COPY --from=builder /app/package.json ./app/package.json
# copy plugins dependencies
COPY --from=builder /app/plugins/dist ./app/plugins/dist
COPY --from=builder /app/plugins/client.js ./app/plugins/client.js
COPY --from=builder /app/plugins/node_modules ./app/plugins/node_modules
COPY --from=builder /app/plugins/packages/common ./app/plugins/packages/common
COPY --from=builder /app/plugins/package.json ./app/plugins/package.json
# copy server build
COPY --from=builder /app/server/package.json ./app/server/package.json
COPY --from=builder /app/server/.version ./app/server/.version
COPY --from=builder /app/server/node_modules ./app/server/node_modules
COPY --from=builder /app/server/templates ./app/server/templates
COPY --from=builder /app/server/scripts ./app/server/scripts
COPY --from=builder /app/server/dist ./app/server/dist
COPY ./docker/cloud/cloud-entrypoint.sh ./app/server/cloud-entrypoint.sh
# Define non-sudo user
RUN useradd --create-home --home-dir /home/appuser appuser \
&& chown -R appuser:0 /app \
&& chown -R appuser:0 /home/appuser \
&& chmod u+x /app \
&& chmod -R g=u /app
# Set npm cache directory
ENV npm_config_cache /home/appuser/.npm
ENV HOME=/home/appuser
# Installing git for simple git commands
RUN apt-get update && apt-get install -y git && apt-get clean
USER appuser
WORKDIR /app
# Dependencies for scripts outside nestjs
RUN npm install dotenv@10.0.0 joi@17.4.1
ENTRYPOINT ["./server/cloud-entrypoint.sh"]

View file

@ -91,12 +91,13 @@ COPY --from=builder /app/plugins/package.json ./app/plugins/package.json
# copy server build
COPY --from=builder /app/server/package.json ./app/server/package.json
COPY --from=builder /app/server/.version ./app/server/.version
COPY --from=builder /app/server/entrypoint.sh ./app/server/entrypoint.sh
COPY --from=builder /app/server/node_modules ./app/server/node_modules
COPY --from=builder /app/server/templates ./app/server/templates
COPY --from=builder /app/server/scripts ./app/server/scripts
COPY --from=builder /app/server/dist ./app/server/dist
COPY ./docker/cloud/cloud-entrypoint.sh ./app/server/cloud-entrypoint.sh
# Define non-sudo user
RUN useradd --create-home --home-dir /home/appuser appuser \
&& chown -R appuser:0 /app \
@ -108,10 +109,14 @@ RUN useradd --create-home --home-dir /home/appuser appuser \
ENV npm_config_cache /home/appuser/.npm
ENV HOME=/home/appuser
# Installing git for simple git commands
RUN apt-get update && apt-get install -y git && apt-get clean
USER appuser
WORKDIR /app
# Dependencies for scripts outside nestjs
RUN npm install dotenv@10.0.0 joi@17.4.1
ENTRYPOINT ["./server/entrypoint.sh"]
ENTRYPOINT ["./server/cloud-entrypoint.sh"]

View file

@ -42,6 +42,115 @@ else
echo "Using external PostgREST at $PGRST_HOST."
fi
# Neo4j configuration
# ----------------------------------
# Default Neo4j environment values
# ----------------------------------
export NEO4J_USER=${NEO4J_USER:-"neo4j"}
export NEO4J_PASSWORD=${NEO4J_PASSWORD:-"appaqvyvRLbeukhFE"}
export NEO4J_AUTH=${NEO4J_AUTH:-"neo4j/appaqvyvRLbeukhFE"}
export NEO4J_URI=${NEO4J_URI:-"bolt://localhost:7687"}
export NEO4J_PLUGINS=${NEO4J_PLUGINS:-'["apoc"]'}
export NEO4J_AUTH
# Extract username and password from NEO4J_AUTH if set
if [ -n "$NEO4J_AUTH" ]; then
# Extract username and password from NEO4J_AUTH (format: username/password)
NEO4J_USERNAME=$(echo "$NEO4J_AUTH" | cut -d'/' -f1)
NEO4J_PASSWORD=$(echo "$NEO4J_AUTH" | cut -d'/' -f2)
# Export these for application use
export NEO4J_USERNAME
export NEO4J_PASSWORD
echo "Neo4j authentication configured with username: $NEO4J_USERNAME"
else
echo "NEO4J_AUTH not set, using default authentication"
fi
# Check if Neo4j is already initialized and set password if necessary
if [ "$NEO4J_AUTH" != "none" ] && [ -n "$NEO4J_PASSWORD" ]; then
echo "Setting Neo4j initial password..."
# Ensure Neo4j is not running before setting the initial password
neo4j stop || true
# Set the initial password using the correct command format for Neo4j 5.x
NEO4J_ADMIN_CMD=$(which neo4j-admin)
NEO4J_VERSION=$(neo4j --version | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+" | head -n 1)
echo "Detected Neo4j version: $NEO4J_VERSION"
# Use version-specific command format
MAJOR_VERSION=$(echo $NEO4J_VERSION | cut -d. -f1)
if [ "$MAJOR_VERSION" -ge "5" ]; then
# For Neo4j 5.x and higher
echo "Using Neo4j 5.x+ password command format"
$NEO4J_ADMIN_CMD dbms set-initial-password "$NEO4J_PASSWORD" --require-password-change=false >/dev/null 2>&1 || {
echo "Warning: Could not set Neo4j password, it may already be set"
}
else
# For Neo4j 4.x and lower
echo "Using Neo4j 4.x password command format" >/dev/null 2>&1
$NEO4J_ADMIN_CMD set-initial-password "$NEO4J_PASSWORD" >/dev/null 2>&1 || {
echo "Warning: Could not set Neo4j password, it may already be set"
}
fi
fi
# Update Neo4j configuration
echo "Configuring Neo4j..."
cat > /etc/neo4j/neo4j.conf << EOF
# Neo4j configuration
dbms.security.auth_enabled=true
server.bolt.enabled=true
server.bolt.listen_address=0.0.0.0:7687
server.directories.data=/var/lib/neo4j/data
server.directories.logs=/var/log/neo4j
initial.dbms.default_database=neo4j
server.directories.plugins=/var/lib/neo4j/plugins
server.directories.import=/var/lib/neo4j/import
# APOC Settings
dbms.security.procedures.unrestricted=apoc.*
dbms.security.procedures.allowlist=apoc.*,algo.*,gds.*
EOF
if [ -w "$NEO4J_LOG_DIR" ]; then
chmod -R 770 "$NEO4J_LOG_DIR" || echo "Warning: Could not set log directory permissions" >/dev/null 2>&1
fi
# Start Neo4j
echo "Starting Neo4j service..."
neo4j console >/dev/null 2>&1 &
# Add a wait for Neo4j to be ready with more robust checking
echo "Waiting for Neo4j to be ready..."
NEO4J_READY=false
for i in {1..60}; do
# First try standard status check
if neo4j status >/dev/null 2>&1; then
echo "Neo4j is ready (via status check)"
NEO4J_READY=true
break
fi
# Also try connecting to the bolt port as a fallback
if command -v nc >/dev/null 2>&1; then
if nc -z localhost 7687 >/dev/null 2>&1; then
echo "Neo4j is ready (port 7687 is open)"
NEO4J_READY=true
break
fi
fi
echo "Waiting for Neo4j to start... ($i/60)"
sleep 2
done
if [ "$NEO4J_READY" = false ]; then
echo "WARNING: Neo4j may not be fully started yet, but continuing..."
fi
# Check WORKLOW_WORKER and skip SETUP_CMD if true
if [ "${WORKFLOW_WORKER}" == "true" ]; then
echo "WORKFLOW_WORKER is set to true. Running worker process."

View file

@ -1,4 +1,4 @@
FROM node:18.18.2-buster AS builder
FROM node:22.15.1 AS builder
# Fix for JS heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
@ -50,10 +50,11 @@ ENV TOOLJET_EDITION=ee
COPY ./server/package.json ./server/package-lock.json ./server/
RUN npm --prefix server install
COPY ./server/ ./server/
RUN npm install -g @nestjs/cli
RUN npm install -g @nestjs/cli
RUN npm install -g copyfiles
RUN npm --prefix server run build
FROM node:18.18.2-bullseye
FROM node:22.15.1-bullseye
RUN apt-get update -yq \
&& apt-get install curl gnupg zip -yq \

View file

@ -1,11 +1,11 @@
FROM node:18.18.2-buster AS builder
FROM node:22.15.1 AS builder
# Fix for JS heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN npm i -g npm@9.8.1
RUN npm i -g npm@10.9.2
RUN mkdir -p /app
# RUN npm cache clean --force
RUN npm cache clean --force
WORKDIR /app
@ -54,13 +54,14 @@ ENV TOOLJET_EDITION=ee
COPY ./server/package.json ./server/package-lock.json ./server/
RUN npm --prefix server install
COPY ./server/ ./server/
RUN npm install -g @nestjs/cli
RUN npm install -g @nestjs/cli
RUN npm install -g copyfiles
RUN npm --prefix server run build
FROM debian:11
FROM debian:12
RUN apt-get update -yq \
&& apt-get install curl gnupg zip -yq \
&& apt-get install curl wget gnupg zip -yq \
&& apt-get install -yq build-essential \
&& apt -y install redis \
&& apt-get clean -y
@ -80,13 +81,29 @@ RUN echo "[supervisord]\n" \
"nodaemon=true\n" \
"\n" \
"[program:postgrest]\n" \
"command=/bin/postgrest \n" \
"command=/bin/postgrest\n" \
"autostart=true\n" \
"autorestart=true\n" \
"stdout_logfile=/dev/stdout\n" \
"stderr_logfile=/dev/stderr\n" \
"stdout_logfile_maxbytes=0\n" \
"stderr_logfile_maxbytes=0\n" \
"\n" \
"[program:neo4j]\n" \
"command=neo4j console\n" \
"autostart=true\n" \
"autorestart=unexpected\n" \
"startsecs=30\n" \
"startretries=999\n" \
"priority=90\n" \
"exitcodes=0,1,2\n" \
"stopsignal=SIGTERM\n" \
"stopasgroup=true\n" \
"killasgroup=true\n" \
"redirect_stderr=true\n" \
"stdout_logfile=/var/log/neo4j/neo4j.log\n" \
"stdout_logfile_backups=10\n" \
"stderr_capture_maxbytes=20MB\n" \
"\n" | sed 's/ //' > /etc/supervisor/conf.d/supervisord.conf
# Create a wrapper for PostgREST to prefix its logs
@ -97,12 +114,12 @@ exec /bin/postgrest-original "$@" 2>&1 | sed "s/^/[PostgREST] /"\n\
chmod +x /bin/postgrest
RUN curl -O https://nodejs.org/dist/v18.18.2/node-v18.18.2-linux-x64.tar.xz \
&& tar -xf node-v18.18.2-linux-x64.tar.xz \
&& mv node-v18.18.2-linux-x64 /usr/local/lib/nodejs \
RUN curl -O https://nodejs.org/dist/v22.15.1/node-v22.15.1-linux-x64.tar.xz \
&& tar -xf node-v22.15.1-linux-x64.tar.xz \
&& mv node-v22.15.1-linux-x64 /usr/local/lib/nodejs \
&& echo 'export PATH="/usr/local/lib/nodejs/bin:$PATH"' >> /etc/profile.d/nodejs.sh \
&& /bin/bash -c "source /etc/profile.d/nodejs.sh" \
&& rm node-v18.18.2-linux-x64.tar.xz
&& rm node-v22.15.1-linux-x64.tar.xz
ENV PATH=/usr/local/lib/nodejs/bin:$PATH
ENV NODE_ENV=production
@ -114,6 +131,48 @@ RUN apt-get update && \
apt-get -y autoremove && \
apt-get -y autoclean
# Install Neo4j
RUN wget -O - https://debian.neo4j.com/neotechnology.gpg.key | apt-key add - && \
echo "deb https://debian.neo4j.com stable 5" > /etc/apt/sources.list.d/neo4j.list && \
apt-get update && \
apt-get install -y neo4j=1:5.26.6 && \
apt-mark hold neo4j && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# Set the necessary Neo4j environment variables
ENV NEO4J_HOME=/opt/neo4j
ENV NEO4J_CONF=/etc/neo4j
ENV NEO4J_DATA=/var/lib/neo4j/data
ENV NEO4J_LOG=/var/log/neo4j
ENV NEO4J_PLUGIN=/var/lib/neo4j/plugins
ENV NEO4J_IMPORT=/var/lib/neo4j/import
# Create the necessary directories for Neo4j
RUN mkdir -p /data/db /data/logs /data/plugins
RUN mkdir -p /opt/neo4j/plugins
# Configure APOC plugin for Neo4j
ENV NEO4J_dbms_active_plugins=apoc
# Download and install APOC plugin for Neo4j 5.x (BEFORE creating user)
RUN mkdir -p /var/lib/neo4j/plugins && \
wget -P /var/lib/neo4j/plugins https://github.com/neo4j/apoc/releases/download/5.26.6/apoc-5.26.6-core.jar && \
# Try to download extended version
(wget -P /var/lib/neo4j/plugins https://github.com/neo4j/apoc/releases/download/5.26.6/apoc-5.26.6-extended.jar || \
wget -P /var/lib/neo4j/plugins https://neo4j-contrib.github.io/neo4j-apoc-procedures/5.26.6/apoc-5.26.6-extended.jar || \
echo "Extended JAR not available, continuing with core only")
# Configure Neo4j with APOC
RUN echo "dbms.security.procedures.unrestricted=apoc.*" >> /etc/neo4j/neo4j.conf && \
echo "dbms.security.procedures.allowlist=apoc.*,algo.*,gds.*" >> /etc/neo4j/neo4j.conf && \
echo "dbms.directories.plugins=/var/lib/neo4j/plugins" >> /etc/neo4j/neo4j.conf
# Configure Neo4j to use authentication
RUN if [ -f "/etc/neo4j/neo4j.conf" ]; then \
sed -i '/dbms.security.auth_enabled/d' /etc/neo4j/neo4j.conf && \
echo "dbms.security.auth_enabled=true" >> /etc/neo4j/neo4j.conf; \
fi
# Install Instantclient Basic Light Oracle and Dependencies
WORKDIR /opt/oracle
@ -149,6 +208,7 @@ COPY --from=builder /app/server/node_modules ./app/server/node_modules
COPY --from=builder /app/server/templates ./app/server/templates
COPY --from=builder /app/server/scripts ./app/server/scripts
COPY --from=builder /app/server/dist ./app/server/dist
COPY --from=builder /app/server/src/assets ./app/server/src/assets
COPY ./docker/ee/ee-entrypoint.sh ./app/server/ee-entrypoint.sh
@ -161,14 +221,21 @@ RUN useradd --create-home --home-dir /home/appuser appuser \
&& chmod -R g=u /app \
&& chmod -R g=u /home
# Create directory /home/appuser and set ownership to appuser (Refer doc for understanding the changes https://app.clickup.com/37484951/v/dc/13qycq-4081)
RUN mkdir -p /var/lib/neo4j/data/databases /var/lib/neo4j/data/transactions /var/log/neo4j /opt/neo4j/run && \
chown -R appuser:0 /var/lib/neo4j /var/log/neo4j /etc/neo4j /opt/neo4j/run && \
chmod -R 770 /var/lib/neo4j /var/log/neo4j /etc/neo4j /opt/neo4j/run && \
chmod -R 644 /var/lib/neo4j/plugins/*.jar && \
chown -R appuser:0 /var/lib/neo4j/plugins && \
chmod 755 /var/lib/neo4j/plugins
# Create directory /home/appuser and set ownership to appuser
RUN mkdir -p /home/appuser \
&& chown -R appuser:0 /home/appuser \
&& chmod g+s /home/appuser \
&& chmod -R g=u /home/appuser \
&& npm cache clean --force
# Create directory /tmp/.npm/npm-cache/ and set ownership to appuser (Refer doc for understanding the changes https://app.clickup.com/37484951/v/dc/13qycq-4081)
# Create directory /tmp/.npm/npm-cache/ and set ownership to appuser
RUN mkdir -p /tmp/.npm/npm-cache/ \
&& chown -R appuser:0 /tmp/.npm/npm-cache/ \
&& chmod g+s /tmp/.npm/npm-cache/ \
@ -206,6 +273,9 @@ RUN mkdir -p /var/lib/postgrest /var/log/postgrest /etc/postgrest \
ENV HOME=/home/appuser
# Installing git for simple git commands
RUN apt-get update && apt-get install -y git && apt-get clean
# Switch back to appuser
USER appuser

View file

@ -1 +1 @@
3.14.0
3.15.1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

View file

@ -0,0 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.02811 1.31381C2.22904 1.11288 2.50157 1 2.78572 1H7.07144C7.16616 1 7.257 1.03763 7.32397 1.10461L10.1812 3.96175C10.2481 4.02872 10.2857 4.11956 10.2857 4.21429V9.92857C10.2857 10.2127 10.1729 10.4853 9.97194 10.6862C9.77101 10.8871 9.49844 11 9.21429 11H2.78572C2.50156 11 2.22904 10.8871 2.02811 10.6862C1.82718 10.4853 1.71429 10.2127 1.71429 9.92857V2.07143C1.71429 1.78727 1.82718 1.51475 2.02811 1.31381ZM5.30739 5.26405C5.51659 5.47326 5.51659 5.81246 5.30739 6.02166L4.25762 7.07143L5.30739 8.12119C5.51659 8.33043 5.51659 8.66957 5.30739 8.87879C5.09818 9.088 4.75898 9.088 4.54977 8.87879L3.1212 7.45024C2.91199 7.24103 2.91199 6.90183 3.1212 6.69262L4.54977 5.26405C4.75898 5.05484 5.09818 5.05484 5.30739 5.26405ZM6.69263 6.02166C6.48342 5.81246 6.48342 5.47326 6.69263 5.26405C6.90184 5.05484 7.24104 5.05484 7.45024 5.26405L8.87879 6.69262C9.08801 6.90183 9.08801 7.24103 8.87879 7.45024L7.45024 8.87879C7.24104 9.088 6.90184 9.088 6.69263 8.87879C6.48342 8.66957 6.48342 8.33043 6.69263 8.12119L7.74239 7.07143L6.69263 6.02166Z" fill="#6A727C"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,3 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.75815 0.483576C6.95842 0.283307 7.28312 0.283307 7.48338 0.483576L9.79108 2.79127C9.99135 2.99154 9.99135 3.31624 9.79108 3.5165L7.48338 5.8242C7.28312 6.02447 6.95842 6.02447 6.75815 5.8242L4.45046 3.5165C4.25018 3.31624 4.25018 2.99154 4.45046 2.79127L6.75815 0.483576ZM2.912 4.32973C3.11227 4.12946 3.43696 4.12946 3.63723 4.32973L5.94492 6.63743C6.1452 6.83769 6.1452 7.16239 5.94492 7.36266L3.63723 9.67035C3.43696 9.87063 3.11227 9.87063 2.912 9.67035L0.604304 7.36266C0.404034 7.16239 0.404034 6.83769 0.604304 6.63743L2.912 4.32973ZM11.3296 4.32973C11.1293 4.12946 10.8046 4.12946 10.6043 4.32973L8.29662 6.63743C8.09634 6.83769 8.09634 7.16239 8.29662 7.36266L10.6043 9.67035C10.8046 9.87063 11.1293 9.87063 11.3296 9.67035L13.6373 7.36266C13.8375 7.16239 13.8375 6.83769 13.6373 6.63743L11.3296 4.32973ZM7.48338 8.17589C7.28312 7.97561 6.95842 7.97561 6.75815 8.17589L4.45046 10.4835C4.25018 10.6838 4.25018 11.0086 4.45046 11.2089L6.75815 13.5166C6.95842 13.7168 7.28312 13.7168 7.48338 13.5166L9.79108 11.2089C9.99135 11.0086 9.99135 10.6838 9.79108 10.4835L7.48338 8.17589Z" fill="#1E823B"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,3 @@
<svg width="20" height="25" viewBox="0 0 20 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.60152 6.16675C2.53311 6.16675 1.66699 7.03286 1.66699 8.10128C1.66699 8.5122 2.00011 8.84532 2.41104 8.84532C2.82197 8.84532 3.15509 8.5122 3.15509 8.10128C3.15509 7.85472 3.35496 7.65485 3.60152 7.65485C4.01245 7.65485 4.34557 7.32172 4.34557 6.9108C4.34557 6.49987 4.01245 6.16675 3.60152 6.16675ZM5.98248 6.16675C5.57155 6.16675 5.23843 6.49987 5.23843 6.9108C5.23843 7.32172 5.57155 7.65485 5.98248 7.65485H7.7682C8.17912 7.65485 8.51224 7.32172 8.51224 6.9108C8.51224 6.49987 8.17912 6.16675 7.7682 6.16675H5.98248ZM9.4051 6.9108C9.4051 6.49987 9.73822 6.16675 10.1492 6.16675C11.2176 6.16675 12.0837 7.03286 12.0837 8.10128C12.0837 8.5122 11.7506 8.84532 11.3396 8.84532C10.9287 8.84532 10.5956 8.5122 10.5956 8.10128C10.5956 7.85472 10.3957 7.65485 10.1492 7.65485C9.73822 7.65485 9.4051 7.32172 9.4051 6.9108ZM3.15509 10.4822C3.15509 10.0713 2.82197 9.73818 2.41104 9.73818C2.00011 9.73818 1.66699 10.0713 1.66699 10.4822V12.2679C1.66699 12.6789 2.00011 13.012 2.41104 13.012C2.82197 13.012 3.15509 12.6789 3.15509 12.2679V10.4822ZM2.41104 13.9049C2.82197 13.9049 3.15509 14.238 3.15509 14.6489C3.15509 14.8955 3.35496 15.0953 3.60152 15.0953C4.01245 15.0953 4.34557 15.4285 4.34557 15.8394C4.34557 16.2503 4.01245 16.5834 3.60152 16.5834C2.53311 16.5834 1.66699 15.7173 1.66699 14.6489C1.66699 14.238 2.00011 13.9049 2.41104 13.9049ZM5.23843 11.5239C5.23843 10.5377 6.03792 9.73818 7.02415 9.73818H13.5718C14.558 9.73818 15.3575 10.5377 15.3575 11.5239V14.9372L12.1665 14.1394C10.6407 13.758 9.25865 15.14 9.6401 16.6658L10.438 19.8572H7.02415C6.03792 19.8572 5.23843 19.0577 5.23843 18.0715V11.5239ZM18.1596 21.7151L17.2157 22.659C16.9832 22.8915 16.6063 22.8915 16.3739 22.659L14.4138 20.699L13.3715 21.7413C13.0443 22.0684 12.4853 21.9137 12.3731 21.4648L11.083 16.3043C10.974 15.8683 11.3689 15.4735 11.8048 15.5825L16.9654 16.8726C17.4142 16.9848 17.569 17.5438 17.2419 17.8709L16.1995 18.9133L18.1596 20.8733C18.392 21.1058 18.392 21.4827 18.1596 21.7151Z" fill="#CCD1D5"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,3 @@
<svg width="20" height="25" viewBox="0 0 20 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.91058 8.08983C3.73357 8.08983 3.59007 8.23333 3.59007 8.41034V9.05136C3.59007 9.5824 3.15957 10.0129 2.62853 10.0129C2.09749 10.0129 1.66699 9.5824 1.66699 9.05136V8.41034C1.66699 7.17124 2.67148 6.16675 3.91058 6.16675H4.55161C5.08265 6.16675 5.51315 6.59724 5.51315 7.12829C5.51315 7.65933 5.08265 8.08983 4.55161 8.08983H3.91058ZM14.4875 7.12829C14.4875 6.59724 14.918 6.16675 15.449 6.16675H16.0901C17.3292 6.16675 18.3337 7.17124 18.3337 8.41034V9.05136C18.3337 9.5824 17.9031 10.0129 17.3721 10.0129C16.8411 10.0129 16.4106 9.5824 16.4106 9.05136V8.41034C16.4106 8.23333 16.2671 8.08983 16.0901 8.08983H15.449C14.918 8.08983 14.4875 7.65933 14.4875 7.12829ZM18.3337 19.9488C18.3337 19.4178 17.9031 18.9873 17.3721 18.9873C16.8411 18.9873 16.4106 19.4178 16.4106 19.9488V20.5898C16.4106 20.7669 16.2671 20.9103 16.0901 20.9103H15.449C14.918 20.9103 14.4875 21.3409 14.4875 21.8719C14.4875 22.4029 14.918 22.8334 15.449 22.8334H16.0901C17.3292 22.8334 18.3337 21.8289 18.3337 20.5898V19.9488ZM2.62853 18.9873C3.15957 18.9873 3.59007 19.4178 3.59007 19.9488V20.5898C3.59007 20.7669 3.73357 20.9103 3.91058 20.9103H4.55161C5.08265 20.9103 5.51315 21.3409 5.51315 21.8719C5.51315 22.4029 5.08265 22.8334 4.55161 22.8334H3.91058C2.67148 22.8334 1.66699 21.8289 1.66699 20.5898V19.9488C1.66699 19.4178 2.09749 18.9873 2.62853 18.9873ZM8.39776 20.9103C7.86672 20.9103 7.43622 21.3409 7.43622 21.8719C7.43622 22.4029 7.86672 22.8334 8.39776 22.8334H11.6029C12.1339 22.8334 12.5644 22.4029 12.5644 21.8719C12.5644 21.3409 12.1339 20.9103 11.6029 20.9103H8.39776ZM7.43622 7.12829C7.43622 6.59724 7.86672 6.16675 8.39776 6.16675H11.6029C12.1339 6.16675 12.5644 6.59724 12.5644 7.12829C12.5644 7.65933 12.1339 8.08983 11.6029 8.08983H8.39776C7.86672 8.08983 7.43622 7.65933 7.43622 7.12829ZM3.59007 12.8975C3.59007 12.3665 3.15957 11.936 2.62853 11.936C2.09749 11.936 1.66699 12.3665 1.66699 12.8975V16.1026C1.66699 16.6337 2.09749 17.0642 2.62853 17.0642C3.15957 17.0642 3.59007 16.6337 3.59007 16.1026V12.8975ZM17.3721 11.936C17.9031 11.936 18.3337 12.3665 18.3337 12.8975V16.1026C18.3337 16.6337 17.9031 17.0642 17.3721 17.0642C16.8411 17.0642 16.4106 16.6337 16.4106 16.1026V12.8975C16.4106 12.3665 16.8411 11.936 17.3721 11.936ZM7.43622 10.0123C6.37413 10.0123 5.51315 10.8733 5.51315 11.9354V17.0636C5.51315 18.1256 6.37413 18.9866 7.43622 18.9866H12.5644C13.6265 18.9866 14.4875 18.1256 14.4875 17.0636V11.9354C14.4875 10.8733 13.6265 10.0123 12.5644 10.0123H7.43622Z" fill="#CCD1D5"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,3 @@
<svg width="103" height="42" viewBox="0 0 103 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M36.8298 0.809768C39.1863 -0.0104135 41.9933 -0.35598 44.1701 0.486052C45.5729 1.02867 46.4514 2.04627 46.896 3.25806C47.3183 4.40936 47.3337 5.68124 47.1897 6.83915C46.9018 9.15345 45.9098 11.5232 45.1884 12.8463C42.2889 18.1639 38.4247 22.5794 33.9787 26.2876C34.5399 26.5461 35.1642 26.7825 35.8578 26.9918C41.9402 28.8269 49.132 29.0238 56.4351 28.3262C63.7231 27.6301 71.0241 26.0534 77.2795 24.4159C82.4789 23.0549 88.4083 21.1217 93.2877 18.5872H89.6629V15.5872C92.9426 15.5872 96.5411 15.0656 99.4739 14.2229C99.907 14.0984 100.423 13.9818 100.902 14.0288C101.15 14.0531 101.586 14.1389 101.965 14.489C102.401 14.8919 102.519 15.4129 102.498 15.8141C102.48 16.1636 102.362 16.4455 102.281 16.6106C102.192 16.7928 102.085 16.9574 101.986 17.0947C101.788 17.3689 101.541 17.6478 101.3 17.9028C100.838 18.3892 100.271 18.9171 99.8104 19.3451L99.7374 19.4131C99.4924 19.6411 99.2855 19.8344 99.1255 19.9913C98.9808 20.1332 98.9314 20.1911 98.9302 20.1901C98.9301 20.19 98.9304 20.1894 98.931 20.1883C98.2154 21.2383 97.4441 22.6219 96.8553 24.0608C96.2546 25.5287 95.8916 26.9391 95.8916 28.062C95.8916 28.8904 95.22 29.562 94.3916 29.562C93.5632 29.562 92.8916 28.8904 92.8916 28.062C92.8916 26.3835 93.4101 24.5588 94.0788 22.9247C94.3303 22.3099 94.6099 21.7058 94.9046 21.1268C89.6711 23.8822 83.3845 25.9189 78.0392 27.3182C71.7006 28.9774 64.229 30.5954 56.7204 31.3126C49.227 32.0284 41.5983 31.8574 34.9912 29.8639C33.6317 29.4537 32.4359 28.9358 31.3973 28.3162C22.759 34.7179 12.321 38.8406 2.44859 41.9316C1.65801 42.1791 0.816456 41.7389 0.568925 40.9483C0.321395 40.1577 0.761626 39.3162 1.55221 39.0687C11.0603 36.0917 20.8465 32.2185 28.9544 26.3854C26.3865 23.6838 25.8234 20.144 26.3038 16.6476C26.8596 12.6029 28.8172 8.40718 30.9138 5.00092C32.0894 3.09103 34.4739 1.6298 36.8298 0.809768ZM31.3635 24.5523C35.8622 20.9286 39.7152 16.6174 42.5545 11.4101C43.1627 10.2948 43.9859 8.29206 44.2126 6.46889C44.3259 5.55807 44.2734 4.81998 44.0795 4.29123C43.9077 3.82297 43.6215 3.49045 43.0878 3.28402C41.8659 2.81135 39.8705 2.92794 37.816 3.64305C35.761 4.35831 34.126 5.50551 33.4687 6.57347C31.4736 9.81466 29.7509 13.5989 29.2759 17.056C28.8625 20.0646 29.3991 22.6539 31.3635 24.5523Z" fill="#ACB2B9"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -4,6 +4,8 @@
"cancel": "Cancel",
"save": "Save",
"savechanges": "Save changes",
"execute": "Execute",
"Build": "Build",
"back": "Back",
"edit": "Edit",
"search": "Search",

@ -1 +1 @@
Subproject commit 4ca98b6bb66d1d9845f8b326100945a969488f94
Subproject commit 961eee83206a2ad6492aba5782b381aeb7c238f7

33256
frontend/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -85,6 +85,7 @@
"query-string": "^8.1.0",
"rc-slider": "^10.1.1",
"react": "^18.2.0",
"react-accessible-treeview": "^2.11.1",
"react-beautiful-dnd": "^13.1.1",
"react-big-calendar": "^1.6.5",
"react-bootstrap": "^2.7.2",
@ -101,6 +102,7 @@
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-highlight-words": "^0.21.0",
"react-hot-toast": "^2.4.0",
"react-hotkeys-hook": "^4.3.5",
"react-i18next": "^12.1.5",
@ -185,11 +187,11 @@
"html-loader": "^4.2.0",
"html-webpack-plugin": "^5.5.0",
"jest": "^29.4.2",
"node-sass": "^8.0.0",
"path": "^0.12.7",
"postcss": "^8.4.35",
"postcss-loader": "^8.1.0",
"prettier": "^2.8.4",
"sass": "^1.78.0",
"sass-loader": "^13.2.0",
"storybook": "^7.2.1",
"style-loader": "^3.3.1",
@ -264,4 +266,4 @@
"jsx"
]
}
}
}

View file

@ -2,7 +2,7 @@ import React, { Suspense } from 'react';
// eslint-disable-next-line no-unused-vars
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
import { authorizeWorkspace, updateCurrentSession } from '@/_helpers/authorizeWorkspace';
import { authenticationService, tooljetService } from '@/_services';
import { authenticationService, tooljetService, licenseService } from '@/_services';
import { withRouter } from '@/_hoc/withRouter';
import { PrivateRoute, AdminRoute, AppsRoute, SwitchWorkspaceRoute } from '@/Routes';
import { HomePage } from '@/HomePage';
@ -42,7 +42,6 @@ import { shallow } from 'zustand/shallow';
import useStore from '@/AppBuilder/_stores/store';
import { checkIfToolJetCloud } from '@/_helpers/utils';
import { BasicPlanMigrationBanner } from '@/HomePage/BasicPlanMigrationBanner/BasicPlanMigrationBanner';
import { licenseService } from '@/_services';
const AppWrapper = (props) => {
const { isAppDarkMode } = useAppDarkMode();
@ -283,9 +282,9 @@ class AppComponent extends React.Component {
exact
path="/:workspaceId/workflows/*"
element={
<AdminRoute {...this.props}>
<PrivateRoute>
<Workflows switchDarkMode={this.switchDarkMode} darkMode={this.darkMode} />
</AdminRoute>
</PrivateRoute>
}
/>
)}
@ -295,6 +294,15 @@ class AppComponent extends React.Component {
></Route>
<Route path="settings/*" element={<InstanceSettings {...this.props} />}></Route>
<Route path="/:workspaceId/settings/*" element={<Settings {...this.props} />}></Route>
<Route
exact
path="/:workspaceId/modules"
element={
<PrivateRoute>
<HomePage switchDarkMode={this.switchDarkMode} darkMode={darkMode} appType={'module'} />
</PrivateRoute>
}
/>
{getAuditLogsRoutes(this.props)}
<Route

View file

@ -14,6 +14,7 @@ import EditorHeader from '@/AppBuilder/Header';
import LeftSidebar from '@/AppBuilder/LeftSidebar';
import Popups from './Popups';
import { ModuleProvider } from '@/AppBuilder/_contexts/ModuleContext';
import { shallow } from 'zustand/shallow';
// const EditorHeader = lazy(() => import('@/AppBuilder/Header'));
// const LeftSidebar = lazy(() => import('@/AppBuilder/LeftSidebar'));
@ -22,12 +23,13 @@ import { ModuleProvider } from '@/AppBuilder/_contexts/ModuleContext';
// const QueryPanel = lazy(() => import('@/AppBuilder/QueryPanel'));
// TODO: split Loader into separate component and remove editor loading state from Editor
export const Editor = ({ id: appId, darkMode, moduleId = 'canvas', switchDarkMode }) => {
export const Editor = ({ id: appId, darkMode, moduleId = 'canvas', switchDarkMode, appType = 'front-end' }) => {
useAppData(appId, moduleId, darkMode);
const isEditorLoading = useStore((state) => state.isEditorLoading);
const currentMode = useStore((state) => state.currentMode);
const isEditorLoading = useStore((state) => state.loaderStore.modules[moduleId].isEditorLoading, shallow);
const currentMode = useStore((state) => state.modeStore.modules[moduleId].currentMode, shallow);
const isModuleEditor = appType === 'module';
const updateIsTJDarkMode = useStore((state) => state.updateIsTJDarkMode);
const updateIsTJDarkMode = useStore((state) => state.updateIsTJDarkMode, shallow);
const changeToDarkMode = (newMode) => {
updateIsTJDarkMode(newMode);
@ -45,19 +47,19 @@ export const Editor = ({ id: appId, darkMode, moduleId = 'canvas', switchDarkMod
return (
<div className={cx('wrapper', { editor: currentMode === 'edit' })}>
<ErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<EditorHeader darkMode={darkMode} />
<LeftSidebar switchDarkMode={changeToDarkMode} darkMode={darkMode} />
</Suspense>
{window?.public_config?.ENABLE_MULTIPLAYER_EDITING === 'true' && <RealtimeCursors />}
<DndProvider backend={HTML5Backend}>
<ModuleProvider moduleId={moduleId}>
<AppCanvas moduleId={moduleId} appId={appId} />
<ModuleProvider moduleId={moduleId} appType={appType} isModuleMode={false} isModuleEditor={isModuleEditor}>
<Suspense fallback={<div>Loading...</div>}>
<EditorHeader darkMode={darkMode} />
<LeftSidebar switchDarkMode={changeToDarkMode} darkMode={darkMode} />
</Suspense>
{window?.public_config?.ENABLE_MULTIPLAYER_EDITING === 'true' && <RealtimeCursors />}
<DndProvider backend={HTML5Backend}>
<AppCanvas appId={appId} />
<QueryPanel darkMode={darkMode} />
<RightSideBar darkMode={darkMode} />
</ModuleProvider>
</DndProvider>
<Popups darkMode={darkMode} />
</DndProvider>
<Popups darkMode={darkMode} />
</ModuleProvider>
</ErrorBoundary>
</div>
);

View file

@ -1,8 +1,8 @@
import React, { useState, useEffect, useRef, useCallback } from 'react';
import React, { useState, useEffect, useRef, useMemo } from 'react';
import { Container } from './Container';
import Grid from './Grid';
import { EditorSelecto } from './Selecto';
import { ModuleProvider } from '@/AppBuilder/_contexts/ModuleContext';
import { useModuleContext } from '@/AppBuilder/_contexts/ModuleContext';
import { HotkeyProvider } from './HotkeyProvider';
import './appCanvas.scss';
import useStore from '@/AppBuilder/_stores/store';
@ -17,16 +17,20 @@ import useAppDarkMode from '@/_hooks/useAppDarkMode';
import useAppCanvasMaxWidth from './useAppCanvasMaxWidth';
import { DeleteWidgetConfirmation } from './DeleteWidgetConfirmation';
import useSidebarMargin from './useSidebarMargin';
import AppCanvasBanner from '../../AppBuilder/Header/AppCanvasBanner';
export const AppCanvas = ({ moduleId, appId, isViewerSidebarPinned }) => {
export const AppCanvas = ({ appId, isViewerSidebarPinned, isViewer = false }) => {
const { moduleId, isModuleMode, appType } = useModuleContext();
const canvasContainerRef = useRef();
const handleCanvasContainerMouseUp = useStore((state) => state.handleCanvasContainerMouseUp, shallow);
const canvasHeight = useStore((state) => state.canvasHeight);
const creationMode = useStore((state) => state.app.creationMode);
const environmentLoadingState = useStore((state) => state.environmentLoadingState || state.isEditorLoading);
const [canvasWidth, setCanvasWidth] = useState(getCanvasWidth());
const canvasHeight = useStore((state) => state.appStore.modules[moduleId].canvasHeight);
const creationMode = useStore((state) => state.appStore.modules[moduleId].app.creationMode);
const environmentLoadingState = useStore(
(state) => state.environmentLoadingState || state.loaderStore.modules[moduleId].isEditorLoading
);
const [canvasWidth, setCanvasWidth] = useState(getCanvasWidth(moduleId));
const gridWidth = canvasWidth / NO_OF_GRIDS;
const currentMode = useStore((state) => state.currentMode, shallow);
const currentMode = useStore((state) => state.modeStore.modules[moduleId].currentMode, shallow);
const pageSidebarStyle = useStore((state) => state?.pageSettings?.definition?.properties?.style, shallow);
const currentLayout = useStore((state) => state.currentLayout, shallow);
const queryPanelHeight = useStore((state) => state?.queryPanel?.queryPanelHeight || 0);
@ -42,23 +46,79 @@ export const AppCanvas = ({ moduleId, appId, isViewerSidebarPinned }) => {
const isSidebarOpen = useStore((state) => state.isSidebarOpen, shallow);
const getPageId = useStore((state) => state.getCurrentPageId, shallow);
const hideSidebar = isModuleMode || isPagesSidebarHidden || appType === 'module';
useEffect(() => {
// Need to remove this if we shift setExposedVariable Logic outside of components
// Currently present to run onLoadQueries after the component is mounted
setIsComponentLayoutReady(true);
return () => setIsComponentLayoutReady(false);
setIsComponentLayoutReady(true, moduleId);
return () => setIsComponentLayoutReady(false, moduleId);
}, []);
useEffect(() => {
function handleResize() {
const _canvasWidth = document.getElementById('real-canvas')?.getBoundingClientRect()?.width;
const _canvasWidth =
moduleId === 'canvas'
? document.getElementById('real-canvas')?.getBoundingClientRect()?.width
: document.getElementById(moduleId)?.getBoundingClientRect()?.width;
if (_canvasWidth !== 0) setCanvasWidth(_canvasWidth);
}
window.addEventListener('resize', handleResize);
if (moduleId === 'canvas') {
window.addEventListener('resize', handleResize);
} else {
const elem = document.getElementById(moduleId);
const resizeObserver = new ResizeObserver(handleResize);
if (elem) resizeObserver.observe(elem);
return () => {
if (elem) resizeObserver.unobserve(elem);
resizeObserver.disconnect();
};
}
handleResize();
return () => window.removeEventListener('resize', handleResize);
}, [currentLayout, canvasMaxWidth, isViewerSidebarPinned]);
}, [currentLayout, canvasMaxWidth, isViewerSidebarPinned, moduleId]);
const styles = useMemo(() => {
const canvasBgColor =
currentMode === 'view'
? computeViewerBackgroundColor(isAppDarkMode, canvasBgColor)
: !isAppDarkMode
? '#EBEBEF'
: '#2F3C4C';
if (isModuleMode) {
return {
borderLeft: 'none',
height: '100%',
background: canvasBgColor,
};
}
return {
borderLeft: currentMode === 'edit' && editorMarginLeft + 'px solid',
height: currentMode === 'edit' ? canvasContainerHeight : '100%',
background: canvasBgColor,
marginLeft:
isViewerSidebarPinned && !hideSidebar && currentLayout !== 'mobile' && currentMode !== 'edit'
? pageSidebarStyle === 'icon'
? '65px'
: '210px'
: 'auto',
};
}, [
currentMode,
isAppDarkMode,
isModuleMode,
editorMarginLeft,
canvasContainerHeight,
isViewerSidebarPinned,
hideSidebar,
currentLayout,
pageSidebarStyle,
]);
return (
<div
@ -66,36 +126,20 @@ export const AppCanvas = ({ moduleId, appId, isViewerSidebarPinned }) => {
id="main-editor-canvas"
onMouseUp={handleCanvasContainerMouseUp}
>
{creationMode === 'GIT' && <FreezeVersionInfo info={'Apps imported from git repository cannot be edited'} />}
{creationMode !== 'GIT' && <FreezeVersionInfo hide={currentMode !== 'edit'} />}
<AppCanvasBanner appId={appId} />
<div
ref={canvasContainerRef}
className={cx(
'canvas-container align-items-center page-container',
{ 'dark-theme theme-dark': isAppDarkMode, close: !isViewerSidebarPinned },
{ 'overflow-x-auto': (currentMode === 'edit' && isSidebarOpen) || currentMode === 'view' }
{ 'overflow-x-auto': (currentMode === 'edit' && isSidebarOpen) || currentMode === 'view' },
{ 'overflow-x-hidden': moduleId !== 'canvas' } // Disbling horizontal scroll for modules in view mode
)}
style={{
// transform: `scale(1)`,
borderLeft: currentMode === 'edit' && editorMarginLeft + 'px solid',
height: currentMode === 'edit' ? canvasContainerHeight : '100%',
background:
currentMode === 'view'
? computeViewerBackgroundColor(isAppDarkMode, canvasBgColor)
: !isAppDarkMode
? '#EBEBEF'
: '#2F3C4C',
marginLeft:
isViewerSidebarPinned && !isPagesSidebarHidden && currentLayout !== 'mobile' && currentMode !== 'edit'
? pageSidebarStyle === 'icon'
? '65px'
: '210px'
: 'auto',
}}
style={styles}
>
<div
style={{
minWidth: `calc((100vw - 300px) - 48px)`,
minWidth: isModuleMode ? '100%' : `calc((100vw - 300px) - 48px)`,
}}
className={`app-${appId} _tooljet-page-${getPageId()}`}
>
@ -107,7 +151,7 @@ export const AppCanvas = ({ moduleId, appId, isViewerSidebarPinned }) => {
{environmentLoadingState !== 'loading' && (
<div>
<Container
id="canvas"
id={moduleId}
gridWidth={gridWidth}
canvasWidth={canvasWidth}
canvasHeight={canvasHeight}
@ -115,8 +159,9 @@ export const AppCanvas = ({ moduleId, appId, isViewerSidebarPinned }) => {
canvasMaxWidth={canvasMaxWidth}
isViewerSidebarPinned={isViewerSidebarPinned}
pageSidebarStyle={pageSidebarStyle}
appType={appType}
/>
<div id="component-portal" />
{appType !== 'module' && <div id="component-portal" />}
</div>
)}

View file

@ -4,6 +4,8 @@ import './configHandle.scss';
import useStore from '@/AppBuilder/_stores/store';
import { findHighestLevelofSelection } from '../Grid/gridUtils';
import SolidIcon from '@/_ui/Icon/solidIcons/index';
import { useModuleContext } from '@/AppBuilder/_contexts/ModuleContext';
import { DROPPABLE_PARENTS } from '../appCanvasConstants';
const CONFIG_HANDLE_HEIGHT = 20;
const BUFFER_HEIGHT = 1;
@ -18,10 +20,12 @@ export const ConfigHandle = ({
showHandle,
componentType,
visibility,
isModuleContainer,
subContainerIndex,
}) => {
const { moduleId } = useModuleContext();
const shouldFreeze = useStore((state) => state.getShouldFreeze());
const componentName = useStore((state) => state.getComponentDefinition(id)?.component?.name || '', shallow);
const componentName = useStore((state) => state.getComponentDefinition(id, moduleId)?.component?.name || '', shallow);
const isMultipleComponentsSelected = useStore(
(state) => (findHighestLevelofSelection(state?.selectedComponents)?.length > 1 ? true : false),
shallow
@ -43,6 +47,7 @@ export const ConfigHandle = ({
return (
(subContainerIndex === 0 || subContainerIndex === null) &&
(isWidgetHovered ||
isModuleContainer ||
(showHandle && (!isMultipleComponentsSelected || (isModal && isModalOpen)) && !anyComponentHovered))
);
}, shallow);
@ -67,7 +72,9 @@ export const ConfigHandle = ({
if (componentType === 'Tabs') {
setFocusedParentId(`${id}-${currentTab}`);
} else {
setFocusedParentId(id);
if (DROPPABLE_PARENTS.has(componentType)) {
setFocusedParentId(id);
}
}
}}
>
@ -125,20 +132,22 @@ export const ConfigHandle = ({
data-cy={`${componentName.toLowerCase()}-inspect-button`}
className="config-handle-inspect"
/>
<span
style={{ cursor: 'pointer', marginLeft: '5px' }}
onClick={() => {
deleteComponents([id]);
}}
data-cy={`${componentName.toLowerCase()}-delete-button`}
>
<SolidIcon
name="trash"
width="12"
height="12"
fill={visibility === false ? 'var(--text-placeholder)' : '#fff'}
/>
</span>
{!isModuleContainer && (
<span
style={{ cursor: 'pointer', marginLeft: '5px' }}
onClick={() => {
deleteComponents([id]);
}}
data-cy={`${componentName.toLowerCase()}-delete-button`}
>
<SolidIcon
name="trash"
width="12"
height="12"
fill={visibility === false ? 'var(--text-placeholder)' : '#fff'}
/>
</span>
)}
</div>
)}
</span>

Some files were not shown because too many files have changed in this diff Show more