diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js index d2fc2b0fc..a06a37bb0 100644 --- a/src/constants/store-mutations.js +++ b/src/constants/store-mutations.js @@ -147,6 +147,9 @@ const storeMutations = { //Affiliate Cookies UPDATE_AFFILIATE_COOKIES: "updateAffiliateCookies", + + // Submitted state (invalidates getters that read sessionStorage submittedState) + INCREMENT_SUBMITTED_STATE_REVISION: "incrementSubmittedStateRevision", }; export { storeMutations }; diff --git a/src/store/index.js b/src/store/index.js index fab5bc6ac..b053749bc 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -232,6 +232,7 @@ const getDefaultState = () => { expiryTime: null, idempotencyKey: null, }, + submittedStateRevision: 0, }; }; @@ -767,6 +768,11 @@ export const mutations = { resetState(state) { Object.assign(state, getDefaultState()); }, + // Bumps when submittedState sessionStorage is created, updated, or cleared so getters + // that read sessionStorage (coverageIsVerified, etc.) invalidate their Vuex cache. + incrementSubmittedStateRevision(state) { + state.submittedStateRevision = (state.submittedStateRevision ?? 0) + 1; + }, resetSaveSessionPromise(state) { state.applicationUser.saveSessionPromise = null; }, @@ -1026,6 +1032,7 @@ export const getters = { return !!nonWindshieldItems?.length; }, coverageIsVerified: (state) => { + state.submittedStateRevision; let order; if (window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !== null) { order = JSON.parse( @@ -1058,6 +1065,7 @@ export const getters = { return getHasRecalibrationPart(state); }, isRecalibrationOnSubmittedState: (state) => { + state.submittedStateRevision; if (window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !== null) { return getHasRecalibrationPart({ order: JSON.parse( @@ -1068,6 +1076,7 @@ export const getters = { return false; }, shouldHideRecalibration: (state) => { + state.submittedStateRevision; if (window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !== null) { state = JSON.parse( window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) @@ -3718,6 +3727,8 @@ export const actions = { //restore affiliate cookies context.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies); + + context.commit(storeMutations.INCREMENT_SUBMITTED_STATE_REVISION); }, addDonationToSubmittedState(context, donationAmount) { @@ -3747,11 +3758,15 @@ export const actions = { sessionStorageKeyConstants.SUBMITTED_STATE, JSON.stringify(submittedState) ); + + context.commit(storeMutations.INCREMENT_SUBMITTED_STATE_REVISION); }, resetSubmittedState(context) { // clear from local storage window.sessionStorage.removeItem(sessionStorageKeyConstants.SUBMITTED_STATE); + + context.commit(storeMutations.INCREMENT_SUBMITTED_STATE_REVISION); }, resetExternalParameterState(context) { if (context.getters.isExternalParameter) { diff --git a/src/store/store.spec.js b/src/store/store.spec.js index f8c41cbe4..ec2a757ca 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -1,7 +1,9 @@ import globalMethods from "@/global-methods"; +import store from "@/store"; import { mutations, state, actions, getters } from "@/store"; import { storeMutations } from "@/constants/store-mutations"; import { storeActions } from "@/constants/store-actions"; +import { sessionStorageKeyConstants } from "@/constants/session-storage"; import { experimentTriggers } from "@/constants/experiments"; import { routeData } from "@/router/constants/routes"; import { AppointmentTypeStrings } from "@/constants/schedule-constants"; @@ -363,6 +365,14 @@ describe("Mutations", () => { expect(state.order.customer.phoneNumber).toEqual("555-555-5555"); expect(state.order.customer.isSmsOptIn).toEqual(true); }); + + it("incrementSubmittedStateRevision, should increment submittedStateRevision", () => { + const storeState = { submittedStateRevision: 0 }; + + mutations.incrementSubmittedStateRevision(storeState); + + expect(storeState.submittedStateRevision).toEqual(1); + }); }); describe("Actions", () => { @@ -3610,6 +3620,85 @@ describe("Actions", () => { }); }); +describe("submittedStateRevision", () => { + beforeEach(() => { + mutations.resetState(store.state); + window.sessionStorage.removeItem(sessionStorageKeyConstants.SUBMITTED_STATE); + }); + + it("resetSubmittedState action commits INCREMENT_SUBMITTED_STATE_REVISION", async () => { + const context = { commit: jest.fn() }; + + await actions.resetSubmittedState(context); + + expect(context.commit).toHaveBeenCalledWith( + storeMutations.INCREMENT_SUBMITTED_STATE_REVISION + ); + }); + + it("createSubmittedState action commits INCREMENT_SUBMITTED_STATE_REVISION at end", async () => { + const context = { + commit: jest.fn(), + state: { + order: { + payment: { insuranceCoverage: { isVerified: false } }, + policy: { currentDeductible: 0 }, + lineItems: {}, + }, + applicationUser: { + experiments: [], + affiliateCookies: [], + }, + }, + }; + + await actions.createSubmittedState(context); + + expect(context.commit).toHaveBeenCalledWith( + storeMutations.INCREMENT_SUBMITTED_STATE_REVISION + ); + }); + + it("addDonationToSubmittedState action commits INCREMENT_SUBMITTED_STATE_REVISION", async () => { + window.sessionStorage.setItem( + sessionStorageKeyConstants.SUBMITTED_STATE, + JSON.stringify({ + order: { + lineItems: { supportingItems: [] }, + }, + applicationUser: {}, + }) + ); + + const context = { commit: jest.fn() }; + + await actions.addDonationToSubmittedState(context, 5); + + expect(context.commit).toHaveBeenCalledWith( + storeMutations.INCREMENT_SUBMITTED_STATE_REVISION + ); + }); + + it("coverageIsVerified re-evaluates after resetSubmittedState clears sessionStorage", () => { + window.sessionStorage.setItem( + sessionStorageKeyConstants.SUBMITTED_STATE, + JSON.stringify({ + order: { + payment: { insuranceCoverage: { isVerified: true } }, + policy: { currentDeductible: 500 }, + }, + applicationUser: {}, + }) + ); + + expect(store.getters.coverageIsVerified).toBe(true); + + store.dispatch(storeActions.RESET_SUBMITTED_STATE); + + expect(store.getters.coverageIsVerified).toBe(false); + }); +}); + describe("Getters", () => { it("Vehicle getter, should return vehicle data", () => { // Arrange