From eaf93c45feb08b2f11c2514e972d49e89f6bbbec Mon Sep 17 00:00:00 2001 From: Glandos Date: Fri, 26 Jun 2020 17:24:24 +0200 Subject: [PATCH 1/4] convert test to use new API --- test/create-proxy.spec.ts | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/test/create-proxy.spec.ts b/test/create-proxy.spec.ts index ee023fe..f2fa77f 100644 --- a/test/create-proxy.spec.ts +++ b/test/create-proxy.spec.ts @@ -2,7 +2,7 @@ import Vuex, {Store} from 'vuex' // @ts-ignore import { createLocalVue } from '@vue/test-utils' -import { Module, VuexModule, getter, mutation, action, getRawActionContext } from '../src' +import { getter, mutation, action, getRawActionContext, createModule, createProxy, clearProxyCache, createSubModule, extractVuexModule } from '../src' interface Name { @@ -10,8 +10,7 @@ interface Name { lastname:string } -@Module({ namespacedPath: 'user/settings/' }) -class UserSettings extends VuexModule { +class UserSettings extends createModule({ namespaced: 'user/settings/' }) { @getter cookieConsent = false @mutation changeConsent(consent: boolean) { @@ -19,13 +18,11 @@ class UserSettings extends VuexModule { } } -@Module({ namespacedPath: 'user/something/'}) -class Something extends VuexModule { +class Something extends createModule({ namespaced: 'user/something/' }) { something = 'nothing' } -@Module({ namespacedPath: 'books/' }) -class Books extends VuexModule{ +class Books extends createModule({ namespaced: 'books/' }) { books: string[] = [] @mutation addBook(book: string) { @@ -33,11 +30,10 @@ class Books extends VuexModule{ } } -@Module({ namespacedPath: 'user/' }) -class UserStore extends VuexModule { +class UserStore extends createModule({ namespaced: 'user/' }) { - settings = UserSettings.CreateSubModule(UserSettings) - something = Something.CreateSubModule(Something) + settings = createSubModule(UserSettings) + something = createSubModule(Something) firstname = 'Michael' lastname = 'Olofinjana' @@ -67,7 +63,7 @@ class UserStore extends VuexModule { } @action async addBook(book: string) { - const booksProxy = Books.CreateProxy(this.$store, Books) + const booksProxy = createProxy(this.$store, Books) booksProxy.addBook(book) } @@ -96,17 +92,18 @@ describe('CreateProxy', () => { localVue.use(Vuex) store = new Store({ modules: { - user: UserStore.ExtractVuexModule(UserStore) + ...extractVuexModule(UserStore) } }) + // console.log('New store with UserStore', store.getters) }) afterEach(() => { - UserStore.ClearProxyCache(UserStore) + clearProxyCache(UserStore) }) it('should proxy getters', () => { - const user = UserStore.CreateProxy(store, UserStore); + const user = createProxy(store, UserStore); expect(user.fullName).toEqual('Michael Olofinjana') expect(user.specialty).toEqual('JavaScript') @@ -114,7 +111,7 @@ describe('CreateProxy', () => { }) it('should proxy state', () => { - const user = UserStore.CreateProxy(store, UserStore) + const user = createProxy(store, UserStore) expect(user.firstname).toEqual('Michael') expect(user.lastname).toEqual('Olofinjana') @@ -122,7 +119,7 @@ describe('CreateProxy', () => { it('should proxy actions', async () => { - const user = UserStore.CreateProxy(store, UserStore) + const user = createProxy(store, UserStore) await user.doAnotherAsyncStuff('Something') @@ -141,7 +138,7 @@ describe('CreateProxy', () => { }) it('should proxy mutations', async () => { - const user = UserStore.CreateProxy(store, UserStore) + const user = createProxy(store, UserStore) await user.changeName({ firstname: 'Ola', lastname: 'Nordmann' }) @@ -151,4 +148,4 @@ describe('CreateProxy', () => { expect(user.lastname).toEqual('Nordmann') }) -}) +}) \ No newline at end of file From 15d0a1cc98845a9be6ea1511f81cffe194230b2e Mon Sep 17 00:00:00 2001 From: Glandos Date: Fri, 26 Jun 2020 17:25:13 +0200 Subject: [PATCH 2/4] fix getters to work with unit tests --- src/proxy.ts | 62 ++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/proxy.ts b/src/proxy.ts index e9d65be..04f10a4 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -305,18 +305,25 @@ function createGettersAndMutationProxyFromState({ cls, proxy, state, $store, nam if ( maxDepth === 0 || typeof value !== "object" || (typeof value === 'object' && !fieldIsSubmodule) ) { + const getter = () => { + // When creating local proxies getters doesn't exist on that context, so we have to account + // for that. + let getters = namespacedPath ? $store.rootGetters : $store.getters + if (getters === undefined) { + if ($store.getters === undefined) { + namespacedPath = "" + getters = $store + } else { + getters = $store.getters + } + } + return getters[ `${namespacedPath}__${className}_internal_getter__` ]( path ) + } + if( !strict || fieldIsSubmodule ) { Object.defineProperty(proxy, field, { - get: () => { - // When creating local proxies getters doesn't exist on that context, so we have to account - // for that. - const getters = cls.prototype.__namespacedPath__ ? $store.rootGetters : $store.getters; - if( getters ) { - const getterPath = refineNamespacedPath(cls.prototype.__namespacedPath__) + `__${className}_internal_getter__`; - return getters[ getterPath ]( path ) - }else return $store[ `__${className}_internal_getter__` ]( path ) - }, + get: getter, set: payload => { const commit = $store.commit || cls.prototype.__store_cache__.commit; if( commit ) commit( refineNamespacedPath( cls.prototype.__namespacedPath__ ) + `__${className}_internal_mutator__`, { field: path, payload }, { root: true }); @@ -333,13 +340,7 @@ function createGettersAndMutationProxyFromState({ cls, proxy, state, $store, nam else { Object.defineProperty(proxy, field, { - get: () => { - // When creating local proxies getters doesn't exist on that context, so we have to account - // for that. - if( $store.getters ) { - return $store.getters[ namespacedPath + `__${className}_internal_getter__` ]( path ) - }else return $store[ `__${className}_internal_getter__` ]( path ) - }, + get: getter, }) } @@ -463,15 +464,26 @@ function createGettersAndGetterMutationsProxy({ cls, getters, mutations, proxy, if( $store === undefined || proxy[ field ] ) continue; + const getter = () => { + // When creating local proxies getters doesn't exist on that context, so we have to account + // for that. + let getters = namespacedPath ? $store.rootGetters : $store.getters + if (getters === undefined) { + if ($store.getters === undefined) { + namespacedPath = "" + getters = $store + } else { + getters = $store.getters + } + } + return getters[ `${namespacedPath}${field}` ] + } + const fieldHasGetterAndMutation = getterMutations.indexOf( field ) > -1; if( fieldHasGetterAndMutation ) { Object.defineProperty( proxy, field, { - get: () => { - const storeGetters = namespacedPath ? $store.rootGetters : $store.getters; - if( storeGetters ) return storeGetters[ namespacedPath + field ] - else return $store[ namespacedPath + field ]; - }, + get: getter, set: ( payload :any ) => $store.commit( namespacedPath + field, payload, { root: !!namespacedPath } ), }) @@ -482,13 +494,7 @@ function createGettersAndGetterMutationsProxy({ cls, getters, mutations, proxy, if( Object.prototype.hasOwnProperty.call(proxy, field) ) continue; Object.defineProperty( proxy, field, { - get: () => { - const storeGetters = namespacedPath ? $store.rootGetters : $store.getters; - if (storeGetters) - return storeGetters[ namespacedPath + field ]; - else - return $store[ namespacedPath + field ]; - } + get: getter }) } From 777de282ddc15ec9c7349f20ae6df5fa920ccebb Mon Sep 17 00:00:00 2001 From: Glandos Date: Mon, 29 Jun 2020 15:50:53 +0200 Subject: [PATCH 3/4] add test for auto setters in strict mode --- test/create-proxy.spec.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/create-proxy.spec.ts b/test/create-proxy.spec.ts index f2fa77f..bd1b6a4 100644 --- a/test/create-proxy.spec.ts +++ b/test/create-proxy.spec.ts @@ -30,7 +30,7 @@ class Books extends createModule({ namespaced: 'books/' }) { } } -class UserStore extends createModule({ namespaced: 'user/' }) { +class UserStore extends createModule({ namespaced: 'user/', strict: false }) { settings = createSubModule(UserSettings) something = createSubModule(Something) @@ -91,11 +91,11 @@ describe('CreateProxy', () => { localVue = createLocalVue() localVue.use(Vuex) store = new Store({ + strict: true, modules: { ...extractVuexModule(UserStore) } }) - // console.log('New store with UserStore', store.getters) }) afterEach(() => { @@ -148,4 +148,15 @@ describe('CreateProxy', () => { expect(user.lastname).toEqual('Nordmann') }) + it('should proxy non-strict setter in strict mode', () => { + const user = createProxy(store, UserStore) + + expect(user.firstname).toEqual('Michael') + expect(user.lastname).toEqual('Olofinjana') + user.firstname = 'Ola' + user.lastname = 'Nordmann' + expect(user.firstname).toEqual('Ola') + expect(user.lastname).toEqual('Nordmann') + }) + }) \ No newline at end of file From 88acfef6199192d36adfbe1bcc315e6d33c8795e Mon Sep 17 00:00:00 2001 From: Glandos Date: Mon, 29 Jun 2020 15:52:03 +0200 Subject: [PATCH 4/4] clean everything in proxy cache to ensure module and proxy is regenerated this is especially useful for tests --- src/proxy.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/proxy.ts b/src/proxy.ts index 04f10a4..a58de71 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -2,7 +2,17 @@ import { extractVuexModule, getNamespacedPath } from "./module"; import { VuexModuleConstructor, Map, VuexModule, ProxyWatchers } from "./interfaces"; import { getClassPath, toCamelCase, refineNamespacedPath } from "./utils"; -export function clearProxyCache( cls :T ) {} +export function clearProxyCache( cls :T ) { + //@ts-ignore + const VuexClass = cls as VuexModuleConstructor + delete VuexClass.prototype.__vuex_module_cache__ + delete VuexClass.prototype.__vuex_proxy_cache__ + delete VuexClass.prototype.__store_cache__ + delete VuexClass.prototype.__vuex_local_proxy_cache__ + for (const submodule of Object.values(VuexClass.prototype.__submodules_cache__)) { + clearProxyCache(submodule) + } +} export function createProxy( $store :any, cls :T ) :ProxyWatchers & InstanceType { //@ts-ignore