Add comprehensive unit tests for Security, UserModel, and Validation utilities
- Implemented SecurityTest to validate token generation, CSRF protection, input sanitization, and rate limiting. - Created UserModelTest to ensure correct database operations for user management, including creation, updating, banning, and fetching active users. - Developed ValidationTest to verify input validation and sanitization for user IDs, nicknames, messages, and API requests. - Introduced Security and Validation utility classes with methods for secure token generation, input sanitization, and comprehensive validation rules.
This commit is contained in:
parent
5692874b10
commit
41cd7a4fd8
32 changed files with 5796 additions and 368 deletions
215
tests/unit/UserModelTest.php
Normal file
215
tests/unit/UserModelTest.php
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
<?php
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test UserModel database operations
|
||||
*/
|
||||
class UserModelTest extends TestCase
|
||||
{
|
||||
private $userModel;
|
||||
private $testUserId;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
// Set up in-memory database for testing
|
||||
TestDatabaseHelper::setupTestSchema();
|
||||
$this->userModel = new UserModel();
|
||||
$this->testUserId = 'test_user_' . bin2hex(random_bytes(8));
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
// Clean up after each test
|
||||
$pdo = TestDatabaseHelper::getTestPdo();
|
||||
$pdo->exec('DELETE FROM users');
|
||||
$pdo->exec('DELETE FROM chat_messages');
|
||||
$pdo->exec('DELETE FROM active_viewers');
|
||||
$pdo->exec('DELETE FROM banned_users');
|
||||
}
|
||||
|
||||
public function testCreateOrUpdateNewUser()
|
||||
{
|
||||
$userData = [
|
||||
'nickname' => 'TestUser',
|
||||
'ip_address' => '192.168.1.100',
|
||||
'session_id' => 'session_123456'
|
||||
];
|
||||
|
||||
$result = $this->userModel->createOrUpdate($this->testUserId, $userData);
|
||||
|
||||
$this->assertNotFalse($result);
|
||||
|
||||
// Verify user was created
|
||||
$user = $this->userModel->getByUserId($this->testUserId);
|
||||
$this->assertNotFalse($user);
|
||||
$this->assertEquals($this->testUserId, $user['user_id']);
|
||||
$this->assertEquals('TestUser', $user['nickname']);
|
||||
$this->assertEquals('192.168.1.100', $user['ip_address']);
|
||||
}
|
||||
|
||||
public function testCreateOrUpdateExistingUser()
|
||||
{
|
||||
// First create user
|
||||
$this->userModel->createOrUpdate($this->testUserId, ['nickname' => 'OriginalName']);
|
||||
|
||||
// Update existing user
|
||||
$this->userModel->createOrUpdate($this->testUserId, ['nickname' => 'UpdatedName']);
|
||||
|
||||
$user = $this->userModel->getByUserId($this->testUserId);
|
||||
$this->assertEquals('UpdatedName', $user['nickname']);
|
||||
}
|
||||
|
||||
public function testGetActiveUsers()
|
||||
{
|
||||
// Create test users
|
||||
$userId1 = 'active_user_1';
|
||||
$userId2 = 'active_user_2';
|
||||
$userId3 = 'inactive_user';
|
||||
|
||||
// Add active users
|
||||
$this->userModel->createOrUpdate($userId1, ['nickname' => 'Active1']);
|
||||
$this->userModel->createOrUpdate($userId2, ['nickname' => 'Active2']);
|
||||
$this->userModel->createOrUpdate($userId3, ['nickname' => 'Inactive']);
|
||||
|
||||
// Simulate inactive user (old timestamp)
|
||||
$pdo = TestDatabaseHelper::getTestPdo();
|
||||
$pdo->exec("UPDATE users SET last_seen = datetime('now', '-40 seconds') WHERE user_id = '$userId3'");
|
||||
|
||||
$activeUsers = $this->userModel->getActiveUsers(30);
|
||||
|
||||
$this->assertCount(2, $activeUsers);
|
||||
|
||||
// Verify active users are returned
|
||||
$userIds = array_column($activeUsers, 'user_id');
|
||||
$this->assertContains($userId1, $userIds);
|
||||
$this->assertContains($userId2, $userIds);
|
||||
$this->assertNotContains($userId3, $userIds);
|
||||
}
|
||||
|
||||
public function testUpdateLastSeen()
|
||||
{
|
||||
// Create user
|
||||
$this->userModel->createOrUpdate($this->testUserId, ['nickname' => 'TestUser']);
|
||||
|
||||
// Get initial last_seen
|
||||
$user = $this->userModel->getByUserId($this->testUserId);
|
||||
$initialLastSeen = $user['last_seen'];
|
||||
|
||||
// Wait a moment to ensure different timestamp
|
||||
sleep(1);
|
||||
|
||||
// Update last seen
|
||||
$result = $this->userModel->updateLastSeen($this->testUserId);
|
||||
$this->assertNotFalse($result);
|
||||
|
||||
// Verify last seen was updated
|
||||
$updatedUser = $this->userModel->getByUserId($this->testUserId);
|
||||
$this->assertNotEquals($initialLastSeen, $updatedUser['last_seen']);
|
||||
}
|
||||
|
||||
public function testBanAndUnbanUser()
|
||||
{
|
||||
// Create user first
|
||||
$this->userModel->createOrUpdate($this->testUserId, ['nickname' => 'TestUser']);
|
||||
|
||||
// Test initial state - not banned
|
||||
$this->assertFalse($this->userModel->isBanned($this->testUserId));
|
||||
|
||||
// Ban user
|
||||
$result = $this->userModel->banUser($this->testUserId, 'admin_user', 'Test ban reason');
|
||||
$this->assertNotFalse($result);
|
||||
|
||||
// Verify user is banned
|
||||
$this->assertTrue($this->userModel->isBanned($this->testUserId));
|
||||
|
||||
// Get banned users list
|
||||
$bannedUsers = $this->userModel->getBannedUsers();
|
||||
$this->assertCount(1, $bannedUsers);
|
||||
$this->assertEquals($this->testUserId, $bannedUsers[0]['user_id']);
|
||||
$this->assertEquals('Test ban reason', $bannedUsers[0]['reason']);
|
||||
|
||||
// Unban user
|
||||
$result = $this->userModel->unbanUser($this->testUserId);
|
||||
$this->assertNotFalse($result);
|
||||
|
||||
// Verify user is no longer banned
|
||||
$this->assertFalse($this->userModel->isBanned($this->testUserId));
|
||||
|
||||
// Verify banned users list is empty
|
||||
$bannedUsers = $this->userModel->getBannedUsers();
|
||||
$this->assertCount(0, $bannedUsers);
|
||||
}
|
||||
|
||||
public function testUpdateNickname()
|
||||
{
|
||||
// Create user
|
||||
$this->userModel->createOrUpdate($this->testUserId, ['nickname' => 'OldName']);
|
||||
|
||||
// Update nickname
|
||||
$result = $this->userModel->updateNickname($this->testUserId, 'NewName');
|
||||
$this->assertNotFalse($result);
|
||||
|
||||
// Verify nickname was updated
|
||||
$user = $this->userModel->getByUserId($this->testUserId);
|
||||
$this->assertEquals('NewName', $user['nickname']);
|
||||
}
|
||||
|
||||
public function testCleanupOldRecords()
|
||||
{
|
||||
// Create user
|
||||
$this->userModel->createOrUpdate($this->testUserId, ['nickname' => 'TestUser']);
|
||||
|
||||
// Set last_seen to be very old
|
||||
$pdo = TestDatabaseHelper::getTestPdo();
|
||||
$pdo->exec("UPDATE users SET last_seen = datetime('now', '-40 days') WHERE user_id = '$this->testUserId'");
|
||||
|
||||
// Cleanup records older than 30 days
|
||||
$result = $this->userModel->cleanupOldRecords(30);
|
||||
$this->assertGreaterThan(0, $result); // Should have deleted at least one record
|
||||
|
||||
// Verify user was cleaned up
|
||||
$user = $this->userModel->getByUserId($this->testUserId);
|
||||
$this->assertFalse($user);
|
||||
}
|
||||
|
||||
public function testNonExistentUser()
|
||||
{
|
||||
$user = $this->userModel->getByUserId('nonexistent_user');
|
||||
$this->assertFalse($user);
|
||||
|
||||
// Test update on non-existent user
|
||||
$result = $this->userModel->updateLastSeen('nonexistent_user');
|
||||
$this->assertEquals(0, $result); // No rows affected
|
||||
}
|
||||
|
||||
public function testGetActiveUsersWithinTimeframe()
|
||||
{
|
||||
// Create users with different activity times
|
||||
$userId1 = 'recent_user';
|
||||
$userId2 = 'old_user';
|
||||
|
||||
$this->userModel->createOrUpdate($userId1, ['nickname' => 'Recent']);
|
||||
$this->userModel->createOrUpdate($userId2, ['nickname' => 'Old']);
|
||||
|
||||
// Make one user appear old
|
||||
$pdo = TestDatabaseHelper::getTestPdo();
|
||||
$pdo->exec("UPDATE users SET last_seen = datetime('now', '-1 hour') WHERE user_id = '$userId2'");
|
||||
|
||||
// Get users active within 30 minutes
|
||||
$activeUsers = $this->userModel->getActiveUsers(30); // 30 seconds for testing
|
||||
$this->assertCount(1, $activeUsers);
|
||||
$this->assertEquals($userId1, $activeUsers[0]['user_id']);
|
||||
}
|
||||
|
||||
public function testDatabaseConnectionFailure()
|
||||
{
|
||||
// This test would verify error handling in a real scenario
|
||||
// For now, we test that the model handles database operations gracefully
|
||||
$this->assertIsObject($this->userModel);
|
||||
|
||||
// Test that methods return false/null on failure rather than throwing exceptions
|
||||
$result = $this->userModel->getByUserId('invalid_id_format_x');
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue