Merge pull request #1052 from Safelite/feature/CSR-1063

Feature/csr 1063
This commit is contained in:
chloeherdsafelite 2023-04-06 13:51:17 -04:00 committed by GitHub
commit 3899b2d191
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 417 additions and 3 deletions

View file

@ -812,6 +812,87 @@ describe("service-location.vue", () => {
expect(wrapper.vm.isServiceableInshop).toEqual(false);
expect(wrapper.vm.displayNoShopsAlert).toEqual(false);
});
test("displayServiceableInshopOnly should be true if inshop is true and mobile is false", async () => {
// Arrange
getServiceabilityDetails.mockImplementation(() =>
Promise.resolve({
isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false,
})
);
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
// Assert
expect(wrapper.vm.isServiceableMobile).toEqual(false);
expect(wrapper.vm.isServiceableInshop).toEqual(true);
expect(wrapper.vm.displayServiceableInshopOnly).toEqual(true);
});
test("displayServiceableInshopOnly should be false if inshop is false", async () => {
// Arrange
getServiceabilityDetails.mockImplementation(() =>
Promise.resolve({
isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false,
})
);
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
// Assert
expect(wrapper.vm.isServiceableMobile).toEqual(false);
expect(wrapper.vm.isServiceableInshop).toEqual(false);
expect(wrapper.vm.displayServiceableInshopOnly).toEqual(false);
});
test("displayServiceableInshopOnly should be false if mobile is true", async () => {
// Arrange
getServiceabilityDetails.mockImplementation(() =>
Promise.resolve({
isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: true,
isRecalibrationServiceableMobile: true,
})
);
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
// Assert
expect(wrapper.vm.isServiceableMobile).toEqual(true);
expect(wrapper.vm.isServiceableInshop).toEqual(true);
expect(wrapper.vm.displayServiceableInshopOnly).toEqual(false);
});
});
describe("should be based only on glass serviceability if recalibration is not defined.", () => {
@ -949,6 +1030,142 @@ describe("service-location.vue", () => {
});
});
describe("should check for dual or static recalibration", () => {
test("isDualOrStaticRecalibration should be true if dual recalibration is present", async () => {
// Arrange
store.getters = {
lineItems: {
supportingItems: [
{
description: null,
kitPrice: 0,
laborAmount: 0,
partNumber: "SUPPLIES-REPAIR",
partType: "REPAIR FEE",
sellingPrice: 7.99,
},
{
description: null,
kitPrice: 0,
laborAmount: 0,
partNumber: "RECAL DUAL",
partType: "RECALIBRATION",
sellingPrice: 0,
},
],
},
order: {
serviceLocation: {
zipCode: "43235",
state: "OH",
},
},
damage: {
isRepair: false,
},
payment: {
isInsurance: false,
},
vehicle: {
registration: {
address: "5555 Sulgrave Dr",
city: "New Albany",
state: "OH",
zipCode: "43054",
},
},
};
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
// Assert
expect(wrapper.vm.isDualOrStaticRecalibration).toBe(true);
});
test("isDualOrStaticRecalibration should be true if static recalibration is present", async () => {
// Arrange
store.getters = {
lineItems: {
supportingItems: [
{
description: null,
kitPrice: 0,
laborAmount: 0,
partNumber: "SUPPLIES-REPAIR",
partType: "REPAIR FEE",
sellingPrice: 7.99,
},
{
description: null,
kitPrice: 0,
laborAmount: 0,
partNumber: "RECAL STATIC",
partType: "RECALIBRATION",
sellingPrice: 0,
},
],
},
order: {
serviceLocation: {
zipCode: "43235",
state: "OH",
},
},
damage: {
isRepair: false,
},
payment: {
isInsurance: false,
},
vehicle: {
registration: {
address: "5555 Sulgrave Dr",
city: "New Albany",
state: "OH",
zipCode: "43054",
},
},
};
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
// Assert
expect(wrapper.vm.isDualOrStaticRecalibration).toBe(true);
});
test("isDualOrStaticRecalibration should be false if neither are present.", async () => {
// Arrange
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
// Assert
expect(wrapper.vm.isDualOrStaticRecalibration).toBe(false);
});
});
describe("should properly display alerts.", () => {
test("Should show mobile-only error if only mobile is available.", async () => {
// Arrange
@ -1057,6 +1274,150 @@ describe("service-location.vue", () => {
// Assert
expect(alertComponent.exists()).toBe(false);
});
test("Should show inshop-only error if only inshop is available", async () => {
// Arrange
getServiceabilityDetails.mockImplementation(() =>
Promise.resolve({
isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false,
})
);
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
const alertComponent = wrapper.findComponent({ ref: "alertInshopOnly" });
// Assert
expect(alertComponent.exists()).toBe(true);
});
test("Should not show inshop-only error if not inshop-only", async () => {
// Arrange
getServiceabilityDetails.mockImplementation(() =>
Promise.resolve({
isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false,
})
);
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
const alertComponent = wrapper.findComponent({ ref: "alertInshopOnly" });
// Assert
expect(alertComponent.exists()).toBe(false);
});
test("Should not show inshop-only error if dual or static recalibration, but should show that error instead.", async () => {
// Arrange
store.getters = {
lineItems: {
supportingItems: [
{
description: null,
kitPrice: 0,
laborAmount: 0,
partNumber: "SUPPLIES-REPAIR",
partType: "REPAIR FEE",
sellingPrice: 7.99,
},
{
description: null,
kitPrice: 0,
laborAmount: 0,
partNumber: "RECAL STATIC",
partType: "RECALIBRATION",
sellingPrice: 0,
},
],
},
order: {
serviceLocation: {
zipCode: "43235",
state: "OH",
},
},
damage: {
isRepair: false,
},
payment: {
isInsurance: false,
},
vehicle: {
registration: {
address: "5555 Sulgrave Dr",
city: "New Albany",
state: "OH",
zipCode: "43054",
},
},
};
getServiceabilityDetails.mockImplementation(() =>
Promise.resolve({
isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false,
})
);
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
const alertInshopComponent = wrapper.findComponent({ ref: "alertInshopOnly" });
const alertRecalComponent = wrapper.findComponent({ ref: "alertRecalNoMobile" });
// Assert
expect(alertInshopComponent.exists()).toBe(false);
expect(alertRecalComponent.exists()).toBe(true);
});
test("Should not show dual/static recalibration error if not those recalibration types", async () => {
// Arrange
const { wrapper } = setupMocks({});
// Act
await serviceLocation.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "serviceLocation" } },
undefined,
(c) => c(wrapper.vm)
);
const alertComponent = wrapper.findComponent({ ref: "alertRecalNoMobile" });
// Assert
expect(alertComponent.exists()).toBe(false);
});
});
});
});

View file

@ -25,6 +25,19 @@
cmsWidgetName="AlertMobileOnlyWidget"
v-if="displayServiceableMobileOnly"
alertClass="alert-warning" />
<alert
ref="alertRecalNoMobile"
class="my-4"
cmsWidgetName="AlertRecalNoMobileWidget"
v-if="displayRecalibrationWarning"
@text-link-clicked="openModalAction"
alertClass="alert-warning" />
<alert
ref="alertInshopOnly"
class="my-4"
cmsWidgetName="AlertInshopOnlyWidget"
v-if="displayServiceableInshopOnly"
alertClass="alert-warning" />
<alert
ref="alertNoShops"
class="my-4"
@ -56,6 +69,7 @@
validationRules="mobile-location-required"
hideInput
centerErrorMessage />
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
<funnel-footer
cmsWidgetName="FunnelFooterWidget"
ref="funnelFooter"
@ -78,6 +92,7 @@ import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-heade
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
import { Form, defineRule } from "vee-validate";
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
// Supporting files
import baseMixin from "@/mixins/base-mixin.js";
@ -222,6 +237,23 @@ export default {
return this.isGlassServiceableInshop;
}
},
isDualOrStaticRecalibration() {
const supportingItems = store.getters.lineItems.supportingItems;
return supportingItems.some(
(item) => item.partNumber === "RECAL STATIC" || item.partNumber === "RECAL DUAL"
);
},
displayRecalibrationWarning() {
return this.isDualOrStaticRecalibration;
},
displayServiceableInshopOnly() {
return (
!this.displayRecalibrationWarning &&
this.isServiceableInshop &&
!this.isServiceableMobile
);
},
displayMilitaryZipAlert() {
return this.zipContainsMilitaryBase && this.isServiceableMobile;
},
@ -297,6 +329,9 @@ export default {
this.$route
);
},
openModalAction(modalName) {
this.$refs[modalName].openModal();
},
},
components: {
alert,
@ -309,6 +344,7 @@ export default {
Form,
loadingModal,
textboxQuestion,
contentGroupModal,
},
};
</script>

View file

@ -11,12 +11,11 @@
<template v-for="paragraph in splitAlertCopyForParagraphTag" :key="paragraph">
<p
class="m-0 text-body small"
v-if="!doesCopyContainRouterLink(paragraph)"
v-if="!doesCopyContainRouterLink(paragraph) && !doesCopyContainTextLink(paragraph)"
v-html="paragraph"></p>
<p class="m-0 text-body small" v-else>
<template v-for="copy in splitCopyOnCMSPlaceHolder(paragraph)" :key="copy">
<span v-if="!doesCopyContainRouterLink(copy)" v-html="copy"></span>
<span v-else>
<span v-if="doesCopyContainRouterLink(copy)">
<router-link
:to="{
query: { [pageQueryString]: `${getRouterLinkRouteFromCopy(copy)}` },
@ -25,6 +24,18 @@
>{{ getRouterLinkDisplayTextFromCopy(copy) }}</router-link
>
</span>
<span v-else-if="doesCopyContainTextLink(copy)">
<textLink
linkType="text"
:text="getRouterLinkDisplayTextFromCopy(copy)"
href="#!"
@click-event="
$emit('textLinkClicked', getRouterLinkRouteFromCopy(copy))
"
:data-bs-target="'#' + getRouterLinkRouteFromCopy(copy)"
aria-label="Modal window" />
</span>
<span v-else v-html="copy"></span>
</template>
</p>
</template>
@ -40,11 +51,13 @@
<script>
import {
doesCopyContainRouterLink,
doesCopyContainTextLink,
splitCopyOnCMSPlaceHolder,
getRouterLinkRouteFromCopy,
getRouterLinkDisplayTextFromCopy,
splitCMSCopyOnParagraphTag,
} from "@/helpers/cms-content-helper";
import textLink from "@/ux-components/text-link/text-link";
import { applicationConfig } from "@/constants/application-config";
export default {
@ -96,6 +109,7 @@ export default {
methods: {
doesCopyContainRouterLink,
splitCopyOnCMSPlaceHolder,
doesCopyContainTextLink,
getRouterLinkRouteFromCopy,
getRouterLinkDisplayTextFromCopy,
ensureAlertIsInViewPort() {
@ -120,6 +134,9 @@ export default {
mounted() {
this.ensureAlertIsInViewPort();
},
components: {
textLink,
},
};
</script>