From 825cccc92f5c326f0f110c8439a1c2c6553ff00a Mon Sep 17 00:00:00 2001 From: Caleb Pollman Date: Wed, 18 Dec 2024 09:16:00 -0800 Subject: [PATCH] chore(react): remove direct usage of react-test-renderer and types (#6255) --- .changeset/cool-pots-fold.md | 8 + .../features/InAppMessaging/Demo/Example.tsx | 167 +++++++++--------- .../InAppMessagingContext.ts | 14 -- .../InAppMessagingContext.tsx | 49 +++++ .../__tests__/InAppMessagingContext.spec.tsx | 53 ++++++ .../__tests__/useInAppMessagingState.ts} | 86 ++++----- .../context/InAppMessagingContext/index.ts | 4 + .../useInAppMessagingState.ts | 24 +++ .../InAppMessagingProvider.tsx | 47 ----- .../context/InAppMessagingProvider/index.ts | 4 - .../src/InAppMessaging/context/index.ts | 1 - .../src/InAppMessaging/hooks/index.ts | 1 - .../__tests__/useInAppMessaging.spec.tsx | 25 --- .../hooks/useInAppMessaging/index.ts | 4 - .../useInAppMessaging/useInAppMessaging.ts | 23 --- .../useMessage/__tests__/useMessage.spec.ts | 5 +- .../hooks/useMessage/useMessage.ts | 6 +- packages/react-core/jest.config.ts | 1 + packages/react-core/jest.setup.ts | 1 + .../__tests__/RenderNothing.spec.tsx | 6 +- .../LivenessIconWithPopover.test.tsx | 3 +- .../__tests__/CarouselMessage.spec.tsx | 5 +- .../Carousel/CarouselPageIndicator.tsx | 5 +- .../Carousel/__tests__/Carousel.spec.tsx | 3 +- .../__tests__/CarouselPageIndicator.spec.tsx | 62 ++++--- .../CarouselPageIndicator.spec.tsx.snap | 115 ------------ .../src/primitives/Carousel/types.ts | 1 + 27 files changed, 320 insertions(+), 403 deletions(-) create mode 100644 .changeset/cool-pots-fold.md delete mode 100644 packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/InAppMessagingContext.ts create mode 100644 packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/InAppMessagingContext.tsx create mode 100644 packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/__tests__/InAppMessagingContext.spec.tsx rename packages/react-core-notifications/src/InAppMessaging/context/{InAppMessagingProvider/__tests__/InAppMessagingProvider.spec.tsx => InAppMessagingContext/__tests__/useInAppMessagingState.ts} (51%) create mode 100644 packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/useInAppMessagingState.ts delete mode 100644 packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/InAppMessagingProvider.tsx delete mode 100644 packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/index.ts delete mode 100644 packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/__tests__/useInAppMessaging.spec.tsx delete mode 100644 packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/index.ts delete mode 100644 packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/useInAppMessaging.ts create mode 100644 packages/react-core/jest.setup.ts diff --git a/.changeset/cool-pots-fold.md b/.changeset/cool-pots-fold.md new file mode 100644 index 00000000000..7bd6d8ee9d0 --- /dev/null +++ b/.changeset/cool-pots-fold.md @@ -0,0 +1,8 @@ +--- +"@aws-amplify/ui-react-core-notifications": patch +"@aws-amplify/ui-react-core": patch +"@aws-amplify/ui-react-liveness": patch +"@aws-amplify/ui-react-native": patch +--- + +chore(react): remove direct usage of react-test-renderer and types diff --git a/examples/react-native/src/features/InAppMessaging/Demo/Example.tsx b/examples/react-native/src/features/InAppMessaging/Demo/Example.tsx index ed9876dbd80..7c4c2c92acd 100644 --- a/examples/react-native/src/features/InAppMessaging/Demo/Example.tsx +++ b/examples/react-native/src/features/InAppMessaging/Demo/Example.tsx @@ -1,9 +1,11 @@ import React from 'react'; +import { ScrollView, StyleSheet, Text, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; + import { Amplify } from 'aws-amplify'; import { initializeInAppMessaging } from 'aws-amplify/in-app-messaging'; -import { SafeAreaView, StyleSheet, Text, View } from 'react-native'; - import { withInAppMessaging } from '@aws-amplify/ui-react-native'; + import { Button, Checkbox, Radio, RadioGroup } from '../../../ui'; import { useInAppDemo, ACTIONS, LAYOUTS, ORIENTATIONS } from './utils'; import config from './aws-exports'; @@ -55,83 +57,85 @@ function Demo() { return ( - - Configure Demo Message - - - - - - - - - - - - - - - - - - - + + + Configure Demo Message + + + + + + + + + + + + + + + + + + + + ); } @@ -152,7 +156,7 @@ const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', - paddingHorizontal: 24, + paddingHorizontal: 16, }, divider: { backgroundColor: 'black', @@ -164,7 +168,8 @@ const styles = StyleSheet.create({ justifyContent: 'center', fontSize: 24, fontWeight: '700', - marginVertical: 8, + marginBottom: 8, + marginTop: 24, }, label: { fontSize: 18, diff --git a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/InAppMessagingContext.ts b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/InAppMessagingContext.ts deleted file mode 100644 index 5fd4203421b..00000000000 --- a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/InAppMessagingContext.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createContext } from 'react'; -import { InAppMessage } from '../../types'; - -export interface InAppMessagingContextType { - clearMessage: () => void; - displayMessage: (message: InAppMessage) => void; - message: InAppMessage | null; -} - -const InAppMessagingContext = createContext( - null -); - -export default InAppMessagingContext; diff --git a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/InAppMessagingContext.tsx b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/InAppMessagingContext.tsx new file mode 100644 index 00000000000..423c3224939 --- /dev/null +++ b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/InAppMessagingContext.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { InAppMessage } from '../../types'; +import { useInAppMessagingState } from './useInAppMessagingState'; + +export interface InAppMessagingContextType { + clearMessage: () => void; + displayMessage: (message: InAppMessage) => void; + message: InAppMessage | null; +} + +const InAppMessagingContext = + React.createContext(null); + +export default InAppMessagingContext; + +export interface InAppMessagingProviderProps { + children: React.ReactNode; +} + +export interface UseInAppMessaging extends InAppMessagingContextType {} + +export const ERROR_MESSAGE = + '`useInAppMessaging` must be called from within `InAppMessagingProvider`'; + +/** + * Utility hook used to access the InAppMessagingContext values + * + * @returns {InAppMessagingContextType} InAppMessaging context values + */ +export function useInAppMessaging(): UseInAppMessaging { + const context = React.useContext(InAppMessagingContext); + + if (!context) { + throw new Error(ERROR_MESSAGE); + } + return context; +} + +export function InAppMessagingProvider({ + children, +}: InAppMessagingProviderProps): React.JSX.Element { + const value = useInAppMessagingState(); + + return ( + + {children} + + ); +} diff --git a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/__tests__/InAppMessagingContext.spec.tsx b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/__tests__/InAppMessagingContext.spec.tsx new file mode 100644 index 00000000000..b0dd56f0dec --- /dev/null +++ b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/__tests__/InAppMessagingContext.spec.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { renderHook } from '@testing-library/react'; + +import { InAppMessagingContextType } from '..'; + +import { + ERROR_MESSAGE, + InAppMessagingProvider, + useInAppMessaging, +} from '../InAppMessagingContext'; + +const clearMessage = jest.fn(); +const displayMessage = jest.fn(); +const message = null; + +jest.mock('../useInAppMessagingState', () => ({ + useInAppMessagingState: (): InAppMessagingContextType => ({ + clearMessage, + displayMessage, + message, + }), +})); + +jest.mock('aws-amplify/in-app-messaging'); + +describe('useInAppMessaging', () => { + it('provides the values of InAppMessagingContext to consumers wrapped in InAppMessagingProvider', () => { + const { result } = renderHook(() => useInAppMessaging(), { + wrapper: ({ children }) => ( + {children} + ), + }); + + expect(result.current).toStrictEqual({ + clearMessage, + displayMessage, + message, + }); + }); + + it('throws an error when called outside an InAppMessagingProvider', () => { + /* eslint-disable no-console */ + // monkeypatch console.error into a no-op temporarily to supress React printed error regarding lack of + // ErrorBoundary component + const original = console.error; + console.error = () => {}; + + expect(() => renderHook(() => useInAppMessaging())).toThrow(ERROR_MESSAGE); + + console.error = original; + /* eslint-enable no-console */ + }); +}); diff --git a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/__tests__/InAppMessagingProvider.spec.tsx b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/__tests__/useInAppMessagingState.ts similarity index 51% rename from packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/__tests__/InAppMessagingProvider.spec.tsx rename to packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/__tests__/useInAppMessagingState.ts index 0d32d3f7771..61cf426b5b5 100644 --- a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/__tests__/InAppMessagingProvider.spec.tsx +++ b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/__tests__/useInAppMessagingState.ts @@ -1,11 +1,9 @@ -import React from 'react'; -import TestRenderer, { ReactTestRenderer } from 'react-test-renderer'; +import { renderHook, act } from '@testing-library/react'; + import * as InAppModule from 'aws-amplify/in-app-messaging'; -import { RenderNothing } from '@aws-amplify/ui-react-core'; -import { useInAppMessaging } from '../../../hooks/useInAppMessaging'; -import { InAppMessagingContextType } from '../..'; -import { InAppMessagingProvider } from '..'; +import { InAppMessagingContextType } from '../InAppMessagingContext'; +import { useInAppMessagingState } from '../useInAppMessagingState'; const onMessageReceivedSpy = jest.spyOn(InAppModule, 'onMessageReceived'); @@ -24,32 +22,17 @@ const mockOnMessageReceived = ( return { remove: mockRemove }; }; -const TestComponent = () => { - const props = useInAppMessaging(); - return ; -}; - const message = { layout: 'TOP_BANNER' as const, id: '0', content: [] }; -describe('InAppMessagingProvider', () => { - let renderer: ReactTestRenderer; - +describe('useInAppMessagingState', () => { beforeEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); onMessageReceivedSpy.mockImplementation(mockOnMessageReceived); - - TestRenderer.act(() => { - renderer = TestRenderer.create( - - - - ); - }); }); it('vends the expected initial context values', () => { - const expectedProps = { + const expected = { clearMessage: expect.any( Function ) as InAppMessagingContextType['clearMessage'], @@ -60,12 +43,14 @@ describe('InAppMessagingProvider', () => { style: undefined, }; - expect(renderer.root.findByType(RenderNothing).props).toEqual( - expectedProps - ); + const { result } = renderHook(() => useInAppMessagingState()); + + expect(result.current).toEqual(expected); }); it('registers a listener to InAppMessaging.onMessageReceived as expected', () => { + renderHook(() => useInAppMessagingState()); + expect(onMessageReceivedSpy).toHaveBeenCalledTimes(1); expect(onMessageReceivedSpy).toHaveBeenCalledWith( expect.any(Function) as InAppMessagingContextType['displayMessage'] @@ -73,53 +58,52 @@ describe('InAppMessagingProvider', () => { }); it('updates the value of message when the listener registered to InAppMessaging.onMessageReceived is called', () => { - TestRenderer.act(() => { + const { result } = renderHook(() => useInAppMessagingState()); + + expect(result.current.message).toBeNull(); + + act(() => { onMessageReceivedCallback(message); }); - const consumer = renderer.root.findByType(RenderNothing); - - expect((consumer.props as InAppMessagingContextType).message).toStrictEqual( - message - ); + expect(result.current.message).toStrictEqual(message); }); it('removes the listener registered to InAppMessaging.onMessageReceived as expected', () => { - TestRenderer.act(() => { - renderer.unmount(); + const { unmount } = renderHook(() => useInAppMessagingState()); + + act(() => { + unmount(); }); expect(mockRemove).toHaveBeenCalledTimes(1); }); it('updates the value of message when displayMessage is called', () => { - const consumer = renderer.root.findByType(RenderNothing); + const { result } = renderHook(() => useInAppMessagingState()); - TestRenderer.act(() => { - ( - consumer.props - .displayMessage as InAppMessagingContextType['displayMessage'] - )(message); + act(() => { + result.current.displayMessage(message); }); - expect((consumer.props as InAppMessagingContextType).message).toStrictEqual( - message - ); + expect(result.current.message).toStrictEqual(message); }); it('updates the value of message when clearMessage is called', () => { - const consumer = renderer.root.findByType(RenderNothing); + const { result } = renderHook(() => useInAppMessagingState()); + + expect(result.current.message).toBeNull(); - TestRenderer.act(() => { - (consumer.props as InAppMessagingContextType).displayMessage(message); + act(() => { + result.current.displayMessage(message); }); - expect(consumer.props.message).not.toBeNull(); + expect(result.current.message).toStrictEqual(message); - TestRenderer.act(() => { - (consumer.props as InAppMessagingContextType).clearMessage(); + act(() => { + result.current.clearMessage(); }); - expect(consumer.props.message).toBeNull(); + expect(result.current.message).toBeNull(); }); }); diff --git a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/index.ts b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/index.ts index 77a9fc71854..68619b49135 100644 --- a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/index.ts +++ b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/index.ts @@ -1,4 +1,8 @@ export { default as InAppMessagingContext, InAppMessagingContextType, + InAppMessagingProviderProps, + InAppMessagingProvider, + useInAppMessaging, + UseInAppMessaging, } from './InAppMessagingContext'; diff --git a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/useInAppMessagingState.ts b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/useInAppMessagingState.ts new file mode 100644 index 00000000000..c8ba44d245a --- /dev/null +++ b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingContext/useInAppMessagingState.ts @@ -0,0 +1,24 @@ +import { useEffect, useMemo, useState } from 'react'; +import { onMessageReceived } from 'aws-amplify/in-app-messaging'; +import { InAppMessagingContextType } from '../InAppMessagingContext'; + +export function useInAppMessagingState(): InAppMessagingContextType { + const [message, setMessage] = + useState(null); + + useEffect(() => { + const listener = onMessageReceived(setMessage); + return listener.remove; + }, []); + + return useMemo( + () => ({ + clearMessage: () => { + setMessage(null); + }, + displayMessage: setMessage, + message, + }), + [message] + ); +} diff --git a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/InAppMessagingProvider.tsx b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/InAppMessagingProvider.tsx deleted file mode 100644 index 4ce621341f3..00000000000 --- a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/InAppMessagingProvider.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { - ReactNode, - useCallback, - useEffect, - useMemo, - useState, -} from 'react'; -import { onMessageReceived } from 'aws-amplify/in-app-messaging'; -import { - InAppMessagingContext, - InAppMessagingContextType, -} from '../InAppMessagingContext'; - -export interface InAppMessagingProviderProps { - children: ReactNode; -} - -export default function InAppMessagingProvider({ - children, -}: InAppMessagingProviderProps): JSX.Element { - const [message, setMessage] = - useState(null); - - useEffect(() => { - const listener = onMessageReceived(setMessage); - return listener.remove; - }, []); - - const clearMessage = useCallback(() => { - setMessage(null); - }, []); - - const value = useMemo( - () => ({ - clearMessage, - displayMessage: setMessage, - message, - }), - [clearMessage, message] - ); - - return ( - - {children} - - ); -} diff --git a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/index.ts b/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/index.ts deleted file mode 100644 index daa7c8b894b..00000000000 --- a/packages/react-core-notifications/src/InAppMessaging/context/InAppMessagingProvider/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - InAppMessagingProviderProps, - default as InAppMessagingProvider, -} from './InAppMessagingProvider'; diff --git a/packages/react-core-notifications/src/InAppMessaging/context/index.ts b/packages/react-core-notifications/src/InAppMessaging/context/index.ts index 768ae70225e..3637954bda2 100644 --- a/packages/react-core-notifications/src/InAppMessaging/context/index.ts +++ b/packages/react-core-notifications/src/InAppMessaging/context/index.ts @@ -1,2 +1 @@ export * from './InAppMessagingContext'; -export * from './InAppMessagingProvider'; diff --git a/packages/react-core-notifications/src/InAppMessaging/hooks/index.ts b/packages/react-core-notifications/src/InAppMessaging/hooks/index.ts index 70a74838495..107ba71afce 100644 --- a/packages/react-core-notifications/src/InAppMessaging/hooks/index.ts +++ b/packages/react-core-notifications/src/InAppMessaging/hooks/index.ts @@ -1,2 +1 @@ -export * from './useInAppMessaging'; export * from './useMessage'; diff --git a/packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/__tests__/useInAppMessaging.spec.tsx b/packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/__tests__/useInAppMessaging.spec.tsx deleted file mode 100644 index 8b7875b674e..00000000000 --- a/packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/__tests__/useInAppMessaging.spec.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import TestRenderer from 'react-test-renderer'; -import { RenderNothing } from '@aws-amplify/ui-react-core'; - -import { useInAppMessaging } from '..'; - -const TestComponent = () => { - const props = useInAppMessaging(); - return ; -}; - -describe('useInAppMessaging', () => { - /* eslint-disable no-console */ - it('throws an error when called outside an InAppMessagingProvider', () => { - // monkeypatch console.error into a no-op temporarily to supress React printed error regarding lack of - // ErrorBoundary component - const original = console.error; - console.error = () => {}; - - expect(() => TestRenderer.create()).toThrow(); - - console.error = original; - }); - /* eslint-enable no-console */ -}); diff --git a/packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/index.ts b/packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/index.ts deleted file mode 100644 index 0fec701dc06..00000000000 --- a/packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - UseInAppMessaging, - default as useInAppMessaging, -} from './useInAppMessaging'; diff --git a/packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/useInAppMessaging.ts b/packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/useInAppMessaging.ts deleted file mode 100644 index 88ed29e37cf..00000000000 --- a/packages/react-core-notifications/src/InAppMessaging/hooks/useInAppMessaging/useInAppMessaging.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { useContext } from 'react'; -import { - InAppMessagingContext, - InAppMessagingContextType, -} from '../../context'; - -export type UseInAppMessaging = InAppMessagingContextType; - -/** - * Utility hook used to access the InAppMessagingContext values - * - * @returns {InAppMessagingContextType} InAppMessaging context values - */ - -export default function useInAppMessaging(): UseInAppMessaging { - const inAppMessagingContext = useContext(InAppMessagingContext); - if (!inAppMessagingContext) { - throw new Error( - 'InAppMessagingContext is empty, did you forget the InAppMessagingProvider?' - ); - } - return inAppMessagingContext; -} diff --git a/packages/react-core-notifications/src/InAppMessaging/hooks/useMessage/__tests__/useMessage.spec.ts b/packages/react-core-notifications/src/InAppMessaging/hooks/useMessage/__tests__/useMessage.spec.ts index bea60ed2450..df311e174b9 100644 --- a/packages/react-core-notifications/src/InAppMessaging/hooks/useMessage/__tests__/useMessage.spec.ts +++ b/packages/react-core-notifications/src/InAppMessaging/hooks/useMessage/__tests__/useMessage.spec.ts @@ -1,7 +1,8 @@ import * as InAppModule from 'aws-amplify/in-app-messaging'; import { ConsoleLogger as Logger } from 'aws-amplify/utils'; import { RenderNothing } from '@aws-amplify/ui-react-core'; -import { useInAppMessaging } from '../../useInAppMessaging'; + +import { useInAppMessaging } from '../../../context'; import { BannerMessageCommonProps, InAppMessage, @@ -11,7 +12,7 @@ import { UseMessageParams } from '../types'; import { EMPTY_PROPS } from '../useMessage'; import { useMessage } from '..'; -jest.mock('../../useInAppMessaging'); +jest.mock('../../../context'); jest.useFakeTimers(); type TestStyle = { backgroundColor: string }; diff --git a/packages/react-core-notifications/src/InAppMessaging/hooks/useMessage/useMessage.ts b/packages/react-core-notifications/src/InAppMessaging/hooks/useMessage/useMessage.ts index 1999d681336..5cea529376a 100644 --- a/packages/react-core-notifications/src/InAppMessaging/hooks/useMessage/useMessage.ts +++ b/packages/react-core-notifications/src/InAppMessaging/hooks/useMessage/useMessage.ts @@ -1,11 +1,11 @@ import { ConsoleLogger as Logger } from 'aws-amplify/utils'; +import { notifyMessageInteraction } from 'aws-amplify/in-app-messaging'; import { isNil } from '@aws-amplify/ui'; - import { RenderNothing } from '@aws-amplify/ui-react-core'; -import { useInAppMessaging } from '../useInAppMessaging'; + +import { useInAppMessaging } from '../../context'; import { UseMessage, UseMessageParams } from './types'; import { getContentProps, getPositionProp } from './utils'; -import { notifyMessageInteraction } from 'aws-amplify/in-app-messaging'; export const EMPTY_PROPS = Object.freeze({}); diff --git a/packages/react-core/jest.config.ts b/packages/react-core/jest.config.ts index 51924732fea..4e332128ae1 100644 --- a/packages/react-core/jest.config.ts +++ b/packages/react-core/jest.config.ts @@ -23,6 +23,7 @@ const config: Config = { moduleNameMapper: { '^uuid$': '/../../node_modules/uuid' }, modulePathIgnorePatterns: ['/dist/'], preset: 'ts-jest', + setupFilesAfterEnv: ['./jest.setup.ts'], testEnvironment: 'jsdom', }; diff --git a/packages/react-core/jest.setup.ts b/packages/react-core/jest.setup.ts new file mode 100644 index 00000000000..7b0828bfa80 --- /dev/null +++ b/packages/react-core/jest.setup.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom'; diff --git a/packages/react-core/src/components/RenderNothing/__tests__/RenderNothing.spec.tsx b/packages/react-core/src/components/RenderNothing/__tests__/RenderNothing.spec.tsx index 11aeb580b2b..250a86714f8 100644 --- a/packages/react-core/src/components/RenderNothing/__tests__/RenderNothing.spec.tsx +++ b/packages/react-core/src/components/RenderNothing/__tests__/RenderNothing.spec.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import TestRenderer from 'react-test-renderer'; +import { render } from '@testing-library/react'; import RenderNothing from '../RenderNothing'; describe('RenderNothing', () => { it('renders nothing', () => { - const renderer = TestRenderer.create(); + const { container } = render(); - expect(renderer.toJSON()).toBeNull(); + expect(container).toBeEmptyDOMElement(); }); }); diff --git a/packages/react-liveness/src/components/FaceLivenessDetector/shared/__tests__/LivenessIconWithPopover.test.tsx b/packages/react-liveness/src/components/FaceLivenessDetector/shared/__tests__/LivenessIconWithPopover.test.tsx index ed8d7fcde12..1838bfbcf61 100644 --- a/packages/react-liveness/src/components/FaceLivenessDetector/shared/__tests__/LivenessIconWithPopover.test.tsx +++ b/packages/react-liveness/src/components/FaceLivenessDetector/shared/__tests__/LivenessIconWithPopover.test.tsx @@ -1,8 +1,7 @@ import * as React from 'react'; -import { render, screen } from '@testing-library/react'; +import { act, render, screen } from '@testing-library/react'; import { LivenessIconWithPopover } from '../LivenessIconWithPopover'; -import { act } from 'react-test-renderer'; describe('LivenessIconWithPopover', () => { it('should render the component content appropriately', () => { diff --git a/packages/react-native/src/InAppMessaging/components/CarouselMessage/__tests__/CarouselMessage.spec.tsx b/packages/react-native/src/InAppMessaging/components/CarouselMessage/__tests__/CarouselMessage.spec.tsx index 2c11cbc4f05..0692d92a9e7 100644 --- a/packages/react-native/src/InAppMessaging/components/CarouselMessage/__tests__/CarouselMessage.spec.tsx +++ b/packages/react-native/src/InAppMessaging/components/CarouselMessage/__tests__/CarouselMessage.spec.tsx @@ -4,7 +4,6 @@ import { render } from '@testing-library/react-native'; import { IN_APP_MESSAGING_TEST_ID } from '../../../constants'; import CarouselMessage from '../CarouselMessage'; import { defaultStyle } from '../styles'; -import { ReactTestRendererJSON } from 'react-test-renderer'; jest.mock('../../../../primitives', () => ({ Carousel: 'Carousel' })); jest.mock('../../MessageWrapper', () => ({ MessageWrapper: 'MessageWrapper' })); @@ -85,7 +84,9 @@ describe('CarouselMessage', () => { const carouselMessageItem = toJSON(); expect(carouselMessageItem).toMatchSnapshot(); - const { props } = toJSON() as ReactTestRendererJSON; + const { props } = toJSON() as unknown as { + props: { layout: string; image: { src: string } }; + }; expect(props.layout).toEqual(baseProps.layout); expect(props.image).toEqual({ src: 'image-src' }); }); diff --git a/packages/react-native/src/primitives/Carousel/CarouselPageIndicator.tsx b/packages/react-native/src/primitives/Carousel/CarouselPageIndicator.tsx index 542761b7f40..46f6fe66784 100644 --- a/packages/react-native/src/primitives/Carousel/CarouselPageIndicator.tsx +++ b/packages/react-native/src/primitives/Carousel/CarouselPageIndicator.tsx @@ -12,6 +12,7 @@ export default function CarouselPageIndicator({ activeStyle, currentIndex, inactiveStyle, + indicatorTestId, numberOfItems, style, }: CarouselPageIndicatorProps): JSX.Element { @@ -24,15 +25,17 @@ export default function CarouselPageIndicator({ ) : ( ) ), - [activeStyle, currentIndex, inactiveStyle, numberOfItems] + [activeStyle, currentIndex, inactiveStyle, indicatorTestId, numberOfItems] ); return {items}; diff --git a/packages/react-native/src/primitives/Carousel/__tests__/Carousel.spec.tsx b/packages/react-native/src/primitives/Carousel/__tests__/Carousel.spec.tsx index 90f903acb0a..c13e80cde75 100644 --- a/packages/react-native/src/primitives/Carousel/__tests__/Carousel.spec.tsx +++ b/packages/react-native/src/primitives/Carousel/__tests__/Carousel.spec.tsx @@ -10,10 +10,11 @@ import { import { act, render } from '@testing-library/react-native'; import Carousel from '../Carousel'; -import { ReactTestInstance } from 'react-test-renderer'; jest.mock('../CarouselPageIndicator', () => 'CarouselPageIndicator'); +type ReactTestInstance = ReturnType['UNSAFE_root']; + type ItemProps = { str?: string }; const Item = ({ str }: ItemProps) => {str}; diff --git a/packages/react-native/src/primitives/Carousel/__tests__/CarouselPageIndicator.spec.tsx b/packages/react-native/src/primitives/Carousel/__tests__/CarouselPageIndicator.spec.tsx index 2c6e144d5f9..4102840a781 100644 --- a/packages/react-native/src/primitives/Carousel/__tests__/CarouselPageIndicator.spec.tsx +++ b/packages/react-native/src/primitives/Carousel/__tests__/CarouselPageIndicator.spec.tsx @@ -1,62 +1,78 @@ import React from 'react'; -import { render } from '@testing-library/react-native'; +import { render, screen } from '@testing-library/react-native'; import CarouselPageIndicator from '../CarouselPageIndicator'; -import { ReactTestRendererJSON } from 'react-test-renderer'; + import { DEFAULT_CAROUSEL_INDICATOR_ACTIVE_STYLE, DEFAULT_CAROUSEL_INDICATOR_INACTIVE_STYLE, } from '../constants'; +const INDICATOR_TEST_ID = 'indicator-test-id'; + describe('CarouselPageIndicator', () => { it('renders with multiple items', () => { - const { toJSON } = render( - + render( + ); - expect(toJSON()).toMatchSnapshot(); + const items = screen.queryAllByTestId(INDICATOR_TEST_ID); - const { children } = toJSON() as ReactTestRendererJSON; - expect(children).toHaveLength(3); + expect(items).toHaveLength(3); }); it('renders with just one item', () => { - const { toJSON } = render( - + render( + ); - expect(toJSON()).toMatchSnapshot(); - const { children } = toJSON() as ReactTestRendererJSON; - expect(children).toHaveLength(1); + const items = screen.queryAllByTestId(INDICATOR_TEST_ID); + expect(items).toHaveLength(1); }); it('handles null numberOfItems value', () => { // Ideally, this should not happen but, if it does, we should be able to handle gracefully - const { toJSON } = render( - + render( + ); - expect(toJSON()).toMatchSnapshot(); + const items = screen.queryByTestId(INDICATOR_TEST_ID); + + expect(items).toBeNull(); }); it('renders indicator styles based on current index', () => { - const { toJSON } = render( - + render( + ); - const { children } = toJSON() as ReactTestRendererJSON; - - expect(toJSON()).toMatchSnapshot(); + const items = screen.queryAllByTestId(INDICATOR_TEST_ID); - expect((children?.[0] as ReactTestRendererJSON).props.style).toStrictEqual([ + expect(items[0].props.style).toStrictEqual([ DEFAULT_CAROUSEL_INDICATOR_INACTIVE_STYLE, undefined, ]); - expect((children?.[1] as ReactTestRendererJSON).props.style).toStrictEqual([ + expect(items[1].props.style).toStrictEqual([ DEFAULT_CAROUSEL_INDICATOR_ACTIVE_STYLE, undefined, ]); - expect((children?.[2] as ReactTestRendererJSON).props.style).toStrictEqual([ + expect(items[2].props.style).toStrictEqual([ DEFAULT_CAROUSEL_INDICATOR_INACTIVE_STYLE, undefined, ]); diff --git a/packages/react-native/src/primitives/Carousel/__tests__/__snapshots__/CarouselPageIndicator.spec.tsx.snap b/packages/react-native/src/primitives/Carousel/__tests__/__snapshots__/CarouselPageIndicator.spec.tsx.snap index 35c6a022213..5b8c43e3f46 100644 --- a/packages/react-native/src/primitives/Carousel/__tests__/__snapshots__/CarouselPageIndicator.spec.tsx.snap +++ b/packages/react-native/src/primitives/Carousel/__tests__/__snapshots__/CarouselPageIndicator.spec.tsx.snap @@ -74,118 +74,3 @@ exports[`CarouselPageIndicator handles null index value 1`] = ` /> `; - -exports[`CarouselPageIndicator handles null numberOfItems value 1`] = ``; - -exports[`CarouselPageIndicator renders indicator styles based on current index 1`] = ` - - - - - -`; - -exports[`CarouselPageIndicator renders with just one item 1`] = ` - - - -`; - -exports[`CarouselPageIndicator renders with multiple items 1`] = ` - - - - - -`; diff --git a/packages/react-native/src/primitives/Carousel/types.ts b/packages/react-native/src/primitives/Carousel/types.ts index a6f098095b3..37795a78394 100644 --- a/packages/react-native/src/primitives/Carousel/types.ts +++ b/packages/react-native/src/primitives/Carousel/types.ts @@ -14,6 +14,7 @@ export interface CarouselPageIndicatorProps { activeStyle?: StyleProp; currentIndex: number | null; inactiveStyle?: StyleProp; + indicatorTestId?: string; numberOfItems: number; style?: StyleProp; }