diff --git a/packages/shared/createInjectionState/index.test.ts b/packages/shared/createInjectionState/index.test.ts index 043380ad774..cb636365275 100644 --- a/packages/shared/createInjectionState/index.test.ts +++ b/packages/shared/createInjectionState/index.test.ts @@ -1,19 +1,20 @@ -import { type InjectionKey, type Ref, defineComponent, h, inject, ref } from 'vue-demi' -import { createInjectionState } from '@vueuse/shared' +import { type InjectionKey, type Ref, defineComponent, h, inject, nextTick, ref } from 'vue-demi' +import { createInjectionState, injectLocal } from '@vueuse/shared' import { describe, expect, it } from 'vitest' -import { mount } from '../../.test' +import { mount, useSetup } from '../../.test' describe('createInjectionState', () => { - it('should work 1', () => { + it('should work for simple nested component', async () => { const [useProvideCountState, useCountState] = createInjectionState((initialValue: number) => { const count = ref(initialValue) return count }) + let count: Ref | undefined + const ChildComponent = defineComponent({ setup() { - const count = useCountState() - expect(count?.value).toBe(0) + count = useCountState() return () => h('div') }, @@ -21,16 +22,20 @@ describe('createInjectionState', () => { const RootComponent = defineComponent({ setup() { - useProvideCountState(0) + useProvideCountState(114514) return () => h(ChildComponent) }, }) - mount(RootComponent) + const vm = mount(RootComponent) + await nextTick() + + expect(count?.value).toBe(114514) + vm.unmount() }) - it('should work (custom key)', () => { + it('should work for custom key', async () => { const KEY: InjectionKey> = Symbol('count-state') const [useProvideCountState, useCountState] = createInjectionState((initialValue: number) => { @@ -38,12 +43,12 @@ describe('createInjectionState', () => { return count }, { injectionKey: KEY }) + let count: Ref | undefined + let count2: Ref | undefined const ChildComponent = defineComponent({ setup() { - const count = useCountState() - expect(count?.value).toBe(0) - const count2 = inject(KEY) - expect(count2?.value).toBe(0) + count = useCountState() + count2 = inject(KEY) return () => h('div') }, @@ -57,25 +62,43 @@ describe('createInjectionState', () => { }, }) - mount(RootComponent) + const vm = mount(RootComponent) + await nextTick() + expect(count?.value).toBe(0) + expect(count2?.value).toBe(0) + vm.unmount() }) - it('allow call provideLocal and injectLocal in same component', () => { + it('allow call useProvidingState and useInjectedState in same component', async () => { const [useProvideCountState, useCountState] = createInjectionState((initialValue: number) => { const count = ref(initialValue) return count }) + const vm = useSetup(() => { + useProvideCountState(114514) + const count = useCountState()! - const CanProvidingStateAndInjectedStateInSameComponent = defineComponent({ - setup() { - useProvideCountState(114514) - const count = useCountState()! - expect(count.value).toBe(114514) - - return () => h('div') - }, + return { count } }) + await nextTick() + expect(vm.count).toBe(114514) + vm.unmount() + }) - mount(CanProvidingStateAndInjectedStateInSameComponent) + it('allow call useProvidingState and injectLocal in same component', async () => { + const KEY: InjectionKey> | string = Symbol('count-state') + const [useProvideCountState] = createInjectionState((initialValue: number) => { + const count = ref(initialValue) + return count + }, { injectionKey: KEY }) + const vm = useSetup(() => { + useProvideCountState(114514) + const count = injectLocal(KEY)! + + return { count } + }) + await nextTick() + expect(vm.count).toBe(114514) + vm.unmount() }) }) diff --git a/packages/shared/injectLocal/index.test.ts b/packages/shared/injectLocal/index.test.ts new file mode 100644 index 00000000000..4c9fce1cf0d --- /dev/null +++ b/packages/shared/injectLocal/index.test.ts @@ -0,0 +1,61 @@ +import { type InjectionKey, defineComponent, getCurrentInstance, h, nextTick } from 'vue-demi' +import { injectLocal, provideLocal } from '@vueuse/shared' +import { describe, expect, it } from 'vitest' +import { mount, useSetup } from '../../.test' + +describe('provideLocal injectLocal deps', () => { + it('depends on getCurrentInstance().proxy === getCurrentInstance().proxy', async () => { + const vm = useSetup(() => { + const instance1 = getCurrentInstance() + const instance2 = getCurrentInstance() + const instanceProxyStable = instance1?.proxy === instance2?.proxy + return { instance1, instance2, instanceProxyStable } + }) + await nextTick() + expect(vm.instance1).not.toBeNull() + expect(vm.instance2).not.toBeNull() + expect(vm.instance1).toBeTypeOf('object') + expect(vm.instance2).toBeTypeOf('object') + expect(vm.instanceProxyStable).toBe(true) + vm.unmount() + }) +}) + +describe('provideLocal injectLocal', () => { + it('should work for nested component', async () => { + const CountKey: InjectionKey | string = Symbol('count') + let count: number | undefined + const ChildComponent = defineComponent({ + setup() { + count = injectLocal(CountKey) + + return () => h('div') + }, + }) + + const RootComponent = defineComponent({ + setup() { + provideLocal(CountKey, 2333) + + return () => h(ChildComponent) + }, + }) + const vm = mount(RootComponent) + await nextTick() + + expect(count).toBe(2333) + vm.unmount() + }) + + it('should work for same component', async () => { + const CountKey: InjectionKey | string = Symbol('count') + const vm = useSetup(() => { + provideLocal(CountKey, 2333) + const count = injectLocal(CountKey)! + return { count } + }) + await nextTick() + expect(vm.count).toBe(2333) + vm.unmount() + }) +}) diff --git a/packages/shared/injectLocal/index.ts b/packages/shared/injectLocal/index.ts index 184cb0d7f18..4b7a68af485 100644 --- a/packages/shared/injectLocal/index.ts +++ b/packages/shared/injectLocal/index.ts @@ -13,9 +13,9 @@ import { localProvidedStateMap } from '../provideLocal/map' // @ts-expect-error overloads are not compatible export const injectLocal: typeof inject = (...args) => { const key = args[0] as string | symbol - const instance = getCurrentInstance() + const instance = getCurrentInstance()?.proxy if (instance == null) - throw new Error('injectEnhancedAllowanceOfCallsFromTheSameComponent must be called in setup') + throw new Error('injectLocal must be called in setup') if (localProvidedStateMap.has(instance) && key in localProvidedStateMap.get(instance)!) return localProvidedStateMap.get(instance)![key] diff --git a/packages/shared/provideLocal/index.ts b/packages/shared/provideLocal/index.ts index 692d7ec8c13..c33a7d5e27f 100644 --- a/packages/shared/provideLocal/index.ts +++ b/packages/shared/provideLocal/index.ts @@ -11,7 +11,7 @@ import { localProvidedStateMap } from './map' * ``` */ export const provideLocal: typeof provide = (key, value) => { - const instance = getCurrentInstance() + const instance = getCurrentInstance()?.proxy if (instance == null) throw new Error('provideLocal must be called in setup') diff --git a/packages/shared/provideLocal/map.ts b/packages/shared/provideLocal/map.ts index 95f18f10a04..c1c601cdcf0 100644 --- a/packages/shared/provideLocal/map.ts +++ b/packages/shared/provideLocal/map.ts @@ -1,3 +1,3 @@ import type { getCurrentInstance } from 'vue-demi' -export const localProvidedStateMap = new WeakMap>, Record>() +export const localProvidedStateMap = new WeakMap>['proxy']>, Record>()