Merge pull request #1052 from Safelite/feature/CSR-1063
Feature/csr 1063
This commit is contained in:
commit
3899b2d191
3 changed files with 417 additions and 3 deletions
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue