From 8f79f91059c9e6ef4c8746ec9761fc16797e6994 Mon Sep 17 00:00:00 2001 From: elisa lee Date: Thu, 19 Oct 2023 13:12:14 -0500 Subject: [PATCH] Make add patient cypress e2e spec 2 rerunnable --- .../organization/OrganizationResolver.java | 18 +++ .../src/main/resources/graphql/admin.graphqls | 1 + .../OrganizationResolverTest.java | 27 ++++ cypress/.eslintrc.json | 5 +- cypress/cypress.config.js | 7 + cypress/e2e/02-add_patient.cy.js | 113 +++++++------ .../e2e/10-save_and_start_covid_test.cy.js | 11 +- cypress/support/commands.js | 27 ++-- cypress/support/e2e.js | 10 +- cypress/utils/request-utils.js | 6 +- cypress/utils/setup-utils.js | 58 +++++++ cypress/utils/testing-data-utils.js | 148 +++++++++++++++++- .../AddressConfirmationModal.tsx | 1 + .../app/commonComponents/Button/Button.tsx | 3 + .../src/app/commonComponents/Dropdown.tsx | 3 + frontend/src/app/commonComponents/Header.tsx | 1 + frontend/src/app/commonComponents/Input.tsx | 3 + .../src/app/commonComponents/MenuButton.tsx | 1 + .../src/app/commonComponents/RadioGroup.tsx | 2 +- frontend/src/app/commonComponents/Select.tsx | 3 + .../src/app/commonComponents/TextInput.tsx | 3 + frontend/src/app/patients/AddPatient.tsx | 3 +- .../patients/Components/AddPatientsHeader.tsx | 2 +- .../patients/Components/FacilitySelect.tsx | 2 + .../Components/ManagePhoneNumbers.tsx | 1 + .../Components/PersonAddressField.tsx | 4 + .../app/patients/Components/PersonForm.tsx | 6 + frontend/src/app/patients/ManagePatients.tsx | 7 +- frontend/src/app/patients/PatientsNav.tsx | 2 +- .../__snapshots__/EditPatient.test.tsx.snap | 74 +++++---- .../UploadPatients.test.tsx.snap | 5 +- .../__snapshots__/QueueItem.test.tsx.snap | 6 +- .../__snapshots__/TestQueue.test.tsx.snap | 12 +- .../app/testQueue/addToQueue/SearchInput.tsx | 3 + frontend/src/generated/graphql.tsx | 5 + 35 files changed, 441 insertions(+), 142 deletions(-) create mode 100644 cypress/utils/setup-utils.js diff --git a/backend/src/main/java/gov/cdc/usds/simplereport/api/organization/OrganizationResolver.java b/backend/src/main/java/gov/cdc/usds/simplereport/api/organization/OrganizationResolver.java index 5737e59c44..791ba527b0 100644 --- a/backend/src/main/java/gov/cdc/usds/simplereport/api/organization/OrganizationResolver.java +++ b/backend/src/main/java/gov/cdc/usds/simplereport/api/organization/OrganizationResolver.java @@ -67,6 +67,24 @@ public List organizations(@Argument Boolean identityVerified) { .collect(Collectors.toList()); } + /** + * Retrieves a list of all organizations, filtered by name + * + * @return a list of organizations + */ + @QueryMapping + @AuthorizationConfiguration.RequireGlobalAdminUser + public List organizationsByName(@Argument String name) { + List orgs = _organizationService.getOrganizationsByName(name); + if (orgs.isEmpty()) { + return null; + } else { + return orgs.stream() + .map(o -> new ApiOrganization(o, _organizationService.getFacilities(o))) + .collect(Collectors.toList()); + } + } + /** * Retrieves a list of all pending organizations AND organization queue items * diff --git a/backend/src/main/resources/graphql/admin.graphqls b/backend/src/main/resources/graphql/admin.graphqls index dfa4de3813..1a7ac2512b 100644 --- a/backend/src/main/resources/graphql/admin.graphqls +++ b/backend/src/main/resources/graphql/admin.graphqls @@ -3,6 +3,7 @@ # which is enforced in the API not in the schema validator. extend type Query { organizations(identityVerified: Boolean): [Organization!]! + organizationsByName(name: String!): [Organization] pendingOrganizations: [PendingOrganization!]! organization(id: ID!): Organization facilityStats(facilityId: ID!): FacilityStats diff --git a/backend/src/test/java/gov/cdc/usds/simplereport/api/organization/OrganizationResolverTest.java b/backend/src/test/java/gov/cdc/usds/simplereport/api/organization/OrganizationResolverTest.java index ed5e3d32f5..4142d1f26c 100644 --- a/backend/src/test/java/gov/cdc/usds/simplereport/api/organization/OrganizationResolverTest.java +++ b/backend/src/test/java/gov/cdc/usds/simplereport/api/organization/OrganizationResolverTest.java @@ -1,10 +1,12 @@ package gov.cdc.usds.simplereport.api.organization; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import gov.cdc.usds.simplereport.api.model.ApiOrganization; import gov.cdc.usds.simplereport.api.model.ApiPendingOrganization; import gov.cdc.usds.simplereport.api.model.accountrequest.OrganizationAccountRequest; import gov.cdc.usds.simplereport.api.model.errors.IllegalGraphqlArgumentException; @@ -75,4 +77,29 @@ void organization_null() { verify(organizationService).getOrganizationById(id); verify(organizationService, times(0)).getFacilities(org); } + + @Test + void organizationsByName_success() { + String orgName = "org name"; + Organization org = new Organization(orgName, "type", "123", true); + when(organizationService.getOrganizationsByName(orgName)).thenReturn(List.of(org)); + + organizationMutationResolver.organizationsByName(orgName); + + verify(organizationService).getOrganizationsByName(orgName); + verify(organizationService).getFacilities(org); + } + + @Test + void organizationsByName_null() { + String orgName = "org name"; + Organization org = new Organization(orgName, "type", "123", true); + when(organizationService.getOrganizationsByName(orgName)).thenReturn(List.of()); + + List actual = organizationMutationResolver.organizationsByName(orgName); + + assertThat(actual).isNull(); + verify(organizationService).getOrganizationsByName(orgName); + verify(organizationService, never()).getFacilities(org); + } } diff --git a/cypress/.eslintrc.json b/cypress/.eslintrc.json index 8f80bb430c..72ae2a0eef 100644 --- a/cypress/.eslintrc.json +++ b/cypress/.eslintrc.json @@ -1,4 +1,7 @@ { "plugins": ["cypress"], - "extends": ["plugin:cypress/recommended"] + "extends": ["plugin:cypress/recommended"], + "rules": { + "cypress/require-data-selectors": "warn" + } } diff --git a/cypress/cypress.config.js b/cypress/cypress.config.js index 639ea621fa..9500ec9e09 100644 --- a/cypress/cypress.config.js +++ b/cypress/cypress.config.js @@ -71,6 +71,13 @@ module.exports = { getMultiplexDeviceName() { return global.multiplexDeviceName; }, + setSpecName(name) { + global.specName = name; + return name; + }, + getSpecName() { + return global.specName || null; + }, }); on("before:browser:launch", (browser = {}, launchOptions = {}) => { launchOptions.args = launchOptions.args.filter( diff --git a/cypress/e2e/02-add_patient.cy.js b/cypress/e2e/02-add_patient.cy.js index 0f078adebd..21a6c7e939 100644 --- a/cypress/e2e/02-add_patient.cy.js +++ b/cypress/e2e/02-add_patient.cy.js @@ -1,67 +1,66 @@ -import { generatePatient, loginHooks } from "../support/e2e"; - -const patient = generatePatient(); - +import { generatePatient, loginHooks, testNumber } from "../support/e2e"; +import { cleanUpPreviousOrg, setupOrgAndFacility } from "../utils/setup-utils"; +let patient= generatePatient(); describe("Adding a single patient", () => { loginHooks(); before("store patient info", () => { cy.task("setPatientName", patient.fullName); cy.task("setPatientDOB", patient.dobForPatientLink); cy.task("setPatientPhone", patient.phone); + cy.task("getSpecName") + .then((specName) => { + if (specName) { + cleanUpPreviousOrg(specName); + } + specName = `${testNumber()}-cypress-spec-2` + cy.task("setSpecName", specName) + setupOrgAndFacility(specName); + }) }); - it("navigates to the add patient form", () => { - cy.visit("/"); - cy.get(".usa-nav-container"); - cy.get("#desktop-patient-nav-link").click(); - cy.get(".prime-container"); - cy.get("#add-patient").click(); - cy.get("#individual_add-patient").click(); - cy.get(".prime-edit-patient").contains("Add new patient"); + it("navigates to and fills out add patient form", () => { + cy.visit('/'); + cy.get('[data-cy="desktop-patient-nav-link"]').click(); + cy.get('[data-cy="add-patients-button"]').click(); + cy.get('[data-cy="individual"]').click(); + cy.get('[data-cy="add-patient-header"]').contains("Add new patient"); cy.injectSRAxe(); - cy.checkAccessibility(); // Patient form - }); - it("fills out some of the form fields", () => { - cy.get('input[name="firstName"]').type(patient.firstName); - cy.get('input[name="birthDate"]').type(patient.dobForInput); - cy.get('input[name="number"]').type(patient.phone); - cy.get('input[value="MOBILE"]+label').click(); - cy.get('input[name="gender"][value="female"]+label').click(); - cy.get('input[name="genderIdentity"][value="female"]+label').click(); - cy.get('input[name="street"]').type(patient.address); - cy.get('select[name="state"]').select(patient.state); - cy.get('input[name="zipCode"]').type(patient.zip); - cy.get('select[name="role"]').select("STUDENT"); - cy.get(".prime-edit-patient").contains("Student ID"); - cy.get('input[name="lookupId"]').type(patient.studentId); - cy.get('input[name="race"][value="other"]+label').click(); - cy.get('input[name="ethnicity"][value="refused"]+label').click(); - cy.get('input[name="residentCongregateSetting"][value="NO"]+label').click(); - cy.get('input[name="employedInHealthcare"][value="NO"]+label').click(); - }); - it("shows what fields are missing on submit", () => { - cy.get(".prime-save-patient-changes").first().click(); - - cy.get(".prime-edit-patient").contains("Last name is missing"); - cy.get(".prime-edit-patient").contains("Testing facility is missing"); - cy.get(".prime-edit-patient").contains("City is missing"); - }); - it("fills out the remaining fields, submits and checks for the patient", () => { - cy.get('input[name="lastName"]').type(patient.lastName); - cy.get('input[name="city"]').type(patient.city); - cy.get('select[name="facilityId"]').select("All facilities"); - cy.get(".prime-save-patient-changes").first().click(); - cy.get( - '.modal__container input[name="addressSelect-person"][value="userAddress"]+label', - ).click(); - - cy.checkAccessibility(); - - cy.get(".modal__container #save-confirmed-address").click(); - cy.get(".usa-card__header").contains("Patients"); - cy.get(".usa-card__header").contains("Showing"); - cy.get("#search-field-small").type(patient.lastName); - cy.get(".prime-container").contains(patient.fullName); - - cy.checkAccessibility(); + cy.checkAccessibility(); // empty patient form + // fill out form + cy.get('[data-cy="personForm-firstName-input"]').type(patient.firstName); + cy.get('[data-cy="personForm-dob-input"]').type(patient.dobForInput); + cy.get('[data-cy="phone-input-0"]').type(patient.phone); + cy.get('[data-cy="radio-group-option-phoneType-0-MOBILE"]').click(); + cy.get('[data-cy="radio-group-option-genderIdentity-female"]').click(); + cy.get('[data-cy="radio-group-option-gender-female"]').click(); + cy.get('[data-cy="street-input"]').type(patient.address); + cy.get('[data-cy="state-input"]').select(patient.state); + cy.get('[data-cy="zip-input"]').type(patient.zip); + cy.get('[data-cy="personForm-role-input"]').select("STUDENT"); + cy.get('[data-cy="add-patient-page"]').contains("Student ID"); + cy.get('[data-cy="personForm-lookupId-input"]').type(patient.studentId); + cy.get('[data-cy="radio-group-option-race-other"]').click(); + cy.get('[data-cy="radio-group-option-ethnicity-refused"]').click(); + cy.get('[data-cy="radio-group-option-residentCongregateSetting-NO"]').click(); + cy.get('[data-cy="radio-group-option-employedInHealthcare-NO"]').click(); + cy.get('[data-cy="add-patient-save-button"]').eq(0).click(); + // check for errors + cy.get('[data-cy="add-patient-page"]').contains("Last name is missing"); + cy.get('[data-cy="add-patient-page"]').contains("Testing facility is missing"); + cy.get('[data-cy="add-patient-page"]').contains("City is missing"); + cy.checkAccessibility(); // patient form with errors + // fill out remaining form + cy.get('[data-cy="personForm-lastName-input"]').type(patient.lastName); + cy.get('[data-cy="city-input"]').type(patient.city); + cy.get('[data-cy="personForm-facility-input"]').select("All facilities"); + cy.get('[data-cy="add-patient-save-button"]').eq(0).click(); + cy.get('[data-cy="radio-group-option-addressSelect-person-userAddress"]').click(); + cy.checkAccessibility(); // address validation modal + cy.get('[data-cy="save-address-confirmation-button"]').click(); + // check for newly created patient on Manage Patients page + cy.get('[data-cy="manage-patients-header"]').contains("Patients"); + cy.get('[data-cy="manage-patients-header"]').contains("Showing"); + cy.get('[data-cy="manage-patients-search-input"]').type(patient.lastName); + cy.get('[data-cy="manage-patients-page"]').contains(patient.fullName); + cy.checkAccessibility(); // manage patients page }); }); diff --git a/cypress/e2e/10-save_and_start_covid_test.cy.js b/cypress/e2e/10-save_and_start_covid_test.cy.js index a915b110aa..9e7416aea5 100644 --- a/cypress/e2e/10-save_and_start_covid_test.cy.js +++ b/cypress/e2e/10-save_and_start_covid_test.cy.js @@ -28,13 +28,12 @@ describe("Save and start covid test", () => { context("edit patient and save and start test", () => { it("searches for the patient", () => { cy.visit("/"); - cy.get(".usa-nav-container"); - cy.get("#desktop-patient-nav-link").click(); - cy.get(".sr-patient-list").should("exist"); - cy.get(".sr-patient-list").contains("Loading...").should("not.exist"); - cy.get("#search-field-small").type(lastName); + cy.get('[data-cy="desktop-patient-nav-link"]').click(); + cy.get('[data-cy="manage-patients-header"]').contains("Patients"); + cy.get('[data-cy="manage-patients-header"]').contains("Showing"); + cy.get('[data-cy="manage-patients-search-input"]').type(lastName); cy.wait("@GetPatientsByFacility"); - cy.get(".sr-patient-list").contains(patientName).should("exist"); + cy.get('[data-cy="manage-patients-page"]').contains(patientName); }); it("edits the found patient and clicks save and start test ", () => { diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 8c5977750b..040adb77c7 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -26,7 +26,7 @@ import "cypress-localstorage-commands"; import { authenticator } from "otplib"; -import { graphqlURL } from "../utils/request-utils"; +import {addOrgToQueueURL, graphqlURL} from "../utils/request-utils"; // read environment variables @@ -95,20 +95,6 @@ Cypress.Commands.add("login", () => { }); }); -Cypress.Commands.add("selectFacility", () => { - cy.get("body").then(($body) => { - if ( - $body - .text() - .includes( - "Please select the testing facility where you are working today.", - ) - ) { - cy.get(".usa-card__body").last().click(); - } - }); -}); - Cypress.Commands.add("addDevice", (device) => { cy.get('input[name="name"]').type(device.name); cy.get('input[name="model"]').type(device.model); @@ -178,6 +164,17 @@ Cypress.Commands.add("makePOSTRequest", (requestBody) => { ); }); +Cypress.Commands.add("makeAccountRequest", (requestBody) => { + cy.request({ + method: "POST", + url: addOrgToQueueURL, + headers: { + "Content-Type": "application/json", + }, + body: requestBody, + }); +}); + Cypress.Commands.add("injectSRAxe", () => { return isLocalRun ? cy.injectAxe({ diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js index ad382fb24e..26948ed2db 100644 --- a/cypress/support/e2e.js +++ b/cypress/support/e2e.js @@ -19,7 +19,9 @@ import "cypress-axe"; const { faker } = require("@faker-js/faker"); const dayjs = require("dayjs"); - +Cypress.Keyboard.defaults({ + keystrokeDelay: 0, +}) export const testNumber = () => { return Math.round(Date.now() / 1000); }; @@ -31,8 +33,8 @@ const getDobFormat = () => { // Generate a random patient export const generatePatient = () => { const patient = {}; - patient.firstName = faker.name.firstName(); - patient.lastName = faker.name.lastName(); + patient.firstName = faker.person.firstName(); + patient.lastName = faker.person.lastName(); patient.fullName = `${patient.lastName}, ${patient.firstName}`; patient.dob = dayjs( faker.date.between({ from: "1920-01-01", to: "2002-12-31" }), @@ -44,7 +46,7 @@ export const generatePatient = () => { patient.city = "Definitely not Washington"; patient.state = "DC"; patient.zip = "20503"; - patient.studentId = faker.datatype.uuid(); + patient.studentId = faker.string.uuid(); return patient; }; diff --git a/cypress/utils/request-utils.js b/cypress/utils/request-utils.js index 7c72663e1f..8696ec9c10 100644 --- a/cypress/utils/request-utils.js +++ b/cypress/utils/request-utils.js @@ -1,3 +1,3 @@ -export const graphqlURL = `${ - Cypress.env("BACKEND_URL") || "http://localhost:8080" -}/graphql`; +const backendURL = Cypress.env("BACKEND_URL") || "http://localhost:8080"; +export const graphqlURL = `${backendURL}/graphql`; +export const addOrgToQueueURL = `${backendURL}/account-request/organization-add-to-queue`; diff --git a/cypress/utils/setup-utils.js b/cypress/utils/setup-utils.js new file mode 100644 index 0000000000..05f61905f6 --- /dev/null +++ b/cypress/utils/setup-utils.js @@ -0,0 +1,58 @@ +import { + accessOrganization, + addMockFacility, + createOrganization, + getOrganizationsByName, getPatientsByFacilityId, + markOrganizationAsDeleted, markPatientAsDeleted, + verifyPendingOrganization +} from "./testing-data-utils"; +import { generateUser } from "../support/e2e"; + +const createOrgName = (specName) => { + return `${specName}-org`; +} + +const createFacilityName = (specName) => { + return `${specName}-facility`; +} + +const createAndVerifyOrganization = (orgName) => { + const adminUser = generateUser(); + return createOrganization(orgName, adminUser.email) + .then((res) => verifyPendingOrganization(res.body.orgExternalId)) +} +const archivePatientsForFacility = (facilityId) => { + return getPatientsByFacilityId(facilityId) + .then((res) => { + let patients = res.body.data.patients; + if (patients.length > 0) { + patients.map( + (patient) => markPatientAsDeleted(patient.internalId, true)) + } + }) +} + +export const cleanUpPreviousOrg = (specName) => { + let orgName = createOrgName(specName); + getOrganizationsByName(orgName) + .then((res) => { + let orgs = res.body.data.organizationsByName; + let org = orgs.length > 1 ? orgs[0] : null; + if (org) { + let facilities = org.facilities + if (facilities.length > 0) { + facilities.map((facility) => archivePatientsForFacility(facility.id)) + } + markOrganizationAsDeleted(org.id, true); + } + }) +} + +export const setupOrgAndFacility = (specName) => { + let orgName = createOrgName(specName); + let facilityName = createFacilityName(specName); + createAndVerifyOrganization(orgName) + .then(() => getOrganizationsByName(orgName)) + .then((res) => accessOrganization(res.body.data.organizationsByName[0].externalId)) + .then(() => addMockFacility(facilityName)) +}; diff --git a/cypress/utils/testing-data-utils.js b/cypress/utils/testing-data-utils.js index 0d4a7039cf..c88f2aa83e 100644 --- a/cypress/utils/testing-data-utils.js +++ b/cypress/utils/testing-data-utils.js @@ -1,24 +1,105 @@ +// QUERIES export const whoAmI = () => { return cy.makePOSTRequest({ operationName: "WhoAmI", variables: {}, - query: `query WhoAmI {\n whoami {\n organization {\n id\n facilities {\n id\n }\n }\n} \n}`, + query: `query WhoAmI { + whoami { + organization { + id + facilities { + id + } + } + } + }`, }); }; - export const getOrganizationById = (organizationId) => { return cy.makePOSTRequest({ operationName: "Organization", variables: { id: organizationId }, query: `query Organization($id: ID!) { - organization(id: $id){ + organization(id: $id) { + id + name + } + }`, + }); +}; +export const getOrganizationsByName = (organizationName) => { + return cy.makePOSTRequest({ + operationName: "OrganizationsByName", + variables: { name: organizationName }, + query: `query OrganizationsByName($name: String!) { + organizationsByName(name: $name) { + id + name + externalId + facilities { + id + name + isDeleted + } + } + }` + }); +}; +export const getPatientsByFacilityId = (facilityId) => { + return cy.makePOSTRequest({ + operationName: "Patients", + variables: { facilityId: facilityId }, + query: `query Patients($facilityId: ID!) { + patients(facilityId: $facilityId){ + internalId + } + }` + }); +}; + +// MUTATIONS +export const verifyPendingOrganization = (orgExternalId) => { + return cy.makePOSTRequest({ + operationName: "VerifyPendingOrganization", + variables: { + externalId: orgExternalId, + }, + query: `mutation VerifyPendingOrganization( + $externalId: String! + ) { + setOrganizationIdentityVerified( + externalId: $externalId, + verified: true + ) + }`, + }); +}; +export const accessOrganization = (orgExternalId) => { + cy.log(orgExternalId) + return cy.makePOSTRequest({ + operationName: "SetCurrentUserTenantDataAccess", + variables: { + organizationExternalId: orgExternalId, + }, + query: `mutation SetCurrentUserTenantDataAccess( + $organizationExternalId: String! + ) { + setCurrentUserTenantDataAccess( + organizationExternalId: $organizationExternalId, + justification: "cypress testing" + ) { + id + organization { + externalId + facilities { id name } - }`, + } + } + }`, }); }; - export const addMockFacility = (facilityName) => { return cy.makePOSTRequest({ operationName: "AddFacility", @@ -27,6 +108,8 @@ export const addMockFacility = (facilityName) => { street: "123 maint street", state: "NJ", zipCode: "07601", + phone: "8002324636", + cliaNumber: "12D4567890", orderingProviderFirstName: "Jane", orderingProviderLastName: "Austen", orderingProviderNPI: "1234567890", @@ -43,6 +126,8 @@ export const addMockFacility = (facilityName) => { $street: String! $state: String! $zipCode: String! + $phone: String + $cliaNumber: String $orderingProviderFirstName: String $orderingProviderMiddleName: String $orderingProviderLastName: String @@ -64,6 +149,8 @@ export const addMockFacility = (facilityName) => { state: $state zipCode: $zipCode } + phone: $phone + cliaNumber: $cliaNumber orderingProvider: { firstName: $orderingProviderFirstName middleName: $orderingProviderMiddleName @@ -85,3 +172,54 @@ export const addMockFacility = (facilityName) => { }`, }); }; +export const markOrganizationAsDeleted = (orgId, deleted) => { + return cy.makePOSTRequest({ + operationName: "MarkOrganizationAsDeleted", + variables: { + organizationId: orgId, + deleted: deleted, + }, + query: `mutation MarkOrganizationAsDeleted( + $organizationId: ID! + $deleted: Boolean! + ) { + markOrganizationAsDeleted( + organizationId: $organizationId, + deleted: $deleted + ) + }`, + }); +}; +export const markPatientAsDeleted = (patientId, deleted) => { + return cy.makePOSTRequest({ + operationName: "MarkPatientAsDeleted", + variables: { + patientId: patientId, + deleted: deleted, + }, + query: `mutation MarkPatientAsDeleted( + $patientId: ID! + $deleted: Boolean! + ) { + setPatientIsDeleted( + id: $patientId, + deleted: $deleted + ) { + id + } + }`, + }); +}; + +export const createOrganization = (name, userEmail) => { + return cy.makeAccountRequest({ + "name": name, + "type": "camp", + "state": "CA", + "firstName": "Greg", + "middleName": "", + "lastName": "McTester", + "email": userEmail, + "workPhoneNumber": "2123892839" + }); +} diff --git a/frontend/src/app/commonComponents/AddressConfirmationModal.tsx b/frontend/src/app/commonComponents/AddressConfirmationModal.tsx index b760041dd0..58c14d1df4 100644 --- a/frontend/src/app/commonComponents/AddressConfirmationModal.tsx +++ b/frontend/src/app/commonComponents/AddressConfirmationModal.tsx @@ -222,6 +222,7 @@ export const AddressConfirmationModal = ({ disabled={addressSuggestionConfig.some( ({ key }) => !selectedAddress[key] )} + dataCy="save-address-confirmation-button" > {t("address.save")} diff --git a/frontend/src/app/commonComponents/Button/Button.tsx b/frontend/src/app/commonComponents/Button/Button.tsx index 654191f881..cfa4612c33 100644 --- a/frontend/src/app/commonComponents/Button/Button.tsx +++ b/frontend/src/app/commonComponents/Button/Button.tsx @@ -25,6 +25,7 @@ interface Props { ariaHidden?: boolean; ariaLabel?: string; ref?: React.RefObject | null; + dataCy?: string; } const Button = ({ @@ -40,6 +41,7 @@ const Button = ({ id, ariaHidden, ariaLabel, + dataCy, }: Props) => (