Merge pull request #385 from Safelite/feature/CSR-414-V2

estimate page
This commit is contained in:
DonielleAtSafelite 2022-05-03 15:20:15 -04:00 committed by GitHub
commit 8ac9309b66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 185 additions and 188 deletions

View file

@ -21,6 +21,7 @@ const errorMessages = {
SERVICE_ZIP_FORMAT: "Please enter a valid Service ZIP",
VIN_REQUIRED: "Please enter your VIN",
VIN_FORMAT: "Please enter a valid VIN",
OPTION_REQUIRED: "Please select an option",
};
export { errorMessages };

View file

@ -22,7 +22,7 @@ const storeMutations = {
UPDATE_REGISTRATION_ZIP_CODE: "updateRegistrationZipCode",
UPDATE_REGISTRATION_FIRST_NAME: "updateRegistrationFirstName",
UPDATE_REGISTRATION_LAST_NAME: "updateRegistrationLastName",
UPDATE_SERVICE_LOCATION_ZIP: "updateServiceLocationZip",
UPDATE_SERVICE_LOCATION_ZIP_CODE: "updateServiceLocationZipCode",
UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress",
// ORDER MUTATIONS

View file

@ -0,0 +1,7 @@
const vinLookupMethodSelections = {
MANUALVIN: "ManualVin",
LICENSEPLATE: "LicensePlate",
HOMEADDRESS: "HomeAddress",
};
export { vinLookupMethodSelections };

View file

@ -93,9 +93,9 @@ async function getLatestPageForRedirection() {
return fmgPageValues.VEHICLE_DAMAGE;
} else {
if (store.getters.vehicle.vin) {
return fmgPageValues.LICENSE_PLATE_LOOKUP;
} else {
return fmgPageValues.VIN_LOOKUP;
} else {
return fmgPageValues.ESTIMATE;
}
}
}

View file

@ -175,7 +175,7 @@ describe("getPageToRouteExistingOrderTo", () => {
expect(result).toBe('vehicle-damage');
});
test("getPageToRouteExistingOrderTo, should return license-plate-lookup", async () => {
test("getPageToRouteExistingOrderTo, should return vin-lookup", async () => {
// Arrange
const toRoute = {
query: {}
@ -228,7 +228,7 @@ describe("getPageToRouteExistingOrderTo", () => {
const result = await getPageToRouteExistingOrderTo(toRoute, false);
//Assert
expect(result).toBe('license-plate-lookup');
expect(result).toBe('vin-lookup');
});
test("getPageToRouteExistingOrderTo, should return estimate", async () => {
@ -283,7 +283,7 @@ describe("getPageToRouteExistingOrderTo", () => {
const result = await getPageToRouteExistingOrderTo(toRoute, false);
//Assert
expect(result).toBe('vin-lookup');
expect(result).toBe('estimate');
});
test("getPageToRouteExistingOrderTo, existing order, should return heritage", async () => {

View file

@ -167,7 +167,7 @@ export default {
return store.getters.order.customer.emailAddress;
},
getServiceZipFromStore() {
return store.getters.order.serviceLocation.zip;
return store.getters.order.serviceLocation.zipCode;
},
async forwardButtonAction() {
this.resetWarningsAndErrors();
@ -302,7 +302,7 @@ export default {
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.customerQuestions.addressQuestions.zipCode);
store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, this.customerQuestions.firstName);
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, this.customerQuestions.lastName);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP, this.serviceZip);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZip);
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.customerQuestions.email);
},

View file

@ -1,13 +1,131 @@
<template>
<p> Estimate </p>
<Form
@submit="onSubmit"
@invalid-submit="onInvalidSubmit"
ref="theForm"
v-slot="{ meta }"
>
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5">
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
<vehicleBanner cmsWidgetName="VehicleBannerWidget" />
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
<buttonQuestion
cmsWidgetName="VinLookupMethod"
class="button-question-overflow"
:questionText="questionText"
:answers="answersFromCms"
groupName="vinLookupMethodOption"
buttonType="listButton"
v-model="selectedValues"
isRequired
validationRules="option-required"
/>
<funnel-footer
cmsWidgetName="FunnelFooterWidget"
:isForwardActionDisabled="!meta.valid"
@isDisabled="!meta.valid"
@back-clicked="backButtonAction"
@ForwardClicked="forwardButtonAction"
/>
</div>
</Form>
</template>
<script>
// Components
import funnelHeader from "@/common-components/funnel-header/funnel-header";
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
import buttonQuestion from "@/common-components/button-question/button-question";
//Supporting Files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import { Form, defineRule } from "vee-validate";
import store from "@/store";
import { vinLookupMethodSelections } from "@/constants/vin-lookup-method-selections.js";
// Define Validation Rules
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
export default {
name: "estimate",
methods: {
arePagePrerequisitesValid() {
return true;
},
}
name: "estimate",
data() {
return {
selectedValues: [],
};
},
async beforeRouteEnter(to, from, next) {
//Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
//Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
methods: {
arePagePrerequisitesValid() {
if(store.getters.damage.isRepair!=null){
return true;
}
return false;
},
resetDependentState() {},
backButtonAction() {
// route to move backwards
this.$router.navigate(
this.navigationScenarios.CLICKED_BACK,
this.$route
);
},
forwardButtonAction() {
if (this.selectedValues[0]===vinLookupMethodSelections.MANUALVIN) {
this.$router.navigate(
this.navigationScenarios.SELECTED_MANUAL_VIN,
this.$route
);
return;
}
if (this.selectedValues[0]===vinLookupMethodSelections.LICENSEPLATE) {
this.$router.navigate(
this.navigationScenarios.SELECTED_LICENSE_PLATE,
this.$route
);
return;
}
if (this.selectedValues[0]===vinLookupMethodSelections.HOMEADDRESS) {
this.$router.navigate(
this.navigationScenarios.SELECTED_HOME_ADDRESS,
this.$route
);
return;
}
},
},
computed: {
questionText() {
return this.getCmsContent("VinLookupMethod", "QuestionText");
},
answersFromCms() {
return this.getCmsContent("VinLookupMethod", "Answers");
},
},
components: {
funnelHeader,
vehicleBanner,
funnelSubHeader,
funnelFooter,
buttonQuestion,
Form,
},
};
</script>
</script>

View file

@ -33,7 +33,7 @@ jest.mock("@/store", () => ({
emailAddress: "test@test.com"
},
serviceLocation: {
zip: "43443"
zipCode: "43443"
}
},
vehicle: {

View file

@ -259,8 +259,8 @@ export default {
getEmailFromStore() {
return store.getters.order.customer.emailAddress;
},
getServiceZipFromStore() {
return store.getters.order.serviceLocation.zip;
getServiceZipFromStore(){
return store.getters.order.serviceLocation.zipCode
},
backButtonAction() {
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
@ -369,8 +369,8 @@ export default {
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR,vehicleInfo.imageColor);
store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE,this.licensePlate);
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState);
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE,this.registrationZip);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP, this.serviceZip);
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.registrationZip);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZip);
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email);
},
},

View file

@ -182,66 +182,6 @@ describe("vehicle-damage.vue", () => {
});
});
describe("vehicle-damage.vue", () => {
test("Windshield replace with single part on ForwardButtonAction triggers a router.navigate and saves selections to store", async () => {
//Arrange
const partsData = { partsOrQuestions: [
{
glassLocation: "Windshield",
glassName: "Single",
partQuestions: null,
parts: [
{
color: "Green Tint, Green Shade",
description: "rain sensor, solar",
partNumber: "FW02728GGYN",
requiresCapabilityQuestions: false,
requiresRecalibration: false
}
]}]};
const { wrapper } = setupMocks({
pageHeaderWidgetHeaderText: "",
mountOptionsMockData: {
router: { navigate: jest.fn(), },
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
store: {
getters: {
vehicle: {},
payment: { insuranceCoverage: { isVerified: false } },
},
},
},
});
wrapper.vm.selectedDamageLocations = ["Windshield"];
wrapper.vm.selectedWindshieldOptions = {
selectedWindshieldChipCount : null,
selectedWindshieldReplaceOptions : ["Single"],
selectedWindshieldDamageType: ["Replace"]
};
const expectedGlassToReplace = [{location: "Windshield", name: "Single"},];
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, false);
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_GLASS_TO_REPLACE, expectedGlassToReplace);
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_PARTS, partsData.partsOrQuestions[0].parts);
});
});
describe("vehicle-damage.vue", () => {
test("Windshield replace with multiple parts on ForwardButtonAction triggers a router.navigateAfterSave and saves selections to store", async () => {
//Arrange
@ -332,48 +272,6 @@ describe("vehicle-damage.vue", () => {
});
});
describe("vehicle-damage.vue", () => {
test("Windshield repair on ForwardButtonAction triggers a router.navigate and saves selection to store", async () => {
//Arrange
const partsData = { partsOrQuestions: []};
const { wrapper } = setupMocks({
pageHeaderWidgetHeaderText: "",
mountOptionsMockData: {
router: { navigate: jest.fn(), },
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
store: {
getters: {
vehicle: {},
payment: { insuranceCoverage: { isVerified: false } },
},
},
},
});
wrapper.vm.selectedDamageLocations = ["Windshield"];
wrapper.vm.selectedWindshieldOptions = {
selectedWindshieldChipCount : [2],
selectedWindshieldDamageType: ["Repair"]
};
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, true);
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_NUMBER_OF_CHIPS, 2);
});
});
describe("vehicle-damage.vue", () => {
test("isWindshieldDamageLocation is true when windshield is selected", async () => {

View file

@ -293,55 +293,20 @@ export default {
store.commit(this.storeMutations.UPDATE_GLASS_TO_REPLACE, this.selectedGlassToReplace());
const partsData = await baseMixin.methods.dispatchStoreAction(this.storeActions.GET_PARTS_OR_QUESTIONS,
{ carId: store.getters.vehicle.carId, glassArray: this.selectedGlassToReplace()}, false);
this.navigateForward(partsData);
this.navigateForward();
},
navigateForward(partsData){
// Temporary easter egg to navigate to heritage funnel.
const vehicleYearsToShowHeritageFunnel = [ 2001, 2002, 2010, 2016 ];
if (vehicleYearsToShowHeritageFunnel.includes(store.getters.vehicle.year)) {
navigateToHeritageFunnel();
return;
}
// Temporary easter egg to navigate to address-lookup.
if (store.getters.vehicle.year === 2014) {
this.$router.navigateAfterSave(this.navigationScenarios.TEMPORARY_TO_ADDRESS_LOOKUP, this.$route, {}, {}, partsData.data);
return;
}
navigateForward(){
// If vin already exists, navigate directly to vin-lookup
if(this.$store.getters.vehicle.vin){
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_VIN, this.$route);
if(store.getters.vehicle.vin) {
this.$router.navigateAfterSave(this.navigationScenarios.CLICKED_FORWARD_WITH_VIN, this.$route);
return;
}
else {
this.$router.navigateAfterSave(this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN, this.$route);
return;
}
//found problem questions
if (partsData.data.partsOrQuestions.some(pq => pq.partQuestions != null && pq.partQuestions.length > 0)){
this.$router.navigateAfterSave(this.navigationScenarios.SELECTED_DAMAGE_WITH_PART_QUESTIONS, this.$route, {}, {}, partsData.data);
return;
}
//found multiple parts for a single glass location (Windshield, Driver, Passenger, Rear)
if (partsData.data.partsOrQuestions){
for (var i = 0; i < partsData.data.partsOrQuestions.length; i++){
if (partsData.data.partsOrQuestions[i].parts != null && partsData.data.partsOrQuestions[i].parts.length > 1){
this.$router.navigateAfterSave(this.navigationScenarios.SELECTED_DAMAGE_WITH_MULTIPLE_PARTS, this.$route, {}, {}, partsData.data);
return;
}
}
}
//if not a repair then there should only be 1 part and no problem questions at this point so save the part to the store.
if (!this.isWindshieldRepair){
store.commit(this.storeMutations.UPDATE_PARTS, partsData.data.partsOrQuestions[0].parts);
}
this.$router.navigate(this.navigationScenarios.SELECTED_DAMAGE_WITH_SINGLE_PART, this.$route);
},
selectedGlassToReplace() {

View file

@ -328,7 +328,7 @@ export default {
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, carInfo.imageUrl);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, carInfo.imageVifNumber);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, carInfo.imageVifNumber);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP, this.zip);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.zip);
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email);
},
},

View file

@ -8,14 +8,14 @@ const navigationScenarios = {
CLICKED_FORWARD: "CLICKED_FORWARD",
CLICKED_FORWARD_WITH_VIN: "CLICKED_FORWARD_WITH_VIN",
SELECTED_PARTS: "SELECTED_PARTS",
SELECTED_DAMAGE_WITH_SINGLE_PART: "SELECTED_DAMAGE_WITH_SINGLE_PART",
SELECTED_DAMAGE_WITH_MULTIPLE_PARTS: "SELECTED_DAMAGE_WITH_MULTIPLE_PARTS",
SELECTED_DAMAGE_WITH_PART_QUESTIONS: "SELECTED_DAMAGE_WITH_PART_QUESTIONS",
CONTINUING_WITH_PARTS_QUESTION: "CONTINUING_WITH_PARTS_QUESTION",
CONTINUING_WITH_MULTIPLE_PARTS: "CONTINUING_WITH_MULTIPLE_PARTS",
CONTINUING_WITH_SINGLE_PART: "CONTINUING_WITH_SINGLE_PART",
CONTINUING_WITH_MULTIPLE_VEHICLES: "CONTINUING_WITH_MULTIPLE_VEHICLES",
TEMPORARY_TO_ADDRESS_LOOKUP: "TEMPORARY_TO_ADDRESS_LOOKUP",
CLICKED_FORWARD_WITHOUT_VIN: "CLICKED_FORWARD_WITHOUT_VIN",
SELECTED_MANUAL_VIN: "SELECTED_MANUAL_VIN",
SELECTED_LICENSE_PLATE: "SELECTED_LICENSE_PLATE",
SELECTED_HOME_ADDRESS: "SELECTED_HOME_ADDRESS",
};
export { navigationScenarios };

View file

@ -59,23 +59,11 @@ const routingTable = [
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_VIN,
destinationFmgPageValue: fmgPageValues.LICENSE_PLATE_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_DAMAGE_WITH_SINGLE_PART,
destinationFmgPageValue: fmgPageValues.LICENSE_PLATE_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_DAMAGE_WITH_MULTIPLE_PARTS,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_DAMAGE_WITH_PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.LICENSE_PLATE_LOOKUP,//This might be temporary
},
{
scenario: navigationScenarios.TEMPORARY_TO_ADDRESS_LOOKUP,
destinationFmgPageValue: fmgPageValues.ADDRESS_LOOKUP, //This will be temporary
scenario: navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
],
},
@ -172,6 +160,26 @@ const routingTable = [
},
],
},
{fmgPageValue: fmgPageValues.ESTIMATE,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.SELECTED_MANUAL_VIN,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_LICENSE_PLATE,
destinationFmgPageValue: fmgPageValues.LICENSE_PLATE_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_HOME_ADDRESS,
destinationFmgPageValue: fmgPageValues.ADDRESS_LOOKUP,
},
],
},
];
export { routingTable };

View file

@ -31,7 +31,7 @@ const getDefaultState = () => {
},
},
serviceLocation: {
zip: null,
zipCode: null,
},
customer: {
emailAddress: null,
@ -144,8 +144,8 @@ export const mutations = {
updateRegistrationAddress(state, registrationAddress){
state.order.vehicle.registration.address = registrationAddress;
},
updateServiceLocationZip(state, serviceLocationZip){
state.order.serviceLocation.zip = serviceLocationZip;
updateServiceLocationZipCode(state, serviceLocationZipCode){
state.order.serviceLocation.zipCode = serviceLocationZipCode;
},
updateRegistrationCity(state, serviceCity){
state.order.serviceLocation.city = serviceCity;