up
This commit is contained in:
@@ -0,0 +1,380 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests para WhatsAppService y BotService
|
||||
* Fecha: 3 de enero de 2026
|
||||
*/
|
||||
|
||||
class ServiceTestSuite {
|
||||
private $whatsappService;
|
||||
private $botService;
|
||||
private $db;
|
||||
|
||||
public function __construct() {
|
||||
$this->db = Database::getInstance();
|
||||
}
|
||||
|
||||
public function runAllServiceTests() {
|
||||
echo "<h2>🔧 Tests Exhaustivos de Servicios</h2>";
|
||||
|
||||
$this->testWhatsAppService();
|
||||
$this->testBotService();
|
||||
$this->testWebhookClass();
|
||||
}
|
||||
|
||||
private function testWhatsAppService() {
|
||||
echo "<h3>📱 Tests WhatsAppService</h3>";
|
||||
|
||||
$this->serviceTest("Inicialización WhatsAppService", function() {
|
||||
$this->whatsappService = new WhatsAppService();
|
||||
|
||||
if (!$this->whatsappService) {
|
||||
throw new Exception("No se pudo crear instancia de WhatsAppService");
|
||||
}
|
||||
|
||||
// Verificar propiedades mediante reflexión
|
||||
$reflection = new ReflectionClass($this->whatsappService);
|
||||
$properties = $reflection->getProperties();
|
||||
|
||||
$requiredProps = ['token', 'phoneNumberId', 'apiUrl', 'db'];
|
||||
foreach ($requiredProps as $prop) {
|
||||
$found = false;
|
||||
foreach ($properties as $property) {
|
||||
if ($property->getName() === $prop) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
throw new Exception("Propiedad requerida '$prop' no encontrada");
|
||||
}
|
||||
}
|
||||
|
||||
return "WhatsAppService inicializado con todas las propiedades";
|
||||
});
|
||||
|
||||
$this->serviceTest("Método formatPhoneNumber", function() {
|
||||
if (!$this->whatsappService) {
|
||||
$this->whatsappService = new WhatsAppService();
|
||||
}
|
||||
|
||||
$reflection = new ReflectionClass($this->whatsappService);
|
||||
$method = $reflection->getMethod('formatPhoneNumber');
|
||||
$method->setAccessible(true);
|
||||
|
||||
// Tests de diferentes formatos
|
||||
$tests = [
|
||||
['input' => '573001234567', 'expected' => '573001234567'],
|
||||
['input' => '+573001234567', 'expected' => '573001234567'],
|
||||
['input' => '57 300 123 4567', 'expected' => '573001234567'],
|
||||
['input' => '+57 (300) 123-4567', 'expected' => '573001234567'],
|
||||
];
|
||||
|
||||
foreach ($tests as $test) {
|
||||
$result = $method->invokeArgs($this->whatsappService, [$test['input']]);
|
||||
if ($result !== $test['expected']) {
|
||||
throw new Exception("Formato incorrecto para '{$test['input']}': esperado '{$test['expected']}', obtenido '$result'");
|
||||
}
|
||||
}
|
||||
|
||||
return "Formateo de números funciona para todos los casos";
|
||||
});
|
||||
|
||||
$this->serviceTest("Validación de estructura de mensaje de texto", function() {
|
||||
if (!$this->whatsappService) {
|
||||
$this->whatsappService = new WhatsAppService();
|
||||
}
|
||||
|
||||
$reflection = new ReflectionClass($this->whatsappService);
|
||||
|
||||
// Verificar que el método sendTextMessage existe
|
||||
if (!$reflection->hasMethod('sendTextMessage')) {
|
||||
throw new Exception("Método sendTextMessage no existe");
|
||||
}
|
||||
|
||||
return "Método sendTextMessage existe y es accesible";
|
||||
});
|
||||
|
||||
$this->serviceTest("Validación de estructura de template message", function() {
|
||||
if (!$this->whatsappService) {
|
||||
$this->whatsappService = new WhatsAppService();
|
||||
}
|
||||
|
||||
$reflection = new ReflectionClass($this->whatsappService);
|
||||
|
||||
// Verificar que el método sendTemplateMessage existe
|
||||
if (!$reflection->hasMethod('sendTemplateMessage')) {
|
||||
throw new Exception("Método sendTemplateMessage no existe");
|
||||
}
|
||||
|
||||
$method = $reflection->getMethod('sendTemplateMessage');
|
||||
$params = $method->getParameters();
|
||||
|
||||
// Verificar parámetros esperados
|
||||
$expectedParams = ['to', 'templateName', 'language', 'parameters'];
|
||||
if (count($params) < 2) {
|
||||
throw new Exception("sendTemplateMessage debe tener al menos 2 parámetros");
|
||||
}
|
||||
|
||||
return "Método sendTemplateMessage tiene estructura correcta";
|
||||
});
|
||||
|
||||
$this->serviceTest("Test método buildMessage", function() {
|
||||
if (!$this->whatsappService) {
|
||||
$this->whatsappService = new WhatsAppService();
|
||||
}
|
||||
|
||||
$reflection = new ReflectionClass($this->whatsappService);
|
||||
|
||||
if ($reflection->hasMethod('buildMessage')) {
|
||||
$method = $reflection->getMethod('buildMessage');
|
||||
$method->setAccessible(true);
|
||||
|
||||
// Test con datos de texto
|
||||
$textData = [
|
||||
'messaging_product' => 'whatsapp',
|
||||
'to' => '573001234567',
|
||||
'type' => 'text',
|
||||
'text' => ['body' => 'Test message']
|
||||
];
|
||||
|
||||
$result = $method->invokeArgs($this->whatsappService, [$textData]);
|
||||
|
||||
if ($result !== 'Test message') {
|
||||
throw new Exception("buildMessage no procesó correctamente mensaje de texto");
|
||||
}
|
||||
|
||||
return "buildMessage funciona correctamente";
|
||||
}
|
||||
|
||||
return "Método buildMessage no existe (puede ser privado o diferente implementación)";
|
||||
});
|
||||
|
||||
$this->serviceTest("Configuración de tokens", function() {
|
||||
if (!defined('WHATSAPP_TOKEN') || empty(WHATSAPP_TOKEN) || WHATSAPP_TOKEN === 'TU_TOKEN_DE_WHATSAPP_AQUI') {
|
||||
throw new Exception("WHATSAPP_TOKEN no está configurado correctamente");
|
||||
}
|
||||
|
||||
if (!defined('WHATSAPP_PHONE_NUMBER_ID') || empty(WHATSAPP_PHONE_NUMBER_ID) || WHATSAPP_PHONE_NUMBER_ID === 'TU_PHONE_ID_AQUI') {
|
||||
throw new Exception("WHATSAPP_PHONE_NUMBER_ID no está configurado correctamente");
|
||||
}
|
||||
|
||||
if (!defined('WHATSAPP_API_URL') || empty(WHATSAPP_API_URL)) {
|
||||
throw new Exception("WHATSAPP_API_URL no está configurado");
|
||||
}
|
||||
|
||||
return "Todos los tokens de WhatsApp están configurados";
|
||||
});
|
||||
}
|
||||
|
||||
private function testBotService() {
|
||||
echo "<h3>🤖 Tests BotService</h3>";
|
||||
|
||||
$this->serviceTest("Inicialización BotService", function() {
|
||||
$this->botService = new BotService();
|
||||
|
||||
if (!$this->botService) {
|
||||
throw new Exception("No se pudo crear instancia de BotService");
|
||||
}
|
||||
|
||||
return "BotService inicializado correctamente";
|
||||
});
|
||||
|
||||
$this->serviceTest("Método processMessage existe", function() {
|
||||
if (!$this->botService) {
|
||||
$this->botService = new BotService();
|
||||
}
|
||||
|
||||
$reflection = new ReflectionClass($this->botService);
|
||||
|
||||
if (!$reflection->hasMethod('processMessage')) {
|
||||
throw new Exception("Método processMessage no existe");
|
||||
}
|
||||
|
||||
$method = $reflection->getMethod('processMessage');
|
||||
$params = $method->getParameters();
|
||||
|
||||
if (count($params) < 1) {
|
||||
throw new Exception("processMessage debe recibir al menos 1 parámetro");
|
||||
}
|
||||
|
||||
return "Método processMessage tiene estructura correcta";
|
||||
});
|
||||
|
||||
$this->serviceTest("Test de respuestas automáticas", function() {
|
||||
// Verificar que hay respuestas automáticas configuradas
|
||||
$responses = $this->db->fetchAll(
|
||||
"SELECT * FROM auto_responses WHERE trigger_type = 'keyword'"
|
||||
);
|
||||
|
||||
if (empty($responses)) {
|
||||
throw new Exception("No hay respuestas automáticas configuradas");
|
||||
}
|
||||
|
||||
// Verificar estructura de respuestas
|
||||
$firstResponse = $responses[0];
|
||||
$requiredFields = ['trigger_value', 'response_text'];
|
||||
|
||||
foreach ($requiredFields as $field) {
|
||||
if (!isset($firstResponse[$field])) {
|
||||
throw new Exception("Campo requerido '$field' faltante en auto_responses");
|
||||
}
|
||||
}
|
||||
|
||||
return "Respuestas automáticas configuradas correctamente: " . count($responses) . " respuestas";
|
||||
});
|
||||
|
||||
$this->serviceTest("Test procesamiento de menús", function() {
|
||||
// Verificar que hay menús configurados
|
||||
$menus = $this->db->fetchAll(
|
||||
"SELECT * FROM menus WHERE is_active = 1"
|
||||
);
|
||||
|
||||
if (empty($menus)) {
|
||||
throw new Exception("No hay menús activos configurados");
|
||||
}
|
||||
|
||||
// Verificar que el menú raíz existe
|
||||
$rootMenu = $this->db->fetch(
|
||||
"SELECT * FROM menus WHERE is_root = 1 AND is_active = 1"
|
||||
);
|
||||
|
||||
if (!$rootMenu) {
|
||||
throw new Exception("No hay menú raíz configurado");
|
||||
}
|
||||
|
||||
// Verificar opciones del menú raíz
|
||||
$options = $this->db->fetchAll(
|
||||
"SELECT * FROM menu_options WHERE menu_id = :id ORDER BY option_number",
|
||||
['id' => $rootMenu['id']]
|
||||
);
|
||||
|
||||
return "Sistema de menús configurado: " . count($menus) . " menús, " . count($options) . " opciones en menú raíz";
|
||||
});
|
||||
|
||||
$this->serviceTest("Test gestión de usuarios", function() {
|
||||
$testPhone = '573168950803';
|
||||
|
||||
// Crear usuario de prueba
|
||||
$userId = $this->db->insert('users', [
|
||||
'phone_number' => $testPhone,
|
||||
'name' => 'Usite',
|
||||
'status' => 'active',
|
||||
'current_step' => 0,
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
if (!$userId) {
|
||||
throw new Exception("No se pudo crear usuario de prueba");
|
||||
}
|
||||
|
||||
// Verificar que se creó correctamente
|
||||
$user = $this->db->fetch(
|
||||
"SELECT * FROM users WHERE id = :id",
|
||||
['id' => $userId]
|
||||
);
|
||||
|
||||
if ($user['phone_number'] !== $testPhone) {
|
||||
throw new Exception("Usuario no se creó correctamente");
|
||||
}
|
||||
|
||||
// Test actualización de estado
|
||||
$updated = $this->db->update('users',
|
||||
['current_step' => 1],
|
||||
'id = :id',
|
||||
['id' => $userId]
|
||||
);
|
||||
|
||||
if (!$updated) {
|
||||
throw new Exception("No se pudo actualizar usuario");
|
||||
}
|
||||
|
||||
// Limpiar
|
||||
$this->db->execute("DELETE FROM users WHERE id = :id", ['id' => $userId]);
|
||||
|
||||
return "Gestión de usuarios funciona correctamente";
|
||||
});
|
||||
}
|
||||
|
||||
private function testWebhookClass() {
|
||||
echo "<h3>🔗 Tests Clase WhatsAppWebhook</h3>";
|
||||
|
||||
$this->serviceTest("Clase WhatsAppWebhook existe", function() {
|
||||
if (!class_exists('WhatsAppWebhook')) {
|
||||
// Intentar cargar el archivo
|
||||
if (file_exists(__DIR__ . '/../api/webhook.php')) {
|
||||
// Cambiar directorio temporalmente
|
||||
$originalDir = getcwd();
|
||||
chdir(__DIR__ . '/..');
|
||||
|
||||
include_once 'api/webhook.php';
|
||||
|
||||
// Restaurar directorio
|
||||
chdir($originalDir);
|
||||
}
|
||||
|
||||
if (!class_exists('WhatsAppWebhook')) {
|
||||
throw new Exception("Clase WhatsAppWebhook no existe");
|
||||
}
|
||||
}
|
||||
|
||||
return "Clase WhatsAppWebhook disponible";
|
||||
});
|
||||
|
||||
$this->serviceTest("Inicialización WhatsAppWebhook", function() {
|
||||
$webhook = new WhatsAppWebhook();
|
||||
|
||||
if (!$webhook) {
|
||||
throw new Exception("No se pudo crear instancia de WhatsAppWebhook");
|
||||
}
|
||||
|
||||
return "WhatsAppWebhook inicializado correctamente";
|
||||
});
|
||||
|
||||
$this->serviceTest("Métodos requeridos en webhook", function() {
|
||||
$webhook = new WhatsAppWebhook();
|
||||
$reflection = new ReflectionClass($webhook);
|
||||
|
||||
$requiredMethods = ['handleRequest'];
|
||||
|
||||
foreach ($requiredMethods as $method) {
|
||||
if (!$reflection->hasMethod($method)) {
|
||||
throw new Exception("Método requerido '$method' no existe en WhatsAppWebhook");
|
||||
}
|
||||
}
|
||||
|
||||
return "Webhook tiene todos los métodos requeridos";
|
||||
});
|
||||
|
||||
$this->serviceTest("Token de verificación webhook", function() {
|
||||
if (!defined('WEBHOOK_VERIFY_TOKEN') || empty(WEBHOOK_VERIFY_TOKEN)) {
|
||||
throw new Exception("WEBHOOK_VERIFY_TOKEN no está definido");
|
||||
}
|
||||
|
||||
if (WEBHOOK_VERIFY_TOKEN === 'mi_token_secreto_123') {
|
||||
return "⚠️ Usando token por defecto - cambiar en producción";
|
||||
}
|
||||
|
||||
return "Token de webhook configurado correctamente";
|
||||
});
|
||||
}
|
||||
|
||||
private function serviceTest($name, $callable) {
|
||||
try {
|
||||
$result = $callable();
|
||||
echo "<div class='alert alert-success'><i class='fas fa-check-circle'></i> <strong>$name:</strong> $result</div>";
|
||||
} catch (Exception $e) {
|
||||
echo "<div class='alert alert-danger'><i class='fas fa-times-circle'></i> <strong>$name:</strong> " . $e->getMessage() . "</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No ejecutar si es incluido por el runner principal
|
||||
if (basename($_SERVER['PHP_SELF']) === 'service_tests.php') {
|
||||
$configPath = __DIR__ . '/../config/config.php';
|
||||
if (file_exists($configPath)) {
|
||||
require_once $configPath;
|
||||
}
|
||||
$suite = new ServiceTestSuite();
|
||||
$suite->runAllServiceTests();
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user