db = Database::getInstance();
}
public function runAllTemplateTests() {
echo "
📝 Tests Exhaustivos de Sistema de Plantillas
";
$this->testTemplateDatabase();
$this->testTemplateAPIs();
$this->testTemplateValidation();
$this->testTemplateIntegration();
$this->testTemplateWorkflow();
// Limpiar plantillas de prueba
$this->cleanup();
}
private function testTemplateDatabase() {
echo "💾 Tests de Base de Datos de Plantillas
";
$this->templateTest("Estructura tabla message_templates", function() {
$columns = $this->db->fetchAll("DESCRIBE message_templates");
$requiredColumns = [
'id', 'name', 'template_name', 'language_code',
'category', 'status', 'created_at'
];
$existingColumns = array_column($columns, 'Field');
foreach ($requiredColumns as $col) {
if (!in_array($col, $existingColumns)) {
throw new Exception("Columna requerida '$col' faltante");
}
}
// Verificar tipos de datos
$statusColumn = array_filter($columns, function($col) {
return $col['Field'] === 'status';
});
$statusColumn = array_values($statusColumn)[0];
if (strpos($statusColumn['Type'], 'enum') === false) {
throw new Exception("Columna status debería ser ENUM");
}
if (strpos($statusColumn['Type'], 'pending') === false ||
strpos($statusColumn['Type'], 'approved') === false ||
strpos($statusColumn['Type'], 'rejected') === false) {
throw new Exception("Estados de plantilla incorrectos en ENUM");
}
return "Estructura de tabla message_templates correcta";
});
$this->templateTest("CRUD básico en message_templates", function() {
$testName = 'Test CRUD Template ' . time();
// CREATE
$id = $this->db->insert('message_templates', [
'name' => $testName,
'template_name' => 'test_crud_' . time(),
'language_code' => 'es',
'category' => 'utility',
'status' => 'pending'
]);
if (!$id) {
throw new Exception("No se pudo insertar plantilla");
}
$this->testTemplateIds[] = $id;
// READ
$template = $this->db->fetch(
"SELECT * FROM message_templates WHERE id = :id",
['id' => $id]
);
if ($template['name'] !== $testName) {
throw new Exception("Datos incorrectos al leer plantilla");
}
// UPDATE
$updated = $this->db->update('message_templates',
['status' => 'approved'],
['id' => $id]
);
if (!$updated) {
throw new Exception("No se pudo actualizar plantilla");
}
// Verificar actualización
$updatedTemplate = $this->db->fetch(
"SELECT status FROM message_templates WHERE id = :id",
['id' => $id]
);
if ($updatedTemplate['status'] !== 'approved') {
throw new Exception("Estado no se actualizó correctamente");
}
// DELETE se hace en cleanup()
return "CRUD completo en message_templates funciona";
});
$this->templateTest("Constrains y validaciones", function() {
// Test unicidad de nombre
$duplicateName = 'Unique Test ' . time();
$id1 = $this->db->insert('message_templates', [
'name' => $duplicateName,
'template_name' => 'unique_test_1',
'language_code' => 'es',
'status' => 'pending'
]);
$this->testTemplateIds[] = $id1;
// Intentar insertar duplicado
try {
$id2 = $this->db->insert('message_templates', [
'name' => $duplicateName,
'template_name' => 'unique_test_2',
'language_code' => 'es',
'status' => 'pending'
]);
if ($id2) {
$this->testTemplateIds[] = $id2;
throw new Exception("Se permitió nombre duplicado");
}
} catch (Exception $e) {
// Error esperado por constraint
if (strpos($e->getMessage(), 'Duplicate') !== false ||
strpos($e->getMessage(), 'UNIQUE') !== false) {
return "Constraint de unicidad funciona correctamente";
}
throw $e;
}
return "Validaciones de base de datos funcionan";
});
}
private function testTemplateAPIs() {
echo "🔌 Tests de APIs de Plantillas
";
// Configurar sesión de admin
$_SESSION['admin_logged_in'] = true;
$_SESSION['last_activity'] = time();
$this->templateTest("API get_templates.php", function() {
ob_start();
include 'api/get_templates.php';
$output = ob_get_clean();
$templates = json_decode($output, true);
if (!is_array($templates)) {
throw new Exception("get_templates debe retornar array JSON");
}
return "API get_templates responde correctamente";
});
$this->templateTest("API save_template.php - plantilla válida", function() {
$testData = [
'name' => 'API Test Template ' . time(),
'template_name' => 'api_test_' . time(),
'language_code' => 'es',
'category' => 'utility'
];
$_POST = $testData;
$GLOBALS['HTTP_RAW_POST_DATA'] = json_encode($testData);
$_SERVER['REQUEST_METHOD'] = 'POST';
ob_start();
try {
include 'api/save_template.php';
$output = ob_get_clean();
$result = json_decode($output, true);
if (!$result['success']) {
throw new Exception("Error creando plantilla: " . ($result['error'] ?? 'Unknown'));
}
// Verificar que se creó en BD
$created = $this->db->fetch(
"SELECT * FROM message_templates WHERE name = :name",
['name' => $testData['name']]
);
if (!$created) {
throw new Exception("Plantilla no se guardó en base de datos");
}
$this->testTemplateIds[] = $created['id'];
return "API save_template crea plantilla correctamente";
} finally {
unset($_POST);
unset($GLOBALS['HTTP_RAW_POST_DATA']);
ob_end_clean();
}
});
$this->templateTest("API save_template.php - validaciones", function() {
$invalidData = [
['name' => '', 'template_name' => 'test', 'error_expected' => 'nombre es requerido'],
['name' => 'Test', 'template_name' => '', 'error_expected' => 'nombre de la plantilla'],
[/* datos vacíos */ 'error_expected' => 'inválidos']
];
foreach ($invalidData as $testCase) {
$_POST = $testCase;
unset($testCase['error_expected']);
$GLOBALS['HTTP_RAW_POST_DATA'] = json_encode($testCase);
$_SERVER['REQUEST_METHOD'] = 'POST';
ob_start();
try {
include 'api/save_template.php';
$output = ob_get_clean();
$result = json_decode($output, true);
if ($result['success']) {
throw new Exception("Debería rechazar datos inválidos");
}
} finally {
unset($_POST);
unset($GLOBALS['HTTP_RAW_POST_DATA']);
}
}
return "API save_template valida datos correctamente";
});
$this->templateTest("API update_template_status.php", function() {
// Crear plantilla para probar
$id = $this->db->insert('message_templates', [
'name' => 'Status Update Test',
'template_name' => 'status_update_test',
'language_code' => 'es',
'status' => 'pending'
]);
$this->testTemplateIds[] = $id;
$updateData = [
'id' => $id,
'status' => 'approved'
];
$_POST = $updateData;
$GLOBALS['HTTP_RAW_POST_DATA'] = json_encode($updateData);
$_SERVER['REQUEST_METHOD'] = 'POST';
ob_start();
try {
include 'api/update_template_status.php';
$output = ob_get_clean();
$result = json_decode($output, true);
if (!$result['success']) {
throw new Exception("Error actualizando estado: " . ($result['error'] ?? 'Unknown'));
}
// Verificar actualización en BD
$updated = $this->db->fetch(
"SELECT status FROM message_templates WHERE id = :id",
['id' => $id]
);
if ($updated['status'] !== 'approved') {
throw new Exception("Estado no se actualizó en base de datos");
}
return "API update_template_status funciona correctamente";
} finally {
unset($_POST);
unset($GLOBALS['HTTP_RAW_POST_DATA']);
}
});
}
private function testTemplateValidation() {
echo "✅ Tests de Validación de Plantillas
";
$this->templateTest("Validación de nombres", function() {
$invalidNames = [
'', // Vacío
str_repeat('a', 200), // Muy largo
'', // XSS
'SELECT * FROM users', // SQL-like
'template with \x00 null byte'
];
foreach ($invalidNames as $name) {
try {
$id = $this->db->insert('message_templates', [
'name' => $name,
'template_name' => 'test_validation_' . time(),
'language_code' => 'es',
'status' => 'pending'
]);
if ($id) {
$this->testTemplateIds[] = $id;
// Verificar que se sanitizó o rechazó apropiadamente
$saved = $this->db->fetch(
"SELECT name FROM message_templates WHERE id = :id",
['id' => $id]
);
if ($saved['name'] === $name && (
strpos($name, '