Skip to content

Commit

Permalink
Merge pull request #65 from abernh/feat-30-add-params-onBeforeReplace…
Browse files Browse the repository at this point in the history
…-and-onBeforeSave

Feat #30 add params onBeforeReplace and onBeforeSave
  • Loading branch information
gabrielmbmb authored Oct 23, 2021
2 parents c79cd7e + a9b8c08 commit c6933ac
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 3 deletions.
24 changes: 21 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@ import Tab from './tab';
export interface Options {
statesPaths?: string[];
key?: string;
onBeforeReplace?(state: any): any;
onBeforeSave?(state: any): any;
}

export default function (options?: Options) {
const tab = new Tab(window);
let key: string = 'vuex-multi-tab';
let statesPaths: string[] = [];
let onBeforeReplace = (state: any) => state;
let onBeforeSave = (state: any) => state;

if (options) {
key = options.key ? options.key : key;
statesPaths = options.statesPaths ? options.statesPaths : statesPaths;
onBeforeReplace = options.onBeforeReplace || onBeforeReplace;
onBeforeSave = options.onBeforeSave || onBeforeSave;
}

function filterStates(state: { [key: string]: any }): { [key: string]: any } {
Expand Down Expand Up @@ -61,15 +67,23 @@ export default function (options?: Options) {
throw new Error('Local storage is not available!');
}

function replaceState(store: any, state: object) {
const adjustedState = onBeforeReplace(state);

if (adjustedState) {
store.replaceState(mergeState(store.state, adjustedState));
}
}

return (store: any) => {
// First time, fetch state from local storage
tab.fetchState(key, (state: object) => {
store.replaceState(mergeState(store.state, state));
replaceState(store, state);
});

// Add event listener to the state saved in local storage
tab.addEventListener(key, (state: object) => {
store.replaceState(mergeState(store.state, state));
replaceState(store, state);
});

store.subscribe((mutation: MutationEvent, state: object) => {
Expand All @@ -80,8 +94,12 @@ export default function (options?: Options) {
toSave = filterStates(state);
}

toSave = onBeforeSave(toSave);

// Save state in local storage
tab.saveState(key, toSave);
if (toSave) {
tab.saveState(key, toSave);
}
});
};
}
81 changes: 81 additions & 0 deletions test/test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,87 @@ describe('vuex-multi-tab-state basic tests', () => {
expect(warnSpy).to.have.been.called;
});

it('should work with onBeforeSave option set', () => {
const store = new Vuex.Store({
strict: true,
state: {
counter: 1,
},
mutations: {
count(state) {
state.counter += 1;
},
},
plugins: [
createMultiTabState({
onBeforeSave(state) {
if (state.counter > 2) return;

return {
...state,
__time: Date.now(),
};
},
}),
],
});

store.commit('count');
store.commit('count');
store.commit('count');

const stateInLs: string | null =
window.localStorage.getItem('vuex-multi-tab');

expect(typeof stateInLs).to.be.eq('string');
if (typeof stateInLs === 'string') {
const parsedStateInLs = JSON.parse(stateInLs);

expect(parsedStateInLs.state.__time).to.be.lte(Date.now());
expect(parsedStateInLs.state.counter).to.be.eq(2);
}
});

it('should work with onBeforeReplace option set', () => {
const testState = { id: 'randomIdHere', state: { random: 6 } };
window.localStorage.setItem('vuex-multi-tab', JSON.stringify(testState));

const store = new Vuex.Store({
strict: true,
state: { random: 0 },
});
const plugin = createMultiTabState({
onBeforeReplace(state) {
return { random: 12 };
},
});
const spy = chai.spy.on(store, 'replaceState');

plugin(store);
expect(spy).to.have.been.called.with({ random: 12 });
expect(store.state.random).to.be.eq(12);
});

it('should work with onBeforeReplace option returning falsy value', () => {
const testState = { id: 'randomIdHere', state: { random: 6 } };
window.localStorage.setItem('vuex-multi-tab', JSON.stringify(testState));

const store = new Vuex.Store({
strict: true,
state: { random: 0 },
});
const plugin = createMultiTabState({
onBeforeReplace(state) {
return;
},
});
const spy = chai.spy.on(store, 'replaceState');

plugin(store);
expect(spy).to.not.have.been.called;
expect(store.state.random).to.be.eq(0);
});

it('should not fetch state from local storage if event newValue property is undefined', () => {
const testState = { id: 'randomIdHere', state: { random: 6 } };
window.localStorage.setItem('vuex-multi-tab', JSON.stringify(testState));
Expand Down

0 comments on commit c6933ac

Please sign in to comment.