Aplicación de búsqueda de productos construida con Next.js 16, React 19 y TypeScript, siguiendo principios de Clean Architecture.
- Framework: Next.js 16 (App Router + Server Components)
- UI: React 19, Tailwind CSS v4
- Testing: Jest 30, Testing Library
- Component Development: Storybook 10
- Lenguaje: TypeScript 5
- Node.js >= 20
- Yarn
cd frontend
yarn installyarn devNavegar a http://localhost:3000.
# Correr todos los tests
yarn test
# Modo watch (re-ejecuta al guardar)
yarn test:watchyarn storybookNavegar a http://localhost:6006.
yarn build
yarn startsrc/
├── domain/ # Capa de Dominio (la más interna)
│ ├── entities/ # Product, Category
│ └── repositories/ # IProductRepository (interfaz/contrato)
│
├── application/ # Capa de Aplicación
│ └── use-cases/ # SearchProducts, GetCategories, GetProductsByCategory
│
├── infrastructure/ # Capa de Infraestructura
│ ├── mappers/ # toProduct(), toCategory() — transforman datos crudos a entidades
│ └── repositories/ # DummyJSONProductRepository (implementación concreta)
│
├── ui/ # Capa de Presentación
│ ├── components/ # ProductCard, SearchBar, EmptyState, Header, etc.
│ └── icons/ # SearchIcon
│
├── lib/ # Composition Root
│ └── container.ts # Inyección de dependencias (conecta las capas)
│
└── app/ # Next.js App Router (rutas y páginas)
├── page.tsx # Home — lista de productos por defecto
├── search/ # Búsqueda por query string (?s=...)
├── category/[slug]/ # Productos filtrados por categoría
├── error.tsx # Error boundary global
└── loading.tsx # Skeleton loading (Suspense automático)
Se priorizaron los tests unitarios en las capas de Application (Use Cases) e Infrastructure (Mappers), ya que contienen la lógica más testeable y valiosa:
| Capa | Archivo | Qué se testea |
|---|---|---|
| Infrastructure | product.mapper.test.ts |
Mapeo correcto de datos crudos a entidades, redondeo de finalPrice |
| Infrastructure | category.mapper.test.ts |
Mapeo de categorías |
| Application | search-products.test.ts |
Que el Use Case delega correctamente al repositorio con los parámetros esperados |
| Application | get-categories.test.ts |
Que retorna máximo 5 categorías (slice), maneja arrays vacíos y menores a 5 |
| Application | get-products-by-category.test.ts |
Delegación correcta al repositorio |
Los tests de Use Cases usan mocks manuales del repositorio. Se inyecta un objeto que implementa IProductRepository con jest.fn(), lo que permite verificar las llamadas sin hacer requests HTTP reales:
const mockRepository: IProductRepository = {
searchProducts: jest.fn(),
getCategories: jest.fn(),
getProductsByCategory: jest.fn(),
};Se documentaron los componentes principales con Storybook para desarrollo visual aislado:
- ProductCard: Default, HighDiscount, NoDiscount, LongTitle
- EmptyState: Default, NoCategories, MultipleCategories, FewCategories, SingleCategory
| Ruta | Descripción |
|---|---|
/ |
Home — muestra productos por defecto |
/search?s=query |
Resultados de búsqueda. Si no hay resultados, muestra EmptyState con categorías sugeridas |
/category/[slug] |
Productos filtrados por categoría |