Adds tests for middleware

main
Yasen Pramatarov 2025-02-19 15:31:01 +02:00
parent c2f63f6121
commit 5327bde032
17 changed files with 587 additions and 127 deletions

View File

@ -2,7 +2,7 @@
/**
* Security Helper
*
*
* Security helper, to be used with all the forms in the app.
* Implements singleton pattern for consistent state management.
*/

View File

@ -2,7 +2,7 @@
require_once __DIR__ . '/../helpers/security.php';
function verifyCsrfToken() {
function applyCsrfMiddleware() {
$security = SecurityHelper::getInstance();
// Skip CSRF check for GET requests

View File

@ -11,6 +11,7 @@ require_once __DIR__ . '/../classes/ratelimiter.php';
* @return bool True if request is allowed, false if rate limited
*/
function checkRateLimit($database, $endpoint, $userId = null) {
$isTest = defined('PHPUNIT_RUNNING');
$rateLimiter = new RateLimiter($database['db']);
$ipAddress = $_SERVER['REMOTE_ADDR'];
@ -19,28 +20,34 @@ function checkRateLimit($database, $endpoint, $userId = null) {
// Get remaining requests for error message
$remaining = $rateLimiter->getRemainingPageRequests($ipAddress, $endpoint, $userId);
// Set rate limit headers
header('X-RateLimit-Remaining: ' . $remaining);
header('X-RateLimit-Reset: ' . (time() + 60)); // Reset in 1 minute
if (!$isTest) {
// Set rate limit headers
header('X-RateLimit-Remaining: ' . $remaining);
header('X-RateLimit-Reset: ' . (time() + 60)); // Reset in 1 minute
// Return 429 Too Many Requests
http_response_code(429);
// Return 429 Too Many Requests
http_response_code(429);
// If AJAX request, return JSON
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
header('Content-Type: application/json');
echo json_encode([
'success' => false,
'message' => 'Too many requests. Please try again in a minute.',
'messageData' => Feedback::getMessageData('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true)
]);
} else {
// For regular requests, set flash message and redirect
Feedback::flash('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true);
header('Location: ' . htmlspecialchars($app_root));
// If AJAX request, return JSON
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
header('Content-Type: application/json');
echo json_encode([
'success' => false,
'message' => 'Too many requests. Please try again in a minute.',
'messageData' => Feedback::getMessageData('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true)
]);
} else {
// For regular requests, set flash message and redirect
Feedback::flash('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true);
header('Location: ' . htmlspecialchars($app_root));
}
exit;
}
exit;
// In test mode, just set the flash message
Feedback::flash('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true);
return false;
}
// Record this request

View File

@ -2,7 +2,7 @@
/**
* Security Headers Middleware
*
*
* Sets various security headers to protect against common web vulnerabilities:
* - HSTS: Force HTTPS connections
* - CSP: Content Security Policy to prevent XSS and other injection attacks
@ -14,7 +14,7 @@
function applySecurityHeaders($testMode = false) {
$headers = [];
// Get current page
$current_page = $_GET['page'] ?? 'dashboard';

View File

@ -2,48 +2,91 @@
/**
* Session Middleware
*
*
* Validates session status and handles session timeout.
* This middleware should be included in all protected pages.
*/
// Start session if not already started
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
function applySessionMiddleware($config, $app_root) {
$isTest = defined('PHPUNIT_RUNNING');
// Check if user is logged in
if (!isset($_SESSION['USER_ID'])) {
header('Location: ' . $app_root . '?page=login');
exit();
}
// Access $_SESSION directly in test mode
if (!$isTest) {
// Start session if not already started
if (session_status() !== PHP_SESSION_ACTIVE && !headers_sent()) {
session_start([
'cookie_httponly' => 1,
'cookie_secure' => 1,
'cookie_samesite' => 'Strict',
'gc_maxlifetime' => 1440 // 24 minutes
]);
}
}
// Check session timeout
$session_timeout = isset($_SESSION['REMEMBER_ME']) ? (30 * 24 * 60 * 60) : 1440; // 30 days or 24 minutes
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $session_timeout)) {
// Session has expired
session_unset();
session_destroy();
setcookie('username', '', [
'expires' => time() - 3600,
'path' => $config['folder'],
'domain' => $config['domain'],
'secure' => isset($_SERVER['HTTPS']),
'httponly' => true,
'samesite' => 'Strict'
]);
header('Location: ' . $app_root . '?page=login&timeout=1');
exit();
}
// Check if user is logged in
if (!isset($_SESSION['USER_ID'])) {
if (!$isTest) {
header('Location: ' . $app_root . '?page=login');
exit();
}
return false;
}
// Update last activity time
$_SESSION['LAST_ACTIVITY'] = time();
// Check session timeout
$session_timeout = isset($_SESSION['REMEMBER_ME']) ? (30 * 24 * 60 * 60) : 1440; // 30 days or 24 minutes
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $session_timeout)) {
// Session has expired
$oldSessionData = $_SESSION;
$_SESSION = array();
// Regenerate session ID periodically (every 30 minutes)
if (!isset($_SESSION['CREATED'])) {
$_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
// Regenerate session ID and update creation time
session_regenerate_id(true);
$_SESSION['CREATED'] = time();
if (!$isTest && session_status() === PHP_SESSION_ACTIVE) {
session_unset();
session_destroy();
// Start a new session to prevent errors
if (!headers_sent()) {
session_start([
'cookie_httponly' => 1,
'cookie_secure' => 1,
'cookie_samesite' => 'Strict',
'gc_maxlifetime' => 1440
]);
}
}
if (!$isTest && !headers_sent()) {
setcookie('username', '', [
'expires' => time() - 3600,
'path' => $config['folder'],
'domain' => $config['domain'],
'secure' => isset($_SERVER['HTTPS']),
'httponly' => true,
'samesite' => 'Strict'
]);
}
if (!$isTest) {
header('Location: ' . $app_root . '?page=login&timeout=1');
exit();
}
return false;
}
// Update last activity time
$_SESSION['LAST_ACTIVITY'] = time();
// Regenerate session ID periodically (every 30 minutes)
if (!isset($_SESSION['CREATED'])) {
$_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
// Regenerate session ID and update creation time
if (!$isTest && !headers_sent() && session_status() === PHP_SESSION_ACTIVE) {
$oldData = $_SESSION;
session_regenerate_id(true);
$_SESSION = $oldData;
$_SESSION['CREATED'] = time();
}
}
return true;
}

View File

@ -0,0 +1,182 @@
<?php
require_once dirname(__DIR__, 4) . '/app/classes/database.php';
require_once dirname(__DIR__, 4) . '/app/classes/ratelimiter.php';
require_once dirname(__DIR__, 4) . '/app/includes/rate_limit_middleware.php';
use PHPUnit\Framework\TestCase;
class RateLimitMiddlewareTest extends TestCase
{
private $db;
private $rateLimiter;
protected function setUp(): void
{
parent::setUp();
// Set up test database
$this->db = new Database([
'type' => 'sqlite',
'dbFile' => ':memory:'
]);
// Create rate limiter table
$this->db->getConnection()->exec("CREATE TABLE pages_rate_limits (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip_address TEXT NOT NULL,
endpoint TEXT NOT NULL,
request_time DATETIME DEFAULT CURRENT_TIMESTAMP
)");
// Create ip_whitelist table
$this->db->getConnection()->exec("CREATE TABLE ip_whitelist (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip_address TEXT NOT NULL UNIQUE,
is_network BOOLEAN DEFAULT 0 CHECK(is_network IN (0,1)),
description TEXT,
created_at TEXT DEFAULT (DATETIME('now')),
created_by TEXT
)");
// Create ip_blacklist table
$this->db->getConnection()->exec("CREATE TABLE ip_blacklist (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip_address TEXT NOT NULL UNIQUE,
is_network BOOLEAN DEFAULT 0 CHECK(is_network IN (0,1)),
reason TEXT,
expiry_time TEXT NULL,
created_at TEXT DEFAULT (DATETIME('now')),
created_by TEXT
)");
$this->rateLimiter = new RateLimiter($this->db);
// Mock $_SERVER variables
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = '/login';
$_SERVER['REQUEST_METHOD'] = 'POST';
// Define testing constant
if (!defined('TESTING')) {
define('TESTING', true);
}
}
protected function tearDown(): void
{
// Clean up rate limit records
$this->db->getConnection()->exec('DELETE FROM pages_rate_limits');
parent::tearDown();
}
public function testRateLimitMiddleware()
{
// Test multiple requests
for ($i = 1; $i <= 5; $i++) {
$result = checkRateLimit(['db' => $this->db], '/login');
if ($i <= 5) {
// First 5 requests should pass
$this->assertTrue($result);
} else {
// 6th and subsequent requests should be blocked
$this->assertFalse($result);
}
}
}
public function testRateLimitBypass()
{
// Test AJAX request bypass
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
$result = checkRateLimit(['db' => $this->db], '/login');
$this->assertTrue($result);
}
public function testRateLimitReset()
{
// Use up the rate limit
for ($i = 0; $i < 5; $i++) {
checkRateLimit(['db' => $this->db], '/login');
}
// Wait for rate limit to reset (use a short window for testing)
sleep(2);
// Should be able to make request again
$result = checkRateLimit(['db' => $this->db], '/login');
$this->assertTrue($result);
}
public function testDifferentEndpoints()
{
// Use up rate limit for login
for ($i = 0; $i < 5; $i++) {
checkRateLimit(['db' => $this->db], '/login');
}
// Should still be able to access different endpoint
$result = checkRateLimit(['db' => $this->db], '/dashboard');
$this->assertTrue($result);
}
public function testDifferentIpAddresses()
{
// Use up rate limit for first IP
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
for ($i = 0; $i < 5; $i++) {
checkRateLimit(['db' => $this->db], '/login');
}
// Different IP should not be affected
$_SERVER['REMOTE_ADDR'] = '127.0.0.2';
$result = checkRateLimit(['db' => $this->db], '/login');
$this->assertTrue($result);
}
public function testWhitelistedIp()
{
// Add IP to whitelist
$this->db->execute(
'INSERT INTO ip_whitelist (ip_address, description, created_by) VALUES (?, ?, ?)',
['127.0.0.1', 'Test whitelist', 'PHPUnit']
);
// Should be able to make more requests than limit
for ($i = 0; $i < 10; $i++) {
$result = checkRateLimit(['db' => $this->db], '/login');
$this->assertTrue($result);
}
}
public function testBlacklistedIp()
{
// Add IP to blacklist
$this->db->execute(
'INSERT INTO ip_blacklist (ip_address, reason, created_by) VALUES (?, ?, ?)',
['127.0.0.1', 'Test blacklist', 'PHPUnit']
);
// Should be blocked immediately
$result = checkRateLimit(['db' => $this->db], '/login');
$this->assertFalse($result);
}
public function testRateLimitPersistence()
{
// Use up some of the rate limit
for ($i = 0; $i < 2; $i++) {
checkRateLimit(['db' => $this->db], '/login');
}
// Destroy and restart session
//session_destroy();
//session_start();
// Should still count previous requests
$result = checkRateLimit(['db' => $this->db], '/login');
$this->assertTrue($result);
}
}

View File

@ -0,0 +1,110 @@
<?php
require_once dirname(__DIR__, 4) . '/app/includes/session_middleware.php';
use PHPUnit\Framework\TestCase;
class SessionMiddlewareTest extends TestCase
{
protected $config;
protected $app_root;
protected function setUp(): void
{
parent::setUp();
// Mock server variables
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit Test Browser';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['HTTPS'] = 'on';
// Set up test config
$this->config = [
'folder' => '/app',
'domain' => 'localhost'
];
$this->app_root = 'https://localhost/app';
}
protected function tearDown(): void
{
parent::tearDown();
}
public function testSessionStart()
{
$_SESSION = ['USER_ID' => 1];
$result = applySessionMiddleware($this->config, $this->app_root);
$this->assertTrue($result);
$this->assertArrayHasKey('LAST_ACTIVITY', $_SESSION);
$this->assertArrayHasKey('CREATED', $_SESSION);
$this->assertArrayHasKey('USER_ID', $_SESSION);
$this->assertEquals(1, $_SESSION['USER_ID']);
}
public function testSessionTimeout()
{
$_SESSION = [
'USER_ID' => 1,
'LAST_ACTIVITY' => time() - 1500 // 25 minutes ago
];
$result = applySessionMiddleware($this->config, $this->app_root);
$this->assertFalse($result);
$this->assertArrayNotHasKey('USER_ID', $_SESSION, 'Session should be cleared after timeout');
}
public function testSessionRegeneration()
{
$now = time();
$_SESSION = [
'USER_ID' => 1,
'CREATED' => $now - 1900 // 31+ minutes ago
];
$result = applySessionMiddleware($this->config, $this->app_root);
$this->assertTrue($result);
$this->assertEquals(1, $_SESSION['USER_ID']);
$this->assertGreaterThanOrEqual($now - 1900, $_SESSION['CREATED']);
$this->assertLessThanOrEqual($now + 10, $_SESSION['CREATED']);
}
public function testRememberMe()
{
$_SESSION = [
'USER_ID' => 1,
'REMEMBER_ME' => true,
'LAST_ACTIVITY' => time() - 86500 // More than 24 hours ago
];
$result = applySessionMiddleware($this->config, $this->app_root);
$this->assertTrue($result);
$this->assertArrayHasKey('USER_ID', $_SESSION);
}
public function testNoUserSession()
{
$_SESSION = [];
$result = applySessionMiddleware($this->config, $this->app_root);
$this->assertFalse($result);
$this->assertArrayNotHasKey('USER_ID', $_SESSION);
}
public function testSessionHeaders()
{
$_SESSION = [
'USER_ID' => 1,
'LAST_ACTIVITY' => time() - 1500 // 25 minutes ago
];
$result = applySessionMiddleware($this->config, $this->app_root);
$this->assertFalse($result);
$this->assertArrayNotHasKey('USER_ID', $_SESSION, 'Session should be cleared after timeout');
}
}

View File

@ -20,7 +20,7 @@ class SecurityHeadersTest extends TestCase
{
// Apply security headers in test mode
$headers = \applySecurityHeaders(true);
// Check security headers
$this->assertContains('X-Frame-Options: DENY', $headers);
$this->assertContains('X-XSS-Protection: 1; mode=block', $headers);
@ -32,7 +32,7 @@ class SecurityHeadersTest extends TestCase
{
// Apply security headers in test mode
$headers = \applySecurityHeaders(true);
// Get CSP header
$cspHeader = '';
foreach ($headers as $header) {
@ -138,10 +138,10 @@ class SecurityHeadersTest extends TestCase
public function testPermissionsPolicyForMediaEnabledPages()
{
$_SERVER['REQUEST_URI'] = '/media/upload';
// Apply security headers in test mode
$headers = \applySecurityHeaders(true);
// Get Permissions-Policy header
$permissionsHeader = '';
foreach ($headers as $header) {

View File

@ -7,23 +7,23 @@ class TestCase extends PHPUnit\Framework\TestCase
protected function setUp(): void
{
parent::setUp();
// Set up test environment
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit Test Browser';
// Include common app files
require_once dirname(__DIR__, 2) . '/app/includes/config.php';
require_once dirname(__DIR__, 2) . '/app/includes/functions.php';
// Clean up any existing session
if (session_status() === PHP_SESSION_ACTIVE) {
session_destroy();
}
// Reset session data
$_SESSION = [];
// Only start session if headers haven't been sent
if (!headers_sent() && session_status() === PHP_SESSION_NONE) {
session_start();
@ -37,7 +37,7 @@ class TestCase extends PHPUnit\Framework\TestCase
$_SESSION = [];
session_destroy();
}
parent::tearDown();
}

View File

@ -0,0 +1,126 @@
<?php
/**
* Test Session Handler
*
* Provides session handling functionality for PHPUnit tests.
* This class ensures proper session management during testing.
*/
class TestSessionHandler implements SessionHandlerInterface
{
private static $initialized = false;
private $data = [];
/**
* Initialize session settings
*/
public static function init()
{
if (!self::$initialized && !headers_sent()) {
// Clean up any existing session
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-3600, '/');
}
$_SESSION = array();
if (session_status() === PHP_SESSION_ACTIVE) {
session_destroy();
}
// Set session configuration
session_name('jilo');
// Start a new session
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start([
'cookie_httponly' => 1,
'cookie_secure' => 1,
'cookie_samesite' => 'Strict',
'gc_maxlifetime' => 1440 // 24 minutes
]);
}
self::$initialized = true;
}
}
/**
* Start a fresh session
*/
public static function startSession()
{
// Clean up any existing session first
self::cleanupSession();
// Initialize new session
if (session_status() !== PHP_SESSION_ACTIVE && !headers_sent()) {
session_name('jilo');
session_start([
'cookie_httponly' => 1,
'cookie_secure' => 1,
'cookie_samesite' => 'Strict',
'gc_maxlifetime' => 1440
]);
self::$initialized = true;
}
}
/**
* Clean up the current session
*/
public static function cleanupSession()
{
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-3600, '/');
}
$_SESSION = array();
if (session_status() === PHP_SESSION_ACTIVE) {
session_destroy();
}
self::$initialized = false;
}
public function open($path, $name): bool
{
return true;
}
public function close(): bool
{
return true;
}
public function read($id): string|false
{
return $this->data[$id] ?? '';
}
public function write($id, $data): bool
{
$this->data[$id] = $data;
return true;
}
public function destroy($id): bool
{
unset($this->data[$id]);
return true;
}
public function gc($max_lifetime): int|false
{
return 0;
}
}

View File

@ -107,7 +107,7 @@ class AgentTest extends TestCase
'secret_key' => 'test_secret',
'check_period' => 60
];
$this->agent->addAgent($hostId, $data);
// Test getting agent details
@ -127,7 +127,7 @@ class AgentTest extends TestCase
'secret_key' => 'test_secret',
'check_period' => 60
];
$this->agent->addAgent($hostId, $data);
// Get agent ID
@ -167,7 +167,7 @@ class AgentTest extends TestCase
'secret_key' => 'test_secret',
'check_period' => 60
];
$this->agent->addAgent($hostId, $data);
// Get agent ID
@ -197,7 +197,7 @@ class AgentTest extends TestCase
'secret_key' => 'test_secret',
'check_period' => 60
];
$this->agent->addAgent($hostId, $data);
// Get agent ID
@ -210,7 +210,7 @@ class AgentTest extends TestCase
->setConstructorArgs([$this->db])
->onlyMethods(['fetchAgent'])
->getMock();
$mockResponse = json_encode([
'status' => 'ok',
'metrics' => [
@ -226,7 +226,7 @@ class AgentTest extends TestCase
$response = $mockAgent->fetchAgent($agentId);
$this->assertJson($response);
$data = json_decode($response, true);
$this->assertEquals('ok', $data['status']);
}

View File

@ -11,11 +11,11 @@ class DatabaseTest extends TestCase
protected function setUp(): void
{
parent::setUp();
// Set development environment for detailed errors
global $config;
$config['environment'] = 'development';
$this->config = [
'type' => 'sqlite',
'dbFile' => ':memory:'
@ -39,7 +39,7 @@ class DatabaseTest extends TestCase
'user' => 'test',
'password' => 'test'
];
$mariadbConfig = [
'type' => 'mariadb',
'host' => 'invalid-host',
@ -48,11 +48,11 @@ class DatabaseTest extends TestCase
'user' => 'test',
'password' => 'test'
];
// Both should fail to connect and return null
$mysqlDb = new Database($mysqlConfig);
$this->assertNull($mysqlDb->getConnection());
$mariaDb = new Database($mariadbConfig);
$this->assertNull($mariaDb->getConnection());
}
@ -67,7 +67,7 @@ class DatabaseTest extends TestCase
'user' => 'test',
'password' => 'test'
];
$invalidDb = new Database($invalidConfig);
$this->assertNull($invalidDb->getConnection());
}

View File

@ -9,12 +9,12 @@ class FeedbackTest extends TestCase
protected function setUp(): void
{
parent::setUp();
// Start session for flash messages
if (session_status() === PHP_SESSION_NONE && !headers_sent()) {
session_start();
}
// Initialize session variables
$_SESSION = [];
$_SESSION['flash_messages'] = [];
@ -34,10 +34,10 @@ class FeedbackTest extends TestCase
// Add a test message
Feedback::flash('LOGIN', 'LOGIN_SUCCESS', 'Test message');
$messages = $_SESSION['flash_messages'];
$this->assertIsArray($messages);
$this->assertCount(1, $messages);
$message = $messages[0];
$this->assertEquals('LOGIN', $message['category']);
$this->assertEquals('LOGIN_SUCCESS', $message['key']);
@ -67,7 +67,7 @@ class FeedbackTest extends TestCase
public function testGetMessageData()
{
$data = Feedback::getMessageData('LOGIN', 'LOGIN_SUCCESS', 'Test message');
$this->assertIsArray($data);
$this->assertEquals(Feedback::TYPE_SUCCESS, $data['type']);
$this->assertEquals('Test message', $data['message']);

View File

@ -56,7 +56,7 @@ class LogTest extends TestCase
$stmt = $this->db->getConnection()->prepare("SELECT * FROM logs WHERE scope = ?");
$stmt->execute(['test']);
$log = $stmt->fetch(PDO::FETCH_ASSOC);
$this->assertEquals(1, $log['user_id']);
$this->assertEquals('Test message', $log['message']);
$this->assertEquals('test', $log['scope']);
@ -67,7 +67,7 @@ class LogTest extends TestCase
// Insert test logs
$this->log->insertLog(1, 'Test message 1', 'user');
$this->log->insertLog(1, 'Test message 2', 'user');
$logs = $this->log->readLog(1, 'user');
$this->assertCount(2, $logs);
$this->assertEquals('Test message 1', $logs[0]['message']);
@ -80,15 +80,15 @@ class LogTest extends TestCase
$this->log->insertLog(1, 'Old message', 'user');
sleep(1); // Ensure different timestamps
$this->log->insertLog(1, 'New message', 'user');
$now = date('Y-m-d H:i:s');
$oneHourAgo = date('Y-m-d H:i:s', strtotime('-1 hour'));
$logs = $this->log->readLog(1, 'user', 0, '', [
'from_time' => $oneHourAgo,
'until_time' => $now
]);
$this->assertCount(2, $logs);
}
@ -98,11 +98,11 @@ class LogTest extends TestCase
$this->log->insertLog(1, 'Message 1', 'user');
$this->log->insertLog(1, 'Message 2', 'user');
$this->log->insertLog(1, 'Message 3', 'user');
// Test with limit
$logs = $this->log->readLog(1, 'user', 0, 2);
$this->assertCount(2, $logs);
// Test with offset
$logs = $this->log->readLog(1, 'user', 2, 2);
$this->assertCount(1, $logs);
@ -113,11 +113,11 @@ class LogTest extends TestCase
// Insert test logs
$this->log->insertLog(1, 'Test message', 'user');
$this->log->insertLog(1, 'Another message', 'user');
$logs = $this->log->readLog(1, 'user', 0, '', [
'message' => 'Test'
]);
$this->assertCount(1, $logs);
$this->assertEquals('Test message', $logs[0]['message']);
}
@ -127,11 +127,11 @@ class LogTest extends TestCase
// Insert test logs for different users
$this->log->insertLog(1, 'User 1 message', 'user');
$this->log->insertLog(2, 'User 2 message', 'user');
$logs = $this->log->readLog(1, 'user', 0, '', [
'id' => 1
]);
$this->assertCount(1, $logs);
$this->assertEquals('User 1 message', $logs[0]['message']);
}

View File

@ -67,7 +67,7 @@ class PlatformTest extends TestCase
$stmt = $this->db->getConnection()->prepare('SELECT * FROM platforms WHERE name = ?');
$stmt->execute([$data['name']]);
$platform = $stmt->fetch(PDO::FETCH_ASSOC);
$this->assertNotNull($platform);
$this->assertEquals($data['name'], $platform['name']);
$this->assertEquals($data['jitsi_url'], $platform['jitsi_url']);

View File

@ -3,18 +3,14 @@
// Set test environment
define('PHPUNIT_RUNNING', true);
// Configure session before starting it
ini_set('session.use_strict_mode', '1');
ini_set('session.use_only_cookies', '1');
ini_set('session.cookie_httponly', '1');
ini_set('session.cookie_secure', '1');
ini_set('session.cookie_samesite', 'Lax');
ini_set('session.gc_maxlifetime', 1440);
// Start session if not already started
//if (session_status() === PHP_SESSION_NONE) {
// session_start();
//}
// Configure session before any output
if (!headers_sent()) {
// Configure session settings
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_samesite', 'Strict');
ini_set('session.gc_maxlifetime', 1440); // 24 minutes
}
// Load Composer's autoloader
require_once __DIR__ . '/vendor/autoload.php';
@ -33,26 +29,9 @@ $GLOBALS['config'] = [
'db' => [
'type' => 'sqlite',
'dbFile' => ':memory:'
],
'folder' => '/',
'domain' => 'localhost',
'login' => [
'max_attempts' => 5,
'lockout_time' => 900
]
];
// Initialize system_messages array
$GLOBALS['system_messages'] = [];
// Set up server variables
$_SERVER['PHP_SELF'] = '/index.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit Test Browser';
$_SERVER['HTTP_HOST'] = 'localhost';
$_SERVER['REQUEST_URI'] = '/?page=login';
$_SERVER['HTTPS'] = 'on';
// Define global connectDB function
if (!function_exists('connectDB')) {
function connectDB($config) {
@ -62,3 +41,9 @@ if (!function_exists('connectDB')) {
];
}
}
// Set up server variables
$_SERVER['PHP_SELF'] = '/index.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit Test Browser';
$_SERVER['HTTPS'] = 'on';

View File

@ -0,0 +1,7 @@
[Session]
session.cookie_httponly = 1
session.use_only_cookies = 1
session.cookie_secure = 1
session.cookie_samesite = "Strict"
session.gc_maxlifetime = 1440
session.use_strict_mode = 1