diff --git a/.gitignore b/.gitignore index 6ba2f61ed7..969a38b46e 100644 --- a/.gitignore +++ b/.gitignore @@ -95,3 +95,4 @@ hosting/.generated-envoy.dev.yaml *.sublime-workspace bin/ +packages/builder/cypress.env.json diff --git a/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js b/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js index b3e0f413f8..28024cb2ae 100644 --- a/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js +++ b/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js @@ -1,14 +1,17 @@ -context("Add Multi-Option Datatype", () => { - before(() => { - cy.login() - cy.createTestApp() - }) +import filterTests from "../support/filterTests" - it("should create a new table, with data", () => { - cy.createTable("Multi Data") - cy.addColumn("Multi Data", "Test Data", "Multi-select", "1\n2\n3\n4\n5") - cy.addRowMultiValue(["1", "2", "3", "4", "5"]) - }) +filterTests(['all'], () => { + context("Add Multi-Option Datatype", () => { + before(() => { + cy.login() + cy.createTestApp() + }) + + it("should create a new table, with data", () => { + cy.createTable("Multi Data") + cy.addColumn("Multi Data", "Test Data", "Multi-select", "1\n2\n3\n4\n5") + cy.addRowMultiValue(["1", "2", "3", "4", "5"]) + }) it("should add form with multi select picker, containing 5 options", () => { cy.navigateToFrontend() diff --git a/packages/builder/cypress/integration/addRadioButtons.spec.js b/packages/builder/cypress/integration/addRadioButtons.spec.js index 68d0a74d55..9888b56086 100644 --- a/packages/builder/cypress/integration/addRadioButtons.spec.js +++ b/packages/builder/cypress/integration/addRadioButtons.spec.js @@ -1,35 +1,39 @@ -context("Add Radio Buttons", () => { - before(() => { - cy.login() - cy.createTestApp() - }) +import filterTests from "../support/filterTests" -it("should add Radio Buttons options picker on form, add data, and confirm", () => { - cy.navigateToFrontend() - cy.addComponent("Form", "Form") - cy.addComponent("Form", "Options Picker").then((componentId) => { - // Provide field setting - cy.get(`[data-cy="field-prop-control"]`).type("1") - // Open dropdown and select Radio buttons - cy.get(`[data-cy="optionsType-prop-control"]`).click().then(() => { - cy.get('.spectrum-Popover').contains('Radio buttons') - .wait(500) - .click() +filterTests(['all'], () => { + context("Add Radio Buttons", () => { + before(() => { + cy.login() + cy.createTestApp() }) - const radioButtonsTotal = 3 - // Add values and confirm total - addRadioButtonData(radioButtonsTotal) - cy.getComponent(componentId).find('[type="radio"]') - .should('have.length', radioButtonsTotal) - }) - }) - - const addRadioButtonData = (totalRadioButtons) => { - cy.get(`[data-cy="optionsSource-prop-control"]`).click().then(() => { - cy.get('.spectrum-Popover').contains('Custom') + + it("should add Radio Buttons options picker on form, add data, and confirm", () => { + cy.navigateToFrontend() + cy.addComponent("Form", "Form") + cy.addComponent("Form", "Options Picker").then((componentId) => { + // Provide field setting + cy.get(`[data-cy="field-prop-control"]`).type("1") + // Open dropdown and select Radio buttons + cy.get(`[data-cy="optionsType-prop-control"]`).click().then(() => { + cy.get('.spectrum-Popover').contains('Radio buttons') .wait(500) .click() + }) + const radioButtonsTotal = 3 + // Add values and confirm total + addRadioButtonData(radioButtonsTotal) + cy.getComponent(componentId).find('[type="radio"]') + .should('have.length', radioButtonsTotal) + }) }) - cy.addCustomSourceOptions(totalRadioButtons) - } + + const addRadioButtonData = (totalRadioButtons) => { + cy.get(`[data-cy="optionsSource-prop-control"]`).click().then(() => { + cy.get('.spectrum-Popover').contains('Custom') + .wait(500) + .click() + }) + cy.addCustomSourceOptions(totalRadioButtons) + } + }) }) diff --git a/packages/builder/cypress/integration/autoScreensUI.spec.js b/packages/builder/cypress/integration/autoScreensUI.spec.js new file mode 100644 index 0000000000..d67ade571a --- /dev/null +++ b/packages/builder/cypress/integration/autoScreensUI.spec.js @@ -0,0 +1,51 @@ +import filterTests from "../support/filterTests" + +filterTests(['smoke', 'all'], () => { + context("Auto Screens UI", () => { + before(() => { + cy.login() + cy.createTestApp() + }) + + it("should generate internal table screens", () => { + // Create autogenerated screens from the internal table + cy.createAutogeneratedScreens(["Cypress Tests"]) + // Confirm screens have been auto generated + cy.get(".nav-items-container").contains("cypress-tests").click() + cy.get(".nav-items-container").should('contain', 'cypress-tests/:id') + .and('contain', 'cypress-tests/new/row') + }) + + it("should generate multiple internal table screens at once", () => { + // Create a second internal table + const initialTable = "Cypress Tests" + const secondTable = "Table Two" + cy.createTable(secondTable) + // Create autogenerated screens from the internal tables + cy.createAutogeneratedScreens([initialTable, secondTable]) + // Confirm screens have been auto generated + cy.get(".nav-items-container").contains("cypress-tests").click() + // Previously generated tables are suffixed with numbers - as expected + cy.get(".nav-items-container").should('contain', 'cypress-tests-2/:id') + .and('contain', 'cypress-tests-2/new/row') + cy.get(".nav-items-container").contains("table-two").click() + cy.get(".nav-items-container").should('contain', 'table-two/:id') + .and('contain', 'table-two/new/row') + }) + + if (Cypress.env("TEST_ENV")) { + it("should generate data source screens", () => { + // Using MySQL data source for testing this + const datasource = "MySQL" + // Select & configure MySQL data source + cy.selectExternalDatasource(datasource) + cy.addDatasourceConfig(datasource) + // Create autogenerated screens from a MySQL table - MySQL contains books table + cy.createAutogeneratedScreens(["books"]) + cy.get(".nav-items-container").contains("books").click() + cy.get(".nav-items-container").should('contain', 'books/:id') + .and('contain', 'books/new/row') + }) + } + }) +}) diff --git a/packages/builder/cypress/integration/changeAppIconAndColour.spec.js b/packages/builder/cypress/integration/changeAppIconAndColour.spec.js new file mode 100644 index 0000000000..92d03a102d --- /dev/null +++ b/packages/builder/cypress/integration/changeAppIconAndColour.spec.js @@ -0,0 +1,43 @@ +import filterTests from "../support/filterTests" + +filterTests(['all'], () => { + context("Change Application Icon and Colour", () => { + before(() => { + cy.login() + }) + + it("should change the icon and colour for an application", () => { + // Search for test application + cy.searchForApplication("Cypress Tests") + cy.get(".appTable") + .within(() => { + cy.get(".spectrum-Icon").eq(1).click() + }) + cy.get(".spectrum-Menu").contains("Edit icon").click() + // Select random icon + cy.get(".grid").within(() => { + cy.get(".icon-item").eq(Math.floor(Math.random() * 23) + 1).click() + }) + // Select random colour + cy.get(".fill").click() + cy.get(".colors").within(() => { + cy.get(".color").eq(Math.floor(Math.random() * 33) + 1).click() + }) + cy.intercept('**/applications/**').as('iconChange') + cy.get(".spectrum-Button").contains("Save").click({ force: true }) + cy.wait("@iconChange") + cy.get("@iconChange").its('response.statusCode') + .should('eq', 200) + cy.wait(1000) + // Confirm icon has changed from default + // Confirm colour has been applied - There is no default colour + cy.get(".appTable") + .within(() => { + cy.get('[aria-label]').eq(0).children() + .should('have.attr', 'xlink:href').and('not.contain', '#spectrum-icon-18-Apps') + cy.get(".title").children().children() + .should('have.attr', 'style').and('contains', 'color') + }) + }) + }) +}) diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index 34f152b540..273683aec8 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -1,8 +1,12 @@ -context("Create an Application", () => { - it("should create a new application", () => { - cy.login() - cy.createTestApp() - cy.visit(`localhost:${Cypress.env("PORT")}/builder`) - cy.contains("Cypress Tests").should("exist") - }) +import filterTests from '../support/filterTests' + +filterTests(['smoke', 'all'], () => { + context("Create an Application", () => { + it("should create a new application", () => { + cy.login() + cy.createTestApp() + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.contains("Cypress Tests").should("exist") + }) + }) }) diff --git a/packages/builder/cypress/integration/createAutomation.spec.js b/packages/builder/cypress/integration/createAutomation.spec.js index efd3c7d023..e8892d16e2 100644 --- a/packages/builder/cypress/integration/createAutomation.spec.js +++ b/packages/builder/cypress/integration/createAutomation.spec.js @@ -1,66 +1,69 @@ -context("Create a automation", () => { - before(() => { - cy.login() - cy.createTestApp() - }) +import filterTests from "../support/filterTests" - // https://on.cypress.io/interacting-with-elements - it("should create a automation", () => { - cy.createTestTableWithData() - cy.wait(2000) - cy.contains("Automate").click() - cy.get("[data-cy='new-screen'] > .spectrum-Icon").click() - cy.get(".modal-inner-wrapper").within(() => { - cy.get("input").type("Add Row") - cy.contains("Row Created").click({ force: true }) +filterTests(['smoke', 'all'], () => { + context("Create a automation", () => { + before(() => { + cy.login() + cy.createTestApp() + }) + + it("should create a automation", () => { + cy.createTestTableWithData() + cy.wait(2000) + cy.contains("Automate").click() + cy.get("[data-cy='new-screen'] > .spectrum-Icon").click() + cy.get(".modal-inner-wrapper").within(() => { + cy.get("input").type("Add Row") + cy.contains("Row Created").click({ force: true }) + cy.wait(500) + cy.get(".spectrum-Button--cta").click() + }) + + // Setup trigger + cy.contains("Setup").click() + cy.get(".spectrum-Picker-label").click() cy.wait(500) - cy.get(".spectrum-Button--cta").click() - }) - - // Setup trigger - cy.contains("Setup").click() - cy.get(".spectrum-Picker-label").click() - cy.wait(500) - cy.contains("dog").click() - cy.wait(2000) - // Create action - cy.get(".block > .spectrum-Icon").click() - cy.get(".modal-inner-wrapper").within(() => { - cy.wait(1000) - cy.contains("Create Row").trigger('mouseover').click().click() - cy.get(".spectrum-Button--cta").click() - }) - cy.contains("Setup").click() - cy.get(".spectrum-Picker-label").click() - cy.contains("dog").click() - cy.get(".spectrum-Textfield-input") - .first() - .type("{{ trigger.row.name }}", { parseSpecialCharSequences: false }) - cy.get(".spectrum-Textfield-input") - .eq(1) - .type("11") - cy.contains("Finish and test automation").click() - - cy.get(".modal-inner-wrapper").within(() => { - cy.wait(1000) + cy.contains("dog").click() + cy.wait(2000) + // Create action + cy.get('[aria-label="AddCircle"]').eq(1).click() + cy.get(".modal-inner-wrapper").within(() => { + cy.wait(1000) + cy.contains("Create Row").trigger('mouseover').click().click() + cy.get(".spectrum-Button--cta").click() + }) + cy.contains("Setup").click() cy.get(".spectrum-Picker-label").click() cy.contains("dog").click() - cy.wait(1000) cy.get(".spectrum-Textfield-input") - .first() - .type("automationGoodboy") + .first() + .type("{{ trigger.row.name }}", { parseSpecialCharSequences: false }) cy.get(".spectrum-Textfield-input") .eq(1) .type("11") - cy.get(".spectrum-Textfield-input") - .eq(2) - .type("123456") - cy.get(".spectrum-Textfield-input") - .eq(3) - .type("123456") - cy.contains("Test").click() + cy.contains("Finish and test automation").click() + + cy.get(".modal-inner-wrapper").within(() => { + cy.wait(1000) + cy.get(".spectrum-Picker-label").click() + cy.contains("dog").click() + cy.wait(1000) + cy.get(".spectrum-Textfield-input") + .first() + .type("automationGoodboy") + cy.get(".spectrum-Textfield-input") + .eq(1) + .type("11") + cy.get(".spectrum-Textfield-input") + .eq(2) + .type("123456") + cy.get(".spectrum-Textfield-input") + .eq(3) + .type("123456") + cy.contains("Test").click() + }) + cy.contains("Data").click() + cy.contains("automationGoodboy") }) - cy.contains("Data").click() - cy.contains("automationGoodboy") }) }) diff --git a/packages/builder/cypress/integration/createBinding.spec.js b/packages/builder/cypress/integration/createBinding.spec.js index 3f85526b11..8bf1ec8ea4 100644 --- a/packages/builder/cypress/integration/createBinding.spec.js +++ b/packages/builder/cypress/integration/createBinding.spec.js @@ -1,58 +1,62 @@ -context("Create Bindings", () => { - before(() => { - cy.login() - cy.createTestApp() - cy.navigateToFrontend() - }) +import filterTests from "../support/filterTests" - it("should add a current user binding", () => { - cy.addComponent("Elements", "Paragraph").then(() => { - addSettingBinding("text", "Current User._id") +filterTests(['smoke', 'all'], () => { + context("Create Bindings", () => { + before(() => { + cy.login() + cy.createTestApp() + cy.navigateToFrontend() + }) + + it("should add a current user binding", () => { + cy.addComponent("Elements", "Paragraph").then(() => { + addSettingBinding("text", "Current User._id") + }) + }) + + it("should handle an invalid binding", () => { + cy.addComponent("Elements", "Paragraph").then(componentId => { + // Cypress needs to escape curly brackets + cy.get("[data-cy=setting-text] input") + .type("{{}{{}{{} Current User._id {}}{}}") + .blur() + cy.getComponent(componentId).should("have.text", "{{{ [user].[_id] }}") + }) + }) + + it("should add a URL param binding", () => { + const paramName = "foo" + cy.createScreen("Test Param", `/test/:${paramName}`) + cy.addComponent("Elements", "Paragraph").then(componentId => { + addSettingBinding("text", `URL.${paramName}`) + // The builder preview pages don't have a real URL, so all we can do + // is check that we were able to bind to the property, and that the + // component exists on the page + cy.getComponent(componentId).should("have.text", "New Paragraph") + }) + }) + + it("should add a binding with a handlebars helper", () => { + cy.addComponent("Elements", "Paragraph").then(componentId => { + // Cypress needs to escape curly brackets + cy.get("[data-cy=setting-text] input") + .type("{{}{{} add 1 2 {}}{}}") + .blur() + cy.getComponent(componentId).should("have.text", "3") + }) }) }) - it("should handle an invalid binding", () => { - cy.addComponent("Elements", "Paragraph").then(componentId => { - // Cypress needs to escape curly brackets - cy.get("[data-cy=setting-text] input") - .type("{{}{{}{{} Current User._id {}}{}}") - .blur() - cy.getComponent(componentId).should("have.text", "{{{ [user].[_id] }}") + const addSettingBinding = (setting, bindingText, clickOption = true) => { + cy.get(`[data-cy="setting-${setting}"] [data-cy=text-binding-button]`).click() + cy.get(".drawer").within(() => { + if (clickOption) { + cy.contains(bindingText).click() + cy.get("textarea").should("have.value", `{{ ${bindingText} }}`) + } else { + cy.get("textarea").type(bindingText) + } + cy.contains("Save").click() }) - }) - - it("should add a URL param binding", () => { - const paramName = "foo" - cy.createScreen("Test Param", `/test/:${paramName}`) - cy.addComponent("Elements", "Paragraph").then(componentId => { - addSettingBinding("text", `URL.${paramName}`) - // The builder preview pages don't have a real URL, so all we can do - // is check that we were able to bind to the property, and that the - // component exists on the page - cy.getComponent(componentId).should("have.text", "New Paragraph") - }) - }) - - it("should add a binding with a handlebars helper", () => { - cy.addComponent("Elements", "Paragraph").then(componentId => { - // Cypress needs to escape curly brackets - cy.get("[data-cy=setting-text] input") - .type("{{}{{} add 1 2 {}}{}}") - .blur() - cy.getComponent(componentId).should("have.text", "3") - }) - }) + } }) - -const addSettingBinding = (setting, bindingText, clickOption = true) => { - cy.get(`[data-cy="setting-${setting}"] [data-cy=text-binding-button]`).click() - cy.get(".drawer").within(() => { - if (clickOption) { - cy.contains(bindingText).click() - cy.get("textarea").should("have.value", `{{ ${bindingText} }}`) - } else { - cy.get("textarea").type(bindingText) - } - cy.contains("Save").click() - }) -} diff --git a/packages/builder/cypress/integration/createComponents.spec.js b/packages/builder/cypress/integration/createComponents.spec.js index 93867e0f1f..e13439d9c6 100644 --- a/packages/builder/cypress/integration/createComponents.spec.js +++ b/packages/builder/cypress/integration/createComponents.spec.js @@ -1,92 +1,97 @@ // TODO for now components are skipped, might not be good to keep doing this -xcontext("Create Components", () => { - let headlineId - before(() => { - cy.login() - cy.createTestApp() - cy.createTable("dog") - cy.addColumn("dog", "name", "Text") - cy.addColumn("dog", "age", "Number") - cy.addColumn("dog", "type", "Options") - cy.navigateToFrontend() - }) +import filterTests from "../support/filterTests" - it("should add a container", () => { - cy.addComponent(null, "Container").then(componentId => { - cy.getComponent(componentId).should("exist") +filterTests(['all'], () => { + xcontext("Create Components", () => { + let headlineId + + before(() => { + cy.login() + cy.createTestApp() + cy.createTable("dog") + cy.addColumn("dog", "name", "Text") + cy.addColumn("dog", "age", "Number") + cy.addColumn("dog", "type", "Options") + cy.navigateToFrontend() }) - }) - it("should add a headline", () => { - cy.addComponent("Elements", "Headline").then(componentId => { - headlineId = componentId - cy.getComponent(headlineId).should("exist") + it("should add a container", () => { + cy.addComponent(null, "Container").then(componentId => { + cy.getComponent(componentId).should("exist") + }) }) - }) - it("should change the text of the headline", () => { - const text = "Lorem ipsum dolor sit amet." - cy.get("[data-cy=Settings]").click() - cy.get("[data-cy=setting-text] input") - .type(text) - .blur() - cy.getComponent(headlineId).should("have.text", text) - }) + it("should add a headline", () => { + cy.addComponent("Elements", "Headline").then(componentId => { + headlineId = componentId + cy.getComponent(headlineId).should("exist") + }) + }) - it("should change the size of the headline", () => { - cy.get("[data-cy=Design]").click() - cy.contains("Typography").click() - cy.get("[data-cy=font-size-prop-control]").click() - cy.contains("60px").click() - cy.getComponent(headlineId).should("have.css", "font-size", "60px") - }) - - it("should create a form and reset to match schema", () => { - cy.addComponent("Form", "Form").then(() => { + it("should change the text of the headline", () => { + const text = "Lorem ipsum dolor sit amet." cy.get("[data-cy=Settings]").click() - cy.get("[data-cy=setting-dataSource]") - .contains("Choose option") - .click() - cy.get(".dropdown") - .contains("dog") - .click() - cy.addComponent("Form", "Field Group").then(fieldGroupId => { + cy.get("[data-cy=setting-text] input") + .type(text) + .blur() + cy.getComponent(headlineId).should("have.text", text) + }) + + it("should change the size of the headline", () => { + cy.get("[data-cy=Design]").click() + cy.contains("Typography").click() + cy.get("[data-cy=font-size-prop-control]").click() + cy.contains("60px").click() + cy.getComponent(headlineId).should("have.css", "font-size", "60px") + }) + + it("should create a form and reset to match schema", () => { + cy.addComponent("Form", "Form").then(() => { cy.get("[data-cy=Settings]").click() - cy.contains("Update Form Fields").click() - cy.get(".modal") - .get("button.primary") + cy.get("[data-cy=setting-dataSource]") + .contains("Choose option") .click() - cy.getComponent(fieldGroupId).within(() => { - cy.contains("name").should("exist") - cy.contains("age").should("exist") - cy.contains("type").should("exist") + cy.get(".dropdown") + .contains("dog") + .click() + cy.addComponent("Form", "Field Group").then(fieldGroupId => { + cy.get("[data-cy=Settings]").click() + cy.contains("Update Form Fields").click() + cy.get(".modal") + .get("button.primary") + .click() + cy.getComponent(fieldGroupId).within(() => { + cy.contains("name").should("exist") + cy.contains("age").should("exist") + cy.contains("type").should("exist") + }) + cy.getComponent(fieldGroupId) + .find("input") + .should("have.length", 2) + cy.getComponent(fieldGroupId) + .find(".spectrum-Picker") + .should("have.length", 1) }) - cy.getComponent(fieldGroupId) - .find("input") - .should("have.length", 2) - cy.getComponent(fieldGroupId) - .find(".spectrum-Picker") - .should("have.length", 1) }) }) - }) - it("deletes a component", () => { - cy.addComponent("Elements", "Paragraph").then(componentId => { - cy.get("[data-cy=setting-_instanceName] input") - .type(componentId) - .blur() - cy.get(".ui-nav ul .nav-item.selected .ri-more-line").click({ - force: true, + it("deletes a component", () => { + cy.addComponent("Elements", "Paragraph").then(componentId => { + cy.get("[data-cy=setting-_instanceName] input") + .type(componentId) + .blur() + cy.get(".ui-nav ul .nav-item.selected .ri-more-line").click({ + force: true, + }) + cy.get(".dropdown-container") + .contains("Delete") + .click() + cy.get(".modal") + .contains("Delete Component") + .click() + cy.getComponent(componentId).should("not.exist") }) - cy.get(".dropdown-container") - .contains("Delete") - .click() - cy.get(".modal") - .contains("Delete Component") - .click() - cy.getComponent(componentId).should("not.exist") }) }) }) diff --git a/packages/builder/cypress/integration/createScreen.js b/packages/builder/cypress/integration/createScreen.js index 26c7cdd846..ada68d82dc 100644 --- a/packages/builder/cypress/integration/createScreen.js +++ b/packages/builder/cypress/integration/createScreen.js @@ -1,21 +1,25 @@ -context("Screen Tests", () => { - before(() => { - cy.login() - cy.createTestApp() - cy.navigateToFrontend() - }) +import filterTests from "../support/filterTests" - it("Should successfully create a screen", () => { - cy.createScreen("Test Screen", "/test") - cy.get(".nav-items-container").within(() => { - cy.contains("/test").should("exist") +filterTests(["smoke", "all"], () => { + context("Screen Tests", () => { + before(() => { + cy.login() + cy.createTestApp() + cy.navigateToFrontend() }) - }) - it("Should update the url", () => { - cy.createScreen("Test Screen", "test with spaces") - cy.get(".nav-items-container").within(() => { - cy.contains("/test-with-spaces").should("exist") + it("Should successfully create a screen", () => { + cy.createScreen("Test Screen", "/test") + cy.get(".nav-items-container").within(() => { + cy.contains("/test").should("exist") + }) + }) + + it("Should update the url", () => { + cy.createScreen("Test Screen", "test with spaces") + cy.get(".nav-items-container").within(() => { + cy.contains("/test-with-spaces").should("exist") + }) }) }) }) diff --git a/packages/builder/cypress/integration/createTable.spec.js b/packages/builder/cypress/integration/createTable.spec.js index 20ec919b57..6d8493134f 100644 --- a/packages/builder/cypress/integration/createTable.spec.js +++ b/packages/builder/cypress/integration/createTable.spec.js @@ -1,74 +1,107 @@ -context("Create a Table", () => { - before(() => { - cy.login() - cy.createTestApp() - }) +import filterTests from "../support/filterTests" - it("should create a new Table", () => { - cy.createTable("dog") - cy.wait(1000) - // Check if Table exists - cy.get(".table-title h1").should("have.text", "dog") - }) +filterTests(['smoke', 'all'], () => { + context("Create a Table", () => { + before(() => { + cy.login() + cy.createTestApp() + }) - it("adds a new column to the table", () => { - cy.addColumn("dog", "name", "Text") - cy.contains("name").should("be.visible") - }) + it("should create a new Table", () => { + cy.createTable("dog") + cy.wait(1000) + // Check if Table exists + cy.get(".table-title h1").should("have.text", "dog") + }) - it("creates a row in the table", () => { - cy.addRow(["Rover"]) - cy.contains("Rover").should("be.visible") - }) + it("adds a new column to the table", () => { + cy.addColumn("dog", "name", "Text") + cy.contains("name").should("be.visible") + }) - it("updates a column on the table", () => { - cy.get(".title").click() - cy.get(".spectrum-Table-editIcon > use").click() - cy.get("input").eq(1).type("updated", { force: true }) - // Unset table display column - cy.get(".spectrum-Switch-input").eq(1).click() - cy.contains("Save Column").click() - cy.contains("nameupdated ").should("contain", "nameupdated") - }) + it("creates a row in the table", () => { + cy.addRow(["Rover"]) + cy.contains("Rover").should("be.visible") + }) - - it("edits a row", () => { - cy.contains("button", "Edit").click({ force: true }) - cy.wait(1000) - cy.get(".spectrum-Modal input").clear() - cy.get(".spectrum-Modal input").type("Updated") - cy.contains("Save").click() - cy.contains("Updated").should("have.text", "Updated") - }) - - it("deletes a row", () => { - cy.get(".spectrum-Checkbox-input").check({ force: true }) - cy.contains("Delete 1 row(s)").click() - cy.get(".spectrum-Modal").contains("Delete").click() - cy.contains("RoverUpdated").should("not.exist") - }) - - it("deletes a column", () => { - cy.get(".title").click() - cy.get(".spectrum-Table-editIcon > use").click() - cy.contains("Delete").click() - cy.wait(50) - cy.get(`[data-cy="delete-column-confirm"]`).type("nameupdated") - cy.contains("Delete Column").click() - cy.contains("nameupdated").should("not.exist") - }) - - it("deletes a table", () => { - cy.get(".nav-item") - .contains("dog") - .parents(".nav-item") - .first() - .within(() => { - cy.get(".actions .spectrum-Icon").click({ force: true }) + it("updates a column on the table", () => { + cy.get(".title").click() + cy.get(".spectrum-Table-editIcon > use").click() + cy.get("input").eq(1).type("updated", { force: true }) + // Unset table display column + cy.get(".spectrum-Switch-input").eq(1).click() + cy.contains("Save Column").click() + cy.contains("nameupdated ").should("contain", "nameupdated") + }) + + it("edits a row", () => { + cy.contains("button", "Edit").click({ force: true }) + cy.wait(1000) + cy.get(".spectrum-Modal input").clear() + cy.get(".spectrum-Modal input").type("Updated") + cy.contains("Save").click() + cy.contains("Updated").should("have.text", "Updated") + }) + + it("deletes a row", () => { + cy.get(".spectrum-Checkbox-input").check({ force: true }) + cy.contains("Delete 1 row(s)").click() + cy.get(".spectrum-Modal").contains("Delete").click() + cy.contains("RoverUpdated").should("not.exist") + }) + + it("Adds 15 rows and checks pagination", () => { + // 10 rows per page, 15 rows should create 2 pages within table + const totalRows = 16 + for (let i = 1; i < totalRows; i++){ + cy.addRow([i]) + } + cy.wait(1000) + cy.get(".spectrum-Pagination").within(() => { + cy.get(".spectrum-ActionButton").eq(1).click() }) - cy.get(".spectrum-Menu > :nth-child(2)").click() - cy.get(`[data-cy="delete-table-confirm"]`).type("dog") - cy.contains("Delete Table").click() - cy.contains("dog").should("not.exist") + cy.get(".spectrum-Pagination").within(() => { + cy.get(".spectrum-Body--secondary").contains("Page 2") + }) + }) + + it("Deletes rows and checks pagination", () => { + // Delete rows, removing second page of rows from table + const deleteRows = 5 + cy.get(".spectrum-Checkbox-input").check({ force: true }) + cy.get(".spectrum-Table-body") + cy.contains("Delete 5 row(s)").click() + cy.get(".spectrum-Modal").contains("Delete").click() + cy.wait(1000) + + // Confirm table only has one page + cy.get(".spectrum-Pagination").within(() => { + cy.get(".spectrum-ActionButton").eq(1).should('not.be.enabled') + }) + }) + + it("deletes a column", () => { + const columnName = "nameupdated" + cy.get(".title").click() + cy.get(".spectrum-Table-editIcon > use").click() + cy.contains("Delete").click() + cy.get('[data-cy="delete-column-confirm"]').type(columnName) + cy.contains("Delete Column").click() + cy.contains("nameupdated").should("not.exist") + }) + + it("deletes a table", () => { + cy.get(".nav-item") + .contains("dog") + .parents(".nav-item") + .first() + .within(() => { + cy.get(".actions .spectrum-Icon").click({ force: true }) + }) + cy.get(".spectrum-Menu > :nth-child(2)").click() + cy.get('[data-cy="delete-table-confirm"]').type("dog") + cy.contains("Delete Table").click() + cy.contains("dog").should("not.exist") + }) }) }) diff --git a/packages/builder/cypress/integration/createUserAndRoles.spec.js b/packages/builder/cypress/integration/createUserAndRoles.spec.js new file mode 100644 index 0000000000..d4f6f784f8 --- /dev/null +++ b/packages/builder/cypress/integration/createUserAndRoles.spec.js @@ -0,0 +1,133 @@ +import filterTests from "../support/filterTests" + + +filterTests(['smoke', 'all'], () => { + context("Create a User and Assign Roles", () => { + before(() => { + cy.login() + }) + + it("should create a user", () => { + cy.createUser("bbuser@test.com") + cy.get(".spectrum-Table-body").should('contain', 'bbuser') + }) + + 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(".spectrum-Table").eq(1).should('not.contain', 'No rows found') + // Get Configure Roles table - Confirm it has no apps + cy.get(".spectrum-Table").eq(0).contains('No rows found') + }) + + it("should assign role types", () => { + // 3 apps minimum required - to assign an app to each role type + cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) + .its("body") + .then(val => { + if (val.length < 3) { + for (let i = 1; i < 3; i++) { + const uuid = () => Cypress._.random(0, 1e6) + const name = uuid() + cy.createApp(name) + } + } + }) + // Navigate back to the user + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(1000) + cy.get(".spectrum-SideNav").contains("Users").click() + cy.get(".spectrum-Table").contains("bbuser").click() + cy.wait(500) + for (let i = 0; i < 3; i++) { + cy.get(".spectrum-Table-body").eq(1).find('tr').eq(0).click() + cy.wait(500) + cy.get(".spectrum-Dialog-grid").contains("Choose an option").click().then(() => { + cy.wait(500) + if (i == 0) { + cy.get(".spectrum-Popover").contains("Admin").click() + } + if (i == 1) { + cy.get(".spectrum-Popover").contains("Power").click() + } + if (i == 2) { + cy.get(".spectrum-Popover").contains("Basic").click() + } + cy.wait(500) + cy.get(".spectrum-Button").contains("Update role").click({ force: true }) + }) + } + // Confirm roles exist within Configure roles table + cy.wait(500) + cy.get(".spectrum-Table-body").eq(0).within((assginedRoles) => { + expect(assginedRoles).to.contain("Admin") + expect(assginedRoles).to.contain("Power") + expect(assginedRoles).to.contain("Basic") + }) + }) + + it("should unassign role types", () => { + // Set each app within Configure roles table to 'No Access' + cy.get(".spectrum-Table-body").eq(0).find('tr').its('length').then((len) => { + for (let i = 0; i < len; i ++){ + cy.get(".spectrum-Table-body").eq(0).find('tr').eq(0).click().then(() => { + cy.get(".spectrum-Form-item").contains("Role").parent().within(() => { + cy.get(".spectrum-Picker").click({ force: true }) + cy.wait(500) + cy.get(".spectrum-Popover").contains("No Access").click() + }) + cy.get(".spectrum-Button").contains("Update role").click({ force: true }) + cy.wait(1000) + }) + } + }) + // Confirm Configure roles table no longer has any apps in it + cy.get(".spectrum-Table-body").eq(0).contains('No rows found') + }) + + it("should enable Developer access", () => { + // Enable Developer access + cy.get(".field").eq(4).within(() => { + cy.get(".spectrum-Switch-input").click({ force: true }) + }) + // No Access table should now be empty + cy.get(".container").contains("No Access").parent().within(() => { + cy.get(".spectrum-Table").contains("No rows found") + }) + + // Each app within Configure roles should have Admin access + cy.get(".spectrum-Table-body").eq(0).find('tr').its('length').then((len) => { + for (let i = 0; i < len; i++) { + cy.get(".spectrum-Table-body").eq(0).find('tr').eq(i).contains("Admin") + cy.wait(500) + } + }) + }) + + it("should disable Developer access", () => { + // Disable Developer access + cy.get(".field").eq(4).within(() => { + cy.get(".spectrum-Switch-input").click({ force: true }) + }) + // Configure roles table should now be empty + cy.get(".container").contains("Configure roles").parent().within(() => { + cy.get(".spectrum-Table").contains("No rows found") + }) + }) + + it("should delete a user", () => { + // Click Delete user button + cy.get(".spectrum-Button").contains("Delete user").click({force: true}).then(() => { + // Confirm deletion within modal + cy.wait(500) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Button").contains("Delete user").click({force: true}) + cy.wait(4000) + }) + }) + cy.get(".spectrum-Table-body").should("not.have.text", "bbuser") + }) + }) +}) diff --git a/packages/builder/cypress/integration/createView.spec.js b/packages/builder/cypress/integration/createView.spec.js index e82ab67c0d..6b06cde0bc 100644 --- a/packages/builder/cypress/integration/createView.spec.js +++ b/packages/builder/cypress/integration/createView.spec.js @@ -1,152 +1,156 @@ -context("Create a View", () => { - before(() => { - cy.login() - cy.createTestApp() - cy.createTable("data") - cy.addColumn("data", "group", "Text") - cy.addColumn("data", "age", "Number") - cy.addColumn("data", "rating", "Number") +import filterTests from "../support/filterTests" - // 6 Rows - cy.addRow(["Students", 25, 1]) - cy.addRow(["Students", 20, 3]) - cy.addRow(["Students", 18, 6]) - cy.addRow(["Students", 25, 2]) - cy.addRow(["Teachers", 49, 5]) - cy.addRow(["Teachers", 36, 3]) - }) +filterTests(['smoke', 'all'], () => { + context("Create a View", () => { + before(() => { + cy.login() + cy.createTestApp() + cy.createTable("data") + cy.addColumn("data", "group", "Text") + cy.addColumn("data", "age", "Number") + cy.addColumn("data", "rating", "Number") - it("creates a view", () => { - cy.contains("Create view").click() - cy.get(".modal-inner-wrapper").within(() => { - cy.get("input").type("Test View") - cy.get("button").contains("Create View").click({ force: true }) + // 6 Rows + cy.addRow(["Students", 25, 1]) + cy.addRow(["Students", 20, 3]) + cy.addRow(["Students", 18, 6]) + cy.addRow(["Students", 25, 2]) + cy.addRow(["Teachers", 49, 5]) + cy.addRow(["Teachers", 36, 3]) }) - cy.get(".table-title h1").contains("Test View") - cy.get(".title").then($headers => { - expect($headers).to.have.length(3) - const headers = Array.from($headers).map(header => - header.textContent.trim() - ) - expect(removeSpacing(headers)).to.deep.eq(["group", "age", "rating"]) + + it("creates a view", () => { + cy.contains("Create view").click() + cy.get(".modal-inner-wrapper").within(() => { + cy.get("input").type("Test View") + cy.get("button").contains("Create View").click({ force: true }) + }) + cy.get(".table-title h1").contains("Test View") + cy.get(".title").then($headers => { + expect($headers).to.have.length(3) + const headers = Array.from($headers).map(header => + header.textContent.trim() + ) + expect(removeSpacing(headers)).to.deep.eq(["group", "age", "rating"]) + }) + }) + + it("filters the view by age over 10", () => { + cy.contains("Filter").click() + cy.contains("Add Filter").click() + + cy.get(".modal-inner-wrapper").within(() => { + cy.get(".spectrum-Picker-label").eq(0).click() + cy.contains("age").click({ force: true }) + + cy.get(".spectrum-Picker-label").eq(1).click() + cy.contains("More Than").click({ force: true }) + + cy.get("input").type(18) + cy.contains("Save").click() + }) + + cy.get(".spectrum-Table-row").get($values => { + expect($values).to.have.length(5) + }) + }) + + it("creates a stats calculation view based on age", () => { + cy.wait(1000) + cy.contains("Calculate").click() + cy.get(".modal-inner-wrapper").within(() => { + cy.get(".spectrum-Picker-label").eq(0).click() + cy.contains("Statistics").click() + + cy.get(".spectrum-Picker-label").eq(1).click() + cy.contains("age").click({ force: true }) + + cy.get(".spectrum-Button").contains("Save").click({ force: true }) + }) + cy.wait(1000) + + cy.get(".title").then($headers => { + expect($headers).to.have.length(7) + const headers = Array.from($headers).map(header => + header.textContent.trim() + ) + expect(removeSpacing(headers)).to.deep.eq([ + "field", + "sum", + "min", + "max", + "count", + "sumsqr", + "avg", + ]) + }) + cy.get(".spectrum-Table-cell").then($values => { + let values = Array.from($values).map(header => header.textContent.trim()) + expect(values).to.deep.eq(["age", "155", "20", "49", "5", "5347", "31"]) + }) + }) + + it("groups the view by group", () => { + cy.contains("Group by").click() + cy.get(".modal-inner-wrapper").within(() => { + cy.get(".spectrum-Picker-label").eq(0).click() + cy.contains("group").click() + cy.contains("Save").click() + }) + cy.wait(1000) + cy.contains("Students").should("be.visible") + cy.contains("Teachers").should("be.visible") + + cy.get(".spectrum-Table-cell").then($values => { + let values = Array.from($values).map(header => header.textContent.trim()) + expect(values).to.deep.eq([ + "Students", + "70", + "20", + "25", + "3", + "1650", + "23.333333333333332", + "Teachers", + "85", + "36", + "49", + "2", + "3697", + "42.5", + ]) + }) + }) + + it("renames a view", () => { + cy.contains(".nav-item", "Test View") + .find(".actions .icon") + .click({ force: true }) + cy.get(".spectrum-Menu-itemLabel").contains("Edit").click() + cy.get(".modal-inner-wrapper").within(() => { + cy.get("input").type(" Updated") + cy.contains("Save").click() + }) + cy.wait(1000) + cy.contains("Test View Updated").should("be.visible") + }) + + it("deletes a view", () => { + cy.contains(".nav-item", "Test View Updated") + .find(".actions .icon") + .click({ force: true }) + cy.contains("Delete").click() + cy.contains("Delete View").click() + cy.wait(500) + cy.contains("TestView Updated").should("not.exist") }) }) - it("filters the view by age over 10", () => { - cy.contains("Filter").click() - cy.contains("Add Filter").click() - - cy.get(".modal-inner-wrapper").within(() => { - cy.get(".spectrum-Picker-label").eq(0).click() - cy.contains("age").click({ force: true }) - - cy.get(".spectrum-Picker-label").eq(1).click() - cy.contains("More Than").click({ force: true }) - - cy.get("input").type(18) - cy.contains("Save").click() - }) - - cy.get(".spectrum-Table-row").get($values => { - expect($values).to.have.length(5) - }) - }) - - it("creates a stats calculation view based on age", () => { - cy.wait(1000) - cy.contains("Calculate").click() - cy.get(".modal-inner-wrapper").within(() => { - cy.get(".spectrum-Picker-label").eq(0).click() - cy.contains("Statistics").click() - - cy.get(".spectrum-Picker-label").eq(1).click() - cy.contains("age").click({ force: true }) - - cy.get(".spectrum-Button").contains("Save").click({ force: true }) - }) - cy.wait(1000) - - cy.get(".title").then($headers => { - expect($headers).to.have.length(7) - const headers = Array.from($headers).map(header => - header.textContent.trim() - ) - expect(removeSpacing(headers)).to.deep.eq([ - "field", - "sum", - "min", - "max", - "count", - "sumsqr", - "avg", - ]) - }) - cy.get(".spectrum-Table-cell").then($values => { - let values = Array.from($values).map(header => header.textContent.trim()) - expect(values).to.deep.eq(["age", "155", "20", "49", "5", "5347", "31"]) - }) - }) - - it("groups the view by group", () => { - cy.contains("Group by").click() - cy.get(".modal-inner-wrapper").within(() => { - cy.get(".spectrum-Picker-label").eq(0).click() - cy.contains("group").click() - cy.contains("Save").click() - }) - cy.wait(1000) - cy.contains("Students").should("be.visible") - cy.contains("Teachers").should("be.visible") - - cy.get(".spectrum-Table-cell").then($values => { - let values = Array.from($values).map(header => header.textContent.trim()) - expect(values).to.deep.eq([ - "Students", - "70", - "20", - "25", - "3", - "1650", - "23.333333333333332", - "Teachers", - "85", - "36", - "49", - "2", - "3697", - "42.5", - ]) - }) - }) - - it("renames a view", () => { - cy.contains(".nav-item", "Test View") - .find(".actions .icon") - .click({ force: true }) - cy.get(".spectrum-Menu-itemLabel").contains("Edit").click() - cy.get(".modal-inner-wrapper").within(() => { - cy.get("input").type(" Updated") - cy.contains("Save").click() - }) - cy.wait(1000) - cy.contains("Test View Updated").should("be.visible") - }) - - it("deletes a view", () => { - cy.contains(".nav-item", "Test View Updated") - .find(".actions .icon") - .click({ force: true }) - cy.contains("Delete").click() - cy.contains("Delete View").click() - cy.wait(500) - cy.contains("TestView Updated").should("not.exist") - }) -}) - -function removeSpacing(headers) { - let newHeaders = [] - for (let header of headers) { - newHeaders.push(header.replace(/\s\s+/g, " ")) + function removeSpacing(headers) { + let newHeaders = [] + for (let header of headers) { + newHeaders.push(header.replace(/\s\s+/g, " ")) + } + return newHeaders } - return newHeaders -} +}) diff --git a/packages/builder/cypress/integration/customThemingProperties.spec.js b/packages/builder/cypress/integration/customThemingProperties.spec.js index 5b7922bde7..ed3478ca67 100644 --- a/packages/builder/cypress/integration/customThemingProperties.spec.js +++ b/packages/builder/cypress/integration/customThemingProperties.spec.js @@ -1,84 +1,87 @@ -xcontext("Custom Theming Properties", () => { - before(() => { - cy.login() - cy.createTestApp() - cy.navigateToFrontend() - }) +import filterTests from "../support/filterTests" - /* Default Values: - Button roundness = Large - Accent colour = Blue 600 - Accent colour (hover) = Blue 500 - Navigation bar background colour = Gray 100 - Navigation bar text colour = Gray 800 */ - it("should reset the color property values", () => { - // Open Theme modal and change colours - cy.get(".spectrum-ActionButton-label").contains("Theme").click() - cy.get(".spectrum-Picker").contains("Large").click() - .parents() - .get(".spectrum-Menu-itemLabel").contains("None").click() - changeThemeColors() - // Reset colours - cy.get(".spectrum-Button-label").contains("Reset").click({force: true}) - // Check values have reset - checkThemeColorDefaults() - }) - - /* Button Roundness Values: - None = 0 - Small = 4px - Medium = 8px - 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){ - cy.get(".spectrum-ActionButton-label").contains("Theme").click() - cy.get(".setting").contains("Button roundness").parent() - .get(".select-wrapper").click() - cy.get(".spectrum-Popover").find('li').eq(index).click() - cy.get(".spectrum-Button").contains("View changes").click({force: true}) - cy.reload() - cy.getComponent(componentId) - .parents(".svelte-xiqd1c").eq(0).should('have.attr', 'style').and('contains', `--buttonBorderRadius:${item}`) +filterTests(['all'], () => { + xcontext("Custom Theming Properties", () => { + before(() => { + cy.login() + cy.createTestApp() + cy.navigateToFrontend() + }) + + /* Default Values: + Button roundness = Large + Accent colour = Blue 600 + Accent colour (hover) = Blue 500 + Navigation bar background colour = Gray 100 + Navigation bar text colour = Gray 800 */ + it("should reset the color property values", () => { + // Open Theme modal and change colours + cy.get(".spectrum-ActionButton-label").contains("Theme").click() + cy.get(".spectrum-Picker").contains("Large").click() + .parents() + .get(".spectrum-Menu-itemLabel").contains("None").click() + changeThemeColors() + // Reset colours + cy.get(".spectrum-Button-label").contains("Reset").click({force: true}) + // Check values have reset + checkThemeColorDefaults() + }) + + /* Button Roundness Values: + None = 0 + Small = 4px + Medium = 8px + 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){ + cy.get(".spectrum-ActionButton-label").contains("Theme").click() + cy.get(".setting").contains("Button roundness").parent() + .get(".select-wrapper").click() + cy.get(".spectrum-Popover").find('li').eq(index).click() + cy.get(".spectrum-Button").contains("View changes").click({force: true}) + cy.reload() + cy.getComponent(componentId) + .parents(".svelte-xiqd1c").eq(0).should('have.attr', 'style').and('contains', `--buttonBorderRadius:${item}`) + }) }) }) + + const changeThemeColors = () => { + // Changes the theme colours + cy.get(".spectrum-FieldLabel").contains("Accent color") + .parent().find(".container.svelte-z3cm5a").click() + .find('[title="Red 400"]').click() + cy.get(".spectrum-FieldLabel").contains("Accent color (hover)") + .parent().find(".container.svelte-z3cm5a").click() + .find('[title="Orange 400"]').click() + cy.get(".spectrum-FieldLabel").contains("Navigation bar background color") + .parent().find(".container.svelte-z3cm5a").click() + .find('[title="Yellow 400"]').click() + cy.get(".spectrum-FieldLabel").contains("Navigation bar text color") + .parent().find(".container.svelte-z3cm5a").click() + .find('[title="Green 400"]').click() + } + + const checkThemeColorDefaults = () => { + cy.get(".spectrum-FieldLabel").contains("Accent color") + .parent().find(".container.svelte-z3cm5a").click() + .get('[title="Blue 600"]').children().find('[aria-label="Checkmark"]') + cy.get(".spectrum-Dialog-grid").click() + cy.get(".spectrum-FieldLabel").contains("Accent color (hover)") + .parent().find(".container.svelte-z3cm5a").click() + .get('[title="Blue 500"]').children().find('[aria-label="Checkmark"]') + cy.get(".spectrum-Dialog-grid").click() + cy.get(".spectrum-FieldLabel").contains("Navigation bar background color") + .parent().find(".container.svelte-z3cm5a").click() + .get('[title="Gray 100"]').children().find('[aria-label="Checkmark"]') + cy.get(".spectrum-Dialog-grid").click() + cy.get(".spectrum-FieldLabel").contains("Navigation bar text color") + .parent().find(".container.svelte-z3cm5a").click() + .get('[title="Gray 800"]').children().find('[aria-label="Checkmark"]') + } }) - - const changeThemeColors = () => { - // Changes the theme colours - cy.get(".spectrum-FieldLabel").contains("Accent color") - .parent().find(".container.svelte-z3cm5a").click() - .find('[title="Red 400"]').click() - cy.get(".spectrum-FieldLabel").contains("Accent color (hover)") - .parent().find(".container.svelte-z3cm5a").click() - .find('[title="Orange 400"]').click() - cy.get(".spectrum-FieldLabel").contains("Navigation bar background color") - .parent().find(".container.svelte-z3cm5a").click() - .find('[title="Yellow 400"]').click() - cy.get(".spectrum-FieldLabel").contains("Navigation bar text color") - .parent().find(".container.svelte-z3cm5a").click() - .find('[title="Green 400"]').click() - } - - const checkThemeColorDefaults = () => { - cy.get(".spectrum-FieldLabel").contains("Accent color") - .parent().find(".container.svelte-z3cm5a").click() - .get('[title="Blue 600"]').children().find('[aria-label="Checkmark"]') - cy.get(".spectrum-Dialog-grid").click() - cy.get(".spectrum-FieldLabel").contains("Accent color (hover)") - .parent().find(".container.svelte-z3cm5a").click() - .get('[title="Blue 500"]').children().find('[aria-label="Checkmark"]') - cy.get(".spectrum-Dialog-grid").click() - cy.get(".spectrum-FieldLabel").contains("Navigation bar background color") - .parent().find(".container.svelte-z3cm5a").click() - .get('[title="Gray 100"]').children().find('[aria-label="Checkmark"]') - cy.get(".spectrum-Dialog-grid").click() - cy.get(".spectrum-FieldLabel").contains("Navigation bar text color") - .parent().find(".container.svelte-z3cm5a").click() - .get('[title="Gray 800"]').children().find('[aria-label="Checkmark"]') - } - }) diff --git a/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js b/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js new file mode 100644 index 0000000000..0eefb750ac --- /dev/null +++ b/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js @@ -0,0 +1,41 @@ +import filterTests from "../../support/filterTests" + +filterTests(['all'], () => { + context("Datasource Wizard", () => { + before(() => { + cy.login() + cy.createTestApp() + }) + + it("should navigate in and out of a datasource via wizard", () => { + // Select PostgreSQL and add config (without fetch) + const datasource = "Oracle" + cy.selectExternalDatasource(datasource) + cy.addDatasourceConfig(datasource, true) + + // 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(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Button").contains("Continue").click({ force: true }) + }) + + // Fetch tables after selection + // Previously entered config should not have been saved + // Config is back to default values + // Modal will close and provide 500 error + cy.intercept('**/datasources').as('datasourceConnection') + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Button").contains("Save and fetch tables").click({ force: true }) + }) + cy.wait("@datasourceConnection") + cy.get("@datasourceConnection").its('response.body') + .should('have.property', 'status', 500) + }) + }) +}) diff --git a/packages/builder/cypress/integration/datasources/mySql.spec.js b/packages/builder/cypress/integration/datasources/mySql.spec.js new file mode 100644 index 0000000000..673a902f96 --- /dev/null +++ b/packages/builder/cypress/integration/datasources/mySql.spec.js @@ -0,0 +1,191 @@ +import filterTests from "../../support/filterTests" + +filterTests(['all'], () => { + context("MySQL Datasource Testing", () => { + if (Cypress.env("TEST_ENV")) { + + before(() => { + cy.login() + cy.createTestApp() + }) + const datasource = "MySQL" + const queryName = "Cypress Test Query" + const queryRename = "CT Query Rename" + + it("Should add MySQL data source without configuration", () => { + // Select MySQL data source + cy.selectExternalDatasource(datasource) + // Attempt to fetch tables without applying configuration + cy.intercept('**/datasources').as('datasource') + cy.get(".spectrum-Button") + .contains("Save and fetch tables") + .click({ force: true }) + // Intercept Request after button click & apply assertions + cy.wait("@datasource") + cy.get("@datasource").its('response.body') + .should('have.property', 'message', 'connect ECONNREFUSED 127.0.0.1:3306') + cy.get("@datasource").its('response.body') + .should('have.property', 'status', 500) + }) + + it("should add MySQL data source and fetch tables", () => { + // Add & configure MySQL data source + cy.selectExternalDatasource(datasource) + cy.intercept('**/datasources').as('datasource') + cy.addDatasourceConfig(datasource) + // Check response from datasource after adding configuration + cy.wait("@datasource") + cy.get("@datasource").its('response.statusCode') + .should('eq', 200) + // Confirm fetch tables was successful + cy.get(".spectrum-Table-body").eq(0) + .find('tr') + .its('length') + .should('be.gt', 0) + }) + + it("should check table fetching error", () => { + // MySQL test data source contains tables without primary keys + cy.get(".spectrum-InLineAlert") + .should('contain', 'Error fetching tables') + .and('contain', 'No primary key constraint found') + }) + + it("should define a One relationship type", () => { + // Select relationship type & configure + cy.get(".spectrum-Button").contains("Define relationship").click({ force: true }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Picker").eq(0).click() + cy.get(".spectrum-Popover").contains("One").click() + cy.get(".spectrum-Picker").eq(1).click() + cy.get(".spectrum-Popover").contains("REGIONS").click() + cy.get(".spectrum-Picker").eq(2).click() + cy.get(".spectrum-Popover").contains("REGION_ID").click() + cy.get(".spectrum-Picker").eq(3).click() + cy.get(".spectrum-Popover").contains("COUNTRIES").click() + cy.get(".spectrum-Picker").eq(4).click() + cy.get(".spectrum-Popover").contains("REGION_ID").click() + // Save relationship & reload page + cy.get(".spectrum-Button").contains("Save").click({ force: true }) + cy.reload() + }) + // Confirm table length & column name + cy.get(".spectrum-Table-body").eq(1) + .find('tr') + .its('length') + .should('eq', 1) + cy.get(".spectrum-Table-cell").should('contain', "COUNTRIES to REGIONS") + }) + + it("should define a Many relationship type", () => { + // Select relationship type & configure + cy.get(".spectrum-Button").contains("Define relationship").click({ force: true }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Picker").eq(0).click() + cy.get(".spectrum-Popover").contains("Many").click() + cy.get(".spectrum-Picker").eq(1).click() + cy.get(".spectrum-Popover").contains("LOCATIONS").click() + cy.get(".spectrum-Picker").eq(2).click() + cy.get(".spectrum-Popover").contains("REGIONS").click() + cy.get(".spectrum-Picker").eq(3).click() + cy.get(".spectrum-Popover").contains("COUNTRIES").click() + cy.get(".spectrum-Picker").eq(4).click() + cy.get(".spectrum-Popover").contains("COUNTRY_ID").click() + cy.get(".spectrum-Picker").eq(5).click() + cy.get(".spectrum-Popover").contains("REGION_ID").click() + // 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-body").eq(1) + .find('tr') + .its('length') + .should('eq', 2) + cy.get(".spectrum-Table-cell") + .should('contain', "LOCATIONS through COUNTRIES → REGIONS") + }) + + it("should delete relationships", () => { + // Delete both relationships + cy.get(".spectrum-Table-body") + .eq(1).find('tr').its('length') + .then((len) => { + for (let i = 0; i < len; i++) { + cy.get(".spectrum-Table-body").eq(1).within(() => { + cy.get(".spectrum-Table-row").eq(0).click() + cy.wait(500) + }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Button").contains("Delete").click({ force: true }) + }) + cy.reload() + } + // Confirm relationships no longer exist + cy.get(".spectrum-Body").should('contain', 'No relationships configured') + }) + }) + + it("should add a query", () => { + // Add query + cy.get(".spectrum-Button").contains("Add query").click({ force: true }) + cy.get(".spectrum-Form-item").eq(0).within(() => { + cy.get("input").type(queryName) + }) + // Insert Query within Fields section + cy.get(".CodeMirror textarea").eq(0) + .type("SELECT * FROM books", { force: true }) + // Intercept query execution + cy.intercept('**/queries/preview').as('query') + cy.get(".spectrum-Button").contains("Run Query").click({ force: true }) + cy.wait(500) + cy.wait("@query") + // Assert against Status Code & Body + cy.get("@query").its('response.statusCode') + .should('eq', 200) + cy.get("@query").its('response.body') + .should('not.be.empty') + // Save query + cy.get(".spectrum-Button").contains("Save Query").click({ force: true }) + cy.get(".nav-item").should('contain', queryName) + }) + + it("should duplicate a query", () => { + // Get last nav item - The query + cy.get(".nav-item").last().within(() => { + cy.get(".icon").eq(1).click({ force: true }) + }) + // Select and confirm duplication + cy.get(".spectrum-Menu").contains("Duplicate").click() + cy.get(".nav-item").should('contain', queryName + ' (1)') + }) + + it("should edit a query name", () => { + // Rename query + cy.get(".spectrum-Form-item").eq(0).within(() => { + cy.get("input").clear().type(queryRename) + }) + // Save query + cy.get(".spectrum-Button").contains("Save Query").click({ force: true }) + cy.get(".nav-item").should('contain', queryRename) + }) + + it("should delete a query", () => { + // Get last nav item - The query + for (let i = 0; i < 2; i++) { + cy.get(".nav-item").last().within(() => { + cy.get(".icon").eq(1).click({ force: true }) + }) + // Select Delete + cy.get(".spectrum-Menu").contains("Delete").click() + 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").should('not.contain', queryRename) + }) + } + }) +}) diff --git a/packages/builder/cypress/integration/datasources/oracle.spec.js b/packages/builder/cypress/integration/datasources/oracle.spec.js new file mode 100644 index 0000000000..370a160bb1 --- /dev/null +++ b/packages/builder/cypress/integration/datasources/oracle.spec.js @@ -0,0 +1,195 @@ +import filterTests from "../../support/filterTests" + +filterTests(['all', 'smoke'], () => { + context("Oracle Datasource Testing", () => { + before(() => { + cy.login() + cy.createTestApp() + }) + const datasource = "Oracle" + const queryName = "Cypress Test Query" + const queryRename = "CT Query Rename" + + it("Should add Oracle data source and skip table fetch", () => { + // Select Oracle data source + cy.selectExternalDatasource(datasource) + // Skip table fetch - no config added + cy.get(".spectrum-Button").contains("Skip table fetch").click({ force: true }) + cy.wait(500) + // Confirm config contains localhost + cy.get(".spectrum-Textfield-input").eq(1).should('have.value', 'localhost') + // Add another Oracle data source, configure & skip table fetch + cy.selectExternalDatasource(datasource) + cy.addDatasourceConfig(datasource, true) + // Confirm config and no tables + cy.get(".spectrum-Textfield-input").eq(1).should('have.value', Cypress.env("oracle").HOST) + cy.get(".spectrum-Body").eq(2).should('contain', 'No tables found.') + }) + + it("Should add Oracle data source and fetch tables without configuration", () => { + // Select Oracle data source + cy.selectExternalDatasource(datasource) + // Attempt to fetch tables without applying configuration + cy.intercept('**/datasources').as('datasource') + cy.get(".spectrum-Button") + .contains("Save and fetch tables") + .click({ force: true }) + // Intercept Request after button click & apply assertions + cy.wait("@datasource") + cy.get("@datasource").its('response.body') + .should('have.property', 'message', 'NJS-007: invalid value for "user" in parameter 1') + cy.get("@datasource").its('response.body') + .should('have.property', 'status', 500) + }) + + it("should add Oracle data source and fetch tables", () => { + // Add & configure Oracle data source + cy.selectExternalDatasource(datasource) + cy.intercept('**/datasources').as('datasource') + cy.addDatasourceConfig(datasource) + // Check response from datasource after adding configuration + cy.wait("@datasource") + cy.get("@datasource").its('response.statusCode') + .should('eq', 200) + // Confirm fetch tables was successful + cy.get(".spectrum-Table-body").eq(0) + .find('tr') + .its('length') + .should('be.gt', 0) + }) + + it("should define a One relationship type", () => { + // Select relationship type & configure + cy.get(".spectrum-Button").contains("Define relationship").click({ force: true }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Picker").eq(0).click() + cy.get(".spectrum-Popover").contains("One").click() + cy.get(".spectrum-Picker").eq(1).click() + cy.get(".spectrum-Popover").contains("REGIONS").click() + cy.get(".spectrum-Picker").eq(2).click() + cy.get(".spectrum-Popover").contains("REGION_ID").click() + cy.get(".spectrum-Picker").eq(3).click() + cy.get(".spectrum-Popover").contains("COUNTRIES").click() + cy.get(".spectrum-Picker").eq(4).click() + cy.get(".spectrum-Popover").contains("REGION_ID").click() + // Save relationship & reload page + cy.get(".spectrum-Button").contains("Save").click({ force: true }) + cy.reload() + }) + // Confirm table length & column name + cy.get(".spectrum-Table-body").eq(1) + .find('tr') + .its('length') + .should('eq', 1) + cy.get(".spectrum-Table-cell").should('contain', "COUNTRIES to REGIONS") + }) + + it("should define a Many relationship type", () => { + // Select relationship type & configure + cy.get(".spectrum-Button").contains("Define relationship").click({ force: true }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Picker").eq(0).click() + cy.get(".spectrum-Popover").contains("Many").click() + cy.get(".spectrum-Picker").eq(1).click() + cy.get(".spectrum-Popover").contains("LOCATIONS").click() + cy.get(".spectrum-Picker").eq(2).click() + cy.get(".spectrum-Popover").contains("REGIONS").click() + cy.get(".spectrum-Picker").eq(3).click() + cy.get(".spectrum-Popover").contains("COUNTRIES").click() + cy.get(".spectrum-Picker").eq(4).click() + cy.get(".spectrum-Popover").contains("COUNTRY_ID").click() + cy.get(".spectrum-Picker").eq(5).click() + cy.get(".spectrum-Popover").contains("REGION_ID").click() + // Save relationship & reload page + cy.get(".spectrum-Button").contains("Save").click({ force: true }) + cy.reload() + }) + // Confirm table length & relationship name + cy.get(".spectrum-Table-body").eq(1) + .find('tr') + .its('length') + .should('eq', 2) + cy.get(".spectrum-Table-cell") + .should('contain', "LOCATIONS through COUNTRIES → REGIONS") + }) + + it("should delete relationships", () => { + // Delete both relationships + cy.get(".spectrum-Table-body") + .eq(1).find('tr').its('length') + .then((len) => { + for (let i = 0; i < len; i++) { + cy.get(".spectrum-Table-body").eq(1).within(() => { + cy.get(".spectrum-Table-row").eq(0).click() + cy.wait(500) + }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Button").contains("Delete").click({ force: true }) + }) + cy.reload() + } + // Confirm relationships no longer exist + cy.get(".spectrum-Body").should('contain', 'No relationships configured') + }) + }) + + it("should add a query", () => { + // Add query + cy.get(".spectrum-Button").contains("Add query").click({ force: true }) + cy.get(".spectrum-Form-item").eq(0).within(() => { + cy.get("input").type(queryName) + }) + // Insert Query within Fields section + cy.get(".CodeMirror textarea").eq(0) + .type("SELECT * FROM JOBS", { force: true }) + // Intercept query execution + cy.intercept('**/queries/preview').as('query') + cy.get(".spectrum-Button").contains("Run Query").click({ force: true }) + cy.wait(500) + cy.wait("@query") + // Assert against Status Code & Body + cy.get("@query").its('response.statusCode') + .should('eq', 200) + cy.get("@query").its('response.body') + .should('not.be.empty') + // Save query + cy.get(".spectrum-Button").contains("Save Query").click({ force: true }) + cy.get(".nav-item").should('contain', queryName) + }) + + it("should duplicate a query", () => { + // Get query nav item + cy.get(".nav-item").contains(queryName).parent().within(() => { + cy.get(".spectrum-Icon").eq(1).click({ force: true }) + }) + // Select and confirm duplication + cy.get(".spectrum-Menu").contains("Duplicate").click() + cy.get(".nav-item").should('contain', queryName + ' (1)') + }) + + it("should edit a query name", () => { + // Rename query + cy.get(".spectrum-Form-item").eq(0).within(() => { + cy.get("input").clear().type(queryRename) + }) + // Save query + cy.get(".spectrum-Button").contains("Save Query").click({ force: true }) + cy.get(".nav-item").should('contain', queryRename) + }) + + it("should delete a query", () => { + // Get query nav item - QueryName + cy.get(".nav-item").contains(queryName).parent().within(() => { + cy.get(".spectrum-Icon").eq(1).click({ force: true }) + }) + + // Select Delete + cy.get(".spectrum-Menu").contains("Delete").click() + cy.get(".spectrum-Button").contains("Delete Query").click({ force: true }) + cy.wait(1000) + + // Confirm deletion + cy.get(".nav-item").should('not.contain', queryName) + }) + }) +}) diff --git a/packages/builder/cypress/integration/datasources/postgreSql.spec.js b/packages/builder/cypress/integration/datasources/postgreSql.spec.js new file mode 100644 index 0000000000..c8ff915f90 --- /dev/null +++ b/packages/builder/cypress/integration/datasources/postgreSql.spec.js @@ -0,0 +1,241 @@ +import filterTests from "../../support/filterTests" + +filterTests(['all'], () => { + context("PostgreSQL Datasource Testing", () => { + if (Cypress.env("TEST_ENV")) { + + before(() => { + cy.login() + cy.createTestApp() + }) + const datasource = "PostgreSQL" + const queryName = "Cypress Test Query" + const queryRename = "CT Query Rename" + + it("Should add PostgreSQL data source without configuration", () => { + // Select PostgreSQL data source + cy.selectExternalDatasource(datasource) + // Attempt to fetch tables without applying configuration + cy.intercept('**/datasources').as('datasource') + cy.get(".spectrum-Button") + .contains("Save and fetch tables") + .click({ force: true }) + // Intercept Request after button click & apply assertions + cy.wait("@datasource") + cy.get("@datasource").its('response.body') + .should('have.property', 'message', 'connect ECONNREFUSED 127.0.0.1:5432') + cy.get("@datasource").its('response.body') + .should('have.property', 'status', 500) + }) + + it("should add PostgreSQL data source and fetch tables", () => { + // Add & configure PostgreSQL data source + cy.selectExternalDatasource(datasource) + cy.intercept('**/datasources').as('datasource') + cy.addDatasourceConfig(datasource) + // Check response from datasource after adding configuration + cy.wait("@datasource") + cy.get("@datasource").its('response.statusCode') + .should('eq', 200) + // Confirm fetch tables was successful + cy.get(".spectrum-Table-body").eq(0) + .find('tr') + .its('length') + .should('be.gt', 0) + }) + + it("should define a One relationship type", () => { + // Select relationship type & configure + cy.get(".spectrum-Button").contains("Define relationship").click({ force: true }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Picker").eq(0).click() + cy.get(".spectrum-Popover").contains("One").click() + cy.get(".spectrum-Picker").eq(1).click() + cy.get(".spectrum-Popover").contains("REGIONS").click() + cy.get(".spectrum-Picker").eq(2).click() + cy.get(".spectrum-Popover").contains("REGION_ID").click() + cy.get(".spectrum-Picker").eq(3).click() + cy.get(".spectrum-Popover").contains("COUNTRIES").click() + cy.get(".spectrum-Picker").eq(4).click() + cy.get(".spectrum-Popover").contains("REGION_ID").click() + // Save relationship & reload page + cy.get(".spectrum-Button").contains("Save").click({ force: true }) + cy.reload() + }) + // Confirm table length & column name + cy.get(".spectrum-Table-body").eq(1) + .find('tr') + .its('length') + .should('eq', 1) + cy.get(".spectrum-Table-cell").should('contain', "COUNTRIES to REGIONS") + }) + + it("should define a Many relationship type", () => { + // Select relationship type & configure + cy.get(".spectrum-Button").contains("Define relationship").click({ force: true }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Picker").eq(0).click() + cy.get(".spectrum-Popover").contains("Many").click() + cy.get(".spectrum-Picker").eq(1).click() + cy.get(".spectrum-Popover").contains("LOCATIONS").click() + cy.get(".spectrum-Picker").eq(2).click() + cy.get(".spectrum-Popover").contains("REGIONS").click() + cy.get(".spectrum-Picker").eq(3).click() + cy.get(".spectrum-Popover").contains("COUNTRIES").click() + cy.get(".spectrum-Picker").eq(4).click() + cy.get(".spectrum-Popover").contains("COUNTRY_ID").click() + cy.get(".spectrum-Picker").eq(5).click() + cy.get(".spectrum-Popover").contains("REGION_ID").click() + // Save relationship & reload page + cy.get(".spectrum-Button").contains("Save").click({ force: true }) + cy.reload() + }) + // Confirm table length & relationship name + cy.get(".spectrum-Table-body").eq(1) + .find('tr') + .its('length') + .should('eq', 2) + cy.get(".spectrum-Table-cell") + .should('contain', "LOCATIONS through COUNTRIES → REGIONS") + }) + + it("should delete a relationship", () => { + cy.get(".hierarchy-items-container").contains(datasource).click() + cy.reload() + // Delete one relationship + cy.get(".spectrum-Table-body").eq(1).within(() => { + cy.get(".spectrum-Table-row").eq(0).click() + cy.wait(500) + }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Button").contains("Delete").click({ force: true }) + }) + cy.reload() + // Confirm relationship was deleted + cy.get(".spectrum-Table-body") + .eq(1).find('tr').its('length').should('eq', 1) + }) + + it("should add a query", () => { + // Add query + cy.get(".spectrum-Button").contains("Add query").click({ force: true }) + cy.get(".spectrum-Form-item").eq(0).within(() => { + cy.get("input").type(queryName) + }) + // Insert Query within Fields section + cy.get(".CodeMirror textarea").eq(0) + .type("SELECT * FROM books", { force: true }) + // Intercept query execution + cy.intercept('**/queries/preview').as('query') + cy.get(".spectrum-Button").contains("Run Query").click({ force: true }) + cy.wait(500) + cy.wait("@query") + // Assert against Status Code & Body + cy.get("@query").its('response.statusCode') + .should('eq', 200) + cy.get("@query").its('response.body') + .should('not.be.empty') + // Save query + cy.get(".spectrum-Button").contains("Save Query").click({ force: true }) + cy.get(".hierarchy-items-container").should('contain', queryName) + }) + + it("should switch to schema with no tables", () => { + // Switch Schema - To one without any tables + cy.get(".hierarchy-items-container").contains(datasource).click() + switchSchema("randomText") + + // No tables displayed + cy.get(".spectrum-Body").eq(2).should('contain', 'No tables found') + + // Previously created query should be visible + cy.get(".spectrum-Table-body").should('contain', queryName) + }) + + it("should switch schemas", () => { + // Switch schema - To one with tables + switchSchema("1") + + // Confirm tables exist - Check for specific one + cy.get(".spectrum-Table-body").eq(0).should('contain', 'test') + cy.get(".spectrum-Table-body").eq(0).find('tr').its('length').should('eq', 1) + + // Confirm specific table visible within left nav bar + cy.get(".hierarchy-items-container").should('contain', 'test') + + // Switch back to public schema + switchSchema("public") + + // Confirm tables exist - again + cy.get(".spectrum-Table-body").eq(0).should('contain', 'REGIONS') + cy.get(".spectrum-Table-body").eq(0) + .find('tr').its('length').should('be.gt', 1) + + // Confirm specific table visible within left nav bar + cy.get(".hierarchy-items-container").should('contain', 'REGIONS') + + // No relationships and one query + cy.get(".spectrum-Body").eq(3).should('contain', 'No relationships configured.') + cy.get(".spectrum-Table-body").eq(1).should('contain', queryName) + }) + + it("should duplicate a query", () => { + // Get last nav item - The query + cy.get(".nav-item").last().within(() => { + cy.get(".icon").eq(1).click({ force: true }) + }) + // Select and confirm duplication + cy.get(".spectrum-Menu").contains("Duplicate").click() + cy.get(".nav-item").should('contain', queryName + ' (1)') + }) + + it("should edit a query name", () => { + // Access query + cy.get(".hierarchy-items-container").contains(queryName + ' (1)').click() + + // Rename query + cy.get(".spectrum-Form-item").eq(0).within(() => { + cy.get("input").clear().type(queryRename) + }) + + // 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(".nav-item").should('contain', queryRename) + }) + + it("should delete a query", () => { + // Get last nav item - The query + for (let i = 0; i < 2; i++) { + cy.get(".nav-item").last().within(() => { + cy.get(".icon").eq(1).click({ force: true }) + }) + // Select Delete + cy.get(".spectrum-Menu").contains("Delete").click() + 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").should('not.contain', queryRename) + }) + + const switchSchema = (schema) => { + // Edit configuration - Change Schema + cy.get(".spectrum-Textfield").eq(6).within(() => { + cy.get('input').clear().type(schema) + }) + // Save configuration & fetch + cy.get(".spectrum-Button").contains("Save").click({ force: true }) + cy.get(".spectrum-Button").contains("Fetch tables").click({ force: true }) + // Click fetch tables again within modal + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get(".spectrum-Button").contains("Fetch tables").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 new file mode 100644 index 0000000000..89653a9e22 --- /dev/null +++ b/packages/builder/cypress/integration/datasources/rest.spec.js @@ -0,0 +1,43 @@ +import filterTests from "../../support/filterTests" + +filterTests(['smoke', 'all'], () => { + context("REST Datasource Testing", () => { + before(() => { + cy.login() + cy.createTestApp() + }) + + const datasource = "REST" + const restUrl = "https://api.openbrewerydb.org/breweries" + + it("Should add REST data source with incorrect API", () => { + // 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.intercept('**/preview').as('queryError') + cy.get("input").clear().type("random text") + cy.get(".spectrum-Button").contains("Send").click({ force: true }) + // Intercept Request after button click & apply assertions + cy.wait("@queryError") + cy.get("@queryError").its('response.body') + .should('have.property', 'message', 'request to http://random/%20text? failed, reason: getaddrinfo ENOTFOUND random') + cy.get("@queryError").its('response.body') + .should('have.property', 'status', 400) + }) + + it("should add and configure a REST datasource", () => { + // Select REST datasource and create query + cy.selectExternalDatasource(datasource) + cy.wait(500) + // createRestQuery confirms query creation + cy.createRestQuery("GET", restUrl) + // Confirm status code response within REST datasource + cy.get(".spectrum-FieldLabel") + .contains("Status") + .children() + .should('contain', 200) + }) + }) +}) diff --git a/packages/builder/cypress/integration/queryLevelTransformers.spec.js b/packages/builder/cypress/integration/queryLevelTransformers.spec.js new file mode 100644 index 0000000000..e1b16774fb --- /dev/null +++ b/packages/builder/cypress/integration/queryLevelTransformers.spec.js @@ -0,0 +1,116 @@ +import filterTests from "../support/filterTests" + +filterTests(['smoke', 'all'], () => { + context("Query Level Transformers", () => { + before(() => { + cy.login() + cy.deleteApp("Cypress Tests") + cy.createApp("Cypress Tests") + }) + + it("should write a transformer function", () => { + // Add REST datasource - contains API for breweries + const datasource = "REST" + const restUrl = "https://api.openbrewerydb.org/breweries" + cy.selectExternalDatasource(datasource) + cy.createRestQuery("GET", restUrl) + cy.get(".spectrum-Tabs-itemLabel").contains("Transformer").click() + // Get Transformer Function from file + cy.readFile("cypress/support/queryLevelTransformerFunction.js").then((transformerFunction) => { + cy.get(".CodeMirror textarea") + // Highlight current text and overwrite with file contents + .type(Cypress.platform === 'darwin' ? '{cmd}a' : '{ctrl}a', { force: true }) + .type(transformerFunction, { parseSpecialCharSequences: false }) + }) + // Send Query + cy.intercept('**/queries/preview').as('query') + cy.get(".spectrum-Button").contains("Send").click({ force: true }) + cy.wait("@query") + // Assert against Status Code, body, & body rows + cy.get("@query").its('response.statusCode') + .should('eq', 200) + cy.get("@query").its('response.body').should('not.be.empty') + cy.get("@query").its('response.body.rows').should('not.be.empty') + }) + + it("should add data to the previous query", () => { + // Add REST datasource - contains API for breweries + const datasource = "REST" + const restUrl = "https://api.openbrewerydb.org/breweries" + cy.selectExternalDatasource(datasource) + cy.createRestQuery("GET", restUrl) + cy.get(".spectrum-Tabs-itemLabel").contains("Transformer").click() + // Get Transformer Function with Data from file + cy.readFile("cypress/support/queryLevelTransformerFunctionWithData.js").then((transformerFunction) => { + //console.log(transformerFunction[1]) + cy.get(".CodeMirror textarea") + // Highlight current text and overwrite with file contents + .type(Cypress.platform === 'darwin' ? '{cmd}a' : '{ctrl}a', { force: true }) + .type(transformerFunction, { parseSpecialCharSequences: false }) + }) + // Send Query + cy.intercept('**/queries/preview').as('query') + cy.get(".spectrum-Button").contains("Send").click({ force: true }) + cy.wait("@query") + // Assert against Status Code, body, & body rows + cy.get("@query").its('response.statusCode') + .should('eq', 200) + cy.get("@query").its('response.body').should('not.be.empty') + cy.get("@query").its('response.body.rows').should('not.be.empty') + }) + + it("should run an invalid query within the transformer section", () => { + // Add REST datasource - contains API for breweries + const datasource = "REST" + const restUrl = "https://api.openbrewerydb.org/breweries" + cy.selectExternalDatasource(datasource) + cy.createRestQuery("GET", restUrl) + cy.get(".spectrum-Tabs-itemLabel").contains("Transformer").click() + // Clear the code box and add "test" + cy.get(".CodeMirror textarea") + .type(Cypress.platform === 'darwin' ? '{cmd}a' : '{ctrl}a', { force: true }) + .type("test") + // Run Query and intercept + cy.intercept('**/preview').as('queryError') + cy.get(".spectrum-Button").contains("Send").click({ force: true }) + cy.wait("@queryError") + cy.wait(500) + // Assert against message and status for the query error + cy.get("@queryError").its('response.body').should('have.property', 'message', "test is not defined") + cy.get("@queryError").its('response.body').should('have.property', 'status', 400) + }) + + it("should run an invalid query via POST request", () => { + // POST request with transformer as null + cy.request({method: 'POST', + url: `${Cypress.config().baseUrl}/api/queries/`, + body: {fields : {"headers":{},"queryString":null,"path":null}, + parameters : [], + schema : {}, + name : "test", + queryVerb : "read", + transformer : null, + datasourceId: "test"}, + // Expected 400 error - Transformer must be a string + failOnStatusCode: false}).then((response) => { + expect(response.status).to.equal(400) + expect(response.body.message).to.include('Invalid body - "transformer" must be a string') + }) + }) + + it("should run an empty query", () => { + // POST request with Transformer as an empty string + cy.request({method: 'POST', + url: `${Cypress.config().baseUrl}/api/queries/preview`, + body: {fields : {"headers":{},"queryString":null,"path":null}, + queryVerb : "read", + transformer : "", + datasourceId: "test"}, + // Expected 400 error - Transformer is not allowed to be empty + failOnStatusCode: false}).then((response) => { + expect(response.status).to.equal(400) + expect(response.body.message).to.include('Invalid body - "transformer" is not allowed to be empty') + }) + }) + }) +}) diff --git a/packages/builder/cypress/integration/renameAnApplication.spec.js b/packages/builder/cypress/integration/renameAnApplication.spec.js index a954faee95..48e829fa03 100644 --- a/packages/builder/cypress/integration/renameAnApplication.spec.js +++ b/packages/builder/cypress/integration/renameAnApplication.spec.js @@ -1,103 +1,133 @@ -context("Rename an App", () => { - beforeEach(() => { - cy.login() - cy.createTestApp() - }) +import filterTests from "../support/filterTests" -it("should rename an unpublished application", () => { - const appRename = "Cypress Renamed" - // Rename app, Search for app, Confirm name was changed - cy.get(".home-logo").click() - renameApp(appRename) - cy.searchForApplication(appRename) - cy.get(".appTable").find(".title").should("have.length", 1) - cy.deleteApp(appRename) -}) - -xit("Should rename a published application", () => { - // It is not possible to rename a published application - const appRename = "Cypress Renamed" - // Publish the app - cy.get(".toprightnav") - cy.get(".spectrum-Button").contains("Publish").click({force: true}) - cy.get(".spectrum-Dialog-grid") - .within(() => { - // Click publish again within the modal - cy.get(".spectrum-Button").contains("Publish").click({force: true}) +filterTests(['all'], () => { + context("Rename an App", () => { + beforeEach(() => { + cy.login() + cy.createTestApp() }) - // Rename app, Search for app, Confirm name was changed - cy.get(".home-logo").click() - renameApp(appRename, true) - cy.searchForApplication(appRename) - cy.get(".appTable").find(".title").should("have.length", 1) -}) -it("Should try to rename an application to have no name", () => { - cy.get(".home-logo").click() - renameApp(" ", false, true) - // Close modal and confirm name has not been changed - cy.get(".spectrum-Dialog-grid").contains("Cancel").click() - cy.searchForApplication("Cypress Tests") - cy.get(".appTable").find(".title").should("have.length", 1) -}) - -xit("Should create two applications with the same name", () => { - // It is not possible to have applications with the same name - const appName = "Cypress Tests" - cy.visit(`localhost:${Cypress.env("PORT")}/builder`) - cy.wait(500) - cy.get(".spectrum-Button").contains("Create app").click({force: true}) - cy.contains(/Start from scratch/).click() - cy.get(".spectrum-Modal") - .within(() => { - cy.get("input").eq(0).type(appName) - cy.get(".spectrum-ButtonGroup").contains("Create app").click({force: true}) - cy.get(".error").should("have.text", "Another app with the same name already exists") + it("should rename an unpublished application", () => { + const appName = "Cypress Tests" + const appRename = "Cypress Renamed" + // Rename app, Search for app, Confirm name was changed + cy.get(".home-logo").click() + renameApp(appName, appRename) + cy.reload() + cy.wait(1000) + cy.searchForApplication(appRename) + cy.get(".appTable").find(".title").should("have.length", 1) + // Set app name back to Cypress Tests + cy.reload() + cy.wait(1000) + renameApp(appRename, appName) }) -}) - -it("should validate application names", () => { - // App name must be letters, numbers and spaces only - // This test checks numbers and special characters specifically - const numberName = 12345 - const specialCharName = "£$%^" - cy.get(".home-logo").click() - renameApp(numberName) - cy.searchForApplication(numberName) - cy.get(".appTable").find(".title").should("have.length", 1) - renameApp(specialCharName) - cy.get(".error").should("have.text", "App name must be letters, numbers and spaces only") -}) - - const renameApp = (appName, published, noName) => { - cy.request(`localhost:${Cypress.env("PORT")}/api/applications?status=all`) - .its("body") - .then(val => { - if (val.length > 0) { - cy.get(".appTable > :nth-child(5) > :nth-child(2) > .spectrum-Icon").click() - // Check for when an app is published - if (published == true){ - // Should not have Edit as option, will unpublish app - cy.should("not.have.value", "Edit") - cy.get(".spectrum-Menu").contains("Unpublish").click() - cy.get(".spectrum-Dialog-grid").contains("Unpublish app").click() - cy.get(".appTable > :nth-child(5) > :nth-child(2) > .spectrum-Icon").click() - } - cy.contains("Edit").click() - cy.get(".spectrum-Modal") + + xit("Should rename a published application", () => { + // It is not possible to rename a published application + const appName = "Cypress Tests" + const appRename = "Cypress Renamed" + // Publish the app + cy.get(".toprightnav") + cy.get(".spectrum-Button").contains("Publish").click({force: true}) + cy.get(".spectrum-Dialog-grid") .within(() => { - if (noName == true){ - cy.get("input").clear() - cy.get(".spectrum-Dialog-grid").click() - .contains("App name must be letters, numbers and spaces only") - return cy + // Click publish again within the modal + cy.get(".spectrum-Button").contains("Publish").click({force: true}) + }) + // Rename app, Search for app, Confirm name was changed + cy.get(".home-logo").click() + renameApp(appName, appRename, true) + cy.searchForApplication(appRename) + cy.get(".appTable").find(".wrapper").should("have.length", 1) + }) + + it("Should try to rename an application to have no name", () => { + const appName = "Cypress Tests" + cy.get(".home-logo").click() + 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.reload() + cy.wait(1000) + cy.searchForApplication(appName) + cy.get(".appTable").find(".title").should("have.length", 1) + + }) + + xit("Should create two applications with the same name", () => { + // 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.contains(/Start from scratch/).click() + cy.get(".spectrum-Modal") + .within(() => { + cy.get("input").eq(0).type(appName) + cy.get(".spectrum-ButtonGroup").contains("Create app").click({force: true}) + cy.get(".error").should("have.text", "Another app with the same name already exists") + }) + }) + + it("should validate application names", () => { + // App name must be letters, numbers and spaces only + // This test checks numbers and special characters specifically + const appName = "Cypress Tests" + const numberName = 12345 + const specialCharName = "£$%^" + cy.get(".home-logo").click() + renameApp(appName, numberName) + cy.reload() + cy.wait(1000) + cy.searchForApplication(numberName) + cy.get(".appTable").find(".title").should("have.length", 1) + 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.request(`${Cypress.config().baseUrl}/api/applications?status=all`) + .its("body") + .then(val => { + if (val.length > 0) { + cy.get(".appTable") + .within(() => { + cy.get(".spectrum-Icon").eq(1).click() + }) + // Check for when an app is published + if (published == true){ + // Should not have Edit as option, will unpublish app + cy.should("not.have.value", "Edit") + cy.get(".spectrum-Menu").contains("Unpublish").click() + cy.get(".spectrum-Dialog-grid").contains("Unpublish app").click() + cy.get(".appTable > :nth-child(5) > :nth-child(2) > .spectrum-Icon").click() } - cy.get("input").clear() - cy.get("input").eq(0).type(appName).should("have.value", appName).blur() - cy.get(".spectrum-ButtonGroup").contains("Save").click({force: true}) - cy.wait(500) - }) + cy.contains("Edit").click() + cy.get(".spectrum-Modal") + .within(() => { + if (noName == true){ + cy.get("input").clear() + cy.get(".spectrum-Dialog-grid").click() + .contains("App name must be letters, numbers and spaces only") + return cy + } + cy.get("input").clear() + cy.get("input").eq(0).type(changedName).should("have.value", changedName).blur() + cy.get(".spectrum-ButtonGroup").contains("Save").click({force: true}) + cy.wait(500) + }) + } + }) + } }) -} }) diff --git a/packages/builder/cypress/integration/revertApp.spec.js b/packages/builder/cypress/integration/revertApp.spec.js new file mode 100644 index 0000000000..5bd2679e34 --- /dev/null +++ b/packages/builder/cypress/integration/revertApp.spec.js @@ -0,0 +1,66 @@ +import filterTests from "../support/filterTests" + +filterTests(['smoke', 'all'], () => { + context("Revert apps", () => { + before(() => { + cy.login() + cy.createTestApp() + }) + + it("should try to revert an unpublished app", () => { + // Click revert icon + cy.get(".toprightnav").within(() => { + cy.get(".spectrum-Icon").eq(1).click() + }) + cy.get(".spectrum-Dialog-grid").within(() => { + // Enter app name before revert + cy.get("input").type("Cypress Tests") + cy.intercept('**/revert').as('revertApp') + // Click Revert + cy.get(".spectrum-Button").contains("Revert").click({ force: true }) + // Intercept Request after button click & apply assertions + cy.wait("@revertApp") + cy.get("@revertApp").its('response.body').should('have.property', 'message', "App has not yet been deployed") + cy.get("@revertApp").its('response.body').should('have.property', 'status', 400) + }) + }) + + it("should revert a published app", () => { + // Add initial component - Paragraph + cy.addComponent("Elements", "Paragraph") + // Publish app + cy.get(".spectrum-Button").contains("Publish").click({ force: true }) + cy.get(".spectrum-ButtonGroup").within(() => { + cy.get(".spectrum-Button").contains("Publish").click({ force: true }) + }) + // Add second component - Button + cy.addComponent("Elements", "Button") + // Click Revert + cy.get(".toprightnav").within(() => { + cy.get(".spectrum-Icon").eq(1).click() + }) + 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") + // Confirm Button component is not visible + cy.get(".root").should("not.have.text", "New Button") + }) + + it("should enter incorrect app name when reverting", () => { + // Click Revert + cy.get(".toprightnav").within(() => { + cy.get(".spectrum-Icon").eq(1).click() + }) + // Enter incorrect app name + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get("input").type("Cypress Tests") + // Revert button within modal should be disabled + cy.get(".spectrum-Button").eq(1).should('be.disabled') + }) + }) + }) +}) diff --git a/packages/builder/cypress/support/filterTests.js b/packages/builder/cypress/support/filterTests.js new file mode 100644 index 0000000000..074fd05d33 --- /dev/null +++ b/packages/builder/cypress/support/filterTests.js @@ -0,0 +1,16 @@ +const filterTests = (testTags, runTest) => { + // testTags is an array of tags + // runTest is all tests + if (Cypress.env("TEST_TAGS")) { + const tags = Cypress.env("TEST_TAGS").split("/") + const found = testTags.some($testTags => tags.includes($testTags)) + + if (found) { + runTest() + } + } else { + runTest() + } +} + +export default filterTests diff --git a/packages/server/src/integrations/utils.ts b/packages/server/src/integrations/utils.ts index b8c96efffe..b9e643e26a 100644 --- a/packages/server/src/integrations/utils.ts +++ b/packages/server/src/integrations/utils.ts @@ -153,8 +153,15 @@ export function isIsoDateString(str: string) { * @param column The column to check, to see if it is a valid relationship. * @param tableIds The IDs of the tables which currently exist. */ -function shouldCopyRelationship(column: { type: string, tableId?: string }, tableIds: [string]) { - return column.type === FieldTypes.LINK && column.tableId && tableIds.includes(column.tableId) +function shouldCopyRelationship( + column: { type: string; tableId?: string }, + tableIds: [string] +) { + return ( + column.type === FieldTypes.LINK && + column.tableId && + tableIds.includes(column.tableId) + ) } /** @@ -165,9 +172,15 @@ function shouldCopyRelationship(column: { type: string, tableId?: string }, tabl * @param column The column to check for options or boolean type. * @param fetchedColumn The fetched column to check for the type in the external database. */ -function shouldCopySpecialColumn(column: { type: string }, fetchedColumn: { type: string } | undefined) { - return column.type === FieldTypes.OPTIONS || - ((!fetchedColumn || fetchedColumn.type === FieldTypes.NUMBER) && column.type === FieldTypes.BOOLEAN) +function shouldCopySpecialColumn( + column: { type: string }, + fetchedColumn: { type: string } | undefined +) { + return ( + column.type === FieldTypes.OPTIONS || + ((!fetchedColumn || fetchedColumn.type === FieldTypes.NUMBER) && + column.type === FieldTypes.BOOLEAN) + ) } /**