Merge pull request #1415 from Safelite/feature/CSR-1395-tech-review-changes

Feature/csr 1395 tech review changes
This commit is contained in:
Leah Schumann 2023-10-17 08:48:17 -04:00 committed by GitHub
commit 1e20dd96d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 237 additions and 209 deletions

View file

@ -31,5 +31,5 @@ module.exports = {
}, },
}, },
// Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit // Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit
silent: true, //silent: true,
}; };

View file

@ -46,6 +46,18 @@ export async function getServiceabilityDetails(serviceZipCode, lineItems, pageNa
return Promise.resolve(serviceabilityDetails); return Promise.resolve(serviceabilityDetails);
} }
export async function getShopProviderData(serviceZipCode) {
const shopProviderData = await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_PROVIDERS,
{
serviceZipCode: serviceZipCode,
},
"service-location"
);
return Promise.resolve(shopProviderData);
}
export async function getAvailabilityRating( export async function getAvailabilityRating(
startDate, startDate,
endDate, endDate,

View file

@ -145,9 +145,6 @@ export default {
alertInvalidZipWidgetName: String, alertInvalidZipWidgetName: String,
customComponentId: String, customComponentId: String,
validationRules: String, validationRules: String,
onZipUpdateCallback: {
type: Function,
},
}, },
computed: { computed: {
mobileLocationLinkPromptText() { mobileLocationLinkPromptText() {
@ -256,10 +253,7 @@ export default {
this.$emit("updated-serviceability", serviceabilityDetails.data); this.$emit("updated-serviceability", serviceabilityDetails.data);
this.$emit("updated-contains-military-base", zipCodeData.containsMilitaryBase); this.$emit("updated-contains-military-base", zipCodeData.containsMilitaryBase);
if (this.onZipUpdateCallback) { // update the page level model
await this.onZipUpdateCallback(serviceZipCode);
}
// Update the page level model
this.$emit("update:modelValue", this.internalModel); this.$emit("update:modelValue", this.internalModel);
this.closeModal(); this.closeModal();

View file

@ -7,10 +7,7 @@ import { getMountOptions } from "@/helpers/unit-test-helper";
import store from "@/store"; import store from "@/store";
import baseMixin from "@/mixins/base-mixin"; import baseMixin from "@/mixins/base-mixin";
import { import { getServiceabilityDetails } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
getServiceabilityDetails,
Provider,
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
// Define Mocks // Define Mocks
jest.mock("@/helpers/cms-content-helper", () => ({ jest.mock("@/helpers/cms-content-helper", () => ({
@ -21,7 +18,7 @@ jest.mock("@/helpers/cms-content-helper", () => ({
jest.mock("./classes/provider"); jest.mock("./classes/provider");
const mockGetPricedMobileFeePart = (mockServiceZipCode) => { let mockGetPricedMobileFeePart = (mockServiceZipCode) => {
let mobileFeePart = {}; let mobileFeePart = {};
if (mockServiceZipCode === "43235") { if (mockServiceZipCode === "43235") {
@ -38,7 +35,7 @@ const mockGetPricedMobileFeePart = (mockServiceZipCode) => {
return Promise.resolve(mobileFeePart); return Promise.resolve(mobileFeePart);
}; };
const mockGetServiceabilityDetails = (mockServiceZipCode) => { let mockGetServiceabilityDetails = (mockServiceZipCode) => {
const serviceabilityDetails = { const serviceabilityDetails = {
isGlassServiceableInshop: true, isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true, isRecalibrationServiceableInshop: true,
@ -49,6 +46,17 @@ const mockGetServiceabilityDetails = (mockServiceZipCode) => {
return Promise.resolve(serviceabilityDetails); return Promise.resolve(serviceabilityDetails);
}; };
let mockGetShopProviderData = (mockServiceZipCode) => {
const result = {
data: {
mobileProviderNumber: "001820",
shopProviders: [{}],
},
};
return Promise.resolve(result);
};
jest.mock( jest.mock(
"@/layouts/service-location/helpers/service-location-helper/service-location-helper", "@/layouts/service-location/helpers/service-location-helper/service-location-helper",
() => ({ () => ({
@ -58,6 +66,9 @@ jest.mock(
getServiceabilityDetails: jest.fn((mockServiceZipCode) => { getServiceabilityDetails: jest.fn((mockServiceZipCode) => {
return mockGetServiceabilityDetails(mockServiceZipCode); return mockGetServiceabilityDetails(mockServiceZipCode);
}), }),
getShopProviderData: jest.fn((mockServiceZipCode) => {
return mockGetShopProviderData(mockServiceZipCode);
}),
}) })
); );
@ -554,14 +565,13 @@ describe("service-location.vue", () => {
describe("should be logical AND when recalibration is defined.", () => { describe("should be logical AND when recalibration is defined.", () => {
test("T & T => T", async () => { test("T & T => T", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: true, isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true, isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: true, isGlassServiceableMobile: true,
isRecalibrationServiceableMobile: true, isRecalibrationServiceableMobile: true,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -582,14 +592,13 @@ describe("service-location.vue", () => {
test("T & F => F", async () => { test("T & F => F", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: true, isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: false, isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: true, isGlassServiceableMobile: true,
isRecalibrationServiceableMobile: false, isRecalibrationServiceableMobile: false,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -610,14 +619,13 @@ describe("service-location.vue", () => {
test("F & T => F", async () => { test("F & T => F", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: false, isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: true, isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: false, isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: true, isRecalibrationServiceableMobile: true,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -638,14 +646,13 @@ describe("service-location.vue", () => {
test("F & F => F", async () => { test("F & F => F", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: false, isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: false, isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: false, isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false, isRecalibrationServiceableMobile: false,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -666,14 +673,13 @@ describe("service-location.vue", () => {
test("displayServiceableMobileOnly should be true if mobile is true and inshop is false.", async () => { test("displayServiceableMobileOnly should be true if mobile is true and inshop is false.", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: false, isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: false, isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: true, isGlassServiceableMobile: true,
isRecalibrationServiceableMobile: true, isRecalibrationServiceableMobile: true,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -695,14 +701,13 @@ describe("service-location.vue", () => {
test("displayServiceableMobileOnly should be false if mobile is false.", async () => { test("displayServiceableMobileOnly should be false if mobile is false.", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: false, isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: false, isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: false, isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false, isRecalibrationServiceableMobile: false,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -724,14 +729,13 @@ describe("service-location.vue", () => {
test("displayServiceableMobileOnly should be false if inShop is true", async () => { test("displayServiceableMobileOnly should be false if inShop is true", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: true, isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true, isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: true, isGlassServiceableMobile: true,
isRecalibrationServiceableMobile: true, isRecalibrationServiceableMobile: true,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -753,14 +757,13 @@ describe("service-location.vue", () => {
test("displayNoShopsAlert should be true if inShop is false and mobile is false", async () => { test("displayNoShopsAlert should be true if inShop is false and mobile is false", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: false, isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: false, isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: false, isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false, isRecalibrationServiceableMobile: false,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -782,14 +785,13 @@ describe("service-location.vue", () => {
test("displayNoShopsAlert should be false if inShop is true and mobile is true", async () => { test("displayNoShopsAlert should be false if inShop is true and mobile is true", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: true, isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true, isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: true, isGlassServiceableMobile: true,
isRecalibrationServiceableMobile: true, isRecalibrationServiceableMobile: true,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -811,14 +813,13 @@ describe("service-location.vue", () => {
test("displayNoShopsAlert should be false if inShop is true", async () => { test("displayNoShopsAlert should be false if inShop is true", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: true, isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true, isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: false, isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false, isRecalibrationServiceableMobile: false,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -840,14 +841,13 @@ describe("service-location.vue", () => {
test("displayNoShopsAlert should be false if mobile is true", async () => { test("displayNoShopsAlert should be false if mobile is true", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: false, isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: false, isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: true, isGlassServiceableMobile: true,
isRecalibrationServiceableMobile: true, isRecalibrationServiceableMobile: true,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -869,14 +869,13 @@ describe("service-location.vue", () => {
test("displayServiceableInshopOnly should be true if inshop is true and mobile is false", async () => { test("displayServiceableInshopOnly should be true if inshop is true and mobile is false", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: true, isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true, isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: false, isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false, isRecalibrationServiceableMobile: false,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -898,14 +897,13 @@ describe("service-location.vue", () => {
test("displayServiceableInshopOnly should be false if inshop is false", async () => { test("displayServiceableInshopOnly should be false if inshop is false", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: false, isGlassServiceableInshop: false,
isRecalibrationServiceableInshop: false, isRecalibrationServiceableInshop: false,
isGlassServiceableMobile: false, isGlassServiceableMobile: false,
isRecalibrationServiceableMobile: false, isRecalibrationServiceableMobile: false,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -927,14 +925,13 @@ describe("service-location.vue", () => {
test("displayServiceableInshopOnly should be false if mobile is true", async () => { test("displayServiceableInshopOnly should be false if mobile is true", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: true, isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true, isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: true, isGlassServiceableMobile: true,
isRecalibrationServiceableMobile: true, isRecalibrationServiceableMobile: true,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
@ -956,14 +953,13 @@ describe("service-location.vue", () => {
test("displayServiceableInshopOnly should be false in the dual/static recalibration scenario", async () => { test("displayServiceableInshopOnly should be false in the dual/static recalibration scenario", async () => {
// Arrange // Arrange
getServiceabilityDetails.mockImplementation(() => mockGetServiceabilityDetails = () =>
Promise.resolve({ Promise.resolve({
isGlassServiceableInshop: true, isGlassServiceableInshop: true,
isRecalibrationServiceableInshop: true, isRecalibrationServiceableInshop: true,
isGlassServiceableMobile: true, isGlassServiceableMobile: true,
isRecalibrationServiceableMobile: false, isRecalibrationServiceableMobile: false,
}) });
);
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});

View file

@ -19,8 +19,7 @@
@updated-serviceability="setServiceabilityDetails" @updated-serviceability="setServiceabilityDetails"
@updated-contains-military-base="setContainsMilitaryBase" @updated-contains-military-base="setContainsMilitaryBase"
linkWidgetName="ServiceZipLinkWidget" linkWidgetName="ServiceZipLinkWidget"
modalWidgetName="ServiceZipModalWidget" modalWidgetName="ServiceZipModalWidget" />
:onZipUpdateCallback="reloadShopData" />
<alert <alert
ref="alertMilitaryBaseZip" ref="alertMilitaryBaseZip"
@ -86,16 +85,15 @@
validationRules="mobile-location-required" validationRules="mobile-location-required"
ref="mobileLocationQuestions" ref="mobileLocationQuestions"
linkWidgetName="MobileLocationLinkWidget" linkWidgetName="MobileLocationLinkWidget"
modalWidgetName="MobileLocationModalWidget" modalWidgetName="MobileLocationModalWidget" />
:onZipUpdateCallback="reloadShopData" />
<shopQuestion <shopQuestion
ref="shopQuestion" ref="shopQuestion"
v-show="isShopQuestionDisplayed" v-show="isShopQuestionDisplayed"
v-model="selectedProvider" v-model="selectedProvider"
:selectedAppointmentType="selectedAppointmentType" :selectedAppointmentType="selectedAppointmentType"
:shopProviderData="shopProviderData"
:isDisplayed="isShopQuestionDisplayed" :isDisplayed="isShopQuestionDisplayed"
@updated-shop-list="setUpdatedShopList"
cmsWidgetName="ShopQuestionWidget" /> cmsWidgetName="ShopQuestionWidget" />
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" /> <contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
@ -135,6 +133,7 @@ import { settleAllPromises } from "@/helpers/layout-helper";
import { import {
getPricedMobileFeePart, getPricedMobileFeePart,
getServiceabilityDetails, getServiceabilityDetails,
getShopProviderData,
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper"; } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
import { Provider } from "@/layouts/service-location/classes/provider"; import { Provider } from "@/layouts/service-location/classes/provider";
@ -180,7 +179,7 @@ export default {
mobileFeePart: null, mobileFeePart: null,
zipContainsMilitaryBase: false, zipContainsMilitaryBase: false,
zipCodeCtu: null, zipCodeCtu: null,
providerData: null, shopProviderData: null,
}; };
}, },
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
@ -188,7 +187,10 @@ export default {
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const serviceZipCode = store.getters.order.serviceLocation.zipCode; const serviceZipCode = store.getters.order.serviceLocation.zipCode;
const getZipCodeData = baseMixin.methods.getZipCodeData(serviceZipCode, "service-location"); const zipCodeDataPromise = baseMixin.methods.getZipCodeData(
serviceZipCode,
"service-location"
);
const serviceabilityDetailsPromise = getServiceabilityDetails( const serviceabilityDetailsPromise = getServiceabilityDetails(
serviceZipCode, serviceZipCode,
@ -198,7 +200,7 @@ export default {
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode, "service-location"); const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode, "service-location");
const shopQuestionInitialDataPromise = shopQuestion.methods.loadInitialData(serviceZipCode); const shopProviderDataPromise = getShopProviderData(serviceZipCode); // shopQuestion.methods.loadInitialData(serviceZipCode);
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
@ -206,6 +208,10 @@ export default {
resultKey: "cmsContent", resultKey: "cmsContent",
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
{
resultKey: "zipCodeData",
promise: zipCodeDataPromise,
},
{ {
resultKey: "mobileFeePart", resultKey: "mobileFeePart",
promise: mobileFeePartPromise, promise: mobileFeePartPromise,
@ -215,12 +221,8 @@ export default {
promise: serviceabilityDetailsPromise, promise: serviceabilityDetailsPromise,
}, },
{ {
resultKey: "zipCodeData", resultKey: "shopProviderData",
promise: getZipCodeData, promise: shopProviderDataPromise,
},
{
resultKey: "shopQuestionInitialData",
promise: shopQuestionInitialDataPromise,
}, },
]; ];
@ -232,14 +234,9 @@ export default {
vm.setData( vm.setData(
resultMap.zipCodeData, resultMap.zipCodeData,
resultMap.serviceabilityDetails, resultMap.serviceabilityDetails,
resultMap.mobileFeePart resultMap.mobileFeePart,
resultMap.shopProviderData
); );
// Initialize the Shop Question component
vm.$refs.shopQuestion.initializeComponent(resultMap.shopQuestionInitialData);
// Initialize the page level shop data
vm.providerData = resultMap.shopQuestionInitialData;
}); });
}, },
computed: { computed: {
@ -254,7 +251,7 @@ export default {
if (newValue.zipCode !== this.zipCode) { if (newValue.zipCode !== this.zipCode) {
this.resetMobileLocation(); this.resetMobileLocation();
this.selectedAppointmentType = null; this.selectedAppointmentType = null;
this.selectedProvider = null; this.selectedProvider = new Provider();
} }
this.state = newValue.state; this.state = newValue.state;
@ -277,20 +274,16 @@ export default {
}; };
}, },
set: function (newValue) { set: function (newValue) {
this.streetAddress = newValue.addressQuestions.streetAddress; if (newValue.addressQuestions.zipCode !== this.zipCode) {
this.apartmentNumberOrBusinessName = getShopProviderData(newValue.addressQuestions.zipCode).then((result) => {
newValue.addressQuestions.apartmentNumberOrBusinessName; this.shopProviderData = result.data;
this.city = newValue.addressQuestions.city; this.selectedProvider = new Provider(
this.state = newValue.addressQuestions.state; this.shopProviderData.mobileProviderNumber
this.zipCode = newValue.addressQuestions.zipCode; );
this.isVehicleProtected = newValue.isVehicleProtected; });
if (newValue.zipCode !== this.zipCode) {
if (!this.selectedAppointmentType == "Mobile") {
this.selectedAppointmentType = null;
}
this.selectedProvider = null;
} }
this.setMobileLocation(newValue);
}, },
}, },
isServiceableMobile() { isServiceableMobile() {
@ -355,7 +348,7 @@ export default {
store.getters.payment.isInsurance !== null store.getters.payment.isInsurance !== null
); );
}, },
setData(zipCodeData, serviceabilityDetails, mobileFeePart) { setData(zipCodeData, serviceabilityDetails, mobileFeePart, shopProviderData) {
if (zipCodeData) { if (zipCodeData) {
this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase; this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
this.zipCodeCtu = zipCodeData.zipCodeCtu; this.zipCodeCtu = zipCodeData.zipCodeCtu;
@ -368,6 +361,10 @@ export default {
if (mobileFeePart) { if (mobileFeePart) {
this.mobileFeePart = mobileFeePart; this.mobileFeePart = mobileFeePart;
} }
if (shopProviderData) {
this.shopProviderData = shopProviderData;
}
}, },
setContainsMilitaryBase(val) { setContainsMilitaryBase(val) {
if (this.zipContainsMilitaryBase !== val) { if (this.zipContainsMilitaryBase !== val) {
@ -416,12 +413,18 @@ export default {
this.isRecalibrationServiceableMobile = this.isRecalibrationServiceableMobile =
serviceabilityDetails.isRecalibrationServiceableMobile; serviceabilityDetails.isRecalibrationServiceableMobile;
}, },
setMobileLocation(mobileLocation) {
this.streetAddress = mobileLocation.addressQuestions.streetAddress;
this.apartmentNumberOrBusinessName =
mobileLocation.addressQuestions.apartmentNumberOrBusinessName;
this.city = mobileLocation.addressQuestions.city;
this.state = mobileLocation.addressQuestions.state;
this.zipCode = mobileLocation.addressQuestions.zipCode;
this.isVehicleProtected = mobileLocation.isVehicleProtected;
},
async reloadShopData(zipCode) { async reloadShopData(zipCode) {
await this.$refs.shopQuestion.reloadShopData(zipCode); await this.$refs.shopQuestion.reloadShopData(zipCode);
}, },
setUpdatedShopList(providerData) {
this.providerData = providerData;
},
openRecalibrationInformationModal() { openRecalibrationInformationModal() {
this.recalibrationInformationModal.openModal(); this.recalibrationInformationModal.openModal();
}, },
@ -500,18 +503,14 @@ export default {
}, },
watch: { watch: {
selectedAppointmentType: { selectedAppointmentType: {
handler(newValue) { async handler(newValue) {
if (newValue === "Mobile") { if (newValue === "Mobile") {
this.selectedProvider = new Provider(this.providerData.mobileProviderNumber); getShopProviderData(this.zipCode).then(async (result) => {
} else { this.shopProviderData = result.data;
this.selectedProvider = new Provider(); this.selectedProvider = new Provider(
} this.shopProviderData.mobileProviderNumber
}, );
}, });
providerData: {
handler(newValue) {
if (newValue === "Mobile") {
this.selectedProvider = new Provider(this.providerData.mobileProviderNumber);
} else { } else {
this.selectedProvider = new Provider(); this.selectedProvider = new Provider();
} }

View file

@ -68,9 +68,6 @@ export default {
}, },
linkWidgetName: String, linkWidgetName: String,
modalWidgetName: String, modalWidgetName: String,
onZipUpdateCallback: {
type: Function,
},
}, },
computed: { computed: {
serviceZipLinkText() { serviceZipLinkText() {
@ -164,13 +161,9 @@ export default {
this.$emit("updated-serviceability", serviceabilityDetails.data); this.$emit("updated-serviceability", serviceabilityDetails.data);
this.$emit("updated-contains-military-base", zipCodeData.containsMilitaryBase); this.$emit("updated-contains-military-base", zipCodeData.containsMilitaryBase);
// Update the page level model // update the page level model
this.$emit("update:modelValue", this.internalModel); this.$emit("update:modelValue", this.internalModel);
if (this.onZipUpdateCallback) {
await this.onZipUpdateCallback(serviceZipCode);
}
this.closeModal(); this.closeModal();
} }
} else { } else {

View file

@ -61,6 +61,7 @@ const mockCmsContent = {
const cmsWidgetName = "ShopQuestionWidget"; const cmsWidgetName = "ShopQuestionWidget";
const shopQuestionInitialData = { const shopQuestionInitialData = {
mobileProviderNumber: "001820",
shopProviders: [ shopProviders: [
{ {
address: { address: {
@ -162,15 +163,18 @@ describe("shop-question.vue", () => {
selectedAppointmentType: "Dropoff", selectedAppointmentType: "Dropoff",
cmsWidgetName: cmsWidgetName, cmsWidgetName: cmsWidgetName,
isDisplayed: true, isDisplayed: true,
shopProviderData: null,
}, },
mountOptions: { mountOptions: {
attachTo: document.body, attachTo: document.body,
}, },
}); });
// Act await wrapper.setProps({
wrapper.vm.initializeComponent(shopQuestionInitialData); shopProviderData: shopQuestionInitialData,
});
// Act
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
@ -199,47 +203,6 @@ describe("shop-question.vue", () => {
}); });
it("Should display the 'Show more locations' link when there are more than three locations to chose from", async () => { it("Should display the 'Show more locations' link when there are more than three locations to chose from", async () => {
// Arrange
const { wrapper } = setupMocks({
mixins: [mockMixin],
props: {
modelValue: {
address: {
city: "POWELL",
country: "US",
state: "OH",
streetAddress: "3938 POWELL RD",
zipCode: "43065",
},
distanceInMiles: 16.2690495685233,
providerNumber: "003341",
},
serviceZipCode: "43081",
selectedAppointmentType: "Dropoff",
cmsWidgetName: cmsWidgetName,
isDisplayed: true,
},
mountOptions: {
attachTo: document.body,
},
});
// Act
wrapper.vm.initializeComponent(shopQuestionInitialData);
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
const showMoreShopsLink = wrapper.findComponent({ ref: "showMoreShopsLink" });
// Assert
expect(showMoreShopsLink.exists()).toBe(true);
expect(showMoreShopsLink.isVisible()).toBe(true);
});
it("Should not display the 'Show more locations' link when there are fewer than three locations to chose from", async () => {
// Arrange // Arrange
const alsoShopQuestionInitialData = { const alsoShopQuestionInitialData = {
shopProviders: [ shopProviders: [
@ -276,6 +239,17 @@ describe("shop-question.vue", () => {
distanceInMiles: 11.738869544543, distanceInMiles: 11.738869544543,
providerNumber: "003343", providerNumber: "003343",
}, },
{
address: {
city: "COLUMBUS",
country: "US",
state: "OH",
streetAddress: "1670 HARMON AVE",
zipCode: "43223",
},
distanceInMiles: 15.9727889297435,
providerNumber: "006747",
},
], ],
}; };
@ -297,6 +271,7 @@ describe("shop-question.vue", () => {
selectedAppointmentType: "Dropoff", selectedAppointmentType: "Dropoff",
cmsWidgetName: cmsWidgetName, cmsWidgetName: cmsWidgetName,
isDisplayed: true, isDisplayed: true,
shopProviderData: null,
}, },
mountOptions: { mountOptions: {
attachTo: document.body, attachTo: document.body,
@ -304,17 +279,94 @@ describe("shop-question.vue", () => {
}); });
// Act // Act
wrapper.vm.initializeComponent(alsoShopQuestionInitialData); await wrapper.setProps({
shopProviderData: alsoShopQuestionInitialData,
});
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
const showMoreShopsLink = wrapper.findComponent({ ref: "showMoreShopsLink" }); const showMoreShopsLink = wrapper.findComponent({ ref: "showMoreShopsLink" });
// Assert // Assert
expect(showMoreShopsLink.exists()).toBe(false); expect(showMoreShopsLink.exists()).toBeTruthy();
expect(showMoreShopsLink.isVisible()).toBeTruthy();
}); });
it("Should display the next three shops when the 'Show more location' link is clicked", async () => { it("Should not display the 'Show more locations' link when there are fewer than three locations to chose from", async () => {
// Arrange
const alsoShopQuestionInitialData = {
shopProviders: [
{
address: {
city: "WESTERVILLE",
country: "US",
state: "OH",
streetAddress: "4403 EXECUTIVE PKWY",
zipCode: "43081",
},
distanceInMiles: 5.16769294095201,
providerNumber: "003335",
},
{
address: {
city: "WORTHINGTON",
country: "US",
state: "OH",
streetAddress: "760 DEARBORN PARK LN",
zipCode: "43085",
},
distanceInMiles: 10.5865432478478,
providerNumber: "001820",
},
],
};
const { wrapper } = setupMocks({
mixins: [mockMixin],
props: {
modelValue: {
address: {
city: "POWELL",
country: "US",
state: "OH",
streetAddress: "3938 POWELL RD",
zipCode: "43065",
},
distanceInMiles: 16.2690495685233,
providerNumber: "003341",
},
serviceZipCode: "43081",
selectedAppointmentType: "Dropoff",
cmsWidgetName: cmsWidgetName,
isDisplayed: true,
shopProviderData: null,
},
mountOptions: {
attachTo: document.body,
},
});
// Act
await wrapper.setProps({
shopProviderData: alsoShopQuestionInitialData,
});
await wrapper.vm.$nextTick();
const showMoreShopsLink = wrapper.findComponent({ ref: "showMoreShopsLink" });
await wrapper.vm.$nextTick();
// Assert
expect(showMoreShopsLink.exists()).toBeFalsy();
});
//TODO: Add test to ensure the "Show more locations" link is not visible when all the existing shops are displayed.
it("Should display the next three shops when the 'Show more locations' link is clicked", async () => {
// Arrange // Arrange
const displayedAnswers = [ const displayedAnswers = [
{ {
@ -355,6 +407,7 @@ describe("shop-question.vue", () => {
selectedAppointmentType: "Dropoff", selectedAppointmentType: "Dropoff",
cmsWidgetName: cmsWidgetName, cmsWidgetName: cmsWidgetName,
isDisplayed: true, isDisplayed: true,
shopProviderData: null,
}, },
mountOptions: { mountOptions: {
attachTo: document.body, attachTo: document.body,
@ -362,7 +415,9 @@ describe("shop-question.vue", () => {
}); });
// Act // Act
wrapper.vm.initializeComponent(shopQuestionInitialData); await wrapper.setProps({
shopProviderData: shopQuestionInitialData,
});
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
@ -384,7 +439,7 @@ describe("shop-question.vue", () => {
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
showMoreShopsLink.trigger("click"); showMoreShopsLink.trigger("click-event");
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
@ -443,6 +498,7 @@ describe("shop-question.vue", () => {
serviceZipCode: "43081", serviceZipCode: "43081",
selectedAppointmentType: "Dropoff", selectedAppointmentType: "Dropoff",
cmsWidgetName: cmsWidgetName, cmsWidgetName: cmsWidgetName,
shopProviderData: null,
}, },
mountOptions: { mountOptions: {
attachTo: document.body, attachTo: document.body,
@ -450,7 +506,9 @@ describe("shop-question.vue", () => {
}); });
// Act // Act
wrapper.vm.initializeComponent(shopQuestionInitialData); await wrapper.setProps({
shopProviderData: shopQuestionInitialData,
});
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
@ -468,15 +526,18 @@ describe("shop-question.vue", () => {
modelValue: null, modelValue: null,
selectedAppointmentType: "Dropoff", selectedAppointmentType: "Dropoff",
cmsWidgetName: cmsWidgetName, cmsWidgetName: cmsWidgetName,
shopProviderData: null,
}, },
mountOptions: { mountOptions: {
attachTo: document.body, attachTo: document.body,
}, },
}); });
// Act await wrapper.setProps({
await wrapper.vm.initializeComponent(shopQuestionInitialData); shopProviderData: shopQuestionInitialData,
});
// Act
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
expect(wrapper.vm.answers.length).toEqual(3); expect(wrapper.vm.answers.length).toEqual(3);

View file

@ -30,7 +30,7 @@
linkType="text" linkType="text"
:text="showMoreShopsLinkText" :text="showMoreShopsLinkText"
href="#!" href="#!"
@click-event="getNextShopsFromList" @click-event="getNextShopsFromList(3)"
:aria-label="showMoreShopsLinkText" /> :aria-label="showMoreShopsLinkText" />
</div> </div>
</transition> </transition>
@ -43,8 +43,6 @@ import buttonQuestion from "@/digital-components/button-question/button-question
import shopListButton from "./shop-list-button/shop-list-button"; import shopListButton from "./shop-list-button/shop-list-button";
import textLink from "@/ux-components/text-link/text-link"; import textLink from "@/ux-components/text-link/text-link";
import { storeActions } from "@/constants/store-actions.js";
// Supporting files // Supporting files
import { defineRule } from "vee-validate"; import { defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules"; import { required } from "@/helpers/validation-rules";
@ -63,7 +61,6 @@ export default {
mixins: [baseMixin], mixins: [baseMixin],
data() { data() {
return { return {
shopProviders: [],
shopListButton: shopListButton, shopListButton: shopListButton,
answers: [], answers: [],
shopIndex: 0, shopIndex: 0,
@ -76,6 +73,7 @@ export default {
default: () => null, default: () => null,
}, },
selectedAppointmentType: String, selectedAppointmentType: String,
shopProviderData: Object,
cmsWidgetName: String, cmsWidgetName: String,
validationRules: String, validationRules: String,
isDisplayed: Boolean, isDisplayed: Boolean,
@ -84,6 +82,9 @@ export default {
questionText() { questionText() {
return this.getCmsContent(this.cmsWidgetName, "QuestionText"); return this.getCmsContent(this.cmsWidgetName, "QuestionText");
}, },
shopProviders() {
return this.shopProviderData?.shopProviders ?? [];
},
selectedValue: { selectedValue: {
get: function () { get: function () {
return this.modelValue; return this.modelValue;
@ -124,22 +125,6 @@ export default {
}, },
}, },
methods: { methods: {
loadInitialData(serviceZipCode) {
return this.loadData(serviceZipCode);
},
loadData(serviceZipCode) {
return baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_PROVIDERS,
{
serviceZipCode: serviceZipCode,
},
"service-location"
);
},
initializeComponent(shopQuestionInitialData) {
this.shopProviders = shopQuestionInitialData.shopProviders;
this.$emit("updated-shop-list", shopQuestionInitialData);
},
async getNextShopsFromList(numberToGet = 3) { async getNextShopsFromList(numberToGet = 3) {
const shopIterator = (array, n) => { const shopIterator = (array, n) => {
const l = array.length; const l = array.length;
@ -199,15 +184,6 @@ export default {
this.answers = []; this.answers = [];
this.shopIndex = 0; this.shopIndex = 0;
}, },
async reloadShopData(serviceZipCode) {
const result = await this.loadData(serviceZipCode);
this.initializeComponent(result.data);
this.resetAnswers();
await nextTick();
await this.getNextShopsFromList();
},
getSelectedProviderObject(providerNumber) { getSelectedProviderObject(providerNumber) {
const provider = const provider =
this.shopProviders?.find((provider) => provider.providerNumber == providerNumber) ?? this.shopProviders?.find((provider) => provider.providerNumber == providerNumber) ??
@ -239,19 +215,16 @@ export default {
shopProviders: { shopProviders: {
async handler(newValue) { async handler(newValue) {
await nextTick(); await nextTick();
const selectedShopIndex = this.getSelectedProviderIndex(
newValue,
this.selectedProviderNumber
);
if (this.selectedAppointmentType) { if (selectedShopIndex >= 3) {
const selectedShopIndex = this.getSelectedProviderIndex( await this.getNextShopsFromList(selectedShopIndex + 1);
newValue, } else {
this.selectedProviderNumber await this.getNextShopsFromList();
); await nextTick();
if (selectedShopIndex >= 3) {
await this.getNextShopsFromList(selectedShopIndex + 1);
} else {
await this.getNextShopsFromList();
await nextTick();
}
} }
}, },
}, },