added unit tests
This commit is contained in:
109
tests/Unit/ApiLogTest.php
Normal file
109
tests/Unit/ApiLogTest.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class ApiLogTest extends TestCase
|
||||
{
|
||||
private string $logDir;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
require_once dirname(__DIR__, 2) . '/lib/api_log.php';
|
||||
$this->logDir = $_ENV['QDB_API_LOG_DIR'] ?? (QDB_TEST_UPLOADS . '/logs/api');
|
||||
if (!is_dir($this->logDir)) {
|
||||
mkdir($this->logDir, 0775, true);
|
||||
}
|
||||
$this->clearLogFiles();
|
||||
unset($GLOBALS['qdb_api_log_ctx']);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->clearLogFiles();
|
||||
unset($GLOBALS['qdb_api_log_ctx']);
|
||||
}
|
||||
|
||||
public function testClassifyActivity(): void
|
||||
{
|
||||
$this->assertNull(qdb_api_log_classify_activity('OPTIONS', 'web', 'users'));
|
||||
$this->assertSame('web_change', qdb_api_log_classify_activity('POST', 'web', 'users'));
|
||||
$this->assertSame('app_change', qdb_api_log_classify_activity('POST', '', 'app_questionnaires'));
|
||||
$this->assertSame('app_sync', qdb_api_log_classify_activity('GET', '', 'app_questionnaires'));
|
||||
$this->assertSame('web_export', qdb_api_log_classify_activity('GET', 'web', 'export'));
|
||||
$this->assertSame('web_change', qdb_api_log_classify_activity('POST', 'web', 'backup'));
|
||||
$this->assertTrue(qdb_api_log_is_website_download('backup'));
|
||||
}
|
||||
|
||||
public function testRedactSensitiveFields(): void
|
||||
{
|
||||
$redacted = qdb_api_log_redact_value([
|
||||
'username' => 'coach1',
|
||||
'password' => 'secret',
|
||||
'encrypted' => str_repeat('x', 40),
|
||||
]);
|
||||
$this->assertSame('coach1', $redacted['username']);
|
||||
$this->assertSame('[REDACTED]', $redacted['password']);
|
||||
$this->assertSame('[ENCRYPTED:40 chars]', $redacted['encrypted']);
|
||||
}
|
||||
|
||||
public function testRedactQueryString(): void
|
||||
{
|
||||
$qs = qdb_api_log_redact_query_string('questionnaireID=qn1&token=abc&password=pw');
|
||||
parse_str((string)$qs, $params);
|
||||
$this->assertSame('qn1', $params['questionnaireID'] ?? null);
|
||||
$this->assertSame('[REDACTED]', $params['token'] ?? null);
|
||||
$this->assertSame('[REDACTED]', $params['password'] ?? null);
|
||||
}
|
||||
|
||||
public function testTokenHintMasksMiddle(): void
|
||||
{
|
||||
$hint = qdb_api_log_token_hint('0123456789abcdef');
|
||||
$this->assertStringContainsString('…', $hint);
|
||||
$this->assertStringNotContainsString('56789', $hint);
|
||||
}
|
||||
|
||||
public function testClientIpUsesForwardedFor(): void
|
||||
{
|
||||
$_SERVER['HTTP_X_FORWARDED_FOR'] = '203.0.113.50, 198.51.100.1';
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$this->assertSame('203.0.113.50', qdb_api_log_client_ip());
|
||||
unset($_SERVER['HTTP_X_FORWARDED_FOR']);
|
||||
}
|
||||
|
||||
public function testBeginFinishWritesWebChangeEntry(): void
|
||||
{
|
||||
$_SERVER['HTTP_X_QDB_CLIENT'] = 'web';
|
||||
$_SERVER['REQUEST_URI'] = '/api/users';
|
||||
$_SERVER['QUERY_STRING'] = '';
|
||||
qdb_test_set_request_body(json_encode(['username' => 'new_coach'], JSON_THROW_ON_ERROR));
|
||||
http_response_code(200);
|
||||
|
||||
qdb_api_log_begin('POST', 'users');
|
||||
qdb_api_log_finish();
|
||||
|
||||
$date = date('Y-m-d');
|
||||
$read = qdb_api_log_read_entries($date, 'web_change', 10);
|
||||
$entries = $read['entries'];
|
||||
$this->assertNotEmpty($entries);
|
||||
$last = $entries[0];
|
||||
$this->assertSame('web_change', $last['activity']);
|
||||
$this->assertSame('POST', $last['method']);
|
||||
$this->assertSame('users', $last['route']);
|
||||
$changes = $last['changes'] ?? [];
|
||||
$fields = array_column($changes, 'field');
|
||||
$this->assertContains('username', $fields);
|
||||
|
||||
qdb_test_reset_http_state();
|
||||
}
|
||||
|
||||
private function clearLogFiles(): void
|
||||
{
|
||||
foreach (glob($this->logDir . '/api-*.log') ?: [] as $path) {
|
||||
@unlink($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user