import { render } from '@testing-library/react-native'; import { Text, View } from 'react-native'; import { CSMask } from '../../../replay/masking/CSMask.ios'; // Import the specific iOS version directly // Mock CSQMethodFilter jest.mock('../../../csq/CSQMethodFilter', () => ({ __esModule: true, default: { warnIfDisabled: jest.fn(), }, })); // Mock the CSMaskedView and CSUnmaskedView components jest.mock('../../../core/specs/CSMaskedViewNativeComponent', () => { const React = require('react'); return React.forwardRef((props, ref) => { return React.createElement( 'View', { ...props, ref, testID: 'CSMaskedViewNativeComponent', 'data-original-testid': props.testID, // Preserve original testID for assertions }, props.children ); }); }); jest.mock('../../../core/specs/CSUnmaskedViewNativeComponent', () => { const React = require('react'); return React.forwardRef((props, ref) => { return React.createElement( 'View', { ...props, ref, testID: 'CSUnmaskedViewNativeComponent', 'data-original-testid': props.testID, // Preserve original testID for assertions }, props.children ); }); }); describe('CSMask.ios', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('rendering behavior', () => { it('should render CSMaskedViewNativeComponent when isMasking is true', () => { const { getByTestId } = render( Test Child ); expect(getByTestId('CSMaskedViewNativeComponent')).toBeTruthy(); }); it('should render CSUnmaskedViewNativeComponent when isMasking is false', () => { const { getByTestId } = render( Test Child ); expect(getByTestId('CSUnmaskedViewNativeComponent')).toBeTruthy(); }); it('should default to masked view when isMasking is not provided', () => { const { getByTestId } = render( Test Child ); expect(getByTestId('CSMaskedViewNativeComponent')).toBeTruthy(); }); }); describe('props forwarding', () => { it('should forward all props to the masked component', () => { const testProps = { isMasking: true, testID: 'test-id', style: { backgroundColor: 'red' }, customProp: 'custom-value', }; const { getByTestId } = render( Test Child ); const maskedComponent = getByTestId('CSMaskedViewNativeComponent'); expect(maskedComponent).toBeTruthy(); expect(maskedComponent.props['data-original-testid']).toBe('test-id'); expect(maskedComponent.props.style).toEqual({ backgroundColor: 'red' }); expect(maskedComponent.props.customProp).toBe('custom-value'); }); it('should forward all props to the unmasked component', () => { const testProps = { isMasking: false, testID: 'test-id', style: { backgroundColor: 'blue' }, customProp: 'custom-value', }; const { getByTestId } = render( Test Child ); const unmaskedComponent = getByTestId('CSUnmaskedViewNativeComponent'); expect(unmaskedComponent).toBeTruthy(); expect(unmaskedComponent.props['data-original-testid']).toBe('test-id'); expect(unmaskedComponent.props.style).toEqual({ backgroundColor: 'blue', }); expect(unmaskedComponent.props.customProp).toBe('custom-value'); }); it('should not forward isMasking prop to native components', () => { const { getByTestId } = render( Test Child ); const maskedComponent = getByTestId('CSMaskedViewNativeComponent'); expect(maskedComponent.props.isMasking).toBeUndefined(); }); }); describe('children rendering', () => { it('should render children in masked component', () => { const { getByTestId, getByText } = render( Child Content ); expect(getByTestId('CSMaskedViewNativeComponent')).toBeTruthy(); expect(getByText('Child Content')).toBeTruthy(); }); it('should render children in unmasked component', () => { const { getByTestId, getByText } = render( Child Content ); expect(getByTestId('CSUnmaskedViewNativeComponent')).toBeTruthy(); expect(getByText('Child Content')).toBeTruthy(); }); it('should render multiple children', () => { const { getByText } = render( First Child Second Child Nested Child ); expect(getByText('First Child')).toBeTruthy(); expect(getByText('Second Child')).toBeTruthy(); expect(getByText('Nested Child')).toBeTruthy(); }); it('should handle no children gracefully', () => { const { getByTestId } = render( {null} ); expect(getByTestId('CSMaskedViewNativeComponent')).toBeTruthy(); }); }); describe('component switching', () => { it('should switch from masked to unmasked when isMasking changes', () => { const { getByTestId, rerender, queryByTestId } = render( Test Child ); // Initially masked expect(getByTestId('CSMaskedViewNativeComponent')).toBeTruthy(); expect(queryByTestId('CSUnmaskedViewNativeComponent')).toBeNull(); // Switch to unmasked rerender( Test Child ); expect(getByTestId('CSUnmaskedViewNativeComponent')).toBeTruthy(); expect(queryByTestId('CSMaskedViewNativeComponent')).toBeNull(); }); it('should switch from unmasked to masked when isMasking changes', () => { const { getByTestId, rerender, queryByTestId } = render( Test Child ); // Initially unmasked expect(getByTestId('CSUnmaskedViewNativeComponent')).toBeTruthy(); expect(queryByTestId('CSMaskedViewNativeComponent')).toBeNull(); // Switch to masked rerender( Test Child ); expect(getByTestId('CSMaskedViewNativeComponent')).toBeTruthy(); expect(queryByTestId('CSUnmaskedViewNativeComponent')).toBeNull(); }); }); describe('edge cases', () => { it('should handle undefined isMasking prop', () => { const { getByTestId } = render( Test Child ); // Should default to true (masked) expect(getByTestId('CSMaskedViewNativeComponent')).toBeTruthy(); }); it('should handle null isMasking prop', () => { const { getByTestId } = render( Test Child ); // Should render unmasked (falsy value) expect(getByTestId('CSUnmaskedViewNativeComponent')).toBeTruthy(); }); it('should handle truthy non-boolean values', () => { const { getByTestId } = render( Test Child ); // Should render masked (truthy value) expect(getByTestId('CSMaskedViewNativeComponent')).toBeTruthy(); }); it('should handle falsy non-boolean values', () => { const { getByTestId } = render( Test Child ); // Should render unmasked (falsy value) expect(getByTestId('CSUnmaskedViewNativeComponent')).toBeTruthy(); }); }); describe('accessibility and testID', () => { it('should pass through accessibility props to masked component', () => { const { getByTestId } = render( Test Child ); const maskedComponent = getByTestId('CSMaskedViewNativeComponent'); expect(maskedComponent.props.accessibilityLabel).toBe('Masked content'); expect(maskedComponent.props.accessibilityHint).toBe( 'This content is masked' ); }); it('should pass through accessibility props to unmasked component', () => { const { getByTestId } = render( Test Child ); const unmaskedComponent = getByTestId('CSUnmaskedViewNativeComponent'); expect(unmaskedComponent.props.accessibilityLabel).toBe( 'Unmasked content' ); expect(unmaskedComponent.props.accessibilityHint).toBe( 'This content is unmasked' ); }); }); describe('performance', () => { it('should not re-render children when isMasking changes', () => { const ChildComponent = jest.fn(() => Child); const { rerender } = render( ); expect(ChildComponent).toHaveBeenCalledTimes(1); rerender( ); // Child should re-render because it's moved to a different component expect(ChildComponent).toHaveBeenCalledTimes(2); }); }); });