diff --git a/src/constants/experiments.js b/src/constants/experiments.js
index b702b11bb..18ca6387d 100644
--- a/src/constants/experiments.js
+++ b/src/constants/experiments.js
@@ -8,6 +8,7 @@ const experimentSettings = {
DISPLAY_AVAILABILITY_INDICATORS: "DisplayAvailabilityIndicators",
PIA_EXPERIENCE: "PIA Experience",
SUBMIT_ORDER_ENABLE_PIA: "SubmitOrder_Enable_PIA",
+ IS_EMAIL_OPTIONAL: "isEmailOptional",
};
const experimentTriggers = {
diff --git a/src/digital-components/textbox-question/textbox-question.vue b/src/digital-components/textbox-question/textbox-question.vue
index 11f232135..da41fe10b 100644
--- a/src/digital-components/textbox-question/textbox-question.vue
+++ b/src/digital-components/textbox-question/textbox-question.vue
@@ -121,6 +121,10 @@ export default {
hideInput: Boolean,
centerErrorMessage: Boolean,
keyDownHandler: Function,
+ isEmailOptional: {
+ type: Boolean,
+ default: false,
+ },
},
setup(props) {
const uuid = uuidv4();
@@ -193,7 +197,9 @@ export default {
},
computed: {
questionText() {
- return this.getCmsContent(this.cmsWidgetName, "QuestionText");
+ return this.isEmailOptional
+ ? this.getCmsContent(this.cmsWidgetName, "QuestionText") + " (optional)"
+ : this.getCmsContent(this.cmsWidgetName, "QuestionText");
},
value: {
get: function () {
diff --git a/src/helpers/heritage-integration/navigation-helper.js b/src/helpers/heritage-integration/navigation-helper.js
index 8fdfc40bb..80734adf8 100644
--- a/src/helpers/heritage-integration/navigation-helper.js
+++ b/src/helpers/heritage-integration/navigation-helper.js
@@ -129,11 +129,7 @@ async function getLatestPageForRedirection() {
} else if (!estimateComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_DAMAGE;
} else {
- if (scheduleComponent.methods.arePagePrerequisitesValid()) {
- return fmgPageValues.SCHEDULE;
- } else if (serviceLocationComponent.methods.arePagePrerequisitesValid()) {
- return fmgPageValues.SERVICE_LOCATION;
- } else if (quoteComponent.methods.arePagePrerequisitesValid()) {
+ if (quoteComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.QUOTE;
} else if (capabilityQuestionsComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.CAPABILITY_QUESTIONS;
diff --git a/src/layouts/address-lookup/address-lookup.spec.js b/src/layouts/address-lookup/address-lookup.spec.js
index cce68d793..731e664dc 100644
--- a/src/layouts/address-lookup/address-lookup.spec.js
+++ b/src/layouts/address-lookup/address-lookup.spec.js
@@ -10,6 +10,7 @@ import { storeMutations } from "@/constants/store-mutations";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import store from "@/store";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
+import { experimentSettings } from "@/constants/experiments";
jest.mock("@/helpers/damage-helper", () => ({
isGlassAvailableForCarId: jest.fn().mockImplementation(() => true),
@@ -641,6 +642,17 @@ describe("address-lookup.vue", () => {
});
});
+const mockMixin = {
+ methods: {
+ getSettingValue: jest.fn((settingName) => {
+ if (settingName === experimentSettings.IS_EMAIL_OPTIONAL) {
+ return "true";
+ }
+ return "false";
+ }),
+ },
+};
+
function setupMocks({
isZipValid = true,
isZipServiceable = true,
@@ -709,6 +721,7 @@ function setupMocks({
},
},
},
+ mixins: [mockMixin],
})
);
diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue
index de0e8d5aa..807bdc5ce 100644
--- a/src/layouts/address-lookup/address-lookup.vue
+++ b/src/layouts/address-lookup/address-lookup.vue
@@ -20,7 +20,11 @@
-
+
+ :isRequired="!isEmailOptional"
+ :validationRules="validationRules"
+ :isEmailOptional="isEmailOptional" />
@@ -79,6 +81,7 @@ export default {
}),
},
validationRules: String,
+ isEmailOptional: Boolean,
},
computed: {
customerModel: {
diff --git a/src/layouts/estimate/estimate.spec.js b/src/layouts/estimate/estimate.spec.js
index 7d395e88d..b8517d833 100644
--- a/src/layouts/estimate/estimate.spec.js
+++ b/src/layouts/estimate/estimate.spec.js
@@ -11,6 +11,7 @@ import { settleAllPromises } from "@/helpers/layout-helper.js";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import baseMixin from "../../mixins/base-mixin";
import { vinLookupMethodSelections } from "@/constants/vin-lookup-method-selections.js";
+import { experimentSettings } from "@/constants/experiments";
// Mock our module for promises.
jest.mock("@/helpers/layout-helper.js", () => ({
@@ -273,12 +274,24 @@ function setupMocks({
Answers: cmsAnswers,
FunnelFooterWidget: FunnelFooterWidget,
};
-
+ const mockMixin = {
+ methods: {
+ getSettingValue: jest.fn((settingName) => {
+ if (settingName === experimentSettings.IS_EMAIL_OPTIONAL) {
+ return "true";
+ }
+ return "false";
+ }),
+ },
+ };
const apiPromise = Promise.resolve({ cmsContent });
settleAllPromises.mockImplementation(() => apiPromise);
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
- const mountOptions = getMountOptions({ ...mountOptionsMockData, mixins: [baseMixin] });
+ const mountOptions = getMountOptions({
+ ...mountOptionsMockData,
+ mixins: [baseMixin, mockMixin],
+ });
mountOptions["attachTo"] = document.body;
const wrapper = shallowMount(estimate, mountOptions);
diff --git a/src/layouts/estimate/estimate.vue b/src/layouts/estimate/estimate.vue
index 410c4d325..d2766f730 100644
--- a/src/layouts/estimate/estimate.vue
+++ b/src/layouts/estimate/estimate.vue
@@ -52,9 +52,10 @@
cmsWidgetName="EmailAddressQuestionWidget"
v-model="emailAddress"
inputId="emailAddress"
- isRequired
+ :isRequired="!IsEmailOptional"
disableAutoFill
- validationRules="email-address-required|email-address-format" />
+ :validationRules="EmailValidationRules"
+ :isEmailOptional="IsEmailOptional" />
"loader.gif");
jest.mock("@/assets/img/windshield.png", () => "windshield.png");
@@ -692,11 +693,20 @@ function setupMocks({
};
const apiPromise = Promise.resolve(apiResponses);
-
+ const mockMixin = {
+ methods: {
+ getSettingValue: jest.fn((settingName) => {
+ if (settingName === experimentSettings.IS_EMAIL_OPTIONAL) {
+ return "true";
+ }
+ return "false";
+ }),
+ },
+ };
settleAllPromises.mockImplementation(() => apiPromise);
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
- const mountOptions = getMountOptions(mountOptionsMockData);
+ const mountOptions = getMountOptions({ ...mountOptionsMockData, mixins: [mockMixin] });
mountOptions["attachTo"] = document.body; // append wrapper to document.body to test DOM methods
const wrapper = shallowMount(licensePlateLookup, mountOptions);
diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.vue b/src/layouts/license-plate-lookup/license-plate-lookup.vue
index 811dbea7b..37d93cc8b 100644
--- a/src/layouts/license-plate-lookup/license-plate-lookup.vue
+++ b/src/layouts/license-plate-lookup/license-plate-lookup.vue
@@ -34,7 +34,9 @@
cmsWidgetName="EmailAddressQuestionWidget"
v-model="email"
customInputId="email"
- validationRules="email-address-required|email-address-format" />
+ :isRequired="!IsEmailOptional"
+ :validationRules="EmailValidationRules"
+ :isEmailOptional="IsEmailOptional" />
diff --git a/src/layouts/payment-method/promo-modal-question/promo-modal-question.spec.js b/src/layouts/payment-method/promo-modal-question/promo-modal-question.spec.js
index 16d170e82..1dcc2ac70 100644
--- a/src/layouts/payment-method/promo-modal-question/promo-modal-question.spec.js
+++ b/src/layouts/payment-method/promo-modal-question/promo-modal-question.spec.js
@@ -1,5 +1,25 @@
import { mount, shallowMount } from "@vue/test-utils";
import promoModalQuestion from "./promo-modal-question";
+import { storeActions } from "@/constants/store-actions";
+import baseMixin from "@/mixins/base-mixin.js";
+
+let mockReturnsForStoreActions = {};
+
+jest.mock("@/mixins/base-mixin", () => ({
+ ...jest.requireActual("@/mixins/base-mixin"),
+ methods: {
+ dispatchStoreActionWithLogging: jest.fn(
+ (action, { promoCode, addableVaps }, pageNameToLog, someBool) => {
+ return mockReturnsForStoreActions[action];
+ }
+ ),
+ },
+}));
+
+afterEach(() => {
+ // reset store action returns
+ mockReturnsForStoreActions = {};
+});
jest.mock("@/digital-components/textbox-question/textbox-question", () => ({
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
@@ -79,4 +99,127 @@ describe("promo-modal-question.vue", () => {
// Assert
expect(wrapper.emitted("update:modelValue")).toEqual([[lineItems]]);
});
+ it("focuses on the input element when focusOnPromoInput is called", async () => {
+ // Arrange
+ const lineItems = {
+ glassParts: [],
+ supportingItems: [],
+ vaps: [],
+ promos: [],
+ };
+
+ const wrapper = mount(promoModalQuestion, {
+ mixins: [mockMixin],
+ props: {
+ modelValue: lineItems,
+ modalWidgetName: modalWidgetName,
+ },
+ attachTo: document.body,
+ });
+ const focusMock = jest.fn();
+ const inputMock = { focus: focusMock };
+
+ // Mock document.getElementById to return the inputMock
+ jest.spyOn(document, "getElementById").mockReturnValue(inputMock);
+
+ //Act
+
+ wrapper.vm.focusOnPromoInput();
+ await wrapper.vm.$nextTick();
+
+ //Assert
+ expect(focusMock).toHaveBeenCalled();
+ });
+ it("returns a validate response on applying promo", async () => {
+ // Arrange
+ const newPromo = "testPromo";
+ const pageNameToLog = "testPage";
+ const validateResponse = { orderPromos: [] };
+ const addableVaps = [];
+ mockReturnsForStoreActions[storeActions.VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA] =
+ validateResponse;
+ const lineItems = {
+ glassParts: [],
+ supportingItems: [],
+ vaps: [],
+ promos: [],
+ };
+
+ const wrapper = mount(promoModalQuestion, {
+ mixins: [mockMixin],
+ props: {
+ modelValue: lineItems,
+ modalWidgetName: modalWidgetName,
+ },
+ attachTo: document.body,
+ });
+ // Act
+
+ wrapper.vm.getPromoCodeData();
+
+ const promoValidationResponse = await baseMixin.methods.dispatchStoreActionWithLogging(
+ storeActions.VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA,
+ {
+ newPromo,
+ lineItems,
+ addableVaps,
+ },
+ pageNameToLog,
+ false
+ );
+
+ // Assert
+ expect(promoValidationResponse).toEqual(validateResponse);
+ });
+ test("If promocode is valid return taxed lineItems", async () => {
+ //Arrange
+ const taxedlineItems = {};
+
+ mockReturnsForStoreActions[storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA] =
+ taxedlineItems;
+
+ const lineItems = {
+ glassParts: [],
+ supportingItems: [],
+ vaps: [],
+ promos: [],
+ };
+
+ let promoCode = "1wiper0";
+ const pricedLineItemsToTax = [];
+
+ pricedLineItemsToTax.push(promoCode);
+ const wrapper = mount(promoModalQuestion, {
+ mixins: [mockMixin],
+
+ props: {
+ modelValue: lineItems,
+ modalWidgetName: modalWidgetName,
+ },
+
+ attachTo: document.body,
+ });
+ wrapper.vm.addPromoCode();
+
+ const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
+ storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
+ {
+ billToAccountNumber: "87291",
+ providerNumber: 2,
+ appointmentType: "IN_SHOP",
+ serviceLocationCity: "city",
+ serviceLocationState: "state",
+ serviceLocationZipCode: "12345",
+ pricedLineItems: pricedLineItemsToTax,
+ },
+
+ "payment-method",
+
+ false
+ );
+
+ // Assert
+
+ expect(taxedLineItems).toEqual(taxedlineItems);
+ });
});
diff --git a/src/layouts/payment-method/promo-modal-question/promo-modal-question.vue b/src/layouts/payment-method/promo-modal-question/promo-modal-question.vue
index b4b02b3ed..da8d344e9 100644
--- a/src/layouts/payment-method/promo-modal-question/promo-modal-question.vue
+++ b/src/layouts/payment-method/promo-modal-question/promo-modal-question.vue
@@ -100,6 +100,12 @@ export default {
modelValue: Object,
modalWidgetName: String,
availableVaps: Object,
+ pageName: String,
+ taxPromos: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
computed: {
promoLinkText() {
@@ -253,44 +259,52 @@ export default {
this.promoCode,
this.lineItems,
this.availableVaps,
- "payment-method"
+ this.pageName
);
if (promoCodeData.isValid) {
- const pricedLineItemsToTax = [];
- pricedLineItemsToTax.push(...promoCodeData.promoCode);
- const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
- storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
- {
- billToAccountNumber: "87291",
- providerNumber:
- store.getters.order.serviceLocation.provider.providerNumber,
- appointmentType: store.getters.order.serviceLocation.appointmentType,
- serviceLocationCity: store.getters.order.serviceLocation.city,
- serviceLocationState: store.getters.order.serviceLocation.state,
- serviceLocationZipCode: store.getters.order.serviceLocation.zipCode,
- pricedLineItems: pricedLineItemsToTax,
- },
- "payment-method",
- false
- );
+ if (this.taxPromos) {
+ const pricedLineItemsToTax = [];
+ pricedLineItemsToTax.push(...promoCodeData.promoCode);
+ const taxedLineItems =
+ await baseMixin.methods.dispatchStoreActionWithLogging(
+ storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
+ {
+ billToAccountNumber: "87291",
+ providerNumber:
+ store.getters.order.serviceLocation.provider.providerNumber,
+ appointmentType:
+ store.getters.order.serviceLocation.appointmentType,
+ serviceLocationCity: store.getters.order.serviceLocation.city,
+ serviceLocationState: store.getters.order.serviceLocation.state,
+ serviceLocationZipCode:
+ store.getters.order.serviceLocation.zipCode,
+ pricedLineItems: pricedLineItemsToTax,
+ },
+ "payment-method",
+ false
+ );
- // Match all line items to the line items as they are in the store
- // and rebuild the original structure.
- this.lineItems = mapTaxedLineItemsToStoreFormat(taxedLineItems, this.lineItems);
- const taxedVaps = mapTaxedLineItemsToStoreFormat(
- taxedLineItems,
- this.availableVaps
- );
+ // Match all line items to the line items as they are in the store
+ // and rebuild the original structure.
+ this.lineItems = mapTaxedLineItemsToStoreFormat(
+ taxedLineItems,
+ this.lineItems
+ );
+ const taxedVaps = mapTaxedLineItemsToStoreFormat(
+ taxedLineItems,
+ this.availableVaps
+ );
- const getVaps = getVapsThatNeedToBeAddedToSatisfyPromos(
- promoCodeData.promoCode,
- taxedVaps,
- this.lineItems
- );
+ const getVaps = getVapsThatNeedToBeAddedToSatisfyPromos(
+ promoCodeData.promoCode,
+ taxedVaps,
+ this.lineItems
+ );
+ this.lineItems.vaps?.push(...getVaps);
+ }
this.lineItems?.promos.push(...promoCodeData.promoCode);
- this.lineItems.vaps?.push(...getVaps);
this.closeModal();
} else {
this.getErrorMessage(promoCodeData.errorCode, promoCodeData.additionalInfo);
diff --git a/src/layouts/quote/quote.spec.js b/src/layouts/quote/quote.spec.js
index dc30985a5..be68267ae 100644
--- a/src/layouts/quote/quote.spec.js
+++ b/src/layouts/quote/quote.spec.js
@@ -133,8 +133,6 @@ describe("quote.vue", () => {
};
});
- wrapper.vm.pricedGlassParts = [];
-
//Act
await wrapper.vm.forwardButtonAction();
@@ -172,8 +170,6 @@ describe("quote.vue", () => {
};
});
- wrapper.vm.pricedGlassParts = [];
-
//Act
await wrapper.vm.forwardButtonAction();
@@ -288,8 +284,8 @@ describe("quote.vue", () => {
);
//Assert
- expect(wrapper.vm.pricedGlassParts !== null).toBe(true);
- expect(wrapper.vm.supportingItems !== null).toBe(true);
+ expect(wrapper.vm.lineItems !== null).toBe(true);
+ expect(wrapper.vm.availableVaps !== null).toBe(true);
expect(wrapper.vm.availableLineItems !== null).toBe(true);
// This should have its own test
//expect(vm.isInsuranceSelected !== null).toBe(true);
@@ -548,6 +544,31 @@ describe("quote.vue", () => {
//Assert
expect(wrapper.vm.isInsuranceSelected).toBe(true);
});
+ test("On forward button action save promos", async () => {
+ //Arrange
+ store.getters.payment = {
+ insuranceCoverage: {},
+ isInsurance: false,
+ };
+ store.getters.order = {
+ lineItems: [],
+ payment: {
+ parentAccountNumber: 167132,
+ },
+ };
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ router: {
+ navigateWithSaving: jest.fn(),
+ },
+ route: { quote },
+ },
+ });
+
+ wrapper.vm.forwardButtonAction();
+
+ expect(wrapper.vm.lineItems.promos !== null).toBe(true);
+ });
});
function setupMocks({ customMountOptions }) {
diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue
index 5c6b2d744..8d3dbcee3 100644
--- a/src/layouts/quote/quote.vue
+++ b/src/layouts/quote/quote.vue
@@ -39,6 +39,15 @@
cmsWidgetName="AfterpayModalWidget"
:lineItems="availableLineItems" />
+
+
{
vm.setCmsContent(resultMap.cmsContent);
- vm.pricedGlassParts = nullSafeGlassParts;
- vm.supportingItems = resultMap.supportingItems;
+ vm.availableVaps = availableVaps;
+ vm.lineItems = lineItems;
vm.availableLineItems = pricingResults;
vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems);
@@ -208,15 +224,17 @@ export default {
data() {
return {
isInsuranceSelected: null,
- selectedVaps: null,
availableLineItems: null,
- supportingItems: null,
- pricedGlassParts: null,
+ lineItems: [],
+ availableVaps: [],
};
},
computed: {
allActivePromos() {
- return this.$store.getters.order.lineItems.promos ?? [];
+ return this.lineItems.promos ?? [];
+ },
+ lineItemsCloneForWatcher() {
+ return Object.assign({}, this.lineItems);
},
},
methods: {
@@ -258,7 +276,7 @@ export default {
}
},
vapsItemsSelectedAction(vapsItemsSelected) {
- this.selectedVaps = vapsItemsSelected;
+ this.lineItems.vaps = vapsItemsSelected;
},
backButtonAction() {
vehicleQuestionsMixin.methods.navigateBack(this);
@@ -285,15 +303,23 @@ export default {
this.supportingItems = this.filterOutFees(this.supportingItems);
}
- if (this.pricedGlassParts.length > 0) {
+ if (this.lineItems.glassParts?.length > 0) {
this.dispatchStoreAction(
this.storeActions.SAVE_GLASS_PARTS_SUPPRESSING_STATE_RESETTING,
- this.pricedGlassParts,
+ this.lineItems.glassParts,
false
);
}
- this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false);
+ this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.lineItems.vaps, false);
+ this.dispatchStoreAction(
+ storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
+ {
+ activePromos: this.lineItems.promos,
+ inactivePromos: this.$store.getters.order.payment.inactivePromos,
+ },
+ false
+ );
const payment = this.$store.getters.payment;
if (payment.isInsurance) {
@@ -310,6 +336,32 @@ export default {
}
},
},
+ watch: {
+ lineItemsCloneForWatcher: {
+ handler(newValue, oldValue) {
+ if (
+ !oldValue ||
+ oldValue.length == 0 ||
+ !oldValue.vaps ||
+ !newValue ||
+ newValue.length == 0
+ ) {
+ return;
+ }
+ if (oldValue.promos.length < newValue.promos.length) {
+ const oldPromoCodes = oldValue.promos.map(
+ (promoObject) => promoObject.promoCode
+ );
+ const newlyActivatedPromoCodes = newValue.promos.filter(
+ (newPromo) => !oldPromoCodes.includes(newPromo.promoCode)
+ );
+ const alert = createPromoSuccessAlert(newlyActivatedPromoCodes[0].promoCode);
+ this.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade);
+ }
+ },
+ deep: true,
+ },
+ },
components: {
funnelHeader,
navbar,
@@ -322,6 +374,7 @@ export default {
contentGroupModal,
loadingModal,
afterpayModalBanner,
+ promoModalQuestion,
},
};
diff --git a/src/layouts/quote/service-package-question/service-package-question.spec.js b/src/layouts/quote/service-package-question/service-package-question.spec.js
index c156ef34c..8163c6324 100644
--- a/src/layouts/quote/service-package-question/service-package-question.spec.js
+++ b/src/layouts/quote/service-package-question/service-package-question.spec.js
@@ -256,6 +256,57 @@ describe("service-package-question.vue", () => {
// Assert
expect(wrapper.vm.selectedPackageName).toBe("TierThree");
});
+ it("should select default package if promos are added", async () => {
+ //Arrange
+ mockProps.activePromos != null;
+ const wrapper = setupMocks({
+ mountOptionsMockData: {
+ store: {
+ getters: {
+ order: {
+ damage: {
+ isRepair: false,
+ glassToReplace: [{ glassLocation: "Windshield" }],
+ },
+ },
+ lineItems: {
+ vaps: [],
+ },
+ hasAnyNonWindshieldGlassParts: false,
+ payment: {
+ isInsurance: false,
+ },
+ },
+ },
+ },
+ });
+
+ //Act
+ wrapper.setProps({
+ activePromos: [
+ {
+ discountedLineItemIds: [
+ {
+ 0: "428ec73c-38e4-4e14-8703-a987b0391898",
+ 1: "79db94d7-163c-4408-a1ec-f83e58c11992",
+ },
+ ],
+ partType: "PROMO_DISCOUNT",
+ promoCode: "1WIPER0",
+ partNumber: "WIPER DISCOUNT",
+ laborAmount: 0,
+ sellingPrice: -10,
+ kitPrice: 0,
+ salesTax: null,
+ },
+ ],
+ });
+ const selectDefaultPackageMock = jest.spyOn(wrapper.vm, "selectDefaultPackage");
+ await nextTick();
+
+ //Assert
+ expect(selectDefaultPackageMock).toHaveBeenCalled();
+ });
});
describe("service-package-question.vue, matching business rules for package display", () => {
// mock scenarios in figma:
diff --git a/src/layouts/quote/service-package-question/service-package-question.vue b/src/layouts/quote/service-package-question/service-package-question.vue
index 28727f155..6b84f3557 100644
--- a/src/layouts/quote/service-package-question/service-package-question.vue
+++ b/src/layouts/quote/service-package-question/service-package-question.vue
@@ -63,6 +63,9 @@ export default {
this.selectDefaultPackage();
}
},
+ activePromos() {
+ this.selectDefaultPackage();
+ },
selectedPackageName(newValue) {
const VapsProductsInSelectedPackage = this.getVapsLineItemsForSelectedPackage(newValue);
this.$emit("vapsItemsSelected", VapsProductsInSelectedPackage);
diff --git a/src/layouts/vin-lookup/vin-lookup.spec.js b/src/layouts/vin-lookup/vin-lookup.spec.js
index f25bc68db..1d7d3f493 100644
--- a/src/layouts/vin-lookup/vin-lookup.spec.js
+++ b/src/layouts/vin-lookup/vin-lookup.spec.js
@@ -3,6 +3,7 @@ import vinLookup from "./vin-lookup.vue";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js";
import { settleAllPromises } from "@/helpers/layout-helper.js";
+import { experimentSettings } from "@/constants/experiments";
import store from "@/store";
@@ -378,5 +379,11 @@ function mockOutStubFunctions(wrapper) {
const mockMixin = {
methods: {
getCmsContent: jest.fn(() => "placeholder CMS content"),
+ getSettingValue: jest.fn((settingName) => {
+ if (settingName === experimentSettings.IS_EMAIL_OPTIONAL) {
+ return "true";
+ }
+ return "false";
+ }),
},
};
diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue
index c809bae70..ae197aeb0 100644
--- a/src/layouts/vin-lookup/vin-lookup.vue
+++ b/src/layouts/vin-lookup/vin-lookup.vue
@@ -53,8 +53,9 @@
cmsWidgetName="EmailAddressQuestionWidget"
v-model="emailAddress"
customInputId="emailAddress"
- isRequired
- validationRules="email-address-required|email-address-format" />
+ :isRequired="!IsEmailOptional"
+ :validationRules="EmailValidationRules"
+ :isEmailOptional="IsEmailOptional" />
diff --git a/src/mixins/vin-pages-mixin.js b/src/mixins/vin-pages-mixin.js
index a0a435000..98eb7a75b 100644
--- a/src/mixins/vin-pages-mixin.js
+++ b/src/mixins/vin-pages-mixin.js
@@ -2,8 +2,20 @@ import { storeActions } from "@/constants/store-actions.js";
import store from "@/store";
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
+import { experimentSettings } from "@/constants/experiments";
export default {
+ computed: {
+ IsEmailOptional() {
+ const emailOptional = this.getSettingValue(experimentSettings.IS_EMAIL_OPTIONAL);
+ return emailOptional === "true";
+ },
+ EmailValidationRules() {
+ return this.IsEmailOptional
+ ? "email-address-format"
+ : "email-address-required|email-address-format";
+ },
+ },
methods: {
async navigateForwardWithSingleCarMatch() {
const pageName = this.$options?.name;