Merge pull request #2387 from Safelite/feature/CASH-423
AB Test: Skip Quote for Recal Vehicles
This commit is contained in:
commit
879f08f13d
8 changed files with 95 additions and 20 deletions
|
|
@ -2,6 +2,7 @@ const experimentUniverses = {
|
||||||
CONCEPT_FUNNEL: "ConceptFunnel",
|
CONCEPT_FUNNEL: "ConceptFunnel",
|
||||||
RECAL_PRICE_REMOVAL: "NextGen_RecalPriceRemoval",
|
RECAL_PRICE_REMOVAL: "NextGen_RecalPriceRemoval",
|
||||||
MSR: "MSR",
|
MSR: "MSR",
|
||||||
|
IGQ_SkipQuote: "NextGen_IGQSkipToInsurance",
|
||||||
};
|
};
|
||||||
|
|
||||||
const experimentSettings = {
|
const experimentSettings = {
|
||||||
|
|
@ -22,6 +23,7 @@ const experimentSettings = {
|
||||||
WAITLIST_THRESHOLD_DAYS: "Waitlist_Threshold_Days",
|
WAITLIST_THRESHOLD_DAYS: "Waitlist_Threshold_Days",
|
||||||
PRICING_BY_DAY: "DisplayPricingByDay",
|
PRICING_BY_DAY: "DisplayPricingByDay",
|
||||||
FOSTER_LOVE: "DisplayFosterLove",
|
FOSTER_LOVE: "DisplayFosterLove",
|
||||||
|
SKIP_TO_INSURANCE: "SkipToInsurance",
|
||||||
};
|
};
|
||||||
|
|
||||||
const experimentTriggers = {
|
const experimentTriggers = {
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,9 @@ export const packageNames = {
|
||||||
TIER_TWO: "TierTwo",
|
TIER_TWO: "TierTwo",
|
||||||
TIER_THREE: "TierThree",
|
TIER_THREE: "TierThree",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const externalParamPackageLabels = {
|
||||||
|
GLASS_ONLY: "glassonly",
|
||||||
|
STANDARD: "standard",
|
||||||
|
PREMIUM: "premium",
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { partTypeStrings } from "@/constants/part-type-strings";
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
import { damageLocationsSelected as glassLocations } from "@/constants/damage-locations-selected";
|
import { damageLocationsSelected as glassLocations } from "@/constants/damage-locations-selected";
|
||||||
import { packageNames } from "@/constants/package-names";
|
import { packageNames, externalParamPackageLabels } from "@/constants/package-names";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
||||||
import {
|
import {
|
||||||
|
|
@ -238,9 +238,9 @@ export function getHighestFullySatisfiedTier(glassToReplace, availableLineItems,
|
||||||
|
|
||||||
export function getPackageNameByType(packageType) {
|
export function getPackageNameByType(packageType) {
|
||||||
const package_names = {
|
const package_names = {
|
||||||
glassonly: packageNames.TIER_ONE,
|
[externalParamPackageLabels.GLASS_ONLY]: packageNames.TIER_ONE,
|
||||||
standard: packageNames.TIER_TWO,
|
[externalParamPackageLabels.STANDARD]: packageNames.TIER_TWO,
|
||||||
premium: packageNames.TIER_THREE,
|
[externalParamPackageLabels.PREMIUM]: packageNames.TIER_THREE,
|
||||||
};
|
};
|
||||||
return package_names[packageType] || null;
|
return package_names[packageType] || null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -836,6 +836,7 @@ describe("quote.vue", () => {
|
||||||
nextFunction
|
nextFunction
|
||||||
);
|
);
|
||||||
await nextTick();
|
await nextTick();
|
||||||
|
await nextTick();
|
||||||
expect(nextFunction).toHaveBeenCalled();
|
expect(nextFunction).toHaveBeenCalled();
|
||||||
expect(baseMixin.methods.isFormValid).toHaveBeenCalled();
|
expect(baseMixin.methods.isFormValid).toHaveBeenCalled();
|
||||||
expect(baseMixin.methods.isFormValid()).toBe(true);
|
expect(baseMixin.methods.isFormValid()).toBe(true);
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ import { storeActions } from "@/constants/store-actions";
|
||||||
import { deepClone } from "@/helpers/object-helper";
|
import { deepClone } from "@/helpers/object-helper";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { experimentSettings } from "@/constants/experiments";
|
import { experimentSettings, experimentUniverses } from "@/constants/experiments";
|
||||||
import { required } from "@/helpers/validation-rules";
|
import { required } from "@/helpers/validation-rules";
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
import { errorMessages } from "@/constants/error-messages";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, defineRule } from "vee-validate";
|
||||||
|
|
@ -154,12 +154,18 @@ import {
|
||||||
findLineItemsWithPartType,
|
findLineItemsWithPartType,
|
||||||
} from "@/helpers/service-package-helper";
|
} from "@/helpers/service-package-helper";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
import { packageNames } from "@/constants/package-names";
|
import { packageNames, externalParamPackageLabels } from "@/constants/package-names";
|
||||||
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||||
import { containsRecalParts } from "@/helpers/recal-helper";
|
import { containsRecalParts } from "@/helpers/recal-helper";
|
||||||
import { externalParameterStatus } from "@/constants/external-parameters";
|
import { externalParameterStatus } from "@/constants/external-parameters";
|
||||||
import { saveQuote } from "@/helpers/heritage-integration/order-helper.js";
|
import { saveQuote } from "@/helpers/heritage-integration/order-helper.js";
|
||||||
import { getBoolFromString } from "@/helpers/boolean-helper";
|
import { getBoolFromString } from "@/helpers/boolean-helper";
|
||||||
|
import {
|
||||||
|
getSessionKeyValue,
|
||||||
|
getUserIdValue,
|
||||||
|
getDeviceIdValue,
|
||||||
|
} from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
||||||
|
|
||||||
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
||||||
|
|
@ -189,6 +195,31 @@ export default {
|
||||||
"quote"
|
"quote"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const shouldExposeSkipQuote = store.getters.isRecalibrationOnOrder;
|
||||||
|
const skipQuoteExperiment = store.getters.applicationUser.experiments.find(
|
||||||
|
(e) => e.universeName === experimentUniverses.IGQ_SkipQuote
|
||||||
|
);
|
||||||
|
const hasExposedSkipQuote = skipQuoteExperiment?.isExposed;
|
||||||
|
|
||||||
|
const shouldSendExposeRequest =
|
||||||
|
shouldExposeSkipQuote && !hasExposedSkipQuote && skipQuoteExperiment;
|
||||||
|
|
||||||
|
if (shouldSendExposeRequest) {
|
||||||
|
// Don't await -- response is not needed so can fire fully asynchronously.
|
||||||
|
baseMixin.methods.dispatchStoreActionWithLogging(
|
||||||
|
storeActions.LOG_EXPERIMENT_EXPOSURE_AND_UPDATE_STORE,
|
||||||
|
{
|
||||||
|
userId: getUserIdValue(),
|
||||||
|
deviceId: getDeviceIdValue(),
|
||||||
|
sessionKey: getSessionKeyValue(),
|
||||||
|
pageName: to.query.fmgPage,
|
||||||
|
experiment: skipQuoteExperiment,
|
||||||
|
},
|
||||||
|
"quote",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const promiseResultMap = [
|
const promiseResultMap = [
|
||||||
{
|
{
|
||||||
resultKey: "cmsContent",
|
resultKey: "cmsContent",
|
||||||
|
|
@ -213,6 +244,12 @@ export default {
|
||||||
const isEmailInStoreOnPageLoad = emailFromStore?.length > 0;
|
const isEmailInStoreOnPageLoad = emailFromStore?.length > 0;
|
||||||
const showSaveProgressPopup = isEmailInStoreOnPageLoad ? false : true;
|
const showSaveProgressPopup = isEmailInStoreOnPageLoad ? false : true;
|
||||||
const showSaveProgressModal = isEmailInStoreOnPageLoad ? false : true;
|
const showSaveProgressModal = isEmailInStoreOnPageLoad ? false : true;
|
||||||
|
const shouldSkipToInsurance =
|
||||||
|
getBoolFromString(
|
||||||
|
experimentMixin.methods.getSettingValue(experimentSettings.SKIP_TO_INSURANCE)
|
||||||
|
) &&
|
||||||
|
shouldExposeSkipQuote &&
|
||||||
|
!hasExposedSkipQuote;
|
||||||
|
|
||||||
const lineItems = deepClone(store.getters.order.lineItems);
|
const lineItems = deepClone(store.getters.order.lineItems);
|
||||||
lineItems.vaps = lineItems.vaps ?? [];
|
lineItems.vaps = lineItems.vaps ?? [];
|
||||||
|
|
@ -302,6 +339,7 @@ export default {
|
||||||
vm.availableLineItems = pricingResults;
|
vm.availableLineItems = pricingResults;
|
||||||
vm.holdParentAccountNumber = holdParentAccountNumber;
|
vm.holdParentAccountNumber = holdParentAccountNumber;
|
||||||
vm.holdBillToAccountNumber = holdBillToAccountNumber;
|
vm.holdBillToAccountNumber = holdBillToAccountNumber;
|
||||||
|
vm.skipToInsurance = shouldSkipToInsurance;
|
||||||
|
|
||||||
if (revalidatePromoResponse) {
|
if (revalidatePromoResponse) {
|
||||||
const revalidateAlerts = buildToastMessagesFromRevalidateOrValidatePromoResponse(
|
const revalidateAlerts = buildToastMessagesFromRevalidateOrValidatePromoResponse(
|
||||||
|
|
@ -434,21 +472,16 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// did user intentionally select insurance?
|
const insuranceSelection = true;
|
||||||
vm.isInsuranceSelected = true;
|
const servicePackage = store.getters.externalParameterQuote.servicePackage;
|
||||||
vm.servicePackage = store.getters.externalParameterQuote.servicePackage;
|
|
||||||
await nextTick();
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
vm.servicePackage != null &&
|
servicePackage != null &&
|
||||||
isExternalParameter === externalParameterStatus.ACTIVE
|
isExternalParameter === externalParameterStatus.ACTIVE
|
||||||
) {
|
) {
|
||||||
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
|
await vm.skip(insuranceSelection, servicePackage);
|
||||||
if (isValid) {
|
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
|
||||||
vm.forwardButtonAction();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
} else {
|
} else {
|
||||||
if (externalThreshold) thresholdToUse = externalThreshold;
|
if (externalThreshold) thresholdToUse = externalThreshold;
|
||||||
|
|
@ -467,6 +500,11 @@ export default {
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vm.skipToInsurance && !vm.showSaveProgressPopup) {
|
||||||
|
// skip ahead only if no email popup.
|
||||||
|
await vm.skip(true, externalParamPackageLabels.GLASS_ONLY);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -482,6 +520,7 @@ export default {
|
||||||
showSaveProgressModal: null,
|
showSaveProgressModal: null,
|
||||||
isSaveProgressComplete: null,
|
isSaveProgressComplete: null,
|
||||||
packageNumber: null,
|
packageNumber: null,
|
||||||
|
skipToInsurance: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -584,8 +623,13 @@ export default {
|
||||||
updateSaveProgressAsSaved() {
|
updateSaveProgressAsSaved() {
|
||||||
this.showSaveProgressModal = false;
|
this.showSaveProgressModal = false;
|
||||||
},
|
},
|
||||||
closeSaveProgressPopup() {
|
async closeSaveProgressPopup() {
|
||||||
this.showSaveProgressPopup = false;
|
this.showSaveProgressPopup = false;
|
||||||
|
|
||||||
|
if (this.skipToInsurance) {
|
||||||
|
// skip ahead now if in IGQ skip experiment
|
||||||
|
await this.skip(true, externalParamPackageLabels.GLASS_ONLY);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
forwardButtonAction() {
|
forwardButtonAction() {
|
||||||
this.dispatchStoreAction(
|
this.dispatchStoreAction(
|
||||||
|
|
@ -729,6 +773,20 @@ export default {
|
||||||
this.pushEventToGA("quote", this.GaActions.SERVICE_PACKAGE_PRICE, eventLabel, true);
|
this.pushEventToGA("quote", this.GaActions.SERVICE_PACKAGE_PRICE, eventLabel, true);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
async skip(insuranceSelection, packageSelection) {
|
||||||
|
this.isInsuranceSelected = insuranceSelection;
|
||||||
|
this.servicePackage = packageSelection;
|
||||||
|
|
||||||
|
// Allow selections to filter through sub-logic
|
||||||
|
await nextTick();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const isValid = await baseMixin.methods.isFormValid(this.$refs.theForm);
|
||||||
|
if (isValid) {
|
||||||
|
showFmgLoadingModal(true);
|
||||||
|
await this.forwardButtonAction();
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
lineItemsCloneForWatcher: {
|
lineItemsCloneForWatcher: {
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,11 @@ export default {
|
||||||
|
|
||||||
this.$emit("servicePackageDiscountSelected", supportingItems);
|
this.$emit("servicePackageDiscountSelected", supportingItems);
|
||||||
},
|
},
|
||||||
|
servicePackage(newValue) {
|
||||||
|
if (newValue !== null) {
|
||||||
|
this.selectDefaultPackage();
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
nullSafeAvailableLineItems() {
|
nullSafeAvailableLineItems() {
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,12 @@ export default {
|
||||||
return "widget-name-" + this.cmsWidgetName;
|
return "widget-name-" + this.cmsWidgetName;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
if (!store.getters.externalParameterState?.isExternalParameter) {
|
||||||
|
showFmgLoadingModal(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function encodeUriData(payload) {
|
function encodeUriData(payload) {
|
||||||
|
|
|
||||||
|
|
@ -433,9 +433,6 @@ router.afterEach(async (to, from) => {
|
||||||
await saveSession({ pageNameToLog: to.query.fmgPage });
|
await saveSession({ pageNameToLog: to.query.fmgPage });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!store.getters.externalParameterState?.isExternalParameter) {
|
|
||||||
showFmgLoadingModal(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push page view to GA
|
// Push page view to GA
|
||||||
analyticsMixin.methods.pushPageViewToGA();
|
analyticsMixin.methods.pushPageViewToGA();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue