mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
commit
5a9f372a50
745 changed files with 44800 additions and 5678 deletions
|
|
@ -32,12 +32,12 @@ PGRST_HOST=
|
|||
PGRST_JWT_SECRET=
|
||||
|
||||
# Checks every 24 hours to see if a new version of ToolJet is available
|
||||
# (Enabled by default. Set 0 to disable)
|
||||
CHECK_FOR_UPDATES=0
|
||||
# (Enabled by default. Set false to disable)
|
||||
CHECK_FOR_UPDATES=true
|
||||
|
||||
# Checks every 24 hours to update app telemetry data to ToolJet hub.
|
||||
# (Telemetry is enabled by default. Set value to true to disable.)
|
||||
# DISABLE_APP_TELEMETRY=false
|
||||
# DISABLE_TOOLJET_TELEMETRY=false
|
||||
|
||||
GOOGLE_CLIENT_ID=
|
||||
GOOGLE_CLIENT_SECRET=
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
node_modules/**
|
||||
cypress-tests/**
|
||||
20
.github/workflows/ci.yml
vendored
20
.github/workflows/ci.yml
vendored
|
|
@ -36,15 +36,15 @@ jobs:
|
|||
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js 18.3.0
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
|
|
@ -66,15 +66,15 @@ jobs:
|
|||
github.ref == 'refs/heads/develop'
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js 18.3.0
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
|
|
@ -106,9 +106,9 @@ jobs:
|
|||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
|
|
@ -144,9 +144,9 @@ jobs:
|
|||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
|
|
|
|||
12
.github/workflows/cypress.yml
vendored
12
.github/workflows/cypress.yml
vendored
|
|
@ -14,10 +14,10 @@ jobs:
|
|||
Run-Cypress:
|
||||
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress' }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
|
||||
|
|
@ -33,6 +33,12 @@ jobs:
|
|||
sleep 1
|
||||
done
|
||||
|
||||
- name: Getting cypress secrets
|
||||
# use quotes around the secret, as its value
|
||||
# is simply inserted as a string into the command
|
||||
run: |
|
||||
echo '${{ secrets.CYPRESS_SECRETS }}' > cypress.env.json
|
||||
|
||||
- name: Cypress integration test
|
||||
uses: cypress-io/github-action@v5
|
||||
with:
|
||||
|
|
@ -41,7 +47,7 @@ jobs:
|
|||
config-file: cypress-run.config.js
|
||||
|
||||
- name: Capturing screenshots
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: screenshots
|
||||
|
|
|
|||
4
.github/workflows/packer-build.yml
vendored
4
.github/workflows/packer-build.yml
vendored
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setting tag
|
||||
if: "${{ github.event.inputs.version != '' }}"
|
||||
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
|
|
|
|||
2
.version
2
.version
|
|
@ -1 +1 @@
|
|||
2.4.9
|
||||
2.5.0
|
||||
|
|
|
|||
5
SECURITY.md
Normal file
5
SECURITY.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you notice a security vulnerability, please let the team know by sending an email to `security@tooljet.com`.
|
||||
|
|
@ -1,6 +1,11 @@
|
|||
const { defineConfig } = require("cypress");
|
||||
const { rmdir } = require("fs");
|
||||
const fs = require("fs");
|
||||
const XLSX = require("node-xlsx");
|
||||
|
||||
const pg = require("pg");
|
||||
const path = require("path");
|
||||
const pdf = require("pdf-parse");
|
||||
|
||||
module.exports = defineConfig({
|
||||
execTimeout: 1800000,
|
||||
|
|
@ -65,12 +70,19 @@ module.exports = defineConfig({
|
|||
|
||||
return require("./cypress/plugins/index.js")(on, config);
|
||||
},
|
||||
downloadsFolder: "cypress/downloads",
|
||||
experimentalRunAllSpecs: true,
|
||||
experimentalModfyObstructiveThirdPartyCode: true,
|
||||
experimentalRunAllSpecs: true,
|
||||
baseUrl: "http://localhost:8082",
|
||||
specPattern: [
|
||||
"cypress/e2e/editor/widget/*.cy.js"],
|
||||
"cypress/e2e/editor/app-version/version.cy.js",
|
||||
"cypress/e2e/exportImport/export.cy.js",
|
||||
"cypress/e2e/exportImport/import.cy.js",
|
||||
"cypress/e2e/database/database.cy.js",
|
||||
"cypress/e2e/editor/widget/*.cy.js",
|
||||
"cypress/e2e/editor/multipage/*.cy.js",
|
||||
],
|
||||
numTestsKeptInMemory: 1,
|
||||
redirectionLimit: 10,
|
||||
experimentalRunAllSpecs: true,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module.exports = defineConfig({
|
|||
requestTimeout: 10000,
|
||||
pageLoadTimeout: 20000,
|
||||
responseTimeout: 10000,
|
||||
viewportWidth: 1200,
|
||||
viewportWidth: 1440,
|
||||
viewportHeight: 960,
|
||||
chromeWebSecurity: false,
|
||||
trashAssetsBeforeRuns: true,
|
||||
|
|
@ -50,13 +50,17 @@ module.exports = defineConfig({
|
|||
on("task", {
|
||||
deleteFolder(folderName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
rmdir(folderName, { maxRetries: 10, recursive: true }, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return reject(err);
|
||||
}
|
||||
resolve(null);
|
||||
});
|
||||
if (fs.existsSync(folderName)) {
|
||||
rmdir(folderName, { maxRetries: 10, recursive: true }, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(null);
|
||||
});
|
||||
} else {
|
||||
return resolve(null);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
@ -73,7 +77,11 @@ module.exports = defineConfig({
|
|||
experimentalModfyObstructiveThirdPartyCode: true,
|
||||
experimentalRunAllSpecs: true,
|
||||
baseUrl: "http://localhost:8082",
|
||||
specPattern: "cypress/e2e/**/*.cy.js",
|
||||
specPattern: [
|
||||
"cypress/e2e/editor/widget/*.cy.js",
|
||||
"cypress/e2e/multipage/*.cy.js",
|
||||
],
|
||||
downloadsFolder: "cypress/downloads",
|
||||
numTestsKeptInMemory: 25,
|
||||
redirectionLimit: 10,
|
||||
experimentalRunAllSpecs: true,
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@ export const cyParamName = (paramName = "") => {
|
|||
export const commonSelectors = {
|
||||
toastMessage: ".go3958317564",
|
||||
oldToastMessage: ".go318386747",
|
||||
newToastMessage:
|
||||
'.drawer-container > [style="position: fixed; z-index: 9999; inset: 16px; pointer-events: none;"] > .go4109123758 > .go2072408551',
|
||||
toastCloseButton: '[data-cy="toast-close-button"]',
|
||||
editButton: "[data-cy=edit-button]",
|
||||
searchField: "[data-cy=widget-search-box]",
|
||||
firstWidget: "[data-cy=widget-list]:eq(0)",
|
||||
canvas: "[data-cy=real-canvas]",
|
||||
appCardOptionsButton: "[data-cy=app-card-menu-icon]",
|
||||
folderCardOptions: "[data-cy=folder-card-menu-icon]",
|
||||
autoSave: "[data-cy=autosave-indicator]",
|
||||
skipButton: ".driver-close-btn",
|
||||
skipInstallationModal: "[data-cy=skip-button]",
|
||||
|
|
@ -27,7 +28,7 @@ export const commonSelectors = {
|
|||
loginButton: '[data-cy="login-button"]',
|
||||
dropdown: "[data-cy=workspace-dropdown]",
|
||||
backButton: "[data-cy=left-sidebar-back-button]",
|
||||
emptyAppCreateButton: "[data-cy=create-new-application]",
|
||||
dashboardAppCreateButton: '[data-cy="button-new-app-from-scratch"]',
|
||||
appCreateButton: "[data-cy=create-new-app-button]",
|
||||
createButton: "[data-cy=create-button]",
|
||||
appNameInput: "[data-cy=app-name-input]",
|
||||
|
|
@ -42,7 +43,7 @@ export const commonSelectors = {
|
|||
createNewFolderButton: "[data-cy=create-new-folder-button]",
|
||||
folderNameInput: "[data-cy=folder-name-input]",
|
||||
createFolderButton: "[data-cy=create-folder-button]",
|
||||
folderList: ".css-2kg7t4-MenuList",
|
||||
folderList: ".css-169zxdi-MenuList",
|
||||
empytyFolderImage: "[data-cy=empty-folder-image]",
|
||||
emptyFolderText: "[data-cy=empty-folder-text]",
|
||||
allApplicationsLink: "[data-cy=all-applications-link]",
|
||||
|
|
@ -56,9 +57,7 @@ export const commonSelectors = {
|
|||
viewerPageLogo: '[data-cy="viewer-page-logo"]',
|
||||
lastPageArrow: '[data-cy="last-page-link"]',
|
||||
nextPageArrow: '[data-cy="next-page-link"]',
|
||||
emailFilterInput: '[data-cy="email-filter-input-field"]',
|
||||
firstNameFilterInput: '[data-cy="first-name-filter-input-field"]',
|
||||
lastNameFilterInput: '[data-cy="last-name-filter-input-field"]',
|
||||
inputUserSearch: '[data-cy="input-field-user-filter-search"]',
|
||||
filterButton: '[data-cy="filter-button"]',
|
||||
copyIcon: '[data-cy="copy-icon"]',
|
||||
addWorkspaceButton: '[data-cy="add-new-workspace-link"]',
|
||||
|
|
@ -84,11 +83,11 @@ export const commonSelectors = {
|
|||
acceptInviteButton: '[data-cy="accept-invite-button"]',
|
||||
databaseIcon: `[data-cy="database-icon"]`,
|
||||
profileSettings: '[data-cy="profile-settings"]',
|
||||
workspaceSettingsIcon: '[data-cy="workspace-settings-icon"]',
|
||||
manageUsersOption: '[data-cy="manage-users-option"]',
|
||||
manageGroupsOption: '[data-cy="manage-groups-option"]',
|
||||
manageSSOOption: '[data-cy="manage-sso-option"]',
|
||||
workspaceVariableOption: '[data-cy="workspace-variable-option"]',
|
||||
workspaceSettingsIcon: '[data-cy="icon-workspace-settings"]',
|
||||
manageUsersOption: '[data-cy="users-list-item"]',
|
||||
manageGroupsOption: '[data-cy="groups-list-item"]',
|
||||
manageSSOOption: '[data-cy="sso-list-item"]',
|
||||
workspaceVariableOption: '[data-cy="workspace-variables-list-item"]',
|
||||
clearFilterButton: '[data-cy="clear-filter-button"]',
|
||||
userStatusSelect: '[data-cy="user-status-select-continer"]',
|
||||
emailInputLabel: '[data-cy="email-input-label"]',
|
||||
|
|
@ -98,7 +97,7 @@ export const commonSelectors = {
|
|||
enableToggleLabel: '[data-cy="enable-toggle-label"]',
|
||||
enableToggle: '[data-cy="enable-toggle"]',
|
||||
mainWrapper: '[data-cy="main-wrapper"]',
|
||||
workspaceEditButton: '[data-cy="edit-workspace-button"]',
|
||||
editRectangleIcon: '[data-cy="edit-rectangle-icon"]',
|
||||
dashboardIcon: '[data-cy="dashboard-icon"]',
|
||||
notificationsIcon: '[data-cy="notifications-icon"]',
|
||||
notificationsCard: '[data-cy="notifications-card"]',
|
||||
|
|
@ -159,6 +158,14 @@ export const commonSelectors = {
|
|||
resetPasswordButton: '[data-cy="reset-password-button"]',
|
||||
resetPasswordPageDescription: '[data-cy="reset-password-page-description"]',
|
||||
backToLoginButton: '[data-cy="back-to-login-button"]',
|
||||
breadcrumbTitle: '[data-cy="breadcrumb-title"]',
|
||||
breadcrumbPageTitle: '[data-cy="breadcrumb-page-title"]',
|
||||
labelFullNameInput: '[data-cy="label-full-name-input-field"]',
|
||||
inputFieldFullName: '[data-cy="input-field-full-name"]',
|
||||
labelEmailInput: '[data-cy="label-email-input-field"]',
|
||||
inputFieldEmailAddress: '[data-cy="input-field-email"]',
|
||||
closeButton: '[data-cy="close-button"]',
|
||||
emptyAppCreateButton: "[data-cy='button-new-app-from-scratch']",
|
||||
|
||||
onboardingRadioButton: (radioButtonText) => {
|
||||
return `[data-cy="${cyParamName(radioButtonText)}-radio-button"]`;
|
||||
|
|
@ -194,6 +201,11 @@ export const commonSelectors = {
|
|||
buttonSelector: (buttonText) => {
|
||||
return `[data-cy="${cyParamName(buttonText)}-button"]`;
|
||||
},
|
||||
|
||||
folderCardOptions: (folderName)=>{
|
||||
return `[data-cy="${cyParamName(folderName)}-list-card"]>[data-cy="folder-card-menu-icon"]>svg`
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export const commonWidgetSelector = {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export const dashboardSelector = {
|
|||
emptyPageHeader: "[data-cy=empty-homepage-welcome-header]",
|
||||
emptyPageDescription: "[data-cy=empty-homepage-description]",
|
||||
createAppButton: "[data-cy=create-new-application]",
|
||||
importAppButton: "[data-cy=import-an-application]",
|
||||
importAppButton: '[data-cy="button-import-an-app"]',
|
||||
chooseFromTemplate: "[data-cy=choose-from-template]",
|
||||
modeToggle: '[data-cy="mode-switch-button"]',
|
||||
dropdownText: "[data-cy=dropdown-organization-list]>>:eq(0)",
|
||||
|
|
@ -22,7 +22,7 @@ export const dashboardSelector = {
|
|||
changeButton: "[data-cy=change-button]",
|
||||
addToFolderTitle: "[data-cy=add-to-folder-title]",
|
||||
moveAppText: "[data-cy=move-selected-app-to-text]",
|
||||
selectFolder: '[data-cy="select-folder"]>>>.css-s59k37-ValueContainer',
|
||||
selectFolder: '[data-cy="select-folder"]>>>>.css-h380uj-Input',
|
||||
addToFolderButton: "[data-cy=add-to-folder-button]",
|
||||
appTemplateRow: '[data-cy="app-template-row"]',
|
||||
homePageContent: '[data-cy="home-page-content"]',
|
||||
|
|
@ -30,6 +30,8 @@ export const dashboardSelector = {
|
|||
folderLabel: '[data-cy="folder-info"]',
|
||||
dashboardAppsHeaderLabel:'[data-cy="app-header-label"]',
|
||||
versionLabel: '[data-cy="version-label"]',
|
||||
dashboardAppCreateButton: '[data-cy="button-new-app-from-scratch"]',
|
||||
|
||||
appCardIcon: (iconName) => {
|
||||
return `[data-cy="app-card-${cyParamName(iconName)}-icon"]`;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ export const appVersionSelectors = {
|
|||
createNewVersion: '[data-cy="create-new-version-title"]',
|
||||
versionNamelabel: '[data-cy="version-name-label"]',
|
||||
appVersionMenuField:
|
||||
'[data-cy="app-version-selector"] .custom-version-selector__indicators',
|
||||
'[data-cy="app-version-selector"] .undefined__indicators',
|
||||
versionNameInputField: '[data-cy="version-name-input-field"]',
|
||||
createVersionFromLabel: '[data-cy="create-version-from-label"]',
|
||||
createVersionInputField: '[data-cy="create-version-from-input-field"]',
|
||||
createNewVersionButton: '[data-cy="create-new-version-button"]',
|
||||
appVersionContentList: ".custom-version-selector__menu-list",
|
||||
appVersionContentList: ".undefined__menu-list",
|
||||
};
|
||||
export const exportAppModalSelectors = {
|
||||
selectVersionTitle: '[data-cy= "select-a-version-to-export-title"]',
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ export const groupsSelector = {
|
|||
permissionsLink: "[data-cy=permissions-link]",
|
||||
searchBox: '[data-cy="select-search"]',
|
||||
appSearchBox:
|
||||
"[data-cy=select-search] >>.css-1e1a1lx-control > .css-s59k37-ValueContainer",
|
||||
searchBoxOptions: ".css-2kg7t4-MenuList",
|
||||
"[data-cy=select-search]>>>>>.dropdown-heading-value > .gray",
|
||||
searchBoxOptions: ".panel-content",
|
||||
appAddButton: "[data-cy=add-button]",
|
||||
addButton: '[data-cy="add-button"]',
|
||||
nameTableHeader: ".active [data-cy=name-header]",
|
||||
|
|
@ -50,14 +50,10 @@ export const groupsSelector = {
|
|||
deleteGroupLink: (groupname) => {
|
||||
return `[data-cy="${cyParamName(groupname)}-group-delete-link"]`;
|
||||
},
|
||||
selectAddButton: (groupname) => {
|
||||
return `[data-cy="${cyParamName(
|
||||
groupname
|
||||
)}-group-select-search-add-button"]`;
|
||||
},
|
||||
mutiSelectAddButton: (groupname) => {
|
||||
return `[data-cy="${cyParamName(
|
||||
groupname
|
||||
)}-group-multi-select-search-add-button"]`;
|
||||
},
|
||||
selectAddButton: '[data-cy="add-button"]'
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export const ssoSelector = {
|
||||
pagetitle: "[data-cy=manage-sso-page-title]",
|
||||
generalSettingsElements: {
|
||||
generalSettings: "[data-cy=left-menu-items] :eq(0)",
|
||||
generalSettings: '[data-cy="general-settings-list-item"]',
|
||||
enableSignupLabel: '[data-cy="enable-sign-up-label"]',
|
||||
helperText: "[data-cy=enable-sign-up-helper-text]",
|
||||
allowDefaultSSOLabel: '[data-cy="allow-default-sso-label"]',
|
||||
|
|
@ -19,7 +19,7 @@ export const ssoSelector = {
|
|||
workspaceLoginUrl: '[data-cy="workspace-login-url"]',
|
||||
cancelButton: "[data-cy=cancel-button]",
|
||||
saveButton: "[data-cy=save-button]",
|
||||
google: "[data-cy=left-menu-items] :eq(1)",
|
||||
google: '[data-cy="google-list-item"]',
|
||||
googleEnableToggle: '[data-cy="google-enable-toggle"]',
|
||||
statusLabel: "[data-cy=status-label]",
|
||||
clientIdLabel: "[data-cy=client-id-label]",
|
||||
|
|
@ -29,8 +29,9 @@ export const ssoSelector = {
|
|||
googleTile: '[data-cy="google-sign-in-text"]',
|
||||
googleIcon: "[data-cy=google-sso-icon]",
|
||||
googleSSOText: "[data-cy=google-sso-text]",
|
||||
git: "[data-cy=left-menu-items] :eq(2)",
|
||||
gitEnableToggle: '[data-cy="git-enable-toogle"]',
|
||||
git: '[data-cy="github-list-item"]',
|
||||
gitEnableToggle: '[data-cy="github-toggle-input"]',
|
||||
githubLabel:'[data-cy="github-toggle-label"]',
|
||||
clientSecretLabel: "[data-cy=client-secret-label]",
|
||||
encriptedLabel: "[data-cy=encripted-label]",
|
||||
clientSecretInput: "[data-cy=client-secret-input]",
|
||||
|
|
@ -48,4 +49,7 @@ export const ssoSelector = {
|
|||
signInHeader: '[data-cy="sign-in-header"]',
|
||||
workspaceSubHeader: '[data-cy="workspace-sign-in-sub-header"]',
|
||||
noLoginMethodWarning: '[data-cy="no-login-methods-warning"]',
|
||||
passwordLoginToggleLbale: '[data-cy="label-password-login"]',
|
||||
alertText: '[data-cy="alert-text"]',
|
||||
disablePasswordHelperText: '[data-cy="disable-password-helper-text"]',
|
||||
};
|
||||
|
|
@ -1,27 +1,31 @@
|
|||
export const usersSelector = {
|
||||
dropdown: "[data-cy=workspace-dropdown]",
|
||||
inviteUserButton: "[data-cy=invite-new-user]",
|
||||
buttonAddUsers: "[data-cy=button-invite-new-user]",
|
||||
usersElements: {
|
||||
pageTitle: "[data-cy=users-page-title]",
|
||||
nameTitile: "[data-cy=name-title]",
|
||||
emailTitle: "[data-cy=email-title]",
|
||||
statusTitle: "[data-cy=status-title]",
|
||||
usersTableNameColumnHeader: '[data-cy="users-table-name-column-header"]',
|
||||
usersTableEmailColumnHeader: '[data-cy="users-table-email-column-header"]',
|
||||
usersTableStatusColumnHeader: '[data-cy="users-table-status-column-header"]',
|
||||
usersFilterLabel: '[data-cy="users-filter-label"]'
|
||||
},
|
||||
usersPageTitle: '[data-cy="title-users-page"]',
|
||||
userFilterInput: '[data-cy="users-filter-input"]',
|
||||
adminUserName: "[data-cy=user-name]",
|
||||
adminUserEmail: "[data-cy=user-email]",
|
||||
userStatus: "[data-cy=user-status]:eq(0)",
|
||||
userState: "[data-cy=user-state]:eq(0)",
|
||||
userStatus: "[data-cy=user-status]",
|
||||
cardTitle: "[data-cy=add-new-user]",
|
||||
firstNameInput: "[data-cy=first-name-input]",
|
||||
addUsersCardTitle: '[data-cy="add-users-card-title"]',
|
||||
|
||||
inputFieldName: "[data-cy=first-name-input]",
|
||||
lastNameInput: "[data-cy=last-name-input]",
|
||||
emailLabel: "[data-cy=email-label]",
|
||||
emailInput: "[data-cy=email-input]",
|
||||
cancelButton: "[data-cy=cancel-button]",
|
||||
createUserButton: "[data-cy=create-user-button]",
|
||||
fisrtNameError: "[data-cy=first-name-error]",
|
||||
lastNameError: "[data-cy=last-name-error]",
|
||||
emailError: "[data-cy=email-error]",
|
||||
buttonInviteUsers: '[data-cy="button-invite-users"]',
|
||||
buttonInviteWithEmail: '[data-cy="button-invite-with-email"]',
|
||||
buttonUploadCsvFile: '[data-cy="button-upload-csv-file"]',
|
||||
fullNameError: '[data-cy="error-message-fullname"]',
|
||||
emailError: '[data-cy="error-message-email"]',
|
||||
pageLogo: "[data-cy=page-logo]",
|
||||
invitePageHeader: '[data-cy="invite-page-header"]',
|
||||
invitePgaeSubHeader: '[data-cy="invite-page-sub-header"]',
|
||||
|
|
@ -47,7 +51,12 @@ export const usersSelector = {
|
|||
inviteBulkUserButton: '[data-cy="invite-bulk-user-button"]',
|
||||
bulkUserUploadPageTitle: '[data-cy="bulk-user-upload-page-title"]',
|
||||
bulkUSerUploadInput: '[data-cy="bulk-user-upload-input"]',
|
||||
downloadTemplateButton: '[data-cy="download-template-button"]',
|
||||
createUsersButton: '[data-cy="create-users-button"]',
|
||||
|
||||
buttonDownloadTemplate: '[data-cy="button-download-template"]',
|
||||
buttonUploadUsers: '[data-cy="button-upload-users"]',
|
||||
helperTextBulkUpload: '[data-cy="helper-text-bulk-upload"]',
|
||||
iconBulkUpload:'[data-cy="icon-bulk-upload"]',
|
||||
helperTextSelectFile:'[data-cy="helper-text-select-file"]',
|
||||
helperTextDropFile: '[data-cy="helper-text-drop-file"]',
|
||||
inputFieldBulkUpload: '[data-cy="input-field-bulk-upload"]',
|
||||
copyInvitationLink: '[data-cy="copy-invitation-link"]',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const tableSelector = {
|
|||
|
||||
labelNumberOfRecords: '[data-cy="footer-number-of-records"]',
|
||||
|
||||
buttonDownloadDropdown: '[data-tip="Download"]',
|
||||
buttonDownloadDropdown: '[data-tooltip-id="tooltip-for-download"]',
|
||||
optionDownloadCSV: '[data-cy="option-download-CSV"]',
|
||||
optionDownloadExcel: '[data-cy="option-download-execel"]',
|
||||
optionDownloadPdf: '[data-cy="option-download-pdf"]',
|
||||
|
|
@ -31,7 +31,7 @@ export const tableSelector = {
|
|||
return `[data-cy="column-header-${column}"]`;
|
||||
},
|
||||
|
||||
filterButton: '[data-tip="Filter data"]',
|
||||
filterButton: '[data-tooltip-id="tooltip-for-filter-data"]',
|
||||
headerFilters: '[data-cy="header-filters"]',
|
||||
labelNoFilters: '[data-cy="label-no-filters"]',
|
||||
buttonAddFilter: '[data-cy="button-add-filter"]',
|
||||
|
|
|
|||
|
|
@ -123,6 +123,14 @@ export const commonText = {
|
|||
backToLoginButton: "Back to log in",
|
||||
resetPasswordPageDescription:
|
||||
"Your password has been reset successfully, log into ToolJet to continue your session",
|
||||
labelFullNameInput: "Enter full name",
|
||||
labelEmailInput: "Email address",
|
||||
breadcrumbworkspaceSettingTitle:"Workspace settings",
|
||||
breadcrumbGlobalDatasourceTitle: "Global datasources",
|
||||
breadcrumbDatabaseTitle: "Databse",
|
||||
breadcrumbApplications: "Applications",
|
||||
breadcrumbSettings: "Settings",
|
||||
|
||||
emailPageDescription: (email) => {
|
||||
return `We’ve sent an email to ${email} with a verification link. Please use that to verify your email address.`;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
export const ssoText = {
|
||||
pagetitle: "Manage SSO",
|
||||
pagetitle: " SSO",
|
||||
generalSettingsElements: {
|
||||
generalSettings: "General Settings",
|
||||
enableSignupLabel: "Enable Signup",
|
||||
helperText: "New account will be created for user's first time SSO sign in",
|
||||
allowDefaultSSOLabel: "Allow default SSO",
|
||||
allowDefaultSSOHelperText:
|
||||
"Allow users to authenticate via default SSO. Default SSO configurations can be overridden by workspace level SSO.",
|
||||
"Allow users to authenticate via default SSO. Default SSO configurations can be overridden by \n workspace level SSO.",
|
||||
allowedDomainLabel: "Allowed domains",
|
||||
allowedDomainHelperText:
|
||||
"Support multiple domains. Enter domain names separated by comma. example: tooljet.com,tooljet.io,yourorganization.com",
|
||||
|
|
@ -14,7 +14,7 @@ export const ssoText = {
|
|||
workspaceLoginHelpText: "Use this URL to login directly to this workspace",
|
||||
},
|
||||
cancelButton: "Cancel",
|
||||
saveButton: "Save",
|
||||
saveButton: "Save changes",
|
||||
allowedDomain: "tooljet.io,gmail.com",
|
||||
ssoToast: "updated sso configurations",
|
||||
ssoToast2: "updated SSO configurations",
|
||||
|
|
@ -50,4 +50,7 @@ export const ssoText = {
|
|||
googleSignUpText: "Sign up with Google",
|
||||
gitSignUpText: "Sign up with GitHub",
|
||||
gitUserStatusToast:"GitHub login failed - User does not exist in the workspace",
|
||||
passwordLoginToggleLbale: 'Password login ',
|
||||
alertText: 'Danger zone',
|
||||
disablePasswordHelperText: 'Disable password login only if your SSO is configured otherwise you will get logged out.',
|
||||
};
|
||||
|
|
@ -1,20 +1,21 @@
|
|||
export const usersText = {
|
||||
usersElements: {
|
||||
pageTitle: "Users & Permissions",
|
||||
nameTitile: "NAME",
|
||||
emailTitle: "EMAIL",
|
||||
statusTitle: "STATUS",
|
||||
|
||||
usersTableNameColumnHeader: "NAME",
|
||||
usersTableEmailColumnHeader: "EMAIL",
|
||||
usersTableStatusColumnHeader: "STATUS",
|
||||
usersFilterLabel: "Showing"
|
||||
},
|
||||
usersPageTitle: "users",
|
||||
breadcrumbUsersPageTitle: " Users & permissions",
|
||||
adminUserName: "The Developer",
|
||||
adminUserEmail: "dev@tooljet.io",
|
||||
adminUserState: "Archive",
|
||||
inviteUserButton: "Invite new user",
|
||||
cardTitle: "Add new user",
|
||||
buttonAddUsers: "Add users",
|
||||
addUsersCardTitle: "Add users",
|
||||
emailLabel: "Email address",
|
||||
cancelButton: "Cancel",
|
||||
createUserButton: "Create User",
|
||||
fieldRequired: "This field is required",
|
||||
buttonInviteUsers: "Invite users",
|
||||
errorTextFieldRequired: "This field is required",
|
||||
exsitingEmail: "User with such email already exists.",
|
||||
userCreatedToast: "User has been created",
|
||||
inviteCopiedToast: "Invitation URL copied",
|
||||
|
|
@ -47,6 +48,13 @@ export const usersText = {
|
|||
"Added to the workspace and password has been set successfully.",
|
||||
inviteBulkUserButton:"Invite bulk users",
|
||||
bulkUserUploadPageTitle: "Upload Users",
|
||||
downloadTemplateButton: 'Download Template',
|
||||
createUsersButton:"Create Users",
|
||||
buttonDownloadTemplate: 'Download Template',
|
||||
buttonUploadUsers:"Upload users",
|
||||
|
||||
buttonInviteWithEmail: " Invite with email",
|
||||
buttonUploadCsvFile: "Upload CSV file",
|
||||
|
||||
helperTextBulkUpload: 'Download the ToolJet template to add user details or format your file in the same as the template. ToolJet won’t be able to recognise files in any other format. ',
|
||||
helperTextSelectFile:'Select a CSV file to upload',
|
||||
helperTextDropFile: 'Or drag and drop it here',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
export const multipageText={
|
||||
labelPages: "Pages",
|
||||
pageNameHome: "Home",
|
||||
headerPageHandle: "Page Handle",
|
||||
pageHandleModalTitle: "Edit page handle",
|
||||
editPagehandleInfo: "Changing the page handle will break any existing apps that are using this page.",
|
||||
pageHanmdleEmptyMessage: "Page handle cannot be empty",
|
||||
samePagehandleToast: "Page with same handle already exists",
|
||||
export const multipageText = {
|
||||
labelPages: "Pages",
|
||||
pageNameHome: "Home",
|
||||
headerPageHandle: "Page Handle",
|
||||
pageHandleModalTitle: "Edit page handle",
|
||||
editPagehandleInfo:
|
||||
"Changing the page handle will break any existing apps that are using this page.",
|
||||
pageHanmdleEmptyMessage: "Page handle cannot be empty",
|
||||
samePagehandleToast: "Page with same handle already exists",
|
||||
|
||||
optionRename: "Rename",
|
||||
optionMarkHome: "Mark home",
|
||||
optionHidePage: "Hide page",
|
||||
|
||||
optionRename: "Rename",
|
||||
optionMarkHome: "Mark home",
|
||||
optionHidePage: "Hide page",
|
||||
optionEventHandler: "Event Handlers",
|
||||
eventModalTitle: "Page Events",
|
||||
labelEvents: "Events",
|
||||
addEventHandlerLink: "+ Add event handler",
|
||||
noEventHandlerInfo: "This page doesn't have any event handlers",
|
||||
|
||||
optionEventHandler: "Event Handlers",
|
||||
eventModalTitle: "Page Events",
|
||||
labelEvents: "Events",
|
||||
addEventHandlerLink: "+ Add event handler",
|
||||
noEventHandlerInfo: "This query doesn't have any event handlers",
|
||||
optionDeletePage: "Delete Page",
|
||||
deleteModalMessage: "Do you really want to delete Home page?",
|
||||
|
||||
optionDeletePage: "Delete Page",
|
||||
deleteModalMessage: "Do you really want to delete this page?",
|
||||
headerSettings: "Settings",
|
||||
optionDisableMenu: "Disable Menu",
|
||||
disableMenuDescription:
|
||||
"To hide the page navigation sidebar in viewer mode, set this option to on.",
|
||||
|
||||
headerSettings: "Settings",
|
||||
optionDisableMenu: "Disable Menu",
|
||||
disableMenuDescription: "To hide the page navigation sidebar in viewer mode, set this option to on.",
|
||||
|
||||
labelNoPagesFound: "No pages found",
|
||||
|
||||
}
|
||||
labelNoPagesFound: "No pages found",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ describe("Password reset functionality", () => {
|
|||
|
||||
before(() => {
|
||||
cy.appUILogin();
|
||||
addNewUserMW(data.firstName, data.lastName, data.email);
|
||||
addNewUserMW(data.firstName, data.email);
|
||||
logout();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ describe("User signup", () => {
|
|||
cy.visit("/");
|
||||
});
|
||||
it("Verify sign up page elements", () => {
|
||||
cy.get(commonSelectors.createAnAccountLink).click();
|
||||
cy.wait(500);
|
||||
cy.reload();
|
||||
cy.get(commonSelectors.createAnAccountLink).realClick();
|
||||
SignUpPageElements();
|
||||
|
||||
cy.clearAndType(commonSelectors.nameInputField, data.fullName);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ describe("dashboard", () => {
|
|||
const data = {};
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
data.folderName = `${fake.companyName}-Folder`;
|
||||
data.cloneAppName = `${data.appName}-Clone`;
|
||||
data.cloneAppName = `cloned-${data.appName}`;
|
||||
data.updatedFolderName = `New-${data.folderName}`;
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -40,9 +40,10 @@ describe("dashboard", () => {
|
|||
cy.intercept("GET", "/api/apps?page=1&folder=&searchKey=", {
|
||||
fixture: "intercept/emptyDashboard.json",
|
||||
}).as("emptyDashboard");
|
||||
cy.intercept("GET", "/api/folders?searchKey=",{"folders":[]}).as("folders");
|
||||
login();
|
||||
cy.wait("@emptyDashboard");
|
||||
|
||||
cy.wait("@folders");
|
||||
deleteDownloadsFolder();
|
||||
});
|
||||
|
||||
|
|
@ -51,19 +52,17 @@ describe("dashboard", () => {
|
|||
cy.get(
|
||||
commonSelectors.workspaceName
|
||||
).verifyVisibleElement("have.text", "My workspace");
|
||||
cy.get(commonSelectors.workspaceEditButton).should("be.visible");
|
||||
cy.get(commonSelectors.workspaceName).click();
|
||||
cy.get(commonSelectors.editRectangleIcon).should("be.visible");
|
||||
cy.get(commonSelectors.appCreateButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
"New app"
|
||||
"Create new app"
|
||||
);
|
||||
cy.get(dashboardSelector.folderLabel).should("be.visible");
|
||||
cy.get(dashboardSelector.folderLabel).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq("Folders");
|
||||
});
|
||||
cy.get(commonSelectors.createNewFolderButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
"+ Create new"
|
||||
);
|
||||
cy.get(commonSelectors.createNewFolderButton).should("be.visible");
|
||||
cy.get(commonSelectors.allApplicationLink).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.allApplicationLink
|
||||
|
|
@ -92,32 +91,34 @@ describe("dashboard", () => {
|
|||
commonText.viewReadNotifications
|
||||
);
|
||||
|
||||
cy.get(commonSelectors.profileSettings).should("be.visible").click();
|
||||
cy.get(profileSelector.profileLink).verifyVisibleElement(
|
||||
"have.text",
|
||||
profileText.profileLink
|
||||
);
|
||||
cy.get(dashboardSelector.modeToggle)
|
||||
.verifyVisibleElement("have.text", dashboardText.darkModeText)
|
||||
|
||||
cy.get(dashboardSelector.modeToggle).should("be.visible")
|
||||
.click();
|
||||
cy.get(commonSelectors.mainWrapper)
|
||||
.should("have.attr", "class")
|
||||
.and("contain", "theme-dark");
|
||||
cy.get(dashboardSelector.modeToggle)
|
||||
.verifyVisibleElement("have.text", dashboardText.lightModeText)
|
||||
.click();
|
||||
cy.get(dashboardSelector.modeToggle).click();
|
||||
cy.get(dashboardSelector.homePageContent)
|
||||
.should("have.attr", "class")
|
||||
.and("contain", "bg-light-gray");
|
||||
|
||||
cy.get(commonSelectors.profileSettings).should("be.visible").click();
|
||||
cy.get(profileSelector.profileLink).verifyVisibleElement(
|
||||
"have.text",
|
||||
profileText.profileLink
|
||||
);
|
||||
cy.get(commonSelectors.logoutLink).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.logoutLink
|
||||
);
|
||||
|
||||
cy.get(dashboardSelector.dashboardAppsHeaderLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
dashboardText.dashboardAppsHeaderLabel
|
||||
);
|
||||
cy.get(commonSelectors.breadcrumbTitle).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
commonText.breadcrumbApplications
|
||||
);
|
||||
});
|
||||
cy.get(commonSelectors.breadcrumbPageTitle).verifyVisibleElement( "have.text",dashboardText.dashboardAppsHeaderLabel);
|
||||
|
||||
cy.get(dashboardSelector.versionLabel).should("be.visible");
|
||||
cy.get(dashboardSelector.emptyPageImage).should("be.visible");
|
||||
cy.get(dashboardSelector.emptyPageHeader).verifyVisibleElement(
|
||||
|
|
@ -128,17 +129,15 @@ describe("dashboard", () => {
|
|||
"have.text",
|
||||
dashboardText.emptyPageDescription
|
||||
);
|
||||
cy.get(dashboardSelector.createAppButton).verifyVisibleElement(
|
||||
cy.get(dashboardSelector.dashboardAppCreateButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
dashboardText.createAppButton
|
||||
);
|
||||
cy.get(dashboardSelector.importAppButton)
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
expect(text.replace(/\u00a0/g, " ")).equal(
|
||||
dashboardText.importAppButton
|
||||
);
|
||||
});
|
||||
// cy.get(dashboardSelector.importAppButton).verifyVisibleElement(
|
||||
// "have.text",
|
||||
// dashboardText.importAppButton
|
||||
// );
|
||||
|
||||
cy.get(dashboardSelector.appTemplateRow).should("be.visible");
|
||||
});
|
||||
|
||||
|
|
@ -166,9 +165,8 @@ describe("dashboard", () => {
|
|||
});
|
||||
});
|
||||
|
||||
viewAppCardOptions(data.appName);
|
||||
cy.get(
|
||||
commonSelectors.appCardOptions(commonText.changeIconOption)
|
||||
viewAppCardOptions(data.appName);
|
||||
cy.get(commonSelectors.appCardOptions(commonText.changeIconOption)
|
||||
).verifyVisibleElement("have.text", commonText.changeIconOption);
|
||||
cy.get(
|
||||
commonSelectors.appCardOptions(commonText.addToFolderOption)
|
||||
|
|
@ -226,7 +224,7 @@ describe("dashboard", () => {
|
|||
|
||||
cancelModal(commonText.cancelButton);
|
||||
|
||||
cy.get(commonSelectors.appCardOptionsButton).click();
|
||||
viewAppCardOptions(data.appName);
|
||||
cy.get(
|
||||
commonSelectors.appCardOptions(commonText.removeFromFolderOption)
|
||||
).click();
|
||||
|
|
@ -256,7 +254,7 @@ describe("dashboard", () => {
|
|||
cy.get(commonSelectors.editorPageLogo).click();
|
||||
cy.wait("@appLibrary");
|
||||
cy.wait(500);
|
||||
cy.reloadAppForTheElement(data.appName);
|
||||
cy.reloadAppForTheElement(data.cloneAppName);
|
||||
|
||||
cy.get(commonSelectors.appCard(data.cloneAppName)).should("be.visible");
|
||||
|
||||
|
|
@ -304,10 +302,12 @@ describe("dashboard", () => {
|
|||
});
|
||||
|
||||
it("Should verify the app CRUD operation", () => {
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
cy.appUILogin();
|
||||
cy.createApp();
|
||||
cy.renameApp(data.appName);
|
||||
cy.get(commonSelectors.editorPageLogo).click();
|
||||
cy.reloadAppForTheElement(data.appName);
|
||||
cy.get(commonSelectors.appCard(data.appName)).should(
|
||||
"contain.text",
|
||||
data.appName
|
||||
|
|
@ -328,6 +328,7 @@ describe("dashboard", () => {
|
|||
});
|
||||
|
||||
it("Should verify the folder CRUD operation", () => {
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
cy.appUILogin();
|
||||
cy.createApp();
|
||||
cy.renameApp(data.appName);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import * as common from "Support/utils/common";
|
|||
import { ssoText } from "Texts/manageSSO";
|
||||
import * as SSO from "Support/utils/manageSSO";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
|
||||
|
||||
describe("Manage SSO for multi workspace", () => {
|
||||
const data = {};
|
||||
|
|
@ -12,10 +14,14 @@ describe("Manage SSO for multi workspace", () => {
|
|||
});
|
||||
it("Should verify General settings page elements", () => {
|
||||
common.navigateToManageSSO();
|
||||
cy.get(ssoSelector.pagetitle).verifyVisibleElement(
|
||||
"have.text",
|
||||
"SSO"
|
||||
);
|
||||
|
||||
cy.get(commonSelectors.breadcrumbTitle).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
commonText.breadcrumbworkspaceSettingTitle
|
||||
);
|
||||
});
|
||||
cy.get(commonSelectors.breadcrumbPageTitle).verifyVisibleElement( "have.text",ssoText.pagetitle);
|
||||
|
||||
cy.get(ssoSelector.cardTitle).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.generalSettingsElements.generalSettings
|
||||
|
|
@ -43,16 +49,20 @@ describe("Manage SSO for multi workspace", () => {
|
|||
);
|
||||
|
||||
SSO.generalSettings();
|
||||
|
||||
cy.get(ssoSelector.alertText).verifyVisibleElement( "have.text",ssoText.alertText);
|
||||
cy.get(ssoSelector.passwordEnableToggle).should("be.visible");
|
||||
cy.get(ssoSelector.passwordLoginToggleLbale).verifyVisibleElement( "have.text",ssoText.passwordLoginToggleLbale);
|
||||
cy.get(ssoSelector.disablePasswordHelperText).verifyVisibleElement( "have.text",ssoText.disablePasswordHelperText);
|
||||
|
||||
SSO.passwordPageElements();
|
||||
});
|
||||
|
||||
it("Should verify Google SSO page elements", () => {
|
||||
common.navigateToManageSSO();
|
||||
cy.get(ssoSelector.google).should("be.visible").click();
|
||||
cy.get(ssoSelector.cardTitle)
|
||||
.should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(ssoText.googleTitle);
|
||||
})
|
||||
.and("be.visible");
|
||||
cy.get(ssoSelector.cardTitle).verifyVisibleElement(
|
||||
"have.text",ssoText.googleTitle)
|
||||
cy.get(ssoSelector.googleEnableToggle).should("be.visible");
|
||||
cy.get(ssoSelector.clientIdLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -84,12 +94,10 @@ describe("Manage SSO for multi workspace", () => {
|
|||
common.navigateToManageSSO();
|
||||
|
||||
cy.get(ssoSelector.git).should("be.visible").click();
|
||||
cy.get(ssoSelector.cardTitle)
|
||||
.should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(ssoText.gitTitle);
|
||||
})
|
||||
.and("be.visible");
|
||||
cy.get(ssoSelector.hostNameLabel).verifyVisibleElement(
|
||||
cy.get(ssoSelector.githubLabel).verifyVisibleElement(
|
||||
"have.text",ssoText.gitTitle);
|
||||
|
||||
cy.get(ssoSelector.hostNameLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.hostNameLabel
|
||||
);
|
||||
|
|
@ -135,23 +143,6 @@ describe("Manage SSO for multi workspace", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("Should verify Password login page elements", () => {
|
||||
|
||||
common.navigateToManageSSO();
|
||||
|
||||
cy.get(ssoSelector.password).should("be.visible").click();
|
||||
cy.get(ssoSelector.cardTitle)
|
||||
.should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
ssoText.passwordTitle
|
||||
);
|
||||
})
|
||||
.and("be.visible");
|
||||
cy.get(ssoSelector.passwordEnableToggle).should("be.visible");
|
||||
|
||||
SSO.passwordPageElements();
|
||||
});
|
||||
|
||||
it("Should verify the workspace login page", () => {
|
||||
data.workspaceName = fake.companyName;
|
||||
|
||||
|
|
@ -220,13 +211,9 @@ describe("Manage SSO for multi workspace", () => {
|
|||
|
||||
SSO.workspaceLogin(data.workspaceName);
|
||||
common.navigateToManageSSO();
|
||||
cy.get(ssoSelector.password).should("be.visible").click();
|
||||
cy.get(ssoSelector.passwordEnableToggle).uncheck();
|
||||
cy.get(commonSelectors.buttonSelector("Yes")).click();
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
cy.get(ssoSelector.googleSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -245,7 +232,6 @@ describe("Manage SSO for multi workspace", () => {
|
|||
common.createWorkspace(data.workspaceName);
|
||||
cy.wait(300);
|
||||
SSO.disableDefaultSSO();
|
||||
cy.get(ssoSelector.password).should("be.visible").click();
|
||||
cy.get(ssoSelector.passwordEnableToggle).uncheck();
|
||||
cy.get(commonSelectors.buttonSelector("Yes")).click();
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonSelectors } from "Selectors/common"
|
||||
import { fake } from "Fixtures/fake";
|
||||
import { usersText } from "Texts/manageUsers"
|
||||
import { usersSelector } from "Selectors/manageUsers";
|
||||
import { usersText } from "Texts/manageUsers";
|
||||
import * as users from "Support/utils/manageUsers";
|
||||
import * as common from "Support/utils/common";
|
||||
import { path } from "Texts/common";
|
||||
import { dashboardSelector } from "../../../constants/selectors/dashboard";
|
||||
import { dashboardSelector } from "Selectors/dashboard";
|
||||
|
||||
const data = {};
|
||||
data.firstName = fake.firstName;
|
||||
|
|
@ -21,106 +21,43 @@ describe("Manage Users for multiple workspace", () => {
|
|||
common.navigateToManageUsers();
|
||||
users.manageUsersElements();
|
||||
|
||||
cy.get(usersSelector.cancelButton).click();
|
||||
cy.get(usersSelector.usersElements.nameTitile).should("be.visible");
|
||||
cy.get(usersSelector.inviteUserButton).click();
|
||||
cy.get(commonSelectors.cancelButton).click();
|
||||
cy.get(usersSelector.usersPageTitle).should("be.visible");
|
||||
cy.get(usersSelector.buttonAddUsers).click();
|
||||
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.get(usersSelector.fisrtNameError).verifyVisibleElement(
|
||||
cy.get(usersSelector.buttonInviteUsers).click();
|
||||
cy.get(usersSelector.fullNameError).verifyVisibleElement("have.text",usersText.errorTextFieldRequired);
|
||||
cy.get(usersSelector.emailError).verifyVisibleElement("have.text",usersText.errorTextFieldRequired);
|
||||
|
||||
cy.clearAndType(commonSelectors.inputFieldFullName, data.firstName);
|
||||
cy.get(commonSelectors.inputFieldEmailAddress).clear();
|
||||
cy.get(usersSelector.buttonInviteUsers).click();
|
||||
cy.get(usersSelector.emailError).verifyVisibleElement("have.text",usersText.errorTextFieldRequired);
|
||||
|
||||
cy.get(commonSelectors.inputFieldFullName).clear();
|
||||
cy.clearAndType(commonSelectors.inputFieldEmailAddress, data.email);
|
||||
cy.get(usersSelector.buttonInviteUsers).click();
|
||||
cy.get(usersSelector.fullNameError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
cy.get(usersSelector.lastNameError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
cy.get(usersSelector.emailError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
usersText.errorTextFieldRequired
|
||||
);
|
||||
|
||||
cy.clearAndType(usersSelector.firstNameInput, data.firstName);
|
||||
cy.get(usersSelector.lastNameInput).clear();
|
||||
cy.get(usersSelector.emailInput).clear();
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.get(usersSelector.lastNameError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
cy.get(usersSelector.emailError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
|
||||
cy.get(usersSelector.firstNameInput).clear();
|
||||
cy.get(usersSelector.emailInput).clear();
|
||||
cy.clearAndType(usersSelector.lastNameInput, data.lastName);
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.get(usersSelector.fisrtNameError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
cy.get(usersSelector.emailError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
|
||||
cy.get(usersSelector.firstNameInput).clear();
|
||||
cy.get(usersSelector.lastNameInput).clear();
|
||||
cy.clearAndType(usersSelector.emailInput, data.email);
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.get(usersSelector.fisrtNameError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
cy.get(usersSelector.lastNameError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
|
||||
cy.get(usersSelector.firstNameInput).clear();
|
||||
cy.clearAndType(usersSelector.lastNameInput, data.lastName);
|
||||
cy.clearAndType(usersSelector.emailInput, data.email);
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.get(usersSelector.fisrtNameError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
|
||||
cy.get(usersSelector.lastNameInput).clear();
|
||||
cy.clearAndType(usersSelector.firstNameInput, data.firstName);
|
||||
cy.clearAndType(usersSelector.emailInput, data.email);
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.get(usersSelector.lastNameError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
|
||||
cy.get(usersSelector.emailInput).clear();
|
||||
cy.clearAndType(usersSelector.firstNameInput, data.firstName);
|
||||
cy.clearAndType(usersSelector.lastNameInput, data.lastName);
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.get(usersSelector.emailError).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.fieldRequired
|
||||
);
|
||||
|
||||
cy.clearAndType(usersSelector.firstNameInput, data.firstName);
|
||||
cy.clearAndType(usersSelector.lastNameInput, data.lastName);
|
||||
cy.clearAndType(commonSelectors.inputFieldFullName, data.firstName);
|
||||
cy.clearAndType(
|
||||
usersSelector.emailInput,
|
||||
commonSelectors.inputFieldEmailAddress,
|
||||
usersText.adminUserEmail
|
||||
);
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.get(usersSelector.buttonInviteUsers).click();
|
||||
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
commonSelectors.newToastMessage,
|
||||
usersText.exsitingEmail
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify the confirm invite page and new user account", () => {
|
||||
common.navigateToManageUsers();
|
||||
users.inviteUser(data.firstName, data.lastName, data.email);
|
||||
users.inviteUser(data.firstName, data.email);
|
||||
users.confirmInviteElements();
|
||||
|
||||
cy.clearAndType(commonSelectors.passwordInputField, "pass");
|
||||
|
|
@ -200,7 +137,7 @@ describe("Manage Users for multiple workspace", () => {
|
|||
cy.contains("td", data.email)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get("td img").click();
|
||||
cy.get(usersSelector.copyInvitationLink).click();
|
||||
});
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
|
|
@ -219,7 +156,6 @@ describe("Manage Users for multiple workspace", () => {
|
|||
cy.get("@copyToClipboardPrompt").then((prompt) => {
|
||||
common.logout();
|
||||
cy.visit(prompt.args[0][1]);
|
||||
cy.url().should("include", path.confirmInvite);
|
||||
});
|
||||
|
||||
cy.get(usersSelector.acceptInvite).click();
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import { groupsText } from "Texts/manageGroups";
|
|||
import * as permissions from "Support/utils/userPermissions";
|
||||
import { usersSelector } from "Selectors/manageUsers";
|
||||
import { commonText } from "Texts/common";
|
||||
import { workspaceVarSelectors } from "../../../constants/selectors/workspaceVariable";
|
||||
import { workspaceVarText } from "../../../constants/texts/workspacevarText";
|
||||
import { workspaceVarSelectors } from "Selectors/workspaceVariable";
|
||||
import { workspaceVarText } from "Texts/workspacevarText";
|
||||
|
||||
const data = {};
|
||||
data.firstName = fake.firstName;
|
||||
|
|
@ -29,20 +29,18 @@ describe("User permissions", () => {
|
|||
permissions.reset();
|
||||
permissions.addNewUserMW(
|
||||
data.firstName,
|
||||
data.lastName,
|
||||
data.email,
|
||||
data.email
|
||||
);
|
||||
|
||||
cy.get("body").then(($title) => {
|
||||
if ($title.text().includes(dashboardText.emptyPageDescription)) {
|
||||
cy.get(commonSelectors.emptyAppCreateButton).click();
|
||||
cy.get(commonSelectors.dashboardAppCreateButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
usersText.createAppPermissionToast
|
||||
);
|
||||
} else {
|
||||
cy.contains(dashboardText.createAppButton).should("not.exist");
|
||||
cy.log("The app is created by the admin");
|
||||
}
|
||||
});
|
||||
common.logout();
|
||||
|
|
@ -65,7 +63,7 @@ describe("User permissions", () => {
|
|||
common.navigateToManageGroups();
|
||||
cy.get(groupsSelector.appSearchBox).click();
|
||||
cy.get(groupsSelector.searchBoxOptions).contains(data.appName).click();
|
||||
cy.get(groupsSelector.selectAddButton("all_users")).click();
|
||||
cy.get(groupsSelector.selectAddButton).click();
|
||||
cy.get("table").contains("td", data.appName);
|
||||
cy.contains("td", data.appName)
|
||||
.parent()
|
||||
|
|
@ -84,8 +82,9 @@ describe("User permissions", () => {
|
|||
.parent()
|
||||
.within(() => {
|
||||
cy.get(commonSelectors.appTitle(data.appName)).trigger("mouseover");
|
||||
cy.get(commonSelectors.launchButton).should("have.class", "tj-disabled-btn");
|
||||
});
|
||||
cy.get(commonSelectors.launchButton).should("exist").and("be.disabled");
|
||||
|
||||
|
||||
permissions.adminLogin();
|
||||
cy.contains("tr", data.appName)
|
||||
|
|
@ -105,7 +104,7 @@ describe("User permissions", () => {
|
|||
.within(() => {
|
||||
cy.get(commonSelectors.appTitle(data.appName)).trigger("mouseover");
|
||||
});
|
||||
cy.get(commonSelectors.launchButton).should("exist").and("be.disabled");
|
||||
cy.get(commonSelectors.launchButton).should("have.class", "tj-disabled-btn");
|
||||
cy.get(commonSelectors.editButton).should("exist").and("be.enabled");
|
||||
|
||||
cy.get(commonSelectors.workspaceName).click();
|
||||
|
|
@ -114,6 +113,7 @@ describe("User permissions", () => {
|
|||
|
||||
cy.get(commonSelectors.workspaceName).click();
|
||||
cy.contains("My workspace").should("be.visible").click();
|
||||
cy.wait(200);
|
||||
});
|
||||
|
||||
it("Should verify the Create and Delete app permission", () => {
|
||||
|
|
@ -163,8 +163,6 @@ describe("User permissions", () => {
|
|||
common.logout();
|
||||
cy.login(data.email, usersText.password);
|
||||
|
||||
cy.contains("+ Create new").should("exist");
|
||||
|
||||
cy.get(commonSelectors.createNewFolderButton).click();
|
||||
cy.clearAndType(commonSelectors.folderNameInput, data.folderName);
|
||||
cy.get(commonSelectors.createFolderButton).click();
|
||||
|
|
@ -182,13 +180,12 @@ describe("User permissions", () => {
|
|||
|
||||
common.logout();
|
||||
cy.login(data.email, usersText.password);
|
||||
cy.contains("+ Create new").should("not.exist");
|
||||
|
||||
permissions.adminLogin();
|
||||
cy.contains("td", data.appName)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get("td a").contains("Delete").click();
|
||||
cy.get("td a").contains("Remove").click();
|
||||
});
|
||||
|
||||
common.logout();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ describe("Manage SSO for single workspace", () => {
|
|||
});
|
||||
it("Should verify General settings page elements", () => {
|
||||
common.navigateToManageSSO();
|
||||
cy.get(ssoSelector.pagetitle).verifyVisibleElement("have.text", "SSO");
|
||||
// cy.get(ssoSelector.pagetitle).verifyVisibleElement("have.text", "SSO");
|
||||
cy.get(ssoSelector.cardTitle).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.generalSettingsElements.generalSettings
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { buttonText } from "Texts/button";
|
|||
|
||||
import { verifyComponent, deleteComponentAndVerify } from "Support/utils/basicComponents";
|
||||
|
||||
describe("App Export Functionality", () => {
|
||||
describe("App Version Functionality", () => {
|
||||
var data = {};
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
let currentVersion = "";
|
||||
|
|
@ -73,12 +73,10 @@ describe("App Export Functionality", () => {
|
|||
deleteVersionAndVerify(currentVersion = "v5", deleteVersionText.deleteToastMessage(currentVersion = "v5"));
|
||||
|
||||
cy.reload();
|
||||
releasedVersionAndVerify(currentVersion = "v3")
|
||||
releasedVersionAndVerify(currentVersion = "v3");
|
||||
editVersionAndVerify(currentVersion = "v3", newVersion = ["v5"], releasedVersionText.cannotUpdateReleasedVersionToastMessage);
|
||||
closeModal(commonText.closeButton);
|
||||
|
||||
cy.reload();
|
||||
closeModal(commonText.closeButton);
|
||||
deleteVersionAndVerify(currentVersion = "v3", releasedVersionText.cannotDeleteReleasedVersionToastMessage)
|
||||
|
||||
navigateToCreateNewVersionModal(currentVersion = "v3");
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ describe("Multipage", () => {
|
|||
cy.get(multipageSelector.pageMenuIcon).should("be.visible");
|
||||
|
||||
cy.get(multipageSelector.pageMenuIcon).click();
|
||||
cy.wait(500);
|
||||
// cy.get(multipageSelector.pageEventHandler).click({force:true})
|
||||
cy.get(multipageSelector.pageEventHandler).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -133,6 +134,7 @@ describe("Multipage", () => {
|
|||
.verifyVisibleElement("have.text", "test_page")
|
||||
.click();
|
||||
cy.get(multipageSelector.pageMenuIcon).click();
|
||||
cy.wait(500);
|
||||
cy.get(multipageSelector.pageHandleText).verifyVisibleElement(
|
||||
"have.text",
|
||||
"test-page"
|
||||
|
|
@ -154,6 +156,7 @@ describe("Multipage", () => {
|
|||
|
||||
cy.get(multipageSelector.homePageLabel).click();
|
||||
cy.get(multipageSelector.pageMenuIcon).click();
|
||||
cy.wait(500);
|
||||
cy.get(multipageSelector.deletePageOptionButton).click();
|
||||
cy.get(".modal-title").verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -173,11 +176,13 @@ describe("Multipage", () => {
|
|||
cy.get('[data-cy="pages-name-test_page"]').should("be.visible");
|
||||
|
||||
cy.get(multipageSelector.pageMenuIcon).click();
|
||||
cy.wait(500);
|
||||
cy.get(multipageSelector.deletePageOptionButton).click();
|
||||
cy.get(multipageSelector.modalConfirmButton).click();
|
||||
cy.notVisible(multipageSelector.homePageLabel);
|
||||
|
||||
cy.get(multipageSelector.pageMenuIcon).click();
|
||||
cy.wait(500);
|
||||
cy.get(multipageSelector.eventHandlerOptionButton).click();
|
||||
cy.get(multipageSelector.modalTitlePageEvents).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -216,6 +221,7 @@ describe("Multipage", () => {
|
|||
|
||||
addNewPage("test");
|
||||
cy.get(multipageSelector.pageMenuIcon).click();
|
||||
cy.wait(500);
|
||||
cy.get(multipageSelector.pageHandleText).click();
|
||||
cy.get(multipageSelector.modalTitleEditPageHandle).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -249,21 +255,21 @@ describe("Multipage", () => {
|
|||
multipageText.samePagehandleToast
|
||||
);
|
||||
});
|
||||
it.only("should verify the basic bunctions of multipage", () => {
|
||||
it("should verify the basic functions of multipage", () => {
|
||||
cy.get(multipageSelector.sidebarPageButton).click();
|
||||
cy.get(multipageSelector.pagesPinIcon).click();
|
||||
addNewPage('pageOne');
|
||||
addNewPage('pageTwo')
|
||||
addNewPage('pageThree')
|
||||
addNewPage("pageOne");
|
||||
addNewPage("pageTwo");
|
||||
addNewPage("pageThree");
|
||||
|
||||
hideOrUnhidePage('pageOne')
|
||||
hideOrUnhidePage('pageTwo')
|
||||
hideOrUnhidePage('pageOne', 'unhide')
|
||||
addEventHandler('pageThree')
|
||||
hideOrUnhidePage("pageOne");
|
||||
hideOrUnhidePage("pageTwo");
|
||||
hideOrUnhidePage("pageOne", "unhide");
|
||||
addEventHandler("pageThree");
|
||||
cy.get(multipageSelector.closeModal).click();
|
||||
setHomePage('pageThree')
|
||||
modifyPageHandle('home', '1')
|
||||
cy.waitForAutoSave()
|
||||
setHomePage("pageThree");
|
||||
modifyPageHandle("home", "1");
|
||||
cy.waitForAutoSave();
|
||||
cy.openInCurrentTab(commonWidgetSelector.previewButton);
|
||||
|
||||
cy.get(multipageSelector.homePageLabel).click();
|
||||
|
|
@ -5,7 +5,7 @@ import { tableSelector } from "Selectors/table";
|
|||
import {
|
||||
verifyComponent,
|
||||
deleteComponentAndVerify,
|
||||
verifyComponentWithOutLabel
|
||||
verifyComponentWithOutLabel,
|
||||
} from "Support/utils/basicComponents";
|
||||
import {
|
||||
openAccordion,
|
||||
|
|
@ -33,29 +33,39 @@ import {
|
|||
describe("Basic components", () => {
|
||||
const data = {};
|
||||
beforeEach(() => {
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
data.appName = `${fake.companyName}-${fake.companyName}-App`;
|
||||
cy.appUILogin();
|
||||
cy.createApp();
|
||||
cy.modifyCanvasSize(900, 900);
|
||||
cy.get('[data-tooltip-id="tooltip-for-hide-query-editor"]').click();
|
||||
cy.renameApp(data.appName);
|
||||
cy.intercept("GET", "/api/comments/*").as("loadComments");
|
||||
});
|
||||
|
||||
it("Should verify Toggle switch", () => {
|
||||
cy.dragAndDropWidget("Toggle Switch", 50, 50);
|
||||
verifyComponent("toggleswitch1");
|
||||
|
||||
cy.resizeWidget("toggleswitch1", 850, 600);
|
||||
cy.resizeWidget("toggleswitch1", 650, 400);
|
||||
|
||||
openEditorSidebar("toggleswitch1");
|
||||
editAndVerifyWidgetName("toggleswitch2");
|
||||
|
||||
verifyAndModifyParameter(commonWidgetText.parameterLabel, "label");
|
||||
cy.forceClickOnCanvas();
|
||||
cy.waitForAutoSave();
|
||||
cy.get(
|
||||
'[data-cy="draggable-widget-toggleswitch2"] > .form-check-label'
|
||||
).should("have.text", "label");
|
||||
|
||||
cy.openInCurrentTab(commonWidgetSelector.previewButton);
|
||||
verifyComponent("toggleswitch2");
|
||||
cy.get(
|
||||
'[data-cy="draggable-widget-toggleswitch2"] > .form-check-label'
|
||||
).should("have.text", "label");
|
||||
|
||||
cy.go("back");
|
||||
cy.wait("@appVersion");
|
||||
deleteComponentAndVerify("toggleswitch2");
|
||||
cy.get(commonSelectors.editorPageLogo).click();
|
||||
|
||||
|
|
@ -64,11 +74,11 @@ describe("Basic components", () => {
|
|||
|
||||
it("Should verify Checkbox", () => {
|
||||
cy.dragAndDropWidget("Checkbox", 50, 50);
|
||||
cy.resizeWidget("checkbox1", 100, 200);
|
||||
// cy.resizeWidget("checkbox1", 50, 200);
|
||||
cy.forceClickOnCanvas();
|
||||
verifyComponent("checkbox1");
|
||||
|
||||
cy.resizeWidget("checkbox1", 850, 600);
|
||||
cy.resizeWidget("checkbox1", 650, 400);
|
||||
|
||||
openEditorSidebar("checkbox1");
|
||||
editAndVerifyWidgetName("checkbox2");
|
||||
|
|
@ -97,7 +107,7 @@ describe("Basic components", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
verifyComponent("radiobutton1");
|
||||
|
||||
cy.resizeWidget("radiobutton1", 850, 600);
|
||||
cy.resizeWidget("radiobutton1", 650, 400);
|
||||
|
||||
openEditorSidebar("radiobutton1");
|
||||
editAndVerifyWidgetName("radiobutton2");
|
||||
|
|
@ -125,7 +135,7 @@ describe("Basic components", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
verifyComponent("dropdown1");
|
||||
|
||||
cy.resizeWidget("dropdown1", 850, 600);
|
||||
cy.resizeWidget("dropdown1", 650, 400);
|
||||
|
||||
openEditorSidebar("dropdown1");
|
||||
editAndVerifyWidgetName("dropdown2");
|
||||
|
|
@ -148,14 +158,14 @@ describe("Basic components", () => {
|
|||
cy.deleteApp(data.appName);
|
||||
});
|
||||
//pending
|
||||
it("Should verify Rating", () => {
|
||||
cy.dragAndDropWidget("Rating", 300, 300);
|
||||
it.skip("Should verify Rating", () => {
|
||||
cy.dragAndDropWidget("Rating", 200, 200);
|
||||
cy.get('[data-cy="draggable-widget-starrating1"]').click({ force: true });
|
||||
// cy.resizeWidget("starrating1", 300, 500);
|
||||
cy.resizeWidget("starrating1", 200, 500);
|
||||
cy.forceClickOnCanvas();
|
||||
verifyComponent("starrating1");
|
||||
|
||||
cy.resizeWidget("starrating1", 850, 600);
|
||||
cy.resizeWidget("starrating1", 650, 400);
|
||||
|
||||
openEditorSidebar("starrating1");
|
||||
editAndVerifyWidgetName("starrating2");
|
||||
|
|
@ -183,7 +193,7 @@ describe("Basic components", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
verifyComponent("buttongroup1");
|
||||
|
||||
cy.resizeWidget("buttongroup1", 850, 600);
|
||||
cy.resizeWidget("buttongroup1", 650, 400);
|
||||
|
||||
openEditorSidebar("buttongroup1");
|
||||
editAndVerifyWidgetName("buttongroup2");
|
||||
|
|
@ -207,12 +217,11 @@ describe("Basic components", () => {
|
|||
|
||||
it("Should verify Calendar", () => {
|
||||
cy.dragAndDropWidget("Calendar", 50, 50);
|
||||
cy.get('[data-tip="Hide query editor"]').click();
|
||||
cy.get('[data-cy="draggable-widget-calendar1"]').click({ force: true });
|
||||
cy.forceClickOnCanvas();
|
||||
verifyComponent("calendar1");
|
||||
|
||||
cy.resizeWidget("calendar1", 850, 600);
|
||||
cy.resizeWidget("calendar1", 650, 400);
|
||||
|
||||
openEditorSidebar("calendar1");
|
||||
editAndVerifyWidgetName("calendar2");
|
||||
|
|
@ -234,7 +243,7 @@ describe("Basic components", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
verifyComponent("chart1");
|
||||
|
||||
cy.resizeWidget("chart1", 850, 600);
|
||||
cy.resizeWidget("chart1", 650, 400);
|
||||
|
||||
openEditorSidebar("chart1");
|
||||
editAndVerifyWidgetName("chart2", ["Chart data", "Properties"]);
|
||||
|
|
@ -262,7 +271,7 @@ describe("Basic components", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
verifyComponent("circularprogressbar1");
|
||||
|
||||
cy.resizeWidget("circularprogressbar1", 850, 600);
|
||||
cy.resizeWidget("circularprogressbar1", 650, 400);
|
||||
|
||||
openEditorSidebar("circularprogressbar1");
|
||||
editAndVerifyWidgetName("circularprogressbar2");
|
||||
|
|
@ -286,7 +295,7 @@ describe("Basic components", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
verifyComponent("codeeditor1");
|
||||
|
||||
cy.resizeWidget("codeeditor1", 850, 600);
|
||||
cy.resizeWidget("codeeditor1", 650, 400);
|
||||
|
||||
openEditorSidebar("codeeditor1");
|
||||
editAndVerifyWidgetName("codeeditor2");
|
||||
|
|
@ -309,7 +318,7 @@ describe("Basic components", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
verifyComponent("colorpicker1");
|
||||
|
||||
cy.resizeWidget("colorpicker1", 850, 600);
|
||||
cy.resizeWidget("colorpicker1", 650, 400);
|
||||
|
||||
openEditorSidebar("colorpicker1");
|
||||
editAndVerifyWidgetName("colorpicker2");
|
||||
|
|
@ -326,25 +335,30 @@ describe("Basic components", () => {
|
|||
|
||||
cy.deleteApp(data.appName);
|
||||
});
|
||||
//needed fix
|
||||
//needed fix
|
||||
it.skip("Should verify Custom Component", () => {
|
||||
cy.dragAndDropWidget("Custom Component", 50, 50);
|
||||
cy.get('[data-cy="draggable-widget-customcomponent1"]').click({ force: true });
|
||||
cy.get('[data-cy="draggable-widget-customcomponent1"]').click({
|
||||
force: true,
|
||||
});
|
||||
cy.forceClickOnCanvas();
|
||||
verifyComponent("customcomponent1");
|
||||
openEditorSidebar("customcomponent1");
|
||||
|
||||
// editAndVerifyWidgetName("customcomponent2", ["Code"]);
|
||||
closeAccordions(["Code"]);
|
||||
cy.get(commonWidgetSelector.WidgetNameInputField).type("{selectAll}{backspace}customcomponent2", {delay:30});
|
||||
cy.forceClickOnCanvas()
|
||||
|
||||
cy.get(commonWidgetSelector.WidgetNameInputField).type(
|
||||
"{selectAll}{backspace}customcomponent2",
|
||||
{ delay: 30 }
|
||||
);
|
||||
cy.forceClickOnCanvas();
|
||||
|
||||
cy.get(commonWidgetSelector.draggableWidget(name)).trigger("mouseover");
|
||||
cy.get(commonWidgetSelector.widgetConfigHandle(name))
|
||||
.click()
|
||||
.should("have.text", name);
|
||||
|
||||
cy.resizeWidget("customcomponent1", 850, 600);
|
||||
cy.resizeWidget("customcomponent1", 650, 400);
|
||||
|
||||
openEditorSidebar("customcomponent1");
|
||||
cy.forceClickOnCanvas();
|
||||
|
|
@ -365,7 +379,7 @@ describe("Basic components", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
verifyComponent("container1");
|
||||
|
||||
cy.resizeWidget("container1", 850, 600);
|
||||
cy.resizeWidget("container1", 650, 400);
|
||||
|
||||
openEditorSidebar("container1");
|
||||
editAndVerifyWidgetName("container2", ["Layout"]);
|
||||
|
|
@ -389,7 +403,7 @@ describe("Basic components", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
verifyComponent("daterangepicker1");
|
||||
|
||||
cy.resizeWidget("daterangepicker1", 850, 600);
|
||||
cy.resizeWidget("daterangepicker1", 650, 400);
|
||||
|
||||
openEditorSidebar("daterangepicker1");
|
||||
editAndVerifyWidgetName("daterangepicker2");
|
||||
|
|
@ -406,20 +420,30 @@ describe("Basic components", () => {
|
|||
|
||||
cy.deleteApp(data.appName);
|
||||
});
|
||||
//visible issue
|
||||
//visible issue
|
||||
it.skip("Should verify Divider", () => {
|
||||
verifyComponentWithOutLabel("Divider", "divider1", "divider2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"Divider",
|
||||
"divider1",
|
||||
"divider2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify File Picker", () => {
|
||||
verifyComponentWithOutLabel("File Picker", "filepicker1", "filepicker2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"File Picker",
|
||||
"filepicker1",
|
||||
"filepicker2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify Form", () => {
|
||||
cy.dragAndDropWidget("Form", 50, 50);
|
||||
verifyComponent("form1");
|
||||
|
||||
cy.resizeWidget("form1", 850, 600);
|
||||
cy.resizeWidget("form1", 650, 400);
|
||||
|
||||
openEditorSidebar("form1");
|
||||
editAndVerifyWidgetName("form2");
|
||||
|
|
@ -440,7 +464,7 @@ describe("Basic components", () => {
|
|||
cy.dragAndDropWidget("HTML Viewe", 50, 50, "HTML Viewer"); // search logic WIP
|
||||
verifyComponent("html1");
|
||||
|
||||
cy.resizeWidget("html1", 850, 600);
|
||||
cy.resizeWidget("html1", 650, 400);
|
||||
|
||||
openEditorSidebar("html1");
|
||||
editAndVerifyWidgetName("html2");
|
||||
|
|
@ -458,31 +482,32 @@ describe("Basic components", () => {
|
|||
});
|
||||
|
||||
it("Should verify Icon", () => {
|
||||
verifyComponentWithOutLabel("Icon", "icon1", "icon2", data.appName)
|
||||
verifyComponentWithOutLabel("Icon", "icon1", "icon2", data.appName);
|
||||
});
|
||||
|
||||
it("Should verify Iframe", () => {
|
||||
verifyComponentWithOutLabel("Iframe", "iframe1", "iframe2", data.appName)
|
||||
verifyComponentWithOutLabel("Iframe", "iframe1", "iframe2", data.appName);
|
||||
});
|
||||
|
||||
it("Should verify Kamban", () => {
|
||||
verifyComponentWithOutLabel("Kanban Board", "kanbanboard1", "kanbanboard2", data.appName) });
|
||||
it.skip("Should verify Kamban", () => {
|
||||
verifyComponentWithOutLabel("Kanban", "kanban1", "kanban2", data.appName);
|
||||
});
|
||||
|
||||
it("Should verify Link", () => {
|
||||
verifyComponentWithOutLabel("Link", "link1", "link2", data.appName)
|
||||
verifyComponentWithOutLabel("Link", "link1", "link2", data.appName);
|
||||
});
|
||||
|
||||
it("Should verify Map", () => {
|
||||
cy.dragAndDropWidget("Map", 50, 50);
|
||||
cy.get("body").then($body => {
|
||||
cy.get("body").then(($body) => {
|
||||
if ($body.find(".dismissButton").length > 0) {
|
||||
cy.get('.dismissButton').click();
|
||||
cy.get(".dismissButton").click();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
verifyComponent("map1");
|
||||
|
||||
cy.resizeWidget("map1", 850, 600);
|
||||
cy.resizeWidget("map1", 650, 400);
|
||||
|
||||
openEditorSidebar("map1");
|
||||
editAndVerifyWidgetName("map2");
|
||||
|
|
@ -500,15 +525,14 @@ describe("Basic components", () => {
|
|||
});
|
||||
|
||||
it("Should verify Modal", () => {
|
||||
verifyComponentWithOutLabel("Modal", "modal1", "modal2", data.appName)
|
||||
verifyComponentWithOutLabel("Modal", "modal1", "modal2", data.appName);
|
||||
});
|
||||
|
||||
it("Should verify PDF", () => {
|
||||
cy.dragAndDropWidget("PDF", 50, 50);
|
||||
cy.get('[data-tip="Hide query editor"]').click();
|
||||
verifyComponent("pdf1");
|
||||
|
||||
cy.resizeWidget("pdf1", 850, 600);
|
||||
cy.resizeWidget("pdf1", 650, 400);
|
||||
|
||||
openEditorSidebar("pdf1");
|
||||
editAndVerifyWidgetName("pdf2");
|
||||
|
|
@ -526,35 +550,70 @@ describe("Basic components", () => {
|
|||
});
|
||||
|
||||
it("Should verify Pagination", () => {
|
||||
verifyComponentWithOutLabel("Pagination", "pagination1", "pagination2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"Pagination",
|
||||
"pagination1",
|
||||
"pagination2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify QR Scanner", () => {
|
||||
verifyComponentWithOutLabel("QR Scanner", "qrscanner1", "qrscanner2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"QR Scanner",
|
||||
"qrscanner1",
|
||||
"qrscanner2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify Range Slider", () => {
|
||||
verifyComponentWithOutLabel("Range Slider", "rangeslider1", "rangeslider2", data.appName)
|
||||
it.skip("Should verify Range Slider", () => {
|
||||
verifyComponentWithOutLabel(
|
||||
"Range Slider",
|
||||
"rangeslider1",
|
||||
"rangeslider2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify Rich Text Editor", () => {
|
||||
verifyComponentWithOutLabel("Text Editor", "richtexteditor1", "richtexteditor2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"Text Editor",
|
||||
"richtexteditor1",
|
||||
"richtexteditor2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify Spinner", () => {
|
||||
verifyComponentWithOutLabel("Spinner", "spinner1", "spinner2", data.appName);
|
||||
verifyComponentWithOutLabel(
|
||||
"Spinner",
|
||||
"spinner1",
|
||||
"spinner2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify Statistics", () => {
|
||||
verifyComponentWithOutLabel("Statistics", "statistics1", "statistics2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"Statistics",
|
||||
"statistics1",
|
||||
"statistics2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify Steps", () => {
|
||||
verifyComponentWithOutLabel("Steps", "steps1", "steps2", data.appName)
|
||||
verifyComponentWithOutLabel("Steps", "steps1", "steps2", data.appName);
|
||||
});
|
||||
|
||||
it("Should verify SVG Image", () => {
|
||||
verifyComponentWithOutLabel("SVG Image", "svgimage1", "svgimage2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"SVG Image",
|
||||
"svgimage1",
|
||||
"svgimage2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify Tabs", () => {
|
||||
|
|
@ -562,7 +621,7 @@ describe("Basic components", () => {
|
|||
verifyComponent("tabs1");
|
||||
deleteComponentAndVerify("image1");
|
||||
|
||||
cy.resizeWidget("tabs1", 850, 600);
|
||||
cy.resizeWidget("tabs1", 650, 400);
|
||||
|
||||
openEditorSidebar("tabs1");
|
||||
editAndVerifyWidgetName("tabs2");
|
||||
|
|
@ -576,29 +635,49 @@ describe("Basic components", () => {
|
|||
deleteComponentAndVerify("tabs2");
|
||||
cy.get(commonSelectors.editorPageLogo).click();
|
||||
|
||||
cy.deleteApp(data.appName);
|
||||
cy.deleteApp(data.appName);
|
||||
});
|
||||
|
||||
it("Should verify Tags", () => {
|
||||
verifyComponentWithOutLabel("Tags", "tags1", "tags2", data.appName)
|
||||
verifyComponentWithOutLabel("Tags", "tags1", "tags2", data.appName);
|
||||
});
|
||||
|
||||
it("Should verify Textarea", () => {
|
||||
verifyComponentWithOutLabel("Textarea", "textarea1", "textarea2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"Textarea",
|
||||
"textarea1",
|
||||
"textarea2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify Timeline", () => {
|
||||
verifyComponentWithOutLabel("Timeline", "timeline1", "timeline2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"Timeline",
|
||||
"timeline1",
|
||||
"timeline2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
it("Should verify Timer", () => {
|
||||
verifyComponentWithOutLabel("Timer", "timer1", "timer2", data.appName)
|
||||
verifyComponentWithOutLabel("Timer", "timer1", "timer2", data.appName);
|
||||
});
|
||||
|
||||
it("Should verify Tree Select", () => {
|
||||
verifyComponentWithOutLabel("Tree Select", "treeselect1", "treeselect2", data.appName)
|
||||
verifyComponentWithOutLabel(
|
||||
"Tree Select",
|
||||
"treeselect1",
|
||||
"treeselect2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
|
||||
it("Should verify Vertical Divider", () => {
|
||||
verifyComponentWithOutLabel("Vertical Divider", "verticaldivider1", "verticaldivider2", data.appName)
|
||||
});
|
||||
verifyComponentWithOutLabel(
|
||||
"Vertical Divider",
|
||||
"verticaldivider1",
|
||||
"verticaldivider2",
|
||||
data.appName
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -292,6 +292,7 @@ describe("Date Picker widget", () => {
|
|||
|
||||
addTextWidgetToVerifyValue(`components.${data.widgetName}.value`);
|
||||
cy.dragAndDropWidget(commonWidgetText.toggleSwitch, 600, 160);
|
||||
cy.waitForAutoSave()
|
||||
|
||||
cy.openInCurrentTab(commonWidgetSelector.previewButton);
|
||||
|
||||
|
|
|
|||
|
|
@ -80,10 +80,13 @@ describe("List view widget", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
cy.waitForAutoSave();
|
||||
cy.reload();
|
||||
cy.wait(2500);
|
||||
|
||||
cy.get(
|
||||
`${commonWidgetSelector.draggableWidget(commonWidgetText.text1)}:eq(0)`
|
||||
).click();
|
||||
)
|
||||
.realHover()
|
||||
.realClick();
|
||||
verifyAndModifyParameter("Text", codeMirrorInputLabel("listItem.name"));
|
||||
cy.forceClickOnCanvas();
|
||||
cy.get(
|
||||
|
|
@ -123,10 +126,11 @@ describe("List view widget", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
cy.waitForAutoSave();
|
||||
cy.reload();
|
||||
cy.wait(2500);
|
||||
|
||||
cy.get(
|
||||
`${commonWidgetSelector.draggableWidget(data.widgetName)}:eq(0)`
|
||||
).click();
|
||||
cy.get(`${commonWidgetSelector.draggableWidget(data.widgetName)}:eq(0)`)
|
||||
.realHover()
|
||||
.click("topRight", { force: true });
|
||||
|
||||
verifyAndModifyParameter(
|
||||
listviewText.showBottomBorder,
|
||||
|
|
@ -165,6 +169,7 @@ describe("List view widget", () => {
|
|||
data.customMessage
|
||||
);
|
||||
|
||||
cy.forceClickOnCanvas();
|
||||
openEditorSidebar(data.widgetName);
|
||||
openAccordion(commonWidgetText.accordionLayout);
|
||||
verifyAndModifyToggleFx(
|
||||
|
|
@ -275,7 +280,7 @@ describe("List view widget", () => {
|
|||
deleteInnerWidget(data.widgetName, "button1");
|
||||
deleteInnerWidget(data.widgetName, "image1");
|
||||
|
||||
dropWidgetToListview("Text Input", 250, 50, data.widgetName);
|
||||
dropWidgetToListview("Text Input", 450, 20, data.widgetName);
|
||||
|
||||
cy.forceClickOnCanvas();
|
||||
openEditorSidebar(data.widgetName);
|
||||
|
|
@ -287,6 +292,7 @@ describe("List view widget", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
cy.waitForAutoSave();
|
||||
cy.reload();
|
||||
cy.wait(3500);
|
||||
|
||||
cy.get(
|
||||
`${commonWidgetSelector.draggableWidget(commonWidgetText.text1)}:eq(0)`
|
||||
|
|
@ -312,6 +318,7 @@ describe("List view widget", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
cy.waitForAutoSave();
|
||||
cy.reload();
|
||||
cy.wait(2500);
|
||||
|
||||
cy.get(
|
||||
`${commonWidgetSelector.draggableWidget(data.widgetName)}:eq(0)`
|
||||
|
|
@ -334,6 +341,7 @@ describe("List view widget", () => {
|
|||
cy.forceClickOnCanvas();
|
||||
cy.waitForAutoSave();
|
||||
cy.reload();
|
||||
cy.wait(2500);
|
||||
|
||||
openEditorSidebar(data.widgetName);
|
||||
openAccordion(commonWidgetText.accordionGenaral);
|
||||
|
|
@ -409,8 +417,7 @@ describe("List view widget", () => {
|
|||
|
||||
cy.get(`[data-cy=${data.widgetName.toLowerCase()}-row-1]`)
|
||||
.invoke("height")
|
||||
.should("be.gte", 98)
|
||||
.and("be.lte", 99);
|
||||
.should("equal", 99);
|
||||
cy.get(`[data-cy=${data.widgetName.toLowerCase()}-row-1]`)
|
||||
.invoke("attr", "class")
|
||||
.and("not.contain", "border-bottom");
|
||||
|
|
|
|||
423
cypress-tests/cypress/e2e/editor/widget/modalHappyPath.cy.js
Normal file
423
cypress-tests/cypress/e2e/editor/widget/modalHappyPath.cy.js
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
|
||||
import { buttonText } from "Texts/button";
|
||||
import { fake } from "Fixtures/fake";
|
||||
import { commonWidgetText } from "Texts/common";
|
||||
|
||||
import { verifyControlComponentAction } from "Support/utils/button";
|
||||
import { selectEvent } from "Support/utils/events";
|
||||
import {
|
||||
launchModal,
|
||||
closeModal,
|
||||
launchButton,
|
||||
verifySize,
|
||||
addAndVerifyColor,
|
||||
typeOnFx,
|
||||
} from "Support/utils/modal";
|
||||
|
||||
import {
|
||||
openAccordion,
|
||||
verifyAndModifyParameter,
|
||||
openEditorSidebar,
|
||||
verifyAndModifyToggleFx,
|
||||
addDefaultEventHandler,
|
||||
addAndVerifyTooltip,
|
||||
verifyComponentFromInspector,
|
||||
verifyAndModifyStylePickerFx,
|
||||
verifyWidgetColorCss,
|
||||
selectColourFromColourPicker,
|
||||
verifyLoaderColor,
|
||||
fillBoxShadowParams,
|
||||
verifyBoxShadowCss,
|
||||
verifyLayout,
|
||||
verifyTooltip,
|
||||
editAndVerifyWidgetName,
|
||||
verifyPropertiesGeneralAccordion,
|
||||
verifyStylesGeneralAccordion,
|
||||
} from "Support/utils/commonWidget";
|
||||
|
||||
describe("Modal", () => {
|
||||
beforeEach(() => {
|
||||
cy.appUILogin();
|
||||
cy.createApp();
|
||||
cy.dragAndDropWidget("Modal");
|
||||
});
|
||||
|
||||
it("should verify the properties of the modal component", () => {
|
||||
const data = {};
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
data.alertMessage = fake.randomSentence;
|
||||
data.widgetName = fake.widgetName;
|
||||
data.customTitle = fake.randomSentence;
|
||||
data.tooltipText = fake.randomSentence;
|
||||
data.buttonText = fake.companyName;
|
||||
|
||||
cy.renameApp(data.appName);
|
||||
launchModal("modal1");
|
||||
cy.get('[data-cy="modal-title"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"This title can be changed"
|
||||
);
|
||||
cy.get('[data-cy="modal-body"]').should("be.visible");
|
||||
cy.get('[data-cy="modal-close-button"]').click();
|
||||
cy.notVisible('[data-cy="modal-title"]');
|
||||
|
||||
openEditorSidebar("modal1", ["Options", "Properties", "Layout"]);
|
||||
editAndVerifyWidgetName(data.widgetName, [
|
||||
"Options",
|
||||
"Properties",
|
||||
"Layout",
|
||||
]);
|
||||
verifyComponentFromInspector(data.widgetName);
|
||||
|
||||
openAccordion(commonWidgetText.accordionProperties);
|
||||
verifyAndModifyParameter("Title", data.customTitle);
|
||||
launchModal(data.widgetName);
|
||||
cy.get('[data-cy="modal-title"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
data.customTitle
|
||||
);
|
||||
cy.get('[data-cy="modal-close-button"]').click();
|
||||
|
||||
verifyAndModifyToggleFx(
|
||||
buttonText.loadingState,
|
||||
commonWidgetText.codeMirrorLabelFalse
|
||||
);
|
||||
launchModal(data.widgetName);
|
||||
cy.get(".spinner-border").should("be.visible");
|
||||
|
||||
cy.get(
|
||||
commonWidgetSelector.parameterTogglebutton(buttonText.loadingState)
|
||||
).click();
|
||||
cy.notVisible(".spinner-border");
|
||||
|
||||
verifyAndModifyToggleFx(
|
||||
"Hide title bar",
|
||||
commonWidgetText.codeMirrorLabelFalse
|
||||
);
|
||||
cy.notVisible('[data-cy="modal-title"]');
|
||||
cy.get('[data-cy="hide-title-bar-toggle-button"]').click();
|
||||
cy.get('[data-cy="modal-title"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
data.customTitle
|
||||
);
|
||||
|
||||
cy.realPress("Escape");
|
||||
cy.notVisible('[data-cy="modal-title"]');
|
||||
|
||||
verifyAndModifyToggleFx(
|
||||
"Close on escape key",
|
||||
commonWidgetText.codeMirrorLabelTrue
|
||||
);
|
||||
launchModal(data.widgetName);
|
||||
|
||||
cy.realPress("Escape");
|
||||
cy.get('[data-cy="modal-title"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
data.customTitle
|
||||
);
|
||||
|
||||
closeModal(data.widgetName);
|
||||
launchModal(data.widgetName);
|
||||
|
||||
verifySize("Medium");
|
||||
verifySize("Large");
|
||||
verifySize("Small");
|
||||
|
||||
verifyAndModifyToggleFx(
|
||||
"Use default trigger button",
|
||||
commonWidgetText.codeMirrorLabelTrue
|
||||
);
|
||||
cy.get('[data-cy="modal-close-button"]').click();
|
||||
cy.notVisible(launchButton(data.widgetName));
|
||||
|
||||
cy.get('[data-cy="use-default-trigger-button-toggle-button"]').click();
|
||||
|
||||
cy.get(
|
||||
'[data-cy="trigger-button-label-input-field"]'
|
||||
).clearAndTypeOnCodeMirror(data.buttonText);
|
||||
cy.forceClickOnCanvas();
|
||||
cy.get(launchButton(data.widgetName))
|
||||
.verifyVisibleElement("have.text", data.buttonText)
|
||||
.click();
|
||||
|
||||
openAccordion(commonWidgetText.accordionEvents);
|
||||
selectEvent("On open", "Show Alert");
|
||||
cy.get('[data-cy="modal-close-button"]').click();
|
||||
launchModal(data.widgetName);
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, "Hello world!");
|
||||
cy.get('[data-cy="modal-close-button"]').click();
|
||||
|
||||
verifyLayout(data.widgetName);
|
||||
|
||||
cy.get(commonWidgetSelector.changeLayoutToDesktopButton).click();
|
||||
cy.get(
|
||||
commonWidgetSelector.parameterTogglebutton(
|
||||
commonWidgetText.parameterShowOnDesktop
|
||||
)
|
||||
).click();
|
||||
|
||||
cy.get(commonWidgetSelector.widgetDocumentationLink).should(
|
||||
"have.text",
|
||||
"Modal documentation"
|
||||
);
|
||||
|
||||
cy.get(commonSelectors.editorPageLogo).click();
|
||||
cy.deleteApp(data.appName);
|
||||
});
|
||||
|
||||
it("should verify the styles of the modal widget", () => {
|
||||
const data = {};
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
data.boxShadowColor = fake.randomRgba;
|
||||
data.colourHex = fake.randomRgbaHex;
|
||||
data.boxShadowParam = fake.boxShadowParam;
|
||||
data.backgroundColor = fake.randomRgba;
|
||||
|
||||
cy.renameApp(data.appName);
|
||||
launchModal("modal1");
|
||||
cy.get(commonWidgetSelector.buttonStylesEditorSideBar).click();
|
||||
|
||||
addAndVerifyColor(
|
||||
"Header background color",
|
||||
"#ffffffff",
|
||||
data.backgroundColor,
|
||||
"[data-cy='modal-header']"
|
||||
);
|
||||
|
||||
data.backgroundColor = fake.randomRgba;
|
||||
addAndVerifyColor(
|
||||
"Header title color",
|
||||
"#000000",
|
||||
data.backgroundColor,
|
||||
"[data-cy='modal-header']",
|
||||
"color"
|
||||
);
|
||||
|
||||
data.backgroundColor = fake.randomRgba;
|
||||
addAndVerifyColor(
|
||||
"Body background color",
|
||||
"#ffffffff",
|
||||
data.backgroundColor,
|
||||
"[data-cy='modal-body']"
|
||||
);
|
||||
|
||||
data.backgroundColor = fake.randomRgba;
|
||||
addAndVerifyColor(
|
||||
"Trigger button background color",
|
||||
"#4D72FA",
|
||||
data.backgroundColor,
|
||||
launchButton("modal1"),
|
||||
"background-color"
|
||||
);
|
||||
|
||||
data.backgroundColor = fake.randomRgba;
|
||||
addAndVerifyColor(
|
||||
"Trigger button text color",
|
||||
"#ffffffff",
|
||||
data.backgroundColor,
|
||||
launchButton("modal1"),
|
||||
"color"
|
||||
);
|
||||
cy.get("[data-cy='modal-header']").realClick();
|
||||
|
||||
verifyAndModifyToggleFx(
|
||||
commonWidgetText.parameterVisibility,
|
||||
commonWidgetText.codeMirrorLabelTrue
|
||||
);
|
||||
cy.get('[data-cy="modal-close-button"]').click();
|
||||
cy.get(commonWidgetSelector.draggableWidget("modal1")).should(
|
||||
"not.be.visible"
|
||||
);
|
||||
cy.get(commonWidgetSelector.parameterTogglebutton("Visibility")).click();
|
||||
|
||||
verifyAndModifyToggleFx(
|
||||
commonWidgetText.parameterDisable,
|
||||
commonWidgetText.codeMirrorLabelFalse
|
||||
);
|
||||
cy.waitForAutoSave();
|
||||
cy.get(launchButton("modal1")).should("have.attr", "disabled");
|
||||
|
||||
cy.get(commonWidgetSelector.parameterTogglebutton("Disable")).click();
|
||||
launchModal("modal1");
|
||||
cy.get('[data-cy="modal-title"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"This title can be changed"
|
||||
);
|
||||
|
||||
cy.get(commonSelectors.editorPageLogo).click();
|
||||
cy.deleteApp(data.appName);
|
||||
});
|
||||
|
||||
it("should verify the app preview", () => {
|
||||
const data = {};
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
data.bgColor = fake.randomRgba;
|
||||
data.titleColor = fake.randomRgba;
|
||||
data.bodyColor = fake.randomRgba;
|
||||
data.buttonColor = fake.randomRgba;
|
||||
data.buttonTextColor = fake.randomRgba;
|
||||
data.customTitle = fake.randomSentence;
|
||||
|
||||
cy.get(".close-svg > path").click();
|
||||
cy.dragAndDropWidget(commonWidgetText.toggleSwitch, 600, 50);
|
||||
cy.get(".close-svg > path").click();
|
||||
cy.dragAndDropWidget(commonWidgetText.toggleSwitch, 600, 100);
|
||||
cy.get(".close-svg > path").click();
|
||||
cy.dragAndDropWidget(commonWidgetText.toggleSwitch, 600, 150);
|
||||
cy.get(".close-svg > path").click();
|
||||
cy.dragAndDropWidget(commonWidgetText.toggleSwitch, 600, 200);
|
||||
cy.get(".close-svg > path").click();
|
||||
cy.dragAndDropWidget(commonWidgetText.toggleSwitch, 600, 250);
|
||||
cy.get(".close-svg > path").click();
|
||||
|
||||
cy.renameApp(data.appName);
|
||||
launchModal("modal1");
|
||||
verifyAndModifyParameter("Title", data.customTitle);
|
||||
cy.get(commonWidgetSelector.buttonStylesEditorSideBar).click();
|
||||
|
||||
addAndVerifyColor(
|
||||
"Header background color",
|
||||
"#ffffffff",
|
||||
data.bgColor,
|
||||
"[data-cy='modal-header']"
|
||||
);
|
||||
|
||||
addAndVerifyColor(
|
||||
"Header title color",
|
||||
"#000000",
|
||||
data.titleColor,
|
||||
"[data-cy='modal-header']",
|
||||
"color"
|
||||
);
|
||||
|
||||
addAndVerifyColor(
|
||||
"Body background color",
|
||||
"#ffffffff",
|
||||
data.bodyColor,
|
||||
"[data-cy='modal-body']"
|
||||
);
|
||||
|
||||
addAndVerifyColor(
|
||||
"Trigger button background color",
|
||||
"#4D72FA",
|
||||
data.buttonColor,
|
||||
launchButton("modal1"),
|
||||
"background-color"
|
||||
);
|
||||
|
||||
addAndVerifyColor(
|
||||
"Trigger button text color",
|
||||
"#ffffffff",
|
||||
data.buttonTextColor,
|
||||
launchButton("modal1"),
|
||||
"color"
|
||||
);
|
||||
|
||||
closeModal("modal1");
|
||||
launchModal("modal1");
|
||||
typeOnFx(
|
||||
commonWidgetText.parameterVisibility,
|
||||
"{{components.toggleswitch1.value"
|
||||
);
|
||||
cy.get("[data-cy='modal-header']").realClick();
|
||||
cy.get(commonWidgetSelector.buttonStylesEditorSideBar).click();
|
||||
|
||||
typeOnFx(
|
||||
commonWidgetText.parameterDisable,
|
||||
"{{components.toggleswitch2.value"
|
||||
);
|
||||
cy.get('[data-cy="sidebar-option-properties"]').click();
|
||||
|
||||
typeOnFx("Loading State", "{{components.toggleswitch3.value");
|
||||
cy.get("[data-cy='modal-header']").realClick();
|
||||
|
||||
typeOnFx("Hide title bar", "{{components.toggleswitch4.value");
|
||||
cy.get("[data-cy='modal-header']").realClick();
|
||||
|
||||
typeOnFx("Hide close button", "{{components.toggleswitch5.value");
|
||||
cy.get("[data-cy='modal-header']").realClick();
|
||||
cy.waitForAutoSave();
|
||||
cy.openInCurrentTab(commonWidgetSelector.previewButton);
|
||||
cy.wait(2000);
|
||||
|
||||
cy.notVisible(launchButton("modal1"));
|
||||
cy.get(commonWidgetSelector.draggableWidget("toggleswitch1"))
|
||||
.find(".form-check-input")
|
||||
.click();
|
||||
cy.get(launchButton("modal1")).should("be.visible");
|
||||
|
||||
cy.get(commonWidgetSelector.draggableWidget("toggleswitch2"))
|
||||
.find(".form-check-input")
|
||||
.click();
|
||||
cy.get(launchButton("modal1")).should("have.attr", "disabled");
|
||||
cy.get(commonWidgetSelector.draggableWidget("toggleswitch2"))
|
||||
.find(".form-check-input")
|
||||
.click();
|
||||
cy.get(commonWidgetSelector.draggableWidget("toggleswitch3"))
|
||||
.find(".form-check-input")
|
||||
.click();
|
||||
launchModal("modal1");
|
||||
cy.get(".spinner-border").should("be.visible");
|
||||
cy.realPress("Escape");
|
||||
|
||||
cy.get(commonWidgetSelector.draggableWidget("toggleswitch3"))
|
||||
.find(".form-check-input")
|
||||
.click();
|
||||
|
||||
cy.get(commonWidgetSelector.draggableWidget("toggleswitch4"))
|
||||
.find(".form-check-input")
|
||||
.click();
|
||||
launchModal("modal1");
|
||||
cy.notVisible('[data-cy="modal-title"]');
|
||||
cy.realPress("Escape");
|
||||
|
||||
cy.get(commonWidgetSelector.draggableWidget("toggleswitch4"))
|
||||
.find(".form-check-input")
|
||||
.click();
|
||||
launchModal("modal1");
|
||||
verifyWidgetColorCss(
|
||||
"[data-cy='modal-header']",
|
||||
"background-color",
|
||||
data.bgColor,
|
||||
true
|
||||
);
|
||||
verifyWidgetColorCss(
|
||||
"[data-cy='modal-header']",
|
||||
"color",
|
||||
data.titleColor,
|
||||
true
|
||||
);
|
||||
verifyWidgetColorCss(
|
||||
"[data-cy='modal-body']",
|
||||
"background-color",
|
||||
data.bodyColor,
|
||||
true
|
||||
);
|
||||
|
||||
cy.realPress("Escape");
|
||||
verifyWidgetColorCss(
|
||||
launchButton("modal1"),
|
||||
"color",
|
||||
data.buttonTextColor,
|
||||
true
|
||||
);
|
||||
verifyWidgetColorCss(
|
||||
launchButton("modal1"),
|
||||
"background-color",
|
||||
data.buttonColor,
|
||||
true
|
||||
);
|
||||
launchModal("modal1");
|
||||
|
||||
cy.get('[data-cy="modal-title"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
data.customTitle
|
||||
);
|
||||
cy.realPress("Escape");
|
||||
cy.get(commonWidgetSelector.draggableWidget("toggleswitch5"))
|
||||
.find(".form-check-input")
|
||||
.click();
|
||||
launchModal("modal1");
|
||||
cy.notVisible('[data-cy="modal-close-button"]');
|
||||
});
|
||||
});
|
||||
|
|
@ -123,8 +123,7 @@ describe("Multiselect widget", () => {
|
|||
cy.get(multiselectSelector.dropdownAllItems)
|
||||
.first()
|
||||
.should("have.text", multiselectText.dropdwonOptionSelectAll)
|
||||
.click()
|
||||
.click();
|
||||
.realClick();
|
||||
|
||||
verifyMultiselectHeader(
|
||||
data.widgetName,
|
||||
|
|
|
|||
|
|
@ -239,10 +239,7 @@ describe("Number Input", () => {
|
|||
commonWidgetText.parameterBorderRadius,
|
||||
commonWidgetText.borderRadiusInput
|
||||
);
|
||||
|
||||
cy.forceClickOnCanvas();
|
||||
cy.waitForAutoSave();
|
||||
cy.reload();
|
||||
|
||||
openEditorSidebar(numberInputText.defaultWidgetName);
|
||||
cy.get(commonWidgetSelector.buttonStylesEditorSideBar).click();
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ describe("Table", () => {
|
|||
);
|
||||
cy.get(tableSelector.buttonCloseFilters).should("be.visible");
|
||||
|
||||
cy.get(tableSelector.buttonAddFilter).dblclick();
|
||||
cy.get(tableSelector.buttonAddFilter).realClick().realClick();
|
||||
|
||||
cy.get(tableSelector.labelColumn).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -211,7 +211,8 @@ describe("Table", () => {
|
|||
codeMirrorInputLabel(`[{id:1,name:"Mike",email:"mike@example.com" },{id:2,name:"Nina",email:"nina@example.com" },{id:3,name:"Steph",email:"steph@example.com" },{id:4,name:"Oliver",email:"oliver@example.com" },
|
||||
]`)
|
||||
);
|
||||
cy.get('[data-cy="inspector-close-icon"]').click();
|
||||
// cy.get('[data-cy="inspector-close-icon"]').click();
|
||||
cy.forceClickOnCanvas();
|
||||
cy.waitForAutoSave();
|
||||
verifyTableElements([
|
||||
{ id: 1, name: "Mike", email: "mike@example.com" },
|
||||
|
|
@ -271,10 +272,9 @@ describe("Table", () => {
|
|||
cy.get('[data-cy="rightActions-cell-2"]')
|
||||
.eq(0)
|
||||
.should("have.text", "FakeName1");
|
||||
selectDropdownOption(
|
||||
`[data-cy="dropdown-action-button-position"] > .select-search`,
|
||||
0
|
||||
);
|
||||
cy.get(`[data-cy="dropdown-action-button-position"]>>:eq(0)`).click();
|
||||
cy.get('[data-index="0"] > .select-search-option').click();
|
||||
|
||||
cy.get('[data-cy="leftActions-cell-0"]')
|
||||
.eq(0)
|
||||
.should("have.text", "FakeName1");
|
||||
|
|
@ -345,25 +345,30 @@ describe("Table", () => {
|
|||
deleteAndVerifyColumn("name");
|
||||
deleteAndVerifyColumn("email");
|
||||
addAndOpenColumnOption("Fake-String", `string`);
|
||||
selectDropdownOption('[data-cy="input-overflow"] > .select-search', `wrap`);
|
||||
selectDropdownOption('[data-cy="input-overflow"] >>:eq(0)', `wrap`);
|
||||
cy.get('[data-index="0"]>.select-search-option:eq(1)').realClick();
|
||||
cy.wait(2000);
|
||||
verifyAndEnterColumnOptionInput("key", "name");
|
||||
verifyAndEnterColumnOptionInput("Text color", "red");
|
||||
verifyAndEnterColumnOptionInput(
|
||||
"Cell Background Color",
|
||||
"{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}yellow"
|
||||
"{backspace}{backspace}{backspace}{backspace}{backspace}yellow"
|
||||
);
|
||||
cy.get(
|
||||
'[data-cy="input-and-label-cell-background-color"] > .form-label'
|
||||
).click();
|
||||
cy.wait(500);
|
||||
|
||||
cy.get(tableSelector.column(0))
|
||||
.eq(0)
|
||||
.should("have.css", "background-color", "rgb(255, 255, 0)")
|
||||
.find("span")
|
||||
.should("have.css", "color", "rgb(255, 0, 0)")
|
||||
.should("have.css", "background-color", "rgb(255, 255, 0)", {
|
||||
timeout: 10000,
|
||||
})
|
||||
.last()
|
||||
.should("have.css", "color", "rgb(62, 82, 91)")
|
||||
.and("have.text", "Sarah");
|
||||
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
cy.get('[data-cy="header-validation"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Validation"
|
||||
|
|
@ -383,7 +388,7 @@ describe("Table", () => {
|
|||
addAndOpenColumnOption("fake-number", `number`);
|
||||
verifyAndEnterColumnOptionInput("key", "id");
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "black");
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
cy.get('[data-cy="header-validation"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"Validation"
|
||||
|
|
@ -391,16 +396,17 @@ describe("Table", () => {
|
|||
|
||||
verifyAndEnterColumnOptionInput("Min value", "2");
|
||||
verifyAndEnterColumnOptionInput("Max value", "3");
|
||||
addInputOnTable(0, 0, "2");
|
||||
addInputOnTable(0, 0, "0");
|
||||
verifyInvalidFeedback(0, 0, "Minimum value is 2");
|
||||
verifyInvalidFeedback(0, 3, "Maximum value is 3");
|
||||
openEditorSidebar(data.widgetName);
|
||||
deleteAndVerifyColumn("fake-number");
|
||||
|
||||
openEditorSidebar(data.widgetName);
|
||||
addAndOpenColumnOption("fake-text", `text`);
|
||||
verifyAndEnterColumnOptionInput("key", "email");
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "");
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
verifySingleValueOnTable(0, 0, "sarah@example.com");
|
||||
addInputOnTable(0, 0, "mike@example.com", "textarea");
|
||||
openEditorSidebar(data.widgetName);
|
||||
|
|
@ -413,7 +419,7 @@ describe("Table", () => {
|
|||
verifyAndEnterColumnOptionInput("Labels", '{{["One","Two","Three"]');
|
||||
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "fakeString");
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
selectDropdownOption(`${tableSelector.column(0)}:eq(0) .badge`, 1);
|
||||
cy.get(`${tableSelector.column(0)}:eq(0) .badge`).should(
|
||||
"have.text",
|
||||
|
|
@ -428,7 +434,7 @@ describe("Table", () => {
|
|||
verifyAndEnterColumnOptionInput("Values", "{{[1,2,3]");
|
||||
verifyAndEnterColumnOptionInput("Labels", '{{["One","Two","Three"]');
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "fakeString");
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
selectDropdownOption(`${tableSelector.column(0)}:eq(0) .badge`, 1); // WIP (workaround needed)
|
||||
cy.get(`${tableSelector.column(0)}:eq(1) .badge`).should(
|
||||
"have.text",
|
||||
|
|
@ -437,9 +443,9 @@ describe("Table", () => {
|
|||
selectDropdownOption(`${tableSelector.column(0)}:eq(0) .badge`, 0);
|
||||
cy.get(`${tableSelector.column(0)}:eq(0) .badge`).should(
|
||||
"have.text",
|
||||
"One"
|
||||
"TwoOne"
|
||||
);
|
||||
// selectDropdownOption(`${tableSelector.column(0)}:eq(1) .badge:eq(1)`, 1);
|
||||
selectDropdownOption(`${tableSelector.column(0)}:eq(1) .badge`, 1);
|
||||
cy.get(`${tableSelector.column(0)}:eq(0) .badge`).should(
|
||||
"have.text",
|
||||
"One"
|
||||
|
|
@ -458,7 +464,7 @@ describe("Table", () => {
|
|||
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "fakeString");
|
||||
//WIP Not editble verify
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
cy.forceClickOnCanvas();
|
||||
|
||||
cy.get(`${tableSelector.column(0)}:eq(0) .badge`)
|
||||
|
|
@ -493,7 +499,7 @@ describe("Table", () => {
|
|||
verifyAndEnterColumnOptionInput("Labels", '{{["One","Two","Three"]');
|
||||
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "fakeString");
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
verifyAndEnterColumnOptionInput("Custom rule", "fakeString");
|
||||
|
||||
deleteAndVerifyColumn("fake-dropdown");
|
||||
|
|
@ -507,7 +513,7 @@ describe("Table", () => {
|
|||
verifyAndEnterColumnOptionInput("Labels", '{{["One","Two","Three"]');
|
||||
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "fakeString");
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
// //verifyRadio
|
||||
deleteAndVerifyColumn("fake-radio");
|
||||
|
||||
|
|
@ -519,7 +525,7 @@ describe("Table", () => {
|
|||
verifyAndEnterColumnOptionInput("Labels", '{{["One","Two","Three"]');
|
||||
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "fakeString");
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
// //verify multiselect
|
||||
deleteAndVerifyColumn("fake-multiselect");
|
||||
|
||||
|
|
@ -529,7 +535,7 @@ describe("Table", () => {
|
|||
verifyAndEnterColumnOptionInput("key", "fakeString");
|
||||
// verifyAndEnterColumnOptionInput("Active color", "green"); //use color Picker
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "fakeString");
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
deleteAndVerifyColumn("fake-toggleSwitch");
|
||||
|
||||
// //Toggle Switch
|
||||
|
|
@ -539,7 +545,7 @@ describe("Table", () => {
|
|||
verifyAndEnterColumnOptionInput("key", "fakeString");
|
||||
// verifyAndEnterColumnOptionInput("Date Display format", "fakeString");
|
||||
// verifyAndEnterColumnOptionInput("Cell Background Color", "blue");
|
||||
cy.get('[data-cy="toggle-make-editable"]').click();
|
||||
cy.get('[data-cy="make-editable-toggle-button"]').click();
|
||||
|
||||
// // verifyAndEnterColumnOptionInput("Date Parse Format", "fakeString");
|
||||
|
||||
|
|
@ -643,6 +649,9 @@ describe("Table", () => {
|
|||
data.color,
|
||||
data.boxShadowParam
|
||||
);
|
||||
cy.get(
|
||||
commonWidgetSelector.draggableWidget(tableText.defaultWidgetName)
|
||||
).click();
|
||||
cy.get(commonWidgetSelector.buttonStylesEditorSideBar).click();
|
||||
|
||||
cy.get('[data-cy="label-table-type"]').verifyVisibleElement(
|
||||
|
|
@ -660,6 +669,9 @@ describe("Table", () => {
|
|||
.find("table")
|
||||
.invoke("attr", "class")
|
||||
.and("contain", "randomText");
|
||||
cy.get(
|
||||
commonWidgetSelector.draggableWidget(tableText.defaultWidgetName)
|
||||
).click();
|
||||
cy.get(commonWidgetSelector.buttonStylesEditorSideBar).click();
|
||||
|
||||
cy.get('[data-cy="table-type-fx-button"]').click();
|
||||
|
|
@ -667,6 +679,7 @@ describe("Table", () => {
|
|||
selectFromSidebarDropdown('[data-cy="dropdown-table-type"]', "Classic");
|
||||
cy.forceClickOnCanvas();
|
||||
cy.get(commonWidgetSelector.draggableWidget(tableText.defaultWidgetName))
|
||||
.click()
|
||||
.find("table")
|
||||
.invoke("attr", "class")
|
||||
.and("contain", "classic");
|
||||
|
|
@ -678,6 +691,7 @@ describe("Table", () => {
|
|||
);
|
||||
cy.forceClickOnCanvas();
|
||||
cy.get(commonWidgetSelector.draggableWidget(tableText.defaultWidgetName))
|
||||
.click()
|
||||
.find("table")
|
||||
.invoke("attr", "class")
|
||||
.and("contain", "table-striped table-bordered ");
|
||||
|
|
@ -695,6 +709,9 @@ describe("Table", () => {
|
|||
`randomText`
|
||||
);
|
||||
cy.forceClickOnCanvas();
|
||||
cy.get(
|
||||
commonWidgetSelector.draggableWidget(tableText.defaultWidgetName)
|
||||
).click();
|
||||
cy.get(tableSelector.column(0))
|
||||
.eq(0)
|
||||
.invoke("attr", "class")
|
||||
|
|
@ -705,6 +722,9 @@ describe("Table", () => {
|
|||
cy.get('[data-cy="cell-size-fx-button"]').click();
|
||||
selectFromSidebarDropdown('[data-cy="dropdown-cell-size"]', "Spacious");
|
||||
cy.forceClickOnCanvas();
|
||||
cy.get(
|
||||
commonWidgetSelector.draggableWidget(tableText.defaultWidgetName)
|
||||
).click();
|
||||
|
||||
cy.get(tableSelector.column(0))
|
||||
.eq(0)
|
||||
|
|
@ -718,7 +738,9 @@ describe("Table", () => {
|
|||
);
|
||||
|
||||
selectColourFromColourPicker(`Text color`, data.color);
|
||||
cy.forceClickOnCanvas();
|
||||
cy.get(commonWidgetSelector.draggableWidget(tableText.defaultWidgetName))
|
||||
.click()
|
||||
.find("tbody")
|
||||
.should(
|
||||
"have.css",
|
||||
|
|
@ -759,10 +781,10 @@ describe("Table", () => {
|
|||
verifyAndModifyToggleFx("Server-side sort", "{{false}}", true);
|
||||
|
||||
verifyAndModifyToggleFx("Show download button", "{{true}}", true);
|
||||
cy.notVisible('[data-tip="Download"]');
|
||||
cy.notVisible('[data-tooltip-id="tooltip-for-download"]');
|
||||
|
||||
verifyAndModifyToggleFx("Show filter button", "{{true}}", true);
|
||||
cy.notVisible('[data-tip="Filter data"]');
|
||||
cy.notVisible('[data-tooltip-id="tooltip-for-filter-data"]');
|
||||
|
||||
cy.get('[data-cy="show-filter-button-toggle-button"]').click();
|
||||
verifyAndModifyToggleFx("Server-side filter", "{{false}}", true);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,10 @@ describe("App Export Functionality", () => {
|
|||
cy.get(appVersionSelectors.appVersionMenuField)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
createNewVersion((otherVersions = ["v2"]));
|
||||
createNewVersion(otherVersions = ["v2"], currentVersion = "v1");
|
||||
cy.wait(500);
|
||||
cy.dragAndDropWidget("Toggle Switch", 50, 50);
|
||||
cy.waitForAutoSave();
|
||||
cy.get(appVersionSelectors.currentVersionField((otherVersions = "v2")))
|
||||
.should("be.visible")
|
||||
.invoke("text")
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ describe("App Import Functionality", () => {
|
|||
force: true,
|
||||
});
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.oldToastMessage,
|
||||
commonSelectors.toastMessage,
|
||||
importText.couldNotImportAppToastMessage
|
||||
);
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ describe("App Import Functionality", () => {
|
|||
});
|
||||
cy.get(".driver-close-btn").click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.oldToastMessage,
|
||||
commonSelectors.toastMessage,
|
||||
importText.appImportedToastMessage
|
||||
);
|
||||
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
|
||||
|
|
@ -104,7 +104,7 @@ describe("App Import Functionality", () => {
|
|||
force: true,
|
||||
});
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.oldToastMessage,
|
||||
commonSelectors.toastMessage,
|
||||
importText.appImportedToastMessage
|
||||
);
|
||||
cy.get(
|
||||
|
|
@ -132,10 +132,11 @@ describe("App Import Functionality", () => {
|
|||
cy.reload();
|
||||
navigateToAppEditor(data.appReName);
|
||||
|
||||
cy.wait(500);
|
||||
cy.get(appVersionSelectors.appVersionMenuField)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
createNewVersion((otherVersions = ["v2"]));
|
||||
createNewVersion(otherVersions = ["v2"], currentVersion = "v1");
|
||||
cy.get(appVersionSelectors.currentVersionField((otherVersions = "v2")))
|
||||
.should("be.visible")
|
||||
.click()
|
||||
|
|
@ -174,7 +175,7 @@ describe("App Import Functionality", () => {
|
|||
}
|
||||
);
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.oldToastMessage,
|
||||
commonSelectors.toastMessage,
|
||||
importText.appImportedToastMessage
|
||||
);
|
||||
cy.get(appVersionSelectors.appVersionMenuField).click();
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ describe("Self host onboarding", () => {
|
|||
.and("have.attr", "href")
|
||||
.and("equal", "https://www.tooljet.com/privacy");
|
||||
|
||||
cy.clearAndType(commonSelectors.nameInputField, "The developer");
|
||||
cy.clearAndType(commonSelectors.nameInputField, "The Developer");
|
||||
cy.clearAndType(commonSelectors.emailInputField, "dev@tooljet.io");
|
||||
cy.clearAndType(commonSelectors.passwordInputField, "password");
|
||||
cy.get(commonSelectors.continueButton).click();
|
||||
|
|
|
|||
|
|
@ -82,16 +82,18 @@ Cypress.Commands.add("appLogin", () => {
|
|||
});
|
||||
|
||||
Cypress.Commands.add("waitForAutoSave", () => {
|
||||
cy.get(commonSelectors.autoSave, { timeout: 10000 }).should(
|
||||
cy.wait(200);
|
||||
cy.get(commonSelectors.autoSave, { timeout: 20000 }).should(
|
||||
"have.text",
|
||||
commonText.autoSave
|
||||
commonText.autoSave,
|
||||
{ timeout: 20000 }
|
||||
);
|
||||
});
|
||||
|
||||
Cypress.Commands.add("createApp", (appName) => {
|
||||
cy.get("body").then(($title) => {
|
||||
if ($title.text().includes(commonText.introductionMessage)) {
|
||||
cy.get(commonSelectors.emptyAppCreateButton).click();
|
||||
cy.get(commonSelectors.emptyAppCreateButton).eq(0).click();
|
||||
} else {
|
||||
cy.get(commonSelectors.appCreateButton).click();
|
||||
}
|
||||
|
|
@ -170,7 +172,9 @@ Cypress.Commands.add(
|
|||
Cypress.Commands.add("deleteApp", (appName) => {
|
||||
cy.intercept("DELETE", "/api/apps/*").as("appDeleted");
|
||||
cy.get(commonSelectors.appCard(appName))
|
||||
.realHover()
|
||||
.find(commonSelectors.appCardOptionsButton)
|
||||
.realHover()
|
||||
.click();
|
||||
cy.get(commonSelectors.deleteAppOption).click();
|
||||
cy.get(commonSelectors.buttonSelector(commonText.modalYesButton)).click();
|
||||
|
|
@ -203,7 +207,10 @@ Cypress.Commands.add("modifyCanvasSize", (x, y) => {
|
|||
});
|
||||
|
||||
Cypress.Commands.add("renameApp", (appName) => {
|
||||
cy.clearAndType(commonSelectors.appNameInput, appName);
|
||||
cy.get(commonSelectors.appNameInput).type(
|
||||
`{selectAll}{backspace}${appName}`,
|
||||
{ force: true }
|
||||
);
|
||||
cy.waitForAutoSave();
|
||||
});
|
||||
|
||||
|
|
@ -236,6 +243,11 @@ Cypress.Commands.add("notVisible", (dataCy) => {
|
|||
cy.get(dataCy).should("not.be.visible");
|
||||
}
|
||||
});
|
||||
const log = Cypress.log({
|
||||
name: "notVisible",
|
||||
displayName: "Not Visible",
|
||||
message: dataCy,
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add("resizeWidget", (widgetName, x, y) => {
|
||||
|
|
|
|||
|
|
@ -11,17 +11,30 @@ export const verifyComponent = (widgetName) => {
|
|||
};
|
||||
|
||||
export const deleteComponentAndVerify = (widgetName) => {
|
||||
cy.get(commonWidgetSelector.draggableWidget(widgetName)).click();
|
||||
cy.get(`[data-cy="${widgetName}-delete-button"]`).last().click();
|
||||
cy.get(commonWidgetSelector.draggableWidget(widgetName)).click().realHover();
|
||||
|
||||
cy.get(commonWidgetSelector.draggableWidget(widgetName)).realHover();
|
||||
|
||||
cy.get(`[data-cy="${widgetName}-delete-button"]`).last().realClick();
|
||||
cy.verifyToastMessage(
|
||||
`[class=go3958317564]`,
|
||||
"Component deleted! (ctrl + Z to undo)"
|
||||
);
|
||||
cy.notVisible(commonWidgetSelector.draggableWidget(widgetName));
|
||||
};
|
||||
|
||||
export const verifyComponentWithOutLabel=(component, defaultName, fakeName, appName, properties=[] )=>{
|
||||
export const verifyComponentWithOutLabel = (
|
||||
component,
|
||||
defaultName,
|
||||
fakeName,
|
||||
appName,
|
||||
properties = []
|
||||
) => {
|
||||
cy.dragAndDropWidget(component, 50, 50);
|
||||
cy.get(`[data-cy="draggable-widget-${defaultName}"]`).click({ force: true });
|
||||
verifyComponent(defaultName);
|
||||
|
||||
cy.resizeWidget(defaultName, 850, 600);
|
||||
cy.resizeWidget(defaultName, 650, 400);
|
||||
|
||||
openEditorSidebar(defaultName);
|
||||
editAndVerifyWidgetName(fakeName, properties);
|
||||
|
|
@ -37,9 +50,4 @@ export const verifyComponentWithOutLabel=(component, defaultName, fakeName, appN
|
|||
cy.get(commonSelectors.editorPageLogo).click();
|
||||
|
||||
cy.deleteApp(appName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -78,21 +78,23 @@ export const navigateToAppEditor = (appName) => {
|
|||
.trigger("mousehover")
|
||||
.trigger("mouseenter")
|
||||
.find(commonSelectors.editButton)
|
||||
.click();
|
||||
.click({force:true});
|
||||
//cy.wait("@appEditor");
|
||||
};
|
||||
|
||||
export const viewAppCardOptions = (appName) => {
|
||||
cy.get(commonSelectors.appCard(appName))
|
||||
.find(commonSelectors.appCardOptionsButton)
|
||||
.click();
|
||||
cy.contains("div", appName)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get(commonSelectors.appCardOptionsButton).invoke("click");
|
||||
});
|
||||
};
|
||||
|
||||
export const viewFolderCardOptions = (folderName) => {
|
||||
cy.contains("div", folderName)
|
||||
cy.get(commonSelectors.folderListcard(folderName))
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get(commonSelectors.folderCardOptions).invoke("click");
|
||||
cy.get('[data-cy="folder-card-menu-icon"]').invoke('click');
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -152,8 +154,7 @@ export const manageUsersPagination = (email) => {
|
|||
};
|
||||
|
||||
export const searchUser = (email) => {
|
||||
cy.clearAndType(commonSelectors.emailFilterInput, email);
|
||||
cy.get(commonSelectors.filterButton).click();
|
||||
cy.clearAndType(commonSelectors.inputUserSearch, email);
|
||||
};
|
||||
|
||||
export const createWorkspace = (workspaceName) => {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ export const addDefaultEventHandler = (message) => {
|
|||
cy.get(commonWidgetSelector.eventHandlerCard).click();
|
||||
cy.get(commonWidgetSelector.alertMessageInputField)
|
||||
.find('[data-cy*="-input-field"]')
|
||||
.eq(0)
|
||||
.clearAndTypeOnCodeMirror(message);
|
||||
};
|
||||
|
||||
|
|
@ -240,9 +241,16 @@ export const verifyAndModifyStylePickerFx = (
|
|||
});
|
||||
};
|
||||
|
||||
export const verifyWidgetColorCss = (widgetName, cssProperty, color) => {
|
||||
export const verifyWidgetColorCss = (
|
||||
widgetName,
|
||||
cssProperty,
|
||||
color,
|
||||
innerProp = false
|
||||
) => {
|
||||
cy.forceClickOnCanvas();
|
||||
cy.get(commonWidgetSelector.draggableWidget(widgetName)).should(
|
||||
cy.get(
|
||||
innerProp ? widgetName : commonWidgetSelector.draggableWidget(widgetName)
|
||||
).should(
|
||||
"have.css",
|
||||
cssProperty,
|
||||
`rgba(${color[0]}, ${color[1]}, ${color[2]}, ${color[3] / 100})`
|
||||
|
|
|
|||
|
|
@ -32,25 +32,22 @@ export const modifyAndVerifyAppCardIcon = (appName) => {
|
|||
);
|
||||
}
|
||||
closeModal(commonText.closeButton);
|
||||
// cy.get(dashboardSelector.appCardDefaultIcon).should("exist");
|
||||
|
||||
viewAppCardOptions(appName);
|
||||
cy.get(commonSelectors.appCardOptions(commonText.changeIconOption)).click();
|
||||
cy.get(dashboardSelector.appIcon(randomIcon)).click();
|
||||
cy.get(dashboardSelector.appIcon(randomIcon)).first().click();
|
||||
cancelModal(commonText.cancelButton);
|
||||
|
||||
// cy.get(dashboardSelector.appCardDefaultIcon).should("exist");
|
||||
|
||||
viewAppCardOptions(appName);
|
||||
cy.get(commonSelectors.appCardOptions(commonText.changeIconOption)).click();
|
||||
|
||||
cy.get(dashboardSelector.appIcon(randomIcon)).click();
|
||||
cy.get(dashboardSelector.appIcon(randomIcon)).first().click();
|
||||
cy.get(dashboardSelector.changeButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
dashboardText.iconUpdatedToast
|
||||
);
|
||||
cy.get(dashboardSelector.appCardIcon(randomIcon)).should("exist");
|
||||
cy.get(commonSelectors.appCard(appName)).should("exist");
|
||||
cy.get(dashboardText.modalComponent).should("not.exist");
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -17,15 +17,15 @@ import { commonText } from "Texts/common";
|
|||
|
||||
export const verifyAllElementsOfPage = () => {
|
||||
cy.get(databaseSelectors.addTableButton).should("be.visible");
|
||||
cy.get(databaseSelectors.tablePageHeader).verifyVisibleElement(
|
||||
"have.text",
|
||||
databaseText.tablePageHeader
|
||||
);
|
||||
cy.get(databaseSelectors.doNotHaveTableText).verifyVisibleElement(
|
||||
"have.text",
|
||||
databaseText.doNotHaveTableText
|
||||
);
|
||||
cy.get(databaseSelectors.searchTableInputField).should("be.visible");
|
||||
// cy.get(databaseSelectors.tablePageHeader).verifyVisibleElement(
|
||||
// "have.text",
|
||||
// databaseText.tablePageHeader
|
||||
// );
|
||||
// cy.get(databaseSelectors.doNotHaveTableText).verifyVisibleElement(
|
||||
// "have.text",
|
||||
// databaseText.doNotHaveTableText
|
||||
// );
|
||||
//cy.get(databaseSelectors.searchTableInputField).should("be.visible");
|
||||
cy.get(databaseSelectors.allTablesSection).should("be.visible");
|
||||
cy.get(databaseSelectors.allTableSubheader).should("be.visible");
|
||||
};
|
||||
|
|
@ -66,7 +66,7 @@ export const createTableAndVerifyToastMessage = (
|
|||
);
|
||||
navigateToTable(tableName);
|
||||
cy.get(databaseSelectors.idColumnHeader).verifyVisibleElement(
|
||||
"have.text",
|
||||
"contain",
|
||||
databaseText.idColumnHeader
|
||||
);
|
||||
cy.get(databaseSelectors.noRecordsText).verifyVisibleElement(
|
||||
|
|
@ -185,8 +185,10 @@ export const createNewColumnAndVerify = (
|
|||
createNewColumnText.defaultValueLabel
|
||||
);
|
||||
cy.clearAndType(createNewColumnSelectors.columnNameInputField, columnName);
|
||||
cy.get(createNewColumnSelectors.dataTypeDropdown).click();
|
||||
cy.get(createNewColumnSelectors.dataTypeDropdown) .within(() => {
|
||||
cy.contains(`Select data type`).click();
|
||||
cy.contains(`[id*="react-select-"]`, columnDataType).click();
|
||||
})
|
||||
if (defaultValue) {
|
||||
cy.clearAndType(
|
||||
createNewColumnSelectors.defaultValueInputField,
|
||||
|
|
@ -215,7 +217,7 @@ export const createNewColumnAndVerify = (
|
|||
);
|
||||
|
||||
cy.get(databaseSelectors.columnHeader(columnName)).verifyVisibleElement(
|
||||
"have.text",
|
||||
"contain",
|
||||
`${String(columnName).toLowerCase().replace(/\s+/g, "-")}`
|
||||
);
|
||||
};
|
||||
|
|
@ -391,6 +393,7 @@ export const sortOperation = (tableName, columnName = [], order = []) => {
|
|||
cy.get(databaseSelectors.idColumnHeader).should("be.visible");
|
||||
};
|
||||
export const deleteCondition = (selector, columnName = [], deleteIcon) => {
|
||||
cy.wait(500);
|
||||
cy.get(selector).click();
|
||||
cy.get(".card-body").eq(1).should("be.visible");
|
||||
for (let i = 0; i < columnName.length; i++) {
|
||||
|
|
|
|||
28
cypress-tests/cypress/support/utils/events.js
Normal file
28
cypress-tests/cypress/support/utils/events.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
export const selectEvent = (event, action) => {
|
||||
cy.get('[data-cy="add-event-handler"]').click()
|
||||
cy.get('[data-cy="event-handler"]').eq(0).click()
|
||||
cy.get('[data-cy="event-selection"]')
|
||||
.click()
|
||||
.find("input")
|
||||
.type(`{selectAll}{backspace}${event}{enter}`);
|
||||
cy.get('[data-cy="action-selection"]')
|
||||
.click()
|
||||
.find("input")
|
||||
.type(`{selectAll}{backspace}${action}{enter}`);
|
||||
};
|
||||
|
||||
export const selectCSA = (
|
||||
component,
|
||||
componentAction,
|
||||
dbounce = `{selectAll}{backspace}`
|
||||
) => {
|
||||
cy.get('[data-cy="action-options-component-selection-field"]')
|
||||
.click()
|
||||
.find("input")
|
||||
.type(`{selectAll}{backspace}${component}`);
|
||||
cy.get('[data-cy="action-options-action-selection-field"]')
|
||||
.click()
|
||||
.find("input")
|
||||
.type(`{selectAll}{backspace}${componentAction}`);
|
||||
cy.get('[data-cy="-input-field"]').type(`{selectAll}{backspace}${debounce}`);
|
||||
};
|
||||
|
|
@ -70,7 +70,7 @@ export const createNewVersion = (newVersion = [], version) => {
|
|||
|
||||
export const clickOnExportButtonAndVerify = (buttonText, appName) => {
|
||||
cy.get(commonSelectors.buttonSelector(buttonText)).click();
|
||||
|
||||
cy.wait(1000);
|
||||
cy.exec("ls ./cypress/downloads/").then((result) => {
|
||||
const downloadedAppExportFileName = result.stdout.split("\n")[0];
|
||||
expect(downloadedAppExportFileName).to.have.string(appName.toLowerCase());
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const deleteInnerWidget = (widgetName, innerWidgetName) => {
|
|||
);
|
||||
cy.get("@innerWidget").first().click();
|
||||
cy.get(`[data-cy="${innerWidgetName}-delete-button"]`)
|
||||
.click()
|
||||
.realClick()
|
||||
.should("not.exist");
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -166,10 +166,6 @@ export const gitSSOPageElements = () => {
|
|||
export const passwordPageElements = () => {
|
||||
cy.get(ssoSelector.passwordEnableToggle).then(($el) => {
|
||||
if ($el.is(":checked")) {
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
cy.get(ssoSelector.passwordEnableToggle).uncheck();
|
||||
cy.get(commonSelectors.modalComponent).should("be.visible");
|
||||
cy.get(commonSelectors.modalMessage).verifyVisibleElement(
|
||||
|
|
@ -181,44 +177,27 @@ export const passwordPageElements = () => {
|
|||
commonSelectors.toastMessage,
|
||||
ssoText.passwordDisabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).check();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.passwordEnabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
|
||||
} else {
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).check();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.passwordEnabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).uncheck();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
ssoText.passwordDisabledToast
|
||||
);
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
|
||||
cy.get(ssoSelector.passwordEnableToggle).check();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,19 +1,33 @@
|
|||
import { path } from "Texts/common";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { usersText } from "Texts/manageUsers";
|
||||
import { commonSelectors } from "Selectors/common"
|
||||
import { usersText } from "Texts/manageUsers"
|
||||
import { usersSelector } from "Selectors/manageUsers";
|
||||
import { ssoSelector } from "Selectors/manageSSO";
|
||||
import { ssoText } from "Texts/manageSSO";
|
||||
import * as common from "Support/utils/common";
|
||||
import { commonText } from "../../constants/texts/common";
|
||||
import { commonText } from "Texts/common";
|
||||
|
||||
export const manageUsersElements = () => {
|
||||
|
||||
cy.get(commonSelectors.breadcrumbTitle).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
commonText.breadcrumbworkspaceSettingTitle
|
||||
);
|
||||
});
|
||||
cy.get(commonSelectors.breadcrumbPageTitle).verifyVisibleElement( "have.text",usersText.breadcrumbUsersPageTitle);
|
||||
|
||||
for (const element in usersSelector.usersElements) {
|
||||
cy.get(usersSelector.usersElements[element]).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.usersElements[element]
|
||||
);
|
||||
}
|
||||
cy.get(usersSelector.usersPageTitle).should(($el) => {
|
||||
expect($el.contents().last().text().trim()).to.eq(
|
||||
usersText.usersPageTitle
|
||||
);
|
||||
});
|
||||
cy.get(commonSelectors.inputUserSearch).should("be.visible")
|
||||
common.searchUser(usersText.adminUserEmail);
|
||||
cy.contains("td", usersText.adminUserEmail)
|
||||
.parent()
|
||||
|
|
@ -35,51 +49,56 @@ export const manageUsersElements = () => {
|
|||
usersText.adminUserState
|
||||
);
|
||||
});
|
||||
cy.get(commonSelectors.emailFilterInput).should("be.visible");
|
||||
cy.get(commonSelectors.firstNameFilterInput).should("be.visible");
|
||||
cy.get(commonSelectors.lastNameFilterInput).should("be.visible");
|
||||
cy.get(commonSelectors.clearFilterButton).should("be.visible");
|
||||
cy.get(commonSelectors.userStatusSelect).should("be.visible");
|
||||
cy.get(usersSelector.userFilterInput).should("be.visible");
|
||||
|
||||
cy.get(usersSelector.inviteUserButton)
|
||||
.verifyVisibleElement("have.text", usersText.inviteUserButton)
|
||||
cy.get(usersSelector.buttonAddUsers)
|
||||
.verifyVisibleElement("have.text", usersText.buttonAddUsers)
|
||||
.click();
|
||||
|
||||
cy.get(usersSelector.cardTitle).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.cardTitle
|
||||
);
|
||||
cy.get(usersSelector.firstNameInput).should("be.visible");
|
||||
cy.get(usersSelector.lastNameInput).should("be.visible");
|
||||
cy.get(usersSelector.emailLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.emailLabel
|
||||
);
|
||||
cy.get(usersSelector.lastNameInput).should("be.visible");
|
||||
cy.get(usersSelector.cancelButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.cancelButton
|
||||
);
|
||||
cy.get(usersSelector.createUserButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.createUserButton
|
||||
);
|
||||
cy.get(usersSelector.cancelButton).click();
|
||||
cy.get(usersSelector.buttonInviteWithEmail).verifyVisibleElement( "have.text",usersText.buttonInviteWithEmail);
|
||||
cy.get(usersSelector.buttonUploadCsvFile).verifyVisibleElement("have.text",usersText.buttonUploadCsvFile);
|
||||
cy.get(usersSelector.addUsersCardTitle).verifyVisibleElement("have.text",usersText.addUsersCardTitle);
|
||||
|
||||
cy.get(commonSelectors.labelFullNameInput).verifyVisibleElement("have.text",commonText.labelFullNameInput);
|
||||
cy.get(commonSelectors.inputFieldFullName).should("be.visible");
|
||||
cy.get(commonSelectors.labelEmailInput).verifyVisibleElement("have.text",commonText.labelEmailInput);
|
||||
cy.get(commonSelectors.inputFieldEmailAddress).should("be.visible");
|
||||
|
||||
cy.get(commonSelectors.cancelButton).verifyVisibleElement("have.text",usersText.cancelButton);
|
||||
cy.get(usersSelector.buttonInviteUsers).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.buttonInviteUsers
|
||||
);
|
||||
cy.get(commonSelectors.cancelButton).click();
|
||||
cy.get(usersSelector.addUsersCardTitle).should("not.exist")
|
||||
|
||||
cy.get(usersSelector.buttonAddUsers).click();
|
||||
cy.get(commonSelectors.closeButton).click();
|
||||
cy.get(usersSelector.addUsersCardTitle).should("not.exist")
|
||||
|
||||
cy.get(usersSelector.buttonAddUsers).click();
|
||||
cy.get(usersSelector.addUsersCardTitle).verifyVisibleElement("have.text", usersText.addUsersCardTitle);
|
||||
cy.get(usersSelector.buttonUploadCsvFile).click();
|
||||
|
||||
cy.get(usersSelector.helperTextBulkUpload).verifyVisibleElement("have.text", usersText.helperTextBulkUpload);
|
||||
cy.get(usersSelector.buttonDownloadTemplate).verifyVisibleElement("have.text", usersText.buttonDownloadTemplate);
|
||||
cy.get(usersSelector.iconBulkUpload).should("be.visible")
|
||||
cy.get(usersSelector.helperTextSelectFile).verifyVisibleElement("have.text", usersText.helperTextSelectFile);
|
||||
cy.get(usersSelector.helperTextDropFile).verifyVisibleElement("have.text", usersText.helperTextDropFile);
|
||||
cy.get(usersSelector.inputFieldBulkUpload).should("exist")
|
||||
cy.get(usersSelector.buttonUploadUsers).verifyVisibleElement("have.text", usersText.buttonUploadUsers);
|
||||
|
||||
|
||||
|
||||
|
||||
cy.get(usersSelector.inviteBulkUserButton).verifyVisibleElement("have.text",usersText.inviteBulkUserButton).click();
|
||||
cy.get(usersSelector.bulkUserUploadPageTitle).verifyVisibleElement("have.text",usersText.bulkUserUploadPageTitle);
|
||||
cy.get(usersSelector.bulkUSerUploadInput).should("be.visible");
|
||||
cy.get(usersSelector.downloadTemplateButton).verifyVisibleElement("have.text",usersText.downloadTemplateButton);
|
||||
cy.get(usersSelector.cancelButton).verifyVisibleElement("have.text",usersText.cancelButton);
|
||||
};
|
||||
|
||||
export const inviteUser = (firstName, lastName, email) => {
|
||||
cy.get(usersSelector.inviteUserButton).click();
|
||||
cy.clearAndType(usersSelector.firstNameInput, firstName);
|
||||
cy.clearAndType(usersSelector.lastNameInput, lastName);
|
||||
cy.clearAndType(usersSelector.emailInput, email);
|
||||
export const inviteUser = (firstName, email) => {
|
||||
cy.get(usersSelector.buttonAddUsers).click();
|
||||
cy.clearAndType(commonSelectors.inputFieldFullName, firstName);
|
||||
cy.clearAndType(commonSelectors.inputFieldEmailAddress, email);
|
||||
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.get(usersSelector.buttonInviteUsers).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
usersText.userCreatedToast
|
||||
|
|
@ -91,7 +110,7 @@ export const inviteUser = (firstName, lastName, email) => {
|
|||
cy.contains("td", email)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get("td img").click();
|
||||
cy.get(usersSelector.copyInvitationLink).click();
|
||||
});
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
|
|
@ -100,15 +119,13 @@ export const inviteUser = (firstName, lastName, email) => {
|
|||
cy.get("@copyToClipboardPrompt").then((prompt) => {
|
||||
common.logout();
|
||||
cy.visit(prompt.args[0][1]);
|
||||
cy.url().should("include", path.confirmInvite);
|
||||
});
|
||||
};
|
||||
|
||||
export const addNewUser = (firstName, lastName, email) => {
|
||||
export const addNewUser = (firstName, email) => {
|
||||
cy.intercept("POST", "/api/organization_users").as("appLibrary");
|
||||
cy.clearAndType(usersSelector.firstNameInput, firstName);
|
||||
cy.clearAndType(usersSelector.lastNameInput, lastName);
|
||||
cy.clearAndType(usersSelector.emailInput, email);
|
||||
cy.clearAndType(commonSelectors.inputFieldFullName, firstName);
|
||||
cy.clearAndType(commonSelectors.inputFieldEmailAddress, email);
|
||||
|
||||
cy.get(usersSelector.createUserButton).click();
|
||||
cy.wait("@appLibrary").then((res) => {
|
||||
|
|
@ -121,7 +138,6 @@ export const addNewUser = (firstName, lastName, email) => {
|
|||
};
|
||||
|
||||
export const confirmInviteElements = () => {
|
||||
cy.url().should("include", '/confirm');
|
||||
cy.get(commonSelectors.invitePageHeader).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.invitePageHeader
|
||||
|
|
|
|||
59
cypress-tests/cypress/support/utils/modal.js
Normal file
59
cypress-tests/cypress/support/utils/modal.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import { commonWidgetSelector } from "Selectors/common";
|
||||
import {
|
||||
verifyAndModifyStylePickerFx,
|
||||
selectColourFromColourPicker,
|
||||
verifyWidgetColorCss,
|
||||
} from "Support/utils/commonWidget";
|
||||
|
||||
export const launchModal = (componentName) => {
|
||||
cy.get(launchButton(componentName)).click();
|
||||
};
|
||||
|
||||
export const launchButton = (componentName) => {
|
||||
return `[data-cy="draggable-widget-${componentName
|
||||
.toLowerCase()
|
||||
.replace(" ", "-")}-launch-button"]`;
|
||||
};
|
||||
|
||||
export const verifySize = (size) => {
|
||||
const className = {
|
||||
Small: "sm",
|
||||
Medium: "lg",
|
||||
Large: "xl",
|
||||
};
|
||||
cy.get('[data-cy="dropdown-modal-size"]')
|
||||
.click()
|
||||
.find("input")
|
||||
.type(`{selectAll}{backspace}${size}{enter}`);
|
||||
cy.get(
|
||||
`[class="modal-dialog modal-${className[size]} modal-dialog-scrollable"]`
|
||||
).should("exist");
|
||||
};
|
||||
|
||||
export const closeModal = (componentName) => {
|
||||
cy.get('[data-cy="modal-close-button"]').realClick();
|
||||
};
|
||||
|
||||
export const addAndVerifyColor = (
|
||||
section,
|
||||
defaultColor,
|
||||
color,
|
||||
dataCy,
|
||||
type = "background-color"
|
||||
) => {
|
||||
verifyAndModifyStylePickerFx(section, defaultColor, "data.colourHex");
|
||||
cy.get(commonWidgetSelector.parameterFxButton(section)).click();
|
||||
|
||||
selectColourFromColourPicker(section, color);
|
||||
verifyWidgetColorCss(dataCy, type, color, true);
|
||||
closeModal("modal1");
|
||||
launchModal("modal1");
|
||||
cy.get(commonWidgetSelector.buttonStylesEditorSideBar).click({ force: true });
|
||||
};
|
||||
|
||||
export const typeOnFx = (fx, data) => {
|
||||
cy.get(commonWidgetSelector.parameterFxButton(fx)).eq(1).realClick();
|
||||
cy.get(commonWidgetSelector.parameterInputField(fx)).clearAndTypeOnCodeMirror(
|
||||
data
|
||||
);
|
||||
};
|
||||
|
|
@ -39,7 +39,7 @@ export const setHomePage = (pageName) => {
|
|||
|
||||
export const addNewPage = (pageName) => {
|
||||
cy.get(multipageSelector.addPageIcon).click();
|
||||
cy.get(".col-12 > .form-control").type(pageName);
|
||||
cy.get(".col-12 > .form-control").type(`{selectAll}{backspace}${pageName}`);
|
||||
cy.get(multipageSelector.addPageIcon).click();
|
||||
cy.get(`[data-cy="pages-name-${pageName.toLowerCase()}"]`).click();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export const selectDropdownOption = (inputSelector, option) => {
|
|||
};
|
||||
|
||||
const click = () => {
|
||||
cy.get(inputSelector).click();
|
||||
cy.get(inputSelector).realClick();
|
||||
cy.wait(500);
|
||||
cy.get("body").then(($body) => {
|
||||
if ($body.find('[data-index="0"]').length == 0) {
|
||||
|
|
@ -55,47 +55,46 @@ export const selectDropdownOption = (inputSelector, option) => {
|
|||
click();
|
||||
cy.get(
|
||||
isNaN(option)
|
||||
? `[data-index="${data[option]}"]`
|
||||
: `[data-index="${option}"]`
|
||||
).click();
|
||||
? `[data-index="${data[option]}"]>.select-search-option:eq(0)`
|
||||
: `[data-index="${option}"]>.select-search-option:eq(0)`
|
||||
).click({ force: true });
|
||||
};
|
||||
|
||||
export const verifyAndEnterColumnOptionInput = (label, value) => {
|
||||
cy.get(`[data-cy="input-and-label-${cyParamName(label)}"]`)
|
||||
.find("label")
|
||||
.should("have.text", label);
|
||||
cy.get(`[data-cy="input-and-label-${cyParamName(label)}"]`).type(
|
||||
`{selectAll}{backspace}${value}`
|
||||
);
|
||||
cy.get(`[data-cy="input-and-label-${cyParamName(label)}"]`)
|
||||
.realClick()
|
||||
.realPress(["Meta", "A"])
|
||||
.realType(
|
||||
`{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}${value}`
|
||||
);
|
||||
};
|
||||
|
||||
export const addAndOpenColumnOption = (name, type) => {
|
||||
cy.get('[data-cy="button-add-column"]').click();
|
||||
cy.get('[data-cy="button-add-column"]')
|
||||
.parents(".accordion-body")
|
||||
.find('[data-cy*="column-"]')
|
||||
.find('[data-cy*="column-new_column"]')
|
||||
.last()
|
||||
.click();
|
||||
selectDropdownOption(
|
||||
'[data-cy="dropdown-column-type"] > .select-search',
|
||||
type
|
||||
);
|
||||
selectDropdownOption('[data-cy="dropdown-column-type"]>>:eq(0)', type);
|
||||
verifyAndEnterColumnOptionInput("Column name", name);
|
||||
};
|
||||
|
||||
export const deleteAndVerifyColumn = (columnName) => {
|
||||
cy.get(`[data-cy="button-delete-${columnName}"]`).click();
|
||||
cy.notVisible(`[data-cy="column-${columnName}"]`);
|
||||
cy.forceClickOnCanvas();
|
||||
cy.notVisible(tableSelector.columnHeader(columnName));
|
||||
};
|
||||
|
||||
export const verifyInvalidFeedback = (columnIndex = 0, rowIndex = 0, text) => {
|
||||
cy.get(tableSelector.column(columnIndex))
|
||||
.eq(rowIndex)
|
||||
.find('[class="invalid-feedback"]')
|
||||
.find(">>>>:eq(1)")
|
||||
.should("have.text", text);
|
||||
cy.forceClickOnCanvas();
|
||||
// cy.forceClickOnCanvas();
|
||||
};
|
||||
|
||||
export const addInputOnTable = (
|
||||
|
|
@ -107,6 +106,7 @@ export const addInputOnTable = (
|
|||
cy.forceClickOnCanvas();
|
||||
cy.get(tableSelector.column(columnIndex))
|
||||
.eq(rowIndex)
|
||||
.click()
|
||||
.find(type)
|
||||
.click()
|
||||
.type(`{selectAll}{backspace}${value}`);
|
||||
|
|
@ -165,14 +165,18 @@ export const dataCsvAssertionHelper = (data) => {
|
|||
return dataArray;
|
||||
};
|
||||
|
||||
export const addFilter =(data=[{column:'name', operation: "contains", value: 'Sarah'}], freshFilter=false)=>{
|
||||
export const addFilter = (
|
||||
data = [{ column: "name", operation: "contains", value: "Sarah" }],
|
||||
freshFilter = false
|
||||
) => {
|
||||
cy.get(tableSelector.filterButton).click();
|
||||
|
||||
|
||||
data.forEach((filter,index) => {
|
||||
if(freshFilter==true){
|
||||
if(index==0){cy.get(tableSelector.buttonClearFilter).click()}
|
||||
cy.get(tableSelector.buttonAddFilter).click()
|
||||
data.forEach((filter, index) => {
|
||||
if (freshFilter == true) {
|
||||
if (index == 0) {
|
||||
cy.get(tableSelector.buttonClearFilter).click();
|
||||
}
|
||||
cy.get(tableSelector.buttonAddFilter).click();
|
||||
}
|
||||
cy.get(tableSelector.filterSelectColumn(index))
|
||||
.click()
|
||||
|
|
@ -180,10 +184,11 @@ export const addFilter =(data=[{column:'name', operation: "contains", value: 'Sa
|
|||
cy.get(tableSelector.filterSelectOperation(index))
|
||||
.click()
|
||||
.type(`${filter.operation}{enter}`);
|
||||
if(filter.value){
|
||||
cy.get(tableSelector.filterInput(index)).type(`{selectAll}{del}${filter.value}`);
|
||||
}
|
||||
|
||||
if (filter.value) {
|
||||
cy.get(tableSelector.filterInput(index)).type(
|
||||
`{selectAll}{del}${filter.value}`
|
||||
);
|
||||
}
|
||||
});
|
||||
cy.get(tableSelector.buttonCloseFilters).click()
|
||||
}
|
||||
cy.get(tableSelector.buttonCloseFilters).click();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import * as common from "Support/utils/common";
|
|||
import { path } from "Texts/common";
|
||||
import { groupsSelector } from "Selectors/manageGroups";
|
||||
import { groupsText } from "Texts/manageGroups";
|
||||
import { dashboardSelector } from "../../constants/selectors/dashboard";
|
||||
import { dashboardSelector } from "Selectors/dashboard";
|
||||
|
||||
export const adminLogin = () => {
|
||||
common.logout();
|
||||
|
|
@ -59,9 +59,9 @@ export const reset = () => {
|
|||
});
|
||||
};
|
||||
|
||||
export const addNewUserMW = (firstName, lastName, email, companyName) => {
|
||||
export const addNewUserMW = (firstName, email, companyName) => {
|
||||
common.navigateToManageUsers();
|
||||
users.inviteUser(firstName, lastName, email);
|
||||
users.inviteUser(firstName, email);
|
||||
cy.clearAndType(commonSelectors.passwordInputField, usersText.password);
|
||||
cy.get(commonSelectors.acceptInviteButton).click();
|
||||
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
|
||||
|
|
|
|||
|
|
@ -2,112 +2,158 @@ import { appVersionText } from "Texts/exportImport";
|
|||
import { appVersionSelectors } from "Selectors/exportImport";
|
||||
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
import { verifyModal, closeModal } from "Support/utils/common"
|
||||
import { deleteVersionSelectors, editVersionSelectors } from "Selectors/version";
|
||||
import { deleteVersionText, editVersionText, releasedVersionText } from "Texts/version";
|
||||
import { verifyModal, closeModal } from "Support/utils/common";
|
||||
import {
|
||||
deleteVersionSelectors,
|
||||
editVersionSelectors,
|
||||
} from "Selectors/version";
|
||||
import {
|
||||
deleteVersionText,
|
||||
editVersionText,
|
||||
releasedVersionText,
|
||||
} from "Texts/version";
|
||||
import { verifyComponent } from "Support/utils/basicComponents";
|
||||
|
||||
export const navigateToCreateNewVersionModal = (value) => {
|
||||
cy.get(appVersionSelectors.currentVersionField(value)).should("be.visible").click();
|
||||
cy.contains(appVersionText.createNewVersion).should("be.visible").click();
|
||||
}
|
||||
cy.get(appVersionSelectors.currentVersionField(value))
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.contains(appVersionText.createNewVersion).should("be.visible");
|
||||
cy.contains(appVersionText.createNewVersion).click();
|
||||
};
|
||||
|
||||
export const navigateToEditVersionModal = (value) => {
|
||||
cy.get(appVersionSelectors.currentVersionField(value)).should("be.visible").click();
|
||||
cy.get('[style="padding: 8px 12px;"] .row').should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(".icon").trigger("mouseover").click();
|
||||
})
|
||||
}
|
||||
cy.get(appVersionSelectors.currentVersionField(value))
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get('[style="padding: 8px 12px;"] .row')
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(".icon").trigger("mouseover").click();
|
||||
});
|
||||
};
|
||||
|
||||
export const verifyElementsOfCreateNewVersionModal = (version = []) => {
|
||||
cy.get(appVersionSelectors.createNewVersion).verifyVisibleElement(
|
||||
"have.text",
|
||||
appVersionText.createNewVersion
|
||||
);
|
||||
cy.get(appVersionSelectors.versionNamelabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
appVersionText.versionNameLabel
|
||||
);
|
||||
cy.get(appVersionSelectors.createVersionFromLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
appVersionText.createVersionFromLabel
|
||||
);
|
||||
cy.get(appVersionSelectors.versionNameInputField).should("be.visible");
|
||||
cy.get(appVersionSelectors.createVersionInputField).verifyVisibleElement(
|
||||
"have.text",
|
||||
version[0]
|
||||
);
|
||||
cy.get(
|
||||
commonSelectors.buttonSelector(appVersionText.createNewVersion)
|
||||
).verifyVisibleElement("have.text", appVersionText.createNewVersion);
|
||||
cy.get(commonSelectors.buttonSelector(commonText.cancelButton))
|
||||
.should("be.visible")
|
||||
.and("have.text", commonText.cancelButton);
|
||||
cy.get(commonSelectors.buttonSelector(commonText.closeButton))
|
||||
.should("be.visible")
|
||||
.click();
|
||||
};
|
||||
|
||||
cy.get(appVersionSelectors.createNewVersion).verifyVisibleElement("have.text", appVersionText.createNewVersion);
|
||||
cy.get(appVersionSelectors.versionNamelabel).verifyVisibleElement("have.text", appVersionText.versionNameLabel);
|
||||
cy.get(appVersionSelectors.createVersionFromLabel).verifyVisibleElement("have.text", appVersionText.createVersionFromLabel);
|
||||
cy.get(appVersionSelectors.versionNameInputField).should("be.visible");
|
||||
cy.get(appVersionSelectors.createVersionInputField).verifyVisibleElement("have.text", version[0]);
|
||||
cy.get(
|
||||
commonSelectors.buttonSelector(appVersionText.createNewVersion)
|
||||
).verifyVisibleElement("have.text", appVersionText.createNewVersion);
|
||||
cy.get(commonSelectors.buttonSelector(commonText.cancelButton))
|
||||
.should("be.visible")
|
||||
.and("have.text", commonText.cancelButton);
|
||||
cy.get(commonSelectors.buttonSelector(commonText.closeButton)).should(
|
||||
"be.visible"
|
||||
).click();
|
||||
export const editVersionAndVerify = (
|
||||
currentVersion,
|
||||
newVersion = [],
|
||||
toastMessageText
|
||||
) => {
|
||||
cy.reload();
|
||||
cy.get(appVersionSelectors.currentVersionField(currentVersion)).then(
|
||||
($ele) => {
|
||||
if ($ele.hasClass("color-light-green")) {
|
||||
cy.contains(releasedVersionText.releasedModalText).should("be.visible");
|
||||
closeModal(commonText.closeButton);
|
||||
}
|
||||
}
|
||||
);
|
||||
navigateToEditVersionModal(currentVersion);
|
||||
cy.get(editVersionSelectors.versionNameInputField).verifyVisibleElement(
|
||||
"have.value",
|
||||
currentVersion
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
export const editVersionAndVerify = (currentVersion, newVersion = [], toastMessageText) => {
|
||||
cy.reload();
|
||||
navigateToEditVersionModal(currentVersion)
|
||||
cy.get(editVersionSelectors.versionNameInputField).verifyVisibleElement("have.value", currentVersion);
|
||||
|
||||
cy.clearAndType(
|
||||
editVersionSelectors.versionNameInputField,
|
||||
newVersion[0]
|
||||
);
|
||||
cy.get(editVersionSelectors.saveButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
toastMessageText
|
||||
);
|
||||
}
|
||||
cy.clearAndType(editVersionSelectors.versionNameInputField, newVersion[0]);
|
||||
cy.get(editVersionSelectors.saveButton).click();
|
||||
cy.wait(500);
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, toastMessageText);
|
||||
};
|
||||
export const deleteVersionAndVerify = (value, toastMessageText) => {
|
||||
cy.get(appVersionSelectors.currentVersionField(value)).should("be.visible").click();
|
||||
cy.contains(`[id*="react-select-"]`, value).should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(" .app-version-list-item")
|
||||
.trigger('mouseover')
|
||||
.trigger("mouseenter")
|
||||
.find(".app-version-delete")
|
||||
.click({ force: true });
|
||||
})
|
||||
cy.get(deleteVersionSelectors.modalMessage).verifyVisibleElement("have.text", deleteVersionText.deleteModalText(value));
|
||||
cy.get(deleteVersionSelectors.yesButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
toastMessageText
|
||||
);
|
||||
cy.get(appVersionSelectors.currentVersionField(value))
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.contains(`[id*="react-select-"]`, value)
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(" .app-version-list-item")
|
||||
.trigger("mouseover")
|
||||
.trigger("mouseenter")
|
||||
.find(".app-version-delete")
|
||||
.click({ force: true });
|
||||
});
|
||||
cy.get(deleteVersionSelectors.modalMessage).verifyVisibleElement(
|
||||
"have.text",
|
||||
deleteVersionText.deleteModalText(value)
|
||||
);
|
||||
cy.get(deleteVersionSelectors.yesButton).click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, toastMessageText);
|
||||
};
|
||||
|
||||
export const verifyDuplicateVersion = (newVersion = [], version) => {
|
||||
cy.contains(appVersionText.createNewVersion).should("be.visible").click();
|
||||
verifyModal(
|
||||
appVersionText.createNewVersion,
|
||||
appVersionText.createNewVersion,
|
||||
appVersionSelectors.createVersionInputField
|
||||
);
|
||||
cy.get(appVersionSelectors.createVersionInputField).click()
|
||||
cy.contains(`[id*="react-select-"]`, version).click();
|
||||
cy.get(appVersionSelectors.versionNameInputField).click().type(newVersion[0]);
|
||||
cy.get(appVersionSelectors.createNewVersionButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
appVersionText.versionNameAlreadyExists
|
||||
);
|
||||
cy.contains(appVersionText.createNewVersion).should("be.visible").click();
|
||||
verifyModal(
|
||||
appVersionText.createNewVersion,
|
||||
appVersionText.createNewVersion,
|
||||
appVersionSelectors.createVersionInputField
|
||||
);
|
||||
cy.get(appVersionSelectors.createVersionInputField).click();
|
||||
cy.contains(`[id*="react-select-"]`, version).click();
|
||||
cy.get(appVersionSelectors.versionNameInputField).click().type(newVersion[0]);
|
||||
cy.get(appVersionSelectors.createNewVersionButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
appVersionText.versionNameAlreadyExists
|
||||
);
|
||||
};
|
||||
export const releasedVersionAndVerify = (currentVersion) => {
|
||||
cy.contains("Release").click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
releasedVersionText.releasedToastMessage(currentVersion)
|
||||
);
|
||||
verifyModal(
|
||||
appVersionText.createNewVersion,
|
||||
appVersionText.createNewVersion,
|
||||
appVersionSelectors.versionNameInputField
|
||||
);
|
||||
cy.contains(releasedVersionText.releasedModalText).should("be.visible");
|
||||
closeModal(commonText.closeButton);
|
||||
cy.get(appVersionSelectors.currentVersionField(currentVersion)).should("have.class", "color-light-green");
|
||||
cy.contains("Release").click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
releasedVersionText.releasedToastMessage(currentVersion)
|
||||
);
|
||||
cy.forceClickOnCanvas();
|
||||
cy.wait(2000);
|
||||
verifyModal(
|
||||
appVersionText.createNewVersion,
|
||||
appVersionText.createNewVersion,
|
||||
appVersionSelectors.versionNameInputField
|
||||
);
|
||||
cy.contains(releasedVersionText.releasedModalText).should("be.visible");
|
||||
cy.wait(500);
|
||||
closeModal(commonText.closeButton);
|
||||
cy.get(appVersionSelectors.currentVersionField(currentVersion)).should(
|
||||
"have.class",
|
||||
"color-light-green"
|
||||
);
|
||||
};
|
||||
|
||||
export const verifyVersionAfterPreview = (currentVersion) => {
|
||||
cy.get(appVersionSelectors.currentVersionField(currentVersion)).should("be.visible")
|
||||
cy.get(commonWidgetSelector.previewButton).invoke('removeAttr', 'target').click();
|
||||
cy.url().should('include', '/home')
|
||||
verifyComponent("button1");
|
||||
cy.contains(currentVersion)
|
||||
cy.get(appVersionSelectors.currentVersionField(currentVersion)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(commonWidgetSelector.previewButton)
|
||||
.invoke("removeAttr", "target")
|
||||
.click();
|
||||
cy.url().should("include", "/home");
|
||||
verifyComponent("button1");
|
||||
cy.contains(currentVersion);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ The user details entered while setting up ToolJet will have Super Admin privileg
|
|||
| Manage Groups in their workspace (Create Group/Add or Delete Users from groups/ Modify Group Permissions) | ✅ | ✅ |
|
||||
| Manage SSO in their workspace | ✅ | ✅ |
|
||||
| Manage Workspace Variables in their workspace | ✅ | ✅ |
|
||||
| [Manage Global datasources for the user group in their workspace](/docs/next/data-sources/overview#permissions) | ✅ | ✅ |
|
||||
| [Access any user's personal workspace (create, edit or delete apps)](#access-any-workspace) | ❌ | ✅ |
|
||||
| [Archive Admin or any user of any workspace](#archiveunarchive-users) | ❌ | ✅ |
|
||||
| [Access any user's ToolJet database (create, edit or delete database)](#access-tooljet-db-in-any-workspace) | ❌ | ✅ |
|
||||
|
|
|
|||
|
|
@ -41,3 +41,6 @@ For VSCode users, you can set the formatter to `ESLint` in the [**settings.json*
|
|||
1. **Node version 18.3.0**
|
||||
2. **npm version 8.11.0**
|
||||
|
||||
:::tip
|
||||
It is recommended to check the VSCode **Setting.json**(Press `ctrl/cmnd + P` and search `>Settings (JSON)`) file to ensure there are no overrides to the eslint config rules. Comment the following rules for eslint: **eslint.options: {...}**.
|
||||
:::
|
||||
11
docs/docs/data-sources/grpc.md
Normal file
11
docs/docs/data-sources/grpc.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
# grpc
|
||||
|
||||
ToolJet can connect to GRPC databases to read and write data.
|
||||
|
||||
- [Connection](#connection)
|
||||
- [Getting Started](#querying-grpc)
|
||||
|
||||
## Connection
|
||||
|
||||
## Querying GRPC
|
||||
|
|
@ -3,9 +3,13 @@ id: overview
|
|||
title: Overview
|
||||
---
|
||||
|
||||
# Datasources : Overview
|
||||
# Global Datasources : Overview
|
||||
|
||||
Datasources pull in and push data to any source including databases, external APIs, or services.
|
||||
Global datasources pull in and push data to any source including databases, external APIs, or services. Once a global datasource is connected to a workspace, the connection can be shared with any app of that workspace.
|
||||
|
||||
:::caution
|
||||
Global datasources are available only on **ToolJet version 2.3.0 and above**.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -13,30 +17,115 @@ Datasources pull in and push data to any source including databases, external AP
|
|||
|
||||
</div>
|
||||
|
||||
## Connecting datasources
|
||||
## Connecting global datasources
|
||||
|
||||
1. After logging in to ToolJet, create a new app from the dashboard
|
||||
1. From the ToolJet dashboard, go to the **global datasources page** from the left sidebar.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
2. There are two ways for connecting a datasource. You can connect from:
|
||||
1. **Left-sidebar**: On the left sidebar, click on the `datasource` icon and then click on the `+ add datasource` button
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/global.png" alt="Datasources: Overview" />
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
</div>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/ls2.png" alt="Datasources: Overview" width="400"/>
|
||||
2. Click on the **Add new datasource** button, a modal will pop-up with all the available global datasources.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
</div>
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/popup.png" alt="Datasources: Overview" />
|
||||
|
||||
2. **Query Panel**: Go to the query panel at the bottom, click on the `+Add` button and then click `Add datasource` button
|
||||
</div>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
3. Select the datasource, enter the **Credentials** and **Save** the datasource.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/qp2.png" alt="Datasources: Overview"/>
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/connection.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
3. Follow the steps in the **[Datasource Library](/docs/data-sources/airtable)** specific to the desired datasource
|
||||
4. Now, go back to the dashboard, create a new app, and the datasource will be available on the query panel under **Global Datasources**. Added datasources will be available on any of the **existing** or the **new applications**.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/globalquery.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
5. You can now create queries of the connected global datasource. From the queries, you'll be able to switch to **different connections** of the same datasource if there are more than one connections created.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/switch.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
## Changing scope of datasources of an app created on older versions of ToolJet
|
||||
|
||||
On ToolJet versions below 2.3.0, the datasource connection was made from within the individual apps. To make it backward compatible, we added an option to change the scope of the datasources and make it global datasource.
|
||||
|
||||
1. If you open an app created on previos versions of ToolJet, you'll find the datasource manager on the left sidebar of the App Builder.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/leftsidebar.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
2. Click on the kebab menu next to the connected datasource, select the **change scope** option.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/changescope.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
3. Once you change the scope of the datasource and make it global, you'll see that the **datasource manager** is removed from the left sidebar and now you'll find the datasource on the **query panel** under Global Datasources. You can now configure the datasource fromt the Global Datasource page on the **dashboard**.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/queryadd.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## Default datasources
|
||||
|
||||
By default, 4 datasources will be available on every app on ToolJet:
|
||||
- **[ToolJet Database](/docs/tooljet-database/)**
|
||||
- **[RestAPI](/docs/data-sources/restapi/)**
|
||||
- **[Run JavaScript Query](/docs/data-sources/run-js/)**
|
||||
- **[Run Python Query](/docs/data-sources/run-py/)**
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/default.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
## Permissions
|
||||
|
||||
Only **Admins** and **[Super Admins](/docs/Enterprise/superadmin)** of the workspace can change the **[Permissions](/docs/tutorial/manage-users-groups#group-properties)** for Global Datasource.
|
||||
|
||||
From **Workspace Settings** -> **Groups Settings**, Admins and Super Admins can set the permission for a user group to:
|
||||
|
||||
- **Create** and **Delete** datasources onto that workspace. If **Create** permission is enabled then the users can add new global datasources and **edit** the datasources as well but cannot **delete** it, and if only **Delete** permission is set then the users of the group will only be able to delete the connected datasources on the workspace.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/create.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
- If any of the permission(Create or Delete) is not enabled for a user group then the users of the group will get an error toast when they try to Add or Delete the global datasource.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/error.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
- **View** or **Edit** allowed global datasources from the **Datasources** tab. If only **View** permission is set then the users of the group will only be able to connect to the allowed datasource, and if only **Edit** permission is set then the users of the group will be able to update the credentials of the allowed datasources.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/view.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
- If any of the permission(View or Edit) is not enabled for a user group then the users of the group will get an error toast when they try to Add or Delete the global datasource.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/edit.png" alt="Datasources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
:::info
|
||||
ToolJet allows you to transform the data returned by datasources using **[Transformations](/docs/tutorial/transformations)**
|
||||
:::
|
||||
|
||||
|
|
|
|||
|
|
@ -5,18 +5,24 @@ title: SMTP
|
|||
|
||||
# SMTP
|
||||
|
||||
SMTP plugin can connect ToolJet applications to **SMTP servers** for sending emails.
|
||||
The SMTP datasource facilitates the connection between ToolJet applications and email servers, enabling the apps to send emails.
|
||||
|
||||
## Connection
|
||||
|
||||
A SMTP server can be connected with the following credentails:
|
||||
- **Host**
|
||||
- **Port**
|
||||
- **User**
|
||||
To connect to an SMTP server, the following credentials are typically required:
|
||||
|
||||
- **Host**
|
||||
- **Port**
|
||||
- **Username**
|
||||
- **Password**
|
||||
|
||||
:::info
|
||||
You can also test your connection before saving the configuration by clicking on `Test Connection` button.
|
||||
:::tip Finding configuration details:
|
||||
The SMTP configuration details like host and port can usually be obtained from your email service provider. Here are some general settings for the most commonly used email providers:
|
||||
- **Gmail**: `Host`: smtp.gmail.com; `Port`: 587 or 465 (SSL); `Username`: your full Gmail email address; `Password`: your Gmail password.
|
||||
- **Yahoo Mail**: `Host`: smtp.mail.yahoo.com; `Port`: 465 (SSL); `Username`: your Yahoo Mail email address; `Password`: your Yahoo Mail password.
|
||||
- **Outlook.com/Hotmail**: `Host`: smtp.office365.com; `Port`: 587 or 465 (SSL); `Username`: your Outlook.com/Hotmail email address; `Password`: your Outlook.com/Hotmail password.
|
||||
|
||||
Before saving the configuration, it's possible to test the connection by clicking the "Test Connection" button.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
|
@ -27,22 +33,25 @@ You can also test your connection before saving the configuration by clicking on
|
|||
|
||||
## Querying SMTP
|
||||
|
||||
Go to the query manager at the bottom panel of the editor and click on the `+` button on the left to create a new query. Select `SMTP` from the datasource dropdown.
|
||||
To create a query for sending an email, follow these steps:
|
||||
|
||||
To create a query for sending email, you will need to provide the following properties:
|
||||
- **From** `required` : Email address of the sender
|
||||
- **From Name** : Name of the sender
|
||||
- **To** `required` : Recipient's email address
|
||||
- **Subject** : Subject of the email
|
||||
1. Open the query panel located at the bottom panel of the editor.
|
||||
2. Click the `+Add` button on the left to create a new query.
|
||||
3. Select `SMTP` from the global datasource.
|
||||
4. Provide the following properties:
|
||||
- **From** `required` : Email address of the sender
|
||||
- **From Name** : Name of the sender
|
||||
- **To** `required` : Recipient's email address
|
||||
- **CC mail to** : Email address of the recipients that will receive a copy of the email, and their email addresses will be visible to other recipients.
|
||||
- **BCC mail to** : Email address of the recipients that will receive a copy of the email but the email addressed will be hidden to other recipients.
|
||||
- **Subject** : Subject of the email.
|
||||
- **Body** : You can enter the body text of the email in either raw text or html format, in their respective fields.
|
||||
- **Attachments** : You can add attachments to an SMTP query by referencing the file from the File Picker component in the attachments field.
|
||||
|
||||
For instance, you can set the `Attachments` field value to `{{ components.filepicker1.file }}` or pass an array of `{{ name: 'filename.jpg', dataURL: '......' }}` objects to include attachments.
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/smtp/query1.png" alt="smtp query1" />
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/smtp/querysmtp.png" alt="smtp connect" />
|
||||
|
||||
- **Body** : You can enter the body text either in the form of `raw text` or `html` in their respective fields.
|
||||
- **Attachments** : Attachments can be added to a SMTP query by referencing the file from the `File Picker` component in the attachments field.
|
||||
|
||||
For example, you can set the `Attachments` field value to `{{ components.filepicker1.file }}` or you can pass an array of `{{ name: 'filename.jpg', dataURL: '......' }}` object to accomplish this.
|
||||
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/smtp/query2.png" alt="smtp query2" />
|
||||
</div>
|
||||
|
|
@ -107,7 +107,7 @@ Learn more about the **[ToolJet Database here](/docs/tooljet-database)**
|
|||
|
||||
### Create a new application
|
||||
|
||||
1. To create a new ToolJet application, go to the **Dashboard** -> **New App from scratch**.
|
||||
1. To create a new ToolJet application, go to the **Dashboard** -> **Create new application**.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ Learn more about the **[ToolJet Database here](/docs/tooljet-database)**
|
|||
</div>
|
||||
|
||||
:::info
|
||||
ToolJet application's User interface is constructed using Components like Tables, Forms, Charts, or Buttons etc. Check **Components Catalog** to learn more.
|
||||
ToolJet application's User interface is constructed using Components like Tables, Forms, Charts, or Buttons etc. Check **[Components Catalog](/docs/widgets/overview)** to learn more.
|
||||
:::
|
||||
|
||||
### Build queries and bind data to UI
|
||||
|
|
@ -156,7 +156,7 @@ ToolJet application's User interface is constructed using Components like Tables
|
|||
</div>
|
||||
|
||||
:::info
|
||||
ToolJet can connect to several databases, APIs and external services to fetch and modify data. Check **Datasource Catalog** to learn more.
|
||||
ToolJet can connect to several databases, APIs and external services to fetch and modify data. Check **[Datasource Catalog](/docs/data-sources/overview)** to learn more.
|
||||
:::
|
||||
|
||||
2. Choose a **Table** from the dropdown, Select the **List rows** option from the **Operation** dropdown, You can leave other query parameters. Scroll down and enable **Run this query on application load** - this will trigger the query when the app is loaded.
|
||||
|
|
@ -199,8 +199,8 @@ ToolJet application's User interface is constructed using Components like Tables
|
|||
</div>
|
||||
|
||||
:::info
|
||||
- You can manipulate the data returned by the queries using **Transformations**
|
||||
- You can also **Run JS query** or **Python query** to perform custom behavior inside ToolJet
|
||||
- You can manipulate the data returned by the queries using **[Transformations](/docs/tutorial/transformations)**
|
||||
- You can also **[Run JavaScript code](/docs/data-sources/run-js)** or **[Run Python code](/docs/data-sources/run-py)** to perform custom behavior inside ToolJet
|
||||
:::
|
||||
|
||||
### Preview, Release and Share app
|
||||
|
|
@ -210,7 +210,7 @@ ToolJet application's User interface is constructed using Components like Tables
|
|||
3. **Share** option allows you to share the **released version** of the application with other users or you can also make the app **public** and anyone with the URL will be able to use the app.
|
||||
|
||||
:::tip
|
||||
You can control how much access to users have to your ToolJet apps and resources using **Org Management**.
|
||||
You can control how much access to users have to your ToolJet apps and resources using **[Org Management](/docs/tutorial/manage-users-groups)**.
|
||||
:::
|
||||
|
||||
## What Can I Do With ToolJet
|
||||
|
|
|
|||
23
docs/docs/how-to/intentionally-fail-js-query.md
Normal file
23
docs/docs/how-to/intentionally-fail-js-query.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
id: intentionally-fail-js-query
|
||||
title: Intentionally fail a RunJS query
|
||||
---
|
||||
|
||||
In this how-to guide, we will create a RunJS query that will throw an error.
|
||||
|
||||
- Create a RunJS query and paste the code below. We will use the constructor `ReferenceError` since it is used to create a range error instance.
|
||||
```js
|
||||
throw new ReferenceError('This is a reference error.');
|
||||
```
|
||||
|
||||
- Now, add a event handler to show an alert when the query fails. **Save** the query and **Run** it.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/failjs/failjs.gif" alt="Intentionally fail a RunJS query" />
|
||||
|
||||
</div>
|
||||
|
||||
:::info
|
||||
Most common use-case for intentionally failing a query is **debugging**.
|
||||
:::
|
||||
173
docs/docs/how-to/use-s3-presigned-url-to-upload-docs.md
Normal file
173
docs/docs/how-to/use-s3-presigned-url-to-upload-docs.md
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
---
|
||||
id: use-s3-signed-url-to-upload-docs
|
||||
title: Use S3 signed URL to upload documents
|
||||
---
|
||||
|
||||
# Use S3 signed URL to upload documents
|
||||
|
||||
In this how-to guide, you'll learn to upload documents to S3 buckets using the **S3 signed URL** from a ToolJet application.
|
||||
|
||||
For this guide, We are going to use one of the existing templates on ToolJet: **S3 File explorer**
|
||||
|
||||
:::info using Templates
|
||||
On ToolJet Dashboard, Click on the down arrow on the right of the **New App** button, from the dropdown choose the **Choose from template** option.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/template.png" alt="Use S3 pre-signed URL to upload documents: Choose template" width="700"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Once you've created a new app using the template, you'll be prompted to create a **new version** of the existing version. After creating a new version, you'll be able to make changes in the app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/newversion.png" alt="Use S3 pre-signed URL to upload documents: new version"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Go to the **datasource manager** on the left-sidebar, you'll find that the **AWS S3 datasource** is already added. All you need to do is update the datasource **credentials**.
|
||||
|
||||
:::tip
|
||||
Check the [AWS S3 datasource reference](/docs/data-sources/s3) to learn more about connnection and choosing your preferred authentication method.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/s3connect.png" alt="Use S3 pre-signed URL to upload documents: add datasource"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Once the datasource is connected successfully, go to the query manager and **Run** the **getBuckets** query. The operation selected in the getBuckets query is **List Buckets** which will fetch an array of all the buckets.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/getbuckets.png" alt="Use S3 pre-signed URL to upload documents: getBuckets query"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Running the **getBuckets** query will load all the buckets in the dropdown in the app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/dropdown.png" alt="Use S3 pre-signed URL to upload documents: loading buckets"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Select a **bucket** from the dropdown and click on the **Fetch files** button to list all the files from the selected bucket on the table. The **Fetch files** button has the event handler added that triggers the **s32** query, the **s32** query uses the **List objects in a bucket** operation, and the bucket field in the query gets the value dynamically from the dropdown.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/fetchfiles.png" alt="Use S3 pre-signed URL to upload documents: list objects in a bucket"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Let's go to the **uploadToS3** query and update the field values:
|
||||
- **Operation**: Signed URL for upload
|
||||
- **Bucket**: `{{components.dropdown1.value}}` this will fetch the dynamic value from the dropdown
|
||||
- **Key**: `{{components.filepicker1.file[0].name}}` this will get the file name from the filepickers exposed variables
|
||||
- **Expires in:** This sets an expiration time of URL, by default its `3600` seconds (1 hour)
|
||||
- **Content Type**: `{{components.filepicker1.file[0].type}}` this will get the file type from the filepickers exposed variables
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/upload.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Create two **RunJS** queries:
|
||||
- Create a **runjs1** query and copy-paste the code below. This query gets the **base64data** from the file picker and convert the file's `base64Data` to into `BLOB`, and returns the file object.
|
||||
```js
|
||||
const base64String = components.filepicker1.file[0].base64Data
|
||||
const decodedArray = new Uint8Array(atob(base64String).split('').map(c => c.charCodeAt(0)));
|
||||
const file = new Blob([decodedArray], { type: components.filepicker1.file[0].type });
|
||||
const fileName = components.filepicker1.file[0].name;
|
||||
const fileObj = new File([file], fileName);
|
||||
|
||||
return fileObj
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/runjs1.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Create another **runjs2** query and copy-paste the code below. This query gets the data(file object) returned by the first runjs query, the url returned by the **uploadToS3** query, and then makes PUT request.
|
||||
```js
|
||||
const file = queries.runjs2.data
|
||||
const url = queries.s31.data.url
|
||||
|
||||
fetch(url, {
|
||||
method: 'PUT',
|
||||
body: file,
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => console.log('Upload successful!'))
|
||||
.catch(error => console.error('Error uploading file:', error));
|
||||
```
|
||||
:::warning Enable Cross Origin Resource Sharing(CORS)
|
||||
- For the file to be uploaded successfully, you will need to add the CORS policies from the **Permissions** tab of your **Bucket** settings. Here's a sample CORS:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"AllowedHeaders": [
|
||||
"*"
|
||||
],
|
||||
"AllowedMethods": [
|
||||
"GET",
|
||||
"PUT",
|
||||
"POST"
|
||||
],
|
||||
"AllowedOrigins": [
|
||||
"*"
|
||||
],
|
||||
"ExposeHeaders": []
|
||||
}
|
||||
]
|
||||
```
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/runjs2.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Go to the **uploadToS3**, scroll down and add an event handler to the **uploadToS3** query. Select the **Query Success** event, **Run Query** as the action, and **runjs1** as the query to be triggered. **Save** the query.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/eventhandlerupload.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Let's go to the **runjs1** query and add the event handler to run a query on query success event, similar to how we did in the previous step. In the event handler, choose **runjs2** query. **Save** the query.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/eventhandlerrunjs2.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Now, let's go the final query **copySignedURL** that is connected to the table's action button. This query copy's the generated **Signed URL for download** onto the **clipboard**.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/copysigned.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Now that we have updated all the queries, and connected them through the event handlers. We can go ahead and pick a file from the file picker. Click on the file picker, select a file and then hit the **Upload file to S3** button.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/uploadbutton.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Once the button is clicked, the **uploadToS3** will triggered along with the **runjs1** and **runjs2** queries in sequence since we added them in the event handlers.
|
||||
|
||||
- You can go to the table and click on the **Copy signed URL** action button on the table, this will trigger the **copySignedURL** query and will copy the URL on the clipboard. You can go to another tab and paste the URL to open the file on the browser.
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ Permissions allow you to create and share resources to easily ensure what level
|
|||
Admins can invite **Users** to their workspaces and assign them to the **Groups** that have Permissions to access Apps, folders, or workspace variables.
|
||||
|
||||
:::info
|
||||
See **[Manage Users and Groups](/docs/tutorial/manage-users-groups)** to learn how to invite users to ToolJet.
|
||||
See **[Manage Users and Groups](/docs/tutorial/manage-users-groups)** to know more about managing users and groups on your workspace.
|
||||
:::
|
||||
|
||||
## Role-Based Access Control (RBAC) Glossary
|
||||
|
|
@ -18,4 +18,4 @@ See **[Manage Users and Groups](/docs/tutorial/manage-users-groups)** to learn h
|
|||
- **All Users** - Contains all the users in your workspace. When **New Users** are invited they are added to this group by default.
|
||||
- **Admins** - Contains all Admins in your workspace. Everyone added to this group will Permission to access all the ToolJet resources.
|
||||
- **Apps, Folder, Workspace Variables -** Resources that Admins can set permissions on.
|
||||
- **Permissions -** Create, Update and Delete.
|
||||
- **Permissions -** Create, Update and Delete.
|
||||
|
|
@ -295,3 +295,9 @@ If this parameter is not specified then PostgREST refuses authentication request
|
|||
:::info
|
||||
Please make sure that DB_URI is given in the format `postgrest://[USERNAME]:[PASSWORD]@[HOST]:[PORT]/[DATABASE]`
|
||||
:::
|
||||
|
||||
## User Session Expiry Time (Optional)
|
||||
|
||||
| variable | description |
|
||||
| ---------------- | ----------------------------------------------- |
|
||||
| USER_SESSION_EXPIRY | This variable controls the user session expiry time. By default, the session expires after 2 days. The variable expects the value in minutes. ex: USER_SESSION_EXPIRY = 120 which is 2 hours |
|
||||
|
|
@ -77,7 +77,7 @@ Similar to archiving a user's access, you can enable it again by clicking on **U
|
|||
|
||||
## Managing Groups
|
||||
|
||||
On ToolJet, Admins can create groups for users added in a workspace and grant them access to particular app(s) with specific permissions. To manage groups, just go to the **Workspace Settings** from the left-sidebar of the dashboard and click on the **Groups**.
|
||||
On ToolJet, Admins and Super Admins can create groups for users added in a workspace and grant them access to particular app(s) with specific permissions. To manage groups, just go to the **Workspace Settings** from the left-sidebar of the dashboard and click on the **Groups**.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -87,11 +87,16 @@ On ToolJet, Admins can create groups for users added in a workspace and grant th
|
|||
|
||||
### Group properties
|
||||
|
||||
Every group on ToolJet has three sections:
|
||||
Every group on ToolJet has **four** sections:
|
||||
|
||||
- [Apps](#apps)
|
||||
- [Users](#users)
|
||||
- [Permissions](#permissions)
|
||||
- [Datasources](#datasources)
|
||||
|
||||
#### Apps:
|
||||
|
||||
Admins can add or remove any number of apps for a group of users. To add an app to a group, select an app from the dropdown and click on `Add` button next to it. You can also set app permissions such as `View` or `Edit` for the group. You can set different permissions for different apps in a group.
|
||||
Admins and Super Admins can add or remove any number of apps for a group of users. To add an app to a group, select an app from the dropdown and click on `Add` button next to it. You can also set app permissions such as `View` or `Edit` for the group. You can set different permissions for different apps in a group.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -101,7 +106,7 @@ Admins can add or remove any number of apps for a group of users. To add an app
|
|||
|
||||
#### Users:
|
||||
|
||||
Admins can add or remove any numbers of users in a group. Just select a user from the dropdown and click on `Add` button to add it to a group. To delete a user from a group, click on `Delete` button next to it.
|
||||
Admins and Super Admins can add or remove any numbers of users in a group. Just select a user from the dropdown and click on `Add` button to add it to a group. To delete a user from a group, click on `Delete` button next to it.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -111,16 +116,30 @@ Admins can add or remove any numbers of users in a group. Just select a user fro
|
|||
|
||||
#### Permissions:
|
||||
|
||||
Admins can set granular permission like creating/deleting apps or creating folder for a group of users.
|
||||
Admins and Super Admins can set granular permission for the users added in that particular group, such as:
|
||||
- **Create** and **Delete** Apps
|
||||
- **Create**, **Update**, and **Delete** Folders
|
||||
- **Create**, **Update**, and **Delete** [Workspace Variables](/docs/tutorial/workspace-variables)
|
||||
- **Create** and **Delete** [Global Datasources](/docs/widgets/overview)
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tutorial/manage-users-groups/permissionsv2.png" alt="permissions" />
|
||||
<img className="screenshot-full" src="/img/tutorial/manage-users-groups/dspermission.png" alt="permissions" />
|
||||
|
||||
</div>
|
||||
|
||||
#### Datasources:
|
||||
|
||||
Only Admins and Super Admins can define what datasources can be **viewed** or **edited** by the users of that group.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tutorial/manage-users-groups/gdspermission.png" alt="permissions" />
|
||||
|
||||
</div>
|
||||
|
||||
:::tip
|
||||
All the activities performed by any Admin or any user in a workspace is logged in `Audit logs` - including any activity related with managing users and groups.
|
||||
All the activities performed by any Admin, Super Admin or any user in a workspace is logged in [Audit logs](/docs/Enterprise/audit_logs) - including any activity related with managing users and groups.
|
||||
:::
|
||||
|
||||
### Predefined Groups
|
||||
|
|
|
|||
|
|
@ -97,4 +97,23 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
| variable | Description |
|
||||
| ----------- | ----------- |
|
||||
| annotations | This variable is an array of objects, where each object represents an annotation added to an image. The object contains the following keys: type, x, y, width, height, text, and id |
|
||||
| annotations.`type` | There are two types of annotations: Rectangle and Point |
|
||||
| annotations.`x` | coordinates on x axis |
|
||||
| annotations.`y` | coordinates on y axis |
|
||||
| annotations.`width` | width of annotation |
|
||||
| annotations.`height` | height of annotation |
|
||||
| annotations.`text` | label selected for the annotation |
|
||||
| annotations.`id` | unique id of the annotation (system generated) |
|
||||
|
||||
The values can be accessed dynamically using `{{components.boundedbox1.annotations[0].text}}` or `{{components.boundedbox1.annotations[1].width}}`
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the bounding box component.
|
||||
|
|
|
|||
|
|
@ -92,4 +92,15 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| selected | If the "enable multiple selection" option is turned off, then the variable is an array of objects, and the first object holds the value of the selected button. However, if the "enable multiple selection" option is turned on, the variable type changes from an array to an object, and the selected button values are stored as a string within that object. The value can be accessed using `{{components.buttongroup1.selected[0]}}` or `{{components.buttongroup1.selected}}` |
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the button-group component.
|
||||
|
|
|
|||
|
|
@ -93,4 +93,20 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of button component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| click | You can regulate the click of a button via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.button1.click()` |
|
||||
| setText | button's text can be controlled using component specific action from any of the event handler. You can also use RunJS query to execute component specific actions: `await components.button1.setText('New Button Text')` |
|
||||
| disable | button can be disabled using the component specific action from any of the event handler. You can also use RunJS query to execute this action: `await components.button1.disable(true)` or `await components.button1.disable(false)` |
|
||||
| visibility | button's visibility can be switched using the component specific action from any of the event handler. You can also use RunJS query to execute this action: `await components.button1.disable(true)` or `await components.button1.disable(false)` |
|
||||
| loading | The loading state of the button can be set dynamically using the component specific actions from any of the event handler. You can also use this action from RunJS: `await components.button1.loading(true)` or `await components.button1.loading(false)` |
|
||||
|
|
@ -197,3 +197,16 @@ This format determines how the column header for each day in week view will be d
|
|||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| selectedEvent | This variable stores information about the event that has been chosen on the calendar component. This object comprises keys like **title**, **start**, **end**, **allDay**, and **color**, and they can be accessed dynamically through JS using the following syntax: `{{components.calendar1.selectedEvent.title}}` or `{{components.calendar1.selectedEvent.start}}` |
|
||||
| selectedSlots | The variable selectedSlots contains the values of the slots chosen on the calendar component. This object comprises keys like **slots**, **start**, **end**, **resourceId**, and **action**, and they can be accessed dynamically through JS using the following syntax: {{components.calendar1.selectedSlots.slots[0]}} or {{components.calendar1.selectedSlots.end}}. |
|
||||
| currentView | The currentView variable holds the type of view currently set on the calendar. The value updates when the user changes the view from the calendar header. Types of views supported: `month`, `week`, and `day`. The value can be accessed using `{{components.calendar1.currentView}}` |
|
||||
| currentDate | The currentDate variable holds the current date data. The date returned by the variable is in the `MM-DD-YYYY HH:mm:ss A Z` format. The value can be accessed using `{{components.calendar1.currentDate}}`|
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the calendar component.
|
||||
|
|
@ -387,3 +387,12 @@ Toggle on or off to control the visibility of the widget. You can programmatical
|
|||
### Disable
|
||||
|
||||
This is `off` by default, toggle `on` the switch to lock the widget and make it non-functional. You can also programmatically set the value by clicking on the `Fx` button next to it. If set to `{{true}}`, the widget will be locked and becomes non-functional. By default, its value is set to `{{false}}`.
|
||||
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -101,8 +101,16 @@ This is `off` by default, toggle `on` the switch to lock the widget and make it
|
|||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Actions
|
||||
## Exposed Variables
|
||||
|
||||
| Action | Description | Properties |
|
||||
| ----------- | ----------- | ------------------ |
|
||||
| `setChecked` | Set checkbox state. | pass status as parameter. ex: `components.checkbox1.setChecked(true)` |
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| value | This variable holds the boolean value `true` if the checkbox is checked and `false` if unchecked. You can access the value dynamically using JS: `{{components.checkbox1.value}}`|
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of checkbox component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| setChecked | You can change the status of the checkbox component using component specific action from within any event handler. Additionally, you have the option to trigger it from the RunJS query: `await components.checkbox1.setChecked(true)` or `await components.checkbox1.setChecked(false)` |
|
||||
|
|
@ -75,4 +75,13 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
|
||||
:::info
|
||||
Circular progress bar widget uses [react-circular-progress](https://github.com/kevinsqi/react-circular-progressbar) package. Check the repo for further more details about properties and styles.
|
||||
:::
|
||||
:::
|
||||
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -206,4 +206,14 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
| ----------- | ----------- |
|
||||
| Visibility | Toggle on or off to control the visibility of the widget. You can programmatically change its value by clicking on the `Fx` button next to it. If `{{false}}` the widget will not be visible after the app is deployed. By default, it's set to `{{true}}`. |
|
||||
| Disable | This is `off` by default, toggle `on` the switch to lock the widget and make it non-functional. You can also programmatically set the value by clicking on the `Fx` button next to it. If set to `{{true}}`, the widget will be locked and becomes non-functional. By default, its value is set to `{{false}}`. |
|
||||
| Border radius | Use this property to modify the border radius of the editor. The field expects only numerical value from `1` to `100`, default is `0`. |
|
||||
| Border radius | Use this property to modify the border radius of the editor. The field expects only numerical value from `1` to `100`, default is `0`. |
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| value | This variable holds the value whenever the user inputs anything on the code-editor . You can access the value dynamically using JS: `{{components.codeeditor1.value}}`|
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -81,4 +81,20 @@ Any property having `Fx` button next to its field can be **programmatically conf
|
|||
|
||||
<img className="screenshot-full" src="/img/widgets/color-picker/colorpickerinspector.png" alt="ToolJet - Widget Reference - Color Picker" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| selectedColorHex | This variable gets updated with HEX color code whenever a user selects a color from the color picker. You can access the value dynamically using JS: `{{components.colorpicker1.selectedColorHex}}`|
|
||||
| selectedColorRGB | This variable gets updated with RGB color code whenever a user selects a color from the color picker. You can access the value dynamically using JS: `{{components.colorpicker1.selectedColorRGB}}`|
|
||||
| selectedColorRGBA | This variable gets updated with RGBA color code whenever a user selects a color from the color picker. You can access the value dynamically using JS: `{{components.colorpicker1.selectedColorRGBA}}`|
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of color picker component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| setColor | Set a color on the color component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.colorpicker1.setColor('#64A07A')` |
|
||||
|
|
@ -8,7 +8,17 @@ Containers are used to group widgets together. You can move the desired number o
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/widgets/container/container.gif" alt="ToolJet - Widget Reference - Container" />
|
||||
<img className="screenshot-full" src="/img/widgets/container/container.png" alt="ToolJet - Widget Reference - Container" />
|
||||
|
||||
</div>
|
||||
|
||||
## Enabling vertical scroll on container
|
||||
|
||||
To enable the vertical scroll on the container, drag and place any component to the bottom grid of the container and the container will automatically enable the scrolling.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/widgets/container/scrollcontainer.png" alt="ToolJet - Widget Reference - Container" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -57,4 +67,13 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
@ -103,3 +103,14 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| data | This variable will hold the variables assigned inside the `code` for custom component. You can access the value dynamically using JS: `{{components.customcomponent1.data.title}}`|
|
||||
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -78,4 +78,16 @@ This property only accepts boolean values. If set to `{{true}}`, the widget will
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| endDate | This variable will hold the date of the endDate selected in the component. You can access the value dynamically using JS: `{{components.customcomponent1.data.title}}`|
|
||||
| startDate | This variable will hold the value assigned inside the `code` for custom component. You can access the value dynamically using JS: `{{components.customcomponent1.data.title}}`|
|
||||
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
@ -106,3 +106,13 @@ Use this property to modify the border radius of the date-picker. The field expe
|
|||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| value | This variable will hold the date selected on the component, the date value will be returned according to the format set in the datepicker properties. You can access the value dynamically using JS: `{{components.datepicker1.value}}`|
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
@ -53,4 +53,13 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
@ -137,4 +137,10 @@ Any property having `Fx` button next to its field can be **programmatically conf
|
|||
| Value | This variable holds the value of the currently selected item on the dropdown. Value can be accesed using `{{components.dropdown1.value}}` |
|
||||
| searchText | This variable is initially empty and will hold the value whenever the user searches on the dropdown. searchText's value can be accesed using`{{components.dropdown1.searchText}}` |
|
||||
| label | The variable label holds the label name of the dropdown. label's value can be accesed using`{{components.dropdown1.searchText}}` |
|
||||
| optionLabels | The optionLabels holds the option labels for the values of the dropdown. optionLabels can be accesed using`{{components.dropdown1.optionLabels}}` for all the option labels in the array form or `{{components.dropdown1.optionLabels[0]}}` for particular option label |
|
||||
| optionLabels | The optionLabels holds the option labels for the values of the dropdown. optionLabels can be accesed using`{{components.dropdown1.optionLabels}}` for all the option labels in the array form or `{{components.dropdown1.optionLabels[0]}}` for particular option label |
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
| Actions | Description |
|
||||
| -------- | ----------- |
|
||||
| selectOption | You can set an option on the dropdown component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.dropdown1.setOption(1)` |
|
||||
|
|
@ -165,8 +165,14 @@ Use this property to modify the border radius of the filepicker widget. The fiel
|
|||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Actions
|
||||
## Exposed Variables
|
||||
|
||||
| Action | Description | Properties |
|
||||
| ----------- | ----------- | ------------ |
|
||||
| `clearFiles()` | It will clear the selected files | None |
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| file | This variable holds the array of objects where each object represents the file loaded on the file picker component. Each object has the following keys: **name**, **type**, **content**, **dataURL**, **base64Data**, **parsedData**, **filePath**. The values can be accesed using `{{components.filepicker1.file[0].base64Data}}` |
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
| Actions | Description |
|
||||
| -------- | ----------- |
|
||||
| clearFiles() | You can clear the selected files on the filepicker component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.filepicker1.clearFiles()` |
|
||||
|
|
|
|||
|
|
@ -73,4 +73,21 @@ A Tooltip is often used to specify extra information about something when the us
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| data | This variable holds the data of all the components that are nested inside the form components. You can access the value dynamically using JS: `{{components.form1.data.numberinput1.value}}`|
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of form component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| resetForm | You can submit the form data via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.form1.resetForm()` |
|
||||
| submitForm | You can reset the form data via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await await components.form1.submitForm()` |
|
||||
|
||||
|
|
|
|||
|
|
@ -70,3 +70,11 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -62,3 +62,16 @@ Check [Action Reference](/docs/category/actions-reference) docs to get the detai
|
|||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of the component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| setVisibility | You can toggle the visibility of the icon component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.icon1.setVisibility(false)` |
|
||||
| click | You can trigger the click action on icon component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.icon1.click()` |
|
||||
|
|
@ -64,4 +64,12 @@ This is `off` by default, toggle `on` the switch to lock the widget and make it
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -104,4 +104,12 @@ This is `off` by default, toggle `on` the switch to lock the widget and make it
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -134,4 +134,15 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
| lastCardMovement | The variable `lastCardMovement` holds the properties of the card that has been recently moved from its original position. It holds the following data - `originColumnId`, `destinationColumnId`, `originCardIndex`, `destinationCardIndex` and an object `cardDetails` which includes `id`, `title`, `description` and `columnId` of the moved card. You can get the values using `{{components.kanbanboard1.lastCardMovement.cardDetails.title}}` or `{{components.kanbanboard1.lastCardMovement.destinationCardIndex}}` |
|
||||
| lastSelectedCard | The variable `lastSelectedCard` holds the `id`, `title`, `columnId`, and `description` of the last selected(clicked to view) card on the kanban. You can get the values using `{{components.kanban1.lastSelectedCard.columnId}}` |
|
||||
| lastUpdatedCard | The variable `lastUpdatedCard` holds the `id`, `title`, `description`, and `columnId` of the last updated card(using componenet specific action). You can get the values using `{{components.kanban1.lastUpdatedCard.columnId}}` |
|
||||
| lastCardUpdate | The variable `lastCardUpdate` holds the old an new values of the property that has been changed in the card(using componenet specific action). You can get the values using `{{components.kanban1.lastCardUpdate[0].title.oldValue}}` |
|
||||
| lastCardUpdate | The variable `lastCardUpdate` holds the old an new values of the property that has been changed in the card(using componenet specific action). You can get the values using `{{components.kanban1.lastCardUpdate[0].title.oldValue}}` |
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of kanban component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| updateCardData | Update the card data of kanban component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `components.kanban1.updateCardData('c1', {title: 'New Title'})` |
|
||||
| moveCard | Move a card from one column to other column on the kanban via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.kanban1.moveCard('card id,'column id')` ex: `await components.kanban1.moveCard('c1','r2')` |
|
||||
| addCard | Add a card onto the kanban via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.kanban1.addCard('c1', {title: 'New Title'})` |
|
||||
| deleteCard | Delete a card from the kanban via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.kanban1.deleteCard('card id')` ex: `await components.kanban1.deleteCard('c2')` |
|
||||
|
|
|
|||
|
|
@ -65,4 +65,17 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of link component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| click | You can trigger the click action of the link component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.link1.click()` |
|
||||
|
|
@ -137,4 +137,14 @@ Any property having `Fx` button next to its field can be **programmatically conf
|
|||
|
||||
Use `{{listItem.key}}` to display data on the nested widgets. Example: For displaying the images we used `{{listItem.avatar}}` where **avatar** is one of the key in the objects from the query result.
|
||||
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| data | This variable holds the data loaded onto the listview component. You can access the data of each row of the listview using `{{components.listview1.data["0"].text1.text}}` |
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -80,8 +80,21 @@ This is `off` by default, toggle `on` the switch to lock the widget and make it
|
|||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Actions
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| center | This variable will hold the latitude, longitude and the google map url value. |
|
||||
| center.`lat` | This variable holds the latitude value of the marker on the map component. You can access the value dynamically using JS: `{{components.map1.center.lat}}`|
|
||||
| centere.`lng` | This variable gets updated with RGB color code whenever a user selects a color from the color picker. You can access the value dynamically using JS: `{{components.map1.center.lng}}`|
|
||||
| center.`googleMapUrl` | This variable holds the URL of the location where the center marker is placed on the map component. You can access the value dynamically using JS: `{{components.map1.center.googleMapUrl}}`|
|
||||
| markers | The markers variable will hold the value only if `add new markers` is enabled from the map properties. Each marker is an object and will have `lat` and `lng` keys. Values can be accessed dynamically using `{{components.map1.markers[1].lat}}` |
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of map component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| setLocation | Set the marker's location on map using latitude and longitude values as parameteres via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as: `component.map1.setLocation(40.7128, -73.935242)` |
|
||||
|
||||
| Action | Description | Properties |
|
||||
| ----------- | ----------- | ------------------ |
|
||||
| `setLocation` | Set map's location. | Latitude and Longitude values as parameters. ex: `component.map1.setLocation(40.7128, -73.935242)` |
|
||||
|
|
@ -98,4 +98,18 @@ Toggle on or off to display the widget in mobile view. You can programmatically
|
|||
|
||||
:::info
|
||||
Trigger Button styles are only visible when **Use default trigger button** under Options is toggled on.
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of modal component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| open | Control the opening and closing of the modal componennt via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.modal1.open()` |
|
||||
| close | Control the closing of the modal componennt via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.modal1.close()` |
|
||||
|
|
@ -87,3 +87,21 @@ This is `off` by default, toggle `on` the switch to lock the widget and make it
|
|||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| values | This variable holds the values of the multiselect component in an array of objects where the objects are the options in the multiselect. You can access the value dynamically using JS: `{{components.multiselect1.values[1]}}` |
|
||||
|
||||
## Component specific actions (CSA)
|
||||
await components.multiselect1.clearSelections()
|
||||
await components.multiselect1.deselectOption(2)
|
||||
|
||||
Following actions of multselect component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| selectOption | Select an option on the multiselect component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.multiselect1.selectOption(3)` |
|
||||
| deselectOption | Deselect a selected option on the multiselect component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.multiselect1.deselectOption(3)` |
|
||||
| clearOptions | Clear all the selected options from the multiselect component via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as `await components.multiselect1.clearSelections(2,3)` |
|
||||
|
|
@ -94,4 +94,14 @@ Change the color of the number in number-input component by entering the Hex col
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| value | This variable updates whenever a user selects a number on the number input. You can access the value dynamically using JS: `{{components.numberinput1.value}}`|
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
@ -67,3 +67,13 @@ This is `off` by default, toggle `on` the switch to lock the widget and make it
|
|||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| totalPages | This variable holds the value of the `Number of Pages` set from the pagination component properties. You can access the value dynamically using JS: `{{components.pagination1.totalPages}}`|
|
||||
| currentPageIndex | This variable will hold the index of the currently selected option on the pagination component. You can access the value dynamically using JS: `{{components.pagination1.currentPageIndex}}`|
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
@ -79,4 +79,14 @@ This is `off` by default, toggle `on` the switch to lock the widget and make it
|
|||
|
||||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
:::
|
||||
|
||||
## Exposed variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| value | This variable holds the value entered by the user onto the password input component. You can access the value dynamically using JS: `{{components.passwordinput1.value}}`|
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -54,3 +54,12 @@ Under the <b>General</b> accordion, you can set the value in the string format.
|
|||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
|
||||
## Exposed variables
|
||||
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -69,3 +69,7 @@ Toggle on or off to control the visibility of the widget. You can programmatical
|
|||
### Disable
|
||||
|
||||
This is `off` by default, toggle `on` the switch to lock the widget and make it non-functional. You can also programmatically set the value by clicking on the `Fx` button next to it. If set to `{{true}}`, the widget will be locked and becomes non-functional. By default, its value is set to `{{false}}`.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
|
|
@ -94,8 +94,14 @@ This is `off` by default, toggle `on` the switch to lock the widget and make it
|
|||
|
||||
</div>
|
||||
|
||||
## Actions
|
||||
## Exposed variables
|
||||
|
||||
| Action | Description | Properties |
|
||||
| ----------- | ----------- | ------------------ |
|
||||
| selectOption | Select an option from the radio buttons. | `option` eg: `component.radiobutton1.selectOption('one')` |
|
||||
There are currently no exposed variables for the component.
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
Following actions of color picker component can be controlled using the component specific actions(CSA):
|
||||
|
||||
| Actions | Description |
|
||||
| ----------- | ----------- |
|
||||
| selectOption | Select an option from the radio buttons via a component-specific action within any event handler. Additionally, you have the option to employ a RunJS query to execute component-specific actions such as: `await components.radiobutton1.selectOption('one')` |
|
||||
|
|
@ -74,3 +74,13 @@ Set the visivlity of the slider programmatically. The default value is `{{true}}
|
|||
:::info
|
||||
Any property having `Fx` button next to its field can be **programmatically configured**.
|
||||
:::
|
||||
|
||||
## Exposed Variables
|
||||
|
||||
| Variables | Description |
|
||||
| ----------- | ----------- |
|
||||
| value | This variable holds an object when `two handles` option is disabled or an array when `two handles` is enabled from the component properties. The value can be accessed dynamically using JS: `{{components.rangeslider1.value}}` or `{{components.rangeslider1.value[1]}}` |
|
||||
|
||||
## Component specific actions (CSA)
|
||||
|
||||
There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue