Merge pull request #2049 from Safelite/feature/CSR-2249

Feature/csr 2249
This commit is contained in:
CarlNation 2024-10-28 08:57:54 -04:00 committed by GitHub
commit 471fed22e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 105 additions and 41 deletions

View file

@ -12,6 +12,7 @@ const experimentSettings = {
SUBMIT_ORDER_ENABLE_PIA: "SubmitOrder_Enable_PIA",
IS_EMAIL_OPTIONAL: "isEmailOptional",
SERVICE_PACKAGE_DISCOUNT: "OfferServicePackageDiscount",
PROMO_ON_PACKAGE: "Offer_Promo_On_Pkg",
RECAL_PRICE_REMOVE: "RecalPriceRemove",
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold",
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold",

View file

@ -10,6 +10,7 @@ import {
containsLineItemWithPartType,
findLineItemsWithPartType,
} from "@/helpers/service-package-helper";
import { experimentSettings } from "@/constants/experiments";
import baseMixin from "@/mixins/base-mixin.js";
import { partTypeStrings } from "@/constants/part-type-strings";
import { nextTick } from "vue";
@ -19,6 +20,18 @@ jest.mock("@/store", () => ({
dispatch: jest.fn(),
}));
const mockExperimentSettings = experimentSettings;
jest.mock("@/mixins/experiment-mixin.js", () => ({
methods: {
getSettingValue(settingName) {
if (settingName === mockExperimentSettings.PROMO_ON_PACKAGE) {
return true;
}
},
},
}));
describe("service-package-question.vue", () => {
beforeEach(async () => {
processedCmsContent = inputQuestionWidgetAnswers;
@ -162,6 +175,19 @@ describe("service-package-question.vue", () => {
wrapper.vm.servicePackageAnswers[0].buttonAuxillaryCopy.includes("As little as")
).toBe(true);
});
it("should show service package discount when insurance is not selected", () => {
// Arrange
mockProps.isInsuranceSelected = false;
const wrapper = setupMocks({});
// Act
// Assert
expect(
wrapper.vm.servicePackageAnswers[0].additionalButtonData.Text.includes(
"Special: Save $"
)
).toBe(true);
});
it("should return [] from nullSafeAvailableLineItems and not error out if availableLineItems is null", () => {
// Arrange
mockProps.availableLineItems = null;

View file

@ -36,6 +36,8 @@ import {
getLineItemsThatMatchPromos,
} from "@/helpers/promotions-helper";
import { containsRecalParts, getItemsWithoutRecalParts } from "@/helpers/recal-helper";
import experimentMixin from "@/mixins/experiment-mixin.js";
import { experimentSettings } from "@/constants/experiments";
export default {
name: "servicePackageQuestion",
@ -129,16 +131,22 @@ export default {
buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.SubWidgetName),
buttonBodyCopy: this.getBodyTextFromCms(answer.SubWidgetName),
//The package supports service-package-discount if it has the text value in CMS
buttonAuxillaryCopy: this.getDiscountedPackagePriceString(
answer.Name,
this.isServicePackageDiscountOnOrder && answer.Text != ""
),
buttonAuxillaryCopy: this.isInsuranceSelected
? this.getDiscountedPackagePriceString(answer.Name, false)
: this.getDiscountedPackagePriceString(
answer.Name,
this.isServicePackageDiscountOnOrder &&
this.discountPackageNames == answer.Name
),
buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName),
additionalButtonData: {
strikeThroughPrice: this.getPackagePriceString(answer.Name),
servicePackageDiscount:
this.isServicePackageDiscountOnOrder && answer.Text != "",
Text: answer.Text + this.getServicePackageDiscountPrice(),
this.isServicePackageDiscountOnOrder &&
this.discountPackageNames == answer.Name,
Text: this.isInsuranceSelected
? false
: "Special: Save $" + this.getServicePackageDiscountPrice(),
},
}));
return modifiedAnswers;
@ -149,6 +157,21 @@ export default {
this.nullSafeAvailableLineItems
);
},
discountPackageNames() {
const discountServicePackage = experimentMixin.methods.getSettingValue(
experimentSettings.PROMO_ON_PACKAGE
);
switch (discountServicePackage) {
case "ECON":
return packageNames.TIER_ONE;
case "STANDARD":
return packageNames.TIER_TWO;
case "PREMIUM":
return packageNames.TIER_THREE;
default:
return null;
}
},
frontWipersApplicableForTierTwo() {
return shouldFrontWipersBeAvailable(
this.glassToReplace,

View file

@ -1,15 +1,8 @@
<template>
<div
:class="[this.additionalButtonData.Text ? 'discount-text' : '']"
v-if="this.additionalButtonData.servicePackageDiscount"
v-html="this.additionalButtonData.Text"></div>
<baseInputButton v-bind="$props" @buttonClicked="handleAnswerChange" v-model="selectedValue">
<div
class="package-label"
:class="[
this.buttonLabelSubCopy ? 'has-subheader' : '',
this.additionalButtonData.servicePackageDiscount ? 'has-text' : '',
]"
:class="[this.buttonLabelSubCopy ? 'has-subheader' : '']"
for="testradio">
<div class="package-specs">
<div v-if="this.additionalButtonData.servicePackageDiscount" class="row">
@ -82,6 +75,15 @@
v-if="this.buttonFooterCopy"
v-html="this.buttonFooterCopy"></div>
</div>
<div
v-if="
this.additionalButtonData.servicePackageDiscount &&
this.additionalButtonData.Text
"
class="special-save-box">
<span v-html="this.additionalButtonData.Text"></span>
</div>
</div>
</div>
</baseInputButton>
@ -143,20 +145,13 @@ export default {
margin: 1rem 0.5rem;
display: flex;
flex-direction: column;
align-self: flex-end;
}
label {
display: block;
@include media-breakpoint-up(md) {
display: flex;
min-height: 336px;
}
//Unique breakpoint for this page only to accommodate price spacing issues
//from use of position: absolute on .service-package-discount (per Design Team request)
@media only screen and (min-width: 860px) {
display: flex;
min-height: 276px;
height: 100%;
}
}
@ -179,19 +174,16 @@ export default {
border-radius: 0.5rem;
overflow: hidden;
min-height: 60px;
max-height: 100px;
max-height: 126px;
@include media-breakpoint-up(md) {
max-height: 500px;
padding-bottom: 3rem;
}
transition: max-height 0.25s ease-in;
&.has-subheader {
min-height: 80px;
}
&.has-text {
border-radius: 0 0 0.5rem 0.5rem;
border: 1px solid $green;
}
&:before {
content: "";
@ -245,6 +237,9 @@ export default {
background-color: $blue-100;
border: 1px solid $blue;
max-height: 500px;
.special-save-box {
background-color: $green-200;
}
}
+ .package-label {
&:before {
@ -294,8 +289,8 @@ export default {
bottom: 0.75rem;
left: 0;
width: 100%;
text-align: center;
font-size: 1.125rem;
margin-left: 1.25rem;
font-weight: 600;
}
span.strikethrough-price {
text-decoration: line-through;
@ -316,28 +311,32 @@ export default {
&.service-package-discount {
color: $green;
text-align: end;
font-weight: 500;
font-size: 13px;
font-weight: 600;
font-size: 0.875rem;
display: flex;
justify-content: space-between;
div.strikethrough-discount-price {
text-decoration: line-through;
margin-right: 0;
font-weight: 400;
font-size: 0.875rem;
margin-right: 0.5rem;
font-weight: 600;
font-size: 0.75rem;
line-height: 20px;
color: $gray-500;
padding-right: 2px;
color: $gray-550;
@include media-breakpoint-up(md) {
margin-right: 0.5rem;
font-size: 0.75rem;
}
}
div.discount-price {
color: $green;
font-weight: 600;
font-size: 1.625rem;
}
@include media-breakpoint-up(md) {
position: absolute;
bottom: 0.75rem;
left: 0;
width: 100%;
text-align: center;
left: 0.5rem;
display: flex;
align-items: center;
justify-content: flex-start;
}
}
}
@ -388,6 +387,21 @@ export default {
font-weight: 600;
letter-spacing: 0.75px;
}
.special-save-box {
background-color: $green-100;
display: flex;
flex-direction: row;
margin: auto;
margin-left: -2rem;
padding: 0.5rem 1rem;
border-radius: 0.25rem;
margin-top: 0.5rem;
span {
color: $green;
font-size: 0.875rem;
font-weight: 600;
}
}
}
}
</style>