diff --git a/src/digital-components/phone-number-question/phone-number-question.vue b/src/digital-components/phone-number-question/phone-number-question.vue
index f3fdc6cd6..86dfc3f04 100644
--- a/src/digital-components/phone-number-question/phone-number-question.vue
+++ b/src/digital-components/phone-number-question/phone-number-question.vue
@@ -8,7 +8,7 @@
:mask="mask"
:isRequired="isRequired"
:validationRules="validationRulesForTextBoxQuestion"
- cmsWidgetName="PhoneNumberQuestionWidget" />
+ :cmsWidgetName="cmsWidgetName" />
diff --git a/src/layouts/customer-details/customer-details.vue b/src/layouts/customer-details/customer-details.vue
index e91317ca9..55e1b01b8 100644
--- a/src/layouts/customer-details/customer-details.vue
+++ b/src/layouts/customer-details/customer-details.vue
@@ -25,7 +25,7 @@
validationRules="email-address-required|email-address-format" />
diff --git a/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.spec.js b/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.spec.js
new file mode 100644
index 000000000..a8e0a6f7b
--- /dev/null
+++ b/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.spec.js
@@ -0,0 +1,150 @@
+import { shallowMount } from "@vue/test-utils";
+import { getMountOptions } from "@/helpers/unit-test-helper.js";
+
+import customerDetailsModalQuestion from "@/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question";
+
+const testConstants = {
+ previousCustomerValues: {
+ firstName: "First",
+ lastName: "Last",
+ emailAddress: "builddigitaltest@safelite.com",
+ phoneNumber: "111-111-1111",
+ isSmsOptIn: false,
+ },
+ newValues: {
+ firstName: "New First",
+ lastName: "New Last",
+ emailAddress: "builddigitaltest2@safelite.com",
+ phoneNumber: "222-222-2222",
+ isSmsOptIn: true,
+ },
+};
+
+let cmsContent;
+
+describe("Customer Details Modal", () => {
+ beforeEach(() => {
+ cmsContent = {};
+ });
+
+ describe("Submit", () => {
+ test("Should push to store if a field has changed", async () => {
+ // Arrange
+ let props = generateDefaultProps();
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ wrapper.vm.onModalOpened();
+
+ wrapper.vm.firstName = testConstants.newValues.firstName;
+
+ await wrapper.vm.setContactDetails();
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
+ expect(wrapper.vm.closeModal).toHaveBeenCalled();
+ });
+
+ test("Should not push to store if no fields have changed", async () => {
+ // Arrange
+ let props = generateDefaultProps();
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ wrapper.vm.onModalOpened();
+
+ await wrapper.vm.setContactDetails();
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ expect(wrapper.vm.dispatchStoreAction).not.toHaveBeenCalled();
+ expect(wrapper.vm.closeModal).toHaveBeenCalled();
+ });
+ });
+
+ describe("Default values", () => {
+ test("Should populate on open", () => {
+ // Arrange
+ let props = generateDefaultProps();
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ wrapper.vm.onModalOpened();
+
+ // Assert
+ expect(wrapper.vm.firstName).toBe(testConstants.previousCustomerValues.firstName);
+ expect(wrapper.vm.lastName).toBe(testConstants.previousCustomerValues.lastName);
+ expect(wrapper.vm.emailAddress).toBe(testConstants.previousCustomerValues.emailAddress);
+ expect(wrapper.vm.phoneNumber).toBe(testConstants.previousCustomerValues.phoneNumber);
+ expect(wrapper.vm.isSmsOptIn).toBe(testConstants.previousCustomerValues.isSmsOptIn);
+ });
+
+ test("Should replace old values on open", async () => {
+ // Arrange
+ let props = generateDefaultProps();
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ wrapper.vm.firstName = testConstants.newValues.firstName;
+ wrapper.vm.lastName = testConstants.newValues.lastName;
+ wrapper.vm.emailAddress = testConstants.newValues.emailAddress;
+ wrapper.vm.phoneNumber = testConstants.newValues.phoneNumber;
+ wrapper.vm.isSmsOptIn = testConstants.newValues.isSmsOptIn;
+
+ wrapper.vm.onModalOpened();
+
+ // Assert
+ expect(wrapper.vm.firstName).toBe(testConstants.previousCustomerValues.firstName);
+ expect(wrapper.vm.lastName).toBe(testConstants.previousCustomerValues.lastName);
+ expect(wrapper.vm.emailAddress).toBe(testConstants.previousCustomerValues.emailAddress);
+ expect(wrapper.vm.phoneNumber).toBe(testConstants.previousCustomerValues.phoneNumber);
+ expect(wrapper.vm.isSmsOptIn).toBe(testConstants.previousCustomerValues.isSmsOptIn);
+ });
+ });
+});
+
+function generateDefaultProps() {
+ return {
+ previousCustomerValues: {
+ firstName: testConstants.previousCustomerValues.firstName,
+ lastName: testConstants.previousCustomerValues.lastName,
+ emailAddress: testConstants.previousCustomerValues.emailAddress,
+ phoneNumber: testConstants.previousCustomerValues.phoneNumber,
+ isSmsOptIn: testConstants.previousCustomerValues.isSmsOptIn,
+ },
+ };
+}
+
+function setupMocks(customMountOptions) {
+ const mountOptions = getMountOptions(customMountOptions);
+
+ const mockMixin = {
+ methods: {
+ getCmsContent: jest.fn((widgetName, cmsFieldName) => {
+ return cmsContent?.[widgetName]?.[cmsFieldName] ?? "";
+ }),
+ },
+ };
+
+ mountOptions.global.mixins = [mockMixin];
+
+ const wrapper = shallowMount(customerDetailsModalQuestion, mountOptions);
+ wrapper.vm.setCmsContent = jest.fn();
+ wrapper.vm.openModal = jest.fn();
+ wrapper.vm.closeModal = jest.fn();
+ wrapper.vm.dispatchStoreAction = jest.fn();
+ return { wrapper };
+}
diff --git a/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.vue b/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.vue
new file mode 100644
index 000000000..0b08abee7
--- /dev/null
+++ b/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
diff --git a/src/layouts/review/review-sections/customer-review/customer-review.spec.js b/src/layouts/review/review-sections/customer-review/customer-review.spec.js
new file mode 100644
index 000000000..1bcbbe83b
--- /dev/null
+++ b/src/layouts/review/review-sections/customer-review/customer-review.spec.js
@@ -0,0 +1,159 @@
+import { shallowMount } from "@vue/test-utils";
+import { getMountOptions } from "@/helpers/unit-test-helper.js";
+
+import customerReview from "@/layouts/review/review-sections/customer-review/customer-review";
+
+const testConstants = {
+ cms: {
+ header: {
+ text: "Header",
+ },
+ sms: {
+ template: "Test {custom:smsOptInJoiner}",
+ expected: {
+ ifTrue: "Test in to",
+ ifFalse: "Test out of",
+ },
+ },
+ },
+ customer: {
+ firstName: "First",
+ lastName: "Last",
+ phoneNumber: "111-111-1111",
+ emailAddress: "builddigitaltest@safelite.com",
+ isSmsOptIn: false,
+ },
+ displayContent: {
+ fullName: "First Last",
+ phoneNumber: "111-111-1111",
+ emailAddress: "builddigitaltest@safelite.com",
+ smsOptIn: "Test out of",
+ },
+};
+
+let cmsContent;
+
+describe("Customer Review Block", () => {
+ beforeEach(() => {
+ cmsContent = {
+ CustomerWidget: {
+ HeaderText: testConstants.cms.header.text,
+ SubheaderText: testConstants.cms.sms.template,
+ },
+ };
+ });
+
+ test("Should display header text from cms", async () => {
+ // Arrange
+ let props = generateDefaultProps();
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ expect(wrapper.vm.header).toEqual(testConstants.cms.header.text);
+ });
+
+ describe("SMS Opt In Text", () => {
+ test("Should render correctly when opt in is true:", async () => {
+ // Arrange
+ let props = generateDefaultProps();
+ props.customer.isSmsOptIn = true;
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ expect(wrapper.vm.smsOptIn).toEqual(testConstants.cms.sms.expected.ifTrue);
+ });
+ test("Should render correctly when opt in is false:", async () => {
+ // Arrange
+ let props = generateDefaultProps();
+ props.customer.isSmsOptIn = false;
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ expect(wrapper.vm.smsOptIn).toEqual(testConstants.cms.sms.expected.ifFalse);
+ });
+ test("Should render correctly when opt in is null:", async () => {
+ // Arrange
+ let props = generateDefaultProps();
+ props.customer.isSmsOptIn = null;
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ expect(wrapper.vm.smsOptIn).toEqual(testConstants.cms.sms.expected.ifFalse);
+ });
+ });
+
+ test("Should render correct display content", async () => {
+ // Arrange
+ let props = generateDefaultProps();
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ expect(wrapper.vm.displayContent).toEqual([
+ testConstants.displayContent.fullName,
+ testConstants.displayContent.emailAddress,
+ testConstants.displayContent.phoneNumber,
+ testConstants.displayContent.smsOptIn,
+ ]);
+ });
+});
+
+function generateDefaultProps() {
+ return {
+ cmsWidgetName: "CustomerWidget",
+ customer: {
+ firstName: testConstants.customer.firstName,
+ lastName: testConstants.customer.lastName,
+ phoneNumber: testConstants.customer.phoneNumber,
+ emailAddress: testConstants.customer.emailAddress,
+ isSmsOptIn: testConstants.customer.isSmsOptIn,
+ },
+ };
+}
+
+function setupMocks(customMountOptions) {
+ const mountOptions = getMountOptions(customMountOptions);
+
+ const mockMixin = {
+ methods: {
+ getCmsContent: jest.fn((widgetName, cmsFieldName) => {
+ return cmsContent?.[widgetName]?.[cmsFieldName] ?? "";
+ }),
+ },
+ };
+
+ mountOptions.global.mixins = [mockMixin];
+
+ const wrapper = shallowMount(customerReview, mountOptions);
+ wrapper.vm.setCmsContent = jest.fn();
+ return { wrapper };
+}
diff --git a/src/layouts/review/review-sections/customer-review/customer-review.vue b/src/layouts/review/review-sections/customer-review/customer-review.vue
new file mode 100644
index 000000000..d8777d9e4
--- /dev/null
+++ b/src/layouts/review/review-sections/customer-review/customer-review.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
diff --git a/src/layouts/review/review.vue b/src/layouts/review/review.vue
index fce6e4f59..fe14e8f7e 100644
--- a/src/layouts/review/review.vue
+++ b/src/layouts/review/review.vue
@@ -76,12 +76,23 @@
cmsWidgetName="ScheduleWidget"
:appointmentType="appointmentType"
@edit-clicked="editSchedule" />
+
+
+
+
+
+
diff --git a/src/router/index.js b/src/router/index.js
index 6d812f847..e8fbf4d26 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -31,11 +31,6 @@ import { applicationConfig } from "../constants/application-config";
import review from "@/layouts/review/review";
import paymentMethod from "@/layouts/payment-method/payment-method";
const routes = [
- {
- path: "/review", // This is a temporary route for testing.
- name: "review",
- component: review,
- },
{
path: "/payment-method", // This is a temporary route for testing.
name: "payment-method",