import React from 'react'; import { Text, View } from 'react-native'; import { render } from '@testing-library/react-native'; import * as UIReactCoreModule from '@aws-amplify/ui-react-core'; import { AuthenticatorMachineContext, UseAuthenticator, } from '@aws-amplify/ui-react-core'; import { Authenticator } from '..'; jest.mock('aws-amplify'); jest.mock('@aws-amplify/ui-react-core'); const CHILD_TEST_ID = 'child-test-id'; const CHILD_CONTENT = 'Test Children'; const CONTAINER_TEST_ID = 'container-test-id'; const FOOTER_TEST_ID = 'footer-test-id'; const HEADER_TEST_ID = 'header-test-id'; function TestChildren() { return <Text testID={CHILD_TEST_ID}>{CHILD_CONTENT}</Text>; } const TestComponent = () => { return null; }; function Container({ children }: { children?: React.ReactNode }) { return <View testID={CONTAINER_TEST_ID}>{children}</View>; } function Footer() { return <View testID={FOOTER_TEST_ID} />; } function Header() { return <View testID={HEADER_TEST_ID} />; } const useAuthenticatorInitMachineSpy = jest.spyOn( UIReactCoreModule, 'useAuthenticatorInitMachine' ); const useAuthenticatorSpy = jest.spyOn(UIReactCoreModule, 'useAuthenticator'); const useAuthenticatorRouteSpy = jest.spyOn( UIReactCoreModule, 'useAuthenticatorRoute' ); type MockSelectorParam = | (( context: AuthenticatorMachineContext ) => AuthenticatorMachineContext[keyof AuthenticatorMachineContext][]) | undefined; describe('Authenticator', () => { beforeEach(() => { jest.clearAllMocks(); useAuthenticatorRouteSpy.mockReturnValue({ Component: TestComponent as any, props: {} as any, }); }); it('behaves as expected in the happy path', () => { const mockUseAuthenticator = (cb: MockSelectorParam) => cb?.({ route: 'signIn', } as unknown as AuthenticatorMachineContext)[0] as unknown as UseAuthenticator; useAuthenticatorSpy.mockImplementation(mockUseAuthenticator); const { toJSON } = render(<Authenticator />); expect(useAuthenticatorInitMachineSpy).toHaveBeenCalledTimes(1); expect(useAuthenticatorSpy).toHaveBeenCalledTimes(1); expect(useAuthenticatorSpy).toHaveBeenCalledWith(expect.any(Function)); expect(toJSON()).toMatchSnapshot(); }); it('handles `authStatus` of authenticated as expected', () => { useAuthenticatorSpy.mockImplementation( () => ({ authStatus: 'authenticated' } as unknown as UseAuthenticator) ); const { getByTestId, toJSON } = render( <Authenticator> <TestChildren /> </Authenticator> ); const children = getByTestId(CHILD_TEST_ID); expect(children.type).toBe('Text'); expect(children.props.children).toBe(CHILD_CONTENT); expect(toJSON()).toMatchSnapshot(); }); it.each(['unauthenticated', 'configuring'])( 'handles an authStatus of %s as expected', (route) => { useAuthenticatorSpy.mockImplementation( () => ({ route } as unknown as UseAuthenticator) ); const { container } = render(<Authenticator />); expect(container.instance).toBeNull(); } ); it('renders with custom slot components as expected', () => { useAuthenticatorSpy.mockReturnValueOnce({ route: 'signIn', } as unknown as UseAuthenticator); const { getByTestId, toJSON } = render( <Authenticator Container={Container} Footer={Footer} Header={Header} /> ); expect(getByTestId(CONTAINER_TEST_ID)).toBeDefined(); expect(getByTestId(FOOTER_TEST_ID)).toBeDefined(); expect(getByTestId(HEADER_TEST_ID)).toBeDefined(); expect(toJSON()).toMatchSnapshot(); }); });