From b9760c6dbc1c37b34a341807368517714c4852b9 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 5 Mar 2021 13:52:26 +0000 Subject: [PATCH 1/6] Add cypress tests for data bindings and component creation --- packages/builder/cypress.json | 4 +- .../cypress/integration/createApp.spec.js | 26 ++--- .../cypress/integration/createBinding.spec.js | 49 +++++--- .../integration/createComponents.spec.js | 110 ++++++++++-------- packages/builder/cypress/support/commands.js | 58 +++++---- .../AppPreview/ComponentSelectionList.svelte | 2 + .../PropertyControls/PropertyControl.svelte | 2 +- .../src/components/settings/Link.svelte | 5 +- .../src/components/start/AppCard.svelte | 2 +- 9 files changed, 153 insertions(+), 105 deletions(-) diff --git a/packages/builder/cypress.json b/packages/builder/cypress.json index d76078f509..09b38ae985 100644 --- a/packages/builder/cypress.json +++ b/packages/builder/cypress.json @@ -1,8 +1,8 @@ { - "baseUrl": "http://localhost:4005/_builder/", + "baseUrl": "http://localhost:4001/_builder/", "video": true, "projectId": "bmbemn", "env": { - "PORT": "4005" + "PORT": "4001" } } diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index a32782867a..7195da24ce 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -1,18 +1,12 @@ -context('Create an Application', () => { +context("Create an Application", () => { + beforeEach(() => { + cy.server() + cy.visit(`localhost:${Cypress.env("PORT")}/_builder`) + }) - beforeEach(() => { - cy.server() - cy.visit(`localhost:${Cypress.env("PORT")}/_builder`) - }) - - // https://on.cypress.io/interacting-with-elements - - it('should create a new application', () => { - // https://on.cypress.io/type - cy.createApp('My Cool App', 'This is a description') - - cy.visit(`localhost:${Cypress.env("PORT")}/_builder`) - - cy.contains('My Cool App').should('exist') - }) + it("should create a new application", () => { + cy.createApp("My Cool App", "This is a description") + cy.visit(`localhost:${Cypress.env("PORT")}/_builder`) + cy.contains("My Cool App").should("exist") + }) }) diff --git a/packages/builder/cypress/integration/createBinding.spec.js b/packages/builder/cypress/integration/createBinding.spec.js index 4074aca112..0550f4204b 100644 --- a/packages/builder/cypress/integration/createBinding.spec.js +++ b/packages/builder/cypress/integration/createBinding.spec.js @@ -1,18 +1,37 @@ -xcontext('Create a Binding', () => { - before(() => { - cy.visit(`localhost:${Cypress.env("PORT")}/_builder`) - cy.createApp('Binding App', 'Binding App Description') - cy.navigateToFrontend() - }) +context("Create Bindings", () => { + before(() => { + cy.createApp("Cypress Tests", "Cypress test app") + cy.navigateToFrontend() + }) - it('add an input binding', () => { - cy.get(".nav-items-container").contains('Home').click() - cy.contains("Add").click() - cy.get("[data-cy=Input]").click() - cy.get("[data-cy=Textfield]").click() - cy.contains("Heading").click() - cy.get("[data-cy=text-binding-button]").click() - cy.get("[data-cy=binding-dropdown-modal]").contains('Input 1').click() - cy.get("[data-cy=binding-dropdown-modal] textarea").should('have.value', 'Home{{ Input 1 }}') + it("should add a current user binding", () => { + cy.addComponent("Elements", "Paragraph").then(componentId => { + addSettingBinding("text", "Current User._id") + cy.getComponent(componentId).should( + "have.text", + `ro_ta_users_us_test@test.com` + ) }) + }) + + 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", "") + }) + }) }) + +const addSettingBinding = (setting, bindingText) => { + cy.get(`[data-cy="setting-${setting}"] [data-cy=text-binding-button]`).click() + cy.get(".drawer").within(() => { + cy.contains(bindingText).click() + cy.get("textarea").should("have.value", `{{ ${bindingText} }}`) + cy.get("button").click() + }) +} diff --git a/packages/builder/cypress/integration/createComponents.spec.js b/packages/builder/cypress/integration/createComponents.spec.js index b87e863e53..c668734f4b 100644 --- a/packages/builder/cypress/integration/createComponents.spec.js +++ b/packages/builder/cypress/integration/createComponents.spec.js @@ -1,60 +1,72 @@ -xcontext("Create Components", () => { +context("Create Components", () => { + let headlineId + before(() => { - cy.server() - cy.visit(`localhost:${Cypress.env("PORT")}/_builder`) - // https://on.cypress.io/type - cy.createApp("Table App", "Table App Description") - cy.createTable("dog", "name", "age") - cy.addRow("bob", "15") - }) - - // https://on.cypress.io/interacting-with-elements - it("should add a container", () => { + cy.createApp("Cypress Tests", "Cypress test app") + cy.createTable("dog") + cy.addColumn("dog", "name", "string") + cy.addColumn("dog", "age", "number") + cy.addColumn("dog", "type", "options") cy.navigateToFrontend() - cy.get(".switcher > :nth-child(2)").click() - cy.contains("Container").click() }) - it("should add a headline", () => { - cy.addHeadlineComponent("An Amazing headline!") - getIframeBody().contains("An Amazing headline!") + it("should add a container", () => { + cy.addComponent(null, "Container").then(componentId => { + cy.getComponent(componentId).should("exist") + }) }) - it("change the font size of the headline", () => { + + it("should add a headline", () => { + cy.addComponent("Elements", "Headline").then(componentId => { + headlineId = componentId + cy.getComponent(headlineId).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 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.contains("Design").click() + cy.getComponent(headlineId).should("have.css", "font-size", "60px") + }) - getIframeBody() - .contains("An Amazing headline!") - .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.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=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) + }) + }) }) }) - -const getIframeDocument = () => { - return ( - cy - .get("iframe") - // Cypress yields jQuery element, which has the real - // DOM element under property "0". - // From the real DOM iframe element we can get - // the "document" element, it is stored in "contentDocument" property - // Cypress "its" command can access deep properties using dot notation - // https://on.cypress.io/its - .its("0.contentDocument") - .should("exist") - ) -} - -const getIframeBody = () => { - // get the document - return ( - getIframeDocument() - // automatically retries until body is loaded - .its("body") - .should("not.be.undefined") - // wraps "body" DOM element to allow - // chaining more Cypress commands, like ".find(...)" - .then(cy.wrap) - ) -} diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index e92034c120..b961181241 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -25,8 +25,9 @@ // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) Cypress.Commands.add("createApp", name => { + cy.deleteApp(name) + cy.visit(`localhost:${Cypress.env("PORT")}/_builder`) cy.contains("Create New Web App").click() - cy.get("body") .then($body => { if ($body.find("input[name=apiKey]").length) { @@ -41,9 +42,7 @@ Cypress.Commands.add("createApp", name => { cy.get("input[name=applicationName]") .type(name) .should("have.value", name) - cy.contains("Next").click() - cy.get("input[name=email]") .click() .type("test@test.com") @@ -57,6 +56,22 @@ Cypress.Commands.add("createApp", name => { }) }) +Cypress.Commands.add("deleteApp", name => { + cy.visit(`localhost:${Cypress.env("PORT")}/_builder`) + cy.get("body").then($body => { + cy.wait(1000) + if ($body.find(`[data-cy="app-${name}"]`).length) { + cy.get(`[data-cy="app-${name}"] a`).click() + cy.get("[data-cy=settings-icon]").click() + cy.get(".modal-content").within(() => { + cy.contains("Danger Zone").click() + cy.get("input").type("DELETE") + cy.contains("Delete Entire App").click() + }) + } + }) +}) + Cypress.Commands.add("createTestTableWithData", () => { cy.createTable("dog") cy.addColumn("dog", "name", "Text") @@ -87,6 +102,7 @@ Cypress.Commands.add("addColumn", (tableName, columnName, type) => { cy.get("input") .first() .type(columnName) + // Unset table display column cy.contains("display column").click() cy.get("select").select(type) @@ -96,15 +112,12 @@ Cypress.Commands.add("addColumn", (tableName, columnName, type) => { Cypress.Commands.add("addRow", values => { cy.contains("Create New Row").click() - cy.get(".modal").within(() => { for (let i = 0; i < values.length; i++) { cy.get("input") .eq(i) .type(values[i]) } - - // Save cy.get(".buttons") .contains("Create") .click() @@ -114,9 +127,7 @@ Cypress.Commands.add("addRow", values => { Cypress.Commands.add("createUser", (email, password, role) => { // Create User cy.contains("Users").click() - cy.contains("Create New User").click() - cy.get(".modal").within(() => { cy.get("input") .first() @@ -135,20 +146,27 @@ Cypress.Commands.add("createUser", (email, password, role) => { }) }) -Cypress.Commands.add("addHeadlineComponent", text => { - cy.get(".switcher > :nth-child(2)").click() - - cy.get("[data-cy=Text]").click() - cy.get("[data-cy=Headline]").click() - cy.get(".tabs > :nth-child(2)").click() - cy.contains("Settings").click() - cy.get('input[name="text"]').type(text) - cy.contains("Design").click() +Cypress.Commands.add("addComponent", (category, component) => { + if (category) { + cy.get(`[data-cy="category-${category}"]`).click() + } + cy.get(`[data-cy="component-${component}"]`).click() + cy.wait(500) + cy.location().then(loc => { + const params = loc.pathname.split("/") + return cy.wrap(params[params.length - 1]) + }) }) -Cypress.Commands.add("addButtonComponent", () => { - cy.get(".switcher > :nth-child(2)").click() - cy.get("[data-cy=Button]").click() +Cypress.Commands.add("getComponent", componentId => { + return cy + .get("iframe") + .its("0.contentDocument") + .should("exist") + .its("body") + .should("not.be.null") + .then(cy.wrap) + .find(`[data-component-id=${componentId}]`) }) Cypress.Commands.add("navigateToFrontend", () => { diff --git a/packages/builder/src/components/design/AppPreview/ComponentSelectionList.svelte b/packages/builder/src/components/design/AppPreview/ComponentSelectionList.svelte index d161fc80a1..a1798d9ad7 100644 --- a/packages/builder/src/components/design/AppPreview/ComponentSelectionList.svelte +++ b/packages/builder/src/components/design/AppPreview/ComponentSelectionList.svelte @@ -57,6 +57,7 @@
onItemChosen(item, idx)} class:active={idx === selectedIndex}> {#if item.icon}{/if} @@ -74,6 +75,7 @@ {#each enrichedStructure[selectedIndex].children as item} {#if !item.showOnAsset || item.showOnAsset.includes($currentAssetName)} onItemChosen(item)} /> diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte index d1c7ec8e49..6b56910eed 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte @@ -69,7 +69,7 @@ } -
+
{label}
-
+
diff --git a/packages/builder/src/components/start/AppCard.svelte b/packages/builder/src/components/start/AppCard.svelte index cf8bcce688..dedbd91203 100644 --- a/packages/builder/src/components/start/AppCard.svelte +++ b/packages/builder/src/components/start/AppCard.svelte @@ -30,7 +30,7 @@
{name} -