diff --git a/cypress.config.ts b/cypress.config.ts new file mode 100644 index 0000000..a031ef1 --- /dev/null +++ b/cypress.config.ts @@ -0,0 +1,12 @@ +import {defineConfig} from "cypress"; + +export default defineConfig({ + e2e: { + viewportHeight: 1000, + viewportWidth: 1200, + setupNodeEvents(on, config) + { + // implement node event listeners here + }, + }, +}); diff --git a/cypress/e2e/spec.cy.ts b/cypress/e2e/spec.cy.ts new file mode 100644 index 0000000..ac0fd02 --- /dev/null +++ b/cypress/e2e/spec.cy.ts @@ -0,0 +1,72 @@ +// noinspection ES6UnusedImports +import * as cypress from "cypress"; + +describe("empty spec", () => +{ + it("passes", () => + { + cy.intercept("GET", "/metaData", {fixture: "metaData/index.json"}).as("metaData"); + cy.intercept("GET", "/data/person?*", {fixture: "data/person/index.json"}).as("personQuery"); + cy.intercept("GET", "/data/person/count?*", {fixture: "data/person/count.json"}).as("personCount") + cy.intercept("GET", "/metaData/process/person.bulkEdit", {fixture: "metaData/process/person.bulkEdit.json"}).as("personBulkEditMetaData") + cy.intercept("POST", "/processes/person.bulkEdit/init?recordsParam=recordIds&recordIds=1,2,3,4,5", {fixture: "processes/person.bulkEdit/init.json"}).as("personBulkEditInit") + cy.intercept("POST", "/processes/person.bulkEdit/74a03a7d-2f53-4784-9911-3a21f7646c43/step/edit", {fixture: "processes/person.bulkEdit/step/edit.json"}).as("personBulkEditStepEdit") + cy.intercept("GET", "/processes/person.bulkEdit/74a03a7d-2f53-4784-9911-3a21f7646c43/records?skip=0&limit=10", {fixture: "processes/person.bulkEdit/records.json"}).as("personBulkEditRecords") + + ///////////////// + // home screen // + ///////////////// + cy.visit("http://localhost:3000/"); + cy.wait(["@metaData"]) + + cy.contains(".MuiListItem-root", "Tables").click(); + cy.contains(".MuiListItem-root", "Person").click(); + + ///////////////////////// + // person query screen // + ///////////////////////// + cy.location().should((loc) => + { + expect(loc.pathname).to.eq("/person") + }); + cy.wait(["@personQuery", "@personCount"]) + + cy.get(".MuiDataGrid-columnHeaders input[type='checkbox']").click(); + cy.contains("button", "Bulk Actions").click(); + cy.contains("li", "Bulk Edit").click(); + + //////////////////////////// + // bulk edit process init // + //////////////////////////// + cy.location().should((loc) => + { + expect(loc.pathname).to.eq("/processes/person.bulkEdit"); + expect(loc.search).to.eq("?recordsParam=recordIds&recordIds=1,2,3,4,5"); + }); + cy.wait(["@personBulkEditMetaData"]) + cy.wait(["@personBulkEditInit"]) + + cy.contains("p[variation='h5']", "Edit Values"); + cy.get("#bulkEditSwitch-firstName").click(); + cy.get("input[name='firstName']").click() + .type("Kahhhhn"); + cy.contains("button", "next").click(); + + /////////////////////////// + // bulk edit review step // + /////////////////////////// + cy.contains("p[variation='h5']", "Review"); + cy.contains(".MuiDataGrid-cellContent", "Kahhhhn"); + + cy.contains("button", "submit").click(); + cy.wait(["@personBulkEditStepEdit"]) + cy.wait(["@personBulkEditRecords"]) + + //////////////////////////// + // bulk edit result step // + //////////////////////////// + cy.contains("p[variation='h5']", "Results"); + cy.wait(["@personBulkEditRecords"]) + }); + +}); diff --git a/cypress/fixtures/data/person/count.json b/cypress/fixtures/data/person/count.json new file mode 100644 index 0000000..8d1d5b4 --- /dev/null +++ b/cypress/fixtures/data/person/count.json @@ -0,0 +1,3 @@ +{ + "count": 5 +} diff --git a/cypress/fixtures/data/person/index.json b/cypress/fixtures/data/person/index.json new file mode 100644 index 0000000..2b3c655 --- /dev/null +++ b/cypress/fixtures/data/person/index.json @@ -0,0 +1,64 @@ +{ + "records": [ + { + "tableName": "person", + "values": { + "id": 1, + "createDate": "2022-07-23T00:17:00", + "modifyDate": "2022-07-22T19:17:06", + "firstName": "Jonny", + "lastName": "Doe", + "birthDate": "1980-05-31", + "email": "jdoe@kingsrook.com" + } + }, + { + "tableName": "person", + "values": { + "id": 2, + "createDate": "2022-07-23T00:17:00", + "modifyDate": "2022-07-23T00:17:00", + "firstName": "James", + "lastName": "Maes", + "birthDate": "1980-05-15", + "email": "jmaes@mmltholdings.com" + } + }, + { + "tableName": "person", + "values": { + "id": 3, + "createDate": "2022-07-23T00:17:00", + "modifyDate": "2022-07-23T00:17:00", + "firstName": "Tim", + "lastName": "Chamberlain", + "birthDate": "1976-05-28", + "email": "tchamberlain@mmltholdings.com" + } + }, + { + "tableName": "person", + "values": { + "id": 4, + "createDate": "2022-07-23T00:17:00", + "modifyDate": "2022-07-23T00:17:00", + "firstName": "Tyler", + "lastName": "Samples", + "birthDate": "1986-05-28", + "email": "tsamples@mmltholdings.com" + } + }, + { + "tableName": "person", + "values": { + "id": 5, + "createDate": "2022-07-23T00:17:00", + "modifyDate": "2022-07-23T00:17:00", + "firstName": "Garret", + "lastName": "Richardson", + "birthDate": "1981-01-01", + "email": "grichardson@mmltholdings.com" + } + } + ] +} diff --git a/cypress/fixtures/metaData/index.json b/cypress/fixtures/metaData/index.json new file mode 100644 index 0000000..6858e0b --- /dev/null +++ b/cypress/fixtures/metaData/index.json @@ -0,0 +1,102 @@ +{ + "tables": { + "carrier": { + "name": "carrier", + "label": "Carrier", + "isHidden": false + }, + "city": { + "name": "city", + "label": "Cities", + "isHidden": true + }, + "person": { + "name": "person", + "label": "Person", + "isHidden": false + } + }, + "processes": { + "person.bulkInsert": { + "name": "person.bulkInsert", + "label": "Person Bulk Insert", + "tableName": "person", + "isHidden": true + }, + "carrier.bulkInsert": { + "name": "carrier.bulkInsert", + "label": "Carrier Bulk Insert", + "tableName": "carrier", + "isHidden": true + }, + "simpleSleep": { + "name": "simpleSleep", + "label": "Simple Sleep", + "isHidden": true + }, + "carrier.bulkDelete": { + "name": "carrier.bulkDelete", + "label": "Carrier Bulk Delete", + "tableName": "carrier", + "isHidden": true + }, + "greet": { + "name": "greet", + "label": "Greet People", + "tableName": "person", + "isHidden": true + }, + "city.bulkDelete": { + "name": "city.bulkDelete", + "label": "Cities Bulk Delete", + "tableName": "city", + "isHidden": true + }, + "person.bulkDelete": { + "name": "person.bulkDelete", + "label": "Person Bulk Delete", + "tableName": "person", + "isHidden": true + }, + "carrier.bulkEdit": { + "name": "carrier.bulkEdit", + "label": "Carrier Bulk Edit", + "tableName": "carrier", + "isHidden": true + }, + "person.bulkEdit": { + "name": "person.bulkEdit", + "label": "Person Bulk Edit", + "tableName": "person", + "isHidden": true + }, + "greetInteractive": { + "name": "greetInteractive", + "label": "Greet Interactive", + "tableName": "person", + "isHidden": false + }, + "city.bulkEdit": { + "name": "city.bulkEdit", + "label": "Cities Bulk Edit", + "tableName": "city", + "isHidden": true + }, + "simpleThrow": { + "name": "simpleThrow", + "label": "Simple Throw", + "isHidden": false + }, + "sleepInteractive": { + "name": "sleepInteractive", + "label": "Sleep Interactive", + "isHidden": false + }, + "city.bulkInsert": { + "name": "city.bulkInsert", + "label": "Cities Bulk Insert", + "tableName": "city", + "isHidden": true + } + } +} diff --git a/cypress/fixtures/metaData/process/person.bulkEdit.json b/cypress/fixtures/metaData/process/person.bulkEdit.json new file mode 100644 index 0000000..62b2260 --- /dev/null +++ b/cypress/fixtures/metaData/process/person.bulkEdit.json @@ -0,0 +1,183 @@ +{ + "process": { + "name": "person.bulkEdit", + "label": "Person Bulk Edit", + "tableName": "person", + "isHidden": true, + "frontendSteps": [ + { + "name": "edit", + "label": "Edit Values", + "stepType": "frontend", + "components": [ + { + "type": "HELP_TEXT", + "values": { + "text": "Flip the switches next to the fields that you want to edit.\nThe values you supply here will be updated in all of the records you are bulk editing.\nYou can clear out the value in a field by flipping the switch on for that field and leaving the input field blank.\nFields whose switches are off will not be updated." + } + }, + { + "type": "BULK_EDIT_FORM" + } + ], + "formFields": [ + { + "name": "firstName", + "label": "First Name", + "backendName": "first_name", + "type": "STRING", + "isRequired": true, + "isEditable": true + }, + { + "name": "lastName", + "label": "Last Name", + "backendName": "last_name", + "type": "STRING", + "isRequired": true, + "isEditable": true + }, + { + "name": "birthDate", + "label": "Birth Date", + "backendName": "birth_date", + "type": "DATE", + "isRequired": false, + "isEditable": true + }, + { + "name": "email", + "label": "Email", + "type": "STRING", + "isRequired": false, + "isEditable": true + } + ] + }, + { + "name": "review", + "label": "Review", + "stepType": "frontend", + "components": [ + { + "type": "HELP_TEXT", + "values": { + "text": "The records below will be updated if you click Submit." + } + } + ], + "viewFields": [ + { + "name": "valuesBeingUpdated", + "label": "Values Being Updated", + "type": "STRING", + "isRequired": false, + "isEditable": true + } + ], + "recordListFields": [ + { + "name": "firstName", + "label": "First Name", + "backendName": "first_name", + "type": "STRING", + "isRequired": true, + "isEditable": true + }, + { + "name": "lastName", + "label": "Last Name", + "backendName": "last_name", + "type": "STRING", + "isRequired": true, + "isEditable": true + }, + { + "name": "birthDate", + "label": "Birth Date", + "backendName": "birth_date", + "type": "DATE", + "isRequired": false, + "isEditable": true + }, + { + "name": "email", + "label": "Email", + "type": "STRING", + "isRequired": false, + "isEditable": true + } + ] + }, + { + "name": "results", + "label": "Results", + "stepType": "frontend", + "components": [ + { + "type": "HELP_TEXT", + "values": { + "text": "The records below have been updated." + } + } + ], + "recordListFields": [ + { + "name": "id", + "label": "Id", + "type": "INTEGER", + "isRequired": false, + "isEditable": false + }, + { + "name": "createDate", + "label": "Create Date", + "backendName": "create_date", + "type": "DATE_TIME", + "isRequired": false, + "isEditable": false + }, + { + "name": "modifyDate", + "label": "Modify Date", + "backendName": "modify_date", + "type": "DATE_TIME", + "isRequired": false, + "isEditable": false + }, + { + "name": "firstName", + "label": "First Name", + "backendName": "first_name", + "type": "STRING", + "isRequired": true, + "isEditable": true + }, + { + "name": "lastName", + "label": "Last Name", + "backendName": "last_name", + "type": "STRING", + "isRequired": true, + "isEditable": true + }, + { + "name": "birthDate", + "label": "Birth Date", + "backendName": "birth_date", + "type": "DATE", + "isRequired": false, + "isEditable": true + }, + { + "name": "email", + "label": "Email", + "type": "STRING", + "isRequired": false, + "isEditable": true + } + ] + } + ] + } +} diff --git a/cypress/fixtures/processes/person.bulkEdit/init.json b/cypress/fixtures/processes/person.bulkEdit/init.json new file mode 100644 index 0000000..c806ccd --- /dev/null +++ b/cypress/fixtures/processes/person.bulkEdit/init.json @@ -0,0 +1,9 @@ +{ + "values": { + "recordsParam": "recordIds", + "recordIds": "1,2,3,4,5", + "queryFilterJSON": "{\"criteria\":[{\"fieldName\":\"id\",\"operator\":\"IN\",\"values\":[\"1\",\"2\",\"3\",\"4\",\"5\"]}]}" + }, + "processUUID": "74a03a7d-2f53-4784-9911-3a21f7646c43", + "nextStep": "edit" +} diff --git a/cypress/fixtures/processes/person.bulkEdit/step/edit.json b/cypress/fixtures/processes/person.bulkEdit/step/edit.json new file mode 100644 index 0000000..b3e0fde --- /dev/null +++ b/cypress/fixtures/processes/person.bulkEdit/step/edit.json @@ -0,0 +1,12 @@ +{ + "values": { + "firstName": "Kahhhhn", + "valuesBeingUpdated": "First Name will be set to: Kahhhhn", + "bulkEditEnabledFields": "firstName", + "recordsParam": "recordIds", + "recordIds": "1,2,3,4,5", + "queryFilterJSON": "{\"criteria\":[{\"fieldName\":\"id\",\"operator\":\"IN\",\"values\":[\"1\",\"2\",\"3\",\"4\",\"5\"]}]}" + }, + "processUUID": "74a03a7d-2f53-4784-9911-3a21f7646c43", + "nextStep": "review" +} diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts new file mode 100644 index 0000000..698b01a --- /dev/null +++ b/cypress/support/commands.ts @@ -0,0 +1,37 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } \ No newline at end of file diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts new file mode 100644 index 0000000..f80f74f --- /dev/null +++ b/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/cypress/videos/spec.cy.ts.mp4 b/cypress/videos/spec.cy.ts.mp4 new file mode 100644 index 0000000..0acb14d Binary files /dev/null and b/cypress/videos/spec.cy.ts.mp4 differ diff --git a/package.json b/package.json index bf08ed2..e7b3d25 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,8 @@ "install-legacy-peer-deps": "npm install --legacy-peer-deps", "prepublishOnly": "tsc -p ./ --outDir lib/", "start": "react-scripts start", - "test": "react-scripts test" + "test": "react-scripts test", + "cypress:open": "cypress open" }, "eslintConfig": { "extends": [ @@ -92,6 +93,7 @@ "@types/uuid": "8.3.4", "@typescript-eslint/eslint-plugin": "5.10.2", "@typescript-eslint/parser": "5.10.2", + "cypress": "^10.3.1", "eslint": "8.8.0", "eslint-config-airbnb": "19.0.4", "eslint-import-resolver-typescript": "2.5.0",