A production-ready recipe search application showcasing Test-Driven Development best practices and 100% test coverage.
π Live Demo | π Documentation | π§ͺ Testing
Real-time recipe search with instant results
- π Instant Search - Real-time recipe filtering with optimized performance
- π± Responsive Design - Seamless experience across all devices
- βΏ Accessible - WCAG AA compliant, keyboard navigation support
- π¨ Modern UI - Clean interface with smooth animations
- π§ͺ 100% Test Coverage - Every feature fully tested (unit + integration)
- β‘ Fast - Optimized bundle size and runtime performance
- π Type-Safe - Built with TypeScript in strict mode (zero
any)
Initially created as a technical assessment, I've transformed it into a showcase of professional development practices:
- β Test-Driven Development (tests written first)
- β Clean Architecture (separation of concerns)
- β SOLID Principles (maintainable, scalable code)
- β Performance optimization (debouncing, memoization)
- β Accessibility first (semantic HTML, ARIA)
This project demonstrates how to build production-grade applications with uncompromising quality standards.
- Node.js 16+
- npm or yarn
# Clone the repository
git clone https://github.com/mdavidgm/recipe-finder.git
# Navigate to project directory
cd recipe-finder
# Install dependencies
npm install
# Start development server
npm startOpen http://localhost:3000 to view it in your browser.
This project follows strict TDD methodology. Every single line of code was written after writing a failing test.
npm run test-coverageπ 100% Coverage Breakdown:
- β Statements: 100%
- β Branches: 100%
- β Functions: 100%
- β Lines: 100%
View the full HTML report at: coverage/lcov-report/index.html
# Run all tests (watch mode)
npm test
# Run tests with coverage
npm run test-coverage
# Run tests in CI mode
npm test -- --coverage --watchAll=false- Framework: Jest / React Testing Library
- Approach: Test-Driven Development (Red-Green-Refactor)
- Types: Unit, Integration, and Accessibility tests
- Coverage: 100% (not a goal, but a natural result of TDD)
describe('RecipeSearch', () => {
it('should filter recipes by search term', () => {
render(<RecipeSearch recipes={mockRecipes} />);
const searchInput = screen.getByRole('searchbox');
fireEvent.change(searchInput, { target: { value: 'pasta' } });
expect(screen.getByText('Pasta Carbonara')).toBeInTheDocument();
expect(screen.queryByText('Chicken Curry')).not.toBeInTheDocument();
});
});src/
βββ components/ # React components (atomic design)
β βββ atoms/ # Basic building blocks
β βββ molecules/ # Composite components
β βββ organisms/ # Complex components
βββ hooks/ # Custom React hooks
βββ services/ # Business logic & API calls
βββ utils/ # Helper functions
βββ types/ # TypeScript definitions
βββ __tests__/ # Test files (co-located)
-
Component Architecture
- Atomic Design for consistency
- Single Responsibility Principle
- Fully typed props with TypeScript
-
State Management
- React hooks for local state
- Context for shared state
- No unnecessary dependencies
-
Performance
- Debounced search (300ms)
- Memoized expensive computations
- Lazy loading for images
- Code splitting where applicable
-
Accessibility
- Semantic HTML elements
- ARIA labels and roles
- Keyboard navigation
- Screen reader tested
| Category | Technology |
|---|---|
| Framework | React 18 |
| Language | TypeScript (strict mode) |
| Build Tool | Create React App / Vite |
| Testing | Jest + React Testing Library |
| Styling | CSS Modules / Styled Components |
| Linting | ESLint + Prettier |
| CI/CD | GitHub Actions |
| Deployment | GitHub Pages |
npm start # Start dev server (port 3000)
npm test # Run tests in watch mode
npm run build # Production buildnpm run test-coverage # Generate coverage report
npm run lint # Run ESLint
npm run type-check # TypeScript validationnpm run deploy # Deploy to GitHub PagesBuilding this project reinforced key concepts:
-
TDD is faster in the long run
- Initial investment pays off with fewer bugs
- Refactoring becomes fearless
- Documentation through tests
-
100% coverage is achievable
- Not by forcing coverage, but by good design
- Testable code is better code
- Integration tests catch more bugs than unit tests alone
-
TypeScript strict mode is worth it
- Catches bugs at compile time
- Better IDE support
- Self-documenting code
-
Accessibility shouldn't be an afterthought
- Semantic HTML is easier to test
- ARIA improves UX for everyone
- Keyboard navigation is a feature, not a burden
The app is automatically deployed to GitHub Pages on every push to main.
Live URL: https://mdavidgm.github.io/recipe-finder/
- Minified bundle
- Tree shaking enabled
- Asset compression
- Cache-busting with hashes
While this started as a personal project, I've open-sourced it as a reference for TDD best practices in React.
If you find it useful:
- β Star the repo
- π Report bugs via issues
- π‘ Suggest improvements via discussions
- π Submit PRs for enhancements
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests first (TDD)
- Implement feature
- Ensure 100% coverage (
npm run test-coverage) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Manuel David Garcia Mateos
- π Website: mdavidgm.com
- πΌ LinkedIn: manuel-david-garcia-mateos
- π§ Email: mdavid29021984@gmail.com
- π GitHub: @mdavidgm
- Built as part of my commitment to Test-Driven Development
- Inspired by the philosophy that code quality matters
- Created to demonstrate that 100% coverage is practical, not idealistic
β‘ Built with TDD, TypeScript, and β€οΈ
If this project helped you understand TDD better, consider giving it a β!