馃敟 Tests Exhaustivos de APIs";
// Configurar sesi贸n de test
$this->setupTestSession();
// Tests de mensajer铆a
$this->testSendMessageAPI();
$this->testBroadcastAPI();
// Tests de plantillas
$this->testTemplateAPIs();
// Tests de usuarios
$this->testUserAPIs();
// Tests de configuraci贸n
$this->testConfigurationAPIs();
// Tests de analytics
$this->testAnalyticsAPIs();
$this->showAPITestSummary();
}
private function setupTestSession() {
$_SESSION['admin_logged_in'] = true;
$_SESSION['last_activity'] = time();
$_SESSION['login_ip'] = '127.0.0.1';
}
private function testSendMessageAPI() {
echo "
馃摠 Tests de API send_message.php
";
// Test 1: Verificar que el archivo existe
$this->apiTest("Verificar archivo send_message existe", function() {
if (!file_exists(__DIR__ . '/../api/send_message.php')) {
throw new Exception("Archivo send_message.php no existe");
}
return "Archivo send_message.php existe";
});
// Test 2: Verificar contenido b谩sico del archivo
$this->apiTest("Verificar estructura de send_message", function() {
$content = file_get_contents(__DIR__ . '/../api/send_message.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("API no incluye verificaci贸n de autenticaci贸n");
}
if (strpos($content, 'Content-Type: application/json') === false) {
throw new Exception("API no establece Content-Type JSON");
}
return "Estructura de send_message correcta";
});
// Test 3: Verificar que usa validaciones
$this->apiTest("Verificar validaciones en send_message", function() {
$content = file_get_contents(__DIR__ . '/../api/send_message.php');
$validations = [
'recipient' => strpos($content, 'recipient') !== false,
'type' => strpos($content, 'type') !== false,
'message' => strpos($content, 'message') !== false
];
foreach ($validations as $field => $found) {
if (!$found) {
throw new Exception("Campo '$field' no est谩 siendo validado");
}
}
return "Validaciones b谩sicas presentes";
});
// Test 4: Verificar integraci贸n con WhatsApp
$this->apiTest("Verificar integraci贸n WhatsApp", function() {
$content = file_get_contents(__DIR__ . '/../api/send_message.php');
if (strpos($content, 'WhatsAppService') === false &&
strpos($content, 'sendMessage') === false) {
throw new Exception("No integra con servicio de WhatsApp");
}
return "Integraci贸n WhatsApp presente";
});
}
private function testBroadcastAPI() {
echo "馃摙 Tests de API send_broadcast.php
";
$this->apiTest("Verificar archivo send_broadcast existe", function() {
if (!file_exists(__DIR__ . '/../api/send_broadcast.php')) {
throw new Exception("Archivo send_broadcast.php no existe");
}
return "Archivo de broadcast existe";
});
// Test de contenido del archivo
$this->apiTest("Verificar estructura de broadcast", function() {
$content = file_get_contents(__DIR__ . '/../api/send_broadcast.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("API no requiere autenticaci贸n");
}
if (strpos($content, 'recipients') === false && strpos($content, 'users') === false) {
throw new Exception("No maneja lista de destinatarios");
}
return "Estructura de broadcast correcta";
});
}
private function testTemplateAPIs() {
echo "馃摑 Tests de APIs de Plantillas
";
// Test get_templates.php
$this->apiTest("API get_templates existe y estructura", function() {
if (!file_exists(__DIR__ . '/../api/get_templates.php')) {
throw new Exception("get_templates.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/get_templates.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("get_templates no requiere autenticaci贸n");
}
if (strpos($content, 'message_templates') === false) {
throw new Exception("No consulta tabla message_templates");
}
return "API get_templates correcta";
});
// Test save_template.php
$this->apiTest("API save_template existe y validaciones", function() {
if (!file_exists(__DIR__ . '/../api/save_template.php')) {
throw new Exception("save_template.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/save_template.php');
$validations = [
'autenticaci贸n' => strpos($content, 'requireAuthentication()') !== false,
'name' => strpos($content, 'name') !== false,
'template_name' => strpos($content, 'template_name') !== false,
'language_code' => strpos($content, 'language_code') !== false
];
foreach ($validations as $check => $found) {
if (!$found) {
throw new Exception("Validaci贸n '$check' faltante");
}
}
return "API save_template completa";
});
// Test update_template_status.php
$this->apiTest("API update_template_status existe", function() {
if (!file_exists(__DIR__ . '/../api/update_template_status.php')) {
throw new Exception("update_template_status.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/update_template_status.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("update_template_status no requiere autenticaci贸n");
}
if (strpos($content, 'status') === false) {
throw new Exception("No maneja campo status");
}
return "API update_template_status correcta";
});
// Test de integraci贸n con base de datos
$this->apiTest("Verificar tablas de plantillas", function() {
$db = Database::getInstance();
// Verificar que la tabla existe
$result = $db->fetchAll("SHOW TABLES LIKE 'message_templates'");
$tables = $result ? $result : [];
if (empty($tables)) {
throw new Exception("Tabla message_templates no existe");
}
// Verificar estructura de la tabla
$columns = $db->fetchAll("DESCRIBE message_templates");
if (!$columns || empty($columns)) {
throw new Exception("No se puede obtener estructura de message_templates");
}
$requiredColumns = ['id', 'name', 'template_name', 'status', 'created_at'];
$existingColumns = array_map(function($col) {
return $col['Field'];
}, $columns);
foreach ($requiredColumns as $required) {
if (!in_array($required, $existingColumns)) {
throw new Exception("Columna '$required' faltante en message_templates");
}
}
return "Estructura de tabla message_templates correcta";
});
}
private function testUserAPIs() {
echo "馃懃 Tests de APIs de Usuarios
";
// Test get_users.php
$this->apiTest("API get_users existe y estructura", function() {
if (!file_exists(__DIR__ . '/../api/get_users.php')) {
throw new Exception("get_users.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/get_users.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("get_users no requiere autenticaci贸n");
}
if (strpos($content, 'users') === false && strpos($content, 'conversations') === false) {
throw new Exception("No consulta tablas de usuarios");
}
return "API get_users correcta";
});
// Test export_users.php
$this->apiTest("API export_users existe", function() {
if (!file_exists(__DIR__ . '/../api/export_users.php')) {
throw new Exception("export_users.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/export_users.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("export_users no requiere autenticaci贸n");
}
if (strpos($content, 'CSV') === false && strpos($content, 'header') === false) {
throw new Exception("No implementa exportaci贸n CSV");
}
return "API export_users correcta";
});
// Verificar tabla de usuarios
$this->apiTest("Verificar estructura tabla usuarios", function() {
$db = Database::getInstance();
// Verificar tabla conversations (usuarios)
$result = $db->fetchAll("SHOW TABLES LIKE 'conversations'");
if (!$result || empty($result)) {
throw new Exception("Tabla conversations no existe");
}
return "Estructura de usuarios correcta";
});
}
private function testConfigurationAPIs() {
echo "鈿欙笍 Tests de APIs de Configuraci贸n
";
// Test get_system_config.php
$this->apiTest("API get_system_config existe", function() {
if (!file_exists(__DIR__ . '/../api/get_system_config.php')) {
throw new Exception("get_system_config.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/get_system_config.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("get_system_config no requiere autenticaci贸n");
}
return "API get_system_config correcta";
});
// Test save_system_config.php
$this->apiTest("API save_system_config existe", function() {
if (!file_exists(__DIR__ . '/../api/save_system_config.php')) {
throw new Exception("save_system_config.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/save_system_config.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("save_system_config no requiere autenticaci贸n");
}
$fields = ['business_name', 'whatsapp_token', 'phone_number_id'];
foreach ($fields as $field) {
if (strpos($content, $field) === false) {
throw new Exception("Campo '$field' no est谩 siendo procesado");
}
}
return "API save_system_config completa";
});
// Verificar tabla system_config
$this->apiTest("Verificar tabla configuraci贸n", function() {
$db = Database::getInstance();
$result = $db->fetchAll("SHOW TABLES LIKE 'system_config'");
if (!$result || empty($result)) {
throw new Exception("Tabla system_config no existe");
}
return "Tabla de configuraci贸n existe";
});
}
private function testAnalyticsAPIs() {
echo "馃搳 Tests de APIs de Analytics
";
// Test get_stats.php
$this->apiTest("API get_stats existe y estructura", function() {
if (!file_exists(__DIR__ . '/../api/get_stats.php')) {
throw new Exception("get_stats.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/get_stats.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("get_stats no requiere autenticaci贸n");
}
$stats = ['total_users', 'conversations_today', 'active_users', 'total_conversations'];
foreach ($stats as $stat) {
if (strpos($content, $stat) === false) {
throw new Exception("Estad铆stica '$stat' no est谩 implementada");
}
}
return "API get_stats completa";
});
// Test get_chart_data.php
$this->apiTest("API get_chart_data existe", function() {
if (!file_exists(__DIR__ . '/../api/get_chart_data.php')) {
throw new Exception("get_chart_data.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/get_chart_data.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("get_chart_data no requiere autenticaci贸n");
}
return "API get_chart_data correcta";
});
// Test get_recent_conversations.php
$this->apiTest("API get_recent_conversations existe", function() {
if (!file_exists(__DIR__ . '/../api/get_recent_conversations.php')) {
throw new Exception("get_recent_conversations.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/get_recent_conversations.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("get_recent_conversations no requiere autenticaci贸n");
}
if (strpos($content, 'conversations') === false && strpos($content, 'conversations') === false) {
throw new Exception("No consulta mensajes");
}
return "API get_recent_conversations correcta";
});
// Test de integridad de datos
$this->apiTest("Verificar tablas de analytics", function() {
$db = Database::getInstance();
$tables = ['conversations', 'conversations'];
foreach ($tables as $table) {
$result = $db->fetchAll("SHOW TABLES LIKE '$table'");
if (!$result || empty($result)) {
throw new Exception("Tabla '$table' necesaria para analytics no existe");
}
}
return "Tablas para analytics existen";
});
}
private function callAPI($endpoint, $method = 'GET', $data = null) {
// Configurar el entorno para la llamada
$_SERVER['REQUEST_METHOD'] = $method;
if ($method === 'POST' && $data) {
$_POST = $data;
// Simular php://input para APIs que lo usan
$GLOBALS['HTTP_RAW_POST_DATA'] = json_encode($data);
}
ob_start();
try {
// Cambiar al directorio padre temporalmente para que las rutas relativas funcionen
$originalDir = getcwd();
chdir(__DIR__ . '/..');
include "api/$endpoint";
// Restaurar directorio original
chdir($originalDir);
$output = ob_get_clean();
// Intentar decodificar como JSON
$decoded = json_decode($output, true);
if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) {
// Si no es JSON v谩lido, retornar el output raw
return ['raw_output' => $output];
}
return $decoded;
} catch (Exception $e) {
ob_end_clean();
// Restaurar directorio en caso de excepci贸n
if (isset($originalDir)) {
chdir($originalDir);
}
throw $e;
} finally {
// Restaurar directorio y limpiar variables globales
if (isset($originalDir)) {
chdir($originalDir);
}
unset($_POST);
unset($GLOBALS['HTTP_RAW_POST_DATA']);
}
}
private function apiTest($name, $callable) {
try {
$result = $callable();
echo " $name: $result
";
$this->testResults[] = ['name' => $name, 'status' => 'passed', 'message' => $result];
} catch (Exception $e) {
echo " $name: " . $e->getMessage() . "
";
$this->testResults[] = ['name' => $name, 'status' => 'failed', 'message' => $e->getMessage()];
}
}
private function showAPITestSummary() {
$total = count($this->testResults);
$passed = count(array_filter($this->testResults, function($r) { return $r['status'] === 'passed'; }));
$failed = $total - $passed;
$successRate = $total > 0 ? ($passed / $total) * 100 : 0;
$alertClass = $successRate === 100.0 ? 'success' : ($successRate >= 80 ? 'warning' : 'danger');
echo "";
echo "
Resumen Tests de APIs
";
echo "
Total de tests API: $total | ";
echo "Pasaron: $passed | ";
echo "Fallaron: $failed | ";
echo "脡xito: " . number_format($successRate, 1) . "%
";
echo "
";
}
}
// No ejecutar si es incluido por el runner principal
if (basename($_SERVER['PHP_SELF']) === 'api_tests.php') {
$configPath = __DIR__ . '/../config/config.php';
if (file_exists($configPath)) {
require_once $configPath;
}
$suite = new APITestSuite();
$suite->runAllAPITests();
}
?>