Merge pull request #1314 from Safelite/feature/digital/INSR-10109

Ymms new endpoint
This commit is contained in:
brich1212safe 2026-07-23 16:14:42 -04:00 committed by GitHub
commit b40809474f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 251 additions and 95 deletions

View file

@ -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}` : '')
}) })
}); });

View file

@ -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'
}, },

View file

@ -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,

View 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;
}

View file

@ -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);

View file

@ -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 {

View file

@ -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);

View file

@ -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();

View file

@ -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();

View file

@ -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(

View file

@ -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);

View file

@ -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);

View file

@ -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()

View file

@ -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 });
}, },

View file

@ -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

View file

@ -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;
} }
} }
}; };

View file

@ -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();
});
});
}); });

View file

@ -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() {