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
deleted file mode 100644
index a8e0a6f7b..000000000
--- a/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.spec.js
+++ /dev/null
@@ -1,150 +0,0 @@
-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
deleted file mode 100644
index 0b08abee7..000000000
--- a/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.vue
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
-
-
-
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
index 1bcbbe83b..45627df2e 100644
--- a/src/layouts/review/review-sections/customer-review/customer-review.spec.js
+++ b/src/layouts/review/review-sections/customer-review/customer-review.spec.js
@@ -9,11 +9,7 @@ const testConstants = {
text: "Header",
},
sms: {
- template: "Test {custom:smsOptInJoiner}",
- expected: {
- ifTrue: "Test in to",
- ifFalse: "Test out of",
- },
+ text: "Sms",
},
},
customer: {
@@ -27,7 +23,7 @@ const testConstants = {
fullName: "First Last",
phoneNumber: "111-111-1111",
emailAddress: "builddigitaltest@safelite.com",
- smsOptIn: "Test out of",
+ smsOptIn: "Sms",
},
};
@@ -38,7 +34,7 @@ describe("Customer Review Block", () => {
cmsContent = {
CustomerWidget: {
HeaderText: testConstants.cms.header.text,
- SubheaderText: testConstants.cms.sms.template,
+ SubheaderText: testConstants.cms.sms.text,
},
};
});
@@ -58,52 +54,19 @@ describe("Customer Review Block", () => {
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;
+ test("Should display sms text from cms", async () => {
+ // Arrange
+ let props = generateDefaultProps();
- const { wrapper } = setupMocks({
- propsData: props,
- });
-
- // Act
- await wrapper.vm.$nextTick();
-
- // Assert
- expect(wrapper.vm.smsOptIn).toEqual(testConstants.cms.sms.expected.ifTrue);
+ const { wrapper } = setupMocks({
+ propsData: props,
});
- 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();
- // 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);
- });
+ // Assert
+ expect(wrapper.vm.smsOptIn).toEqual(testConstants.cms.sms.text);
});
test("Should render correct display content", async () => {
diff --git a/src/layouts/review/review-sections/customer-review/customer-review.vue b/src/layouts/review/review-sections/customer-review/customer-review.vue
index d8777d9e4..678dcf0b6 100644
--- a/src/layouts/review/review-sections/customer-review/customer-review.vue
+++ b/src/layouts/review/review-sections/customer-review/customer-review.vue
@@ -36,10 +36,7 @@ export default {
return this.customer?.phoneNumber;
},
smsOptIn() {
- const rawCmsText = this.getCmsContent(this.cmsWidgetName, "SubheaderText");
- const joinerText = this.customer?.isSmsOptIn ? "in to" : "out of";
-
- return rawCmsText.replace("{custom:smsOptInJoiner}", joinerText);
+ return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
},
},
components: {
diff --git a/src/layouts/review/review.spec.js b/src/layouts/review/review.spec.js
index 674dc71f7..a4f82451d 100644
--- a/src/layouts/review/review.spec.js
+++ b/src/layouts/review/review.spec.js
@@ -1,3 +1,362 @@
+import { shallowMount } from "@vue/test-utils";
+import { getMountOptions } from "@/helpers/unit-test-helper.js";
+import store from "@/store";
+
+import review from "@/layouts/review/review";
+
+const testConstants = {};
+
+jest.mock("@/store", () => ({
+ commit: jest.fn(),
+ dispatch: jest.fn(),
+}));
+
describe("Review Page", () => {
- test.todo("Add more tests as specific functionality is added.");
+ beforeEach(() => {
+ store.getters = {
+ order: {
+ vehicle: {
+ year: "2020",
+ make: "Acura",
+ model: "MDX",
+ style: "4 door sedan",
+ },
+ damage: {
+ isRepair: false,
+ numberOfChips: 2,
+ glassToReplace: ["dummy location value"],
+ },
+ lineItems: {
+ glassParts: ["dummy part value"],
+ supportingItems: ["dummy supporting item"],
+ vaps: ["dummy vap"],
+ },
+ serviceLocation: {
+ address: "address 1",
+ address2: "address 2",
+ city: "city",
+ state: "state",
+ zipCode: "zip code",
+ appointmentType: "Mobile",
+ provider: {
+ providerNumber: 1,
+ address: {
+ streetAddress: "provider address 1",
+ city: "provider city",
+ state: "provider state",
+ zipCode: "provider zip code",
+ },
+ },
+ },
+ schedule: {
+ date: "date",
+ startTime: "start",
+ endTime: "end",
+ jobMinMinutes: "30",
+ jobMaxMinutes: "45",
+ },
+ customer: {
+ firstName: "first name",
+ lastName: "last name",
+ emailAddress: "builddigitaltest@safelite.com",
+ phoneNumber: "555-555-5555",
+ isSmsOptIn: true,
+ },
+ },
+ };
+ });
+ describe("arePagePrerequisitesValid", () => {
+ test("Returns true for baseline valid state", () => {
+ // Arrange
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(true);
+ });
+ test("Returns false for empty state", () => {
+ // Arrange
+ store.getters.order = {
+ vehicle: {
+ year: null,
+ make: null,
+ model: null,
+ style: null,
+ carId: null,
+ category: null,
+ vin: null,
+ imageUrl: null,
+ imageVifNumber: null,
+ imageColor: null,
+ registration: {
+ licensePlate: null,
+ },
+ },
+ serviceLocation: {
+ address: null,
+ address2: null,
+ city: null,
+ state: null,
+ zipCode: null,
+ zipCodeCtu: null,
+ appointmentType: null,
+ isVehicleProtected: null,
+ provider: {
+ providerNumber: null,
+ address: {
+ streetAddress: null,
+ city: null,
+ state: null,
+ zipCode: null,
+ zipCodeCtu: null,
+ },
+ },
+ techNotes: null,
+ },
+ customer: {
+ firstName: null,
+ lastName: null,
+ emailAddress: null,
+ phoneNumber: null,
+ isSmsOptIn: null,
+ },
+ damage: {
+ isRepair: null,
+ numberOfChips: null,
+ glassToReplace: null,
+ partQuestionAnswers: null,
+ moldingQuestionAnswers: null,
+ capabilityQuestionAnswers: null,
+ },
+ lineItems: {
+ glassParts: null,
+ supportingItems: null,
+ vaps: null,
+ serverData: null,
+ },
+ payment: {
+ isInsurance: null,
+ insuranceCoverage: {
+ isVerified: null,
+ coverageStatus: null,
+ },
+ parentAccountNumber: 0,
+ },
+ schedule: {
+ date: null,
+ startTime: null,
+ endTime: null,
+ routeCode: null,
+ jobMaxMinutes: null,
+ jobMinMinutes: null,
+ },
+ referralNumber: null,
+ referralSequenceNumber: null,
+ referralDate: null,
+ referralCorrelationId: null,
+ eon: null,
+ };
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(false);
+ });
+ describe("Damage requirements", () => {
+ test("Accepts null glassToReplace when is repair", () => {
+ // Arrange
+ store.getters.order.damage.isRepair = true;
+ store.getters.order.damage.glassToReplace = null;
+ store.getters.order.damage.numberOfChips = 1;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(true);
+ });
+ test("Rejects 0 chips when repair", () => {
+ // Arrange
+ store.getters.order.damage.isRepair = true;
+ store.getters.order.damage.numberOfChips = 0;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(false);
+ });
+ test("Rejects null chips when repair", () => {
+ // Arrange
+ store.getters.order.damage.isRepair = true;
+ store.getters.order.damage.numberOfChips = null;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(false);
+ });
+ test("Accepts null chips when not repair", () => {
+ // Arrange
+ store.getters.order.damage.isRepair = false;
+ store.getters.order.damage.numberOfChips = null;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(true);
+ });
+ test("Rejects empty glassToReplace when not repair", () => {
+ // Arrange
+ store.getters.order.damage.isRepair = false;
+ store.getters.order.damage.glassToReplace = null;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(false);
+ });
+ test("Rejects null glassToReplace when not repair", () => {
+ // Arrange
+ store.getters.order.damage.isRepair = false;
+ store.getters.order.damage.glassToReplace = [];
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(false);
+ });
+ });
+ describe("Package requirements", () => {
+ test("Accepts null glassParts when is repair", () => {
+ // Arrange
+ store.getters.order.damage.isRepair = true;
+ store.getters.order.lineItems.glassParts = null;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(true);
+ });
+ test("Rejects null glassParts when not repair", () => {
+ // Arrange
+ store.getters.order.damage.isRepair = false;
+ store.getters.order.lineItems.glassParts = null;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(false);
+ });
+ });
+ describe("Service Location requirements", () => {
+ test("Accepts null provider address when mobile appointment", () => {
+ // Arrange
+ store.getters.order.serviceLocation.appointmentType = "Mobile";
+ store.getters.order.serviceLocation.provider.address = {};
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(true);
+ });
+ test("Reject null provider address when non-mobile appointment", () => {
+ // Arrange
+ store.getters.order.serviceLocation.appointmentType = "Inshop";
+ store.getters.order.serviceLocation.provider.address = {};
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(false);
+ });
+ test("Accepts null service location address when non-mobile appointment", () => {
+ // Arrange
+ store.getters.order.serviceLocation.appointmentType = "Inshop";
+ store.getters.order.serviceLocation.address = null;
+ store.getters.order.serviceLocation.address2 = null;
+ store.getters.order.serviceLocation.zipCode = null;
+ store.getters.order.serviceLocation.city = null;
+ store.getters.order.serviceLocation.state = null;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(true);
+ });
+ test("Rejects null service location address when mobile appointment", () => {
+ // Arrange
+ store.getters.order.serviceLocation.appointmentType = "Mobile";
+ store.getters.order.serviceLocation.address = null;
+ store.getters.order.serviceLocation.address2 = null;
+ store.getters.order.serviceLocation.zipCode = null;
+ store.getters.order.serviceLocation.city = null;
+ store.getters.order.serviceLocation.state = null;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const isValid = wrapper.vm.arePagePrerequisitesValid();
+
+ // Assert
+ expect(isValid).toBe(false);
+ });
+ });
+ });
});
+
+function setupMocks(customMountOptions) {
+ customMountOptions.store = store;
+
+ const mountOptions = getMountOptions(customMountOptions);
+
+ const mockMixin = {
+ methods: {
+ getCmsContent: jest.fn((widgetName, cmsFieldName) => {
+ return `${widgetName} ${cmsFieldName}`;
+ }),
+ },
+ };
+
+ mountOptions.global.mixins = [mockMixin];
+
+ const wrapper = shallowMount(review, mountOptions);
+ wrapper.vm.setCmsContent = jest.fn();
+ return { wrapper };
+}
diff --git a/src/layouts/review/review.vue b/src/layouts/review/review.vue
index fe14e8f7e..2fb033ea3 100644
--- a/src/layouts/review/review.vue
+++ b/src/layouts/review/review.vue
@@ -89,10 +89,6 @@
-
-
diff --git a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue
index 31c415a2d..9a0fb063e 100644
--- a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue
+++ b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue
@@ -88,7 +88,7 @@ export default {
if (this.availabilityRating == null) {
return "gray";
} else {
- return this.availabilityRating == "high" ? "green" : "red";
+ return this.availabilityRating == "high" ? "green" : "Orange";
}
},
badgeText() {
diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js
index bf89f4f3f..30f7d0341 100644
--- a/src/router/router-constants/navigation-scenarios.js
+++ b/src/router/router-constants/navigation-scenarios.js
@@ -46,6 +46,7 @@ const navigationScenarios = {
CLICKED_SERVICE_PACKAGE_EDIT: "CLICKED_SERVICE_PACKAGE_EDIT",
CLICKED_SERVICE_LOCATION_EDIT: "CLICKED_SERVICE_LOCATION_EDIT",
CLICKED_SCHEDULE_EDIT: "CLICKED_SCHEDULE_EDIT",
+ CLICKED_CUSTOMER_EDIT: "CLICKED_CUSTOMER_EDIT",
};
export { navigationScenarios };
diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js
index b90806e94..91fd47229 100644
--- a/src/router/router-constants/routing-table.js
+++ b/src/router/router-constants/routing-table.js
@@ -441,6 +441,10 @@ const routingTable = function (store) {
scenario: navigationScenarios.CLICKED_SCHEDULE_EDIT,
destinationFmgPageValue: fmgPageValues.SCHEDULE,
},
+ {
+ scenario: navigationScenarios.CLICKED_CUSTOMER_EDIT,
+ destinationFmgPageValue: fmgPageValues.CUSTOMER_DETAILS,
+ },
],
},
];