Skip to content

Commit

Permalink
pc/modals: Validate phone and email even when they're optional
Browse files Browse the repository at this point in the history
  • Loading branch information
ssangervasi committed Jan 24, 2023
1 parent 02a6af3 commit a1e71c7
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The types of changes are:

* Home screen header scaling and responsiveness issues [#2200](https://github.com/ethyca/fides/pull/2277)
* Added a feature flag for the recent dataset classification UX changes [#2335](https://github.com/ethyca/fides/pull/2335)
* Privacy Center identity inputs validate even when they are optional. [#2308](https://github.com/ethyca/fides/pull/2308)

### Security

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { addCommonHeaders } from "~/common/CommonHeaders";
import { config, defaultIdentityInput, hostUrl } from "~/constants";
import dynamic from "next/dynamic";
import * as Yup from "yup";
import { emailValidation, phoneValidation } from "../validation";
import { ModalViews, VerificationType } from "../types";

const PhoneInput = dynamic(() => import("react-phone-number-input"), {
Expand Down Expand Up @@ -114,25 +115,8 @@ const useConsentRequestForm = ({
}
},
validationSchema: Yup.object().shape({
email: (() => {
let validation = Yup.string();
if (identityInputs.email === "required") {
validation = validation
.email("Email is invalid")
.required("Email is required");
}
return validation;
})(),
phone: (() => {
let validation = Yup.string();
if (identityInputs?.phone === "required") {
validation = validation
.required("Phone is required")
// E.164 international standard format
.matches(/^\+[1-9]\d{1,14}$/, "Phone is invalid");
}
return validation;
})(),
email: emailValidation(identityInputs?.email),
phone: phoneValidation(identityInputs?.phone),
}),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ import * as Yup from "yup";
import { ModalViews } from "../types";

import "react-phone-number-input/style.css";
import {
emailValidation,
nameValidation,
phoneValidation,
} from "../validation";

const PhoneInput = dynamic(() => import("react-phone-number-input"), {
ssr: false,
Expand Down Expand Up @@ -141,32 +146,9 @@ const usePrivacyRequestForm = ({
}
},
validationSchema: Yup.object().shape({
name: (() => {
let validation = Yup.string();
if (identityInputs.name === "required") {
validation = validation.required("Name is required");
}
return validation;
})(),
email: (() => {
let validation = Yup.string();
if (identityInputs.email === "required") {
validation = validation
.email("Email is invalid")
.required("Email is required");
}
return validation;
})(),
phone: (() => {
let validation = Yup.string();
if (identityInputs.phone === "required") {
validation = validation
.required("Phone is required")
// E.164 international standard format
.matches(/^\+[1-9]\d{1,14}$/, "Phone is invalid");
}
return validation;
})(),
name: nameValidation(identityInputs?.name),
email: emailValidation(identityInputs?.email),
phone: phoneValidation(identityInputs?.phone),
}),
});

Expand Down
35 changes: 35 additions & 0 deletions clients/privacy-center/components/modals/validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as Yup from "yup";

export const nameValidation = (option?: string) => {
let validation = Yup.string();
if (option === "required") {
validation = validation.required("Name is required");
} else {
validation = validation.optional();
}
return validation;
};

export const emailValidation = (option?: string) => {
let validation = Yup.string().email("Email is invalid");
if (option === "required") {
validation = validation.required("Email is required");
} else {
validation = validation.optional();
}
return validation;
};

export const phoneValidation = (option?: string) => {
// E.164 international standard format
let validation = Yup.string().matches(
/^\+[1-9]\d{1,14}$/,
"Phone is invalid"
);
if (option === "required") {
validation = validation.required("Phone is required");
} else {
validation = validation.optional();
}
return validation;
};
24 changes: 24 additions & 0 deletions clients/privacy-center/cypress/e2e/privacy-request.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,29 @@ describe("Privacy request", () => {

cy.getByTestId("request-submitted");
});

it("requires valid inputs", () => {
cy.visit("/");
cy.getByTestId("card").contains("Access your data").click();

cy.getByTestId("privacy-request-form").within(() => {
// This block uses `.root()` to keep queries within the form. This is necessary because of
// `.blur()` which triggers input validation.
cy.root().get("input#email").type("invalid email");
cy.root().get("input#phone").type("123 456 7890 1234567").blur();

cy.root().should("contain", "Email is invalid");
cy.root().should("contain", "Phone is invalid");
cy.root().get("button").contains("Continue").should("be.disabled");

cy.root().get("input#email").type("[email protected]");
cy.root().get("input#phone").clear().type("123 456 7890").blur();
cy.root().get("button").contains("Continue").should("be.enabled");

// The phone input is optional (in the default config) so it can be left blank.
cy.root().get("input#phone").clear().blur();
cy.root().get("button").contains("Continue").should("be.enabled");
});
});
});
});

0 comments on commit a1e71c7

Please sign in to comment.