import { cleanup, render, screen, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; import 'jest-styled-components'; import { composeStories } from '@storybook/testing-react'; import * as stories from './Input.stories'; import color from '../../styles/colors'; import React from 'react'; import rgbToHex from '../../utils/rgbToHex'; import Input from './Input'; const { EmailInput, NumberInput, PasswordInput, PrefixCopyableHidden, TelInput, DefaultInput, InputConfirmed, InputError, Validation, ValidateNumberRange, ValidateValueLength, } = composeStories(stories); let container: HTMLDivElement; const testValue = ''; const testPlaceholder = ''; const testInputId = 'test-input'; const testLabelId = 'test-label'; const testDivId = 'test-div'; const testEvent = jest.fn(); test("should conditionally render 'empty / filled' className", () => { render(); const div: HTMLDivElement = screen.getByTestId(testDivId); const input: HTMLInputElement = screen.getByTestId(testInputId); expect(div.classList.contains('filled')).toBeFalsy; expect(div.classList.contains('empty')).toBeTruthy; input.focus(); fireEvent.change(input, { target: { value: 'foo' } }); expect(input.value).toBe('foo'); expect(div.classList.contains('filled')).toBeTruthy; expect(div.classList.contains('empty')).toBeFalsy; }); test('onChange event is returned, testEvent => event.target', () => { render( testEvent(e.target)} />); const div: HTMLDivElement = screen.getByTestId(testDivId); const input: HTMLInputElement = screen.getByTestId(testInputId); expect(div.classList.contains('filled')).toBeFalsy; expect(div.classList.contains('empty')).toBeTruthy; input.focus(); fireEvent.change(input, { target: { value: 'foo' } }); expect(input.value).toBe('foo'); expect(testEvent).toHaveBeenCalledWith(input); }); test('onBlur event is returned, testEvent => event.target', () => { render( testEvent(e.target)} />); const div: HTMLDivElement = screen.getByTestId(testDivId); const input: HTMLInputElement = screen.getByTestId(testInputId); expect(div.classList.contains('filled')).toBeFalsy; expect(div.classList.contains('empty')).toBeTruthy; input.focus(); fireEvent.blur(input, { target: { value: 'foo' } }); expect(input.value).toBe('foo'); expect(testEvent).toHaveBeenCalledWith(input); }); describe('Input - Text', () => { const testLabel = DefaultInput?.args?.label; const testName = DefaultInput?.args?.name; beforeEach(() => { container = document.createElement('div'); render( ) => testEvent(event.target) } />, { container: document.body.appendChild(container), }, ); }); afterEach(() => { cleanup(); }); it('renders the component', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); }); it('renders input with the value and placeholder passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.value).toBe(testValue); input && expect(input.placeholder).toBe(testPlaceholder); }); it('renders the correct type of input', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.type).toBe('text'); }); it('renders input with the name passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.name).toBe(testName); }); it('renders input correct colors', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testDivId}"]`, ); const styles = input && getComputedStyle(input); expect(rgbToHex(styles?.outlineColor).toUpperCase()).toBe( color.greyLight, ); }); it('renders label text', () => { const label = container.querySelector(`[data-testid="${testLabelId}"]`); expect(label).not.toBeNull(); expect(label?.textContent).toBe(testLabel); }); }); describe('Input - Text Error', () => { const testLabel = InputError?.args?.label; const testName = InputError?.args?.name; beforeEach(() => { container = document.createElement('div'); render( ) => testEvent(event.target) } />, { container: document.body.appendChild(container), }, ); }); afterEach(() => { cleanup(); }); it('renders the component', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); }); it('renders input with the value and placeholder passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.value).toBe(testValue); input && expect(input.placeholder).toBe(testPlaceholder); }); it('renders the correct type of input', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.type).toBe('text'); }); it('renders input with the name passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.name).toBe(testName); }); it('renders input correct colors', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testDivId}"]`, ); const styles = input && getComputedStyle(input); expect(rgbToHex(styles?.outlineColor).toUpperCase()).toBe(color.red); }); it('renders label text', () => { const label = container.querySelector(`[data-testid="${testLabelId}"]`); expect(label).not.toBeNull(); expect(label?.textContent).toBe(testLabel); }); }); describe('Input - Text Confirmed', () => { const testLabel = InputConfirmed?.args?.label; const testName = InputConfirmed?.args?.name; beforeEach(() => { container = document.createElement('div'); render( ) => testEvent(event.target) } />, { container: document.body.appendChild(container), }, ); }); afterEach(() => { cleanup(); }); it('renders the component', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); }); it('renders input with the value and placeholder passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.value).toBe(testValue); input && expect(input.placeholder).toBe(testPlaceholder); }); it('renders the correct type of input', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.type).toBe('text'); }); it('renders input with the name passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.name).toBe(testName); }); it('renders input correct colors', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testDivId}"]`, ); const styles = input && getComputedStyle(input); expect(rgbToHex(styles?.outlineColor).toUpperCase()).toBe(color.green); }); it('renders label text', () => { const label = container.querySelector(`[data-testid="${testLabelId}"]`); expect(label).not.toBeNull(); expect(label?.textContent).toBe(testLabel); }); }); describe('Input - Number', () => { const testLabel = NumberInput?.args?.label; const testName = NumberInput?.args?.name; const testType = NumberInput?.args?.type; beforeEach(() => { container = document.createElement('div'); render( ) => testEvent(event.target) } />, { container: document.body.appendChild(container), }, ); }); afterEach(() => { cleanup(); }); it('renders the component', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); }); it('renders input with the value and placeholder passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.value).toBe(testValue); input && expect(input.placeholder).toBe(testPlaceholder); }); it('renders the correct type of input', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.type).toBe(testType); }); it('renders input with the name passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.name).toBe(testName); }); it('renders input correct colors', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testDivId}"]`, ); const styles = input && getComputedStyle(input); expect(rgbToHex(styles?.outlineColor).toUpperCase()).toBe( color.greyLight, ); }); it('renders label text', () => { const label = container.querySelector(`[data-testid="${testLabelId}"]`); expect(label).not.toBeNull(); expect(label?.textContent).toBe(testLabel); }); it('number input wont return letters', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input?.focus(); input && fireEvent.change(input, { target: { value: 'foo' } }); input && expect(input.value).toBe(''); }); }); describe('Input - Password', () => { const testLabel = PasswordInput?.args?.label; const testName = PasswordInput?.args?.name; beforeEach(() => { container = document.createElement('div'); render( ) => testEvent(event.target) } />, { container: document.body.appendChild(container), }, ); }); afterEach(() => { cleanup(); }); it('renders the component', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); }); it('renders input with the value and placeholder passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.value).toBe(testValue); input && expect(input.placeholder).toBe(testPlaceholder); }); it('renders the correct type of input', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.type).toBe('password'); }); it('renders input with the name passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.name).toBe(testName); }); it('renders input correct colors', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testDivId}"]`, ); const styles = input && getComputedStyle(input); expect(rgbToHex(styles?.outlineColor).toUpperCase()).toBe( color.greyLight, ); }); it('renders label text', () => { const label = container.querySelector(`[data-testid="${testLabelId}"]`); expect(label).not.toBeNull(); expect(label?.textContent).toBe(testLabel); }); }); describe('Input - Email', () => { const testLabel = EmailInput?.args?.label; const testName = EmailInput?.args?.name; const testType = EmailInput?.args?.type; beforeEach(() => { container = document.createElement('div'); render( ) => testEvent(event.target) } />, { container: document.body.appendChild(container), }, ); }); afterEach(() => { cleanup(); }); it('renders the component', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); }); it('renders input with the value and placeholder passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.value).toBe(testValue); input && expect(input.placeholder).toBe(testPlaceholder); }); it('renders the correct type of input', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.type).toBe(testType); }); it('renders input with the name passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.name).toBe(testName); }); it('renders input correct colors', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testDivId}"]`, ); const styles = input && getComputedStyle(input); expect(rgbToHex(styles?.outlineColor).toUpperCase()).toBe( color.greyLight, ); }); it('renders label text', () => { const label = container.querySelector(`[data-testid="${testLabelId}"]`); expect(label).not.toBeNull(); expect(label?.textContent).toBe(testLabel); }); }); describe('Input - Tel', () => { const testLabel = TelInput?.args?.label; const testName = TelInput?.args?.name; const testType = TelInput?.args?.type; beforeEach(() => { container = document.createElement('div'); render( ) => testEvent(event.target) } />, { container: document.body.appendChild(container), }, ); }); afterEach(() => { cleanup(); }); it('renders the component', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); }); it('renders input with the value and placeholder passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.value).toBe(testValue); input && expect(input.placeholder).toBe(testPlaceholder); }); it('renders the correct type of input', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.type).toBe(testType); }); it('renders input with the name passed', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input && expect(input.name).toBe(testName); }); it('renders input correct colors', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testDivId}"]`, ); const styles = input && getComputedStyle(input); expect(rgbToHex(styles?.outlineColor).toUpperCase()).toBe( color.greyLight, ); }); it('renders label text', () => { const label = container.querySelector(`[data-testid="${testLabelId}"]`); expect(label).not.toBeNull(); expect(label?.textContent).toBe(testLabel); }); }); describe('PrefixCopyableHidden - Text', () => { beforeEach(() => { container = document.createElement('div'); render(, { container: document.body.appendChild(container), }); }); afterEach(() => { cleanup(); }); it('renders the hidden value', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input?.type).toBe('text'); }); }); describe('Validation - Required', () => { beforeEach(() => { container = document.createElement('div'); render(, { container: document.body.appendChild(container), }); }); afterEach(() => { cleanup(); }); it('renders the required attribute', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).toHaveAttribute('required'); }); it('validates a required input', async () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input?.focus(); input && fireEvent.change(input, { target: { value: '' } }); input?.blur(); expect(input?.checkValidity()).toBeFalsy; }); }); describe('Validation - Number Range', () => { beforeEach(() => { container = document.createElement('div'); render(, { container: document.body.appendChild(container), }); }); afterEach(() => { cleanup(); }); it('renders HTML validation attributes', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).toHaveAttribute('min'); expect(input).toHaveAttribute('max'); }); it('validates a the valid input', async () => { const goodValue = Number(ValidateNumberRange?.args?.validation?.numberMax) - 1; const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input?.focus(); input && fireEvent.change(input, { target: { value: `${goodValue}` } }); input?.blur(); expect(input?.checkValidity()).toBeTruthy; }); it('validates a the non valid input', async () => { const badValue = Number(ValidateNumberRange?.args?.validation?.numberMax) + 1; const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input?.focus(); input && fireEvent.change(input, { target: { value: `${badValue}` } }); input?.blur(); expect(input?.checkValidity()).toBeFalsy; }); }); describe('Validation - Character length Range', () => { beforeEach(() => { container = document.createElement('div'); render(, { container: document.body.appendChild(container), }); }); afterEach(() => { cleanup(); }); it('renders HTML validation attributes', () => { const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).toHaveAttribute('maxlength'); expect(input).toHaveAttribute('minlength'); }); it('validates a the valid input', async () => { const goodValue = '123456789'; const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input?.focus(); input && fireEvent.change(input, { target: { value: `${goodValue}` } }); input?.blur(); expect(input?.checkValidity()).toBeTruthy; }); it('validates a the non valid input', async () => { const badValue = '123'; const input: HTMLInputElement | null = container.querySelector( `[data-testid="${testInputId}"]`, ); expect(input).not.toBeNull(); input?.focus(); input && fireEvent.change(input, { target: { value: `${badValue}` } }); input?.blur(); expect(input?.checkValidity()).toBeFalsy; }); });