import React from 'react';
import { render, cleanup } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { FlexDirectionsEnum, JustifyEnum, AlignEnum } from '../../types';
import { Box } from './index';

afterEach(cleanup);

test('should take a snapshot', () => {
	const { asFragment } = render(<Box />);

	expect(asFragment()).toMatchSnapshot();
});

describe('tests the box with and without children', () => {
	test('renders a Box with no children', () => {
		const { getByTestId } = render(<Box data-testid="box-id" />);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toBeEmptyDOMElement();
	});

	test('renders a Box with children', () => {
		const { getByTestId } = render(
			<Box data-testid="box-id">
				<div data-testid="child-id" />
			</Box>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toContainElement(getByTestId('child-id'));
	});
});

describe('tests the flexbox properties', () => {
	test('renders a Box with flex row', () => {
		const { getByTestId } = render(
			<Box data-testid="box-id" flex={FlexDirectionsEnum.row}>
				<div data-testid="child-id" />
			</Box>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			display: 'flex',
			'flex-direction': 'row',
		});
	});
	test('renders a Box with flex column and justify', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				justify={JustifyEnum.center}
				flex={FlexDirectionsEnum.column}>
				<div data-testid="child-id" />
			</Box>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			display: 'flex',
			'flex-direction': 'column',
			'justify-content': 'center',
		});
	});
	test('renders a Box with flex reverse-column align and justify', () => {
		const { getByTestId } = render(
			<Box
				align={AlignEnum.center}
				data-testid="box-id"
				flex={FlexDirectionsEnum['column-reverse']}
				justify={JustifyEnum.center}>
				<div data-testid="child-id" />
			</Box>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'align-items': 'center',
			display: 'flex',
			'flex-direction': 'column-reverse',
			'justify-content': 'center',
		});
	});
});

describe('tests the adjustable height and width', () => {
	test('renders a Box with height and width', () => {
		const { getByTestId } = render(
			<Box data-testid="box-id" width={10} height={5}>
				<div data-testid="child-id" />
			</Box>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			height: '5rem',
			width: '10rem',
		});
	});
});

describe('tests the adjustable max/min height/width', () => {
	test('renders a Box with max height and max width', () => {
		const { getByTestId } = render(
			<Box data-testid="box-id" maxW="100px" maxH="50px">
				<div data-testid="child-id" />
			</Box>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'max-height': '50px',
			'max-width': '100px',
		});
	});
	test('renders a Box with min height and min width', () => {
		const { getByTestId } = render(
			<Box data-testid="box-id" minW="100px" minH="50px">
				<div data-testid="child-id" />
			</Box>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'min-height': '50px',
			'min-width': '100px',
		});
	});
});

describe('tests the border props', () => {
	test('renders a Box with a b string', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				b="1px solid #aaaaaa"
				height="100px"
				width="50px"
			/>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			border: '1px solid #aaaaaa',
		});
	});
	test('renders a Box with bx/by as number', () => {
		const { getByTestId } = render(
			<Box data-testid="box-id" bx={1} by={1} height="100px" width="50px" />
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'border-top-width': '1px',
			'border-right-width': '1px',
			'border-bottom-width': '1px',
			'border-left-width': '1px',
			'border-color': '#aaaaaa',
			'border-style': 'solid',
		});
	});
	test('renders a Box with bx/by as string', () => {
		const { getByTestId } = render(
			<Box data-testid="box-id" bx="2px" by="2px" height="100px" width="50px" />
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'border-top-width': '2px',
			'border-right-width': '2px',
			'border-bottom-width': '2px',
			'border-left-width': '2px',
		});
	});
	test('renders a Box with bt/br/bb/bl as string', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				bt="2px"
				br="2px"
				bb="2px"
				bl="2px"
				height="100px"
				width="50px"
			/>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'border-top-width': '2px',
			'border-right-width': '2px',
			'border-bottom-width': '2px',
			'border-left-width': '2px',
		});
	});
	test('renders a Box with bt/br/bb/bl as number', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				bt={1}
				br={1}
				bb={1}
				bl={1}
				height="100px"
				width="50px"
			/>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'border-top-width': '1px',
			'border-right-width': '1px',
			'border-bottom-width': '1px',
			'border-left-width': '1px',
		});
	});
});

describe('tests the radius props', () => {
	test('renders a Box with a radius string', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				radius="1rem 0.5rem"
				height="100px"
				width="50px"
			/>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			borderRadius: '1rem 0.5rem',
		});
	});
	test('renders a Box with a radius number', () => {
		const { getByTestId } = render(
			<Box data-testid="box-id" radius={2} height="100px" width="50px" />
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			borderRadius: '2rem',
		});
	});
});

describe('tests the spacing properties (margin/padding)', () => {
	test('renders a Box with padding and margin as numbers', () => {
		const { getByTestId } = render(
			<Box data-testid="box-id" p={0.5} m={0.5} height="100px" width="50px" />
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			margin: '0.5rem',
			padding: '0.5rem',
		});
	});
	test('renders a Box with padding and margin as string', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				p="10px 12px 16px 14px"
				m="10px 12px 16px 14px"
				height="100px"
				width="50px"
			/>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			margin: '10px 12px 16px 14px',
			padding: '10px 12px 16px 14px',
		});
	});
	test('renders a Box with px/py and mx/my as number', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				px={0.75}
				py={0.75}
				mx={0.75}
				my={0.75}
				height="100px"
				width="50px"
			/>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'margin-top': '0.75rem',
			'margin-right': '0.75rem',
			'margin-bottom': '0.75rem',
			'margin-left': '0.75rem',
			'padding-top': '0.75rem',
			'padding-right': '0.75rem',
			'padding-bottom': '0.75rem',
			'padding-left': '0.75rem',
		});
	});
	test('renders a Box with px/py and mx/my as string', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				px="12px"
				py="12px"
				mx="12px"
				my="12px"
				height="100px"
				width="50px"
			/>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'margin-top': '12px',
			'margin-right': '12px',
			'margin-bottom': '12px',
			'margin-left': '12px',
			'padding-top': '12px',
			'padding-right': '12px',
			'padding-bottom': '12px',
			'padding-left': '12px',
		});
	});
	test('renders a Box with pt/pr/pb/pl and mt/mr/mb/ml as string', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				pt="12px"
				pr="12px"
				pb="12px"
				pl="12px"
				mt="12px"
				mr="12px"
				mb="12px"
				ml="12px"
				height="100px"
				width="50px"
			/>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'margin-top': '12px',
			'margin-right': '12px',
			'margin-bottom': '12px',
			'margin-left': '12px',
			'padding-top': '12px',
			'padding-right': '12px',
			'padding-bottom': '12px',
			'padding-left': '12px',
		});
	});
	test('renders a Box with pt/pr/pb/pl and mt/mr/mb/ml as number', () => {
		const { getByTestId } = render(
			<Box
				data-testid="box-id"
				pt={0.75}
				pr={0.75}
				pb={0.75}
				pl={0.75}
				mt={0.75}
				mr={0.75}
				mb={0.75}
				ml={0.75}
				height="100px"
				width="50px"
			/>
		);
		expect(getByTestId('box-id')).toBeInTheDocument();
		expect(getByTestId('box-id')).toHaveStyle({
			'margin-top': '0.75rem',
			'margin-right': '0.75rem',
			'margin-bottom': '0.75rem',
			'margin-left': '0.75rem',
			'padding-top': '0.75rem',
			'padding-right': '0.75rem',
			'padding-bottom': '0.75rem',
			'padding-left': '0.75rem',
		});
	});
});

describe('tests the elevation prop', () => {
	test('renders Boxes with different elevations', () => {
		const { getByTestId } = render(
			<>
				<Box
					flex={FlexDirectionsEnum.row}
					mb={0.5}
					justify={JustifyEnum.center}>
					<Box
						elevation={5}
						height={5}
						mr={0.5}
						width={5}
						data-testid="elevation-5"
					/>
					<Box
						elevation={4}
						height={5}
						mr={0.5}
						width={5}
						data-testid="elevation-4"
					/>
					<Box
						elevation={3}
						height={5}
						mr={0.5}
						width={5}
						data-testid="elevation-3"
					/>
				</Box>
				<Box
					flex={FlexDirectionsEnum['row-reverse']}
					mb={0.5}
					justify={JustifyEnum.center}>
					<Box
						elevation={2}
						height={5}
						mr={0.5}
						width={5}
						data-testid="elevation-2"
					/>
					<Box
						elevation={1}
						height={5}
						mr={0.5}
						width={5}
						data-testid="elevation-1"
					/>
					<Box
						elevation={0}
						height={5}
						mr={0.5}
						width={5}
						data-testid="elevation-0"
					/>
				</Box>
				<Box
					flex={FlexDirectionsEnum.row}
					mb={0.5}
					justify={JustifyEnum.center}>
					<Box
						elevation={-1}
						height={5}
						mr={0.5}
						width={5}
						data-testid="elevation--1"
					/>
					<Box
						elevation={-2}
						height={5}
						mr={0.5}
						width={5}
						data-testid="elevation--2"
					/>
					<Box
						elevation={-3}
						height={5}
						mr={0.5}
						width={5}
						data-testid="elevation--3"
					/>
				</Box>
			</>
		);
		expect(getByTestId('elevation-5')).toHaveStyle({
			'box-shadow': '0px 15px 20px rgba(0,0,0,0.15)',
		});
		expect(getByTestId('elevation-4')).toHaveStyle({
			'box-shadow': '0px 10px 15px rgba(0,0,0,0.15)',
		});
		expect(getByTestId('elevation-3')).toHaveStyle({
			'box-shadow': '0px 5px 10px rgba(0,0,0,0.15)',
		});
		expect(getByTestId('elevation-2')).toHaveStyle({
			'box-shadow': '0px 2.5px 5px rgba(0,0,0,0.15)',
		});
		expect(getByTestId('elevation-1')).toHaveStyle({
			'box-shadow': '0px 1.25px 2.5px rgba(0,0,0,0.15)',
		});
		expect(getByTestId('elevation-0')).toHaveStyle({
			'box-shadow': 'none',
			border: '1px solid #fffffe',
		});
		expect(getByTestId('elevation--1')).toHaveStyle({
			'box-shadow': 'inset 0px 2.5px 5px rgba(0,0,0,0.15)',
		});
		expect(getByTestId('elevation--2')).toHaveStyle({
			'box-shadow': 'inset 0px 5px 10px rgba(0,0,0,0.15)',
		});
		expect(getByTestId('elevation--3')).toHaveStyle({
			'box-shadow': 'inset 0px 10px 15px rgba(0,0,0,0.15)',
		});
	});
});
