refactor: Extract reusable UI components and add TDD documentation

- Add comprehensive TDD documentation to CLAUDE.md with coverage requirements and examples
- Extract reusable UI components to frontend/src/components/ui/ (Modal, FormInput, Button, Alert, etc.)
- Add shared constants (schedulePresets) and utility hooks (useCrudMutation, useFormValidation)
- Update frontend/CLAUDE.md with component documentation and usage examples
- Refactor CreateTaskModal to use shared components and constants
- Fix test assertions to be more robust and accurate across all test files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-10 15:27:27 -05:00
parent 18c9a69d75
commit 8c52d6a275
48 changed files with 2780 additions and 444 deletions

View File

@@ -221,7 +221,7 @@ describe('BusinessLayout', () => {
it('should render the layout with all main components', () => {
renderLayout();
expect(screen.getByTestId('sidebar')).toBeInTheDocument();
expect(screen.getAllByTestId('sidebar').length).toBeGreaterThan(0);
expect(screen.getByTestId('topbar')).toBeInTheDocument();
expect(screen.getByTestId('outlet')).toBeInTheDocument();
expect(screen.getByTestId('floating-help-button')).toBeInTheDocument();
@@ -247,7 +247,7 @@ describe('BusinessLayout', () => {
it('should render sidebar with business and user info', () => {
renderLayout();
const sidebar = screen.getByTestId('sidebar');
const sidebar = screen.getAllByTestId('sidebar')[0];
expect(sidebar).toBeInTheDocument();
expect(sidebar).toHaveTextContent('Test Business');
expect(sidebar).toHaveTextContent('John Doe');
@@ -256,7 +256,7 @@ describe('BusinessLayout', () => {
it('should render sidebar in expanded state by default on desktop', () => {
renderLayout();
const sidebar = screen.getByTestId('sidebar');
const sidebar = screen.getAllByTestId('sidebar')[0];
expect(sidebar).toHaveTextContent('Expanded');
});
@@ -264,9 +264,9 @@ describe('BusinessLayout', () => {
renderLayout();
// Mobile menu has translate-x-full class when closed
const container = screen.getByTestId('sidebar').closest('div');
const container = screen.getAllByTestId('sidebar')[0].closest('div');
// The visible sidebar on desktop should exist
expect(screen.getByTestId('sidebar')).toBeInTheDocument();
expect(screen.getAllByTestId('sidebar').length).toBeGreaterThan(0);
});
it('should open mobile menu when menu button is clicked', () => {
@@ -333,7 +333,7 @@ describe('BusinessLayout', () => {
renderLayout();
// Desktop sidebar should be visible
expect(screen.getByTestId('sidebar')).toBeInTheDocument();
expect(screen.getAllByTestId('sidebar').length).toBeGreaterThan(0);
});
});
@@ -348,7 +348,7 @@ describe('BusinessLayout', () => {
it('should display user name in Sidebar', () => {
renderLayout();
const sidebar = screen.getByTestId('sidebar');
const sidebar = screen.getAllByTestId('sidebar')[0];
expect(sidebar).toHaveTextContent('John Doe');
});
@@ -362,7 +362,7 @@ describe('BusinessLayout', () => {
renderLayout({ user: staffUser });
expect(screen.getByTestId('sidebar')).toHaveTextContent('Jane Smith');
expect(screen.getAllByTestId('sidebar')[0]).toHaveTextContent('Jane Smith');
expect(screen.getByTestId('topbar')).toHaveTextContent('Jane Smith');
});
});
@@ -631,8 +631,9 @@ describe('BusinessLayout', () => {
it('should have flex layout structure', () => {
const { container } = renderLayout();
const mainDiv = container.firstChild;
expect(mainDiv).toHaveClass('flex', 'h-full');
// Find the flex container that wraps sidebar and main content
const flexContainer = container.querySelector('.flex.h-full');
expect(flexContainer).toBeInTheDocument();
});
it('should have main content area with overflow-auto', () => {
@@ -663,7 +664,7 @@ describe('BusinessLayout', () => {
renderLayout({ user: minimalUser });
expect(screen.getByTestId('sidebar')).toHaveTextContent('Test User');
expect(screen.getAllByTestId('sidebar')[0]).toHaveTextContent('Test User');
expect(screen.getByTestId('topbar')).toHaveTextContent('Test User');
});
@@ -683,7 +684,7 @@ describe('BusinessLayout', () => {
renderLayout({ business: minimalBusiness });
expect(screen.getByTestId('sidebar')).toHaveTextContent('Minimal Business');
expect(screen.getAllByTestId('sidebar')[0]).toHaveTextContent('Minimal Business');
});
it('should handle invalid masquerade stack in localStorage', () => {
@@ -791,7 +792,7 @@ describe('BusinessLayout', () => {
expect(screen.getByTestId('sandbox-banner')).toBeInTheDocument();
expect(screen.getByTestId('trial-banner')).toBeInTheDocument();
expect(screen.getByTestId('onboarding-wizard')).toBeInTheDocument();
expect(screen.getByTestId('sidebar')).toBeInTheDocument();
expect(screen.getAllByTestId('sidebar').length).toBeGreaterThan(0);
expect(screen.getByTestId('topbar')).toBeInTheDocument();
expect(screen.getByTestId('outlet')).toBeInTheDocument();
expect(screen.getByTestId('floating-help-button')).toBeInTheDocument();