diff --git a/src/constants/experiments.js b/src/constants/experiments.js index 4fab998af..8df02597c 100644 --- a/src/constants/experiments.js +++ b/src/constants/experiments.js @@ -58,6 +58,8 @@ const experimentSettings = { TIER_ONE: "TierOne", TIER_TWO: "TierTwo", TIER_THREE: "TierThree", + TIER_TWO_DESCRIPTION: "TierTwo_Description", + TIER_THREE_DESCRIPTION: "TierThree_Description", // Consent Management SHOW_CONSENT_MANAGEMENT: "ShowConsentManagement", diff --git a/src/experiment-components/service-package-radio-for-afterpay.vue b/src/experiment-components/service-package-radio-for-afterpay.vue index 7f7e91084..1e896b3f7 100644 --- a/src/experiment-components/service-package-radio-for-afterpay.vue +++ b/src/experiment-components/service-package-radio-for-afterpay.vue @@ -4,6 +4,7 @@ class="package-label" :class="[ this.buttonLabelSubCopy ? 'has-subheader' : '', + this.additionalButtonData?.packageDescription ? 'has-description' : '', this.additionalButtonData.isInsuranceSelected ? 'is-insurance' : '', this.hasPackageDiscount() ? 'has-package-discount' : '', ]" @@ -13,6 +14,10 @@
+
.package-specs { display: inline-flex; } } //Package container height with package discount AND "most popular" label - &.has-package-discount.has-subheader { + &.has-package-discount.has-subheader, + &.has-package-discount.has-description { min-height: 170px; } + &.has-package-discount.has-subheader.has-description { + min-height: 190px; + } //Package container height with package discount only &.has-package-discount { min-height: 136px; @@ -307,30 +318,28 @@ export default { &:checked { + .package-label { + max-height: 1000px; + border: 1px solid $blue; + .package-specs { - max-height: 1000px; - } - } - + .package-label { - .package-specs { + max-height: none; + .hide-when-closed { - display: block; + max-height: none; + overflow: visible; + opacity: 1; + transition: opacity 0.2s ease 0.15s; } } - } - + .package-label { - border: 1px solid $blue; - max-height: 500px; + .special-save-box { background-color: $green-100; } - } - + .package-label { + &:before { box-shadow: 0px 0px 0px 1px $blue; } - } - + .package-label { + &:after { background: $blue; } @@ -356,8 +365,9 @@ export default { flex-direction: column; width: 100%; transition: all 0.5s ease; + @include media-breakpoint-up(md) { - max-height: 500px; + max-height: none; } .row { @@ -378,6 +388,13 @@ export default { font-size: 0.75rem; margin-left: auto; } + &.package-description { + color: $gray-550; + font-size: 0.875rem; + font-weight: 400; + font-style: italic; + white-space: normal; + } } span { &.service-package-discount { @@ -441,10 +458,17 @@ export default { } .hide-when-closed { - display: none; + display: flex; + flex-direction: column; + max-height: 0; + overflow: hidden; + opacity: 0; + transition: opacity 0.15s ease; + @include media-breakpoint-up(md) { - display: flex; - flex-direction: column; + max-height: none; + opacity: 1; + overflow: visible; } } } diff --git a/src/experiment-components/service-package-radio.vue b/src/experiment-components/service-package-radio.vue index a116fecd8..763035ff0 100644 --- a/src/experiment-components/service-package-radio.vue +++ b/src/experiment-components/service-package-radio.vue @@ -4,6 +4,7 @@ class="package-label pricing-by-day-pkg-lbl" :class="[ this.buttonLabelSubCopy ? 'has-subheader' : '', + this.additionalButtonData?.packageDescription ? 'has-description' : '', !this.additionalButtonData.hasDiscount ? 'adjust-top' : '', ]" for="testradio"> @@ -13,6 +14,10 @@
+
+
.package-specs {
+ display: inline-flex;
+ }
}
&:before {
@@ -288,12 +302,6 @@ export default {
height: 10px;
min-width: 10px;
}
-
- &.has-subheader {
- & > .package-specs {
- display: inline-flex;
- }
- }
}
&:hover {
@@ -309,30 +317,28 @@ export default {
&:checked {
+ .package-label {
+ max-height: 1000px;
+ border: 1px solid $blue;
+
.package-specs {
- max-height: 1000px;
- }
- }
- + .package-label {
- .package-specs {
+ max-height: none;
+
.hide-when-closed {
- display: block;
+ max-height: none;
+ overflow: visible;
+ opacity: 1;
+ transition: opacity 0.2s ease 0.15s;
}
}
- }
- + .package-label {
- border: 1px solid $blue;
- max-height: 500px;
+
.special-save-box {
background-color: $green-200;
}
- }
- + .package-label {
+
&:before {
box-shadow: 0px 0px 0px 1px $blue;
}
- }
- + .package-label {
+
&:after {
background: $blue;
}
@@ -358,8 +364,9 @@ export default {
flex-direction: column;
width: 100%;
transition: all 0.5s ease;
+
@include media-breakpoint-up(md) {
- max-height: 500px;
+ max-height: none;
}
span.pricing-by-day {
@@ -398,6 +405,13 @@ export default {
text-transform: uppercase;
font-size: 0.75rem;
}
+ &.package-description {
+ color: $gray-550;
+ font-size: 0.875rem;
+ font-weight: 400;
+ font-style: italic;
+ white-space: normal;
+ }
}
span {
&.service-package-discount-pricing-by-day {
@@ -458,10 +472,17 @@ export default {
}
.hide-when-closed {
- display: none;
+ display: flex;
+ flex-direction: column;
+ max-height: 0;
+ overflow: hidden;
+ opacity: 0;
+ transition: opacity 0.15s ease;
+
@include media-breakpoint-up(md) {
- display: flex;
- flex-direction: column;
+ max-height: none;
+ opacity: 1;
+ overflow: visible;
}
}
}
diff --git a/src/helpers/service-package-helper.js b/src/helpers/service-package-helper.js
index f43680dd2..b790385fb 100644
--- a/src/helpers/service-package-helper.js
+++ b/src/helpers/service-package-helper.js
@@ -16,6 +16,11 @@ const tierExperimentSettingKeys = {
[packageNames.TIER_THREE]: experimentSettings.TIER_THREE,
};
+const tierDescriptionExperimentSettingKeys = {
+ [packageNames.TIER_TWO]: experimentSettings.TIER_TWO_DESCRIPTION,
+ [packageNames.TIER_THREE]: experimentSettings.TIER_THREE_DESCRIPTION,
+};
+
export function containsLineItemWithPartType(typeToFind, itemsToSearch) {
const partTypeMatches = findLineItemsWithPartType(typeToFind, itemsToSearch);
return !!partTypeMatches?.length;
@@ -284,16 +289,24 @@ export function isServicePackageNameTestActive(experimentSettingsMap) {
}
export function getExperimentPackageDisplayName(tierName, experimentSettingsMap) {
+ return getExperimentPackageSetting(tierName, tierExperimentSettingKeys, experimentSettingsMap);
+}
+
+export function getExperimentPackageDescription(tierName, experimentSettingsMap) {
+ return getExperimentPackageSetting(
+ tierName,
+ tierDescriptionExperimentSettingKeys,
+ experimentSettingsMap
+ );
+}
+
+function getExperimentPackageSetting(tierName, settingKeys, experimentSettingsMap) {
if (!isServicePackageNameTestActive(experimentSettingsMap)) {
return null;
}
- const settingKey = tierExperimentSettingKeys[tierName];
- if (!settingKey) {
- return null;
- }
-
- return experimentHelper.getSettingValue(settingKey, experimentSettingsMap);
+ const settingKey = settingKeys[tierName];
+ return settingKey ? experimentHelper.getSettingValue(settingKey, experimentSettingsMap) : null;
}
function maxTier(tierA, tierB) {
diff --git a/src/helpers/service-package-helper.spec.js b/src/helpers/service-package-helper.spec.js
index 495436c8d..2e4f12e76 100644
--- a/src/helpers/service-package-helper.spec.js
+++ b/src/helpers/service-package-helper.spec.js
@@ -969,34 +969,29 @@ describe("service-package-helper.js", () => {
describe("getExperimentPackageDisplayName", () => {
const { experimentSettings } = require("@/constants/experiments");
+ const activeExperimentSettingsMap = {
+ [experimentSettings.SHOW_SERVICE_PACKAGE_NAME_TEST]: "true",
+ [experimentSettings.TIER_ONE]: "Essential",
+ [experimentSettings.TIER_TWO]: "Plus",
+ [experimentSettings.TIER_THREE]: "Full Service",
+ [experimentSettings.TIER_TWO_DESCRIPTION]: "Most popular choice",
+ [experimentSettings.TIER_THREE_DESCRIPTION]: "Best value",
+ };
it("Returns null when the experiment is not active", () => {
- const result = servicePackageHelper.getExperimentPackageDisplayName(
- packageNames.TIER_ONE,
- {}
- );
-
- expect(result).toBeNull();
+ expect(
+ servicePackageHelper.getExperimentPackageDisplayName(packageNames.TIER_ONE, {})
+ ).toBeNull();
+ expect(
+ servicePackageHelper.getExperimentPackageDescription(packageNames.TIER_TWO, {})
+ ).toBeNull();
});
it("Returns null when the test flag is not true", () => {
- const result = servicePackageHelper.getExperimentPackageDisplayName(
- packageNames.TIER_ONE,
- {
- [experimentSettings.SHOW_SERVICE_PACKAGE_NAME_TEST]: "false",
- [experimentSettings.TIER_ONE]: "Essential",
- }
- );
-
- expect(result).toBeNull();
- });
-
- it("Returns the experiment display name for each tier when active", () => {
const experimentSettingsMap = {
- [experimentSettings.SHOW_SERVICE_PACKAGE_NAME_TEST]: "true",
+ [experimentSettings.SHOW_SERVICE_PACKAGE_NAME_TEST]: "false",
[experimentSettings.TIER_ONE]: "Essential",
- [experimentSettings.TIER_TWO]: "Plus",
- [experimentSettings.TIER_THREE]: "Full Service",
+ [experimentSettings.TIER_TWO_DESCRIPTION]: "Most popular choice",
};
expect(
@@ -1004,28 +999,70 @@ describe("service-package-helper.js", () => {
packageNames.TIER_ONE,
experimentSettingsMap
)
+ ).toBeNull();
+ expect(
+ servicePackageHelper.getExperimentPackageDescription(
+ packageNames.TIER_TWO,
+ experimentSettingsMap
+ )
+ ).toBeNull();
+ });
+
+ it("Returns the experiment display name for each tier when active", () => {
+ expect(
+ servicePackageHelper.getExperimentPackageDisplayName(
+ packageNames.TIER_ONE,
+ activeExperimentSettingsMap
+ )
).toBe("Essential");
expect(
servicePackageHelper.getExperimentPackageDisplayName(
packageNames.TIER_TWO,
- experimentSettingsMap
+ activeExperimentSettingsMap
)
).toBe("Plus");
expect(
servicePackageHelper.getExperimentPackageDisplayName(
packageNames.TIER_THREE,
- experimentSettingsMap
+ activeExperimentSettingsMap
)
).toBe("Full Service");
});
- it("Returns null for an unknown tier", () => {
- const result = servicePackageHelper.getExperimentPackageDisplayName("UnknownTier", {
- [experimentSettings.SHOW_SERVICE_PACKAGE_NAME_TEST]: "true",
- [experimentSettings.TIER_ONE]: "Essential",
- });
+ it("Returns the experiment description for tier two and three when active", () => {
+ expect(
+ servicePackageHelper.getExperimentPackageDescription(
+ packageNames.TIER_TWO,
+ activeExperimentSettingsMap
+ )
+ ).toBe("Most popular choice");
+ expect(
+ servicePackageHelper.getExperimentPackageDescription(
+ packageNames.TIER_THREE,
+ activeExperimentSettingsMap
+ )
+ ).toBe("Best value");
+ });
- expect(result).toBeNull();
+ it("Returns null for unknown tiers and tiers without configured settings", () => {
+ expect(
+ servicePackageHelper.getExperimentPackageDisplayName("UnknownTier", {
+ [experimentSettings.SHOW_SERVICE_PACKAGE_NAME_TEST]: "true",
+ [experimentSettings.TIER_ONE]: "Essential",
+ })
+ ).toBeNull();
+ expect(
+ servicePackageHelper.getExperimentPackageDescription(
+ packageNames.TIER_ONE,
+ activeExperimentSettingsMap
+ )
+ ).toBeNull();
+ expect(
+ servicePackageHelper.getExperimentPackageDescription(
+ "UnknownTier",
+ activeExperimentSettingsMap
+ )
+ ).toBeNull();
});
});
});
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 1d0f78c1a..46b084d02 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
@@ -856,6 +856,52 @@ describe("service-package-question.vue, matching business rules for package disp
getExperimentPackageLabelSpy.mockRestore();
});
+ it("should use experiment package descriptions when ServicePackageNameTest is active", () => {
+ const getExperimentPackageDescriptionSpy = jest
+ .spyOn(servicePackageQuestion.methods, "getExperimentPackageDescription")
+ .mockImplementation((tierName) => {
+ const experimentPackageDescriptions = {
+ [packageNames.TIER_TWO]: "Most popular choice",
+ [packageNames.TIER_THREE]: "Best value",
+ };
+
+ return experimentPackageDescriptions[tierName] ?? null;
+ });
+
+ const packageNameKey = "05_01_CSR_Quote_Standard_Repair";
+ Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]);
+ mockProps.availableLineItems.push(driverFrontWiperLineItem);
+ mockProps.availableLineItems.push(passengerFrontWiperLineItem);
+ const wrapper = setupMocks({
+ mountOptionsMockData: {
+ store: {
+ getters: {
+ order: {
+ damage: {
+ isRepair: true,
+ glassToReplace: [],
+ },
+ },
+ hasAnyNonWindshieldGlassParts: false,
+ },
+ },
+ },
+ });
+
+ expect(
+ wrapper.vm.servicePackageAnswers[0].additionalButtonData.packageDescription
+ ).toBeNull();
+ expect(wrapper.vm.servicePackageAnswers[1].additionalButtonData.packageDescription).toBe(
+ "Most popular choice"
+ );
+ expect(wrapper.vm.servicePackageAnswers[2].additionalButtonData.packageDescription).toBe(
+ "Best value"
+ );
+ expect(wrapper.vm.servicePackageAnswers[1].buttonLabelSubCopy).toBe("MOST POPULAR");
+ expect(wrapper.vm.servicePackageAnswers[2].buttonLabelSubCopy).toBe("");
+
+ getExperimentPackageDescriptionSpy.mockRestore();
+ });
it("should use CMS package names when ServicePackageNameTest is not active", () => {
const packageNameKey = "05_01_CSR_Quote_Standard_Repair";
Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]);
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 4a54ee3f5..905898481 100644
--- a/src/layouts/quote/service-package-question/service-package-question.vue
+++ b/src/layouts/quote/service-package-question/service-package-question.vue
@@ -159,6 +159,7 @@ export default {
? false
: "Special: Save $" + this.getDiscountPrice(answer.Name),
isInsuranceSelected: this.isInsuranceSelected,
+ packageDescription: this.getExperimentPackageDescription(answer.Name),
},
}));
@@ -265,6 +266,19 @@ export default {
);
},
getExperimentPackageLabel(tierName) {
+ return this.getExperimentPackageSetting(tierName, {
+ [packageNames.TIER_ONE]: experimentSettings.TIER_ONE,
+ [packageNames.TIER_TWO]: experimentSettings.TIER_TWO,
+ [packageNames.TIER_THREE]: experimentSettings.TIER_THREE,
+ });
+ },
+ getExperimentPackageDescription(tierName) {
+ return this.getExperimentPackageSetting(tierName, {
+ [packageNames.TIER_TWO]: experimentSettings.TIER_TWO_DESCRIPTION,
+ [packageNames.TIER_THREE]: experimentSettings.TIER_THREE_DESCRIPTION,
+ });
+ },
+ getExperimentPackageSetting(tierName, tierSettingKeys) {
if (
!experimentMixin.methods.hasSettingEqualTo(
experimentSettings.SHOW_SERVICE_PACKAGE_NAME_TEST,
@@ -274,13 +288,8 @@ export default {
return null;
}
- const tierSettingKey = {
- [packageNames.TIER_ONE]: experimentSettings.TIER_ONE,
- [packageNames.TIER_TWO]: experimentSettings.TIER_TWO,
- [packageNames.TIER_THREE]: experimentSettings.TIER_THREE,
- }[tierName];
-
- return tierSettingKey ? experimentMixin.methods.getSettingValue(tierSettingKey) : null;
+ const settingKey = tierSettingKeys[tierName];
+ return settingKey ? experimentMixin.methods.getSettingValue(settingKey) : null;
},
getHeaderTextFromCms(cmsWidgetName) {
return this.getCmsContent(cmsWidgetName, "HeaderText");
diff --git a/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.vue b/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.vue
index 959c7345e..bae95af8f 100644
--- a/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.vue
+++ b/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.vue
@@ -2,7 +2,10 @@