diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml
index e940e6fa10..6e886f3011 100644
--- a/.github/workflows/budibase_ci.yml
+++ b/.github/workflows/budibase_ci.yml
@@ -7,6 +7,7 @@ on:
branches:
- master
- develop
+ - new-design-ui
pull_request:
branches:
- master
@@ -59,3 +60,19 @@ jobs:
with:
install: false
command: yarn test:e2e:ci
+
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v1
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ aws-region: eu-west-1
+
+ - name: Upload to S3
+ if: github.ref == 'refs/heads/new-design-ui'
+ run: |
+ tar -czvf new_ui.tar.gz packages/server/builder/assets packages/server/builder/index.html
+ aws s3 cp new_ui.tar.gz s3://prod-budi-app-assets/beta:design_ui/
+ aws s3 cp packages/client/dist/budibase-client.js s3://prod-budi-app-assets/beta:design_ui/budibase-client.js
+ aws cloudfront create-invalidation --distribution-id E3ELKP4RCEHVLW --paths "/beta:design_ui/*"
+
diff --git a/.github/workflows/release-develop.yml b/.github/workflows/release-develop.yml
index 4502482b23..631308d945 100644
--- a/.github/workflows/release-develop.yml
+++ b/.github/workflows/release-develop.yml
@@ -21,7 +21,8 @@ env:
# Posthog token used by ui at build time
POSTHOG_TOKEN: phc_uDYOfnFt6wAbBAXkC6STjcrTpAFiWIhqgFcsC1UVO5F
INTERCOM_TOKEN: ${{ secrets.INTERCOM_TOKEN }}
- PERSONAL_ACCESS_TOKEN : ${{ secrets.PERSONAL_ACCESS_TOKEN }}
+ PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
+ FEATURE_PREVIEW_URL: https://budirelease.live
jobs:
release:
@@ -124,4 +125,4 @@ jobs:
with:
webhook-url: ${{ secrets.PROD_DEPLOY_WEBHOOK_URL }}
content: "Release Env Deployment Complete: ${{ env.RELEASE_VERSION }} deployed to Budibase Release Env."
- embed-title: ${{ env.RELEASE_VERSION }}
\ No newline at end of file
+ embed-title: ${{ env.RELEASE_VERSION }}
diff --git a/charts/budibase/values.yaml b/charts/budibase/values.yaml
index 455d3251a8..2734202fff 100644
--- a/charts/budibase/values.yaml
+++ b/charts/budibase/values.yaml
@@ -103,7 +103,7 @@ globals:
google:
clientId: ""
secret: ""
- automationMaxIterations: "500"
+ automationMaxIterations: "200"
createSecrets: true # creates an internal API key, JWT secrets and redis password for you
diff --git a/lerna.json b/lerna.json
index cb7bd2c0f9..d9d78eb964 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
{
- "version": "1.0.212-alpha.0",
+ "version": "1.0.212-alpha.10",
"npmClient": "yarn",
"packages": [
"packages/*"
diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json
index 8217599f77..116db847b0 100644
--- a/packages/backend-core/package.json
+++ b/packages/backend-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/backend-core",
- "version": "1.0.212-alpha.0",
+ "version": "1.0.212-alpha.10",
"description": "Budibase backend core libraries used in server and worker",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
@@ -20,7 +20,7 @@
"test:watch": "jest --watchAll"
},
"dependencies": {
- "@budibase/types": "^1.0.212-alpha.0",
+ "@budibase/types": "^1.0.212-alpha.10",
"@techpass/passport-openidconnect": "0.3.2",
"aws-sdk": "2.1030.0",
"bcrypt": "5.0.1",
diff --git a/packages/backend-core/src/db/utils.ts b/packages/backend-core/src/db/utils.ts
index 125d7a81da..adaf33af98 100644
--- a/packages/backend-core/src/db/utils.ts
+++ b/packages/backend-core/src/db/utils.ts
@@ -92,13 +92,17 @@ export function generateGlobalUserID(id?: any) {
/**
* Gets parameters for retrieving users.
*/
-export function getGlobalUserParams(globalId: any, otherProps = {}) {
+export function getGlobalUserParams(globalId: any, otherProps: any = {}) {
if (!globalId) {
globalId = ""
}
+ const startkey = otherProps?.startkey
return {
...otherProps,
- startkey: `${DocumentTypes.USER}${SEPARATOR}${globalId}`,
+ // need to include this incase pagination
+ startkey: startkey
+ ? startkey
+ : `${DocumentTypes.USER}${SEPARATOR}${globalId}`,
endkey: `${DocumentTypes.USER}${SEPARATOR}${globalId}${UNICODE_MAX}`,
}
}
@@ -433,6 +437,26 @@ export const getPlatformUrl = async (opts = { tenantAware: true }) => {
return platformUrl
}
+export function pagination(
+ data: any[],
+ pageSize: number,
+ { paginate, property } = { paginate: true, property: "_id" }
+) {
+ if (!paginate) {
+ return { data, hasNextPage: false }
+ }
+ const hasNextPage = data.length > pageSize
+ let nextPage = undefined
+ if (hasNextPage) {
+ nextPage = property ? data[pageSize]?.[property] : data[pageSize]?._id
+ }
+ return {
+ data: data.slice(0, pageSize),
+ hasNextPage,
+ nextPage,
+ }
+}
+
export async function getScopedConfig(db: any, params: any) {
const configDoc = await getScopedFullConfig(db, params)
return configDoc && configDoc.config ? configDoc.config : configDoc
diff --git a/packages/backend-core/src/objectStore/index.ts b/packages/backend-core/src/objectStore/index.ts
index 9bb0760f5b..a7e0b0c134 100644
--- a/packages/backend-core/src/objectStore/index.ts
+++ b/packages/backend-core/src/objectStore/index.ts
@@ -294,6 +294,16 @@ export const uploadDirectory = async (
await Promise.all(uploads)
}
+exports.downloadTarballDirect = async (url: string, path: string) => {
+ path = sanitizeKey(path)
+ const response = await fetch(url)
+ if (!response.ok) {
+ throw new Error(`unexpected response ${response.statusText}`)
+ }
+
+ await streamPipeline(response.body, zlib.Unzip(), tar.extract(path))
+}
+
export const downloadTarball = async (url: any, bucketName: any, path: any) => {
bucketName = sanitizeBucket(bucketName)
path = sanitizeKey(path)
diff --git a/packages/backend-core/src/users.js b/packages/backend-core/src/users.js
index 4acccda2a0..0c1350a674 100644
--- a/packages/backend-core/src/users.js
+++ b/packages/backend-core/src/users.js
@@ -1,5 +1,6 @@
const { ViewNames } = require("./db/utils")
const { queryGlobalView } = require("./db/views")
+const { UNICODE_MAX } = require("./db/constants")
/**
* Given an email address this will use a view to search through
@@ -19,3 +20,24 @@ exports.getGlobalUserByEmail = async email => {
return response
}
+
+/**
+ * Performs a starts with search on the global email view.
+ */
+exports.searchGlobalUsersByEmail = async (email, opts) => {
+ if (typeof email !== "string") {
+ throw new Error("Must provide a string to search by")
+ }
+ const lcEmail = email.toLowerCase()
+ // handle if passing up startkey for pagination
+ const startkey = opts && opts.startkey ? opts.startkey : lcEmail
+ let response = await queryGlobalView(ViewNames.USER_BY_EMAIL, {
+ ...opts,
+ startkey,
+ endkey: `${lcEmail}${UNICODE_MAX}`,
+ })
+ if (!response) {
+ response = []
+ }
+ return Array.isArray(response) ? response : [response]
+}
diff --git a/packages/bbui/package.json b/packages/bbui/package.json
index d3101946f3..0c590eccf4 100644
--- a/packages/bbui/package.json
+++ b/packages/bbui/package.json
@@ -1,7 +1,7 @@
{
"name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.",
- "version": "1.0.212-alpha.0",
+ "version": "1.0.212-alpha.10",
"license": "MPL-2.0",
"svelte": "src/index.js",
"module": "dist/bbui.es.js",
@@ -38,7 +38,7 @@
],
"dependencies": {
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
- "@budibase/string-templates": "^1.0.212-alpha.0",
+ "@budibase/string-templates": "^1.0.212-alpha.10",
"@spectrum-css/actionbutton": "^1.0.1",
"@spectrum-css/actiongroup": "^1.0.1",
"@spectrum-css/avatar": "^3.0.2",
diff --git a/packages/builder/cypress.json b/packages/builder/cypress.json
index 06bf558946..46f85a52c8 100644
--- a/packages/builder/cypress.json
+++ b/packages/builder/cypress.json
@@ -13,7 +13,7 @@
"HOST_IP": ""
},
"retries": {
- "runMode": 2,
+ "runMode": 1,
"openMode": 0
}
}
diff --git a/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js b/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js
index 38ae881db8..32f62efe1f 100644
--- a/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js
+++ b/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js
@@ -16,18 +16,15 @@ filterTests(['all'], () => {
it("should add form with multi select picker, containing 5 options", () => {
cy.navigateToFrontend()
- cy.wait(500)
// Add data provider
- cy.get(interact.CATEGORY_DATA).click()
+ cy.get(interact.CATEGORY_DATA, { timeout: 500 }).click()
cy.get(interact.COMPONENT_DATA_PROVIDER).click()
cy.get(interact.DATASOURCE_PROP_CONTROL).click()
cy.get(interact.DROPDOWN).contains("Multi Data").click()
- cy.wait(500)
// Add Form with schema to match table
cy.addComponent("Form", "Form")
cy.get(interact.DATASOURCE_PROP_CONTROL).click()
cy.get(interact.DROPDOWN).contains("Multi Data").click()
- cy.wait(500)
// Add multi-select picker to form
cy.addComponent("Form", "Multi-select Picker").then(componentId => {
cy.get(interact.DATASOURCE_FIELD_CONTROL).type("Test Data").type("{enter}")
diff --git a/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js b/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js
new file mode 100644
index 0000000000..c615b2b4e6
--- /dev/null
+++ b/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js
@@ -0,0 +1,131 @@
+import filterTests from "../../support/filterTests"
+const interact = require('../../support/interact')
+
+filterTests(["smoke", "all"], () => {
+ context("Account Portals", () => {
+
+ const bbUserEmail = "bbuser@test.com"
+
+ before(() => {
+ cy.login()
+ cy.deleteApp("Cypress Tests")
+ cy.createApp("Cypress Tests")
+
+ // Create new user
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 1000})
+ cy.createUser(bbUserEmail)
+ cy.contains("bbuser").click()
+ cy.wait(500)
+
+ // Reset password
+ cy.get(".spectrum-ActionButton-label", { timeout: 2000 }).contains("Force password reset").click({ force: true })
+
+ cy.get(".spectrum-Dialog-grid")
+ .find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('pwd')
+
+ cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").click({ force: true })
+
+ // Login as new user and set password
+ cy.logOut()
+ cy.get('@pwd').then((pwd) => {
+ cy.login(bbUserEmail, pwd)
+ })
+
+ for (let i = 0; i < 2; i++) {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test")
+ }
+ cy.get(interact.SPECTRUM_BUTTON).contains("Reset your password").click({ force: true })
+ cy.logoutNoAppGrid()
+ })
+
+ it("should verify Admin Portal", () => {
+ cy.login()
+ cy.contains("Users").click()
+ cy.contains("bbuser").click()
+
+ // Enable Development & Administration access
+ cy.wait(500)
+ for (let i = 4; i < 6; i++) {
+ cy.get(interact.FIELD).eq(i).within(() => {
+ cy.get(interact.SPECTRUM_SWITCH_INPUT).click({ force: true })
+ cy.get(interact.SPECTRUM_SWITCH_INPUT).should('be.enabled')
+ })
+ }
+ bbUserLogin()
+
+ // Verify available options for Admin portal
+ cy.get(".spectrum-SideNav")
+ .should('contain', 'Apps')
+ //.and('contain', 'Usage')
+ .and('contain', 'Users')
+ .and('contain', 'Auth')
+ .and('contain', 'Email')
+ .and('contain', 'Organisation')
+ .and('contain', 'Theming')
+ .and('contain', 'Update')
+ //.and('contain', 'Upgrade')
+
+ cy.logOut()
+ })
+
+ it("should verify Development Portal", () => {
+ // Only Development access should be enabled
+ cy.login()
+ cy.contains("Users").click()
+ cy.contains("bbuser").click()
+ cy.wait(500)
+ cy.get(interact.FIELD).eq(5).within(() => {
+ cy.get(interact.SPECTRUM_SWITCH_INPUT).click({ force: true })
+ })
+
+ bbUserLogin()
+
+ // Verify available options for Admin portal
+ cy.get(interact.SPECTRUM_SIDENAV)
+ .should('contain', 'Apps')
+ //.and('contain', 'Usage')
+ .and('not.contain', 'Users')
+ .and('not.contain', 'Auth')
+ .and('not.contain', 'Email')
+ .and('not.contain', 'Organisation')
+ .and('contain', 'Theming')
+ .and('not.contain', 'Update')
+ .and('not.contain', 'Upgrade')
+
+ cy.logOut()
+ })
+
+ it("should verify Standard Portal", () => {
+ // Development access should be disabled (Admin access is already disabled)
+ cy.login()
+ cy.contains("Users").click()
+ cy.contains("bbuser").click()
+ cy.wait(500)
+ cy.get(interact.FIELD).eq(4).within(() => {
+ cy.get(interact.SPECTRUM_SWITCH_INPUT).click({ force: true })
+ })
+
+ bbUserLogin()
+
+ // Verify Standard Portal
+ cy.get(interact.SPECTRUM_SIDENAV).should('not.exist') // No config sections
+ cy.get(interact.CREATE_APP_BUTTON).should('not.exist') // No create app button
+ cy.get(".app").should('not.exist') // No apps -> no roles assigned to user
+ cy.get(interact.CONTAINER).should('contain', bbUserEmail) // Message containing users email
+
+ cy.logoutNoAppGrid()
+ })
+
+ const bbUserLogin = () => {
+ // Login as bbuser
+ cy.logOut()
+ cy.login(bbUserEmail, "test")
+ }
+
+ after(() => {
+ cy.login()
+ // Delete BB user
+ cy.deleteUser(bbUserEmail)
+ })
+ })
+})
diff --git a/packages/builder/cypress/integration/createUserAndRoles.spec.js b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js
similarity index 50%
rename from packages/builder/cypress/integration/createUserAndRoles.spec.js
rename to packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js
index d47a96ed8d..3c23086136 100644
--- a/packages/builder/cypress/integration/createUserAndRoles.spec.js
+++ b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js
@@ -1,28 +1,34 @@
-import filterTests from "../support/filterTests"
-const interact = require('../support/interact')
+import filterTests from "../../support/filterTests"
+const interact = require('../../support/interact')
filterTests(["smoke", "all"], () => {
- context("Create a User and Assign Roles", () => {
+ context("User Management", () => {
before(() => {
cy.login()
cy.deleteApp("Cypress Tests")
cy.createApp("Cypress Tests")
})
- it("should create a user", () => {
- cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(1000)
+ it("should create a user via basic onboarding", () => {
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 1000})
cy.createUser("bbuser@test.com")
cy.get(interact.SPECTRUM_TABLE).should("contain", "bbuser")
})
- it("should confirm there is No Access for a New User", () => {
- // Click into the user
+ it("should confirm basic permission for a New User", () => {
+ // Basic permission = development & administraton disabled
cy.contains("bbuser").click()
- cy.wait(500)
- // Get No Access table - Confirm it has apps in it
- cy.get(interact.SPECTRUM_TABLE).eq(1).should("not.contain", "No rows found")
- // Get Configure Roles table - Confirm it has no apps
+ // Confirm development and admin access are disabled
+ for (let i = 4; i < 6; i++) {
+ cy.wait(500)
+ cy.get(interact.FIELD).eq(i).within(() => {
+ //cy.get(interact.SPECTRUM_SWITCH_INPUT).should('be.disabled')
+ cy.get(".spectrum-Switch-switch").should('not.be.checked')
+ })
+ }
+ // Existing apps appear within the No Access table
+ cy.get(interact.SPECTRUM_TABLE, { timeout: 500 }).eq(1).should("not.contain", "No rows found")
+ // Configure roles table should not contain apps
cy.get(interact.SPECTRUM_TABLE).eq(0).contains("No rows found")
})
@@ -40,20 +46,16 @@ filterTests(["smoke", "all"], () => {
cy.createApp(name)
} else {
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
- cy.get(interact.CREATE_APP_BUTTON).click({ force: true })
+ cy.get(interact.CREATE_APP_BUTTON, { timeout: 1000 }).click({ force: true })
cy.createAppFromScratch(name)
}
}
}
})
// Navigate back to the user
- cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 500})
cy.get(interact.SPECTRUM_SIDENAV).contains("Users").click()
- cy.wait(500)
- cy.get(interact.SPECTRUM_TABLE).contains("bbuser").click()
- cy.wait(1000)
+ cy.get(interact.SPECTRUM_TABLE, { timeout: 500 }).contains("bbuser").click()
for (let i = 0; i < 3; i++) {
cy.get(interact.SPECTRUM_TABLE, { timeout: 3000})
.eq(1)
@@ -62,31 +64,28 @@ filterTests(["smoke", "all"], () => {
.find(interact.SPECTRUM_TABLE_CELL)
.eq(0)
.click()
- cy.wait(500)
- cy.get(interact.SPECTRUM_DIALOG_GRID)
+ cy.get(interact.SPECTRUM_DIALOG_GRID, { timeout: 500 })
.contains("Choose an option")
.click()
.then(() => {
- cy.wait(1000)
if (i == 0) {
- cy.get(interact.SPECTRUM_MENU).contains("Admin").click({ force: true })
+ cy.get(interact.SPECTRUM_MENU, { timeout: 1000 }).contains("Admin").click({ force: true })
}
else if (i == 1) {
- cy.get(interact.SPECTRUM_MENU).contains("Power").click({ force: true })
+ cy.get(interact.SPECTRUM_MENU, { timeout: 1000 }).contains("Power").click({ force: true })
}
else if (i == 2) {
- cy.get(interact.SPECTRUM_MENU).contains("Basic").click({ force: true })
+ cy.get(interact.SPECTRUM_MENU, { timeout: 1000 }).contains("Basic").click({ force: true })
}
- cy.wait(1000)
- cy.get(interact.SPECTRUM_BUTTON)
+ cy.get(interact.SPECTRUM_BUTTON, { timeout: 1000 })
.contains("Update role")
.click({ force: true })
})
cy.reload()
+ cy.wait(1000)
}
// Confirm roles exist within Configure roles table
- cy.wait(2000)
- cy.get(interact.SPECTRUM_TABLE)
+ cy.get(interact.SPECTRUM_TABLE, { timeout: 2000 })
.eq(0)
.within(assginedRoles => {
expect(assginedRoles).to.contain("Admin")
@@ -112,21 +111,19 @@ filterTests(["smoke", "all"], () => {
.click()
.then(() => {
cy.get(interact.SPECTRUM_PICKER).eq(1).click({ force: true })
- cy.wait(500)
- cy.get(interact.SPECTRUM_POPOVER).contains("No Access").click()
+ cy.get(interact.SPECTRUM_POPOVER, { timeout: 500 }).contains("No Access").click()
})
cy.get(interact.SPECTRUM_BUTTON)
.contains("Update role")
.click({ force: true })
- cy.wait(1000)
}
})
// Confirm Configure roles table no longer has any apps in it
- cy.get(interact.SPECTRUM_TABLE).eq(0).contains("No rows found")
+ cy.get(interact.SPECTRUM_TABLE, { timeout: 1000 }).eq(0).contains("No rows found")
})
}
- it("should enable Developer access", () => {
+ it("should enable Developer access and verify application access", () => {
// Enable Developer access
cy.get(interact.FIELD)
.eq(4)
@@ -158,15 +155,15 @@ filterTests(["smoke", "all"], () => {
})
})
- it("should disable Developer access", () => {
+ it("should disable Developer access and verify application access", () => {
// Disable Developer access
- cy.get(".field")
+ cy.get(interact.FIELD)
.eq(4)
.within(() => {
cy.get(".spectrum-Switch-input").click({ force: true })
})
// Configure roles table should now be empty
- cy.get(".container")
+ cy.get(interact.CONTAINER)
.contains("Configure roles")
.parent()
.within(() => {
@@ -174,22 +171,64 @@ filterTests(["smoke", "all"], () => {
})
})
+ it("Should edit user details within user details page", () => {
+ // Add First name
+ cy.get(interact.FIELD, { timeout: 500 }).eq(2).within(() => {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 500 }).type("bb")
+ })
+ // Add Last name
+ cy.get(interact.FIELD).eq(3).within(() => {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).type("test")
+ })
+ cy.get(interact.FIELD).eq(0).click()
+ // Reload page
+ cy.reload()
+
+ // Confirm details have been saved
+ cy.get(interact.FIELD, { timeout: 1000 }).eq(2).within(() => {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', "bb")
+ })
+ cy.get(interact.FIELD).eq(3).within(() => {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 500 }).should('have.value', "test")
+ })
+ })
+
+ it("should reset the users password", () => {
+ cy.get(interact.REGENERATE, { timeout: 500 }).contains("Force password reset").click({ force: true })
+
+ // Reset password modal
+ cy.get(interact.SPECTRUM_DIALOG_GRID)
+ .find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('pwd')
+ cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").click({ force: true })
+
+ // Logout, then login with new password
+ cy.logOut()
+ cy.get('@pwd').then((pwd) => {
+ cy.login("bbuser@test.com", pwd)
+ })
+
+ // Reset password screen
+ for (let i = 0; i < 2; i++) {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test")
+ }
+ cy.get(interact.SPECTRUM_BUTTON).contains("Reset your password").click({ force: true })
+
+ // Confirm user logged in afer password change
+ cy.get(".avatar > .icon").click({ force: true })
+
+ cy.get(".spectrum-Menu-item").contains("Update user information").click({ force: true })
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
+ .eq(0)
+ .invoke('val').should('eq', 'bbuser@test.com')
+
+ // Logout and login as previous user
+ cy.logoutNoAppGrid()
+ cy.login()
+ })
+
it("should delete a user", () => {
- // Click Delete user button
- cy.get(interact.SPECTRUM_BUTTON)
- .contains("Delete user")
- .click({ force: true })
- .then(() => {
- // Confirm deletion within modal
- cy.wait(500)
- cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
- cy.get(interact.SPECTRUM_BUTTON)
- .contains("Delete user")
- .click({ force: true })
- cy.wait(4000)
- })
- })
- cy.get(interact.SPECTRUM_TABLE).should("not.have.text", "bbuser")
+ cy.deleteUser("bbuser@test.com")
+ cy.get(interact.SPECTRUM_TABLE, { timeout: 4000 }).should("not.have.text", "bbuser")
})
})
})
diff --git a/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js b/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js
new file mode 100644
index 0000000000..7827275620
--- /dev/null
+++ b/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js
@@ -0,0 +1,108 @@
+import filterTests from "../../support/filterTests"
+const interact = require('../../support/interact')
+
+filterTests(["smoke", "all"], () => {
+ context("User Settings Menu", () => {
+
+ before(() => {
+ cy.login()
+ })
+
+ it("should update user information via user settings menu", () => {
+ const fname = "test"
+ const lname = "user"
+
+ cy.visit(`${Cypress.config().baseUrl}/builder`)
+ cy.updateUserInformation(fname, lname)
+
+ // Go to user info and confirm name update
+ cy.contains("Users").click()
+ cy.contains("test@test.com").click()
+
+ cy.get(interact.FIELD, { timeout: 1000 }).eq(2).within(() => {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', fname)
+ })
+ cy.get(interact.FIELD).eq(3).within(() => {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', lname)
+ })
+ })
+
+ it("should allow copying of the users API key", () => {
+ cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true })
+ cy.get(interact.SPECTRUM_MENU_ITEM).contains("View API key").click({ force: true })
+ cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => {
+ cy.get(interact.SPECTRUM_ICON).click({force: true})
+ })
+ // There may be timing issues with this on the smoke build
+ cy.wait(500)
+ cy.get(".spectrum-Toast-content")
+ .contains("URL copied to clipboard")
+ .should("be.visible")
+ })
+
+ it("should allow API key regeneration", () => {
+ // Get initial API key value
+ cy.get(interact.SPECTRUM_DIALOG_CONTENT)
+ .find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('keyOne')
+
+ // Click re-generate key button
+ cy.get("button").contains("Re-generate key").click({ force: true })
+
+ // Verify API key was changed
+ cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => {
+ cy.get('@keyOne').then((keyOne) => {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').should('not.eq', keyOne)
+ })
+ })
+ cy.closeModal()
+ })
+
+ it("should update password", () => {
+ // Access Update password modal
+ cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true })
+ cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true })
+
+ // Enter new password and update
+ cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
+ for (let i = 0; i < 2; i++) {
+ // password set to 'newpwd'
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("newpwd")
+ }
+ cy.get("button").contains("Update password").click({ force: true })
+ })
+
+ // Logout & in with new password
+ cy.logOut()
+ cy.login("test@test.com", "newpwd")
+ })
+
+ it("should open and close developer mode", () => {
+ cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true })
+
+ // Close developer mode & verify
+ cy.get(interact.SPECTRUM_MENU_ITEM).contains("Close developer mode").click({ force: true })
+ cy.get(interact.SPECTRUM_SIDENAV).should('not.exist') // No config sections
+ cy.get(interact.CREATE_APP_BUTTON).should('not.exist') // No create app button
+ cy.get(".app").should('not.exist') // At least one app should be available
+
+ // Open developer mode & verify
+ cy.get(".avatar > .icon").click({ force: true })
+ cy.get(interact.SPECTRUM_MENU_ITEM).contains("Open developer mode").click({ force: true })
+ cy.get(interact.SPECTRUM_SIDENAV).should('exist') // config sections available
+ cy.get(interact.CREATE_APP_BUTTON).should('exist') // create app button available
+ cy.get(interact.APP_TABLE).should('exist') // App table available
+ })
+
+ after(() => {
+ // Change password back to original value
+ cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true })
+ cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true })
+ cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
+ for (let i = 0; i < 2; i++) {
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test")
+ }
+ cy.get("button").contains("Update password").click({ force: true })
+ })
+ })
+ })
+})
diff --git a/packages/builder/cypress/integration/appOverview.spec.js b/packages/builder/cypress/integration/appOverview.spec.js
index 4b9d072338..d718f95b9f 100644
--- a/packages/builder/cypress/integration/appOverview.spec.js
+++ b/packages/builder/cypress/integration/appOverview.spec.js
@@ -136,7 +136,6 @@ filterTests(["all"], () => {
.within(() => {
cy.get(".confirm-wrap button").click({ force: true })
})
- cy.wait(1000)
cy.visit(`${Cypress.config().baseUrl}/builder`)
cy.get(".appTable .app-row-actions button")
@@ -158,12 +157,9 @@ filterTests(["all"], () => {
.contains("Manage")
.eq(0)
.click({ force: true })
- cy.wait(1000)
- cy.get(".app-overview-actions-icon").within(() => {
- cy.get(".spectrum-Icon").click({ force: true })
- })
- cy.get(".spectrum-Menu").contains("Edit icon").click()
+ cy.get(".edit-hover", { timeout: 1000 }).eq(0).click({ force: true })
// Select random icon
+ cy.wait(400)
cy.get(".grid").within(() => {
cy.get(".icon-item")
.eq(Math.floor(Math.random() * 23) + 1)
@@ -182,6 +178,7 @@ filterTests(["all"], () => {
cy.get("@iconChange").its("response.statusCode").should("eq", 200)
// Confirm icon has changed from default
// Confirm colour has been applied
+ cy.get(".spectrum-ActionButton-label").contains("Back").click({ force: true })
cy.get(".appTable", { timeout: 2000 }).within(() => {
cy.get("[aria-label]")
.eq(0)
@@ -265,10 +262,9 @@ filterTests(["all"], () => {
//Downgrade the app for the test
cy.alterAppVersion(appId, "0.0.1-alpha.0").then(() => {
cy.reload()
- cy.wait(1000)
cy.log("Current deployment version: " + clientPackage.version)
- cy.get(".version-status a").contains("Update").click()
+ cy.get(".version-status a", { timeout: 1000 }).contains("Update").click()
cy.get(".spectrum-Tabs-item.is-selected").contains("Settings")
cy.get(".version-section .page-action button")
@@ -336,8 +332,7 @@ filterTests(["all"], () => {
})
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(1000)
- cy.get(".appTable .app-row-actions button")
+ cy.get(".appTable .app-row-actions button", { timeout: 1000 })
.contains("Manage")
.eq(0)
.click({ force: true })
@@ -345,8 +340,7 @@ filterTests(["all"], () => {
cy.get(".spectrum-Tabs-item.is-selected").contains("Settings")
cy.get(".details-section .page-action .spectrum-Button").scrollIntoView()
- cy.wait(1000)
- cy.get(".details-section .page-action .spectrum-Button").should(
+ cy.get(".details-section .page-action .spectrum-Button", { timeout: 1000 }).should(
"be.disabled"
)
})
@@ -375,27 +369,21 @@ filterTests(["all"], () => {
.contains("Copy App ID")
.click({ force: true })
})
-
+
cy.get(".spectrum-Toast-content")
- .contains("App ID copied to clipboard.")
- .should("be.visible")
+ .contains("App ID copied to clipboard.")
+ .should("be.visible")
})
- it("Should allow unpublishing of the application", () => {
+ it("Should allow unpublishing of the application via the Unpublish link", () => {
cy.visit(`${Cypress.config().baseUrl}/builder`)
cy.get(".appTable .app-row-actions button")
.contains("Manage")
.eq(0)
.click({ force: true })
- cy.get(".app-overview-actions-icon > .icon").click({ force: true })
- cy.get("[data-cy='app-overview-menu-popover']")
- .eq(0)
- .within(() => {
- cy.get(".spectrum-Menu-item")
- .contains("Unpublish")
- .click({ force: true })
- cy.wait(500)
+ cy.get(`[data-cy="app-status"]`).within(() => {
+ cy.contains("Unpublish").click({ force: true })
})
cy.get("[data-cy='unpublish-modal']")
@@ -406,9 +394,8 @@ filterTests(["all"], () => {
cy.get(".overview-tab [data-cy='app-status']").within(() => {
cy.get(".status-display").contains("Unpublished")
- cy.get(".status-display .icon svg[aria-label='GlobeStrike']").should(
- "exist"
- )
+ cy.get(".status-display .icon svg[aria-label='GlobeStrike']")
+ .should("exist")
})
})
diff --git a/packages/builder/cypress/integration/appPublishWorkflow.spec.js b/packages/builder/cypress/integration/appPublishWorkflow.spec.js
index f0a7dd791a..a431051075 100644
--- a/packages/builder/cypress/integration/appPublishWorkflow.spec.js
+++ b/packages/builder/cypress/integration/appPublishWorkflow.spec.js
@@ -11,9 +11,8 @@ filterTests(['all'], () => {
it("Should reflect the unpublished status correctly", () => {
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(1000)
- cy.get(interact.APP_TABLE_STATUS).eq(0)
+ cy.get(interact.APP_TABLE_STATUS, { timeout: 3000 }).eq(0)
.within(() => {
cy.contains("Unpublished")
cy.get(interact.GLOBESTRIKE).should("exist")
@@ -35,11 +34,10 @@ filterTests(['all'], () => {
cy.get(interact.DEPLOY_APP_MODAL).should("be.visible")
.within(() => {
cy.get(interact.SPECTRUM_BUTTON).contains("Publish").click({ force : true })
- cy.wait(1000)
});
//Verify that the app url is presented correctly to the user
- cy.get(interact.DEPLOY_SUCCESS_MODAL)
+ cy.get(interact.DEPLOY_SUCCESS_MODAL, { timeout: 1000 })
.should("be.visible")
.within(() => {
let appUrl = Cypress.config().baseUrl + '/app/cypress-tests'
@@ -48,9 +46,8 @@ filterTests(['all'], () => {
})
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(1000)
- cy.get(interact.APP_TABLE_STATUS).eq(0)
+ cy.get(interact.APP_TABLE_STATUS, { timeout: 3000 }).eq(0)
.within(() => {
cy.contains("Published")
cy.get(interact.GLOBE).should("exist")
@@ -58,7 +55,7 @@ filterTests(['all'], () => {
cy.get(interact.APP_TABLE_ROW_ACTION).eq(0)
.within(() => {
- cy.get(interact.SPECTRUM_BUTTON).contains("View")
+ cy.get(interact.SPECTRUM_BUTTON).contains("Manage")
cy.get(interact.SPECTRUM_BUTTON).contains("Edit").click({ force: true })
})
@@ -83,24 +80,25 @@ filterTests(['all'], () => {
cy.get("svg[aria-label='Globe']").should("exist")
})
- cy.get(interact.APP_TABLE_ROW_ACTION).eq(0)
+ cy.get(interact.APP_TABLE).eq(0)
.within(() => {
- cy.get(interact.SPECTRUM_BUTTON).contains("View")
cy.get(interact.APP_TABLE_APP_NAME).click({ force: true })
})
- cy.get(interact.SPECTRUM_LINK).contains('Unpublish').click();
+ cy.get(interact.DEPLOYMENT_TOP_NAV).click()
+ cy.get(interact.PUBLISH_POPOVER_ACTION).click({ force: true })
+ cy.get(interact.UNPUBLISH_MODAL)
+ .within(() => {
+ cy.get(interact.CONFIRM_WRAP_BUTTON).click({ force: true })
+ })
cy.get(interact.UNPUBLISH_MODAL).should("be.visible")
.within(() => {
cy.get(interact.CONFIRM_WRAP_BUTTON).click({ force: true }
)})
- cy.get(interact.DEPLOYMENT_TOP_NAV_GLOBESTRIKE).should("exist")
-
cy.visit(`${Cypress.config().baseUrl}/builder`)
-
- cy.get(interact.APP_TABLE_STATUS).eq(0).contains("Unpublished")
+ cy.get(interact.APP_TABLE_STATUS, { timeout: 1000 }).eq(0).contains("Unpublished")
})
})
diff --git a/packages/builder/cypress/integration/autoScreensUI.spec.js b/packages/builder/cypress/integration/autoScreensUI.spec.js
index eebeac3e71..ca997479ae 100644
--- a/packages/builder/cypress/integration/autoScreensUI.spec.js
+++ b/packages/builder/cypress/integration/autoScreensUI.spec.js
@@ -5,6 +5,7 @@ filterTests(['smoke', 'all'], () => {
context("Auto Screens UI", () => {
before(() => {
cy.login()
+ cy.deleteAllApps()
})
it("should disable the autogenerated screen options if no sources are available", () => {
diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js
index df617e3d9f..097b70db30 100644
--- a/packages/builder/cypress/integration/createApp.spec.js
+++ b/packages/builder/cypress/integration/createApp.spec.js
@@ -6,14 +6,14 @@ filterTests(['smoke', 'all'], () => {
before(() => {
cy.login()
- cy.deleteApp("Cypress Tests")
+ cy.deleteAllApps()
})
if (!(Cypress.env("TEST_ENV"))) {
it("should show the new user UI/UX", () => {
- cy.visit(`${Cypress.config().baseUrl}/builder/portal/apps/create`) //added /portal/apps/create
+ cy.visit(`${Cypress.config().baseUrl}/builder/portal/apps/create`, { timeout: 5000 }) //added /portal/apps/create
+ cy.wait(1000)
cy.get(interact.CREATE_APP_BUTTON).contains('Start from scratch').should("exist")
- cy.get(interact.CREATE_APP_BUTTON).should("exist")
cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist")
cy.get(interact.TEMPLATE_CATEGORY).should("exist")
@@ -23,7 +23,7 @@ filterTests(['smoke', 'all'], () => {
}
it("should provide filterable templates", () => {
- cy.visit(`${Cypress.config().baseUrl}/builder`)
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
cy.wait(500)
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
@@ -48,11 +48,10 @@ filterTests(['smoke', 'all'], () => {
})
it("should enforce a valid url before submission", () => {
- cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 10000 })
// Start create app process. If apps already exist, click second button
- cy.get(interact.CREATE_APP_BUTTON).click({ force: true })
+ cy.get(interact.CREATE_APP_BUTTON, { timeout: 1000 }).click({ force: true })
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
.its("body")
.then(val => {
@@ -92,21 +91,16 @@ filterTests(['smoke', 'all'], () => {
it("should create the first application from scratch", () => {
const appName = "Cypress Tests"
- cy.createApp(appName)
+ cy.createApp(appName, false)
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(1000)
cy.applicationInAppTable(appName)
cy.deleteApp(appName)
})
it("should create the first application from scratch with a default name", () => {
- cy.createApp()
-
- cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(1000)
-
+ cy.createApp("", false)
cy.applicationInAppTable("My app")
cy.deleteApp("My app")
})
@@ -116,26 +110,22 @@ filterTests(['smoke', 'all'], () => {
cy.updateUserInformation("Ted", "Userman")
- cy.createApp()
+ cy.createApp("", false)
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(1000)
cy.applicationInAppTable("Teds app")
cy.deleteApp("Teds app")
- cy.wait(2000)
//Accomodate names that end in 'S'
cy.updateUserInformation("Chris", "Userman")
- cy.createApp()
+ cy.createApp("", false)
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(1000)
cy.applicationInAppTable("Chris app")
cy.deleteApp("Chris app")
- cy.wait(2000)
cy.updateUserInformation("", "")
})
@@ -145,7 +135,7 @@ filterTests(['smoke', 'all'], () => {
cy.importApp(exportedApp, "")
- cy.visit(`${Cypress.config().baseUrl}/builder`)
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 2000 })
cy.applicationInAppTable("My app")
@@ -224,14 +214,12 @@ filterTests(['smoke', 'all'], () => {
cy.createApp(appName)
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
// Create second app
const secondAppName = "Second App Demo"
cy.createApp(secondAppName)
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
//Both applications should exist and be searchable
cy.searchForApplication(appName)
diff --git a/packages/builder/cypress/integration/createAutomation.spec.js b/packages/builder/cypress/integration/createAutomation.spec.js
index 6a4b70f8dc..b5ff406297 100644
--- a/packages/builder/cypress/integration/createAutomation.spec.js
+++ b/packages/builder/cypress/integration/createAutomation.spec.js
@@ -16,17 +16,15 @@ filterTests(['smoke', 'all'], () => {
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
cy.get("input").type("Add Row")
cy.contains("Row Created").click({ force: true })
- cy.wait(500)
- cy.get(interact.SPECTRUM_BUTTON_CTA).click()
+ cy.get(interact.SPECTRUM_BUTTON_CTA, { timeout: 500 }).click()
})
// Setup trigger
cy.get(interact.SPECTRUM_PICKER_LABEL).click()
cy.wait(500)
cy.contains("dog").click()
- cy.wait(2000)
// Create action
- cy.get('[aria-label="AddCircle"]').eq(1).click()
+ cy.get('[aria-label="AddCircle"]', { timeout: 2000 }).eq(1).click()
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
cy.wait(1000)
cy.contains("Create Row").trigger('mouseover').click().click()
@@ -43,11 +41,9 @@ filterTests(['smoke', 'all'], () => {
cy.contains("Finish and test automation").click()
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
- cy.wait(1000)
- cy.get(interact.SPECTRUM_PICKER_LABEL).click()
+ cy.get(interact.SPECTRUM_PICKER_LABEL, { timeout: 1000 }).click()
cy.contains("dog").click()
- cy.wait(1000)
- cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
+ cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 1000 })
.first()
.type("automationGoodboy")
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
diff --git a/packages/builder/cypress/integration/createScreen.js b/packages/builder/cypress/integration/createScreen.spec.js
similarity index 100%
rename from packages/builder/cypress/integration/createScreen.js
rename to packages/builder/cypress/integration/createScreen.spec.js
diff --git a/packages/builder/cypress/integration/createTable.spec.js b/packages/builder/cypress/integration/createTable.spec.js
index 7d55a1f03c..da73c19fa6 100644
--- a/packages/builder/cypress/integration/createTable.spec.js
+++ b/packages/builder/cypress/integration/createTable.spec.js
@@ -10,9 +10,8 @@ filterTests(["smoke", "all"], () => {
it("should create a new Table", () => {
cy.createTable("dog")
- cy.wait(1000)
// Check if Table exists
- cy.get(interact.TABLE_TITLE_H1).should("have.text", "dog")
+ cy.get(interact.TABLE_TITLE_H1, { timeout: 1000 }).should("have.text", "dog")
})
it("adds a new column to the table", () => {
@@ -40,7 +39,7 @@ filterTests(["smoke", "all"], () => {
it("edits a row", () => {
cy.contains("button", "Edit").click({ force: true })
- cy.wait(1000)
+ cy.wait(500)
cy.get(interact.SPECTRUM_MODAL_INPUT).clear()
cy.get(interact.SPECTRUM_MODAL_INPUT).type("Updated")
cy.contains("Save").click()
@@ -63,8 +62,7 @@ filterTests(["smoke", "all"], () => {
cy.addRow([i])
}
cy.reload()
- cy.wait(2000)
- cy.get(interact.SPECTRUM_PAGINATION).within(() => {
+ cy.get(interact.SPECTRUM_PAGINATION, { timeout: 2000 }).within(() => {
cy.get(interact.SPECTRUM_ACTION_BUTTON).eq(1).click()
})
cy.get(interact.SPECTRUM_PAGINATION).within(() => {
@@ -79,10 +77,9 @@ filterTests(["smoke", "all"], () => {
cy.get(interact.SPECTRUM_BUTTON).click({ force: true })
})
cy.get(interact.SPECTRUM_DIALOG_GRID).contains("Delete").click({ force: true })
- cy.wait(1000)
// Confirm table only has one page
- cy.get(interact.SPECTRUM_PAGINATION).within(() => {
+ cy.get(interact.SPECTRUM_PAGINATION, { timeout: 1000 }).within(() => {
cy.get(interact.SPECTRUM_ACTION_BUTTON).eq(1).should("not.be.enabled")
})
})
diff --git a/packages/builder/cypress/integration/createView.spec.js b/packages/builder/cypress/integration/createView.spec.js
index e554f6f866..a2d09d97bf 100644
--- a/packages/builder/cypress/integration/createView.spec.js
+++ b/packages/builder/cypress/integration/createView.spec.js
@@ -69,8 +69,8 @@ filterTests(['smoke', 'all'], () => {
cy.get(interact.SPECTRUM_BUTTON).contains("Save").click({ force: true })
})
- cy.wait(1000)
+ cy.wait(1000)
cy.get(interact.TITLE).then($headers => {
expect($headers).to.have.length(7)
const headers = Array.from($headers).map(header =>
diff --git a/packages/builder/cypress/integration/customThemingProperties.spec.js b/packages/builder/cypress/integration/customThemingProperties.spec.js
index ed3478ca67..e9de0985d0 100644
--- a/packages/builder/cypress/integration/customThemingProperties.spec.js
+++ b/packages/builder/cypress/integration/customThemingProperties.spec.js
@@ -34,7 +34,6 @@ filterTests(['all'], () => {
Large = 16px */
it("should test button roundness", () => {
const buttonRoundnessValues = ["0", "4px", "8px", "16px"]
- cy.wait(1000)
// Add button, change roundness and confirm value
cy.addComponent("Button", null).then((componentId) => {
buttonRoundnessValues.forEach(function (item, index){
diff --git a/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js b/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js
index 1bee7b5ec1..14653d8286 100644
--- a/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js
+++ b/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js
@@ -17,11 +17,10 @@ filterTests(['all'], () => {
// Navigate back within datasource wizard
cy.get(".spectrum-Dialog-grid").within(() => {
cy.get(".spectrum-Button").contains("Back").click({ force: true })
- cy.wait(1000)
})
// Select PostgreSQL datasource again
- cy.get(".item-list").contains(datasource).click()
+ cy.get(".item-list", { timeout: 1000 }).contains(datasource).click()
cy.get(".spectrum-Dialog-grid").within(() => {
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
})
diff --git a/packages/builder/cypress/integration/datasources/mySql.spec.js b/packages/builder/cypress/integration/datasources/mySql.spec.js
index 98bb2f2acf..b79f5af9c6 100644
--- a/packages/builder/cypress/integration/datasources/mySql.spec.js
+++ b/packages/builder/cypress/integration/datasources/mySql.spec.js
@@ -111,10 +111,9 @@ filterTests(["all"], () => {
// Save relationship & reload page
cy.get(".spectrum-Button").contains("Save").click({ force: true })
cy.reload()
- cy.wait(1000)
})
// Confirm table length & relationship name
- cy.get(".spectrum-Table")
+ cy.get(".spectrum-Table", { timeout: 1000 })
.eq(1)
.find(".spectrum-Table-row")
.its("length")
@@ -136,15 +135,15 @@ filterTests(["all"], () => {
cy.get(".spectrum-Table")
.eq(1)
.within(() => {
- cy.get(".spectrum-Table-row").eq(0).click({ force: true })
- cy.wait(500)
+ cy.get(".spectrum-Table-cell").eq(0).click({ force: true })
})
- cy.get(".spectrum-Dialog-grid").within(() => {
+ cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
cy.get(".spectrum-Button")
.contains("Delete")
.click({ force: true })
})
cy.reload()
+ cy.wait(500)
}
// Confirm relationships no longer exist
cy.get(".spectrum-Body").should(
@@ -217,9 +216,8 @@ filterTests(["all"], () => {
cy.get(".spectrum-Button")
.contains("Delete Query")
.click({ force: true })
- cy.wait(1000)
// Confirm deletion
- cy.get(".nav-item").should("not.contain", queryName)
+ cy.get(".nav-item", { timeout: 1000 }).should("not.contain", queryName)
})
}
})
diff --git a/packages/builder/cypress/integration/datasources/oracle.spec.js b/packages/builder/cypress/integration/datasources/oracle.spec.js
index 4c4d33d654..92a5737ff9 100644
--- a/packages/builder/cypress/integration/datasources/oracle.spec.js
+++ b/packages/builder/cypress/integration/datasources/oracle.spec.js
@@ -20,7 +20,7 @@ filterTests(["all"], () => {
.click({ force: true })
cy.wait(500)
// Confirm config contains localhost
- cy.get(".spectrum-Textfield-input")
+ cy.get(".spectrum-Textfield-input", { timeout: 500 })
.eq(1)
.should("have.value", "localhost")
// Add another Oracle data source, configure & skip table fetch
@@ -140,9 +140,8 @@ filterTests(["all"], () => {
.eq(1)
.within(() => {
cy.get(".spectrum-Table-row").eq(0).click()
- cy.wait(500)
})
- cy.get(".spectrum-Dialog-grid").within(() => {
+ cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
cy.get(".spectrum-Button")
.contains("Delete")
.click({ force: true })
@@ -221,10 +220,9 @@ filterTests(["all"], () => {
cy.get(".spectrum-Button")
.contains("Delete Query")
.click({ force: true })
- cy.wait(1000)
// Confirm deletion
- cy.get(".nav-item").should("not.contain", queryName)
+ cy.get(".nav-item", { timeout: 1000 }).should("not.contain", queryName)
})
}
})
diff --git a/packages/builder/cypress/integration/datasources/postgreSql.spec.js b/packages/builder/cypress/integration/datasources/postgreSql.spec.js
index 7448e6b27d..de959e203c 100644
--- a/packages/builder/cypress/integration/datasources/postgreSql.spec.js
+++ b/packages/builder/cypress/integration/datasources/postgreSql.spec.js
@@ -35,6 +35,7 @@ filterTests(["all"], () => {
// Check response from datasource after adding configuration
cy.wait("@datasource")
cy.get("@datasource").its("response.statusCode").should("eq", 200)
+ cy.wait(2000)
// Confirm fetch tables was successful
cy.get(".spectrum-Table")
.eq(0)
@@ -113,13 +114,13 @@ filterTests(["all"], () => {
cy.get(".spectrum-Table")
.eq(1)
.within(() => {
- cy.get(".spectrum-Table-row").eq(0).click({ force: true })
- cy.wait(500)
+ cy.get(".spectrum-Table-cell").eq(0).click({ force: true })
})
- cy.get(".spectrum-Dialog-grid").within(() => {
+ cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
cy.get(".spectrum-Button").contains("Delete").click({ force: true })
})
cy.reload()
+ cy.wait(500)
// Confirm relationship was deleted
cy.get(".spectrum-Table")
.eq(1)
@@ -159,7 +160,7 @@ filterTests(["all"], () => {
switchSchema("randomText")
// No tables displayed
- cy.get(".spectrum-Body").eq(2).should("contain", "No tables found")
+ cy.get(".spectrum-Body", { timeout: 5000 }).eq(2).should("contain", "No tables found")
// Previously created query should be visible
cy.get(".spectrum-Table").should("contain", queryName)
@@ -170,7 +171,7 @@ filterTests(["all"], () => {
switchSchema("1")
// Confirm tables exist - Check for specific one
- cy.get(".spectrum-Table").eq(0).should("contain", "test")
+ cy.get(".spectrum-Table", { timeout: 5000 }).eq(0).should("contain", "test")
cy.get(".spectrum-Table")
.eq(0)
.find(".spectrum-Table-row")
@@ -184,7 +185,7 @@ filterTests(["all"], () => {
switchSchema("public")
// Confirm tables exist - again
- cy.get(".spectrum-Table").eq(0).should("contain", "REGIONS")
+ cy.get(".spectrum-Table", { timeout: 5000 }).eq(0).should("contain", "REGIONS")
cy.get(".spectrum-Table")
.eq(0)
.find(".spectrum-Table-row")
@@ -230,7 +231,9 @@ filterTests(["all"], () => {
// Run and Save query
cy.get(".spectrum-Button").contains("Run Query").click({ force: true })
cy.wait(500)
- cy.get(".spectrum-Button").contains("Save Query").click({ force: true })
+ cy.get(".spectrum-Button", { timeout: 500 }).contains("Save Query").click({ force: true })
+ //cy.reload()
+ //cy.wait(500)
cy.get(".nav-item").should("contain", queryRename)
})
@@ -247,9 +250,8 @@ filterTests(["all"], () => {
cy.get(".spectrum-Button")
.contains("Delete Query")
.click({ force: true })
- cy.wait(1000)
// Confirm deletion
- cy.get(".nav-item").should("not.contain", queryName)
+ cy.get(".nav-item", { timeout: 1000 }).should("not.contain", queryName)
})
const switchSchema = schema => {
@@ -271,7 +273,7 @@ filterTests(["all"], () => {
.click({ force: true })
})
cy.reload()
- cy.wait(5000)
+ cy.wait(1000)
}
}
})
diff --git a/packages/builder/cypress/integration/datasources/rest.spec.js b/packages/builder/cypress/integration/datasources/rest.spec.js
index a15487c01b..488c30c0cf 100644
--- a/packages/builder/cypress/integration/datasources/rest.spec.js
+++ b/packages/builder/cypress/integration/datasources/rest.spec.js
@@ -14,8 +14,7 @@ filterTests(["smoke", "all"], () => {
// Select REST data source
cy.selectExternalDatasource(datasource)
// Enter incorrect api & attempt to send query
- cy.wait(500)
- cy.get(".spectrum-Button").contains("Add query").click({ force: true })
+ cy.get(".spectrum-Button", { timeout: 500 }).contains("Add query").click({ force: true })
cy.intercept("**/preview").as("queryError")
cy.get("input").clear().type("random text")
cy.get(".spectrum-Button").contains("Send").click({ force: true })
@@ -36,8 +35,7 @@ filterTests(["smoke", "all"], () => {
// createRestQuery confirms query creation
cy.createRestQuery("GET", restUrl, "/breweries")
// Confirm status code response within REST datasource
- cy.wait(1000)
- cy.get(".stats").within(() => {
+ cy.get(".stats", { timeout: 1000 }).within(() => {
cy.get(".spectrum-FieldLabel")
.eq(0)
.should("contain", 200)
diff --git a/packages/builder/cypress/integration/renameAnApplication.spec.js b/packages/builder/cypress/integration/renameAnApplication.spec.js
index 703535a507..370efadff2 100644
--- a/packages/builder/cypress/integration/renameAnApplication.spec.js
+++ b/packages/builder/cypress/integration/renameAnApplication.spec.js
@@ -13,16 +13,13 @@ filterTests(["all"], () => {
const appRename = "Cypress Renamed"
// Rename app, Search for app, Confirm name was changed
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
renameApp(appName, appRename)
cy.reload()
- cy.wait(1000)
cy.searchForApplication(appRename)
cy.get(interact.APP_TABLE).find(interact.TITLE).should("have.length", 1)
cy.applicationInAppTable(appRename)
// Set app name back to Cypress Tests
cy.reload()
- cy.wait(1000)
renameApp(appRename, appName)
})
@@ -43,7 +40,6 @@ filterTests(["all"], () => {
})
// Rename app, Search for app, Confirm name was changed
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
renameApp(appName, appRename, true)
cy.get(interact.APP_TABLE).find(interact.WRAPPER).should("have.length", 1)
cy.applicationInAppTable(appRename)
@@ -52,13 +48,9 @@ filterTests(["all"], () => {
it("Should try to rename an application to have no name", () => {
const appName = "Cypress Tests"
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
renameApp(appName, " ", false, true)
- cy.wait(500)
// Close modal and confirm name has not been changed
- cy.get(interact.SPECTRUM_DIALOG_GRID).contains("Cancel").click()
- cy.reload()
- cy.wait(1000)
+ cy.get(interact.SPECTRUM_DIALOG_GRID, { timeout: 1000 }).contains("Cancel").click()
cy.applicationInAppTable(appName)
})
@@ -66,8 +58,7 @@ filterTests(["all"], () => {
// It is not possible to have applications with the same name
const appName = "Cypress Tests"
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
- cy.get(interact.SPECTRUM_BUTTON)
+ cy.get(interact.SPECTRUM_BUTTON), { timeout: 500 }
.contains("Create app")
.click({ force: true })
cy.contains(/Start from scratch/).click()
@@ -90,13 +81,10 @@ filterTests(["all"], () => {
const numberName = 12345
const specialCharName = "£$%^"
cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(500)
renameApp(appName, numberName)
cy.reload()
- cy.wait(1000)
cy.applicationInAppTable(numberName)
cy.reload()
- cy.wait(1000)
renameApp(numberName, specialCharName)
cy.get(interact.ERROR).should(
"have.text",
@@ -104,13 +92,12 @@ filterTests(["all"], () => {
)
// Set app name back to Cypress Tests
cy.reload()
- cy.wait(1000)
renameApp(numberName, appName)
})
const renameApp = (originalName, changedName, published, noName) => {
cy.searchForApplication(originalName)
- cy.get(interact.APP_TABLE).within(() => {
+ cy.get(interact.APP_TABLE, { timeout: 1000 }).within(() => {
cy.get(".app-row-actions button")
.contains("Manage")
.eq(0)
diff --git a/packages/builder/cypress/integration/revertApp.spec.js b/packages/builder/cypress/integration/revertApp.spec.js
index 93501ab972..4c6f245b76 100644
--- a/packages/builder/cypress/integration/revertApp.spec.js
+++ b/packages/builder/cypress/integration/revertApp.spec.js
@@ -36,8 +36,8 @@ filterTests(['smoke', 'all'], () => {
cy.get(interact.SPECTRUM_BUTTON_GROUP).within(() => {
cy.get(interact.SPECTRUM_BUTTON).contains("Publish").click({ force: true })
})
- cy.wait(1000)
- cy.get(interact.SPECTRUM_BUTTON_GROUP).within(() => {
+ cy.wait(1000) // Wait for next modal to finish loading
+ cy.get(interact.SPECTRUM_BUTTON_GROUP, { timeout: 1000 }).within(() => {
cy.get(interact.SPECTRUM_BUTTON).contains("Done").click({ force: true })
})
@@ -50,18 +50,17 @@ filterTests(['smoke', 'all'], () => {
cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
// Click Revert
cy.get(interact.SPECTRUM_BUTTON).contains("Revert").click({ force: true })
- cy.wait(1000)
+ cy.wait(2000) // Wait for app to finish reverting
})
// Confirm Paragraph component is still visible
- cy.get(interact.ROOT).contains("New Paragraph")
+ cy.get(interact.ROOT, { timeout: 1000 }).contains("New Paragraph")
// Confirm Button component is not visible
- cy.get(interact.ROOT).should("not.have.text", "New Button")
- cy.wait(500)
+ cy.get(interact.ROOT, { timeout: 1000 }).should("not.have.text", "New Button")
})
it("should enter incorrect app name when reverting", () => {
// Click Revert
- cy.get(interact.TOP_RIGHT_NAV).within(() => {
+ cy.get(interact.TOP_RIGHT_NAV, { timeout: 1000 }).within(() => {
cy.get(interact.AREA_LABEL_REVERT).click({ force: true })
})
// Enter incorrect app name
diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js
index 29aabc4611..9d77b89c57 100644
--- a/packages/builder/cypress/support/commands.js
+++ b/packages/builder/cypress/support/commands.js
@@ -3,7 +3,7 @@ Cypress.on("uncaught:exception", () => {
})
// ACCOUNTS & USERS
-Cypress.Commands.add("login", () => {
+Cypress.Commands.add("login", (email, password) => {
cy.visit(`${Cypress.config().baseUrl}/builder`)
cy.wait(2000)
cy.url().then(url => {
@@ -17,8 +17,13 @@ Cypress.Commands.add("login", () => {
if (url.includes("builder/auth/login") || url.includes("builder/admin")) {
// login
cy.contains("Sign in to Budibase").then(() => {
- cy.get("input").first().type("test@test.com")
- cy.get('input[type="password"]').type("test")
+ if (email == null) {
+ cy.get("input").first().type("test@test.com")
+ cy.get('input[type="password"]').type("test")
+ } else {
+ cy.get("input").first().type(email)
+ cy.get('input[type="password"]').type(password)
+ }
cy.get("button").first().click({ force: true })
cy.wait(1000)
})
@@ -27,7 +32,7 @@ Cypress.Commands.add("login", () => {
})
Cypress.Commands.add("logOut", () => {
- cy.visit(`${Cypress.config().baseUrl}/builder`)
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 2000 })
cy.get(".user-dropdown .avatar > .icon").click({ force: true })
cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => {
cy.get("li[data-cy='user-logout']").click({ force: true })
@@ -35,24 +40,58 @@ Cypress.Commands.add("logOut", () => {
cy.wait(2000)
})
+Cypress.Commands.add("logoutNoAppGrid", () => {
+ // Logs user out when app grid is not present
+ cy.visit(`${Cypress.config().baseUrl}/builder`)
+ cy.get(".avatar > .icon").click({ force: true })
+ cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => {
+ cy.get(".spectrum-Menu-item").contains("Log out").click({ force: true })
+ })
+ cy.wait(2000)
+})
+
Cypress.Commands.add("createUser", email => {
// quick hacky recorded way to create a user
cy.contains("Users").click()
cy.get(`[data-cy="add-user"]`).click()
- cy.get(".spectrum-Picker-label").click()
- cy.get(".spectrum-Menu-item:nth-child(2) > .spectrum-Menu-itemLabel").click()
+ cy.get(".spectrum-Dialog-grid").within(() => {
+ cy.get(".spectrum-Picker-label").click()
+ cy.get(
+ ".spectrum-Menu-item:nth-child(2) > .spectrum-Menu-itemLabel"
+ ).click()
- //Onboarding type selector
- cy.get(
- ":nth-child(2) > .spectrum-Form-itemField > .spectrum-Textfield > .spectrum-Textfield-input"
- )
- .first()
- .type(email, { force: true })
- cy.get(".spectrum-Button--cta").click({ force: true })
+ // Onboarding type selector
+ cy.get(".spectrum-Textfield-input")
+ .eq(0)
+ .first()
+ .type(email, { force: true })
+ cy.get(".spectrum-Button--cta").click({ force: true })
+ })
+})
+
+Cypress.Commands.add("deleteUser", email => {
+ // Assumes user has access to Users section
+ cy.contains("Users", { timeout: 2000 }).click()
+ cy.contains(email).click()
+
+ // Click Delete user button
+ cy.get(".spectrum-Button")
+ .contains("Delete user")
+ .click({ force: true })
+ .then(() => {
+ // Confirm deletion within modal
+ cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
+ cy.get(".spectrum-Button")
+ .contains("Delete user")
+ .click({ force: true })
+ })
+ })
})
Cypress.Commands.add("updateUserInformation", (firstName, lastName) => {
- cy.get(".user-dropdown .avatar > .icon").click({ force: true })
+ cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({
+ force: true,
+ })
cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => {
cy.get("li[data-cy='user-info']").click({ force: true })
@@ -95,9 +134,8 @@ Cypress.Commands.add("createApp", (name, addDefaultTable) => {
const shouldCreateDefaultTable =
typeof addDefaultTable != "boolean" ? true : addDefaultTable
- cy.visit(`${Cypress.config().baseUrl}/builder`)
- cy.wait(1000)
- cy.get(`[data-cy="create-app-btn"]`).click({ force: true })
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
+ cy.get(`[data-cy="create-app-btn"]`, { timeout: 2000 }).click({ force: true })
// If apps already exist
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
@@ -117,7 +155,7 @@ Cypress.Commands.add("createApp", (name, addDefaultTable) => {
cy.get(".spectrum-ButtonGroup")
.contains("Create app")
.click({ force: true })
- cy.wait(10000)
+ cy.wait(2000)
})
if (shouldCreateDefaultTable) {
cy.createTable("Cypress Tests", true)
@@ -125,7 +163,7 @@ Cypress.Commands.add("createApp", (name, addDefaultTable) => {
})
Cypress.Commands.add("deleteApp", name => {
- cy.visit(`${Cypress.config().baseUrl}/builder`)
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
cy.wait(2000)
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
.its("body")
@@ -150,14 +188,15 @@ Cypress.Commands.add("deleteApp", name => {
cy.get(actionEleId).within(() => {
cy.contains("Manage").click({ force: true })
})
- cy.wait(1000)
+ cy.wait(500)
// Unpublish first if needed
cy.get(`[data-cy="app-status"]`).then($status => {
- if ($status.text().includes("Last published")) {
- cy.contains("Unpublish").click()
+ if ($status.text().includes("- Unpublish")) {
+ // Exact match for Unpublish
+ cy.contains("Unpublish").click({ force: true })
cy.get(".spectrum-Modal").within(() => {
- cy.contains("Unpublish app").click()
+ cy.contains("Unpublish app").click({ force: true })
})
}
})
@@ -276,16 +315,18 @@ Cypress.Commands.add("alterAppVersion", (appId, version) => {
})
Cypress.Commands.add("importApp", (exportFilePath, name) => {
- cy.visit(`${Cypress.config().baseUrl}/builder`)
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
.its("body")
.then(val => {
if (val.length > 0) {
cy.get(`[data-cy="create-app-btn"]`).click({ force: true })
- cy.wait(500)
}
- cy.get(`[data-cy="import-app-btn"]`).click({ force: true })
+ cy.wait(500)
+ cy.get(`[data-cy="import-app-btn"]`).click({
+ force: true,
+ })
})
cy.get(".spectrum-Modal").within(() => {
@@ -303,7 +344,7 @@ Cypress.Commands.add("importApp", (exportFilePath, name) => {
cy.get(".confirm-wrap button")
.should("not.be.disabled")
.click({ force: true })
- cy.wait(5000)
+ cy.wait(3000)
})
})
@@ -332,7 +373,8 @@ Cypress.Commands.add("searchForApplication", appName => {
// Assumes there are no others
Cypress.Commands.add("applicationInAppTable", appName => {
- cy.get(".appTable").within(() => {
+ cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 10000 })
+ cy.get(".appTable", { timeout: 2000 }).within(() => {
cy.get(".title").contains(appName).should("exist")
})
})
@@ -360,7 +402,7 @@ Cypress.Commands.add("createTable", (tableName, initialTable) => {
cy.navigateToDataSection()
cy.get(`[data-cy="new-table"]`).click()
}
- cy.wait(5000)
+ cy.wait(2000)
cy.get(".item")
.contains("Budibase DB")
.click({ force: true })
@@ -368,8 +410,7 @@ Cypress.Commands.add("createTable", (tableName, initialTable) => {
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
})
cy.get(".spectrum-Modal").within(() => {
- cy.wait(1000)
- cy.get("input").first().type(tableName).blur()
+ cy.get("input", { timeout: 1000 }).first().type(tableName).blur()
cy.get(".spectrum-ButtonGroup").contains("Create").click()
})
cy.contains(tableName).should("be.visible")
@@ -451,8 +492,7 @@ Cypress.Commands.add("addCustomSourceOptions", totalOptions => {
.contains("Add Option")
.click({ force: true })
.then(() => {
- cy.wait(500)
- cy.get("[placeholder='Label']").eq(i).type(i)
+ cy.get("[placeholder='Label']", { timeout: 500 }).eq(i).type(i)
cy.get("[placeholder='Value']").eq(i).type(i)
})
}
@@ -464,10 +504,14 @@ Cypress.Commands.add("addCustomSourceOptions", totalOptions => {
// DESIGN AREA
Cypress.Commands.add("addComponent", (category, component) => {
if (category) {
- cy.get(`[data-cy="category-${category}"]`).click({ force: true })
+ cy.get(`[data-cy="category-${category}"]`, { timeout: 1000 }).click({
+ force: true,
+ })
}
if (component) {
- cy.get(`[data-cy="component-${component}"]`).click({ force: true })
+ cy.get(`[data-cy="component-${component}"]`, { timeout: 1000 }).click({
+ force: true,
+ })
}
cy.wait(1000)
cy.location().then(loc => {
@@ -496,15 +540,14 @@ Cypress.Commands.add("createScreen", (route, accessLevelLabel) => {
cy.get(".spectrum-Modal").within(() => {
cy.get("[data-cy='blank-screen']").click()
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
- cy.wait(500)
})
- cy.get(".spectrum-Dialog-grid").within(() => {
+ cy.wait(500)
+ cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
cy.get(".spectrum-Form-itemField").eq(0).type(route)
- cy.get(".spectrum-Button").contains("Continue").click({ force: true })
- cy.wait(1000)
+ cy.get(".confirm-wrap").contains("Continue").click({ force: true })
})
- cy.get(".spectrum-Modal").within(() => {
+ cy.get(".spectrum-Modal", { timeout: 1000 }).within(() => {
if (accessLevelLabel) {
cy.get(".spectrum-Picker-label").click()
cy.wait(500)
@@ -522,10 +565,12 @@ Cypress.Commands.add(
cy.get(".spectrum-Modal").within(() => {
cy.get(".item").contains("Autogenerated screens").click()
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
- cy.wait(500)
})
- cy.get(".spectrum-Modal [data-cy='data-source-modal']").within(() => {
+ cy.get(".spectrum-Modal [data-cy='data-source-modal']", {
+ timeout: 500,
+ }).within(() => {
for (let i = 0; i < datasourceNames.length; i++) {
+ cy.wait(500)
cy.get(".data-source-entry").contains(datasourceNames[i]).click()
//Ensure the check mark is visible
cy.get(".data-source-entry")
@@ -574,7 +619,7 @@ Cypress.Commands.add(
// NAVIGATION
Cypress.Commands.add("navigateToFrontend", () => {
// Clicks on Design tab and then the Home nav item
- cy.wait(1000)
+ cy.wait(500)
cy.contains("Design").click()
cy.get(".spectrum-Search").type("/")
cy.get(".nav-item").contains("home").click()
@@ -606,11 +651,11 @@ Cypress.Commands.add("selectExternalDatasource", datasourceName => {
cy.get(".add-button").click()
})
// Clicks specified datasource & continue
- cy.wait(1000)
- cy.get(".item-list").contains(datasourceName).click()
+ cy.get(".item-list", { timeout: 1000 }).contains(datasourceName).click()
cy.get(".spectrum-Dialog-grid").within(() => {
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
})
+ cy.wait(500)
})
Cypress.Commands.add("addDatasourceConfig", (datasource, skipFetch) => {
@@ -618,8 +663,7 @@ Cypress.Commands.add("addDatasourceConfig", (datasource, skipFetch) => {
// Adds the config for specified datasource & fetches tables
// Currently supports MySQL, PostgreSQL, Oracle
// Host IP Address
- cy.wait(500)
- cy.get(".spectrum-Dialog-grid").within(() => {
+ cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
cy.get(".form-row")
.eq(0)
.within(() => {
@@ -719,16 +763,18 @@ Cypress.Commands.add("addDatasourceConfig", (datasource, skipFetch) => {
Cypress.Commands.add("createRestQuery", (method, restUrl, queryPrettyName) => {
// addExternalDatasource should be called prior to this
// Configures REST datasource & sends query
- cy.wait(1000)
- cy.get(".spectrum-Button").contains("Add query").click({ force: true })
+ cy.get(".spectrum-Button", { timeout: 1000 })
+ .contains("Add query")
+ .click({ force: true })
// Select Method & add Rest URL
cy.get(".spectrum-Picker-label").eq(1).click()
cy.get(".spectrum-Menu").contains(method).click()
cy.get("input").clear().type(restUrl)
// Send query
cy.get(".spectrum-Button").contains("Send").click({ force: true })
- cy.wait(500)
- cy.get(".spectrum-Button").contains("Save").click({ force: true })
+ cy.get(".spectrum-Button", { timeout: 500 })
+ .contains("Save")
+ .click({ force: true })
cy.get(".hierarchy-items-container")
.should("contain", method)
.and("contain", queryPrettyName)
diff --git a/packages/builder/cypress/support/interact.js b/packages/builder/cypress/support/interact.js
index f0fae61660..0b31d8a8c5 100644
--- a/packages/builder/cypress/support/interact.js
+++ b/packages/builder/cypress/support/interact.js
@@ -62,6 +62,7 @@ export const GLOBESTRIKE = "svg[aria-label=GlobeStrike]"
export const GLOBE = "svg[aria-label=Globe]"
export const UNPUBLISH_MODAL = "[data-cy=unpublish-modal]"
export const CONFIRM_WRAP_BUTTON = ".confirm-wrap button"
+export const DEPLOYMENT_TOP_NAV = ".deployment-top-nav"
//changeAppiconAndColour
export const APP_ROW_ACTION = ".app-row-actions-icon"
@@ -97,13 +98,16 @@ export const ACTION_SPECTRUM_ICON = ".actions .spectrum-Icon"
export const SPECTRUM_MENU_CHILD2 = ".spectrum-Menu > :nth-child(2)"
export const DELETE_TABLE_CONFIRM = '[data-cy="delete-table-confirm"]'
-//createUSerAndRoles
+//adminAndManagement Folder
export const SPECTRUM_TABLE = ".spectrum-Table"
export const SPECTRUM_SIDENAV = ".spectrum-SideNav"
export const SPECTRUM_TABLE_ROW = ".spectrum-Table-row"
export const SPECTRUM_TABLE_CELL = ".spectrum-Table-cell"
export const FIELD = ".field"
export const CONTAINER = ".container"
+export const REGENERATE = ".regenerate"
+export const SPECTRUM_DIALOG_CONTENT = ".spectrum-Dialog-content"
+export const SPECTRUM_ICON = ".spectrum-Icon"
//createView
export const SPECTRUM_MENU_ITEM_LABEL = ".spectrum-Menu-itemLabel"
@@ -113,14 +117,17 @@ export const TOP_RIGHT_NAV = ".toprightnav"
export const AREA_LABEL_REVERT = "[aria-label=Revert]"
export const ROOT = ".root"
-//quertLevelTransformers
+//queryLevelTransformers
export const SPECTRUM_TABS_ITEM = ".spectrum-Tabs-itemLabel"
export const CODEMIRROR_TEXTAREA = ".CodeMirror textarea"
-//renemaApplication
+//renameApplication
export const WRAPPER = ".wrapper"
export const ERROR = ".error"
export const AREA_LABEL_MORE = "[aria-label=More]"
export const APP_ROW_ACTION_MENU_POPOVER =
'[data-cy="app-row-actions-menu-popover"]'
-export const SPECTRUM_MENU_ITEMM = ".spectrum-Menu-item"
+export const SPECTRUM_MENU_ITEM = ".spectrum-Menu-item"
+
+//commands
+export const HOME_LOGO = ".home-logo"
diff --git a/packages/builder/package.json b/packages/builder/package.json
index 147333a224..8fc012ad29 100644
--- a/packages/builder/package.json
+++ b/packages/builder/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/builder",
- "version": "1.0.212-alpha.0",
+ "version": "1.0.212-alpha.10",
"license": "GPL-3.0",
"private": true,
"scripts": {
@@ -69,10 +69,10 @@
}
},
"dependencies": {
- "@budibase/bbui": "^1.0.212-alpha.0",
- "@budibase/client": "^1.0.212-alpha.0",
- "@budibase/frontend-core": "^1.0.212-alpha.0",
- "@budibase/string-templates": "^1.0.212-alpha.0",
+ "@budibase/bbui": "^1.0.212-alpha.10",
+ "@budibase/client": "^1.0.212-alpha.10",
+ "@budibase/frontend-core": "^1.0.212-alpha.10",
+ "@budibase/string-templates": "^1.0.212-alpha.10",
"@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1",
diff --git a/packages/builder/src/components/backend/DatasourceNavigator/icons/SQLServer.svelte b/packages/builder/src/components/backend/DatasourceNavigator/icons/SQLServer.svelte
index 5bc3a8e061..af547bcae2 100644
--- a/packages/builder/src/components/backend/DatasourceNavigator/icons/SQLServer.svelte
+++ b/packages/builder/src/components/backend/DatasourceNavigator/icons/SQLServer.svelte
@@ -4,396 +4,40 @@
diff --git a/packages/builder/src/helpers/pagination.js b/packages/builder/src/helpers/pagination.js
new file mode 100644
index 0000000000..122973f1a1
--- /dev/null
+++ b/packages/builder/src/helpers/pagination.js
@@ -0,0 +1,66 @@
+import { writable } from "svelte/store"
+
+function defaultValue() {
+ return {
+ nextPage: null,
+ page: undefined,
+ hasPrevPage: false,
+ hasNextPage: false,
+ loading: false,
+ pageNumber: 1,
+ pages: [],
+ }
+}
+
+export function createPaginationStore() {
+ const { subscribe, set, update } = writable(defaultValue())
+
+ function prevPage() {
+ update(state => {
+ state.pageNumber--
+ state.nextPage = state.pages.pop()
+ state.page = state.pages[state.pages.length - 1]
+ state.hasPrevPage = state.pageNumber > 1
+ return state
+ })
+ }
+
+ function nextPage() {
+ update(state => {
+ state.pageNumber++
+ state.page = state.nextPage
+ state.pages.push(state.page)
+ state.hasPrevPage = state.pageNumber > 1
+ return state
+ })
+ }
+
+ function fetched(hasNextPage, nextPage) {
+ update(state => {
+ state.hasNextPage = hasNextPage
+ state.nextPage = nextPage
+ state.loading = false
+ return state
+ })
+ }
+
+ function loading(loading = true) {
+ update(state => {
+ state.loading = loading
+ return state
+ })
+ }
+
+ function reset() {
+ set(defaultValue())
+ }
+
+ return {
+ subscribe,
+ prevPage,
+ nextPage,
+ fetched,
+ loading,
+ reset,
+ }
+}
diff --git a/packages/builder/src/pages/builder/app/[application]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/_layout.svelte
index ebe5e32653..8c3de02202 100644
--- a/packages/builder/src/pages/builder/app/[application]/_layout.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/_layout.svelte
@@ -1,7 +1,14 @@
@@ -75,17 +70,31 @@
$goto(`./${detail._id}`)}
{schema}
- data={filteredUsers || $users}
+ data={$users.data}
allowEditColumns={false}
allowEditRows={false}
allowSelectRows={false}
customRenderers={[{ column: "group", component: TagsRenderer }]}
/>
+
-
+ {
+ pageInfo.reset()
+ await fetchUsers()
+ }}
+ />