import { fireEvent } from '@testing-library/react' import userEvent from '@testing-library/user-event' import * as React from 'react' import animationRender from '../../tests/helpers/animationRender' import renderWithTheme from '../../tests/helpers/renderWithTheme' import ColorPicker from './ColorPicker' describe('component: ColorPicker', () => { describe('can be controlled', () => { test('with hsl', () => { const { getByLabelText } = renderWithTheme( ) expect((getByLabelText('Color') as HTMLInputElement).value).toBe('#00FF00') }) test('with hsv', () => { const { getByLabelText } = renderWithTheme( ) expect((getByLabelText('Color') as HTMLInputElement).value).toBe('#00FF00') }) test('with rgb', () => { const { getByLabelText } = renderWithTheme( ) expect((getByLabelText('Color') as HTMLInputElement).value).toBe('#00FF00') }) test('with hex', () => { const { getByLabelText } = renderWithTheme( ) expect((getByLabelText('Color') as HTMLInputElement).value).toBe('#00FF00') }) test('empty string resets value', () => { const { getByLabelText, rerender } = renderWithTheme( ) rerender() expect((getByLabelText('Color') as HTMLInputElement).value).toBe('#000000') }) }) test('can open portal', async () => { const { getByLabelText, queryByRole } = renderWithTheme( ) const trigger = getByLabelText('Click to open the color picker') expect(queryByRole('dialog')).toBe(null) userEvent.click(trigger) expect(queryByRole('dialog')).toBeInTheDocument() // Should focus the hex input when initially opened await animationRender() expect(document.activeElement).toBe(getByLabelText('Hex')) }) describe('calls onChange', () => { test('when apply button is clicked', () => { const onChange = jest.fn() const { getByLabelText, getByText } = renderWithTheme( ) const trigger = getByLabelText('Click to open the color picker') userEvent.click(trigger) const redInput = getByLabelText('R') as HTMLInputElement const greenInput = getByLabelText('G') as HTMLInputElement const blueInput = getByLabelText('B') as HTMLInputElement userEvent.clear(redInput) userEvent.type(redInput, '0') fireEvent.blur(redInput) userEvent.clear(greenInput) userEvent.type(greenInput, '0') fireEvent.blur(greenInput) userEvent.clear(blueInput) userEvent.type(blueInput, '255') fireEvent.blur(blueInput) expect(onChange).not.toHaveBeenCalled() const applyButton = getByText('Apply') userEvent.click(applyButton) expect(onChange).toHaveBeenCalledTimes(1) }) test('when outer hex input is changed', () => { const onChange = jest.fn() const { getByLabelText } = renderWithTheme( ) const outerHexInput = getByLabelText('Color') userEvent.clear(outerHexInput) userEvent.type(outerHexInput, 'FF0000') expect(onChange).toHaveBeenCalledTimes(1) }) }) describe('does not call onChange', () => { test('when cancel button is clicked', () => { const onChange = jest.fn() const { getByLabelText, getByText } = renderWithTheme( ) const trigger = getByLabelText('Click to open the color picker') userEvent.click(trigger) const redInput = getByLabelText('R') as HTMLInputElement const greenInput = getByLabelText('G') as HTMLInputElement const blueInput = getByLabelText('B') as HTMLInputElement userEvent.clear(redInput) userEvent.type(redInput, '0') fireEvent.blur(redInput) userEvent.clear(greenInput) userEvent.type(greenInput, '0') fireEvent.blur(greenInput) userEvent.clear(blueInput) userEvent.type(blueInput, '255') fireEvent.blur(blueInput) const cancelButton = getByText('Cancel') userEvent.click(cancelButton) expect(onChange).not.toHaveBeenCalled() const outerHexInput = getByLabelText('Color') as HTMLInputElement expect(outerHexInput.value).toBe('#000000') expect(onChange).toHaveBeenCalledTimes(0) }) }) describe('calls onFocus', () => { test('when outer hex input is focused', () => { const onFocus = jest.fn() const { getByLabelText } = renderWithTheme( ) const outerHexInput = getByLabelText('Color') fireEvent.focus(outerHexInput) expect(onFocus).toHaveBeenCalledTimes(1) }) test('when icon button is clicked', () => { const onFocus = jest.fn() const onBlur = jest.fn() const { getByLabelText } = renderWithTheme( ) const trigger = getByLabelText('Click to open the color picker') userEvent.click(trigger) expect(onFocus).toHaveBeenCalledTimes(1) expect(onBlur).toHaveBeenCalledTimes(0) }) }) describe('calls onBlur', () => { test('when the outer hex input is blurred', async () => { const onBlur = jest.fn() const { getByLabelText } = renderWithTheme( ) const outerHexInput = getByLabelText('Color') fireEvent.focus(outerHexInput) fireEvent.blur(outerHexInput) await animationRender() expect(onBlur).toHaveBeenCalledTimes(1) }) test('when another element is focused', async () => { const onBlur = jest.fn() const { getByLabelText, getByRole } = renderWithTheme( <> ) const trigger = getByLabelText('Click to open the color picker') userEvent.click(trigger) const dialog = getByRole('dialog') userEvent.click(getByLabelText('sup')) await animationRender() expect(onBlur).toHaveBeenCalledTimes(1) // Also closes the dialog if it's open. expect(dialog).not.toBeInTheDocument() }) }) describe('can set color', () => { test('using the outer hex input', () => { let value = null const onChange = (e: any) => { value = e.target.value } const { getByLabelText } = renderWithTheme( ) const outerHexInput = getByLabelText('Color') as HTMLInputElement userEvent.clear(outerHexInput) userEvent.type(outerHexInput, 'FF0000') fireEvent.blur(outerHexInput) expect(value).toBe('#FF0000') const trigger = getByLabelText('Click to open the color picker') userEvent.click(trigger) const innerHexInput = getByLabelText('Hex') as HTMLInputElement expect(innerHexInput.value).toBe('#FF0000') expect((getByLabelText('R') as HTMLInputElement).value).toBe('255') expect((getByLabelText('G') as HTMLInputElement).value).toBe('0') expect((getByLabelText('B') as HTMLInputElement).value).toBe('0') }) test('using the inner hex input', () => { const { getByLabelText } = renderWithTheme( ) const trigger = getByLabelText('Click to open the color picker') userEvent.click(trigger) const outerHexInput = getByLabelText('Color') as HTMLInputElement const innerHexInput = getByLabelText('Hex') as HTMLInputElement userEvent.clear(innerHexInput) userEvent.type(innerHexInput, 'FF0000') fireEvent.blur(innerHexInput) expect(outerHexInput.value).toBe('#000000') expect((getByLabelText('R') as HTMLInputElement).value).toBe('255') expect((getByLabelText('G') as HTMLInputElement).value).toBe('0') expect((getByLabelText('B') as HTMLInputElement).value).toBe('0') }) test('using the rgb inputs', () => { const { getByLabelText } = renderWithTheme( ) const trigger = getByLabelText('Click to open the color picker') userEvent.click(trigger) const outerHexInput = getByLabelText('Color') as HTMLInputElement const innerHexInput = getByLabelText('Hex') as HTMLInputElement const redInput = getByLabelText('R') as HTMLInputElement const greenInput = getByLabelText('G') as HTMLInputElement const blueInput = getByLabelText('B') as HTMLInputElement userEvent.clear(redInput) userEvent.type(redInput, '0') fireEvent.blur(redInput) userEvent.clear(greenInput) userEvent.type(greenInput, '0') fireEvent.blur(greenInput) userEvent.clear(blueInput) userEvent.type(blueInput, '255') fireEvent.blur(blueInput) expect(outerHexInput.value).toBe('#000000') expect(innerHexInput.value).toBe('#0000FF') expect(redInput.value).toBe('0') expect(greenInput.value).toBe('0') expect(blueInput.value).toBe('255') }) }) })