From dc3bedeeecc9ccc13edb10d7129e5f9e4d9f864f Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Sun, 19 Apr 2026 08:20:29 +0300 Subject: [PATCH] feat: add Input and Textarea components to shared/ui --- src/shared/ui/Input/index.ts | 1 + src/shared/ui/Input/ui/Input.test.tsx | 72 +++++++++++++++++++++++++++ src/shared/ui/Input/ui/Input.tsx | 57 +++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 src/shared/ui/Input/index.ts create mode 100644 src/shared/ui/Input/ui/Input.test.tsx create mode 100644 src/shared/ui/Input/ui/Input.tsx diff --git a/src/shared/ui/Input/index.ts b/src/shared/ui/Input/index.ts new file mode 100644 index 0000000..a538399 --- /dev/null +++ b/src/shared/ui/Input/index.ts @@ -0,0 +1 @@ +export { Input, Textarea } from './ui/Input' diff --git a/src/shared/ui/Input/ui/Input.test.tsx b/src/shared/ui/Input/ui/Input.test.tsx new file mode 100644 index 0000000..980e906 --- /dev/null +++ b/src/shared/ui/Input/ui/Input.test.tsx @@ -0,0 +1,72 @@ +import { describe, it, expect } from 'vitest' +import { render, screen } from '@testing-library/react' +import { Input, Textarea } from './Input' + +describe('Input', () => { + describe('rendering', () => { + it('renders an input element', () => { + render() + expect(screen.getByRole('textbox')).toBeInTheDocument() + }) + it('renders label when provided', () => { + render() + expect(screen.getByText('Email')).toBeInTheDocument() + }) + it('does not render label when omitted', () => { + const { container } = render() + expect(container.querySelector('label')).toBeNull() + }) + it('renders error message when provided', () => { + render() + expect(screen.getByText('Required')).toBeInTheDocument() + }) + it('does not render error when omitted', () => { + render() + expect(screen.queryByText('Required')).toBeNull() + }) + }) + describe('styling', () => { + it('has brutal-border class', () => { + render() + expect(screen.getByRole('textbox')).toHaveClass('brutal-border') + }) + it('applies custom className', () => { + render() + expect(screen.getByRole('textbox')).toHaveClass('w-full') + }) + }) + describe('forwarded props', () => { + it('passes placeholder to input', () => { + render() + expect(screen.getByPlaceholderText('Enter email')).toBeInTheDocument() + }) + it('passes type to input', () => { + render() + expect(screen.getByRole('textbox')).toHaveAttribute('type', 'email') + }) + }) +}) +describe('Textarea', () => { + describe('rendering', () => { + it('renders a textarea element', () => { + render(