jilo-web/tests/Unit/Classes/LogTest.php

262 lines
8.8 KiB
PHP

<?php
require_once dirname(__DIR__, 3) . '/app/classes/database.php';
use PHPUnit\Framework\TestCase;
/**
* TestLogger class for testing log functionality
* This is a simplified implementation that mimics the plugin's Log class
* but with a different name to avoid conflicts
*/
class TestLogger {
private $db;
public function __construct($database) {
$this->db = $database->getConnection();
}
public function insertLog($userId, $message, $scope = 'user') {
try {
$sql = 'INSERT INTO log
(user_id, scope, message)
VALUES
(:user_id, :scope, :message)';
$query = $this->db->prepare($sql);
$query->execute([
':user_id' => $userId,
':scope' => $scope,
':message' => $message,
]);
return true;
} catch (Exception $e) {
return $e->getMessage();
}
}
public function readLog($userId, $scope, $offset = 0, $items_per_page = '', $filters = []) {
$params = [];
$where_clauses = [];
// Base query with user join
$base_sql = 'SELECT l.*, u.username
FROM log l
LEFT JOIN user u ON l.user_id = u.id';
// Add scope condition
if ($scope === 'user') {
$where_clauses[] = 'l.user_id = :user_id';
$params[':user_id'] = $userId;
}
// Add time range filters if specified
if (!empty($filters['from_time'])) {
$where_clauses[] = 'l.time >= :from_time';
$params[':from_time'] = $filters['from_time'] . ' 00:00:00';
}
if (!empty($filters['until_time'])) {
$where_clauses[] = 'l.time <= :until_time';
$params[':until_time'] = $filters['until_time'] . ' 23:59:59';
}
// Add message search if specified
if (!empty($filters['message'])) {
$where_clauses[] = 'l.message LIKE :message';
$params[':message'] = '%' . $filters['message'] . '%';
}
// Add user ID search if specified
if (!empty($filters['id'])) {
$where_clauses[] = 'l.user_id = :search_user_id';
$params[':search_user_id'] = $filters['id'];
}
// Combine WHERE clauses
$sql = $base_sql;
if (!empty($where_clauses)) {
$sql .= ' WHERE ' . implode(' AND ', $where_clauses);
}
// Add ordering
$sql .= ' ORDER BY l.time DESC';
// Add pagination
if ($items_per_page) {
$items_per_page = (int)$items_per_page;
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
}
$query = $this->db->prepare($sql);
$query->execute($params);
return $query->fetchAll(PDO::FETCH_ASSOC);
}
}
class LogTest extends TestCase
{
private $db;
private $log;
private $testUserId;
protected function setUp(): void
{
parent::setUp();
// Prepare DB for Github CI
$host = defined('CI_DB_HOST') ? CI_DB_HOST : '127.0.0.1';
$password = defined('CI_DB_PASSWORD') ? CI_DB_PASSWORD : '';
// Set up test database
$this->db = new Database([
'type' => 'mariadb',
'host' => $host,
'port' => '3306',
'dbname' => 'jilo_test',
'user' => 'test_jilo',
'password' => $password
]);
$connection = $this->db->getConnection();
// Ensure fresh log table schema (drop old schema if present)
$connection->exec("DROP TABLE IF EXISTS log");
// Use centralized schema setup
setupTestDatabaseSchema($connection);
// Load logs plugin migration to create log table
$logMigrationPath = __DIR__ . '/../../../plugins/logs/migrations/create_log_table.sql';
if (file_exists($logMigrationPath)) {
$sql = file_get_contents($logMigrationPath);
$statements = array_filter(array_map('trim', explode(';', $sql)));
foreach ($statements as $statement) {
if (!empty($statement)) {
$connection->exec($statement);
}
}
}
// Clean up any existing test data
$connection->exec("DELETE FROM log WHERE user_id >= 1000");
$connection->exec("DELETE FROM user WHERE id >= 1000");
// Create test users
$timestamp = time();
$connection->exec("
INSERT INTO user (id, username, password)
VALUES
(1000, 'testuser_log_{$timestamp}', 'password123'),
(1001, 'testuser2_log_{$timestamp}', 'password123')
");
// Store test user ID for later use
$this->testUserId = 1000;
// Create a TestLogger instance that will be used by the app's Log wrapper
$this->log = new TestLogger($this->db);
}
protected function tearDown(): void
{
// Clean up test data
$this->db->getConnection()->exec("DELETE FROM log WHERE user_id >= 1000");
$this->db->getConnection()->exec("DELETE FROM user WHERE id >= 1000");
parent::tearDown();
}
public function testInsertLog()
{
$result = $this->log->insertLog($this->testUserId, 'Test message', 'user');
$this->assertTrue($result);
// Verify the log was inserted
$stmt = $this->db->getConnection()->query("SELECT * FROM log WHERE user_id = {$this->testUserId} LIMIT 1");
$log = $stmt->fetch(PDO::FETCH_ASSOC);
$this->assertEquals('Test message', $log['message']);
$this->assertEquals('user', $log['scope']);
}
public function testReadLog()
{
// Insert some test logs with a delay to ensure order
$this->log->insertLog($this->testUserId, 'Test message 1', 'user');
sleep(1); // Ensure different timestamps
$this->log->insertLog($this->testUserId, 'Test message 2', 'user');
$logs = $this->log->readLog($this->testUserId, 'user');
$this->assertCount(2, $logs);
$this->assertEquals('Test message 2', $logs[0]['message']); // Most recent first (by time)
}
public function testReadLogWithTimeFilter()
{
// First message from yesterday
$yesterday = date('Y-m-d', strtotime('-1 day'));
$stmt = $this->db->getConnection()->prepare("
INSERT INTO log (user_id, scope, message, time)
VALUES (?, ?, ?, ?)
");
$stmt->execute([$this->testUserId, 'user', 'Test message 1', $yesterday . ' 12:00:00']);
// Second message from today
$today = date('Y-m-d');
$stmt->execute([$this->testUserId, 'user', 'Test message 2', $today . ' 12:00:00']);
// Should get only today's messages
$logs = $this->log->readLog($this->testUserId, 'user', 0, '', [
'from_time' => $today
]);
$this->assertCount(1, $logs);
$this->assertEquals('Test message 2', $logs[0]['message']); // Most recent first
}
public function testReadLogWithPagination()
{
// Insert multiple test logs with delays to ensure order
for ($i = 1; $i <= 5; $i++) {
$this->log->insertLog($this->testUserId, "Test message $i", 'user');
sleep(1); // Ensure different timestamps
}
// Get all logs to verify total
$allLogs = $this->log->readLog($this->testUserId, 'user');
$this->assertCount(5, $allLogs);
// Get first page (offset 0, limit 2)
$logs = $this->log->readLog($this->testUserId, 'user', 0, 2);
$this->assertCount(2, $logs);
$this->assertEquals('Test message 5', $logs[0]['message']); // Most recent first
$this->assertEquals('Test message 4', $logs[1]['message']);
// Get second page (offset 2, limit 2)
$logs = $this->log->readLog($this->testUserId, 'user', 2, 2);
$this->assertCount(2, $logs);
$this->assertEquals('Test message 3', $logs[0]['message']);
$this->assertEquals('Test message 2', $logs[1]['message']);
}
public function testReadLogWithMessageFilter()
{
// Insert test logs with different messages and delays
$this->log->insertLog($this->testUserId, 'Test message ABC', 'user');
sleep(1); // Ensure different timestamps
$this->log->insertLog($this->testUserId, 'Test message XYZ', 'user');
sleep(1); // Ensure different timestamps
$this->log->insertLog($this->testUserId, 'Different message', 'user');
// Filter by message content
$logs = $this->log->readLog($this->testUserId, 'user', 0, '', ['message' => 'Test message']);
$this->assertCount(2, $logs);
// Verify filtered results
foreach ($logs as $log) {
$this->assertStringContainsString('Test message', $log['message']);
}
}
}