Invalidate cached getters using non-reactive properties

This commit is contained in:
Matt Sykes 2026-05-27 08:37:53 -04:00
parent 71e12d6655
commit 2eac24f0c7
3 changed files with 107 additions and 0 deletions

View file

@ -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 };

View file

@ -225,6 +225,7 @@ const getDefaultState = () => {
expiryTime: null,
idempotencyKey: null,
},
submittedStateRevision: 0,
};
};
@ -745,6 +746,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;
},
@ -1004,6 +1010,7 @@ export const getters = {
return !!nonWindshieldItems?.length;
},
coverageIsVerified: (state) => {
state.submittedStateRevision;
let order;
if (window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !== null) {
order = JSON.parse(
@ -1036,6 +1043,7 @@ export const getters = {
return getHasRecalibrationPart(state);
},
isRecalibrationOnSubmittedState: (state) => {
state.submittedStateRevision;
if (window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !== null) {
return getHasRecalibrationPart({
order: JSON.parse(
@ -1046,6 +1054,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)
@ -3696,6 +3705,8 @@ export const actions = {
//restore affiliate cookies
context.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies);
context.commit(storeMutations.INCREMENT_SUBMITTED_STATE_REVISION);
},
addDonationToSubmittedState(context, donationAmount) {
@ -3725,11 +3736,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) {

View file

@ -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