- 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.
215 lines
7.7 KiB
PHP
215 lines
7.7 KiB
PHP
<?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);
|
|
}
|
|
}
|