Files
whatsapp/tests/api_tests.php
T
2026-01-21 08:28:54 -05:00

495 lines
19 KiB
PHP

<?php
/**
* Tests específicos para APIs del sistema WhatsApp Bot
* Fecha: 3 de enero de 2026
*/
class APITestSuite {
private $testResults = [];
public function runAllAPITests() {
echo "<h2>🔥 Tests Exhaustivos de APIs</h2>";
// 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 "<h4>📨 Tests de API send_message.php</h4>";
// 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 "<h4>📢 Tests de API send_broadcast.php</h4>";
$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 "<h4>📝 Tests de APIs de Plantillas</h4>";
// 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 "<h4>👥 Tests de APIs de Usuarios</h4>";
// 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 "<h4>⚙️ Tests de APIs de Configuración</h4>";
// 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 "<h4>📊 Tests de APIs de Analytics</h4>";
// 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 "<div class='alert alert-success'><i class='fas fa-check'></i> <strong>$name:</strong> $result</div>";
$this->testResults[] = ['name' => $name, 'status' => 'passed', 'message' => $result];
} catch (Exception $e) {
echo "<div class='alert alert-danger'><i class='fas fa-times'></i> <strong>$name:</strong> " . $e->getMessage() . "</div>";
$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 "<div class='alert alert-$alertClass mt-4'>";
echo "<h4><i class='fas fa-api'></i> Resumen Tests de APIs</h4>";
echo "<p><strong>Total de tests API:</strong> $total | ";
echo "<strong>Pasaron:</strong> $passed | ";
echo "<strong>Fallaron:</strong> $failed | ";
echo "<strong>Éxito:</strong> " . number_format($successRate, 1) . "%</p>";
echo "</div>";
}
}
// 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();
}
?>