import React from 'react';
import { render, renderHook } from '@testing-library/react-native';
import { ConsoleLogger as Logger } from '@aws-amplify/core';
import { useTheme } from '../../../theme';
import { getThemedStyles } from '../styles';
import Icon from '../Icon';
import { IconProps, iconSizes } from '..';
import { Size } from '../types';
// use empty mockImplementation to turn off console output
const warnSpy = jest.spyOn(Logger.prototype, 'warn').mockImplementation();
const MOCK_SOURCE = { uri: 'mock.png' };
const testID = 'iconTestID';
const props: IconProps = {
source: MOCK_SOURCE,
testID,
};
describe('Icon', () => {
it('renders as expected', () => {
const { toJSON, getByTestId } = render();
expect(toJSON()).toMatchSnapshot();
const { result } = renderHook(() => useTheme());
const themedStyle = getThemedStyles(result.current);
const image = getByTestId(testID);
expect(image.props.accessibilityRole).toEqual('image');
expect(image.props.source).toEqual(MOCK_SOURCE);
expect(themedStyle.icon.height).toEqual(iconSizes.medium);
expect(themedStyle.icon.width).toEqual(iconSizes.medium);
expect(image.props.style).toStrictEqual([themedStyle.icon, undefined]);
});
it('renders as expected with custom styles', () => {
const customStyle = { tintColor: 'red' };
const { toJSON, getByTestId } = render(
);
expect(toJSON()).toMatchSnapshot();
const { result } = renderHook(() => useTheme());
const themedStyle = getThemedStyles(result.current);
expect(getByTestId(testID).props.style).toStrictEqual([
themedStyle.icon,
customStyle,
]);
});
it('renders an animated icon', () => {
const { toJSON } = render();
expect(toJSON()).toMatchSnapshot();
});
it('should override size as number', () => {
const testSize = 22;
const { toJSON, getByTestId } = render();
expect(toJSON()).toMatchSnapshot();
const { result } = renderHook(() => useTheme());
const themedStyle = getThemedStyles(result.current, undefined, testSize);
const image = getByTestId(testID);
expect(themedStyle.icon.height).toEqual(testSize);
expect(themedStyle.icon.width).toEqual(testSize);
expect(image.props.style).toStrictEqual([themedStyle.icon, undefined]);
});
it('should override size as string', () => {
const testSize = 'large';
const { toJSON, getByTestId } = render();
expect(toJSON()).toMatchSnapshot();
const { result } = renderHook(() => useTheme());
const themedStyle = getThemedStyles(result.current, undefined, testSize);
const image = getByTestId(testID);
expect(themedStyle.icon.height).toEqual(iconSizes[testSize]);
expect(themedStyle.icon.width).toEqual(iconSizes[testSize]);
expect(image.props.style).toStrictEqual([themedStyle.icon, undefined]);
});
it('throws an error for invalid size type', () => {
const invalidSize = 'small_medium' as unknown as Size;
const { toJSON } = render();
expect(toJSON()).toMatchSnapshot();
expect(warnSpy).toHaveBeenCalledTimes(1);
expect(warnSpy).toHaveBeenCalledWith(
`"${invalidSize}" is not a valid icon size. Available values are: ${Object.keys(
iconSizes
)}`
);
});
});