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);
});
});
});