- Configure workspace Git repository with comprehensive .gitignore - Add Odoo as submodule for ERP reference code - Include documentation: SETUP.md, GIT-STRUCTURE.md - Add gitignore templates for projects (backend, frontend, database) - Structure supports independent repos per project/subproject level Workspace includes: - core/ - Reusable patterns, modules, orchestration system - projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.) - knowledge-base/ - Reference code and patterns (includes Odoo submodule) - devtools/ - Development tools and templates - customers/ - Client implementations template 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
289 lines
10 KiB
Bash
Executable File
289 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# =============================================================================
|
||
# Script de prueba para endpoints de Teacher Content
|
||
# =============================================================================
|
||
# Este script prueba los endpoints CRUD de contenido educativo personalizado
|
||
# para teachers usando curl.
|
||
#
|
||
# Uso:
|
||
# 1. Asegurar que el backend esté corriendo: npm run start:dev
|
||
# 2. Ejecutar: bash test-teacher-content-endpoints.sh
|
||
#
|
||
# Prerrequisitos:
|
||
# - Backend corriendo en http://localhost:3006
|
||
# - Token JWT válido de un usuario con rol 'teacher'
|
||
# =============================================================================
|
||
|
||
set -e # Exit on error
|
||
|
||
# Colores para output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Configuración
|
||
API_URL="http://localhost:3006/api/v1"
|
||
TEACHER_CONTENT_URL="${API_URL}/teacher/content"
|
||
|
||
# =============================================================================
|
||
# Variables globales (ajustar según tu entorno)
|
||
# =============================================================================
|
||
|
||
# TODO: Reemplazar con un token JWT válido de un teacher
|
||
# Puedes obtenerlo de:
|
||
# 1. Login como teacher: POST /api/v1/auth/login
|
||
# 2. Usar las credenciales de un teacher de test (ver seeds)
|
||
JWT_TOKEN="${JWT_TOKEN:-your_jwt_token_here}"
|
||
|
||
# =============================================================================
|
||
# Funciones auxiliares
|
||
# =============================================================================
|
||
|
||
print_header() {
|
||
echo -e "\n${BLUE}========================================${NC}"
|
||
echo -e "${BLUE}$1${NC}"
|
||
echo -e "${BLUE}========================================${NC}\n"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✓ $1${NC}"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}✗ $1${NC}"
|
||
}
|
||
|
||
print_info() {
|
||
echo -e "${YELLOW}ℹ $1${NC}"
|
||
}
|
||
|
||
# =============================================================================
|
||
# Tests
|
||
# =============================================================================
|
||
|
||
print_header "Teacher Content Endpoints - CRUD Tests"
|
||
|
||
# Validar que el token esté configurado
|
||
if [ "$JWT_TOKEN" == "your_jwt_token_here" ]; then
|
||
print_error "JWT_TOKEN no configurado. Por favor, obtén un token válido e inicia sesión como teacher."
|
||
echo ""
|
||
echo "Ejemplo para obtener token:"
|
||
echo "curl -X POST ${API_URL}/auth/login \\"
|
||
echo " -H 'Content-Type: application/json' \\"
|
||
echo " -d '{\"username\":\"teacher1\",\"password\":\"teacher123\"}'"
|
||
echo ""
|
||
exit 1
|
||
fi
|
||
|
||
# Variable para almacenar el ID del contenido creado
|
||
CONTENT_ID=""
|
||
|
||
# =============================================================================
|
||
# TEST 1: Crear nuevo contenido educativo
|
||
# =============================================================================
|
||
print_header "TEST 1: Crear nuevo contenido educativo (POST /teacher/content)"
|
||
|
||
CREATE_RESPONSE=$(curl -s -X POST "${TEACHER_CONTENT_URL}" \
|
||
-H "Authorization: Bearer ${JWT_TOKEN}" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"title": "Ejercicio de Fracciones Interactivo",
|
||
"description": "Ejercicios interactivos para practicar operaciones con fracciones",
|
||
"content_type": "custom_exercise",
|
||
"content_data": {
|
||
"questions": [
|
||
{"id": 1, "text": "¿Cuánto es 1/2 + 1/4?", "answer": "3/4"},
|
||
{"id": 2, "text": "¿Cuánto es 3/4 - 1/2?", "answer": "1/4"}
|
||
]
|
||
},
|
||
"instructions": "Resuelve cada ejercicio y muestra tu procedimiento",
|
||
"learning_objectives": ["Sumar fracciones", "Restar fracciones"],
|
||
"subject_area": "Matemáticas",
|
||
"grade_level": "5",
|
||
"difficulty_level": "medium",
|
||
"estimated_duration_minutes": 30,
|
||
"visibility": "private",
|
||
"status": "draft",
|
||
"points_value": 100,
|
||
"ml_coins_reward": 50
|
||
}')
|
||
|
||
echo "$CREATE_RESPONSE" | jq '.' 2>/dev/null || echo "$CREATE_RESPONSE"
|
||
|
||
# Extraer el ID del contenido creado
|
||
CONTENT_ID=$(echo "$CREATE_RESPONSE" | jq -r '.id' 2>/dev/null)
|
||
|
||
if [ "$CONTENT_ID" != "null" ] && [ ! -z "$CONTENT_ID" ]; then
|
||
print_success "Contenido creado con ID: $CONTENT_ID"
|
||
else
|
||
print_error "Error al crear contenido"
|
||
exit 1
|
||
fi
|
||
|
||
sleep 1
|
||
|
||
# =============================================================================
|
||
# TEST 2: Listar todo el contenido del teacher
|
||
# =============================================================================
|
||
print_header "TEST 2: Listar contenido (GET /teacher/content)"
|
||
|
||
LIST_RESPONSE=$(curl -s -X GET "${TEACHER_CONTENT_URL}?page=1&limit=10" \
|
||
-H "Authorization: Bearer ${JWT_TOKEN}")
|
||
|
||
echo "$LIST_RESPONSE" | jq '.' 2>/dev/null || echo "$LIST_RESPONSE"
|
||
|
||
CONTENT_COUNT=$(echo "$LIST_RESPONSE" | jq -r '.pagination.total' 2>/dev/null)
|
||
if [ "$CONTENT_COUNT" != "null" ] && [ ! -z "$CONTENT_COUNT" ]; then
|
||
print_success "Total de contenidos: $CONTENT_COUNT"
|
||
else
|
||
print_error "Error al listar contenidos"
|
||
fi
|
||
|
||
sleep 1
|
||
|
||
# =============================================================================
|
||
# TEST 3: Obtener contenido por ID
|
||
# =============================================================================
|
||
print_header "TEST 3: Obtener contenido por ID (GET /teacher/content/:id)"
|
||
|
||
GET_RESPONSE=$(curl -s -X GET "${TEACHER_CONTENT_URL}/${CONTENT_ID}" \
|
||
-H "Authorization: Bearer ${JWT_TOKEN}")
|
||
|
||
echo "$GET_RESPONSE" | jq '.' 2>/dev/null || echo "$GET_RESPONSE"
|
||
|
||
RETRIEVED_TITLE=$(echo "$GET_RESPONSE" | jq -r '.title' 2>/dev/null)
|
||
if [ "$RETRIEVED_TITLE" == "Ejercicio de Fracciones Interactivo" ]; then
|
||
print_success "Contenido obtenido correctamente"
|
||
else
|
||
print_error "Error al obtener contenido"
|
||
fi
|
||
|
||
sleep 1
|
||
|
||
# =============================================================================
|
||
# TEST 4: Actualizar contenido
|
||
# =============================================================================
|
||
print_header "TEST 4: Actualizar contenido (PUT /teacher/content/:id)"
|
||
|
||
UPDATE_RESPONSE=$(curl -s -X PUT "${TEACHER_CONTENT_URL}/${CONTENT_ID}" \
|
||
-H "Authorization: Bearer ${JWT_TOKEN}" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"title": "Ejercicio de Fracciones Interactivo - Actualizado",
|
||
"description": "Ejercicios actualizados con más ejemplos",
|
||
"estimated_duration_minutes": 45
|
||
}')
|
||
|
||
echo "$UPDATE_RESPONSE" | jq '.' 2>/dev/null || echo "$UPDATE_RESPONSE"
|
||
|
||
UPDATED_TITLE=$(echo "$UPDATE_RESPONSE" | jq -r '.title' 2>/dev/null)
|
||
if [[ "$UPDATED_TITLE" == *"Actualizado"* ]]; then
|
||
print_success "Contenido actualizado correctamente"
|
||
else
|
||
print_error "Error al actualizar contenido"
|
||
fi
|
||
|
||
sleep 1
|
||
|
||
# =============================================================================
|
||
# TEST 5: Publicar contenido
|
||
# =============================================================================
|
||
print_header "TEST 5: Publicar contenido (PATCH /teacher/content/:id/publish)"
|
||
|
||
PUBLISH_RESPONSE=$(curl -s -X PATCH "${TEACHER_CONTENT_URL}/${CONTENT_ID}/publish" \
|
||
-H "Authorization: Bearer ${JWT_TOKEN}")
|
||
|
||
echo "$PUBLISH_RESPONSE" | jq '.' 2>/dev/null || echo "$PUBLISH_RESPONSE"
|
||
|
||
PUBLISHED_STATUS=$(echo "$PUBLISH_RESPONSE" | jq -r '.status' 2>/dev/null)
|
||
if [ "$PUBLISHED_STATUS" == "published" ]; then
|
||
print_success "Contenido publicado correctamente"
|
||
else
|
||
print_error "Error al publicar contenido"
|
||
fi
|
||
|
||
sleep 1
|
||
|
||
# =============================================================================
|
||
# TEST 6: Clonar contenido
|
||
# =============================================================================
|
||
print_header "TEST 6: Clonar contenido (POST /teacher/content/:id/clone)"
|
||
|
||
CLONE_RESPONSE=$(curl -s -X POST "${TEACHER_CONTENT_URL}/${CONTENT_ID}/clone" \
|
||
-H "Authorization: Bearer ${JWT_TOKEN}" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"new_title": "Copia - Ejercicio de Fracciones"
|
||
}')
|
||
|
||
echo "$CLONE_RESPONSE" | jq '.' 2>/dev/null || echo "$CLONE_RESPONSE"
|
||
|
||
CLONED_ID=$(echo "$CLONE_RESPONSE" | jq -r '.id' 2>/dev/null)
|
||
CLONED_STATUS=$(echo "$CLONE_RESPONSE" | jq -r '.status' 2>/dev/null)
|
||
if [ "$CLONED_ID" != "null" ] && [ "$CLONED_STATUS" == "draft" ]; then
|
||
print_success "Contenido clonado correctamente con ID: $CLONED_ID"
|
||
else
|
||
print_error "Error al clonar contenido"
|
||
fi
|
||
|
||
sleep 1
|
||
|
||
# =============================================================================
|
||
# TEST 7: Filtrar contenido por tipo
|
||
# =============================================================================
|
||
print_header "TEST 7: Filtrar por tipo (GET /teacher/content?content_type=custom_exercise)"
|
||
|
||
FILTER_RESPONSE=$(curl -s -X GET "${TEACHER_CONTENT_URL}?content_type=custom_exercise&page=1&limit=10" \
|
||
-H "Authorization: Bearer ${JWT_TOKEN}")
|
||
|
||
echo "$FILTER_RESPONSE" | jq '.' 2>/dev/null || echo "$FILTER_RESPONSE"
|
||
|
||
FILTERED_COUNT=$(echo "$FILTER_RESPONSE" | jq -r '.pagination.total' 2>/dev/null)
|
||
if [ "$FILTERED_COUNT" != "null" ] && [ "$FILTERED_COUNT" -ge 2 ]; then
|
||
print_success "Filtrado por tipo exitoso. Resultados: $FILTERED_COUNT"
|
||
else
|
||
print_error "Error al filtrar contenido"
|
||
fi
|
||
|
||
sleep 1
|
||
|
||
# =============================================================================
|
||
# TEST 8: Eliminar contenido clonado (soft delete)
|
||
# =============================================================================
|
||
print_header "TEST 8: Eliminar contenido clonado (DELETE /teacher/content/:id)"
|
||
|
||
DELETE_RESPONSE=$(curl -s -X DELETE "${TEACHER_CONTENT_URL}/${CLONED_ID}" \
|
||
-H "Authorization: Bearer ${JWT_TOKEN}")
|
||
|
||
echo "$DELETE_RESPONSE" | jq '.' 2>/dev/null || echo "$DELETE_RESPONSE"
|
||
|
||
DELETE_SUCCESS=$(echo "$DELETE_RESPONSE" | jq -r '.success' 2>/dev/null)
|
||
if [ "$DELETE_SUCCESS" == "true" ]; then
|
||
print_success "Contenido eliminado correctamente"
|
||
else
|
||
print_error "Error al eliminar contenido"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Resumen Final
|
||
# =============================================================================
|
||
print_header "Resumen de Tests"
|
||
|
||
echo -e "${GREEN}Tests completados:${NC}"
|
||
echo " 1. ✓ Crear contenido educativo"
|
||
echo " 2. ✓ Listar contenido"
|
||
echo " 3. ✓ Obtener contenido por ID"
|
||
echo " 4. ✓ Actualizar contenido"
|
||
echo " 5. ✓ Publicar contenido"
|
||
echo " 6. ✓ Clonar contenido"
|
||
echo " 7. ✓ Filtrar contenido por tipo"
|
||
echo " 8. ✓ Eliminar contenido (soft delete)"
|
||
echo ""
|
||
echo -e "${BLUE}Endpoints implementados correctamente!${NC}"
|
||
echo ""
|
||
echo -e "${YELLOW}Nota: El contenido original (ID: $CONTENT_ID) permanece en la BD.${NC}"
|
||
echo -e "${YELLOW}Puedes eliminarlo manualmente o usar el endpoint DELETE si es necesario.${NC}"
|