diff --git a/packages/vue/src/composables/__tests__/useAuthenticator.spec.ts b/packages/vue/src/composables/__tests__/useAuthenticator.spec.ts index 96f81128b11..ac89658c02f 100644 --- a/packages/vue/src/composables/__tests__/useAuthenticator.spec.ts +++ b/packages/vue/src/composables/__tests__/useAuthenticator.spec.ts @@ -20,6 +20,7 @@ class MockAuthService { const mockServiceFacade = { authStatus: 'authenticated', + socialProviders: ['amazon'], } as unknown as AuthenticatorServiceFacade; const getServiceFacadeSpy = jest @@ -54,13 +55,19 @@ describe('useAuthenticator', () => { it('returns the expected values', () => { const wrapper = mount(TestComponent); + expect(wrapper.vm.authStatus).toBe('unauthenticated'); + expect(wrapper.vm.socialProviders).toStrictEqual(['amazon']); + wrapper.unmount(); + }); + + it('calls getServiceFacade once on initial mount', () => { + const wrapper = mount(TestComponent); + expect(getServiceFacadeSpy).toBeCalledTimes(1); expect(getServiceFacadeSpy).toBeCalledWith({ send: mockSend, state: mockState.value, }); - - expect(wrapper.vm.authStatus).toBe('unauthenticated'); wrapper.unmount(); }); diff --git a/packages/vue/src/composables/useAuth.ts b/packages/vue/src/composables/useAuth.ts index 52b732928a9..006caa1e5f3 100644 --- a/packages/vue/src/composables/useAuth.ts +++ b/packages/vue/src/composables/useAuth.ts @@ -14,7 +14,6 @@ import { } from '@aws-amplify/ui'; import { UseAuth } from '../types'; -import { facade } from './useUtils'; export const useAuth = createSharedComposable((): UseAuth => { const machine = createAuthenticatorMachine(); @@ -53,20 +52,25 @@ export const useAuth = createSharedComposable((): UseAuth => { export const useAuthenticator = createSharedComposable(() => { const { authStatus, state, send } = useAuth(); - const useAuthenticatorValue = reactive({ - ...facade, - send, - state, - }) as any; + // TODO(BREAKING): remove the cast to any + const useAuthenticatorValue = reactive({}) as any; + /* + * Note that watchEffect runs immediately, so `useAuthenticatorValue` is + * guaranteed to have facade values by the time `useAuthenticator` returns. + * + * https://vuejs.org/api/reactivity-core.html#watcheffect + */ watchEffect(() => { - const facadeValues = getServiceFacade({ - send, - state: state.value, - }); + const facade = getServiceFacade({ send, state: state.value }); + + /* + * TODO(BREAKING): consider using a plain object with `refs` instead of + * one `reactive` object to prevent iterating manually over its keys. + */ for (const key of Object.keys(facade)) { //@ts-ignore - useAuthenticatorValue[key] = facadeValues[key]; + useAuthenticatorValue[key] = facade[key]; } useAuthenticatorValue.authStatus = authStatus.value; useAuthenticatorValue.send = send; diff --git a/packages/vue/src/composables/useUtils.ts b/packages/vue/src/composables/useUtils.ts deleted file mode 100644 index f5301f0b05c..00000000000 --- a/packages/vue/src/composables/useUtils.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { AuthEventData } from '@aws-amplify/ui'; - -export const facade = { - error: '', - hasValidationErrors: false, - isPending: false, - route: '', - authStatus: '', - user: '', - validationErrors: [''], - codeDeliveryDetails: { - val: '', - DeliveryMedium: '', - }, - change: (data?: AuthEventData) => null, - updateForm: (data?: AuthEventData) => null, - updateBlur: (data?: AuthEventData) => null, - resend: (data?: AuthEventData) => null, - resendCode: (data?: AuthEventData) => null, - signOut: (data?: AuthEventData) => null, - federatedSignIn: (data?: AuthEventData) => null, - toFederatedSignIn: (data?: AuthEventData) => null, - resetPassword: (data?: AuthEventData) => null, - toResetPassword: (data?: AuthEventData) => null, - signIn: (data?: AuthEventData) => null, - toSignIn: (data?: AuthEventData) => null, - signUp: (data?: AuthEventData) => null, - toSignUp: (data?: AuthEventData) => null, - skip: (data?: AuthEventData) => null, - skipVerification: (data?: AuthEventData) => null, - submit: (data?: AuthEventData) => null, - submitForm: (data?: AuthEventData) => null, -};