Merge pull request #1314 from Safelite/feature/digital/INSR-10109
Ymms new endpoint
This commit is contained in:
commit
b40809474f
18 changed files with 251 additions and 95 deletions
|
|
@ -102,9 +102,9 @@ const bailoutMessage = Object.freeze({
|
||||||
code: bailoutCode.NeedHelp,
|
code: bailoutCode.NeedHelp,
|
||||||
message: 'User clicked the Need Help link in the app.'
|
message: 'User clicked the Need Help link in the app.'
|
||||||
}),
|
}),
|
||||||
YMMNotFound: () => ({
|
YMMNotFound: (message = null) => ({
|
||||||
code: bailoutCode.YMMNotFound,
|
code: bailoutCode.YMMNotFound,
|
||||||
message: 'Vin Required vehicle'
|
message: `Vin Required vehicle` + (message ? ` ${message}` : '')
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ const endpoints = Object.freeze({
|
||||||
url: `${PARTS_V1_BASE_URL}/parts-or-questions`,
|
url: `${PARTS_V1_BASE_URL}/parts-or-questions`,
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
GetPartsOrQuestionsVinRequired: {
|
GetPartsOrQuestionsV2: {
|
||||||
url: `${PARTS_V2_BASE_URL}/parts-or-questions`,
|
url: `${PARTS_V2_BASE_URL}/parts-or-questions`,
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ export function getMountOptions(mockData) {
|
||||||
mocks.pushEventToGA = jest.fn();
|
mocks.pushEventToGA = jest.fn();
|
||||||
mocks.$loadScript = mockData?.loadScript;
|
mocks.$loadScript = mockData?.loadScript;
|
||||||
mocks.prependActionToMethod = jest.fn();
|
mocks.prependActionToMethod = jest.fn();
|
||||||
|
mocks.navigateBailout = jest.fn();
|
||||||
|
|
||||||
const global = {
|
const global = {
|
||||||
mocks,
|
mocks,
|
||||||
|
|
|
||||||
21
src/helpers/vehicle-helper.js
Normal file
21
src/helpers/vehicle-helper.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { useMainStore } from '@/store';
|
||||||
|
import { experimentSettings } from '@/constants/experiments';
|
||||||
|
import experimentMixin from '@/mixins/experiment-mixin';
|
||||||
|
|
||||||
|
export function hasYMMExperimentBailoutSettingEnabled() {
|
||||||
|
return ymmIsVinRequired() && experimentMixin.methods.hasSettingEqualTo(experimentSettings.ISS_YMMS_VIN_REQUIRED_BAILOUT_ENABLED, 'true');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasYMMExperimentPageSettingEnabled() {
|
||||||
|
return ymmIsVinRequired() && experimentMixin.methods.hasSettingEqualTo(experimentSettings.ISS_YMMS_VIN_REQUIRED_PAGE_ENABLED, 'true');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasYMMExperimentSettingEnabled() {
|
||||||
|
return ymmIsVinRequired()
|
||||||
|
&& (experimentMixin.methods.hasSettingEqualTo(experimentSettings.ISS_YMMS_VIN_REQUIRED_PAGE_ENABLED, 'true')
|
||||||
|
|| experimentMixin.methods.hasSettingEqualTo(experimentSettings.ISS_YMMS_VIN_REQUIRED_BAILOUT_ENABLED, 'true'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ymmIsVinRequired() {
|
||||||
|
return useMainStore().order?.vehicle?.vinRequired === true;
|
||||||
|
}
|
||||||
|
|
@ -442,7 +442,7 @@ describe('address-lookup.vue', () => {
|
||||||
useMainStore().order.vehicle.carId = 'C0000';
|
useMainStore().order.vehicle.carId = 'C0000';
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.navigateForward(carsFound);
|
await wrapper.vm.navigateForward(carsFound);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.navigateForwardWithSingleCarMatch).toHaveBeenCalledTimes(1);
|
expect(wrapper.vm.navigateForwardWithSingleCarMatch).toHaveBeenCalledTimes(1);
|
||||||
|
|
@ -482,9 +482,10 @@ describe('address-lookup.vue', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
useMainStore().order.vehicle.carId = 'CARID3';
|
useMainStore().order.vehicle.carId = 'CARID3';
|
||||||
|
useMainStore().order.vehicle.vinRequired = false;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.navigateForward(carsFound);
|
await wrapper.vm.navigateForward(carsFound);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.navigateForwardWithSingleCarMatch).toHaveBeenCalledTimes(1);
|
expect(wrapper.vm.navigateForwardWithSingleCarMatch).toHaveBeenCalledTimes(1);
|
||||||
|
|
|
||||||
|
|
@ -81,9 +81,9 @@ import alert from '@/ux-components/alert/alert.vue';
|
||||||
import { Form } from 'vee-validate';
|
import { Form } from 'vee-validate';
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { experimentSettings } from '@/constants/experiments';
|
|
||||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||||
import settleAllPromises from '@/helpers/layout-helper';
|
import settleAllPromises from '@/helpers/layout-helper';
|
||||||
|
import { hasYMMExperimentBailoutSettingEnabled } from '@/helpers/vehicle-helper';
|
||||||
import routerParams from '@/router/router-constants/router-params';
|
import routerParams from '@/router/router-constants/router-params';
|
||||||
import {
|
import {
|
||||||
getDamageString,
|
getDamageString,
|
||||||
|
|
@ -345,13 +345,9 @@ export default {
|
||||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
||||||
);
|
);
|
||||||
} else if (matchingCars.length === 1) {
|
} else if (matchingCars.length === 1) {
|
||||||
const ymmsBailoutEnabled = this.getSettingValue(experimentSettings.ISS_YMMS_VIN_REQUIRED_BAILOUT_ENABLED) === 'true';
|
if (hasYMMExperimentBailoutSettingEnabled()) {
|
||||||
if (ymmsBailoutEnabled && this.mainStore.order.vehicle.vinRequired) {
|
this.navigateBailout(bailoutMessage.YMMNotFound());
|
||||||
this.mainStore.setBailout(bailoutMessage.YMMNotFound());
|
return;
|
||||||
return this.$router.navigate(
|
|
||||||
this.navigationScenarios.BAILOUT,
|
|
||||||
this.$route
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
await this.navigateForwardWithSingleCarMatch();
|
await this.navigateForwardWithSingleCarMatch();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { shallowMount } from '@vue/test-utils';
|
||||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||||
|
import vinPagesMixin from '@/mixins/vin-pages-mixin';
|
||||||
|
|
||||||
jest.mock('@/helpers/damage-helper', () => ({
|
jest.mock('@/helpers/damage-helper', () => ({
|
||||||
isGlassAvailableForCarId: jest.fn().mockImplementation(() => true),
|
isGlassAvailableForCarId: jest.fn().mockImplementation(() => true),
|
||||||
|
|
@ -24,6 +25,11 @@ jest.mock('@/helpers/cms-content-helper', () => ({
|
||||||
|
|
||||||
// Mock our module for promises.
|
// Mock our module for promises.
|
||||||
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
|
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
|
||||||
|
jest.mock('@/mixins/vin-pages-mixin', () => ({
|
||||||
|
methods: {
|
||||||
|
handleVinRequiredVehicle: jest.fn().mockReturnValue(false)
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
function setupMocks({
|
function setupMocks({
|
||||||
route = null,
|
route = null,
|
||||||
|
|
@ -121,7 +127,7 @@ function setupMocks({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mountOptions.mixins = [mockMixin];
|
mountOptions.mixins = [mockMixin, vinPagesMixin];
|
||||||
|
|
||||||
const wrapper = shallowMount(addressVehicles, mountOptions);
|
const wrapper = shallowMount(addressVehicles, mountOptions);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,8 @@ import settleAllPromises from '@/helpers/layout-helper';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import issPageValues from '@/router/router-constants/issPage-values';
|
import issPageValues from '@/router/router-constants/issPage-values';
|
||||||
import errorMessages from '@/constants/error-messages';
|
import errorMessages from '@/constants/error-messages';
|
||||||
import { experimentSettings } from '@/constants/experiments';
|
|
||||||
import { required } from '@/helpers/validation-rules';
|
import { required } from '@/helpers/validation-rules';
|
||||||
|
import { hasYMMExperimentBailoutSettingEnabled } from '@/helpers/vehicle-helper';
|
||||||
import { Form, defineRule } from 'vee-validate';
|
import { Form, defineRule } from 'vee-validate';
|
||||||
import { isGlassAvailableForCarId } from '@/helpers/damage-helper';
|
import { isGlassAvailableForCarId } from '@/helpers/damage-helper';
|
||||||
import {
|
import {
|
||||||
|
|
@ -233,6 +233,7 @@ export default {
|
||||||
},
|
},
|
||||||
async forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
this.mainStore.resetBailout();
|
this.mainStore.resetBailout();
|
||||||
|
|
||||||
const vinLookup = await useMainStore().lookupVehicleByVin(this.selectedVehicle.vin);
|
const vinLookup = await useMainStore().lookupVehicleByVin(this.selectedVehicle.vin);
|
||||||
if (!vinLookup) {
|
if (!vinLookup) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -257,13 +258,9 @@ export default {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
const ymmsBailoutEnabled = this.getSettingValue(experimentSettings.ISS_YMMS_VIN_REQUIRED_BAILOUT_ENABLED) === 'true';
|
if (hasYMMExperimentBailoutSettingEnabled()) {
|
||||||
if (ymmsBailoutEnabled && this.mainStore.order.vehicle.vinRequired) {
|
this.navigateBailout(bailoutMessage.YMMNotFound());
|
||||||
this.mainStore.setBailout(bailoutMessage.YMMNotFound());
|
return;
|
||||||
return this.$router.navigate(
|
|
||||||
this.navigationScenarios.BAILOUT,
|
|
||||||
this.$route
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.navigateForward();
|
await this.navigateForward();
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ import settleAllPromises from '@/helpers/layout-helper';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import bailoutMessage from '@/constants/bailoutMessage';
|
import bailoutMessage from '@/constants/bailoutMessage';
|
||||||
import errorMessages from '@/constants/error-messages';
|
import errorMessages from '@/constants/error-messages';
|
||||||
import { experimentSettings } from '@/constants/experiments';
|
import { hasYMMExperimentBailoutSettingEnabled } from '@/helpers/vehicle-helper';
|
||||||
import { required } from '@/helpers/validation-rules';
|
import { required } from '@/helpers/validation-rules';
|
||||||
import { defineRule, Form } from 'vee-validate';
|
import { defineRule, Form } from 'vee-validate';
|
||||||
import {
|
import {
|
||||||
|
|
@ -305,13 +305,9 @@ export default {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const ymmsBailoutEnabled = this.getSettingValue(experimentSettings.ISS_YMMS_VIN_REQUIRED_BAILOUT_ENABLED) === 'true';
|
if (hasYMMExperimentBailoutSettingEnabled()) {
|
||||||
if (ymmsBailoutEnabled && this.mainStore.order.vehicle.vinRequired) {
|
this.navigateBailout(bailoutMessage.YMMNotFound());
|
||||||
this.mainStore.setBailout(bailoutMessage.YMMNotFound());
|
return;
|
||||||
return this.$router.navigate(
|
|
||||||
this.navigationScenarios.BAILOUT,
|
|
||||||
this.$route
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.navigateForward();
|
return this.navigateForward();
|
||||||
|
|
|
||||||
|
|
@ -428,9 +428,19 @@ export default {
|
||||||
this.$route
|
this.$route
|
||||||
);
|
);
|
||||||
} else if (this.mainStore.order.vehicle.vin || !this.isWindshieldReplace) {
|
} else if (this.mainStore.order.vehicle.vin || !this.isWindshieldReplace) {
|
||||||
// If vin already exists or not replacing windshield, get parts/questions and navigate forward
|
let partsOrQuestionsResponse;
|
||||||
|
const isVinRequired = this.mainStore.order.vehicle.vinRequired;
|
||||||
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
|
if (isVinRequired) {
|
||||||
|
this.mainStore.resetBailout();
|
||||||
|
partsOrQuestionsResponse = await this.getPartsOrQuestionsV2();
|
||||||
|
if (partsOrQuestionsResponse.data.partsOrQuestions.length === 0) {
|
||||||
|
this.navigateBailout(bailoutMessage.YMMNotFound('No Parts Returned'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If vin already exists or not replacing windshield, get parts/questions and navigate forward
|
||||||
|
partsOrQuestionsResponse = await this.getPartsOrQuestions();
|
||||||
|
}
|
||||||
|
|
||||||
// Comes from vehicleQuestionsMixin.navigateForward()
|
// Comes from vehicleQuestionsMixin.navigateForward()
|
||||||
await this.navigateForward(
|
await this.navigateForward(
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@
|
||||||
|
|
||||||
// Import Other Supporting Files
|
// Import Other Supporting Files
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import { experimentSettings } from '@/constants/experiments';
|
|
||||||
import vinLookupMethodSelections from '@/constants/vin-lookup-methods';
|
import vinLookupMethodSelections from '@/constants/vin-lookup-methods';
|
||||||
|
import { hasYMMExperimentSettingEnabled } from '@/helpers/vehicle-helper';
|
||||||
import settleAllPromises from '@/helpers/layout-helper';
|
import settleAllPromises from '@/helpers/layout-helper';
|
||||||
import globalRules from '@/constants/global-rules';
|
import globalRules from '@/constants/global-rules';
|
||||||
|
|
||||||
|
|
@ -67,9 +67,9 @@ export default {
|
||||||
answers.splice(homeAddressIndex, 1);
|
answers.splice(homeAddressIndex, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ymmsBailoutEnabled = this.getSettingValue(experimentSettings.ISS_YMMS_VIN_REQUIRED_BAILOUT_ENABLED) === 'true';
|
const ymmsExperimentEnabled = hasYMMExperimentSettingEnabled();
|
||||||
const isVinRequired = useMainStore().order.vehicle.vinRequired;
|
const isVinRequired = useMainStore().order.vehicle.vinRequired;
|
||||||
if (isVinRequired && ymmsBailoutEnabled) {
|
if (isVinRequired && ymmsExperimentEnabled) {
|
||||||
const vinIndex = answers.findIndex(answer => answer.Name === vinLookupMethodSelections.NOVIN);
|
const vinIndex = answers.findIndex(answer => answer.Name === vinLookupMethodSelections.NOVIN);
|
||||||
if (vinIndex >= 0) {
|
if (vinIndex >= 0) {
|
||||||
answers.splice(vinIndex, 1);
|
answers.splice(vinIndex, 1);
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ const getPartsOrQuestions = {
|
||||||
methodName: 'getPartsOrQuestions',
|
methodName: 'getPartsOrQuestions',
|
||||||
mockResponse: null
|
mockResponse: null
|
||||||
};
|
};
|
||||||
const getPartsOrQuestionsVinRequired = {
|
const getPartsOrQuestionsV2 = {
|
||||||
methodName: 'getPartsOrQuestionsVinRequired',
|
methodName: 'getPartsOrQuestionsV2',
|
||||||
mockResponse: null
|
mockResponse: null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -384,8 +384,8 @@ describe('vin-lookup.vue', () => {
|
||||||
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsVinRequired.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsV2.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestionsVinRequired.mockResponse);
|
.mockResolvedValue(getPartsOrQuestionsV2.mockResponse);
|
||||||
|
|
||||||
const { container } = render(VinLookupComponent, mountOptions);
|
const { container } = render(VinLookupComponent, mountOptions);
|
||||||
|
|
||||||
|
|
@ -417,8 +417,8 @@ describe('vin-lookup.vue', () => {
|
||||||
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsVinRequired.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsV2.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestionsVinRequired.mockResponse);
|
.mockResolvedValue(getPartsOrQuestionsV2.mockResponse);
|
||||||
|
|
||||||
const { container } = render(VinLookupComponent, mountOptions);
|
const { container } = render(VinLookupComponent, mountOptions);
|
||||||
|
|
||||||
|
|
@ -452,8 +452,8 @@ describe('vin-lookup.vue', () => {
|
||||||
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsVinRequired.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsV2.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestionsVinRequired.mockResponse);
|
.mockResolvedValue(getPartsOrQuestionsV2.mockResponse);
|
||||||
store.getCapabilityQuestions.mockResolvedValueOnce({ data: [] });
|
store.getCapabilityQuestions.mockResolvedValueOnce({ data: [] });
|
||||||
|
|
||||||
const { container } = render(VinLookupComponent, mountOptions);
|
const { container } = render(VinLookupComponent, mountOptions);
|
||||||
|
|
@ -487,8 +487,8 @@ describe('vin-lookup.vue', () => {
|
||||||
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsVinRequired.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsV2.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestionsVinRequired.mockResponse);
|
.mockResolvedValue(getPartsOrQuestionsV2.mockResponse);
|
||||||
|
|
||||||
const { container } = render(VinLookupComponent, mountOptions);
|
const { container } = render(VinLookupComponent, mountOptions);
|
||||||
|
|
||||||
|
|
@ -525,8 +525,8 @@ describe('vin-lookup.vue', () => {
|
||||||
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
.mockResolvedValue(lookupVehicleByVin.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
.mockResolvedValue(getPartsOrQuestions.mockResponse);
|
||||||
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsVinRequired.methodName)
|
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestionsV2.methodName)
|
||||||
.mockResolvedValue(getPartsOrQuestionsVinRequired.mockResponse);
|
.mockResolvedValue(getPartsOrQuestionsV2.mockResponse);
|
||||||
|
|
||||||
const { container } = render(VinLookupComponent, mountOptions);
|
const { container } = render(VinLookupComponent, mountOptions);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@
|
||||||
<script>
|
<script>
|
||||||
// Import Supporting Files
|
// Import Supporting Files
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { experimentSettings } from '@/constants/experiments';
|
|
||||||
import vehicleLookupAlertTypes from '@/constants/vehicle-lookup-alert-types';
|
import vehicleLookupAlertTypes from '@/constants/vehicle-lookup-alert-types';
|
||||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||||
import { isGlassAvailableForCarId } from '@/helpers/damage-helper';
|
import { isGlassAvailableForCarId } from '@/helpers/damage-helper';
|
||||||
|
|
@ -62,6 +61,7 @@ import vinLocationInformation from '@/layouts/vin-lookup/vin-location-informatio
|
||||||
import vinLookupAlerts from '@/layouts/vin-lookup/vin-lookup-alerts/vin-lookup-alerts.vue';
|
import vinLookupAlerts from '@/layouts/vin-lookup/vin-lookup-alerts/vin-lookup-alerts.vue';
|
||||||
import vinQuestion from '@/layouts/vin-lookup/vin-question/vin-question.vue';
|
import vinQuestion from '@/layouts/vin-lookup/vin-question/vin-question.vue';
|
||||||
import bailoutMessage from '@/constants/bailoutMessage';
|
import bailoutMessage from '@/constants/bailoutMessage';
|
||||||
|
import vinPagesMixin from '@/mixins/vin-pages-mixin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'vin-lookup',
|
name: 'vin-lookup',
|
||||||
|
|
@ -74,7 +74,7 @@ export default {
|
||||||
vinLookupAlerts,
|
vinLookupAlerts,
|
||||||
vinQuestion
|
vinQuestion
|
||||||
},
|
},
|
||||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
mixins: [baseFormMixin, vehicleQuestionsMixin, vinPagesMixin],
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
vehicleFromLookup: computed(() => this.vehicleFromLookup)
|
vehicleFromLookup: computed(() => this.vehicleFromLookup)
|
||||||
|
|
@ -137,8 +137,9 @@ export default {
|
||||||
return vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase();
|
return vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase();
|
||||||
},
|
},
|
||||||
vinMask() {
|
vinMask() {
|
||||||
|
const vinRequired = this.mainStore.order.vehicle.vinRequired === true;
|
||||||
// TODO: Side effects in computed.
|
// TODO: Side effects in computed.
|
||||||
if (this.vinPopulatedOnPageLoad) {
|
if (this.vinPopulatedOnPageLoad && !vinRequired) {
|
||||||
// TODO: Modify to remove side effects in computed
|
// TODO: Modify to remove side effects in computed
|
||||||
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.PERFECT_MATCH;
|
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.PERFECT_MATCH;
|
||||||
this.needToLookupVehicle = false;
|
this.needToLookupVehicle = false;
|
||||||
|
|
@ -177,14 +178,8 @@ export default {
|
||||||
this.$refs.siteFooter.enableForwardAction();
|
this.$refs.siteFooter.enableForwardAction();
|
||||||
showIssLoadingModal(true);
|
showIssLoadingModal(true);
|
||||||
|
|
||||||
const ymmsBailoutEnabled = this.getSettingValue(experimentSettings.ISS_YMMS_VIN_REQUIRED_BAILOUT_ENABLED) === 'true';
|
if (await this.handleVinRequiredVehicle(this.vin)) {
|
||||||
if (ymmsBailoutEnabled && this.mainStore.order.vehicle.vinRequired) {
|
return;
|
||||||
this.mainStore.order.vehicle.vin = this.vin;
|
|
||||||
this.mainStore.setBailout(bailoutMessage.YMMNotFound());
|
|
||||||
return this.$router.navigate(
|
|
||||||
this.navigationScenarios.BAILOUT,
|
|
||||||
this.$route
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.needToLookupVehicle) {
|
if (this.needToLookupVehicle) {
|
||||||
|
|
@ -273,30 +268,6 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If the vehicle is vinRequired, we need to call getPartsOrQuestionsVinRequired() to get the parts or questions.
|
|
||||||
* If the vehicle is not vinRequired, we can call getPartsOrQuestions() to get the parts or questions.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
if (this.mainStore.order.vehicle.vinRequired) {
|
|
||||||
try {
|
|
||||||
const partsOrQuestionsResponse = await this.getPartsOrQuestionsVinRequired();
|
|
||||||
await this.navigateForward(
|
|
||||||
partsOrQuestionsResponse.data.partsOrQuestions,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
this.mainStore.setBailout(bailoutMessage.HeavyTruckVehicle(this.vehicleFromLookup.carId));
|
|
||||||
this.$router.navigate(
|
|
||||||
this.navigationScenarios.BAILOUT,
|
|
||||||
this.$route
|
|
||||||
);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
|
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
|
||||||
|
|
||||||
// Comes from vehicleQuestionsMixin.navigateForward()
|
// Comes from vehicleQuestionsMixin.navigateForward()
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,9 @@ export default {
|
||||||
|
|
||||||
self.$router.navigateWithSpinner(scenario, self.$route);
|
self.$router.navigateWithSpinner(scenario, self.$route);
|
||||||
},
|
},
|
||||||
|
navigateBailout(bailoutData = null) {
|
||||||
|
this.$router.navigateBailout(bailoutData);
|
||||||
|
},
|
||||||
savePageDataToStore(page, data) {
|
savePageDataToStore(page, data) {
|
||||||
useMainStore().updatePageData({ page, data });
|
useMainStore().updatePageData({ page, data });
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -355,8 +355,8 @@ export default {
|
||||||
async getPartsOrQuestions() {
|
async getPartsOrQuestions() {
|
||||||
return useMainStore().getPartsOrQuestions();
|
return useMainStore().getPartsOrQuestions();
|
||||||
},
|
},
|
||||||
async getPartsOrQuestionsVinRequired() {
|
async getPartsOrQuestionsV2() {
|
||||||
return useMainStore().getPartsOrQuestionsVinRequired();
|
return useMainStore().getPartsOrQuestionsV2();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Can't use `this` because navigateForward is also called from vin-pages-mixin
|
// Can't use `this` because navigateForward is also called from vin-pages-mixin
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,49 @@
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||||
|
import bailoutMessage from '@/constants/bailoutMessage';
|
||||||
|
import { hasYMMExperimentBailoutSettingEnabled, hasYMMExperimentPageSettingEnabled, hasYMMExperimentSettingEnabled } from '@/helpers/vehicle-helper';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
methods: {
|
methods: {
|
||||||
async navigateForwardWithSingleCarMatch() {
|
async navigateForwardWithSingleCarMatch() {
|
||||||
const result = await useMainStore().getPartsOrQuestions();
|
let result;
|
||||||
|
if (this.mainStore.order.vehicle.vinRequired) {
|
||||||
|
result = await useMainStore().getPartsOrQuestionsV2();
|
||||||
|
if (result.data.partsOrQuestions.length === 0) {
|
||||||
|
useMainStore().resetBailout();
|
||||||
|
this.navigateBailout(bailoutMessage.YMMNotFound('No Parts Returned'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = await useMainStore().getPartsOrQuestions();
|
||||||
|
}
|
||||||
const { partsOrQuestions } = result.data;
|
const { partsOrQuestions } = result.data;
|
||||||
|
await vehicleQuestionsMixin.methods.navigateForward(partsOrQuestions, this);
|
||||||
|
},
|
||||||
|
async handleVinRequiredVehicle(vin) {
|
||||||
|
if (!this.mainStore.order.vehicle.vinRequired || !hasYMMExperimentSettingEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
vehicleQuestionsMixin.methods.navigateForward(partsOrQuestions, this);
|
this.mainStore.order.vehicle.vin = vin;
|
||||||
|
if (hasYMMExperimentBailoutSettingEnabled()) {
|
||||||
|
useMainStore().resetBailout();
|
||||||
|
this.navigateBailout(bailoutMessage.YMMNotFound());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasYMMExperimentPageSettingEnabled()) {
|
||||||
|
const partsOrQuestionsResponse = await useMainStore().getPartsOrQuestionsV2();
|
||||||
|
if (partsOrQuestionsResponse.data.partsOrQuestions.length === 0) {
|
||||||
|
useMainStore().resetBailout();
|
||||||
|
this.navigateBailout(bailoutMessage.YMMNotFound('No Parts Returned'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
await vehicleQuestionsMixin.methods.navigateForward(partsOrQuestionsResponse.data.partsOrQuestions, this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,42 @@
|
||||||
import vinPagesMixin from '@/mixins/vin-pages-mixin';
|
import vinPagesMixin from '@/mixins/vin-pages-mixin';
|
||||||
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 {
|
||||||
|
hasYMMExperimentSettingEnabled,
|
||||||
|
hasYMMExperimentBailoutSettingEnabled,
|
||||||
|
hasYMMExperimentPageSettingEnabled,
|
||||||
|
} from '@/helpers/vehicle-helper';
|
||||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
|
import experimentMixin from '@/mixins/experiment-mixin';
|
||||||
|
|
||||||
|
jest.mock('@/mixins/vehicle-questions-mixin', () => ({
|
||||||
|
methods: {
|
||||||
|
navigateForward: jest.fn(),
|
||||||
|
getPartsOrQuestionsV2: jest.fn()
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
jest.mock('@/mixins/experiment-mixin', () => ({
|
||||||
|
methods: {
|
||||||
|
hasSettingEqualTo: jest.fn(),
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
jest.mock('@/helpers/vehicle-helper', () => ({
|
||||||
|
hasYMMExperimentSettingEnabled: jest.fn(),
|
||||||
|
hasYMMExperimentBailoutSettingEnabled: jest.fn(),
|
||||||
|
hasYMMExperimentPageSettingEnabled: jest.fn(),
|
||||||
|
}));
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
function setupMocks() {
|
function setupMocks() {
|
||||||
const mocks = getMountOptions({
|
const mocks = getMountOptions({
|
||||||
router: {
|
router: {
|
||||||
navigate: jest.fn()
|
navigate: jest.fn(),
|
||||||
|
navigateBailout: jest.fn()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const mockVinComponent = {
|
const mockVinComponent = {
|
||||||
mixins: [vinPagesMixin]
|
mixins: [vinPagesMixin, experimentMixin, vehicleQuestionsMixin]
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = shallowMount(mockVinComponent, mocks);
|
const wrapper = shallowMount(mockVinComponent, mocks);
|
||||||
|
|
@ -40,4 +63,72 @@ describe('vin-pages-mixin', () => {
|
||||||
expect(vehicleQuestionsMixin.methods.navigateForward).toHaveBeenCalled();
|
expect(vehicleQuestionsMixin.methods.navigateForward).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('handleVinRequiredVehicle', () => {
|
||||||
|
const vin = '12345678901234567';
|
||||||
|
|
||||||
|
test('should return false for non vin required vehicle', async () => {
|
||||||
|
// Arrange
|
||||||
|
useMainStore().order.vehicle.vinRequired = false;
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const handled = await wrapper.vm.handleVinRequiredVehicle(vin);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(handled).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should bailout if bailout experiment setting is true', async () => {
|
||||||
|
// Arrange
|
||||||
|
useMainStore().order.vehicle.vinRequired = true;
|
||||||
|
hasYMMExperimentSettingEnabled.mockReturnValue(true);
|
||||||
|
hasYMMExperimentBailoutSettingEnabled.mockReturnValue(true);
|
||||||
|
hasYMMExperimentPageSettingEnabled.mockReturnValue(false);
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const handled = await wrapper.vm.handleVinRequiredVehicle(vin);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(handled).toBeTruthy();
|
||||||
|
expect(wrapper.vm.navigateBailout).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should navigateBailout when parts not found', async () => {
|
||||||
|
// Arrange
|
||||||
|
useMainStore().getPartsOrQuestionsV2 = () => ({ data: { partsOrQuestions: [] } });
|
||||||
|
useMainStore().order.vehicle.vinRequired = true;
|
||||||
|
hasYMMExperimentSettingEnabled.mockReturnValue(true);
|
||||||
|
hasYMMExperimentBailoutSettingEnabled.mockReturnValue(false);
|
||||||
|
hasYMMExperimentPageSettingEnabled.mockReturnValue(true);
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const handled = await wrapper.vm.handleVinRequiredVehicle(vin);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(handled).toBeTruthy();
|
||||||
|
expect(wrapper.vm.navigateBailout).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should navigate next when parts found', async () => {
|
||||||
|
// Arrange
|
||||||
|
useMainStore().order.vehicle.vinRequired = true;
|
||||||
|
hasYMMExperimentSettingEnabled.mockReturnValue(true);
|
||||||
|
hasYMMExperimentBailoutSettingEnabled.mockReturnValue(false);
|
||||||
|
hasYMMExperimentPageSettingEnabled.mockReturnValue(true);
|
||||||
|
experimentMixin.methods.hasSettingEqualTo = jest.fn().mockReturnValue(false);
|
||||||
|
useMainStore().getPartsOrQuestionsV2 = () => ({ data: { partsOrQuestions: [{}] } });
|
||||||
|
vehicleQuestionsMixin.methods.navigateForward = jest.fn();
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const handled = await wrapper.vm.handleVinRequiredVehicle(vin);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(handled).toBeTruthy();
|
||||||
|
expect(vehicleQuestionsMixin.methods.navigateForward).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -864,7 +864,8 @@ export const useMainStore = defineStore({
|
||||||
glassPieces: glassArrayForPayload,
|
glassPieces: glassArrayForPayload,
|
||||||
zip: zipCode,
|
zip: zipCode,
|
||||||
vin,
|
vin,
|
||||||
oemEndorsementFlag: this.hasOemEndorsement
|
oemEndorsementFlag: this.hasOemEndorsement,
|
||||||
|
parentAccountNumber: this.order.parentAccountNumber
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async getPartsOrQuestions() {
|
async getPartsOrQuestions() {
|
||||||
|
|
@ -882,19 +883,45 @@ export const useMainStore = defineStore({
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
async getPartsOrQuestionsVinRequired() {
|
async getPartsOrQuestionsV2() {
|
||||||
this.resetPartsAndDependencies();
|
this.resetPartsAndDependencies();
|
||||||
|
|
||||||
const payload = this.getPartsOrQuestionsPayload();
|
const payload = this.getPartsOrQuestionsPayload();
|
||||||
const response = await globalMethods.callHttpClient({
|
let response = await globalMethods.callHttpClient({
|
||||||
method: endpoints.GetPartsOrQuestionsVinRequired.method,
|
method: endpoints.GetPartsOrQuestionsV2.method,
|
||||||
endpoint: endpoints.GetPartsOrQuestionsVinRequired.url,
|
endpoint: endpoints.GetPartsOrQuestionsV2.url,
|
||||||
payload: payload
|
payload: payload
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
partsOrQuestions: []
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Flatten location and name properties
|
// Flatten location and name properties
|
||||||
response.data.partsOrQuestions = convertGlassPieceNamingFromApi(response.data.partsOrQuestions);
|
response.data.partsOrQuestions = convertGlassPieceNamingFromApi(response.data.partsOrQuestions);
|
||||||
|
|
||||||
|
// If no parts are returned for non oem check for OEM parts
|
||||||
|
if (!payload.oemEndorsementFlag && response.data.partsOrQuestions.length === 0) {
|
||||||
|
payload.oemEndorsementFlag = true;
|
||||||
|
response = await globalMethods.callHttpClient({
|
||||||
|
method: endpoints.GetPartsOrQuestionsV2.method,
|
||||||
|
endpoint: endpoints.GetPartsOrQuestionsV2.url,
|
||||||
|
payload: payload
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
partsOrQuestions: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
response.data.partsOrQuestions = convertGlassPieceNamingFromApi(response.data.partsOrQuestions);
|
||||||
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
async getParts() {
|
async getParts() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue