Merge branch 'develop' into feature/apiModelChanges
This commit is contained in:
commit
e3174515b9
9 changed files with 454 additions and 361 deletions
|
|
@ -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 };
|
|
||||||
}
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
<template>
|
|
||||||
<transition name="fade" mode="out-in">
|
|
||||||
<div class="customer-details-question">
|
|
||||||
<modal
|
|
||||||
ref="CustomerDetailsModal"
|
|
||||||
headerText="Contact details"
|
|
||||||
footerButtonText="Save contact details"
|
|
||||||
:onModalOpenedCallback="onModalOpened"
|
|
||||||
:onModalClosedCallback="onModalClosed"
|
|
||||||
@isModalOpened="setModalStatus"
|
|
||||||
@footer-button-event="setContactDetails">
|
|
||||||
<template v-if="isModalOpened">
|
|
||||||
<textboxQuestion
|
|
||||||
class="mb-4"
|
|
||||||
cmsWidgetName="CustomerFirstNameWidget"
|
|
||||||
v-model="firstName"
|
|
||||||
ref="firstName"
|
|
||||||
customInputId="firstName"
|
|
||||||
validation-rules="first-name-required" />
|
|
||||||
<textboxQuestion
|
|
||||||
class="mb-4"
|
|
||||||
cmsWidgetName="CustomerLastNameWidget"
|
|
||||||
v-model="lastName"
|
|
||||||
ref="lastName"
|
|
||||||
customInputId="lastName"
|
|
||||||
validation-rules="last-name-required" />
|
|
||||||
<textboxQuestion
|
|
||||||
class="mb-4"
|
|
||||||
cmsWidgetName="CustomerEmailWidget"
|
|
||||||
v-model="emailAddress"
|
|
||||||
ref="emailAddress"
|
|
||||||
customInputId="emailAddress"
|
|
||||||
validation-rules="email-address-required|email-address-format" />
|
|
||||||
<phoneNumberQuestion
|
|
||||||
class="mb-4"
|
|
||||||
cmsWidgetName="CustomerPhoneWidget"
|
|
||||||
v-model="phoneNumber"
|
|
||||||
ref="phoneNumber"
|
|
||||||
isRequired
|
|
||||||
validation-rules="phone-number-required" />
|
|
||||||
<checkboxQuestion
|
|
||||||
class="mb-5"
|
|
||||||
cmsWidgetName="CustomerTextMeWidget"
|
|
||||||
v-model="isSmsOptIn" />
|
|
||||||
<textBlock cmsWidgetName="CustomerTextDisclaimerWidget" typeStyle="caption" />
|
|
||||||
</template>
|
|
||||||
</modal>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import modal from "@/digital-components/modal/modal";
|
|
||||||
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
|
||||||
import phoneNumberQuestion from "@/digital-components/phone-number-question/phone-number-question";
|
|
||||||
import checkboxQuestion from "@/digital-components/checkbox-question/checkbox-question";
|
|
||||||
import textBlock from "@/digital-components/text-block/text-block";
|
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
|
||||||
import { required, regex } from "@/helpers/validation-rules";
|
|
||||||
import { defineRule } from "vee-validate";
|
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
|
||||||
defineRule("first-name-required", required(errorMessages.FIRST_NAME_REQUIRED));
|
|
||||||
defineRule("last-name-required", required(errorMessages.LAST_NAME_REQUIRED));
|
|
||||||
defineRule("phone-number-required", required(errorMessages.PHONE_REQUIRED));
|
|
||||||
defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
|
|
||||||
defineRule(
|
|
||||||
"email-address-format",
|
|
||||||
regex(
|
|
||||||
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/,
|
|
||||||
errorMessages.EMAIL_ADDRESS_FORMAT
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "customer-details-modal-question",
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isModalOpened: false,
|
|
||||||
firstName: "",
|
|
||||||
lastName: "",
|
|
||||||
emailAddress: "",
|
|
||||||
phoneNumber: "",
|
|
||||||
isSmsOptIn: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
previousCustomerValues: Object,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
modal() {
|
|
||||||
return this.$refs.CustomerDetailsModal;
|
|
||||||
},
|
|
||||||
haveCustomerDetailsChanged() {
|
|
||||||
return (
|
|
||||||
this.firstName !== this.previousCustomerValues?.firstName ||
|
|
||||||
this.lastName !== this.previousCustomerValues?.lastName ||
|
|
||||||
this.emailAddress !== this.previousCustomerValues?.emailAddress ||
|
|
||||||
this.phoneNumber !== this.previousCustomerValues?.phoneNumber ||
|
|
||||||
this.isSmsOptIn !== this.previousCustomerValues?.isSmsOptIn
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openModal() {
|
|
||||||
this.modal.openModal();
|
|
||||||
},
|
|
||||||
closeModal() {
|
|
||||||
this.modal.closeModal();
|
|
||||||
},
|
|
||||||
onModalOpened() {
|
|
||||||
this.firstName = this.previousCustomerValues?.firstName ?? "";
|
|
||||||
this.lastName = this.previousCustomerValues?.lastName ?? "";
|
|
||||||
this.emailAddress = this.previousCustomerValues?.emailAddress ?? "";
|
|
||||||
this.phoneNumber = this.previousCustomerValues?.phoneNumber ?? "";
|
|
||||||
this.isSmsOptIn = this.previousCustomerValues?.isSmsOptIn ?? false;
|
|
||||||
},
|
|
||||||
onModalClosed() {},
|
|
||||||
setModalStatus(isOpened) {
|
|
||||||
this.isModalOpened = isOpened;
|
|
||||||
},
|
|
||||||
async setContactDetails() {
|
|
||||||
if (this.haveCustomerDetailsChanged) {
|
|
||||||
await this.dispatchStoreAction(
|
|
||||||
this.storeActions.SAVE_CUSTOMER_DETAILS,
|
|
||||||
{
|
|
||||||
firstName: this.firstName,
|
|
||||||
lastName: this.lastName,
|
|
||||||
emailAddress: this.emailAddress,
|
|
||||||
phoneNumber: this.phoneNumber,
|
|
||||||
isSmsOptIn: this.isSmsOptIn,
|
|
||||||
},
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.closeModal();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
modal,
|
|
||||||
textboxQuestion,
|
|
||||||
phoneNumberQuestion,
|
|
||||||
checkboxQuestion,
|
|
||||||
textBlock,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
@ -9,11 +9,7 @@ const testConstants = {
|
||||||
text: "Header",
|
text: "Header",
|
||||||
},
|
},
|
||||||
sms: {
|
sms: {
|
||||||
template: "Test {custom:smsOptInJoiner}",
|
text: "Sms",
|
||||||
expected: {
|
|
||||||
ifTrue: "Test in to",
|
|
||||||
ifFalse: "Test out of",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
customer: {
|
customer: {
|
||||||
|
|
@ -27,7 +23,7 @@ const testConstants = {
|
||||||
fullName: "First Last",
|
fullName: "First Last",
|
||||||
phoneNumber: "111-111-1111",
|
phoneNumber: "111-111-1111",
|
||||||
emailAddress: "builddigitaltest@safelite.com",
|
emailAddress: "builddigitaltest@safelite.com",
|
||||||
smsOptIn: "Test out of",
|
smsOptIn: "Sms",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -38,7 +34,7 @@ describe("Customer Review Block", () => {
|
||||||
cmsContent = {
|
cmsContent = {
|
||||||
CustomerWidget: {
|
CustomerWidget: {
|
||||||
HeaderText: testConstants.cms.header.text,
|
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);
|
expect(wrapper.vm.header).toEqual(testConstants.cms.header.text);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("SMS Opt In Text", () => {
|
test("Should display sms text from cms", async () => {
|
||||||
test("Should render correctly when opt in is true:", async () => {
|
// Arrange
|
||||||
// Arrange
|
let props = generateDefaultProps();
|
||||||
let props = generateDefaultProps();
|
|
||||||
props.customer.isSmsOptIn = true;
|
|
||||||
|
|
||||||
const { wrapper } = setupMocks({
|
const { wrapper } = setupMocks({
|
||||||
propsData: props,
|
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({
|
// Act
|
||||||
propsData: props,
|
await wrapper.vm.$nextTick();
|
||||||
});
|
|
||||||
|
|
||||||
// Act
|
// Assert
|
||||||
await wrapper.vm.$nextTick();
|
expect(wrapper.vm.smsOptIn).toEqual(testConstants.cms.sms.text);
|
||||||
|
|
||||||
// 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 () => {
|
test("Should render correct display content", async () => {
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,7 @@ export default {
|
||||||
return this.customer?.phoneNumber;
|
return this.customer?.phoneNumber;
|
||||||
},
|
},
|
||||||
smsOptIn() {
|
smsOptIn() {
|
||||||
const rawCmsText = this.getCmsContent(this.cmsWidgetName, "SubheaderText");
|
return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
|
||||||
const joinerText = this.customer?.isSmsOptIn ? "in to" : "out of";
|
|
||||||
|
|
||||||
return rawCmsText.replace("{custom:smsOptInJoiner}", joinerText);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
||||||
|
|
@ -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", () => {
|
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 };
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,10 +89,6 @@
|
||||||
<hr class="my-0" />
|
<hr class="my-0" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<customerDetailsModalQuestion
|
|
||||||
ref="customerDetailsModalQuestion"
|
|
||||||
:previousCustomerValues="customerInfo" />
|
|
||||||
|
|
||||||
<funnelFooter
|
<funnelFooter
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
|
|
@ -115,10 +111,11 @@ import serviceLocationReview from "@/layouts/review/review-sections/service-loca
|
||||||
import scheduleReview from "@/layouts/review/review-sections/schedule-review/schedule-review";
|
import scheduleReview from "@/layouts/review/review-sections/schedule-review/schedule-review";
|
||||||
import customerReview from "@/layouts/review/review-sections/customer-review/customer-review";
|
import customerReview from "@/layouts/review/review-sections/customer-review/customer-review";
|
||||||
|
|
||||||
import customerDetailsModalQuestion from "@/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.vue";
|
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
||||||
|
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "review",
|
name: "review",
|
||||||
|
|
@ -153,7 +150,75 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
return true;
|
// Vehicle
|
||||||
|
const vehicle = store.getters.order.vehicle;
|
||||||
|
const vehicleReqs = !!(vehicle.year && vehicle.make && vehicle.model && vehicle.style);
|
||||||
|
|
||||||
|
// Damage
|
||||||
|
const damage = store.getters.order.damage;
|
||||||
|
const damageReqs = !!(
|
||||||
|
(damage.isRepair && damage.numberOfChips) ||
|
||||||
|
(!damage.isRepair && damage.glassToReplace?.length)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Service Package
|
||||||
|
const lineItems = store.getters.order.lineItems;
|
||||||
|
// damageReqs handles checking for damage, even though it is also required for this section.
|
||||||
|
const packageReqs = !!(
|
||||||
|
(damage.isRepair || lineItems.glassParts) &&
|
||||||
|
lineItems.supportingItems &&
|
||||||
|
lineItems.vaps
|
||||||
|
);
|
||||||
|
|
||||||
|
// Service Location
|
||||||
|
const serviceLocation = store.getters.order.serviceLocation;
|
||||||
|
const mobileReqs = !!(
|
||||||
|
serviceLocation.address &&
|
||||||
|
serviceLocation.city &&
|
||||||
|
serviceLocation.state &&
|
||||||
|
serviceLocation.zipCode
|
||||||
|
);
|
||||||
|
|
||||||
|
const providerLocation = serviceLocation.provider.address;
|
||||||
|
const dropOffInshopReqs = !!(
|
||||||
|
providerLocation.streetAddress &&
|
||||||
|
providerLocation.city &&
|
||||||
|
providerLocation.state &&
|
||||||
|
providerLocation.zipCode
|
||||||
|
);
|
||||||
|
|
||||||
|
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
|
||||||
|
|
||||||
|
const serviceLocationReqs =
|
||||||
|
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
|
||||||
|
|
||||||
|
// Schedule
|
||||||
|
const schedule = store.getters.order.schedule;
|
||||||
|
const scheduleReqs = !!(
|
||||||
|
schedule.date &&
|
||||||
|
schedule.startTime &&
|
||||||
|
schedule.endTime &&
|
||||||
|
schedule.jobMaxMinutes &&
|
||||||
|
schedule.jobMinMinutes
|
||||||
|
);
|
||||||
|
|
||||||
|
// Customer
|
||||||
|
const customer = store.getters.order.customer;
|
||||||
|
const customerReqs = !!(
|
||||||
|
customer.firstName &&
|
||||||
|
customer.lastName &&
|
||||||
|
customer.phoneNumber &&
|
||||||
|
customer.emailAddress
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
vehicleReqs &&
|
||||||
|
damageReqs &&
|
||||||
|
packageReqs &&
|
||||||
|
serviceLocationReqs &&
|
||||||
|
scheduleReqs &&
|
||||||
|
customerReqs
|
||||||
|
);
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
|
|
@ -190,7 +255,10 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
editCustomerDetails() {
|
editCustomerDetails() {
|
||||||
this.$refs.customerDetailsModalQuestion.openModal();
|
this.$router.navigateWithoutSaving(
|
||||||
|
this.navigationScenarios.CLICKED_CUSTOMER_EDIT,
|
||||||
|
this.$route
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -234,7 +302,6 @@ export default {
|
||||||
serviceLocationReview,
|
serviceLocationReview,
|
||||||
scheduleReview,
|
scheduleReview,
|
||||||
customerReview,
|
customerReview,
|
||||||
customerDetailsModalQuestion,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ export default {
|
||||||
if (this.availabilityRating == null) {
|
if (this.availabilityRating == null) {
|
||||||
return "gray";
|
return "gray";
|
||||||
} else {
|
} else {
|
||||||
return this.availabilityRating == "high" ? "green" : "red";
|
return this.availabilityRating == "high" ? "green" : "Orange";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
badgeText() {
|
badgeText() {
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ const navigationScenarios = {
|
||||||
CLICKED_SERVICE_PACKAGE_EDIT: "CLICKED_SERVICE_PACKAGE_EDIT",
|
CLICKED_SERVICE_PACKAGE_EDIT: "CLICKED_SERVICE_PACKAGE_EDIT",
|
||||||
CLICKED_SERVICE_LOCATION_EDIT: "CLICKED_SERVICE_LOCATION_EDIT",
|
CLICKED_SERVICE_LOCATION_EDIT: "CLICKED_SERVICE_LOCATION_EDIT",
|
||||||
CLICKED_SCHEDULE_EDIT: "CLICKED_SCHEDULE_EDIT",
|
CLICKED_SCHEDULE_EDIT: "CLICKED_SCHEDULE_EDIT",
|
||||||
|
CLICKED_CUSTOMER_EDIT: "CLICKED_CUSTOMER_EDIT",
|
||||||
};
|
};
|
||||||
|
|
||||||
export { navigationScenarios };
|
export { navigationScenarios };
|
||||||
|
|
|
||||||
|
|
@ -441,6 +441,10 @@ const routingTable = function (store) {
|
||||||
scenario: navigationScenarios.CLICKED_SCHEDULE_EDIT,
|
scenario: navigationScenarios.CLICKED_SCHEDULE_EDIT,
|
||||||
destinationFmgPageValue: fmgPageValues.SCHEDULE,
|
destinationFmgPageValue: fmgPageValues.SCHEDULE,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.CLICKED_CUSTOMER_EDIT,
|
||||||
|
destinationFmgPageValue: fmgPageValues.CUSTOMER_DETAILS,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue