From 72adb450b364bcf922bde13b7f5d3a6c7d07b622 Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Wed, 8 Jun 2022 17:14:02 +0100 Subject: [PATCH 01/15] Minor Smoke Build Test changes Updates for appOverview & autoScreensUI --- packages/builder/cypress/integration/appOverview.spec.js | 7 ++----- packages/builder/cypress/integration/autoScreensUI.spec.js | 1 + 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/builder/cypress/integration/appOverview.spec.js b/packages/builder/cypress/integration/appOverview.spec.js index 090e4e369b..7acfbc5f69 100644 --- a/packages/builder/cypress/integration/appOverview.spec.js +++ b/packages/builder/cypress/integration/appOverview.spec.js @@ -309,11 +309,8 @@ filterTests(['all'], () => { cy.visit(`${Cypress.config().baseUrl}/builder`) cy.get(".appTable .name").eq(0).click() - 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(".overview-tab [data-cy='app-status']").within(() => { + cy.get(".spectrum-Link").contains("Unpublish").click() }) cy.get("[data-cy='unpublish-modal']").should("be.visible") 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", () => { From 56d3b46366a2a97e3b6c41e09d6e1073d7161344 Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Wed, 8 Jun 2022 17:33:56 +0100 Subject: [PATCH 02/15] appPublishWorkflow test fix Third test was failing as part of the smoke build --- .../cypress/integration/appPublishWorkflow.spec.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/builder/cypress/integration/appPublishWorkflow.spec.js b/packages/builder/cypress/integration/appPublishWorkflow.spec.js index f0a7dd791a..9a4b372f02 100644 --- a/packages/builder/cypress/integration/appPublishWorkflow.spec.js +++ b/packages/builder/cypress/integration/appPublishWorkflow.spec.js @@ -83,9 +83,8 @@ 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 }) }) @@ -96,11 +95,8 @@ filterTests(['all'], () => { 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") }) }) From ccc584bdf212212a2774b7be379661ca6948c2fd Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Wed, 8 Jun 2022 18:08:45 +0100 Subject: [PATCH 03/15] Edit User Details Test + Timeout Changes for Commands New user test - Edits user details (for now just adds first name and last name) Commands updated - Removing some waits and replacing with timeouts associated with 'get' Cypress functionality --- .../integration/createUserAndRoles.spec.js | 29 ++++++++++-- packages/builder/cypress/support/commands.js | 46 +++++++++---------- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/packages/builder/cypress/integration/createUserAndRoles.spec.js b/packages/builder/cypress/integration/createUserAndRoles.spec.js index d47a96ed8d..2c3dd223db 100644 --- a/packages/builder/cypress/integration/createUserAndRoles.spec.js +++ b/packages/builder/cypress/integration/createUserAndRoles.spec.js @@ -19,9 +19,8 @@ filterTests(["smoke", "all"], () => { it("should confirm there is No Access for a New User", () => { // Click into the user 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") + cy.get(interact.SPECTRUM_TABLE, { timeout: 500 }).eq(1).should("not.contain", "No rows found") // Get Configure Roles table - Confirm it has no apps cy.get(interact.SPECTRUM_TABLE).eq(0).contains("No rows found") }) @@ -40,8 +39,7 @@ 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) } } @@ -174,6 +172,29 @@ filterTests(["smoke", "all"], () => { }) }) + it("Should edit user details", () => { + // Add First name + cy.get(".field").eq(2).within(() => { + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).type("bb") + }) + // Add Last name + cy.get(".field").eq(3).within(() => { + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).type("test") + }) + // Navigate away and back to the user + cy.contains("Apps").click() + cy.contains("Users").click() + cy.contains("bbuser").click() + + // Confirm details have been saved + cy.get(".field").eq(2).within(() => { + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', "bb") + }) + cy.get(".field").eq(3).within(() => { + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', "test") + }) + }) + it("should delete a user", () => { // Click Delete user button cy.get(interact.SPECTRUM_BUTTON) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index 804b22f0fc..5484a45efa 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -96,8 +96,7 @@ Cypress.Commands.add("createApp", (name, addDefaultTable) => { 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.get(`[data-cy="create-app-btn"]`, { timeout: 1000 }).click({ force: true }) // If apps already exist cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) @@ -286,9 +285,10 @@ Cypress.Commands.add("importApp", (exportFilePath, name) => { .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.get(`[data-cy="import-app-btn"]`, { timeout: 500 }).click({ + force: true, + }) }) cy.get(".spectrum-Modal").within(() => { @@ -363,16 +363,14 @@ Cypress.Commands.add("createTable", (tableName, initialTable) => { cy.navigateToDataSection() cy.get(`[data-cy="new-table"]`).click() } - cy.wait(5000) - cy.get(".spectrum-Dialog-grid") + cy.get(".spectrum-Dialog-grid", { timeout: 5000 }) .contains("Budibase DB") .click({ force: true }) .then(() => { 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") @@ -454,8 +452,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) }) } @@ -499,15 +496,13 @@ 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.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(".spectrum-Modal").within(() => { + cy.get(".spectrum-Modal", { timeout: 1000 }).within(() => { if (accessLevelLabel) { cy.get(".spectrum-Picker-label").click() cy.wait(500) @@ -525,9 +520,10 @@ 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.get(".data-source-entry").contains(datasourceNames[i]).click() //Ensure the check mark is visible @@ -577,7 +573,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() @@ -609,8 +605,7 @@ 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 }) }) @@ -621,8 +616,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(() => { @@ -722,16 +716,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) From 8b41e9bca6529712a2c058f46369814e428acf40 Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Fri, 17 Jun 2022 17:41:07 +0100 Subject: [PATCH 04/15] AdminAndManagement Test folder + timeouts refactoring Created a new folder called adminAndManagement - contains user and portal based tests Timeouts refactoring - Replacing a large number of waits with timeouts - this will prevent less time waiting during all testing --- .../addMultiOptionDatatype.spec.js | 5 +- .../adminAndManagement/accountPortal.spec.js | 59 +++++++++ .../userManagement.spec.js} | 118 +++++++++++------- .../cypress/integration/appOverview.spec.js | 9 +- .../integration/appPublishWorkflow.spec.js | 9 +- .../cypress/integration/createApp.spec.js | 11 +- .../integration/createAutomation.spec.js | 12 +- .../cypress/integration/createTable.spec.js | 14 +-- .../cypress/integration/createView.spec.js | 3 +- .../customThemingProperties.spec.js | 1 - .../datasources/datasourceWizard.spec.js | 3 +- .../integration/datasources/mySql.spec.js | 9 +- .../integration/datasources/oracle.spec.js | 9 +- .../datasources/postgreSql.spec.js | 16 +-- .../integration/datasources/rest.spec.js | 6 +- .../integration/renameAnApplication.spec.js | 18 +-- .../cypress/integration/revertApp.spec.js | 9 +- packages/builder/cypress/support/commands.js | 29 +++-- packages/builder/cypress/support/interact.js | 3 +- 19 files changed, 192 insertions(+), 151 deletions(-) create mode 100644 packages/builder/cypress/integration/adminAndManagement/accountPortal.spec.js rename packages/builder/cypress/integration/{createUserAndRoles.spec.js => adminAndManagement/userManagement.spec.js} (60%) 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/accountPortal.spec.js b/packages/builder/cypress/integration/adminAndManagement/accountPortal.spec.js new file mode 100644 index 0000000000..3d952949de --- /dev/null +++ b/packages/builder/cypress/integration/adminAndManagement/accountPortal.spec.js @@ -0,0 +1,59 @@ +import filterTests from "../../support/filterTests" +const interact = require('../../support/interact') + +filterTests(["smoke", "all"], () => { + context("Account Portal", () => { + before(() => { + cy.login() + cy.deleteApp("Cypress Tests") + cy.createApp("Cypress Tests") + + // Create new user + cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 1000}) + cy.createUser("bbuser@test.com") + cy.contains("bbuser").click() + + // Reset password + cy.get(interact.REGENERATE, { timeout: 500 }).click({ force: true }) + const newPwd = cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).its('value') + cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").click({ force: true }) + + // Login as new user and set password + cy.logOut() + cy.login("bbuser@test.com", newPwd) + 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.logOut() + }) + + it("should verify Admin Portal", () => { + cy.login() + // Enable Development & Administration access + 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') + }) + } + // Login as new user + cy.logOut() + cy.login("bbuser@test.com", "test") + + // Enter developer mode + cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) + cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => { + cy.get(".spectrum-Menu-itemLabel").contains("Open developer mode").click({ force: true }) + }) + cy.get(".spectrum-SideNav") + .should('contain', 'Apps') + .and('contain', 'Users') + .and('contain', 'Auth') + .and('contain', 'Email') + .and('contain', 'Organisation') + .and('contain', 'Theming') + .and('contain', 'Update') + }) + }) +}) diff --git a/packages/builder/cypress/integration/createUserAndRoles.spec.js b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js similarity index 60% rename from packages/builder/cypress/integration/createUserAndRoles.spec.js rename to packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js index 2c3dd223db..323f401ff8 100644 --- a/packages/builder/cypress/integration/createUserAndRoles.spec.js +++ b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js @@ -1,27 +1,32 @@ -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() - // Get No Access table - Confirm it has apps in it + // Confirm development and admin access are disabled + for (let i = 4; i < 6; i++) { + cy.get(interact.FIELD).eq(i).within(() => { + cy.get(interact.SPECTRUM_SWITCH_INPUT).should('be.disabled') + }) + } + // Existing apps appear within the No Access table cy.get(interact.SPECTRUM_TABLE, { timeout: 500 }).eq(1).should("not.contain", "No rows found") - // Get Configure Roles table - Confirm it has no apps + // Configure roles table should not contain apps cy.get(interact.SPECTRUM_TABLE).eq(0).contains("No rows found") }) @@ -46,12 +51,9 @@ filterTests(["smoke", "all"], () => { } }) // 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) @@ -60,31 +62,27 @@ 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() } // 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") @@ -110,21 +108,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) @@ -156,15 +152,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(() => { @@ -172,45 +168,75 @@ filterTests(["smoke", "all"], () => { }) }) - it("Should edit user details", () => { + it("Should edit user details within user details page", () => { // Add First name - cy.get(".field").eq(2).within(() => { + cy.get(interact.FIELD, { timeout: 500 }).eq(2).within(() => { cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).type("bb") }) // Add Last name - cy.get(".field").eq(3).within(() => { + cy.get(interact.FIELD).eq(3).within(() => { cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).type("test") }) - // Navigate away and back to the user - cy.contains("Apps").click() - cy.contains("Users").click() - cy.contains("bbuser").click() + // Reload page + cy.reload() // Confirm details have been saved - cy.get(".field").eq(2).within(() => { + cy.get(interact.FIELD, { timeout: 1000 }).eq(2).within(() => { cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', "bb") }) - cy.get(".field").eq(3).within(() => { + cy.get(interact.FIELD).eq(3).within(() => { cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', "test") }) }) + it("should reset the users password", () => { + cy.get(interact.REGENERATE, { timeout: 500 }).click({ force: true }) + + // Reset password modal + const newPwd = cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).its('value') + cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").click({ force: true }) + + // Logout, then login with new password + cy.logOut() + cy.login("bbuser@test.com", newPwd) + + // 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(".user-dropdown .avatar > .icon").click({ force: true }) + + cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => { + cy.get("li[data-cy='user-info']").click({ force: true }) + }) + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).its('value').should('eq', 'bbuser@test.com') + + // Logout and login as previous user + cy.logOut() + cy.login() + }) + it("should delete a user", () => { + // Navigate to test user + cy.contains("Users").click() + cy.contains("bbuser").click() + // 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_DIALOG_GRID, { timeout: 500 }).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.get(interact.SPECTRUM_TABLE, { timeout: 4000 }).should("not.have.text", "bbuser") }) }) }) diff --git a/packages/builder/cypress/integration/appOverview.spec.js b/packages/builder/cypress/integration/appOverview.spec.js index 7acfbc5f69..6a5ec10076 100644 --- a/packages/builder/cypress/integration/appOverview.spec.js +++ b/packages/builder/cypress/integration/appOverview.spec.js @@ -222,10 +222,9 @@ filterTests(['all'], () => { 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").contains("Update").click({ force: true }) @@ -273,14 +272,12 @@ filterTests(['all'], () => { }); cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(1000) - cy.get(".appTable .name").eq(0).click() + cy.get(".appTable .name", { timeout: 1000 }).eq(0).click() cy.get(".spectrum-Tabs-item").contains("Settings").click() 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("be.disabled") + cy.get(".details-section .page-action .spectrum-Button", { timeout: 1000 }).should("be.disabled") }) diff --git a/packages/builder/cypress/integration/appPublishWorkflow.spec.js b/packages/builder/cypress/integration/appPublishWorkflow.spec.js index 9a4b372f02..661d79d04b 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: 1000 }).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: 1000 }).eq(0) .within(() => { cy.contains("Published") cy.get(interact.GLOBE).should("exist") diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index df617e3d9f..99f28e7d71 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -49,10 +49,9 @@ filterTests(['smoke', 'all'], () => { it("should enforce a valid url before submission", () => { cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(500) // 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 => { @@ -95,7 +94,6 @@ filterTests(['smoke', 'all'], () => { cy.createApp(appName) cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(1000) cy.applicationInAppTable(appName) cy.deleteApp(appName) @@ -105,7 +103,6 @@ filterTests(['smoke', 'all'], () => { cy.createApp() cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(1000) cy.applicationInAppTable("My app") cy.deleteApp("My app") @@ -119,11 +116,9 @@ filterTests(['smoke', 'all'], () => { cy.createApp() 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") @@ -131,11 +126,9 @@ filterTests(['smoke', 'all'], () => { cy.createApp() cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(1000) cy.applicationInAppTable("Chris app") cy.deleteApp("Chris app") - cy.wait(2000) cy.updateUserInformation("", "") }) @@ -224,14 +217,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/createTable.spec.js b/packages/builder/cypress/integration/createTable.spec.js index 7d55a1f03c..4be693ee8f 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,9 +39,8 @@ filterTests(["smoke", "all"], () => { it("edits a row", () => { cy.contains("button", "Edit").click({ force: true }) - cy.wait(1000) - cy.get(interact.SPECTRUM_MODAL_INPUT).clear() - cy.get(interact.SPECTRUM_MODAL_INPUT).type("Updated") + cy.get(interact.SPECTRUM_MODAL_INPUT, { timeout: 1000 }).clear() + cy.get(interact.SPECTRUM_MODAL_INPUT, { timeout: 1000 }).type("Updated") cy.contains("Save").click() cy.contains("Updated").should("have.text", "Updated") }) @@ -63,8 +61,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 +76,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 feaf1c3b5f..80cbb8dd63 100644 --- a/packages/builder/cypress/integration/createView.spec.js +++ b/packages/builder/cypress/integration/createView.spec.js @@ -68,9 +68,8 @@ filterTests(['smoke', 'all'], () => { cy.get(".spectrum-Button").contains("Save").click({ force: true }) }) - cy.wait(1000) - cy.get(".title").then($headers => { + cy.get(".title", { timeout: 1000 }).then($headers => { expect($headers).to.have.length(7) const headers = Array.from($headers).map(header => header.textContent.trim() 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..a83ab9a615 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") @@ -137,9 +136,8 @@ filterTests(["all"], () => { .eq(1) .within(() => { cy.get(".spectrum-Table-row").eq(0).click({ force: true }) - 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 }) @@ -217,9 +215,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..531f36eae7 100644 --- a/packages/builder/cypress/integration/datasources/oracle.spec.js +++ b/packages/builder/cypress/integration/datasources/oracle.spec.js @@ -18,9 +18,8 @@ filterTests(["all"], () => { cy.get(".spectrum-Button") .contains("Skip table fetch") .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 +139,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 +219,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..db4b506669 100644 --- a/packages/builder/cypress/integration/datasources/postgreSql.spec.js +++ b/packages/builder/cypress/integration/datasources/postgreSql.spec.js @@ -114,9 +114,8 @@ filterTests(["all"], () => { .eq(1) .within(() => { cy.get(".spectrum-Table-row").eq(0).click({ force: true }) - 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 }) }) cy.reload() @@ -159,7 +158,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 +169,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 +183,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") @@ -229,8 +228,7 @@ 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.get(".nav-item").should("contain", queryRename) }) @@ -247,9 +245,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 +268,6 @@ filterTests(["all"], () => { .click({ force: true }) }) cy.reload() - cy.wait(5000) } } }) 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 7e611ac4ec..caf3c6173f 100644 --- a/packages/builder/cypress/integration/renameAnApplication.spec.js +++ b/packages/builder/cypress/integration/renameAnApplication.spec.js @@ -12,16 +12,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(".appTable").find(".title").should("have.length", 1) cy.applicationInAppTable(appRename) // Set app name back to Cypress Tests cy.reload() - cy.wait(1000) renameApp(appRename, appName) }) @@ -39,7 +36,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(".appTable").find(".wrapper").should("have.length", 1) cy.applicationInAppTable(appRename) @@ -48,13 +44,10 @@ 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(".spectrum-Dialog-grid").contains("Cancel").click() + cy.get(".spectrum-Dialog-grid", { timeout: 1000 }).contains("Cancel").click() cy.reload() - cy.wait(1000) cy.applicationInAppTable(appName) }) @@ -62,8 +55,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(".spectrum-Button").contains("Create app").click({ force: true }) + cy.get(".spectrum-Button", { timeout: 500 }).contains("Create app").click({ force: true }) cy.contains(/Start from scratch/).click() cy.get(".spectrum-Modal") .within(() => { @@ -80,24 +72,20 @@ 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(".error").should("have.text", "App name must be letters, numbers and spaces only") // 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(".appTable") + cy.get(".appTable", { timeout: 1000 }) .within(() => { cy.get("[aria-label='More']").eq(0).click() }) diff --git a/packages/builder/cypress/integration/revertApp.spec.js b/packages/builder/cypress/integration/revertApp.spec.js index 01d5a04981..e18915295a 100644 --- a/packages/builder/cypress/integration/revertApp.spec.js +++ b/packages/builder/cypress/integration/revertApp.spec.js @@ -35,8 +35,7 @@ filterTests(['smoke', 'all'], () => { cy.get(".spectrum-ButtonGroup").within(() => { cy.get(".spectrum-Button").contains("Publish").click({ force: true }) }) - cy.wait(1000) - cy.get(".spectrum-ButtonGroup").within(() => { + cy.get(".spectrum-ButtonGroup", { timeout: 1000 }).within(() => { cy.get(".spectrum-Button").contains("Done").click({ force: true }) }) @@ -49,18 +48,16 @@ filterTests(['smoke', 'all'], () => { cy.get(".spectrum-Dialog-grid").within(() => { // Click Revert cy.get(".spectrum-Button").contains("Revert").click({ force: true }) - cy.wait(1000) }) // Confirm Paragraph component is still visible - cy.get(".root").contains("New Paragraph") + cy.get(".root", { timeout: 1000 }).contains("New Paragraph") // Confirm Button component is not visible cy.get(".root").should("not.have.text", "New Button") - cy.wait(500) }) it("should enter incorrect app name when reverting", () => { // Click Revert - cy.get(".toprightnav").within(() => { + cy.get(".toprightnav", { timeout: 1000 }).within(() => { cy.get("[aria-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 5484a45efa..9476812ef1 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 || password == 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) }) @@ -42,7 +47,7 @@ Cypress.Commands.add("createUser", email => { cy.get(".spectrum-Picker-label").click() cy.get(".spectrum-Menu-item:nth-child(2) > .spectrum-Menu-itemLabel").click() - //Onboarding type selector + // Onboarding type selector cy.get( ":nth-child(2) > .spectrum-Form-itemField > .spectrum-Textfield > .spectrum-Textfield-input" ) @@ -52,7 +57,9 @@ Cypress.Commands.add("createUser", email => { }) 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 }) @@ -96,7 +103,7 @@ Cypress.Commands.add("createApp", (name, addDefaultTable) => { typeof addDefaultTable != "boolean" ? true : addDefaultTable cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(`[data-cy="create-app-btn"]`, { timeout: 1000 }).click({ force: true }) + 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`) @@ -335,7 +342,7 @@ Cypress.Commands.add("searchForApplication", appName => { // Assumes there are no others Cypress.Commands.add("applicationInAppTable", appName => { - cy.get(".appTable").within(() => { + cy.get(".appTable", { timeout: 1000 }).within(() => { cy.get(".title").contains(appName).should("exist") }) }) @@ -464,10 +471,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(2000) cy.location().then(loc => { diff --git a/packages/builder/cypress/support/interact.js b/packages/builder/cypress/support/interact.js index 4a70b2fa8c..516586b407 100644 --- a/packages/builder/cypress/support/interact.js +++ b/packages/builder/cypress/support/interact.js @@ -97,10 +97,11 @@ 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" From 55432388cff332e31a3d81b26027bec801863a28 Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Mon, 20 Jun 2022 18:38:44 +0100 Subject: [PATCH 05/15] Account Portal tests + Command file changes Account portal tests - Visibility when accessing the portal with different permissions Commands - New command to logout when app grid is not present - Need matching data-cy commands for this --- .../adminAndManagement/accountPortal.spec.js | 59 --------- .../adminAndManagement/accountPortals.spec.js | 123 ++++++++++++++++++ packages/builder/cypress/support/commands.js | 14 +- 3 files changed, 135 insertions(+), 61 deletions(-) delete mode 100644 packages/builder/cypress/integration/adminAndManagement/accountPortal.spec.js create mode 100644 packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js diff --git a/packages/builder/cypress/integration/adminAndManagement/accountPortal.spec.js b/packages/builder/cypress/integration/adminAndManagement/accountPortal.spec.js deleted file mode 100644 index 3d952949de..0000000000 --- a/packages/builder/cypress/integration/adminAndManagement/accountPortal.spec.js +++ /dev/null @@ -1,59 +0,0 @@ -import filterTests from "../../support/filterTests" -const interact = require('../../support/interact') - -filterTests(["smoke", "all"], () => { - context("Account Portal", () => { - before(() => { - cy.login() - cy.deleteApp("Cypress Tests") - cy.createApp("Cypress Tests") - - // Create new user - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 1000}) - cy.createUser("bbuser@test.com") - cy.contains("bbuser").click() - - // Reset password - cy.get(interact.REGENERATE, { timeout: 500 }).click({ force: true }) - const newPwd = cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).its('value') - cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").click({ force: true }) - - // Login as new user and set password - cy.logOut() - cy.login("bbuser@test.com", newPwd) - 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.logOut() - }) - - it("should verify Admin Portal", () => { - cy.login() - // Enable Development & Administration access - 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') - }) - } - // Login as new user - cy.logOut() - cy.login("bbuser@test.com", "test") - - // Enter developer mode - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) - cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => { - cy.get(".spectrum-Menu-itemLabel").contains("Open developer mode").click({ force: true }) - }) - cy.get(".spectrum-SideNav") - .should('contain', 'Apps') - .and('contain', 'Users') - .and('contain', 'Auth') - .and('contain', 'Email') - .and('contain', 'Organisation') - .and('contain', 'Theming') - .and('contain', 'Update') - }) - }) -}) 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..b929fe84a2 --- /dev/null +++ b/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js @@ -0,0 +1,123 @@ +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 + }) + + const bbUserLogin = () => { + // Login as bbuser + cy.logOut() + cy.login(bbUserEmail, "test") + } + }) +}) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index c046664bc2..f480dd69c0 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -17,7 +17,7 @@ Cypress.Commands.add("login", (email, password) => { if (url.includes("builder/auth/login") || url.includes("builder/admin")) { // login cy.contains("Sign in to Budibase").then(() => { - if (email == null || password == null) { + if (email == null) { cy.get("input").first().type("test@test.com") cy.get('input[type="password"]').type("test") } else { @@ -40,6 +40,16 @@ 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() @@ -123,7 +133,7 @@ Cypress.Commands.add("createApp", (name, addDefaultTable) => { cy.get(".spectrum-ButtonGroup") .contains("Create app") .click({ force: true }) - cy.wait(10000) + cy.wait(5000) }) if (shouldCreateDefaultTable) { cy.createTable("Cypress Tests", true) From d707b504f6c53ee8cb580975c0239f0b88c98d38 Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Tue, 21 Jun 2022 18:25:33 +0100 Subject: [PATCH 06/15] User Settings Menu tests New test file with user setting menu tests - Also updated AccountPortals test (logout was required) Commands & Interact files updated as required --- .../adminAndManagement/accountPortals.spec.js | 2 + .../adminAndManagement/userSettings.spec.js | 108 ++++++++++++++++++ packages/builder/cypress/support/commands.js | 2 +- packages/builder/cypress/support/interact.js | 11 +- 4 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js diff --git a/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js b/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js index b929fe84a2..c65f818a26 100644 --- a/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js +++ b/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js @@ -112,6 +112,8 @@ filterTests(["smoke", "all"], () => { 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.logOut() }) const bbUserLogin = () => { 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/support/commands.js b/packages/builder/cypress/support/commands.js index 036517e7b9..e84f604122 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -133,7 +133,7 @@ Cypress.Commands.add("createApp", (name, addDefaultTable) => { cy.get(".spectrum-ButtonGroup") .contains("Create app") .click({ force: true }) - cy.wait(5000) + cy.wait(2000) }) if (shouldCreateDefaultTable) { cy.createTable("Cypress Tests", true) diff --git a/packages/builder/cypress/support/interact.js b/packages/builder/cypress/support/interact.js index 059d75584a..7cf786625a 100644 --- a/packages/builder/cypress/support/interact.js +++ b/packages/builder/cypress/support/interact.js @@ -105,6 +105,8 @@ 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" @@ -114,14 +116,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" From 66c3991b55e2718eb718e51cc563ec98a5cc308a Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Wed, 22 Jun 2022 18:55:43 +0100 Subject: [PATCH 07/15] AdminAndManagement test changes + Commands update Specifically changes for accountPortals & userManagement Commands - Delete user function added - Few timing changes --- .../adminAndManagement/accountPortals.spec.js | 8 +++- .../adminAndManagement/userManagement.spec.js | 17 +------ packages/builder/cypress/support/commands.js | 45 ++++++++++++++----- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js b/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js index c65f818a26..c615b2b4e6 100644 --- a/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js +++ b/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js @@ -113,7 +113,7 @@ filterTests(["smoke", "all"], () => { 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.logOut() + cy.logoutNoAppGrid() }) const bbUserLogin = () => { @@ -121,5 +121,11 @@ filterTests(["smoke", "all"], () => { cy.logOut() cy.login(bbUserEmail, "test") } + + after(() => { + cy.login() + // Delete BB user + cy.deleteUser(bbUserEmail) + }) }) }) diff --git a/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js index 323f401ff8..265ccdb5ed 100644 --- a/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js +++ b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js @@ -220,22 +220,7 @@ filterTests(["smoke", "all"], () => { }) it("should delete a user", () => { - // Navigate to test user - cy.contains("Users").click() - cy.contains("bbuser").click() - - // Click Delete user button - cy.get(interact.SPECTRUM_BUTTON) - .contains("Delete user") - .click({ force: true }) - .then(() => { - // Confirm deletion within modal - cy.get(interact.SPECTRUM_DIALOG_GRID, { timeout: 500 }).within(() => { - cy.get(interact.SPECTRUM_BUTTON) - .contains("Delete user") - .click({ force: true }) - }) - }) + cy.deleteUser("bbuser@test.com") cy.get(interact.SPECTRUM_TABLE, { timeout: 4000 }).should("not.have.text", "bbuser") }) }) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index e84f604122..c98ea17d80 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -32,7 +32,7 @@ Cypress.Commands.add("login", (email, password) => { }) 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 }) @@ -54,16 +54,38 @@ 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) => { @@ -377,7 +399,8 @@ Cypress.Commands.add("createTable", (tableName, initialTable) => { cy.navigateToDataSection() cy.get(`[data-cy="new-table"]`).click() } - cy.get(".spectrum-Dialog-grid", { timeout: 5000 }) + cy.wait(500) + cy.get(".spectrum-Dialog-grid") .contains("Budibase DB") .click({ force: true }) .then(() => { From 60592616f80063a2069272ad17088e4f9684e9ec Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Mon, 27 Jun 2022 18:28:21 +0100 Subject: [PATCH 08/15] Test Refactoring AdminAndManagement + Datasources tests are being being refactored here --- .../adminAndManagement/userManagement.spec.js | 31 ++++++++++++------- .../cypress/integration/appOverview.spec.js | 6 +--- .../integration/datasources/mySql.spec.js | 3 +- .../integration/datasources/oracle.spec.js | 1 + .../datasources/postgreSql.spec.js | 8 ++++- packages/builder/cypress/support/commands.js | 1 + 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js index 265ccdb5ed..3c23086136 100644 --- a/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js +++ b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js @@ -20,8 +20,10 @@ filterTests(["smoke", "all"], () => { cy.contains("bbuser").click() // 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(interact.SPECTRUM_SWITCH_INPUT).should('be.disabled') + cy.get(".spectrum-Switch-switch").should('not.be.checked') }) } // Existing apps appear within the No Access table @@ -80,6 +82,7 @@ filterTests(["smoke", "all"], () => { .click({ force: true }) }) cy.reload() + cy.wait(1000) } // Confirm roles exist within Configure roles table cy.get(interact.SPECTRUM_TABLE, { timeout: 2000 }) @@ -171,12 +174,13 @@ 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).type("bb") + 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() @@ -185,20 +189,23 @@ filterTests(["smoke", "all"], () => { cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', "bb") }) cy.get(interact.FIELD).eq(3).within(() => { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', "test") + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 500 }).should('have.value', "test") }) }) it("should reset the users password", () => { - cy.get(interact.REGENERATE, { timeout: 500 }).click({ force: true }) + cy.get(interact.REGENERATE, { timeout: 500 }).contains("Force password reset").click({ force: true }) // Reset password modal - const newPwd = cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).its('value') + 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.login("bbuser@test.com", newPwd) + cy.get('@pwd').then((pwd) => { + cy.login("bbuser@test.com", pwd) + }) // Reset password screen for (let i = 0; i < 2; i++) { @@ -207,15 +214,15 @@ filterTests(["smoke", "all"], () => { cy.get(interact.SPECTRUM_BUTTON).contains("Reset your password").click({ force: true }) // Confirm user logged in afer password change - cy.get(".user-dropdown .avatar > .icon").click({ force: true }) + cy.get(".avatar > .icon").click({ force: true }) - cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => { - cy.get("li[data-cy='user-info']").click({ force: true }) - }) - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).its('value').should('eq', 'bbuser@test.com') + 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.logOut() + cy.logoutNoAppGrid() cy.login() }) diff --git a/packages/builder/cypress/integration/appOverview.spec.js b/packages/builder/cypress/integration/appOverview.spec.js index b25a53a916..a78578facf 100644 --- a/packages/builder/cypress/integration/appOverview.spec.js +++ b/packages/builder/cypress/integration/appOverview.spec.js @@ -158,11 +158,7 @@ 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(".app-icon", { timwout: 1000 }).click({ force: true }) // Select random icon cy.get(".grid").within(() => { cy.get(".icon-item") diff --git a/packages/builder/cypress/integration/datasources/mySql.spec.js b/packages/builder/cypress/integration/datasources/mySql.spec.js index a83ab9a615..b79f5af9c6 100644 --- a/packages/builder/cypress/integration/datasources/mySql.spec.js +++ b/packages/builder/cypress/integration/datasources/mySql.spec.js @@ -135,7 +135,7 @@ filterTests(["all"], () => { cy.get(".spectrum-Table") .eq(1) .within(() => { - cy.get(".spectrum-Table-row").eq(0).click({ force: true }) + cy.get(".spectrum-Table-cell").eq(0).click({ force: true }) }) cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => { cy.get(".spectrum-Button") @@ -143,6 +143,7 @@ filterTests(["all"], () => { .click({ force: true }) }) cy.reload() + cy.wait(500) } // Confirm relationships no longer exist cy.get(".spectrum-Body").should( diff --git a/packages/builder/cypress/integration/datasources/oracle.spec.js b/packages/builder/cypress/integration/datasources/oracle.spec.js index 531f36eae7..92a5737ff9 100644 --- a/packages/builder/cypress/integration/datasources/oracle.spec.js +++ b/packages/builder/cypress/integration/datasources/oracle.spec.js @@ -18,6 +18,7 @@ filterTests(["all"], () => { cy.get(".spectrum-Button") .contains("Skip table fetch") .click({ force: true }) + cy.wait(500) // Confirm config contains localhost cy.get(".spectrum-Textfield-input", { timeout: 500 }) .eq(1) diff --git a/packages/builder/cypress/integration/datasources/postgreSql.spec.js b/packages/builder/cypress/integration/datasources/postgreSql.spec.js index db4b506669..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,12 +114,13 @@ filterTests(["all"], () => { cy.get(".spectrum-Table") .eq(1) .within(() => { - cy.get(".spectrum-Table-row").eq(0).click({ force: true }) + cy.get(".spectrum-Table-cell").eq(0).click({ force: true }) }) 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) @@ -228,7 +230,10 @@ filterTests(["all"], () => { // Run and Save query cy.get(".spectrum-Button").contains("Run Query").click({ force: true }) + cy.wait(500) cy.get(".spectrum-Button", { timeout: 500 }).contains("Save Query").click({ force: true }) + //cy.reload() + //cy.wait(500) cy.get(".nav-item").should("contain", queryRename) }) @@ -268,6 +273,7 @@ filterTests(["all"], () => { .click({ force: true }) }) cy.reload() + cy.wait(1000) } } }) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index 099f57932d..8d60d243e0 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -650,6 +650,7 @@ Cypress.Commands.add("selectExternalDatasource", datasourceName => { cy.get(".spectrum-Dialog-grid").within(() => { cy.get(".spectrum-Button").contains("Continue").click({ force: true }) }) + cy.wait(500) }) Cypress.Commands.add("addDatasourceConfig", (datasource, skipFetch) => { From 5fb18d4d79416174bb8148f966ab6e0a33b5b9a4 Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Tue, 28 Jun 2022 18:01:04 +0100 Subject: [PATCH 09/15] appOverview Refactor + Commands update Refactoring tests within appOverview.spec.js Commands - refactoring the deleteApp command (works better with new UI) --- .../cypress/integration/appOverview.spec.js | 25 ++++++++----------- packages/builder/cypress/support/commands.js | 9 ++++--- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/builder/cypress/integration/appOverview.spec.js b/packages/builder/cypress/integration/appOverview.spec.js index a78578facf..244c0c89d4 100644 --- a/packages/builder/cypress/integration/appOverview.spec.js +++ b/packages/builder/cypress/integration/appOverview.spec.js @@ -158,8 +158,9 @@ filterTests(["all"], () => { .contains("Manage") .eq(0) .click({ force: true }) - cy.get(".app-icon", { timwout: 1000 }).click({ force: true }) + 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) @@ -178,6 +179,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) @@ -368,10 +370,10 @@ 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", () => { @@ -380,15 +382,9 @@ filterTests(["all"], () => { .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']") @@ -399,9 +395,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/support/commands.js b/packages/builder/cypress/support/commands.js index 8d60d243e0..6bd6074eda 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -188,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 }) }) } }) From 7495b859c8330b027a5104ab05f874210c066e1b Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Wed, 29 Jun 2022 18:28:32 +0100 Subject: [PATCH 10/15] Cypress Tests Refactoring Refactoring a large portion of tests - necessary updates to have them working (may still be timing issues on the smoke build) --- .../builder/cypress/integration/appOverview.spec.js | 3 +-- .../cypress/integration/appPublishWorkflow.spec.js | 13 +++++++++---- .../{createScreen.js => createScreen.spec.js} | 0 .../builder/cypress/integration/createTable.spec.js | 5 +++-- .../builder/cypress/integration/createView.spec.js | 3 ++- .../cypress/integration/renameAnApplication.spec.js | 1 - .../builder/cypress/integration/revertApp.spec.js | 3 ++- packages/builder/cypress/support/commands.js | 9 ++++++--- packages/builder/cypress/support/interact.js | 1 + 9 files changed, 24 insertions(+), 14 deletions(-) rename packages/builder/cypress/integration/{createScreen.js => createScreen.spec.js} (100%) diff --git a/packages/builder/cypress/integration/appOverview.spec.js b/packages/builder/cypress/integration/appOverview.spec.js index 244c0c89d4..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") @@ -376,7 +375,7 @@ filterTests(["all"], () => { .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") diff --git a/packages/builder/cypress/integration/appPublishWorkflow.spec.js b/packages/builder/cypress/integration/appPublishWorkflow.spec.js index 661d79d04b..a431051075 100644 --- a/packages/builder/cypress/integration/appPublishWorkflow.spec.js +++ b/packages/builder/cypress/integration/appPublishWorkflow.spec.js @@ -12,7 +12,7 @@ filterTests(['all'], () => { it("Should reflect the unpublished status correctly", () => { cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(interact.APP_TABLE_STATUS, { timeout: 1000 }).eq(0) + cy.get(interact.APP_TABLE_STATUS, { timeout: 3000 }).eq(0) .within(() => { cy.contains("Unpublished") cy.get(interact.GLOBESTRIKE).should("exist") @@ -47,7 +47,7 @@ filterTests(['all'], () => { cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(interact.APP_TABLE_STATUS, { timeout: 1000 }).eq(0) + cy.get(interact.APP_TABLE_STATUS, { timeout: 3000 }).eq(0) .within(() => { cy.contains("Published") cy.get(interact.GLOBE).should("exist") @@ -55,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 }) }) @@ -85,7 +85,12 @@ filterTests(['all'], () => { 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(() => { 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 4be693ee8f..da73c19fa6 100644 --- a/packages/builder/cypress/integration/createTable.spec.js +++ b/packages/builder/cypress/integration/createTable.spec.js @@ -39,8 +39,9 @@ filterTests(["smoke", "all"], () => { it("edits a row", () => { cy.contains("button", "Edit").click({ force: true }) - cy.get(interact.SPECTRUM_MODAL_INPUT, { timeout: 1000 }).clear() - cy.get(interact.SPECTRUM_MODAL_INPUT, { timeout: 1000 }).type("Updated") + cy.wait(500) + cy.get(interact.SPECTRUM_MODAL_INPUT).clear() + cy.get(interact.SPECTRUM_MODAL_INPUT).type("Updated") cy.contains("Save").click() cy.contains("Updated").should("have.text", "Updated") }) diff --git a/packages/builder/cypress/integration/createView.spec.js b/packages/builder/cypress/integration/createView.spec.js index fc89e61a5e..a2d09d97bf 100644 --- a/packages/builder/cypress/integration/createView.spec.js +++ b/packages/builder/cypress/integration/createView.spec.js @@ -70,7 +70,8 @@ filterTests(['smoke', 'all'], () => { cy.get(interact.SPECTRUM_BUTTON).contains("Save").click({ force: true }) }) - cy.get(interact.TITLE, { timeout: 1000 }).then($headers => { + cy.wait(1000) + cy.get(interact.TITLE).then($headers => { expect($headers).to.have.length(7) const headers = Array.from($headers).map(header => header.textContent.trim() diff --git a/packages/builder/cypress/integration/renameAnApplication.spec.js b/packages/builder/cypress/integration/renameAnApplication.spec.js index 8c92935481..370efadff2 100644 --- a/packages/builder/cypress/integration/renameAnApplication.spec.js +++ b/packages/builder/cypress/integration/renameAnApplication.spec.js @@ -51,7 +51,6 @@ filterTests(["all"], () => { renameApp(appName, " ", false, true) // Close modal and confirm name has not been changed cy.get(interact.SPECTRUM_DIALOG_GRID, { timeout: 1000 }).contains("Cancel").click() - cy.reload() cy.applicationInAppTable(appName) }) diff --git a/packages/builder/cypress/integration/revertApp.spec.js b/packages/builder/cypress/integration/revertApp.spec.js index ce59a4624a..4c6f245b76 100644 --- a/packages/builder/cypress/integration/revertApp.spec.js +++ b/packages/builder/cypress/integration/revertApp.spec.js @@ -36,6 +36,7 @@ filterTests(['smoke', 'all'], () => { cy.get(interact.SPECTRUM_BUTTON_GROUP).within(() => { cy.get(interact.SPECTRUM_BUTTON).contains("Publish").click({ force: true }) }) + 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 }) }) @@ -49,7 +50,7 @@ filterTests(['smoke', 'all'], () => { cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { // Click Revert cy.get(interact.SPECTRUM_BUTTON).contains("Revert").click({ force: true }) - + cy.wait(2000) // Wait for app to finish reverting }) // Confirm Paragraph component is still visible cy.get(interact.ROOT, { timeout: 1000 }).contains("New Paragraph") diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index 6bd6074eda..c5baec3f4e 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -372,7 +372,8 @@ Cypress.Commands.add("searchForApplication", appName => { // Assumes there are no others Cypress.Commands.add("applicationInAppTable", appName => { - cy.get(".appTable", { timeout: 1000 }).within(() => { + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.get(".appTable", { timeout: 2000 }).within(() => { cy.get(".title").contains(appName).should("exist") }) }) @@ -400,7 +401,7 @@ Cypress.Commands.add("createTable", (tableName, initialTable) => { cy.navigateToDataSection() cy.get(`[data-cy="new-table"]`).click() } - cy.wait(500) + cy.wait(2000) cy.get(".item") .contains("Budibase DB") .click({ force: true }) @@ -539,9 +540,10 @@ Cypress.Commands.add("createScreen", (route, accessLevelLabel) => { cy.get("[data-cy='blank-screen']").click() cy.get(".spectrum-Button").contains("Continue").click({ force: true }) }) + 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.get(".confirm-wrap").contains("Continue").click({ force: true }) }) cy.get(".spectrum-Modal", { timeout: 1000 }).within(() => { @@ -567,6 +569,7 @@ Cypress.Commands.add( 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") diff --git a/packages/builder/cypress/support/interact.js b/packages/builder/cypress/support/interact.js index 7cf786625a..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" From b5fcff3213980c78c4b2fd0bcefeb11c04bd9d49 Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Thu, 30 Jun 2022 11:41:11 +0100 Subject: [PATCH 11/15] CreateApp Test Update Timing issues affecting some tests - Updated some cy.visit commands to include timeouts --- packages/builder/cypress/integration/createApp.spec.js | 7 ++----- packages/builder/cypress/support/commands.js | 8 ++++---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index 99f28e7d71..628b97366c 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -48,7 +48,7 @@ filterTests(['smoke', 'all'], () => { }) it("should enforce a valid url before submission", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) // Start create app process. If apps already exist, click second button cy.get(interact.CREATE_APP_BUTTON, { timeout: 1000 }).click({ force: true }) @@ -101,9 +101,6 @@ filterTests(['smoke', 'all'], () => { it("should create the first application from scratch with a default name", () => { cy.createApp() - - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.applicationInAppTable("My app") cy.deleteApp("My app") }) @@ -138,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") diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index c5baec3f4e..8466603926 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -134,7 +134,7 @@ Cypress.Commands.add("createApp", (name, addDefaultTable) => { const shouldCreateDefaultTable = typeof addDefaultTable != "boolean" ? true : addDefaultTable - cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) cy.get(`[data-cy="create-app-btn"]`, { timeout: 2000 }).click({ force: true }) // If apps already exist @@ -315,7 +315,7 @@ 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") @@ -343,7 +343,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) }) }) @@ -372,7 +372,7 @@ Cypress.Commands.add("searchForApplication", appName => { // Assumes there are no others Cypress.Commands.add("applicationInAppTable", appName => { - cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 2000 }) cy.get(".appTable", { timeout: 2000 }).within(() => { cy.get(".title").contains(appName).should("exist") }) From 0d4773241b473d36e2c255a40776976799bf47af Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Thu, 30 Jun 2022 12:30:53 +0100 Subject: [PATCH 12/15] Additional timing changes for CreateApp test file Timing issues against the CI run - included more timeouts as a result of this --- packages/builder/cypress/integration/createApp.spec.js | 6 +++--- packages/builder/cypress/support/commands.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index 628b97366c..a4cb759ebd 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -11,9 +11,9 @@ filterTests(['smoke', 'all'], () => { 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`) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index 8466603926..b8b705bc53 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -163,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") From 0941615b94be1fa99397266dbf66ff581ec2327b Mon Sep 17 00:00:00 2001 From: Mitch-Budibase Date: Thu, 30 Jun 2022 13:53:16 +0100 Subject: [PATCH 13/15] Additional timing based changes for createApp All tests pass locally, just having issues with timing on the CI run Also reduced test retries (runs a total of 2 times instead of 3, the 3rd run does not add any value) --- packages/builder/cypress.json | 2 +- .../builder/cypress/integration/createApp.spec.js | 12 ++++++------ packages/builder/cypress/support/commands.js | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) 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/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index a4cb759ebd..097b70db30 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -6,7 +6,7 @@ filterTests(['smoke', 'all'], () => { before(() => { cy.login() - cy.deleteApp("Cypress Tests") + cy.deleteAllApps() }) if (!(Cypress.env("TEST_ENV"))) { @@ -48,7 +48,7 @@ filterTests(['smoke', 'all'], () => { }) it("should enforce a valid url before submission", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) + 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, { timeout: 1000 }).click({ force: true }) @@ -91,7 +91,7 @@ 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`) @@ -100,7 +100,7 @@ filterTests(['smoke', 'all'], () => { }) it("should create the first application from scratch with a default name", () => { - cy.createApp() + cy.createApp("", false) cy.applicationInAppTable("My app") cy.deleteApp("My app") }) @@ -110,7 +110,7 @@ filterTests(['smoke', 'all'], () => { cy.updateUserInformation("Ted", "Userman") - cy.createApp() + cy.createApp("", false) cy.visit(`${Cypress.config().baseUrl}/builder`) @@ -120,7 +120,7 @@ filterTests(['smoke', 'all'], () => { //Accomodate names that end in 'S' cy.updateUserInformation("Chris", "Userman") - cy.createApp() + cy.createApp("", false) cy.visit(`${Cypress.config().baseUrl}/builder`) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index b8b705bc53..9d77b89c57 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -323,7 +323,8 @@ Cypress.Commands.add("importApp", (exportFilePath, name) => { if (val.length > 0) { cy.get(`[data-cy="create-app-btn"]`).click({ force: true }) } - cy.get(`[data-cy="import-app-btn"]`, { timeout: 500 }).click({ + cy.wait(500) + cy.get(`[data-cy="import-app-btn"]`).click({ force: true, }) }) @@ -372,7 +373,7 @@ Cypress.Commands.add("searchForApplication", appName => { // Assumes there are no others Cypress.Commands.add("applicationInAppTable", appName => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 2000 }) + cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 10000 }) cy.get(".appTable", { timeout: 2000 }).within(() => { cy.get(".title").contains(appName).should("exist") }) From 548b2c1a9fa92fb4e9bef9f3cef05bb9097af701 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Thu, 30 Jun 2022 13:56:24 +0000 Subject: [PATCH 14/15] v1.0.212-alpha.7 --- lerna.json | 2 +- packages/backend-core/package.json | 4 ++-- packages/bbui/package.json | 4 ++-- packages/builder/package.json | 10 +++++----- packages/cli/package.json | 2 +- packages/client/package.json | 8 ++++---- packages/frontend-core/package.json | 4 ++-- packages/server/package.json | 10 +++++----- packages/string-templates/package.json | 2 +- packages/types/package.json | 2 +- packages/worker/package.json | 8 ++++---- 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lerna.json b/lerna.json index e65ce20401..beadd0ddcd 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.0.212-alpha.6", + "version": "1.0.212-alpha.7", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 3f36482120..0d51086e2b 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.6", + "version": "1.0.212-alpha.7", "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.6", + "@budibase/types": "^1.0.212-alpha.7", "@techpass/passport-openidconnect": "0.3.2", "aws-sdk": "2.1030.0", "bcrypt": "5.0.1", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 6bb51dda7b..e03b7263e6 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.6", + "version": "1.0.212-alpha.7", "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.6", + "@budibase/string-templates": "^1.0.212-alpha.7", "@spectrum-css/actionbutton": "^1.0.1", "@spectrum-css/actiongroup": "^1.0.1", "@spectrum-css/avatar": "^3.0.2", diff --git a/packages/builder/package.json b/packages/builder/package.json index 404fd3b1cc..3f38918e8e 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "1.0.212-alpha.6", + "version": "1.0.212-alpha.7", "license": "GPL-3.0", "private": true, "scripts": { @@ -69,10 +69,10 @@ } }, "dependencies": { - "@budibase/bbui": "^1.0.212-alpha.6", - "@budibase/client": "^1.0.212-alpha.6", - "@budibase/frontend-core": "^1.0.212-alpha.6", - "@budibase/string-templates": "^1.0.212-alpha.6", + "@budibase/bbui": "^1.0.212-alpha.7", + "@budibase/client": "^1.0.212-alpha.7", + "@budibase/frontend-core": "^1.0.212-alpha.7", + "@budibase/string-templates": "^1.0.212-alpha.7", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index b33161f525..607c044f17 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "1.0.212-alpha.6", + "version": "1.0.212-alpha.7", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "src/index.js", "bin": { diff --git a/packages/client/package.json b/packages/client/package.json index 6a1bba3146..4605cf564e 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "1.0.212-alpha.6", + "version": "1.0.212-alpha.7", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -19,9 +19,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "^1.0.212-alpha.6", - "@budibase/frontend-core": "^1.0.212-alpha.6", - "@budibase/string-templates": "^1.0.212-alpha.6", + "@budibase/bbui": "^1.0.212-alpha.7", + "@budibase/frontend-core": "^1.0.212-alpha.7", + "@budibase/string-templates": "^1.0.212-alpha.7", "@spectrum-css/button": "^3.0.3", "@spectrum-css/card": "^3.0.3", "@spectrum-css/divider": "^1.0.3", diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json index 30b4d6c44f..e258760430 100644 --- a/packages/frontend-core/package.json +++ b/packages/frontend-core/package.json @@ -1,12 +1,12 @@ { "name": "@budibase/frontend-core", - "version": "1.0.212-alpha.6", + "version": "1.0.212-alpha.7", "description": "Budibase frontend core libraries used in builder and client", "author": "Budibase", "license": "MPL-2.0", "svelte": "src/index.js", "dependencies": { - "@budibase/bbui": "^1.0.212-alpha.6", + "@budibase/bbui": "^1.0.212-alpha.7", "lodash": "^4.17.21", "svelte": "^3.46.2" } diff --git a/packages/server/package.json b/packages/server/package.json index d85aa28d04..4c8e9d793e 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "1.0.212-alpha.6", + "version": "1.0.212-alpha.7", "description": "Budibase Web Server", "main": "src/index.ts", "repository": { @@ -77,11 +77,11 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "10.0.3", - "@budibase/backend-core": "^1.0.212-alpha.6", - "@budibase/client": "^1.0.212-alpha.6", + "@budibase/backend-core": "^1.0.212-alpha.7", + "@budibase/client": "^1.0.212-alpha.7", "@budibase/pro": "1.0.212-alpha.6", - "@budibase/string-templates": "^1.0.212-alpha.6", - "@budibase/types": "^1.0.212-alpha.6", + "@budibase/string-templates": "^1.0.212-alpha.7", + "@budibase/types": "^1.0.212-alpha.7", "@bull-board/api": "3.7.0", "@bull-board/koa": "3.9.4", "@elastic/elasticsearch": "7.10.0", diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index 582f2d9a87..7ca41f0816 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "1.0.212-alpha.6", + "version": "1.0.212-alpha.7", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/types/package.json b/packages/types/package.json index d6f7b58ebd..6662e91404 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/types", - "version": "1.0.212-alpha.6", + "version": "1.0.212-alpha.7", "description": "Budibase types", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/worker/package.json b/packages/worker/package.json index f223c9f480..82b6e7c442 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "1.0.212-alpha.6", + "version": "1.0.212-alpha.7", "description": "Budibase background service", "main": "src/index.ts", "repository": { @@ -34,10 +34,10 @@ "author": "Budibase", "license": "GPL-3.0", "dependencies": { - "@budibase/backend-core": "^1.0.212-alpha.6", + "@budibase/backend-core": "^1.0.212-alpha.7", "@budibase/pro": "1.0.212-alpha.6", - "@budibase/string-templates": "^1.0.212-alpha.6", - "@budibase/types": "^1.0.212-alpha.6", + "@budibase/string-templates": "^1.0.212-alpha.7", + "@budibase/types": "^1.0.212-alpha.7", "@koa/router": "8.0.8", "@sentry/node": "6.17.7", "@techpass/passport-openidconnect": "0.3.2", From 6a82c7ce92654ccf14e17eb80a6d0e0b353a1099 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Thu, 30 Jun 2022 13:57:49 +0000 Subject: [PATCH 15/15] Update pro version to 1.0.212-alpha.7 --- packages/server/package.json | 2 +- packages/worker/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 4c8e9d793e..3545eb5594 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -79,7 +79,7 @@ "@apidevtools/swagger-parser": "10.0.3", "@budibase/backend-core": "^1.0.212-alpha.7", "@budibase/client": "^1.0.212-alpha.7", - "@budibase/pro": "1.0.212-alpha.6", + "@budibase/pro": "1.0.212-alpha.7", "@budibase/string-templates": "^1.0.212-alpha.7", "@budibase/types": "^1.0.212-alpha.7", "@bull-board/api": "3.7.0", diff --git a/packages/worker/package.json b/packages/worker/package.json index 82b6e7c442..22b06d11a5 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -35,7 +35,7 @@ "license": "GPL-3.0", "dependencies": { "@budibase/backend-core": "^1.0.212-alpha.7", - "@budibase/pro": "1.0.212-alpha.6", + "@budibase/pro": "1.0.212-alpha.7", "@budibase/string-templates": "^1.0.212-alpha.7", "@budibase/types": "^1.0.212-alpha.7", "@koa/router": "8.0.8",