docs(qa): add manual QA testing report and dev startup script

- Add comprehensive QA report with 11 test cases and screenshots
- Document DEF-001 bug analysis, solutions, and resolution
- Add dev-start.sh script for faster development server startup
- Include recommendations for UX, technical, and quality improvements
This commit is contained in:
Andrés Eduardo García Márquez 2026-01-08 08:41:24 -05:00
parent 12a4c881f5
commit bcfd2ba6f9
2 changed files with 334 additions and 0 deletions

184
docs/DEFECTOS_QA.md Normal file
View File

@ -0,0 +1,184 @@
# Reporte de Pruebas Manuales QA
**Fecha:** 2026-01-08
**Tester:** Claude Code
**Ambiente:** Desarrollo Local (localhost:4200 / localhost:5000)
---
## Resumen Ejecutivo
| Categoría | Total | Pasaron | Fallaron | Corregidos |
|-----------|-------|---------|----------|------------|
| CRUD Estudiantes | 4 | 4 | 0 | 1 |
| Inscripciones | 5 | 5 | 0 | 0 |
| Compañeros | 2 | 2 | 0 | 0 |
| **Total** | **11** | **11** | **0** | **1** |
---
## Capturas de Pantalla
| # | Archivo | Descripción |
|---|---------|-------------|
| 01 | `01-inicio-cargando.png` | Página inicial cargando |
| 02 | `02-formulario-nuevo-estudiante.png` | Formulario de nuevo estudiante |
| 03 | `03-formulario-lleno.png` | Formulario con datos |
| 04 | `04-estudiante-creado.png` | Estudiante creado exitosamente |
| 05 | `05-DEFECTO-editar-estudiante-no-encontrado.png` | **DEFECTO: Error al editar** |
| 06 | `06-pagina-inscripcion.png` | Página de inscripción |
| 07 | `07-inscripcion-exitosa-regla-profesor.png` | Regla de profesor funcionando |
| 08 | `08-maximo-3-materias.png` | Límite de materias visible |
| 09 | `09-creditos-maximos-9-9.png` | 9/9 créditos alcanzados |
| 10 | `10-dos-estudiantes.png` | Lista con dos estudiantes |
| 11 | `11-companeros-de-clase.png` | Vista de compañeros |
| 12 | `12-confirmar-eliminacion.png` | Diálogo de confirmación |
| 13 | `13-estudiante-eliminado.png` | Estudiante eliminado |
| 14 | `14-CORREGIDO-editar-estudiante-funciona.png` | **CORREGIDO: Editar funciona** |
---
## Defectos Encontrados
### DEFECTO #1: Error "Estudiante no encontrado" al editar
**ID:** DEF-001
**Severidad:** Alta
**Prioridad:** P1
**Estado:** RESUELTO
#### Descripcion
Al hacer clic en el boton de editar (icono de lapiz) en la lista de estudiantes, aparece un snackbar con el mensaje "Estudiante no encontrado" en lugar de abrir el formulario de edicion.
#### Pasos para Reproducir
1. Ir a http://localhost:4200/students
2. Crear un nuevo estudiante
3. En la tabla, hacer clic en el boton de editar (icono de lapiz)
4. **Resultado (antes):** Aparecia mensaje "Estudiante no encontrado"
5. **Resultado (despues del fix):** El formulario de edicion abre correctamente
#### Capturas de Pantalla
| Estado | Captura |
|--------|---------|
| Antes | ![Defecto](../.playwright-mcp/05-DEFECTO-editar-estudiante-no-encontrado.png) |
| Despues | ![Corregido](../.playwright-mcp/14-CORREGIDO-editar-estudiante-funciona.png) |
#### Causa Raiz Identificada
Se encontraron **DOS problemas** combinados:
1. **Problema de navegacion:** El boton de editar usaba `<button [routerLink]>` pero en Angular el `routerLink` funciona mejor con elementos `<a>`.
2. **Problema de timing con signals:** El componente `StudentFormComponent` usaba `ngOnInit` para leer el parametro de ruta `id` via `input()` signal, pero el valor no estaba disponible en ese momento del ciclo de vida.
#### Archivos Modificados
- `student-list.component.ts`: Cambio `<button>` por `<a>` para el boton de editar
- `student-form.component.ts`: Cambio `ngOnInit` por `effect()` para reaccionar cuando el input signal este disponible
---
## Analisis de Soluciones - DEFECTO #1
### Soluciones Propuestas
| Solucion | Descripcion | Ventajas | Desventajas |
|----------|-------------|----------|-------------|
| A | Verificar navegacion y parametros de ruta | Simple si el problema es routing | No resuelve si es backend |
| B | Revisar servicio de estudiantes | Identifica problemas en servicios | Requiere debugging profundo |
| C | Agregar logs de diagnostico | Ayuda a identificar donde falla | Es temporal |
| D | Usar modal en lugar de navegacion | Evita problemas de nav, mejor UX | Cambio arquitectonico grande |
### SOLUCION IMPLEMENTADA
Se implemento una **combinacion de A + investigacion profunda** que revelo dos problemas:
#### Fix 1: Cambiar `<button>` por `<a>` en student-list.component.ts
```typescript
// ANTES (no funcionaba)
<button [routerLink]="['/students', student.id, 'edit']">
<mat-icon>edit</mat-icon>
</button>
// DESPUES (funciona)
<a [routerLink]="['/students', student.id, 'edit']">
<mat-icon>edit</mat-icon>
</a>
```
#### Fix 2: Usar `effect()` en lugar de `ngOnInit` en student-form.component.ts
```typescript
// ANTES (no funcionaba - el input signal no estaba listo en ngOnInit)
ngOnInit(): void {
const studentId = this.id();
if (studentId) {
this.loadStudent(parseInt(studentId, 10));
}
}
// DESPUES (funciona - effect reacciona cuando el signal tiene valor)
constructor() {
effect(() => {
const studentId = this.id();
if (studentId && !this.isEditing()) {
this.isEditing.set(true);
this.loadStudent(parseInt(studentId, 10));
}
});
}
```
### Validacion del Fix
- El formulario de edicion carga correctamente con los datos del estudiante
- La actualizacion de datos funciona sin errores
- No aparece mas el snackbar "Estudiante no encontrado"
---
## Funcionalidades Verificadas (OK)
### Crear Estudiante
- Formulario con validación de campos requeridos
- Botón deshabilitado hasta completar campos
- Mensaje de éxito al crear
- Redirección a lista de estudiantes
### Inscripción en Materias
- Lista de 10 materias con 5 profesores
- Regla de negocio: No repetir profesor (FUNCIONA)
- Regla de negocio: Máximo 3 materias (FUNCIONA)
- Indicadores visuales de disponibilidad
- Mensajes claros de restricciones
### Ver Compañeros
- Lista de materias inscritas
- Nombres de compañeros visibles
- Mensaje cuando no hay compañeros
### Eliminar Estudiante
- Diálogo de confirmación
- Mensaje de éxito al eliminar
- Actualización de lista
---
## Recomendaciones
### Mejoras de UX
1. Agregar tooltips a los botones de acción
2. Mostrar spinner durante operaciones async
3. Agregar confirmación antes de cancelar inscripción
### Mejoras Técnicas
1. Implementar caché de estudiantes para evitar consultas repetidas
2. Agregar paginación a la lista de estudiantes
3. Implementar búsqueda/filtro de estudiantes
### Mejoras de Calidad
1. Agregar tests E2E con Playwright
2. Implementar monitoreo de errores (Sentry)
3. Agregar métricas de rendimiento
---
*Reporte generado automáticamente durante pruebas manuales con Playwright MCP*

150
scripts/dev-start.sh Normal file
View File

@ -0,0 +1,150 @@
#!/bin/bash
# Script de inicio rápido para desarrollo
# Combina las mejores estrategias: detección, paralelismo, SQLite
set -e
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
BACKEND_PORT=5000
FRONTEND_PORT=4200
# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Verificar si un puerto está en uso
port_in_use() {
lsof -i :$1 >/dev/null 2>&1
}
# Esperar a que un servicio esté listo
wait_for_service() {
local url=$1
local max_attempts=${2:-30}
local attempt=1
while [ $attempt -le $max_attempts ]; do
if curl -s "$url" >/dev/null 2>&1; then
return 0
fi
sleep 1
((attempt++))
done
return 1
}
# Iniciar Backend con SQLite (desarrollo rápido)
start_backend() {
if port_in_use $BACKEND_PORT; then
log_info "Backend ya corriendo en puerto $BACKEND_PORT"
return 0
fi
log_info "Iniciando Backend (.NET) con SQLite..."
cd "$PROJECT_ROOT/src/backend/Host"
# Usar SQLite para desarrollo (sin necesidad de Docker/SQL Server)
export ConnectionStrings__DefaultConnection="Data Source=$PROJECT_ROOT/data/dev.db"
export ASPNETCORE_ENVIRONMENT=Development
export USE_SQLITE=true
nohup dotnet run --no-build > /tmp/backend.log 2>&1 &
echo $! > /tmp/backend.pid
log_info "Esperando Backend (max 20s)..."
if wait_for_service "http://localhost:$BACKEND_PORT/health" 20; then
log_info "Backend listo!"
return 0
else
log_error "Backend no respondió a tiempo"
return 1
fi
}
# Iniciar Frontend
start_frontend() {
if port_in_use $FRONTEND_PORT; then
log_info "Frontend ya corriendo en puerto $FRONTEND_PORT"
return 0
fi
log_info "Iniciando Frontend (Angular)..."
cd "$PROJECT_ROOT/src/frontend"
nohup npm start > /tmp/frontend.log 2>&1 &
echo $! > /tmp/frontend.pid
log_info "Esperando Frontend (max 30s)..."
if wait_for_service "http://localhost:$FRONTEND_PORT" 30; then
log_info "Frontend listo!"
return 0
else
log_error "Frontend no respondió a tiempo"
return 1
fi
}
# Detener servicios
stop_services() {
log_info "Deteniendo servicios..."
[ -f /tmp/backend.pid ] && kill $(cat /tmp/backend.pid) 2>/dev/null && rm /tmp/backend.pid
[ -f /tmp/frontend.pid ] && kill $(cat /tmp/frontend.pid) 2>/dev/null && rm /tmp/frontend.pid
fuser -k $BACKEND_PORT/tcp 2>/dev/null || true
fuser -k $FRONTEND_PORT/tcp 2>/dev/null || true
log_info "Servicios detenidos"
}
# Main
case "${1:-start}" in
start)
log_info "=== Inicio Rápido de Desarrollo ==="
# Crear directorio de datos si no existe
mkdir -p "$PROJECT_ROOT/data"
# Iniciar en paralelo
start_backend &
BACKEND_PID=$!
start_frontend &
FRONTEND_PID=$!
# Esperar ambos
wait $BACKEND_PID
BACKEND_STATUS=$?
wait $FRONTEND_PID
FRONTEND_STATUS=$?
if [ $BACKEND_STATUS -eq 0 ] && [ $FRONTEND_STATUS -eq 0 ]; then
log_info "=== Todos los servicios listos ==="
log_info "Backend: http://localhost:$BACKEND_PORT/graphql"
log_info "Frontend: http://localhost:$FRONTEND_PORT"
else
log_error "Algunos servicios fallaron"
exit 1
fi
;;
stop)
stop_services
;;
restart)
stop_services
sleep 2
$0 start
;;
status)
echo "Backend: $(port_in_use $BACKEND_PORT && echo 'Running' || echo 'Stopped')"
echo "Frontend: $(port_in_use $FRONTEND_PORT && echo 'Running' || echo 'Stopped')"
;;
*)
echo "Uso: $0 {start|stop|restart|status}"
exit 1
;;
esac