import * as React from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { BLOCK_CLASS, BODY_TEXT_TEST_ID, BUTTON_CLASS, BUTTON_GROUP_TEST_ID, CONTENT_CLASS, CONTENT_TEST_ID, HEADER_TEXT_TEST_ID, IMAGE_CONTAINER_CLASS, IMAGE_CONTAINER_TEST_ID, MESSAGE_LAYOUT_TEST_ID, PRIMARY_BUTTON_TEST_ID, SECONDARY_BUTTON_TEST_ID, TEXT_CONTAINER_CLASS, TEXT_CONTAINER_TEST_ID, } from '../constants'; import { MessageLayout } from '../MessageLayout'; import { MessageLayoutProps } from '../types'; import { getButtonModifier } from '../utils'; jest.mock('../utils'); const mockOnClose = jest.fn(); const mockPrimaryButtonOnAction = jest.fn(); const mockSecondaryButtonOnAction = jest.fn(); const BODY_CONTENT = 'body content'; const DARK_BACKGROUND_COLOR = 'black'; const HEADER_CONTENT = 'header content'; const IMAGE_SRC = 'http://image.url'; const LIGHT_BACKGROUND_COLOR = 'white'; const PRIMARY_BUTTON = 'primary button'; const SECONDARY_BUTTON = 'secondary button'; const STYLES = { body: { backgroundColor: '#001' }, closeIconButton: { backgroundColor: '#002' }, container: { backgroundColor: '#003' }, header: { backgroundColor: '#004' }, image: { backgroundColor: '#005' }, primaryButton: { backgroundColor: DARK_BACKGROUND_COLOR }, secondaryButton: { backgroundColor: LIGHT_BACKGROUND_COLOR }, }; const TEST_PROPS: MessageLayoutProps = { body: { content: BODY_CONTENT }, hasRenderableImage: false, header: { content: HEADER_CONTENT }, image: { src: IMAGE_SRC }, layout: 'TOP_BANNER', onClose: mockOnClose, styles: STYLES, }; const primaryButton = { title: PRIMARY_BUTTON, onAction: mockPrimaryButtonOnAction, }; const secondaryButton = { title: SECONDARY_BUTTON, onAction: mockSecondaryButtonOnAction, }; describe('MessageLayout component', () => { beforeEach(() => { jest.clearAllMocks(); }); it('should render', () => { render(); const buttons = screen.queryAllByRole('button'); const body = screen.queryByText(BODY_CONTENT); const header = screen.queryByText(HEADER_CONTENT); const imageContainer = screen.queryByTestId(IMAGE_CONTAINER_TEST_ID); const messageLayout = screen.queryByTestId(MESSAGE_LAYOUT_TEST_ID); const textContainer = screen.queryByTestId(TEXT_CONTAINER_TEST_ID); expect(body).toBeInTheDocument(); expect(buttons).toHaveLength(1); // only close button expect(header).toBeInTheDocument(); expect(imageContainer).not.toBeInTheDocument(); expect(messageLayout).toBeInTheDocument(); expect(textContainer).toBeInTheDocument(); expect(messageLayout).toHaveClass(BLOCK_CLASS); }); it('should render with an image', () => { render(); const image = screen.queryByRole('img'); const imageContainer = screen.queryByTestId(IMAGE_CONTAINER_TEST_ID); expect(imageContainer).toBeInTheDocument(); expect(image).toBeInTheDocument(); expect(image).toHaveAttribute('src', IMAGE_SRC); }); it('should be vertical orientation by default', () => { render(); const content = screen.getByTestId(CONTENT_TEST_ID); const imageContainer = screen.getByTestId(IMAGE_CONTAINER_TEST_ID); const textContainer = screen.getByTestId(TEXT_CONTAINER_TEST_ID); expect(content).toHaveClass(`${CONTENT_CLASS}--vertical`); expect(imageContainer).toHaveClass(`${IMAGE_CONTAINER_CLASS}--vertical`); expect(textContainer).toHaveClass(`${TEXT_CONTAINER_CLASS}--vertical`); }); it('should allow horizontal orientation', () => { render( ); const content = screen.getByTestId(CONTENT_TEST_ID); const imageContainer = screen.getByTestId(IMAGE_CONTAINER_TEST_ID); const textContainer = screen.getByTestId(TEXT_CONTAINER_TEST_ID); expect(content).toHaveClass(`${CONTENT_CLASS}--horizontal`); expect(imageContainer).toHaveClass(`${IMAGE_CONTAINER_CLASS}--horizontal`); expect(textContainer).toHaveClass(`${TEXT_CONTAINER_CLASS}--horizontal`); }); it('should trigger onClose function', () => { render(); const closeButton = screen.getByRole('button'); userEvent.click(closeButton); expect(mockOnClose).toBeCalled(); }); it('should render a primary button', () => { render(); expect(screen.queryByText(PRIMARY_BUTTON)).toBeInTheDocument(); }); it('should render a secondary button', () => { render( ); expect(screen.queryByText(PRIMARY_BUTTON)).toBeInTheDocument(); expect(screen.queryByText(SECONDARY_BUTTON)).toBeInTheDocument(); }); it('should apply the correct button modifiers', () => { (getButtonModifier as jest.Mock).mockImplementation(({ backgroundColor }) => backgroundColor === DARK_BACKGROUND_COLOR ? 'dark' : 'light' ); render( ); expect(screen.getByText(PRIMARY_BUTTON)).toHaveClass( `${BUTTON_CLASS}--dark` ); expect(screen.getByText(SECONDARY_BUTTON)).toHaveClass( `${BUTTON_CLASS}--light` ); }); it('should trigger the button onAction functions', () => { render( ); userEvent.click(screen.getByText(PRIMARY_BUTTON)); expect(mockPrimaryButtonOnAction).toBeCalled(); expect(mockSecondaryButtonOnAction).not.toBeCalled(); userEvent.click(screen.getByText(SECONDARY_BUTTON)); expect(mockSecondaryButtonOnAction).toBeCalled(); }); it('should apply additional styles to components', () => { render( ); const [closeButton, secondaryButtonElement, primaryButtonElement] = screen.getAllByRole('button'); const body = screen.getByText(BODY_CONTENT); const header = screen.getByText(HEADER_CONTENT); const image = screen.getByRole('img'); const messageLayout = screen.getByTestId(MESSAGE_LAYOUT_TEST_ID); expect(body).toHaveStyle(STYLES.body); expect(closeButton).toHaveStyle(STYLES.closeIconButton); expect(header).toHaveStyle(STYLES.header); expect(image).toHaveStyle(STYLES.image); expect(messageLayout).toHaveStyle(STYLES.container); expect(primaryButtonElement).toHaveStyle(STYLES.primaryButton); expect(secondaryButtonElement).toHaveStyle(STYLES.secondaryButton); }); it('does not render header text if header content is missing', () => { const { queryByTestId } = render( ); const headerText = queryByTestId(HEADER_TEXT_TEST_ID); expect(headerText).toBeNull(); }); it('does not render body text if body content is missing', () => { const { queryByTestId } = render( ); const bodyText = queryByTestId(BODY_TEXT_TEST_ID); expect(bodyText).toBeNull(); }); it('does not render a primary button if no primaryButton prop', () => { const { queryByTestId } = render(); expect(queryByTestId(PRIMARY_BUTTON_TEST_ID)).toBeNull(); }); it('does not render a secondary button if no secondaryButton prop', () => { const { queryByTestId } = render(); expect(queryByTestId(SECONDARY_BUTTON_TEST_ID)).toBeNull(); }); it('does not render any buttons or a button group', () => { const { queryByTestId } = render(); expect(queryByTestId(BUTTON_GROUP_TEST_ID)).toBeNull(); expect(queryByTestId(PRIMARY_BUTTON_TEST_ID)).toBeNull(); expect(queryByTestId(SECONDARY_BUTTON)).toBeNull(); }); });