Merge branch 'develop' into feature/CSR-1425
This commit is contained in:
commit
db7ae81a6a
35 changed files with 1304 additions and 443 deletions
|
|
@ -17,7 +17,6 @@ module.exports = {
|
||||||
"!src/ux-components/text-link/**/*.vue",
|
"!src/ux-components/text-link/**/*.vue",
|
||||||
"!src/layouts/vin-lookup/**/*.vue", //Temporary for Quote page testing
|
"!src/layouts/vin-lookup/**/*.vue", //Temporary for Quote page testing
|
||||||
"!src/common-components/funnel-header/menu-modal/**/*.vue",
|
"!src/common-components/funnel-header/menu-modal/**/*.vue",
|
||||||
"!src/layouts/schedule/*.vue", // Temp test exclusion while in development
|
|
||||||
"!src/layouts/schedule/helpers/schedule-helper.js", // Temp test exclusion while in development
|
"!src/layouts/schedule/helpers/schedule-helper.js", // Temp test exclusion while in development
|
||||||
"!src/layouts/review/*.vue", // Temp test exclusion while in development
|
"!src/layouts/review/*.vue", // Temp test exclusion while in development
|
||||||
// END
|
// END
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ const GaEvents = {
|
||||||
const GaCategories = {
|
const GaCategories = {
|
||||||
API_RESPONSE: "Api_Response",
|
API_RESPONSE: "Api_Response",
|
||||||
EVOX: "Evox",
|
EVOX: "Evox",
|
||||||
FUNNEL_ENTRY: "funnel_entry",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const GaActions = {
|
const GaActions = {
|
||||||
|
|
@ -21,7 +20,6 @@ const GaActions = {
|
||||||
VIF: "vif",
|
VIF: "vif",
|
||||||
SUBMITTED: "Submitted",
|
SUBMITTED: "Submitted",
|
||||||
DISPLAYED: "Displayed",
|
DISPLAYED: "Displayed",
|
||||||
ZIP_CODE_PROVIDED: "zip_code_provided",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const GaLabels = {
|
const GaLabels = {
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ const endpoints = {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
},
|
},
|
||||||
SaveSession: {
|
SaveSession: {
|
||||||
url: "/order/api/v1/order/save-session",
|
url: "/order/api/v1/order/save-session/fmg",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
LoadSession: {
|
LoadSession: {
|
||||||
|
|
|
||||||
1
src/constants/pay-with-insurance-states.js
Normal file
1
src/constants/pay-with-insurance-states.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const payWithInsuranceStates = ["AZ", "CT", "FL", "KY", "MA", "MN", "NY", "SC"];
|
||||||
|
|
@ -23,13 +23,6 @@ const storeMutations = {
|
||||||
UPDATE_SUPPORTING_ITEMS: "updateSupportingItems",
|
UPDATE_SUPPORTING_ITEMS: "updateSupportingItems",
|
||||||
UPDATE_LINE_ITEMS_SERVER_DATA: "updateLineItemsServerData",
|
UPDATE_LINE_ITEMS_SERVER_DATA: "updateLineItemsServerData",
|
||||||
|
|
||||||
UPDATE_REGISTRATION_LICENSE_PLATE: "updateRegistrationLicensePlate",
|
|
||||||
UPDATE_REGISTRATION_ADDRESS: "updateRegistrationAddress",
|
|
||||||
UPDATE_REGISTRATION_CITY: "updateRegistrationCity",
|
|
||||||
UPDATE_REGISTRATION_STATE: "updateRegistrationState",
|
|
||||||
UPDATE_REGISTRATION_ZIP_CODE: "updateRegistrationZipCode",
|
|
||||||
UPDATE_REGISTRATION_FIRST_NAME: "updateRegistrationFirstName",
|
|
||||||
UPDATE_REGISTRATION_LAST_NAME: "updateRegistrationLastName",
|
|
||||||
UPDATE_REGISTRATION: "updateRegistration",
|
UPDATE_REGISTRATION: "updateRegistration",
|
||||||
|
|
||||||
UPDATE_SERVICE_ZIP: "updateServiceZip",
|
UPDATE_SERVICE_ZIP: "updateServiceZip",
|
||||||
|
|
@ -43,6 +36,7 @@ const storeMutations = {
|
||||||
|
|
||||||
// ORDER MUTATIONS
|
// ORDER MUTATIONS
|
||||||
UPDATE_REFERRAL_NUMBER: "updateReferralNumber",
|
UPDATE_REFERRAL_NUMBER: "updateReferralNumber",
|
||||||
|
UPDATE_REFERRAL_SEQUENCE_NUMBER: "updateReferralSequenceNumber",
|
||||||
UPDATE_REFERRAL_DATE: "updateReferralDate",
|
UPDATE_REFERRAL_DATE: "updateReferralDate",
|
||||||
UPDATE_REFERRAL_CORRELATION_ID: "updateReferralCorrelationId",
|
UPDATE_REFERRAL_CORRELATION_ID: "updateReferralCorrelationId",
|
||||||
UPDATE_PARENT_ACCT_NUMBER: "updateParentAcctNumber",
|
UPDATE_PARENT_ACCT_NUMBER: "updateParentAcctNumber",
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
:mask="mask"
|
:mask="mask"
|
||||||
:isRequired="isRequired"
|
:isRequired="isRequired"
|
||||||
:validationRules="validationRulesForTextBoxQuestion"
|
:validationRules="validationRulesForTextBoxQuestion"
|
||||||
cmsWidgetName="PhoneNumberQuestionWidget" />
|
:cmsWidgetName="cmsWidgetName" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ describe("vehicleBanner", () => {
|
||||||
const { wrapper } = setupMocks({
|
const { wrapper } = setupMocks({
|
||||||
displayGenericVehicleImageProp: true,
|
displayGenericVehicleImageProp: true,
|
||||||
imageUrlValue: "NULL",
|
imageUrlValue: "NULL",
|
||||||
|
displayUnmatchedVehicleIconProp: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
@ -87,7 +88,12 @@ describe("vehicleBanner", () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupMocks({ displayGenericVehicleImageProp, imageUrlValue, categoryValue = "CAR" }) {
|
function setupMocks({
|
||||||
|
displayGenericVehicleImageProp,
|
||||||
|
displayUnmatchedVehicleIconProp,
|
||||||
|
imageUrlValue,
|
||||||
|
categoryValue = "CAR",
|
||||||
|
}) {
|
||||||
const mockGetCmsContent = jest.fn();
|
const mockGetCmsContent = jest.fn();
|
||||||
mockGetCmsContent((cmsWidget, field) => {
|
mockGetCmsContent((cmsWidget, field) => {
|
||||||
return field;
|
return field;
|
||||||
|
|
@ -108,7 +114,10 @@ function setupMocks({ displayGenericVehicleImageProp, imageUrlValue, categoryVal
|
||||||
});
|
});
|
||||||
|
|
||||||
//Mock props
|
//Mock props
|
||||||
mountOptions.propsData = { displayGenericVehicleImage: displayGenericVehicleImageProp };
|
mountOptions.propsData = {
|
||||||
|
displayGenericVehicleImage: displayGenericVehicleImageProp,
|
||||||
|
displayUnmatchedVehicleIconProp: displayUnmatchedVehicleIconProp,
|
||||||
|
};
|
||||||
mountOptions.mixins = [mockMixin];
|
mountOptions.mixins = [mockMixin];
|
||||||
const wrapper = shallowMount(vehicleBanner, mountOptions);
|
const wrapper = shallowMount(vehicleBanner, mountOptions);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,16 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
displayUnmatchedVehicleIcon: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
vehicleCategory: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
vehicleImageToDisplay() {
|
vehicleImageToDisplay() {
|
||||||
|
|
@ -29,7 +39,8 @@ export default {
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
this.$store.getters.vehicle.imageUrl === null ||
|
this.$store.getters.vehicle.imageUrl === null ||
|
||||||
this.$store.getters.vehicle.imageUrl === "NULL"
|
this.$store.getters.vehicle.imageUrl === "NULL" ||
|
||||||
|
this.displayUnmatchedVehicleIcon
|
||||||
) {
|
) {
|
||||||
return this.getUnmatchedVehicleIcon();
|
return this.getUnmatchedVehicleIcon();
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +68,8 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getUnmatchedVehicleIcon() {
|
getUnmatchedVehicleIcon() {
|
||||||
switch (this.$store.getters.vehicle.category) {
|
const category = this.vehicleCategory ?? this.$store.getters.vehicle.category;
|
||||||
|
switch (category) {
|
||||||
case this.vehicleCategories.CAR:
|
case this.vehicleCategories.CAR:
|
||||||
return this.carUnmatchedVehicleIcon;
|
return this.carUnmatchedVehicleIcon;
|
||||||
case this.vehicleCategories.SUV:
|
case this.vehicleCategories.SUV:
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@ export async function getPageToRouteExistingOrderTo(toRoute = {}, existingHerita
|
||||||
// Return that page, so that it can navigate like normal.
|
// Return that page, so that it can navigate like normal.
|
||||||
if (
|
if (
|
||||||
toRoute.query[queryStrings.FMG_PAGE] !== undefined &&
|
toRoute.query[queryStrings.FMG_PAGE] !== undefined &&
|
||||||
toRoute.query[queryStrings.FMG_PAGE] !== fmgPageValues.QUOTE &&
|
toRoute.query[queryStrings.FMG_PAGE] !== fmgPageValues.SERVICE_LOCATION &&
|
||||||
|
toRoute.query[queryStrings.FMG_PAGE] !== fmgPageValues.SCHEDULE &&
|
||||||
!isVinRelatedPage(toRoute)
|
!isVinRelatedPage(toRoute)
|
||||||
) {
|
) {
|
||||||
return overrideYmmsDirectionIfNeeded(toRoute);
|
return overrideYmmsDirectionIfNeeded(toRoute);
|
||||||
|
|
@ -112,6 +113,8 @@ async function getLatestPageForRedirection() {
|
||||||
fmgPageValues.CAPABILITY_QUESTIONS
|
fmgPageValues.CAPABILITY_QUESTIONS
|
||||||
);
|
);
|
||||||
const quoteComponent = await getLazyLoadedComponent(fmgPageValues.QUOTE);
|
const quoteComponent = await getLazyLoadedComponent(fmgPageValues.QUOTE);
|
||||||
|
const serviceLocationComponent = await getLazyLoadedComponent(fmgPageValues.SERVICE_LOCATION);
|
||||||
|
const scheduleComponent = await getLazyLoadedComponent(fmgPageValues.SCHEDULE);
|
||||||
|
|
||||||
const skipVin = await skipVinLookup();
|
const skipVin = await skipVinLookup();
|
||||||
|
|
||||||
|
|
@ -120,7 +123,11 @@ async function getLatestPageForRedirection() {
|
||||||
} else if (!estimateComponent.methods.arePagePrerequisitesValid()) {
|
} else if (!estimateComponent.methods.arePagePrerequisitesValid()) {
|
||||||
return fmgPageValues.VEHICLE_DAMAGE;
|
return fmgPageValues.VEHICLE_DAMAGE;
|
||||||
} else {
|
} else {
|
||||||
if (quoteComponent.methods.arePagePrerequisitesValid()) {
|
if (scheduleComponent.methods.arePagePrerequisitesValid()) {
|
||||||
|
return fmgPageValues.SCHEDULE;
|
||||||
|
} else if (serviceLocationComponent.methods.arePagePrerequisitesValid()) {
|
||||||
|
return fmgPageValues.SERVICE_LOCATION;
|
||||||
|
} else if (quoteComponent.methods.arePagePrerequisitesValid()) {
|
||||||
return fmgPageValues.QUOTE;
|
return fmgPageValues.QUOTE;
|
||||||
} else if (capabilityQuestionsComponent.methods.arePagePrerequisitesValid()) {
|
} else if (capabilityQuestionsComponent.methods.arePagePrerequisitesValid()) {
|
||||||
return fmgPageValues.CAPABILITY_QUESTIONS;
|
return fmgPageValues.CAPABILITY_QUESTIONS;
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ async function saveSessionHelper() {
|
||||||
storeActions.UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE,
|
storeActions.UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE,
|
||||||
{
|
{
|
||||||
referralNumber: savedSessionInfo.data.referralNumber?.toString(),
|
referralNumber: savedSessionInfo.data.referralNumber?.toString(),
|
||||||
|
referralSequenceNumber: savedSessionInfo.data.referralSequenceNumber,
|
||||||
referralCorrelationId: savedSessionInfo.data.referralCorrelationId,
|
referralCorrelationId: savedSessionInfo.data.referralCorrelationId,
|
||||||
referralDate: savedSessionInfo.data.referralDate,
|
referralDate: savedSessionInfo.data.referralDate,
|
||||||
parentAccountNumber: savedSessionInfo.data.parentAccountNumber?.toString(),
|
parentAccountNumber: savedSessionInfo.data.parentAccountNumber?.toString(),
|
||||||
|
|
|
||||||
10
src/helpers/querystring-helper.js
Normal file
10
src/helpers/querystring-helper.js
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
export function getQuerystringParameter(key) {
|
||||||
|
const queryString = window.location.search;
|
||||||
|
const urlParams = new URLSearchParams(queryString);
|
||||||
|
const lowerCaseParams = new URLSearchParams();
|
||||||
|
for (const [name, value] of urlParams) {
|
||||||
|
lowerCaseParams.append(name.toLowerCase(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lowerCaseParams.get(key) ? lowerCaseParams.get(key) : null;
|
||||||
|
}
|
||||||
|
|
@ -681,7 +681,6 @@ function setupMocks({
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
router: {
|
router: {
|
||||||
navigate: jest.fn(),
|
|
||||||
navigate: jest.fn(),
|
navigate: jest.fn(),
|
||||||
navigateWithSaving: jest.fn(),
|
navigateWithSaving: jest.fn(),
|
||||||
navigateWithoutSaving: jest.fn(),
|
navigateWithoutSaving: jest.fn(),
|
||||||
|
|
|
||||||
|
|
@ -323,10 +323,6 @@ export default {
|
||||||
registrationInfo: {
|
registrationInfo: {
|
||||||
firstName: this.customerQuestions.firstName,
|
firstName: this.customerQuestions.firstName,
|
||||||
lastName: this.customerQuestions.lastName,
|
lastName: this.customerQuestions.lastName,
|
||||||
address: this.customerQuestions.addressQuestions.streetAddress,
|
|
||||||
city: this.customerQuestions.addressQuestions.city,
|
|
||||||
state: resultMap.serviceZipValidationResponse.state,
|
|
||||||
zipCode: this.customerQuestions.addressQuestions.zipCode,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
validationRules="email-address-required|email-address-format" />
|
validationRules="email-address-required|email-address-format" />
|
||||||
<phoneNumberQuestion
|
<phoneNumberQuestion
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
cmsWidgetName="phoneNumberQuestionWidget"
|
cmsWidgetName="PhoneNumberQuestionWidget"
|
||||||
v-model="phoneNumber"
|
v-model="phoneNumber"
|
||||||
isRequired
|
isRequired
|
||||||
validationRules="phone-number-required" />
|
validationRules="phone-number-required" />
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,7 @@
|
||||||
<funnelSubHeader class="pb-4" cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader class="pb-4" cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
<div v-if="!skipVin">
|
<div v-if="!skipVin">
|
||||||
<alert
|
<div class="vinlookupquestion" v-html="this.VinLookupQuestionText"></div>
|
||||||
class="vinLookupMethodHeading"
|
|
||||||
cmsWidgetName="AlertVinLookupQuestion"
|
|
||||||
alertClass="" />
|
|
||||||
<buttonQuestion
|
<buttonQuestion
|
||||||
cmsWidgetName="VinLookupMethod"
|
cmsWidgetName="VinLookupMethod"
|
||||||
:answers="answersFromCms"
|
:answers="answersFromCms"
|
||||||
|
|
@ -333,6 +330,9 @@ export default {
|
||||||
alertInfo() {
|
alertInfo() {
|
||||||
return this.skipVinNotRepair ? "AlertQuoteVinOptional" : "AlertQuoteReady";
|
return this.skipVinNotRepair ? "AlertQuoteVinOptional" : "AlertQuoteReady";
|
||||||
},
|
},
|
||||||
|
VinLookupQuestionText() {
|
||||||
|
return this.getCmsContent("VinLookupQuestion", "BodyText");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
serviceZipCode() {
|
serviceZipCode() {
|
||||||
|
|
@ -355,13 +355,11 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.vinLookupMethodHeading p {
|
.vinlookupquestion p {
|
||||||
font-size: 14px;
|
margin-bottom: 0;
|
||||||
font-weight: 400;
|
}
|
||||||
color: $black;
|
.vinlookupquestion p:nth-child(2) {
|
||||||
strong {
|
font-size: 0.875rem;
|
||||||
font-size: 1rem;
|
margin-bottom: 1rem;
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -292,8 +292,6 @@ export default {
|
||||||
vehicleInfo: Object.assign(vinLookup.data.vehicle, { vin: vinLookup.data.vin }),
|
vehicleInfo: Object.assign(vinLookup.data.vehicle, { vin: vinLookup.data.vin }),
|
||||||
registrationInfo: {
|
registrationInfo: {
|
||||||
licensePlate: this.licensePlate,
|
licensePlate: this.licensePlate,
|
||||||
state: resultMap.registrationZipValidationResponse.state,
|
|
||||||
zipCode: this.registrationZipCode,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
|
|
|
||||||
|
|
@ -263,6 +263,9 @@ describe("quote.vue", () => {
|
||||||
payment: {
|
payment: {
|
||||||
isInsurance: null,
|
isInsurance: null,
|
||||||
},
|
},
|
||||||
|
serviceLocation: {
|
||||||
|
state: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
wrapper.vm.$route = { query: { isInsurance: "true" } };
|
wrapper.vm.$route = { query: { isInsurance: "true" } };
|
||||||
|
|
@ -290,6 +293,9 @@ describe("quote.vue", () => {
|
||||||
payment: {
|
payment: {
|
||||||
isInsurance: null,
|
isInsurance: null,
|
||||||
},
|
},
|
||||||
|
serviceLocation: {
|
||||||
|
state: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
wrapper.vm.$route = { query: { isInsurance: "false" } };
|
wrapper.vm.$route = { query: { isInsurance: "false" } };
|
||||||
|
|
@ -317,6 +323,9 @@ describe("quote.vue", () => {
|
||||||
payment: {
|
payment: {
|
||||||
isInsurance: true,
|
isInsurance: true,
|
||||||
},
|
},
|
||||||
|
serviceLocation: {
|
||||||
|
state: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// Ensure that query param isn't overriding selection
|
// Ensure that query param isn't overriding selection
|
||||||
|
|
@ -345,6 +354,9 @@ describe("quote.vue", () => {
|
||||||
payment: {
|
payment: {
|
||||||
isInsurance: false,
|
isInsurance: false,
|
||||||
},
|
},
|
||||||
|
serviceLocation: {
|
||||||
|
state: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// Ensure that query param isn't overriding selection
|
// Ensure that query param isn't overriding selection
|
||||||
|
|
@ -374,6 +386,9 @@ describe("quote.vue", () => {
|
||||||
payment: {
|
payment: {
|
||||||
isInsurance: null, // Ensure that previous selection isn't overriding selection
|
isInsurance: null, // Ensure that previous selection isn't overriding selection
|
||||||
},
|
},
|
||||||
|
serviceLocation: {
|
||||||
|
state: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
mockTierOnePrice = 200;
|
mockTierOnePrice = 200;
|
||||||
|
|
@ -404,6 +419,9 @@ describe("quote.vue", () => {
|
||||||
payment: {
|
payment: {
|
||||||
isInsurance: null, // Ensure that previous selection isn't overriding selection
|
isInsurance: null, // Ensure that previous selection isn't overriding selection
|
||||||
},
|
},
|
||||||
|
serviceLocation: {
|
||||||
|
state: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
mockTierOnePrice = 505;
|
mockTierOnePrice = 505;
|
||||||
|
|
@ -421,6 +439,33 @@ describe("quote.vue", () => {
|
||||||
//Assert
|
//Assert
|
||||||
expect(wrapper.vm.isInsuranceSelected).toBe(true);
|
expect(wrapper.vm.isInsuranceSelected).toBe(true);
|
||||||
});
|
});
|
||||||
|
test("Should default to insurence if user Service zip is from certain States", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
lineItems: {
|
||||||
|
glassParts: ["item", "item2"],
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: null,
|
||||||
|
},
|
||||||
|
serviceLocation: {
|
||||||
|
state: "AZ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
wrapper.vm.$route = { query: null };
|
||||||
|
//Act
|
||||||
|
await quote.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "quote" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isInsuranceSelected).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupMocks({ customMountOptions }) {
|
function setupMocks({ customMountOptions }) {
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ import { errorMessages } from "@/constants/error-messages";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, defineRule } from "vee-validate";
|
||||||
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||||
import { applicationConfig } from "@/constants/application-config";
|
import { applicationConfig } from "@/constants/application-config";
|
||||||
|
import { payWithInsuranceStates } from "@/constants/pay-with-insurance-states";
|
||||||
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -154,11 +154,18 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
getDefaultIsInsuranceSelectedValue(availableLineItems) {
|
getDefaultIsInsuranceSelectedValue(availableLineItems) {
|
||||||
|
const serviceLocationState = store.getters.order.serviceLocation.state;
|
||||||
// Override if coming back from QuoteDetails. Remove override after Quote release
|
// Override if coming back from QuoteDetails. Remove override after Quote release
|
||||||
const isInsuranceOverrideValue = this.$route.query?.isInsurance;
|
const isInsuranceOverrideValue = this.$route.query?.isInsurance;
|
||||||
|
|
||||||
const defaultIsInsuranceSelectedValue = this.$store.getters.order.payment.isInsurance;
|
const defaultIsInsuranceSelectedValue = this.$store.getters.order.payment.isInsurance;
|
||||||
if (isInsuranceOverrideValue != null) {
|
//Default to Insurance Tab if user Service zip is from certain States
|
||||||
|
if (
|
||||||
|
serviceLocationState != null &&
|
||||||
|
payWithInsuranceStates.find((item) => item === serviceLocationState)
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
else if (isInsuranceOverrideValue != null) {
|
||||||
return isInsuranceOverrideValue == "true";
|
return isInsuranceOverrideValue == "true";
|
||||||
} else if (defaultIsInsuranceSelectedValue != null) {
|
} else if (defaultIsInsuranceSelectedValue != null) {
|
||||||
return defaultIsInsuranceSelectedValue;
|
return defaultIsInsuranceSelectedValue;
|
||||||
|
|
|
||||||
|
|
@ -135,64 +135,9 @@ describe("service-package-question.vue", () => {
|
||||||
expectedModifiedAnswers[packageNameKey].tierThree
|
expectedModifiedAnswers[packageNameKey].tierThree
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it("should not select a default package if ANY glass part or supporting item has no prices", async () => {
|
it("should not select a default package if isInsurance is null", async () => {
|
||||||
// Note, only the first WSREPAIR item has a 0 for laborAmount, this is enough to not try and select a default package
|
// Note, only the first WSREPAIR item has a 0 for laborAmount, this is enough to not try and select a default package
|
||||||
const wrapper = setupMocks({
|
const wrapper = setupMocks({});
|
||||||
mountOptionsMockData: {
|
|
||||||
store: {
|
|
||||||
getters: {
|
|
||||||
lineItems: {
|
|
||||||
glassParts: [
|
|
||||||
{
|
|
||||||
partNumber: "FW02627GBYNOEE",
|
|
||||||
description: "solar, 3rd visor band",
|
|
||||||
color: "Green Tint, Blue Shade",
|
|
||||||
partType: "WINDSHIELD",
|
|
||||||
canSafeliteRecalibrate: false,
|
|
||||||
requiresRecalibration: false,
|
|
||||||
requiresCapabilityQuestions: false,
|
|
||||||
recalibrationType: null,
|
|
||||||
childParts: null,
|
|
||||||
laborAmount: 5.0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
supportingItems: [
|
|
||||||
{
|
|
||||||
partNumber: "SUPPLIES-REPAIR",
|
|
||||||
description: null,
|
|
||||||
partType: "REPAIR FEE",
|
|
||||||
laborAmount: 5.0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "WSREPAIR",
|
|
||||||
description: null,
|
|
||||||
partType: "REPAIR FEE",
|
|
||||||
laborAmount: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "WSREPAIR",
|
|
||||||
description: null,
|
|
||||||
partType: "REPAIR FEE",
|
|
||||||
laborAmount: 5.0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "WSREPAIR",
|
|
||||||
description: null,
|
|
||||||
partType: "REPAIR FEE",
|
|
||||||
laborAmount: 5.0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
order: {
|
|
||||||
damage: {
|
|
||||||
isRepair: false,
|
|
||||||
glassToReplace: [{ glassLocation: "Windshield" }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.setProps({ availableLineItems: null });
|
wrapper.setProps({ availableLineItems: null });
|
||||||
|
|
@ -202,59 +147,24 @@ describe("service-package-question.vue", () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.selectedPackageName).toBe(null);
|
expect(wrapper.vm.selectedPackageName).toBe(null);
|
||||||
});
|
});
|
||||||
it("should select a default package if ALL glass parts and supporting items have prices", async () => {
|
it("should select a default package if isInsurance is NOT null", async () => {
|
||||||
const wrapper = setupMocks({
|
const wrapper = setupMocks({
|
||||||
mountOptionsMockData: {
|
mountOptionsMockData: {
|
||||||
store: {
|
store: {
|
||||||
getters: {
|
getters: {
|
||||||
lineItems: {
|
|
||||||
glassParts: [
|
|
||||||
{
|
|
||||||
partNumber: "FW02627GBYNOEE",
|
|
||||||
description: "solar, 3rd visor band",
|
|
||||||
color: "Green Tint, Blue Shade",
|
|
||||||
partType: "WINDSHIELD",
|
|
||||||
canSafeliteRecalibrate: false,
|
|
||||||
requiresRecalibration: false,
|
|
||||||
requiresCapabilityQuestions: false,
|
|
||||||
recalibrationType: null,
|
|
||||||
childParts: null,
|
|
||||||
laborAmount: 5.0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
supportingItems: [
|
|
||||||
{
|
|
||||||
partNumber: "SUPPLIES-REPAIR",
|
|
||||||
description: null,
|
|
||||||
partType: "REPAIR FEE",
|
|
||||||
laborAmount: 5.0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "WSREPAIR",
|
|
||||||
description: null,
|
|
||||||
partType: "REPAIR FEE",
|
|
||||||
laborAmount: 5.0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "WSREPAIR",
|
|
||||||
description: null,
|
|
||||||
partType: "REPAIR FEE",
|
|
||||||
laborAmount: 5.0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "WSREPAIR",
|
|
||||||
description: null,
|
|
||||||
partType: "REPAIR FEE",
|
|
||||||
laborAmount: 5.0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
order: {
|
order: {
|
||||||
damage: {
|
damage: {
|
||||||
isRepair: false,
|
isRepair: false,
|
||||||
glassToReplace: [{ glassLocation: "Windshield" }],
|
glassToReplace: [{ glassLocation: "Windshield" }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
lineItems: {
|
||||||
|
vaps: [],
|
||||||
|
},
|
||||||
|
hasAnyNonWindshieldGlassParts: false,
|
||||||
|
payment: {
|
||||||
|
isInsurance: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -329,6 +239,9 @@ describe("service-package-question.vue", () => {
|
||||||
glassToReplace: [{ glassLocation: "Windshield" }],
|
glassToReplace: [{ glassLocation: "Windshield" }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -758,6 +671,9 @@ function setupMocks({ mountOptionsMockData, props = mockProps }) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hasAnyNonWindshieldGlassParts: false,
|
hasAnyNonWindshieldGlassParts: false,
|
||||||
|
payment: {
|
||||||
|
isInsurance: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ export default {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
availableLineItems() {
|
availableLineItems() {
|
||||||
if (this.allGlassPartsAndSupportingItemsHavePrices(this.$store.getters.lineItems)) {
|
if (this.$store.getters.payment.isInsurance != null) {
|
||||||
this.selectDefaultPackage();
|
this.selectDefaultPackage();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -196,30 +196,6 @@ export default {
|
||||||
vapsFromStore
|
vapsFromStore
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
allGlassPartsAndSupportingItemsHavePrices(lineItems) {
|
|
||||||
if (lineItems?.glassParts) {
|
|
||||||
for (let i = 0; i < lineItems.glassParts.length; i++) {
|
|
||||||
if (this.priceIsNullOrZero(lineItems.glassParts[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lineItems?.supportingItems) {
|
|
||||||
for (let i = 0; i < lineItems.supportingItems.length; i++) {
|
|
||||||
if (this.priceIsNullOrZero(lineItems.supportingItems[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
priceIsNullOrZero(lineItem) {
|
|
||||||
return (
|
|
||||||
(lineItem.kitPrice == null || lineItem.kitPrice == 0) &&
|
|
||||||
(lineItem.laborAmount == null || lineItem.laborAmount == 0) &&
|
|
||||||
(lineItem.sellingPrice == null || lineItem.sellingPrice == 0)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getVapsLineItemsForSelectedPackage(packageName) {
|
getVapsLineItemsForSelectedPackage(packageName) {
|
||||||
const packageContentTypes = getPackageContents(
|
const packageContentTypes = getPackageContents(
|
||||||
this.glassToReplace,
|
this.glassToReplace,
|
||||||
|
|
|
||||||
|
|
@ -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 };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
<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>
|
||||||
|
|
@ -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 };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<template>
|
||||||
|
<reviewBlock :customHeaderText="header" :content="displayContent" @edit-clicked="editClicked" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import reviewBlock from "@/layouts/review/review-block/review-block";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "customer-review",
|
||||||
|
props: {
|
||||||
|
cmsWidgetName: String,
|
||||||
|
customer: Object,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
editClicked() {
|
||||||
|
this.$emit("edit-clicked");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
displayContent() {
|
||||||
|
return [this.fullName, this.email, this.phoneNumber, this.smsOptIn];
|
||||||
|
},
|
||||||
|
header() {
|
||||||
|
return this.getCmsContent(this.cmsWidgetName, "HeaderText");
|
||||||
|
},
|
||||||
|
fullName() {
|
||||||
|
return `${this.customer?.firstName} ${this.customer?.lastName}`;
|
||||||
|
},
|
||||||
|
email() {
|
||||||
|
return this.customer?.emailAddress;
|
||||||
|
},
|
||||||
|
phoneNumber() {
|
||||||
|
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);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
reviewBlock,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
@ -76,12 +76,23 @@
|
||||||
cmsWidgetName="ScheduleWidget"
|
cmsWidgetName="ScheduleWidget"
|
||||||
:appointmentType="appointmentType"
|
:appointmentType="appointmentType"
|
||||||
@edit-clicked="editSchedule" />
|
@edit-clicked="editSchedule" />
|
||||||
|
|
||||||
|
<hr class="my-0" />
|
||||||
|
|
||||||
|
<customerReview
|
||||||
|
cmsWidgetName="CustomerReviewWidget"
|
||||||
|
:customer="customerInfo"
|
||||||
|
@edit-clicked="editCustomerDetails" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<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"
|
||||||
|
|
@ -102,6 +113,9 @@ import damageReview from "@/layouts/review/review-sections/damage-review/damage-
|
||||||
import servicePackageReview from "@/layouts/review/review-sections/service-package-review/service-package-review";
|
import servicePackageReview from "@/layouts/review/review-sections/service-package-review/service-package-review";
|
||||||
import serviceLocationReview from "@/layouts/review/review-sections/service-location-review/service-location-review";
|
import serviceLocationReview from "@/layouts/review/review-sections/service-location-review/service-location-review";
|
||||||
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 customerDetailsModalQuestion from "@/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.vue";
|
||||||
|
|
||||||
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";
|
||||||
|
|
@ -175,6 +189,9 @@ export default {
|
||||||
this.$route
|
this.$route
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
editCustomerDetails() {
|
||||||
|
this.$refs.customerDetailsModalQuestion.openModal();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
subHeaderTitle() {
|
subHeaderTitle() {
|
||||||
|
|
@ -201,8 +218,8 @@ export default {
|
||||||
appointmentType() {
|
appointmentType() {
|
||||||
return this.$store.getters.order.serviceLocation.appointmentType;
|
return this.$store.getters.order.serviceLocation.appointmentType;
|
||||||
},
|
},
|
||||||
exposeCms() {
|
customerInfo() {
|
||||||
return this.$root.cmsContentByWidget;
|
return this.$store.getters.order.customer;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -216,6 +233,8 @@ export default {
|
||||||
servicePackageReview,
|
servicePackageReview,
|
||||||
serviceLocationReview,
|
serviceLocationReview,
|
||||||
scheduleReview,
|
scheduleReview,
|
||||||
|
customerReview,
|
||||||
|
customerDetailsModalQuestion,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,77 @@
|
||||||
|
// Components
|
||||||
|
import schedule from "@/layouts/schedule/schedule.vue";
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount } from "@vue/test-utils";
|
||||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
import { applicationConfig } from "@/constants/application-config";
|
|
||||||
import { storeActions } from "@/constants/store-actions";
|
|
||||||
import schedule from "@/layouts/schedule/schedule.vue";
|
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
|
import router from "@/router";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
|
import baseMixin from "../../mixins/base-mixin";
|
||||||
|
|
||||||
jest.mock("@/store", () => ({
|
// Mock basemixin
|
||||||
commit: jest.fn(),
|
jest.mock("@/mixins/base-mixin.js", () => ({
|
||||||
dispatch: jest.fn(),
|
methods: {
|
||||||
|
dispatchStoreAction: jest.fn().mockImplementation((storeAction) => {
|
||||||
|
if (storeAction === "getShopTimeSlots") {
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
estimatedServiceMinutesMinimum: 90,
|
||||||
|
estimatedServiceMinutesMaximum: 120,
|
||||||
|
days: [
|
||||||
|
{
|
||||||
|
date: "2023-12-01",
|
||||||
|
timeSlots: [
|
||||||
|
{
|
||||||
|
id: "06747-01820-S-B*20424*7 AM",
|
||||||
|
startTime: "07:00",
|
||||||
|
endTime: "08:00",
|
||||||
|
offerPremium: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (storeAction === "getMobilePremiumFee") {
|
||||||
|
return Promise.resolve({
|
||||||
|
data: {
|
||||||
|
partNumber: "EARLY BIRD",
|
||||||
|
description: null,
|
||||||
|
partType: "EARLY BIRD",
|
||||||
|
laborAmount: 0,
|
||||||
|
sellingPrice: 14.99,
|
||||||
|
kitPrice: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (storeAction === "priceOrderItemsAndSaveServerData") {
|
||||||
|
return Promise.resolve([
|
||||||
|
{
|
||||||
|
partNumber: "EARLY BIRD",
|
||||||
|
description: null,
|
||||||
|
partType: "EARLY BIRD",
|
||||||
|
laborAmount: 0,
|
||||||
|
sellingPrice: 14.99,
|
||||||
|
kitPrice: 0,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if (storeAction === "saveSupportingItemsSuppressingStateResetting") {
|
||||||
|
return Promise.resolve([
|
||||||
|
{
|
||||||
|
partNumber: "EARLY BIRD",
|
||||||
|
description: null,
|
||||||
|
partType: "EARLY BIRD",
|
||||||
|
laborAmount: 0,
|
||||||
|
sellingPrice: 14.99,
|
||||||
|
kitPrice: 0,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Mock fetchCmsContentForPage
|
// Mock fetchCmsContentForPage
|
||||||
|
|
@ -18,50 +80,402 @@ jest.mock("@/helpers/cms-content-helper", () => ({
|
||||||
splitCopyOnCMSPlaceHolder: jest.fn(() => ["A", "B"]),
|
splitCopyOnCMSPlaceHolder: jest.fn(() => ["A", "B"]),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock(
|
beforeEach(() => {
|
||||||
"@/store",
|
jest.restoreAllMocks();
|
||||||
() => {
|
jest.clearAllMocks();
|
||||||
return {};
|
store.getters = {
|
||||||
},
|
order: {
|
||||||
{ virtual: true }
|
schedule: {
|
||||||
);
|
date: "2019-01-01",
|
||||||
|
startTime: "09:00",
|
||||||
store.getters = {
|
endTime: "10:00",
|
||||||
order: {
|
routeCode: "000",
|
||||||
schedule: {
|
},
|
||||||
date: "2020-01-01",
|
lineItems: {
|
||||||
|
glassParts: [
|
||||||
|
{
|
||||||
|
partNumber: "ABC123",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
supportingItems: [],
|
||||||
|
},
|
||||||
|
serviceLocation: {
|
||||||
|
appointmentType: "Inshop",
|
||||||
|
zipCode: "12345",
|
||||||
|
zipCodeCtu: "01234",
|
||||||
|
provider: {
|
||||||
|
providerNumber: "123",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
isRepair: false,
|
||||||
|
},
|
||||||
|
referralNumber: "1234567",
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: true,
|
||||||
},
|
},
|
||||||
lineItems: {
|
lineItems: {
|
||||||
glassParts: [],
|
glassParts: [],
|
||||||
supportingItems: [],
|
supportingItems: [],
|
||||||
},
|
},
|
||||||
serviceLocation: {
|
};
|
||||||
appointmentType: "Inshop",
|
});
|
||||||
},
|
afterEach(() => {
|
||||||
},
|
store.getters = {};
|
||||||
lineItems: {
|
jest.restoreAllMocks();
|
||||||
glassParts: [],
|
jest.clearAllMocks();
|
||||||
supportingItems: [],
|
});
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
describe("schedule.vue", () => {
|
describe("schedule.vue...", () => {
|
||||||
test("Should navigateWithoutSaving", async () => {
|
describe("initial load", () => {
|
||||||
//Arrange
|
test("should pass arePagePrerequisitesValid with a mobile order and no providerNumber", () => {
|
||||||
const { wrapper } = setupMocks({
|
//Arrange
|
||||||
customMountOptions: {
|
const { wrapper } = setupMocks({});
|
||||||
router: {
|
store.getters.order.serviceLocation.appointmentType = "Mobile";
|
||||||
navigateWithSaving: jest.fn(),
|
store.getters.order.serviceLocation.provider = null;
|
||||||
},
|
|
||||||
route: { schedule },
|
//Act
|
||||||
},
|
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(arePagePrerequisitesValid).toBe(true);
|
||||||
|
});
|
||||||
|
test("should pass arePagePrerequisitesValid with a inshop order and providerNumber", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(arePagePrerequisitesValid).toBe(true);
|
||||||
|
});
|
||||||
|
test("should fail arePagePrerequisitesValid with a replace with no glass parts", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
store.getters.order.lineItems.glassParts = [];
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const arePagePrerequisitesValid2 = await wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(arePagePrerequisitesValid2).toBe(false);
|
||||||
|
});
|
||||||
|
test("should fail arePagePrerequisitesValid without isInsurance", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
store.getters.payment.isInsurance = null;
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(arePagePrerequisitesValid).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should return newShopTimeSlots when getAvailableDatesMethod is called", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const newShopTimeSlots = await wrapper.vm.getAvailableDatesMethod(
|
||||||
|
"2023-01-01",
|
||||||
|
"2023-01-31"
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(newShopTimeSlots).toStrictEqual({
|
||||||
|
days: [
|
||||||
|
{
|
||||||
|
date: "2023-12-01",
|
||||||
|
timeSlots: [
|
||||||
|
{
|
||||||
|
endTime: "08:00",
|
||||||
|
id: "06747-01820-S-B*20424*7 AM",
|
||||||
|
offerPremium: false,
|
||||||
|
startTime: "07:00",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
estimatedServiceMinutesMinimum: 90,
|
||||||
|
estimatedServiceMinutesMaximum: 120,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should call API service in day ranges of 34 or less when getAvailableDatesMethod is called with large date ranges", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await wrapper.vm.getAvailableDates.call(
|
||||||
|
wrapper.vm,
|
||||||
|
"2023-01-01",
|
||||||
|
"2023-03-31",
|
||||||
|
"Inshop",
|
||||||
|
"123"
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalledTimes(3);
|
||||||
|
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(
|
||||||
|
"getShopTimeSlots",
|
||||||
|
expect.anything(),
|
||||||
|
expect.anything()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("beforeRouteEnter function... ", () => {
|
||||||
|
test("should call next() and call all functions within next", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [],
|
||||||
|
};
|
||||||
|
wrapper.vm.updateFooterButtonText = jest.fn();
|
||||||
|
const nextFunction = jest.fn((c) => {
|
||||||
|
c(wrapper.vm);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await schedule.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "schedule" } },
|
||||||
|
undefined,
|
||||||
|
nextFunction
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(nextFunction).toHaveBeenCalled();
|
||||||
|
expect(wrapper.vm.setCmsContent).toHaveBeenCalledWith("content");
|
||||||
|
expect(wrapper.vm.$refs.datePicker.initializeComponent).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
calendarViewDirection: "future",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(wrapper.vm.$refs.locationAlerts.initializeComponent).toHaveBeenCalled();
|
||||||
|
expect(wrapper.vm.selectableDatesData).toStrictEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
days: expect.any(Array),
|
||||||
|
estimatedServiceMinutesMaximum: expect.any(Number),
|
||||||
|
estimatedServiceMinutesMinimum: expect.any(Number),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(wrapper.vm.mobilePremiumAppointmentFee).toStrictEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
partNumber: expect.any(String),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(wrapper.vm.updateFooterButtonText).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("computed properties...", () => {
|
||||||
|
test("timeSlotsForSelectedDate should return timeslots if selected date is available", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [
|
||||||
|
{
|
||||||
|
date: "2022-11-11",
|
||||||
|
timeSlots: [
|
||||||
|
{
|
||||||
|
id: "1820I-01820-M-I*20425*AM",
|
||||||
|
startTime: "08:00",
|
||||||
|
endTime: "12:00",
|
||||||
|
offerPremium: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "1820I-01820-M-I*20425*PM",
|
||||||
|
startTime: "12:00",
|
||||||
|
endTime: "17:00",
|
||||||
|
offerPremium: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
wrapper.setData({
|
||||||
|
selectedDate: "2022-11-11",
|
||||||
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const testValue = wrapper.vm.timeSlotsForSelectedDate;
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(testValue).toStrictEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
date: "2022-11-11",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("timeSlotsForSelectedDate should be null if no date has been selected", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [
|
||||||
|
{
|
||||||
|
date: "2022-11-11",
|
||||||
|
timeSlots: [
|
||||||
|
{
|
||||||
|
id: "1820I-01820-M-I*20425*AM",
|
||||||
|
startTime: "08:00",
|
||||||
|
endTime: "12:00",
|
||||||
|
offerPremium: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "1820I-01820-M-I*20425*PM",
|
||||||
|
startTime: "12:00",
|
||||||
|
endTime: "17:00",
|
||||||
|
offerPremium: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
wrapper.setData({
|
||||||
|
selectedDate: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const testValue = wrapper.vm.timeSlotsForSelectedDate;
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(testValue).toBe(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("schedule page methods...", () => {
|
||||||
|
test("getServiceZipCtuCodeFromStore should return zipCodeCtu", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const testValue = wrapper.vm.getServiceZipCtuCodeFromStore();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(testValue).toStrictEqual("01234");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("openInshopTimeSlotsModal should trigger openModal method", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
//Act
|
||||||
|
wrapper.vm.openInshopTimeSlotsModal();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$refs.timeSlotModalQuestion.openModal).toBeCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getSelectedRouteCode should return schedule routeCode", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const testValue = wrapper.vm.getSelectedRouteCode();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(testValue).toStrictEqual("000");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("timeSlotModalClosed should null any selected date when there's no route code", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [],
|
||||||
|
};
|
||||||
|
wrapper.setData({
|
||||||
|
selectedDate: "1980-05-05",
|
||||||
|
});
|
||||||
|
wrapper.setData({
|
||||||
|
selectedTimeSlot: {
|
||||||
|
date: "2019-01-01",
|
||||||
|
startTime: "09:00",
|
||||||
|
endTime: "10:00",
|
||||||
|
routeCode: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
wrapper.vm.timeSlotModalClosed();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.selectedDate).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getDisplayTextForMilitaryTime should return the correctly formatted string", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [],
|
||||||
|
};
|
||||||
|
const timeInput1 = "15:00";
|
||||||
|
const timeInput2 = "15:30";
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const testOutput1 = wrapper.vm.getDisplayTextForMilitaryTime(timeInput1);
|
||||||
|
const testOutput2 = wrapper.vm.getDisplayTextForMilitaryTime(timeInput2);
|
||||||
|
const testOutput3 = wrapper.vm.getDisplayTextForMilitaryTime(timeInput1, true);
|
||||||
|
const testOutput4 = wrapper.vm.getDisplayTextForMilitaryTime(timeInput2, true);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(testOutput1).toBe("3:00 PM");
|
||||||
|
expect(testOutput2).toBe("3:30 PM");
|
||||||
|
expect(testOutput3).toBe("3 PM");
|
||||||
|
expect(testOutput4).toBe("3:30 PM");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getDisplayTextForMilitaryTime should return the correctly formatted string", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
wrapper.vm.selectableDatesData = {
|
||||||
|
days: [],
|
||||||
|
};
|
||||||
|
wrapper.vm.$router.navigateWithoutSaving = jest.fn();
|
||||||
|
wrapper.vm.$route = "testRoute";
|
||||||
|
|
||||||
|
//Act
|
||||||
|
wrapper.vm.backButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
|
||||||
|
"CLICKED_BACK",
|
||||||
|
"testRoute"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("forwardButtonAction should call route method navigateWithoutSaving", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||||
return {
|
return {
|
||||||
data: [],
|
data: [],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
wrapper.vm.$router.navigateWithSaving = jest.fn(() => {
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
await wrapper.vm.forwardButtonAction();
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
@ -69,136 +483,123 @@ describe("schedule.vue", () => {
|
||||||
//Assert
|
//Assert
|
||||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
|
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
test("should pass arePagePrerequisitesValid with a mobile order and no providerNumber", () => {
|
|
||||||
|
test("for mobile appts, updateSupportingItems should call store action to save supporting items", async () => {
|
||||||
//Arrange
|
//Arrange
|
||||||
|
store.getters.order.serviceLocation.appointmentType = "Mobile";
|
||||||
|
store.getters.lineItems.supportingItems = [
|
||||||
|
{
|
||||||
|
partNumber: "EARLY BIRD",
|
||||||
|
description: null,
|
||||||
|
partType: "EARLY BIRD",
|
||||||
|
laborAmount: 0,
|
||||||
|
sellingPrice: 0,
|
||||||
|
kitPrice: 0,
|
||||||
|
},
|
||||||
|
];
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
store.getters = {
|
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||||
order: {
|
return {
|
||||||
schedule: {
|
data: [],
|
||||||
date: "2020-01-01",
|
};
|
||||||
},
|
});
|
||||||
serviceLocation: {
|
wrapper.vm.mobilePremiumAppointmentFee = 14.99;
|
||||||
zipCode: "12345",
|
wrapper.setData({
|
||||||
zipCodeCtu: "value",
|
selectedTimeSlot: {
|
||||||
appointmentType: "Mobile",
|
date: "2019-01-01",
|
||||||
},
|
startTime: "09:00",
|
||||||
damage: {
|
endTime: "10:00",
|
||||||
isRepair: true,
|
routeCode: null,
|
||||||
},
|
isPremiumAppointment: true,
|
||||||
referralNumber: "1234567",
|
|
||||||
},
|
},
|
||||||
payment: {
|
});
|
||||||
isInsurance: true,
|
|
||||||
},
|
|
||||||
lineItems: {
|
|
||||||
supportingItems: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
//Act
|
||||||
|
await wrapper.vm.updateSupportingItems();
|
||||||
|
|
||||||
expect(arePagePrerequisitesValid).toBe(true);
|
//Assert
|
||||||
|
expect(wrapper.vm.dispatchStoreAction).toBeCalledWith(
|
||||||
|
"saveSupportingItemsSuppressingStateResetting",
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
partType: "EARLY BIRD",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
expect.anything()
|
||||||
|
);
|
||||||
});
|
});
|
||||||
test("should pass arePagePrerequisitesValid with a inshop order and providerNumber", () => {
|
|
||||||
|
test("for Inshop appts, updateSupportingItems should call store action to save supporting items WITHOUT the EARLY BIRD supporting item", async () => {
|
||||||
//Arrange
|
//Arrange
|
||||||
|
store.getters.order.serviceLocation.appointmentType = "Inshop";
|
||||||
|
store.getters.lineItems.supportingItems = [
|
||||||
|
{
|
||||||
|
partNumber: "EARLY BIRD",
|
||||||
|
description: null,
|
||||||
|
partType: "EARLY BIRD",
|
||||||
|
laborAmount: 0,
|
||||||
|
sellingPrice: 0,
|
||||||
|
kitPrice: 0,
|
||||||
|
},
|
||||||
|
];
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
store.getters = {
|
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||||
order: {
|
return {
|
||||||
schedule: {
|
data: [],
|
||||||
date: "2020-01-01",
|
};
|
||||||
},
|
});
|
||||||
serviceLocation: {
|
wrapper.vm.mobilePremiumAppointmentFee = 14.99;
|
||||||
zipCode: "12345",
|
wrapper.setData({
|
||||||
zipCodeCtu: "value",
|
selectedTimeSlot: {
|
||||||
appointmentType: "Inshop",
|
date: "2019-01-01",
|
||||||
provider: {
|
startTime: "09:00",
|
||||||
providerNumber: "5",
|
endTime: "10:00",
|
||||||
},
|
routeCode: null,
|
||||||
},
|
isPremiumAppointment: true,
|
||||||
damage: {
|
|
||||||
isRepair: true,
|
|
||||||
},
|
|
||||||
referralNumber: "1234567",
|
|
||||||
},
|
},
|
||||||
payment: {
|
});
|
||||||
isInsurance: true,
|
|
||||||
},
|
|
||||||
lineItems: {
|
|
||||||
supportingItems: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
//Act
|
||||||
|
await wrapper.vm.updateSupportingItems();
|
||||||
|
|
||||||
expect(arePagePrerequisitesValid).toBe(true);
|
//Assert
|
||||||
|
expect(wrapper.vm.dispatchStoreAction).toBeCalledWith(
|
||||||
|
"saveSupportingItemsSuppressingStateResetting",
|
||||||
|
expect.not.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
partType: "EARLY BIRD",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
expect.anything()
|
||||||
|
);
|
||||||
});
|
});
|
||||||
test("should fail arePagePrerequisitesValid with a replace with no glass parts", () => {
|
|
||||||
|
test("if no EARLY BIRD supporting item, then updateSupportingItems should NOT call store action", async () => {
|
||||||
//Arrange
|
//Arrange
|
||||||
|
store.getters.order.serviceLocation.appointmentType = "Mobile";
|
||||||
|
store.getters.lineItems.supportingItems = [];
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
store.getters = {
|
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||||
order: {
|
return {
|
||||||
schedule: {
|
data: [],
|
||||||
date: "2020-01-01",
|
};
|
||||||
},
|
});
|
||||||
serviceLocation: {
|
wrapper.vm.mobilePremiumAppointmentFee = 14.99;
|
||||||
zipCode: "12345",
|
wrapper.setData({
|
||||||
zipCodeCtu: "value",
|
selectedTimeSlot: {
|
||||||
appointmentType: "Inshop",
|
date: "2019-01-01",
|
||||||
provider: {
|
startTime: "09:00",
|
||||||
providerNumber: "5",
|
endTime: "10:00",
|
||||||
},
|
routeCode: null,
|
||||||
},
|
isPremiumAppointment: false,
|
||||||
damage: {
|
|
||||||
isRepair: false,
|
|
||||||
},
|
|
||||||
referralNumber: "1234567",
|
|
||||||
},
|
},
|
||||||
payment: {
|
});
|
||||||
isInsurance: true,
|
|
||||||
},
|
|
||||||
lineItems: {
|
|
||||||
supportingItems: [],
|
|
||||||
glassParts: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
//Act
|
||||||
|
await wrapper.vm.updateSupportingItems();
|
||||||
|
|
||||||
expect(arePagePrerequisitesValid).toBe(false);
|
//Assert
|
||||||
});
|
expect(wrapper.vm.dispatchStoreAction).not.toBeCalled();
|
||||||
test("should fail arePagePrerequisitesValid without isInsurance", () => {
|
|
||||||
//Arrange
|
|
||||||
const { wrapper } = setupMocks({});
|
|
||||||
store.getters = {
|
|
||||||
order: {
|
|
||||||
schedule: {
|
|
||||||
date: "2020-01-01",
|
|
||||||
},
|
|
||||||
serviceLocation: {
|
|
||||||
zipCode: "12345",
|
|
||||||
zipCodeCtu: "value",
|
|
||||||
appointmentType: "Inshop",
|
|
||||||
provider: {
|
|
||||||
providerNumber: "5",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
damage: {
|
|
||||||
isRepair: true,
|
|
||||||
},
|
|
||||||
referralNumber: "1234567",
|
|
||||||
},
|
|
||||||
payment: {
|
|
||||||
isInsurance: null,
|
|
||||||
},
|
|
||||||
lineItems: {
|
|
||||||
supportingItems: [],
|
|
||||||
glassParts: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
|
||||||
|
|
||||||
expect(arePagePrerequisitesValid).toBe(false);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -210,6 +611,7 @@ function setupMocks({ customMountOptions }) {
|
||||||
});
|
});
|
||||||
|
|
||||||
mountOptions.global.mocks["$store"] = store;
|
mountOptions.global.mocks["$store"] = store;
|
||||||
|
mountOptions.global.mocks["$router"] = router;
|
||||||
mountOptions["attachTo"] = document.body;
|
mountOptions["attachTo"] = document.body;
|
||||||
mountOptions.mixins = [
|
mountOptions.mixins = [
|
||||||
{
|
{
|
||||||
|
|
@ -223,6 +625,12 @@ function setupMocks({ customMountOptions }) {
|
||||||
];
|
];
|
||||||
|
|
||||||
const wrapper = shallowMount(schedule, mountOptions);
|
const wrapper = shallowMount(schedule, mountOptions);
|
||||||
|
|
||||||
wrapper.vm.setCmsContent = jest.fn();
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
|
wrapper.vm.$refs.datePicker.initializeComponent = jest.fn();
|
||||||
|
wrapper.vm.$refs.locationAlerts.initializeComponent = jest.fn();
|
||||||
|
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||||
|
wrapper.vm.$refs.timeSlotModalQuestion.openModal = jest.fn();
|
||||||
|
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
0
src/layouts/schedule/schedule.spec.js1
Normal file
0
src/layouts/schedule/schedule.spec.js1
Normal file
|
|
@ -320,6 +320,7 @@ export default {
|
||||||
);
|
);
|
||||||
return newShopTimeSlots;
|
return newShopTimeSlots;
|
||||||
},
|
},
|
||||||
|
getAvailableDates,
|
||||||
getServiceZipCtuCodeFromStore() {
|
getServiceZipCtuCodeFromStore() {
|
||||||
return store.getters.order.serviceLocation.zipCodeCtu;
|
return store.getters.order.serviceLocation.zipCodeCtu;
|
||||||
},
|
},
|
||||||
|
|
@ -338,12 +339,6 @@ export default {
|
||||||
getSupportingItems() {
|
getSupportingItems() {
|
||||||
return store.getters.lineItems.supportingItems;
|
return store.getters.lineItems.supportingItems;
|
||||||
},
|
},
|
||||||
isMobilePremiumFeeOnOrderInVuex() {
|
|
||||||
const supportingItemsFromVuex = store.getters.lineItems.supportingItems;
|
|
||||||
return !!supportingItemsFromVuex.filter(
|
|
||||||
(lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE
|
|
||||||
).length;
|
|
||||||
},
|
|
||||||
timeSlotModalClosed() {
|
timeSlotModalClosed() {
|
||||||
// Clear the selectedDate if no timeSlot has been selected
|
// Clear the selectedDate if no timeSlot has been selected
|
||||||
if (this.selectedTimeSlot.routeCode == null) {
|
if (this.selectedTimeSlot.routeCode == null) {
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ jest.mock("@/store", () => ({
|
||||||
damage: {
|
damage: {
|
||||||
glassToReplace: [],
|
glassToReplace: [],
|
||||||
},
|
},
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -134,7 +133,6 @@ describe("vehicle-damage.vue", () => {
|
||||||
getters: {
|
getters: {
|
||||||
vehicle: {},
|
vehicle: {},
|
||||||
payment: { insuranceCoverage: { isVerified: false } },
|
payment: { insuranceCoverage: { isVerified: false } },
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -177,7 +175,7 @@ describe("vehicle-damage.vue", () => {
|
||||||
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
||||||
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(
|
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(
|
||||||
storeActions.GET_DAMAGE_OPTIONS,
|
storeActions.GET_DAMAGE_OPTIONS,
|
||||||
{ carId: "C00000000", zipCode: "11111" }
|
{ carId: "C00000000" }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -243,7 +241,6 @@ describe("vehicle-damage.vue", () => {
|
||||||
getters: {
|
getters: {
|
||||||
vehicle: {},
|
vehicle: {},
|
||||||
payment: { insuranceCoverage: { isVerified: false } },
|
payment: { insuranceCoverage: { isVerified: false } },
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -273,7 +270,7 @@ describe("vehicle-damage.vue", () => {
|
||||||
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
||||||
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(
|
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(
|
||||||
storeActions.GET_DAMAGE_OPTIONS,
|
storeActions.GET_DAMAGE_OPTIONS,
|
||||||
{ carId: "C00000000", zipCode: "11111" }
|
{ carId: "C00000000" }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -526,7 +523,6 @@ describe("vehicle-damage.vue", () => {
|
||||||
eventBusItem: jest.fn(),
|
eventBusItem: jest.fn(),
|
||||||
damage: { glassToReplace: [{ glassLocation: damageLocation }] },
|
damage: { glassToReplace: [{ glassLocation: damageLocation }] },
|
||||||
isRepair: true,
|
isRepair: true,
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var glassSelections = wrapper.vm.getDamageLocationsFromStore();
|
var glassSelections = wrapper.vm.getDamageLocationsFromStore();
|
||||||
|
|
@ -604,7 +600,6 @@ describe("vehicle-damage.vue", () => {
|
||||||
isRepair: isRepair,
|
isRepair: isRepair,
|
||||||
numberOfChips: 2,
|
numberOfChips: 2,
|
||||||
},
|
},
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var windshieldSelections = wrapper.vm.getWindshieldOptionsFromStore();
|
var windshieldSelections = wrapper.vm.getWindshieldOptionsFromStore();
|
||||||
|
|
@ -641,7 +636,6 @@ describe("vehicle-damage.vue", () => {
|
||||||
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
|
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
|
||||||
},
|
},
|
||||||
isRepair: true,
|
isRepair: true,
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var glassSelections = wrapper.vm.getDriverSideReplaceOptionsFromStore();
|
var glassSelections = wrapper.vm.getDriverSideReplaceOptionsFromStore();
|
||||||
|
|
@ -678,7 +672,6 @@ describe("vehicle-damage.vue", () => {
|
||||||
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
|
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
|
||||||
},
|
},
|
||||||
isRepair: true,
|
isRepair: true,
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var glassSelections = wrapper.vm.getPassengerSideReplaceOptionsFromStore();
|
var glassSelections = wrapper.vm.getPassengerSideReplaceOptionsFromStore();
|
||||||
|
|
@ -713,7 +706,6 @@ describe("vehicle-damage.vue", () => {
|
||||||
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
|
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
|
||||||
},
|
},
|
||||||
isRepair: true,
|
isRepair: true,
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var glassSelections = wrapper.vm.getRearReplaceOptionsFromStore();
|
var glassSelections = wrapper.vm.getRearReplaceOptionsFromStore();
|
||||||
|
|
@ -746,7 +738,6 @@ describe("vehicle-damage.vue", () => {
|
||||||
getters: {
|
getters: {
|
||||||
vehicle: {},
|
vehicle: {},
|
||||||
payment: { insuranceCoverage: { isVerified: true } },
|
payment: { insuranceCoverage: { isVerified: true } },
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -787,7 +778,6 @@ function setupMocks({ pageHeaderWidgetHeaderText, mountOptionsMockData, funnelCo
|
||||||
isVerified: false,
|
isVerified: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
order: { serviceLocation: { zipCode: "11111" } },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,6 @@ import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import baseMixin from "@/mixins/base-mixin";
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
import { queryStrings } from "@/constants/query-strings";
|
|
||||||
// DEFINE VALIDATION RULES
|
// DEFINE VALIDATION RULES
|
||||||
defineRule("replace-options-required", required(errorMessages.REPLACE_OPTIONS_REQUIRED));
|
defineRule("replace-options-required", required(errorMessages.REPLACE_OPTIONS_REQUIRED));
|
||||||
|
|
||||||
|
|
@ -90,20 +89,10 @@ export default {
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
// Call APIs
|
// Call APIs
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
const queryString = window.location.search;
|
|
||||||
const urlParams = new URLSearchParams(queryString);
|
|
||||||
const lowerCaseParams = new URLSearchParams();
|
|
||||||
for (const [name, value] of urlParams) {
|
|
||||||
lowerCaseParams.append(name.toLowerCase(), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const zip = lowerCaseParams.get(queryStrings.ZIP_CODE)
|
|
||||||
? lowerCaseParams.get(queryStrings.ZIP_CODE)
|
|
||||||
: store.getters.order.serviceLocation.zipCode;
|
|
||||||
|
|
||||||
const damageOptionsPromise = baseMixin.methods.dispatchStoreAction(
|
const damageOptionsPromise = baseMixin.methods.dispatchStoreAction(
|
||||||
storeActions.GET_DAMAGE_OPTIONS,
|
storeActions.GET_DAMAGE_OPTIONS,
|
||||||
{ carId: store.getters.vehicle.carId, zipCode: zip }
|
{ carId: store.getters.vehicle.carId }
|
||||||
);
|
);
|
||||||
|
|
||||||
// Settle promises and get results
|
// Settle promises and get results
|
||||||
|
|
@ -146,7 +135,6 @@ export default {
|
||||||
},
|
},
|
||||||
selectedWindshieldOptions: this.getWindshieldOptionsFromStore(),
|
selectedWindshieldOptions: this.getWindshieldOptionsFromStore(),
|
||||||
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore(),
|
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore(),
|
||||||
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -169,18 +157,6 @@ export default {
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this.serviceZipCode) {
|
|
||||||
this.pushEventToGA(
|
|
||||||
this.GaCategories.FUNNEL_ENTRY,
|
|
||||||
this.GaActions.ZIP_CODE_PROVIDED,
|
|
||||||
this.serviceZipCode,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getZipFromStore() {
|
|
||||||
return this.$store.getters.order.serviceLocation.zipCode;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,9 @@
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
:displayGenericVehicleImage="displayGeneric"
|
:displayGenericVehicleImage="displayGeneric"
|
||||||
:displayVehicleImage="vehicle.imageUrl"
|
:displayVehicleImage="imageUrl"
|
||||||
|
:vehicleCategory="category"
|
||||||
|
:displayUnmatchedVehicleIcon="unmatchedVehicleIcon"
|
||||||
class="mt-5 mb-3"
|
class="mt-5 mb-3"
|
||||||
ref="banner" />
|
ref="banner" />
|
||||||
|
|
||||||
|
|
@ -110,17 +112,17 @@ export default {
|
||||||
selectedMake: this.selectedMakefromStore(),
|
selectedMake: this.selectedMakefromStore(),
|
||||||
selectedModel: this.selectedModelfromStore(),
|
selectedModel: this.selectedModelfromStore(),
|
||||||
selectedStyle: this.selectedStylefromStore(),
|
selectedStyle: this.selectedStylefromStore(),
|
||||||
vehicle: {
|
carId: null,
|
||||||
carId: null,
|
category: null,
|
||||||
category: null,
|
imageUrl: null,
|
||||||
imageUrl: null,
|
imageVifNumber: null,
|
||||||
imageVifNumber: null,
|
imageVifColor: null,
|
||||||
imageVifColor: null,
|
|
||||||
},
|
|
||||||
yearOptions: [],
|
yearOptions: [],
|
||||||
makeOptions: [],
|
makeOptions: [],
|
||||||
modelOptions: [],
|
modelOptions: [],
|
||||||
styleOptions: [],
|
styleOptions: [],
|
||||||
|
displayGeneric: this.displayGenericFromStore(),
|
||||||
|
unmatchedVehicleIcon: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -279,7 +281,18 @@ export default {
|
||||||
this.selectedModel,
|
this.selectedModel,
|
||||||
style
|
style
|
||||||
);
|
);
|
||||||
this.vehicle = result?.data;
|
this.carId = result?.data.carId;
|
||||||
|
this.category = result?.data.category;
|
||||||
|
this.imageUrl = result?.data.imageUrl;
|
||||||
|
this.imageVifNumber = result?.data.imageVifNumber;
|
||||||
|
this.imageVifColor = result?.data.imageVifColor;
|
||||||
|
if (this.imageUrl == null) {
|
||||||
|
this.displayGeneric = false;
|
||||||
|
this.unmatchedVehicleIcon = true;
|
||||||
|
} else this.unmatchedVehicleIcon = false;
|
||||||
|
} else {
|
||||||
|
this.imageUrl = null;
|
||||||
|
this.displayGeneric = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -293,6 +306,15 @@ export default {
|
||||||
style: style,
|
style: style,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
displayGenericFromStore() {
|
||||||
|
if (store.getters.vehicle.imageUrl !== null) return false;
|
||||||
|
else if (
|
||||||
|
store.getters.vehicle.imageUrl === null &&
|
||||||
|
store.getters.vehicle.carId !== null
|
||||||
|
)
|
||||||
|
return false;
|
||||||
|
else return true;
|
||||||
|
},
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
@ -305,7 +327,11 @@ export default {
|
||||||
make: this.selectedMake,
|
make: this.selectedMake,
|
||||||
model: this.selectedModel,
|
model: this.selectedModel,
|
||||||
style: this.selectedStyle,
|
style: this.selectedStyle,
|
||||||
vehicle: this.vehicle,
|
carId: this.carId,
|
||||||
|
category: this.category,
|
||||||
|
imageUrl: this.imageUrl,
|
||||||
|
imageVifNumber: this.imageVifNumber,
|
||||||
|
imageVifColor: this.imageVifColor,
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
@ -353,12 +379,6 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
|
||||||
displayGeneric() {
|
|
||||||
return !this.selectedStyle;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
funnelFooter,
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ export default {
|
||||||
event: pageEvent,
|
event: pageEvent,
|
||||||
shouldUseSessionId: false,
|
shouldUseSessionId: false,
|
||||||
experimentsForUser: store.getters.applicationUser.experiments,
|
experimentsForUser: store.getters.applicationUser.experiments,
|
||||||
|
referralSequenceNumber: store.getters.order.referralSequenceNumber,
|
||||||
|
parentAccountNumber: store.getters.order.payment.parentAccountNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false);
|
baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false);
|
||||||
|
|
@ -57,6 +59,8 @@ export default {
|
||||||
value: value,
|
value: value,
|
||||||
shouldUseSessionId: false,
|
shouldUseSessionId: false,
|
||||||
experimentsForUser: store.getters.applicationUser.experiments,
|
experimentsForUser: store.getters.applicationUser.experiments,
|
||||||
|
referralSequenceNumber: store.getters.order.referralSequenceNumber,
|
||||||
|
parentAccountNumber: store.getters.order.payment.parentAccountNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
baseMixin.methods.dispatchStoreAction(storeActions.LOG_CUSTOM_EVENT, payload, false);
|
baseMixin.methods.dispatchStoreAction(storeActions.LOG_CUSTOM_EVENT, payload, false);
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,6 @@ import { applicationConfig } from "../constants/application-config";
|
||||||
import review from "@/layouts/review/review";
|
import review from "@/layouts/review/review";
|
||||||
import paymentMethod from "@/layouts/payment-method/payment-method";
|
import paymentMethod from "@/layouts/payment-method/payment-method";
|
||||||
const routes = [
|
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.
|
path: "/payment-method", // This is a temporary route for testing.
|
||||||
name: "payment-method",
|
name: "payment-method",
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||||
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper.js";
|
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper.js";
|
||||||
import { deepEqual } from "@/helpers/object-helper";
|
import { deepEqual } from "@/helpers/object-helper";
|
||||||
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
|
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
|
||||||
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||||
|
import { queryStrings } from "@/constants/query-strings";
|
||||||
import { partTypeStrings } from "@/constants/part-type-strings";
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
import {
|
import {
|
||||||
convertDateStringToDate,
|
convertDateStringToDate,
|
||||||
|
|
@ -37,12 +39,6 @@ const getDefaultState = () => {
|
||||||
imageColor: null,
|
imageColor: null,
|
||||||
registration: {
|
registration: {
|
||||||
licensePlate: null,
|
licensePlate: null,
|
||||||
address: null,
|
|
||||||
city: null,
|
|
||||||
state: null,
|
|
||||||
zipCode: null,
|
|
||||||
firstName: null,
|
|
||||||
lastName: null,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
serviceLocation: {
|
serviceLocation: {
|
||||||
|
|
@ -104,6 +100,7 @@ const getDefaultState = () => {
|
||||||
jobMinMinutes: null,
|
jobMinMinutes: null,
|
||||||
},
|
},
|
||||||
referralNumber: null,
|
referralNumber: null,
|
||||||
|
referralSequenceNumber: null,
|
||||||
referralDate: null,
|
referralDate: null,
|
||||||
referralCorrelationId: null,
|
referralCorrelationId: null,
|
||||||
eon: null,
|
eon: null,
|
||||||
|
|
@ -196,6 +193,9 @@ export const mutations = {
|
||||||
updateReferralNumber(state, referralNumber) {
|
updateReferralNumber(state, referralNumber) {
|
||||||
state.order.referralNumber = referralNumber;
|
state.order.referralNumber = referralNumber;
|
||||||
},
|
},
|
||||||
|
updateReferralSequenceNumber(state, referralSequenceNumber) {
|
||||||
|
state.order.referralSequenceNumber = referralSequenceNumber;
|
||||||
|
},
|
||||||
updateReferralDate(state, referralDate) {
|
updateReferralDate(state, referralDate) {
|
||||||
state.order.referralDate = referralDate;
|
state.order.referralDate = referralDate;
|
||||||
},
|
},
|
||||||
|
|
@ -211,27 +211,6 @@ export const mutations = {
|
||||||
updateInsuranceVerifiedStatus(state, isVerified) {
|
updateInsuranceVerifiedStatus(state, isVerified) {
|
||||||
state.order.payment.insuranceCoverage.isVerified = isVerified;
|
state.order.payment.insuranceCoverage.isVerified = isVerified;
|
||||||
},
|
},
|
||||||
updateRegistrationLicensePlate(state, licensePlate) {
|
|
||||||
state.order.vehicle.registration.licensePlate = licensePlate;
|
|
||||||
},
|
|
||||||
updateRegistrationAddress(state, registrationAddress) {
|
|
||||||
state.order.vehicle.registration.address = registrationAddress;
|
|
||||||
},
|
|
||||||
updateRegistrationCity(state, registrationCity) {
|
|
||||||
state.order.vehicle.registration.city = registrationCity;
|
|
||||||
},
|
|
||||||
updateRegistrationState(state, registrationState) {
|
|
||||||
state.order.vehicle.registration.state = registrationState;
|
|
||||||
},
|
|
||||||
updateRegistrationZipCode(state, registrationZipCode) {
|
|
||||||
state.order.vehicle.registration.zipCode = registrationZipCode;
|
|
||||||
},
|
|
||||||
updateRegistrationFirstName(state, firstName) {
|
|
||||||
state.order.vehicle.registration.firstName = firstName;
|
|
||||||
},
|
|
||||||
updateRegistrationLastName(state, lastName) {
|
|
||||||
state.order.vehicle.registration.lastName = lastName;
|
|
||||||
},
|
|
||||||
updateCustomerEmailAddress(state, customerEmailAddress) {
|
updateCustomerEmailAddress(state, customerEmailAddress) {
|
||||||
state.order.customer.emailAddress = customerEmailAddress;
|
state.order.customer.emailAddress = customerEmailAddress;
|
||||||
},
|
},
|
||||||
|
|
@ -352,12 +331,8 @@ export const mutations = {
|
||||||
},
|
},
|
||||||
resetRegistrationState(state) {
|
resetRegistrationState(state) {
|
||||||
state.order.vehicle.registration.licensePlate = null;
|
state.order.vehicle.registration.licensePlate = null;
|
||||||
state.order.vehicle.registration.address = null;
|
state.order.customer.firstName = null;
|
||||||
state.order.vehicle.registration.city = null;
|
state.order.customer.lastName = null;
|
||||||
state.order.vehicle.registration.state = null;
|
|
||||||
state.order.vehicle.registration.zipCode = null;
|
|
||||||
state.order.vehicle.registration.firstName = null;
|
|
||||||
state.order.vehicle.registration.lastName = null;
|
|
||||||
},
|
},
|
||||||
resetGlassPartsState(state) {
|
resetGlassPartsState(state) {
|
||||||
state.order.lineItems.glassParts = null;
|
state.order.lineItems.glassParts = null;
|
||||||
|
|
@ -419,6 +394,7 @@ export const mutations = {
|
||||||
// Misc Mutations
|
// Misc Mutations
|
||||||
updateStateWithOrderInformation(state, sessionInformation) {
|
updateStateWithOrderInformation(state, sessionInformation) {
|
||||||
state.order.referralNumber = sessionInformation.order.referralNumber;
|
state.order.referralNumber = sessionInformation.order.referralNumber;
|
||||||
|
state.order.referralSequenceNumber = sessionInformation.order.referralSequenceNumber;
|
||||||
state.order.referralDate = sessionInformation.order.referralDate;
|
state.order.referralDate = sessionInformation.order.referralDate;
|
||||||
state.order.referralCorrelationId = sessionInformation.order.referralCorrelationId;
|
state.order.referralCorrelationId = sessionInformation.order.referralCorrelationId;
|
||||||
state.order.eon = sessionInformation.order.eon;
|
state.order.eon = sessionInformation.order.eon;
|
||||||
|
|
@ -500,7 +476,7 @@ export const mutations = {
|
||||||
state.order.customer.emailAddress = sessionInformation.order.customer.emailAddress;
|
state.order.customer.emailAddress = sessionInformation.order.customer.emailAddress;
|
||||||
state.order.customer.firstName = sessionInformation.order.customer.firstName;
|
state.order.customer.firstName = sessionInformation.order.customer.firstName;
|
||||||
state.order.customer.lastName = sessionInformation.order.customer.lastName;
|
state.order.customer.lastName = sessionInformation.order.customer.lastName;
|
||||||
state.order.customer.phoneNumber = sessionInformation.order.customer.phoneNumber;
|
state.order.customer.phoneNumber = sessionInformation.order.customer.servicePhoneNumber;
|
||||||
state.order.customer.isSmsOptIn = sessionInformation.order.customer.isSmsOptIn;
|
state.order.customer.isSmsOptIn = sessionInformation.order.customer.isSmsOptIn;
|
||||||
|
|
||||||
state.order.existingPromoCode = sessionInformation.order.existingPromoCode;
|
state.order.existingPromoCode = sessionInformation.order.existingPromoCode;
|
||||||
|
|
@ -787,12 +763,13 @@ export const actions = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getDamageOptions(context, { carId, zipCode }) {
|
getDamageOptions(context, { carId }) {
|
||||||
return globalMethods.callHttpClient({
|
return globalMethods.callHttpClient({
|
||||||
methods: endpoints.GetDamageOptions.method,
|
methods: endpoints.GetDamageOptions.method,
|
||||||
endpoint: `${endpoints.GetDamageOptions.url}/${carId}`,
|
endpoint: `${endpoints.GetDamageOptions.url}/${carId}`,
|
||||||
payload: {},
|
payload: {},
|
||||||
additionalSuccessEventDataHandler: (response) => "QueryStringZip: " + zipCode,
|
additionalSuccessEventDataHandler: (response) =>
|
||||||
|
"QueryStringZip: " + getQuerystringParameter(queryStrings.ZIP_CODE),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -908,6 +885,7 @@ export const actions = {
|
||||||
context,
|
context,
|
||||||
{
|
{
|
||||||
referralNumber,
|
referralNumber,
|
||||||
|
referralSequenceNumber,
|
||||||
referralDate,
|
referralDate,
|
||||||
referralCorrelationId,
|
referralCorrelationId,
|
||||||
eon,
|
eon,
|
||||||
|
|
@ -917,6 +895,7 @@ export const actions = {
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
context.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber);
|
context.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber);
|
||||||
|
context.commit(storeMutations.UPDATE_REFERRAL_SEQUENCE_NUMBER, referralSequenceNumber);
|
||||||
context.commit(storeMutations.UPDATE_REFERRAL_DATE, referralDate);
|
context.commit(storeMutations.UPDATE_REFERRAL_DATE, referralDate);
|
||||||
context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId);
|
context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId);
|
||||||
context.commit(storeMutations.UPDATE_EON, eon);
|
context.commit(storeMutations.UPDATE_EON, eon);
|
||||||
|
|
@ -936,6 +915,8 @@ export const actions = {
|
||||||
event,
|
event,
|
||||||
shouldUseSessionId,
|
shouldUseSessionId,
|
||||||
experimentsForUser,
|
experimentsForUser,
|
||||||
|
referralSequenceNumber,
|
||||||
|
parentAccountNumber,
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
var payload = {
|
var payload = {
|
||||||
|
|
@ -948,6 +929,8 @@ export const actions = {
|
||||||
event: event,
|
event: event,
|
||||||
shouldUseSessionId: shouldUseSessionId,
|
shouldUseSessionId: shouldUseSessionId,
|
||||||
experimentsForUser: experimentsForUser,
|
experimentsForUser: experimentsForUser,
|
||||||
|
referralSequenceNumber: referralSequenceNumber,
|
||||||
|
parentAccountNumber: parentAccountNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
return globalMethods
|
return globalMethods
|
||||||
|
|
@ -980,6 +963,8 @@ export const actions = {
|
||||||
value,
|
value,
|
||||||
shouldUseSessionId,
|
shouldUseSessionId,
|
||||||
experimentsForUser,
|
experimentsForUser,
|
||||||
|
referralSequenceNumber,
|
||||||
|
parentAccountNumber,
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
var payload = {
|
var payload = {
|
||||||
|
|
@ -994,6 +979,8 @@ export const actions = {
|
||||||
value: value,
|
value: value,
|
||||||
shouldUseSessionId: shouldUseSessionId,
|
shouldUseSessionId: shouldUseSessionId,
|
||||||
experimentsForUser: experimentsForUser,
|
experimentsForUser: experimentsForUser,
|
||||||
|
referralSequenceNumber: referralSequenceNumber,
|
||||||
|
parentAccountNumber: parentAccountNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
return globalMethods
|
return globalMethods
|
||||||
|
|
@ -1443,7 +1430,7 @@ export const actions = {
|
||||||
firstName: order.customer.firstName,
|
firstName: order.customer.firstName,
|
||||||
lastName: order.customer.lastName,
|
lastName: order.customer.lastName,
|
||||||
isSmsOptIn: order.customer.isSmsOptIn,
|
isSmsOptIn: order.customer.isSmsOptIn,
|
||||||
phoneNumber: order.customer.phoneNumber,
|
servicePhoneNumber: order.customer.phoneNumber,
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
numberOfChips: damage.numberOfChips,
|
numberOfChips: damage.numberOfChips,
|
||||||
|
|
@ -1463,7 +1450,7 @@ export const actions = {
|
||||||
InsuranceCoverage: {
|
InsuranceCoverage: {
|
||||||
isVerified: order.payment.insuranceCoverage.isVerified ?? false,
|
isVerified: order.payment.insuranceCoverage.isVerified ?? false,
|
||||||
},
|
},
|
||||||
isInsurance: order.payment.isInsurance ?? false,
|
isInsurance: order.payment.isInsurance,
|
||||||
parentAccountNumber: order.payment.parentAccountNumber,
|
parentAccountNumber: order.payment.parentAccountNumber,
|
||||||
},
|
},
|
||||||
serviceLocation: {
|
serviceLocation: {
|
||||||
|
|
@ -1499,8 +1486,8 @@ export const actions = {
|
||||||
existingPromoCode: null,
|
existingPromoCode: null,
|
||||||
referralCorrelationId: order.referralCorrelationId,
|
referralCorrelationId: order.referralCorrelationId,
|
||||||
referralDate: order.referralDate,
|
referralDate: order.referralDate,
|
||||||
referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place
|
referralNumber: order.referralNumber?.toString(),
|
||||||
referralSequenceNumber: order.referralNumber?.toString(), // TODO Pass the referralSequence number once insurance flow creates it
|
referralSequenceNumber: order.referralSequenceNumber,
|
||||||
eon: order.eon,
|
eon: order.eon,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -1679,12 +1666,8 @@ export const actions = {
|
||||||
) {
|
) {
|
||||||
//Reset dependent state when changing
|
//Reset dependent state when changing
|
||||||
if (
|
if (
|
||||||
registrationInfo?.address !== context.state.order.vehicle.registration?.address ||
|
registrationInfo?.firstName !== context.state.order.customer?.firstName ||
|
||||||
registrationInfo?.city !== context.state.order.vehicle.registration?.city ||
|
registrationInfo?.lastName !== context.state.order.customer?.lastName
|
||||||
registrationInfo?.state !== context.state.order.vehicle.registration?.state ||
|
|
||||||
registrationInfo?.zipCode !== context.state.order.vehicle.registration?.zipCode ||
|
|
||||||
registrationInfo?.firstName !== context.state.order.vehicle.registration?.firstName ||
|
|
||||||
registrationInfo?.lastName !== context.state.order.vehicle.registration?.lastName
|
|
||||||
) {
|
) {
|
||||||
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
|
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
|
||||||
|
|
||||||
|
|
@ -2015,12 +1998,6 @@ export const actions = {
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
context.state.order.vehicle.make.toLowerCase() === "ford" &&
|
|
||||||
context.state.order.vehicle.year >= 2018
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (
|
if (
|
||||||
context.state.order.vehicle.make.toLowerCase() === "bmw" &&
|
context.state.order.vehicle.make.toLowerCase() === "bmw" &&
|
||||||
context.state.order.vehicle.year <= 2017
|
context.state.order.vehicle.year <= 2017
|
||||||
|
|
|
||||||
|
|
@ -819,6 +819,7 @@ describe("Actions", () => {
|
||||||
// Act
|
// Act
|
||||||
actions.updateStoreWithSaveSessionResponse(context, {
|
actions.updateStoreWithSaveSessionResponse(context, {
|
||||||
referralNumber: "123",
|
referralNumber: "123",
|
||||||
|
referralSequenceNumber: 123,
|
||||||
referralDate: new Date().toUTCString(),
|
referralDate: new Date().toUTCString(),
|
||||||
referralCorrelationId: "xxx-xxx-xxx",
|
referralCorrelationId: "xxx-xxx-xxx",
|
||||||
parentAccountNumber: "167132",
|
parentAccountNumber: "167132",
|
||||||
|
|
@ -1551,7 +1552,7 @@ describe("Actions", () => {
|
||||||
isCarIdDifferent: true,
|
isCarIdDifferent: true,
|
||||||
isSelectedGlassAvailableForVehicle: false,
|
isSelectedGlassAvailableForVehicle: false,
|
||||||
vehicleInfo: { carId: "C010101", vin: "XXXXX" },
|
vehicleInfo: { carId: "C010101", vin: "XXXXX" },
|
||||||
registrationInfo: { zipCode: "80020", address: "123 Marys Ave" },
|
registrationInfo: { firstName: "abc", lastName: "123" },
|
||||||
serviceLocationInfo: { state: "CO" },
|
serviceLocationInfo: { state: "CO" },
|
||||||
customerEmail: "test@safelite.com",
|
customerEmail: "test@safelite.com",
|
||||||
};
|
};
|
||||||
|
|
@ -1599,14 +1600,20 @@ describe("Actions", () => {
|
||||||
make: "Honda",
|
make: "Honda",
|
||||||
model: "Civic",
|
model: "Civic",
|
||||||
style: "Sedan",
|
style: "Sedan",
|
||||||
vehicle: {
|
carId: "C00000000",
|
||||||
carId: "C00000000",
|
category: "CAR",
|
||||||
category: "CAR",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
actions.saveVehicle(context, payload);
|
actions.saveVehicle(context, payload);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
|
expect(dispatch).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
|
||||||
|
);
|
||||||
|
expect(dispatch).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
|
||||||
|
);
|
||||||
if (context.state.order.vehicle.year !== payload.year) {
|
if (context.state.order.vehicle.year !== payload.year) {
|
||||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_YEAR, payload.year);
|
expect(commit).toBeCalledWith(storeMutations.UPDATE_YEAR, payload.year);
|
||||||
}
|
}
|
||||||
|
|
@ -1619,8 +1626,8 @@ describe("Actions", () => {
|
||||||
if (context.state.order.vehicle.style !== payload.style) {
|
if (context.state.order.vehicle.style !== payload.style) {
|
||||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, payload.style);
|
expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, payload.style);
|
||||||
}
|
}
|
||||||
context.commit(storeMutations.UPDATE_CAR_ID, payload.vehicle.carId);
|
context.commit(storeMutations.UPDATE_CAR_ID, payload.carId);
|
||||||
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, payload.vehicle.category);
|
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, payload.category);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("saveVehicleDamage, should wipe out damage if different", () => {
|
it("saveVehicleDamage, should wipe out damage if different", () => {
|
||||||
|
|
@ -3159,8 +3166,6 @@ describe("Getters", () => {
|
||||||
describe("isVinOptionalVehicle", () => {
|
describe("isVinOptionalVehicle", () => {
|
||||||
const testVehicles = [
|
const testVehicles = [
|
||||||
["2017", "acura", false],
|
["2017", "acura", false],
|
||||||
["2017", "ford", false],
|
|
||||||
["2018", "ford", true],
|
|
||||||
["2018", "bmw", false],
|
["2018", "bmw", false],
|
||||||
["2017", "bmw", true],
|
["2017", "bmw", true],
|
||||||
["2016", "bmw", true],
|
["2016", "bmw", true],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue