diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts index 59b63d5..3deb170 100644 --- a/dist/types/index.d.ts +++ b/dist/types/index.d.ts @@ -8,6 +8,7 @@ export interface ActionObject { export interface ActionCache { getKey: (injectee: ActionContext, payload: any) => any; action: Action; + onFree?: (result: any) => any; } export interface ActionCaches { [key: string]: ActionCache; @@ -16,6 +17,7 @@ export interface ActionResultCache { getKey?: (injectee: ActionContext, payload: any) => any; getResultKey: (injectee: ActionContext, payload: any) => any; action: Action; + onFree?: (result: any) => any; } export interface ActionResultCaches { [key: string]: ActionResultCache; @@ -23,11 +25,15 @@ export interface ActionResultCaches { export interface ActionCacheConditional { isInvalid: (injectee: ActionContext, payload: any) => any; action: Action; + onFree?: (result: any) => any; } export interface ActionCacheConditionals { [key: string]: ActionCacheConditional; } export declare type ActionRouteOtherwise = (to: any, from: any, rejectReason: any, store: any, action: any) => any; +export declare type ActionRouteName = string; +export declare type ActionRouteNameCallback = (to: any, from: any, store: any) => string; +export declare type ActionRouteNameInput = ActionRouteName | ActionRouteNameCallback; export declare type ActionLoadingHandler = (injectee: ActionContext, loading: boolean) => any; export declare type ActionLoadingInput = string | ActionLoadingHandler; export interface ActionsPluginOptions extends ActionsWatchOptions { @@ -111,13 +117,36 @@ export declare function actionsDestroyCache(): void; * * ``` * - * @param action The action to dispatch on the store and watch for. + * @param actionInput The action to dispatch on the store and wait for. * @param getOtherwise Where to go if the dispatched action is a reject. */ -export declare function actionBeforeRoute(action: string, getOtherwise?: ActionRouteOtherwise): { +export declare function actionBeforeRoute(actionInput: ActionRouteNameInput, getOtherwise?: ActionRouteOtherwise): { beforeRouteEnter: (to: any, from: any, next: any) => void; beforeRouteUpdate: (to: any, from: any, next: any) => void; }; +/** + * Dispatches an action in the store and optionally waits for the action to + * finish before leaving the current component (see `beforeRouteLeave` in + * `vue-router`). + * + * ```javascript + * // MyPage.vue + * + * ``` + * + * @param actionInput The action to dispatch on the store and optionally wait for. + * @param waitForFinish If the unload action should finish before the component + * is left. + */ +export declare function actionBeforeLeave(actionInput: ActionRouteNameInput, waitForFinish?: boolean): { + beforeRouteLeave: (to: any, from: any, next: any) => void; +}; /** * Allows you to pass the results of a dispath through this function and whether * or not it resolves or rejects it won't stop from proceeding. This happens by diff --git a/dist/vuex-router-actions.js b/dist/vuex-router-actions.js index 743194b..9a2d914 100644 --- a/dist/vuex-router-actions.js +++ b/dist/vuex-router-actions.js @@ -1 +1 @@ -!function(n,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("VuexRouterActions",[],t):"object"==typeof exports?exports.VuexRouterActions=t():n.VuexRouterActions=t()}(window,function(){return function(n){var t={};function o(e){if(t[e])return t[e].exports;var i=t[e]={i:e,l:!1,exports:{}};return n[e].call(i.exports,i,i.exports,o),i.l=!0,i.exports}return o.m=n,o.c=t,o.d=function(n,t,e){o.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:e})},o.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},o.t=function(n,t){if(1&t&&(n=o(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var e=Object.create(null);if(o.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var i in n)o.d(e,i,function(t){return n[t]}.bind(null,i));return e},o.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return o.d(t,"a",t),t},o.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},o.p="",o(o.s=0)}([function(n,t,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var e,i,r="VuexRouterActions must be passed as a plugin to one store",c="Cached action isInvalid must be a function.",u="Cached action getKey must be a function.",a="Cached action getResultKey must be a function.",f="An action passed is not a valid Vuex action.",s=function(n,t,o){return!1},l=y(),d=0,p=0,v=[];function y(){return{onActionStart:function(){},onActionReject:function(){},onActionResolve:function(){},onActionEnd:function(){},onActionsDone:function(){},createCacheKey:function(n){return JSON.stringify(n)}}}function h(){v.forEach(function(n){return n()}),v=[]}function A(n){var t=n.action,o=n.isInvalid;K("function"==typeof o,c);var e=void 0;return v.push(function(){e=void 0}),g(t,"",function(n){return function(t,i){return(void 0===e||o.call(this,t,i))&&(e=n.apply(this,arguments)),e}})}function b(n,t){var o=R({},l,t),e=n.action,i=n.getKey;K("function"==typeof i,u);var r=void 0,c=void 0;return v.push(function(){r=void 0,c=void 0}),g(e,"",function(n){return function(t,e){var u=o.createCacheKey(i.call(this,t,e));return void 0!==r&&u===r||(r=u,c=n.apply(this,arguments)),c}})}function j(n,t){var o=R({},l,t),e=n.action,i=n.getKey,r=n.getResultKey;K("function"==typeof r,a);var c=void 0,u=Object.create(null);return v.push(function(){c=void 0,u=Object.create(null)}),g(e,"",function(n){return function(t,e){var a=i?o.createCacheKey(i.call(this,t,e)):void 0;a!==c&&(c=a,u=Object.create(null));var f=o.createCacheKey(r.call(this,t,e));return f in u||(u[f]=n.apply(this,arguments)),u[f]}})}function m(n,t,o){return o?(n.onActionStart=o.onActionStart||t.onActionStart,n.onActionReject=o.onActionReject||t.onActionReject,n.onActionResolve=o.onActionResolve||t.onActionResolve,n.onActionEnd=o.onActionEnd||t.onActionEnd,n.onActionsDone=o.onActionsDone||t.onActionsDone,n):t}function R(n,t,o){return o?(n.createCacheKey=o.createCacheKey||t.createCacheKey,n):t}function C(n,t){return P(n,function(n,o){return g(n,o,t)})}function g(n,t,o){if(O(n))return o(n,t);if(x(n))return{root:n.root,handler:o(n.handler,t)};throw f}function O(n){return"function"==typeof n}function x(n){return"object"==typeof n&&"function"==typeof n.handler}function P(n,t){var o=Object.create(null);for(var e in n)o[e]=t(n[e],e);return o}function K(n,t){if(!n)throw t}t.default=function(n){return m(l,l,n),R(l,l,n),function(n){K(void 0===i,r),i=n}},t.actionsDestroy=function(){i=e,l=y(),d=0,p=0,h()},t.actionsDefaultOptions=y,t.actionsDestroyCache=h,t.actionBeforeRoute=function(n,t){void 0===t&&(t=s);var o=function(o,e,c){K(void 0!==i,r),i.dispatch(n,o).then(function(n){c()},function(r){c(t(o,e,r,i,n))})};return{beforeRouteEnter:o,beforeRouteUpdate:o}},t.actionOptional=function(n,t){return void 0===t&&(t=function(){return null}),new Promise(function(o,e){n.then(o,function(n){return o(t())})})},t.actionsCachedConditional=function(n){return P(n,function(n){return A(n)})},t.actionCachedConditional=A,t.actionsCached=function(n,t){var o=R({},l,t);return P(n,function(n){return b(n,o)})},t.actionCached=b,t.actionsCachedResults=function(n,t){var o=R({},l,t);return P(n,function(n){return j(n,o)})},t.actionCachedResults=j,t.actionsWatch=function(n,t){var o=m({},l,t),e=t&&t.onActionsDone,i=0,r=0,c=function(n,t){(e?++i:++p)===n&&o.onActionsDone(t)};return C(n,function(n,t){return function(i,u){var a=n.apply(this,arguments),f=e?++r:++d;return a instanceof Promise?(o.onActionStart(t,f,i,u),a.then(function(n){o.onActionResolve(t,f,i,u,n),o.onActionEnd(t,f,i,u,n,!0),c(f,i)},function(n){o.onActionReject(t,f,i,u,n),o.onActionEnd(t,f,i,u,n,!1),c(f,i)})):(o.onActionStart(t,f,i,u),o.onActionEnd(t,f,i,u,a,!0),c(f,i)),a}})},t.actionsProtect=function(n){return C(n,function(n){return function(t,o){return function(n){return n instanceof Promise?n:n?Promise.resolve(n):Promise.reject(n)}(n.apply(this,arguments))}})},t.actionsLoading=function(n,t){var o=0,e=!1,c=function(t){var c=o>0;c!==e&&(K(void 0!==i,r),e=c,function(n){return"string"==typeof n}(n)?i.commit(n,e):function(n){return"function"==typeof n}(n)&&n(t,e))};return C(t,function(n){return function(t,e){var i=n.apply(this,arguments);if(i instanceof Promise){var r=function(n){return function(){o--,c(n)}}(t);o++,i.then(r,r),c(t)}return i}})}}])}); \ No newline at end of file +!function(n,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("VuexRouterActions",[],t):"object"==typeof exports?exports.VuexRouterActions=t():n.VuexRouterActions=t()}(window,function(){return function(n){var t={};function o(e){if(t[e])return t[e].exports;var i=t[e]={i:e,l:!1,exports:{}};return n[e].call(i.exports,i,i.exports,o),i.l=!0,i.exports}return o.m=n,o.c=t,o.d=function(n,t,e){o.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:e})},o.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},o.t=function(n,t){if(1&t&&(n=o(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var e=Object.create(null);if(o.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var i in n)o.d(e,i,function(t){return n[t]}.bind(null,i));return e},o.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return o.d(t,"a",t),t},o.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},o.p="",o(o.s=0)}([function(n,t,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var e,i,r="VuexRouterActions must be passed as a plugin to one store",c="Cached action isInvalid must be a function.",u="Cached action getKey must be a function.",f="Cached action getResultKey must be a function.",a="An action passed is not a valid Vuex action.",s=function(n,t,o){return!1},l=y(),d=0,v=0,p=[];function y(){return{onActionStart:function(){},onActionReject:function(){},onActionResolve:function(){},onActionEnd:function(){},onActionsDone:function(){},createCacheKey:function(n){return JSON.stringify(n)}}}function h(){p.forEach(function(n){return n()}),p=[]}function A(n){var t=n.action,o=n.isInvalid,e=n.onFree;S("function"==typeof o,c);var r=void 0,u=function(){void 0!==r&&e&&e.call(i,r),r=void 0};return p.push(u),g(t,"",function(n){return function(t,e){return(void 0===r||o.call(this,t,e))&&(u(),r=n.apply(this,arguments)),r}})}function b(n,t){var o=R({},l,t),e=n.action,r=n.getKey,c=n.onFree;S("function"==typeof r,u);var f=void 0,a=void 0,s=function(){void 0!==a&&c&&c.call(i,a),f=void 0,a=void 0};return p.push(s),g(e,"",function(n){return function(t,e){var i=o.createCacheKey(r.call(this,t,e));return void 0!==f&&i===f||(s(),f=i,a=n.apply(this,arguments)),a}})}function m(n,t){var o=R({},l,t),e=n.action,r=n.getKey,c=n.getResultKey,u=n.onFree;S("function"==typeof c,f);var a=void 0,s=Object.create(null),d=function(){if(u)for(var n in s)u.call(i,s[n]);a=void 0,s=Object.create(null)};return p.push(d),g(e,"",function(n){return function(t,e){var i=r?o.createCacheKey(r.call(this,t,e)):void 0;i!==a&&(d(),a=i,s=Object.create(null));var u=o.createCacheKey(c.call(this,t,e));return u in s||(s[u]=n.apply(this,arguments)),s[u]}})}function j(n,t,o){return o?(n.onActionStart=o.onActionStart||t.onActionStart,n.onActionReject=o.onActionReject||t.onActionReject,n.onActionResolve=o.onActionResolve||t.onActionResolve,n.onActionEnd=o.onActionEnd||t.onActionEnd,n.onActionsDone=o.onActionsDone||t.onActionsDone,n):t}function R(n,t,o){return o?(n.createCacheKey=o.createCacheKey||t.createCacheKey,n):t}function C(n,t){return K(n,function(n,o){return g(n,o,t)})}function g(n,t,o){if(x(n))return o(n,t);if(P(n))return{root:n.root,handler:o(n.handler,t)};throw a}function O(n,t,o){if("string"==typeof n)return n;if("function"==typeof n)return n(t,o,i);throw"Invalid action name or function."}function x(n){return"function"==typeof n}function P(n){return"object"==typeof n&&"function"==typeof n.handler}function K(n,t){var o=Object.create(null);for(var e in n)o[e]=t(n[e],e);return o}function S(n,t){if(!n)throw t}t.default=function(n){return j(l,l,n),R(l,l,n),function(n){S(void 0===i,r),i=n}},t.actionsDestroy=function(){i=e,l=y(),d=0,v=0,h()},t.actionsDefaultOptions=y,t.actionsDestroyCache=h,t.actionBeforeRoute=function(n,t){void 0===t&&(t=s);var o=function(o,e,c){S(void 0!==i,r);var u=O(n,o,e);i.dispatch(u,{to:o,from:e}).then(function(n){c()},function(n){c(t(o,e,n,i,u))})};return{beforeRouteEnter:o,beforeRouteUpdate:o}},t.actionBeforeLeave=function(n,t){return void 0===t&&(t=!1),{beforeRouteLeave:function(o,e,c){S(void 0!==i,r);var u=O(n,o,e),f=function(){return t?c():void 0};i.dispatch(u,{to:o,from:e}).then(f,f),t||c()}}},t.actionOptional=function(n,t){return void 0===t&&(t=function(){return null}),new Promise(function(o,e){n.then(o,function(n){return o(t())})})},t.actionsCachedConditional=function(n){return K(n,function(n){return A(n)})},t.actionCachedConditional=A,t.actionsCached=function(n,t){var o=R({},l,t);return K(n,function(n){return b(n,o)})},t.actionCached=b,t.actionsCachedResults=function(n,t){var o=R({},l,t);return K(n,function(n){return m(n,o)})},t.actionCachedResults=m,t.actionsWatch=function(n,t){var o=j({},l,t),e=t&&t.onActionsDone,i=0,r=0,c=function(n,t){(e?++i:++v)===n&&o.onActionsDone(t)};return C(n,function(n,t){return function(i,u){var f=n.apply(this,arguments),a=e?++r:++d;return f instanceof Promise?(o.onActionStart(t,a,i,u),f.then(function(n){o.onActionResolve(t,a,i,u,n),o.onActionEnd(t,a,i,u,n,!0),c(a,i)},function(n){o.onActionReject(t,a,i,u,n),o.onActionEnd(t,a,i,u,n,!1),c(a,i)})):(o.onActionStart(t,a,i,u),o.onActionEnd(t,a,i,u,f,!0),c(a,i)),f}})},t.actionsProtect=function(n){return C(n,function(n){return function(t,o){return function(n){return n instanceof Promise?n:n?Promise.resolve(n):Promise.reject(n)}(n.apply(this,arguments))}})},t.actionsLoading=function(n,t){var o=0,e=!1,c=function(t){var c=o>0;c!==e&&(S(void 0!==i,r),e=c,function(n){return"string"==typeof n}(n)?i.commit(n,e):function(n){return"function"==typeof n}(n)&&n(t,e))};return C(t,function(n){return function(t,e){var i=n.apply(this,arguments);if(i instanceof Promise){var r=function(n){return function(){o--,c(n)}}(t);o++,i.then(r,r),c(t)}return i}})}}])}); \ No newline at end of file diff --git a/package.json b/package.json index 3c5a91d..b446c57 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vuex-router-actions", - "version": "1.0.0", + "version": "1.1.0", "author": "Philip Diffenderfer", "description": "A library for loading views with actions, including caching, permissions, loading, and logging.", "license": "MIT", diff --git a/src/index.ts b/src/index.ts index a0df88f..530a39b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,6 +17,7 @@ export interface ActionCache { getKey: (injectee: ActionContext, payload: any) => any action: Action + onFree?: (result: any) => any } export interface ActionCaches @@ -29,6 +30,7 @@ export interface ActionResultCache getKey?: (injectee: ActionContext, payload: any) => any, getResultKey: (injectee: ActionContext, payload: any) => any, action: Action + onFree?: (result: any) => any } export interface ActionResultCaches @@ -41,6 +43,7 @@ export interface ActionCacheConditional { isInvalid: (injectee: ActionContext, payload: any) => any action: Action + onFree?: (result: any) => any } export interface ActionCacheConditionals @@ -50,6 +53,12 @@ export interface ActionCacheConditionals export type ActionRouteOtherwise = (to, from, rejectReason, store, action) => any +export type ActionRouteName = string + +export type ActionRouteNameCallback = (to, from, store) => string + +export type ActionRouteNameInput = ActionRouteName | ActionRouteNameCallback; + export type ActionLoadingHandler = (injectee: ActionContext, loading: boolean) => any export type ActionLoadingInput = string | ActionLoadingHandler @@ -198,16 +207,18 @@ export function actionsDestroyCache(): void * * ``` * - * @param action The action to dispatch on the store and watch for. + * @param actionInput The action to dispatch on the store and wait for. * @param getOtherwise Where to go if the dispatched action is a reject. */ -export function actionBeforeRoute (action: string, getOtherwise: ActionRouteOtherwise = DEFAULT_OTHERWISE) +export function actionBeforeRoute (actionInput: ActionRouteNameInput, getOtherwise: ActionRouteOtherwise = DEFAULT_OTHERWISE) { const dispatch = (to, from, next) => { assert(store !== undefined, ASSERT_STORE) - store.dispatch(action, to).then( + const action = toAction(actionInput, to, from) + + store.dispatch(action, {to, from}).then( (resolved) => { next() }, @@ -223,6 +234,49 @@ export function actionBeforeRoute (action: string, getOtherwise: ActionRouteOthe } } +/** + * Dispatches an action in the store and optionally waits for the action to + * finish before leaving the current component (see `beforeRouteLeave` in + * `vue-router`). + * + * ```javascript + * // MyPage.vue + * + * ``` + * + * @param actionInput The action to dispatch on the store and optionally wait for. + * @param waitForFinish If the unload action should finish before the component + * is left. + */ +export function actionBeforeLeave (actionInput: ActionRouteNameInput, waitForFinish: boolean = false) +{ + const dispatch = (to, from, next) => + { + assert(store !== undefined, ASSERT_STORE) + + const action = toAction(actionInput, to, from) + const finish = () => waitForFinish ? next() : undefined + + store.dispatch(action, {to, from}).then(finish, finish) + + if (!waitForFinish) { + next() + } + } + + return { + beforeRouteLeave: dispatch + } +} + + + /** * Allows you to pass the results of a dispath through this function and whether * or not it resolves or rejects it won't stop from proceeding. This happens by @@ -286,16 +340,23 @@ export function actionsCachedConditional (actions: ActionCacheCondition */ export function actionCachedConditional (input: ActionCacheConditional): Action { - const { action, isInvalid } = input + const { action, isInvalid, onFree } = input assert(typeof isInvalid === 'function', ASSERT_IS_INVALID) let cachedResult = undefined - cacheDestroyers.push(() => + const clearResult = () => { + if (cachedResult !== undefined && onFree) + { + onFree.call(store, cachedResult) + } + cachedResult = undefined - }) + } + + cacheDestroyers.push(clearResult) return actionTransform(action, '', handler => { @@ -303,6 +364,7 @@ export function actionCachedConditional (input: ActionCacheConditional< { if (cachedResult === undefined || isInvalid.call(this, context, payload)) { + clearResult() cachedResult = handler.apply(this, arguments) } @@ -365,18 +427,25 @@ export function actionsCached (actions: ActionCaches, cache?: Par export function actionCached (input: ActionCache, cache?: Partial): Action { const cacheOptions = parseCacheOptions({}, options, cache) - const { action, getKey } = input + const { action, getKey, onFree } = input assert(typeof getKey === 'function', ASSERT_GET_KEY) let cacheKey: string | undefined = undefined let cacheResults = undefined - cacheDestroyers.push(() => + const clearResult = () => { + if (cacheResults !== undefined && onFree) + { + onFree.call(store, cacheResults) + } + cacheKey = undefined cacheResults = undefined - }) + } + + cacheDestroyers.push(clearResult) return actionTransform(action, '', handler => { @@ -386,6 +455,7 @@ export function actionCached (input: ActionCache, cache?: Partial if (cacheKey === undefined || key !== cacheKey) { + clearResult() cacheKey = key cacheResults = handler.apply(this, arguments) } @@ -431,18 +501,28 @@ export function actionsCachedResults (actions: ActionResultCaches export function actionCachedResults (input: ActionResultCache, cache?: Partial): Action { const cacheOptions = parseCacheOptions({}, options, cache) - const { action, getKey, getResultKey } = input + const { action, getKey, getResultKey, onFree } = input assert(typeof getResultKey === 'function', ASSERT_GET_RESULT_KEY) let cachedKey: string | undefined = undefined let cachedResults = Object.create(null) - cacheDestroyers.push(() => + const clearResult = () => { + if (onFree) + { + for (let resultKey in cachedResults) + { + onFree.call(store, cachedResults[resultKey]) + } + } + cachedKey = undefined cachedResults = Object.create(null) - }) + } + + cacheDestroyers.push(clearResult) return actionTransform(action, '', handler => { @@ -452,6 +532,7 @@ export function actionCachedResults (input: ActionResultCache, ca if (key !== cachedKey) { + clearResult() cachedKey = key cachedResults = Object.create(null) } @@ -755,6 +836,21 @@ function actionTransform (action: Action, key: string, getHandler throw ASSERT_ACTION_INVALID } +// Converts the input to an action name. +function toAction (action: ActionRouteNameInput, to, from): string +{ + if (typeof action === 'string') + { + return action + } + else if (typeof action === 'function') + { + return action(to, from, store) + } + + throw 'Invalid action name or function.' +} + // Converts the result to a promise. If its not a promise then its truthy value // determines whether the returned promise is resolved or rejected. function toPromise (x: any): Promise diff --git a/tests/actions.ts b/tests/actions.ts index cf02179..0632e63 100644 --- a/tests/actions.ts +++ b/tests/actions.ts @@ -20,6 +20,8 @@ import VuexRouterActions, { actionsLoading } from '../src' + + const DEFAULT_OPTIONS = { onActionStart: (action: string, num: number) => {}, onActionReject: (action: string, num: number, reason: any) => {}, @@ -534,6 +536,57 @@ describe('actions', function() }) + it('actionsCached onFree', function() + { + const plugin = VuexRouterActions() + + type TestStore = {} + + let refreshes: number = 0 + let frees: number = 0 + + const store = new Vuex.Store({ + plugins: [plugin], + actions: { + ...actionsCached({ + refresh: { + getKey: () => 23, + action: () => ++refreshes, + onFree: () => ++frees + } + }) + } + }) + + expect(refreshes).to.equal(0) + expect(frees).to.equal(0) + + store.dispatch('refresh') + + expect(refreshes).to.equal(1) + expect(frees).to.equal(0) + + store.dispatch('refresh') + + expect(refreshes).to.equal(1) + expect(frees).to.equal(0) + + actionsDestroyCache() + + expect(refreshes).to.equal(1) + expect(frees).to.equal(1) + + store.dispatch('refresh') + + expect(refreshes).to.equal(2) + expect(frees).to.equal(1) + + store.dispatch('refresh') + + expect(refreshes).to.equal(2) + expect(frees).to.equal(1) + }) + it('actionsDestroyCache actionsCached', function() { const plugin = VuexRouterActions()