'admin', 'password' => 'secret123']; $result = RequestLogMiddleware::sanitizeBody($body); $this->assertSame('admin', $result['username']); $this->assertSame('***', $result['password']); } public function test_sanitize_body_handles_nested_password_fields(): void { $body = [ 'user' => [ 'name' => 'test', 'password' => 'nested_secret', ], ]; $result = RequestLogMiddleware::sanitizeBody($body); $this->assertSame('test', $result['user']['name']); $this->assertSame('***', $result['user']['password']); } public function test_sanitize_body_handles_all_password_variants(): void { $body = [ 'password' => 'p1', 'old_password' => 'p2', 'new_password' => 'p3', 'password_confirmation' => 'p4', ]; $result = RequestLogMiddleware::sanitizeBody($body); $this->assertSame('***', $result['password']); $this->assertSame('***', $result['old_password']); $this->assertSame('***', $result['new_password']); $this->assertSame('***', $result['password_confirmation']); } public function test_sanitize_body_preserves_non_sensitive_fields(): void { $body = ['username' => 'admin', 'email' => 'a@b.com', 'status' => 1]; $result = RequestLogMiddleware::sanitizeBody($body); $this->assertSame($body, $result); } public function test_sanitize_body_handles_empty_array(): void { $result = RequestLogMiddleware::sanitizeBody([]); $this->assertSame([], $result); } // ========== extractResponseCode ========== public function test_extract_response_code_from_json_response(): void { $response = new Response(200, ['Content-Type' => 'application/json'], json_encode([ 'code' => 0, 'message' => 'success', 'data' => [], ])); $code = RequestLogMiddleware::extractResponseCode($response); $this->assertSame(0, $code); } public function test_extract_response_code_returns_null_for_non_json(): void { $response = new Response(200, ['Content-Type' => 'text/html'], ''); $code = RequestLogMiddleware::extractResponseCode($response); $this->assertNull($code); } public function test_extract_response_code_returns_null_when_no_code_field(): void { $response = new Response(200, ['Content-Type' => 'application/json'], json_encode([ 'message' => 'ok', ])); $code = RequestLogMiddleware::extractResponseCode($response); $this->assertNull($code); } // ========== getClientIp ========== public function test_get_client_ip_from_x_forwarded_for(): void { $request = new ServerRequest('GET', '/test', ['X-Forwarded-For' => '1.2.3.4, 5.6.7.8']); $ip = RequestLogMiddleware::getClientIp($request); $this->assertSame('1.2.3.4', $ip); } public function test_get_client_ip_from_x_real_ip(): void { $request = new ServerRequest('GET', '/test', ['X-Real-IP' => '10.0.0.1']); $ip = RequestLogMiddleware::getClientIp($request); $this->assertSame('10.0.0.1', $ip); } public function test_get_client_ip_from_server_params(): void { $request = new ServerRequest('GET', '/test', [], null, '1.1', ['remote_addr' => '192.168.1.1']); $ip = RequestLogMiddleware::getClientIp($request); $this->assertSame('192.168.1.1', $ip); } public function test_get_client_ip_returns_null_when_no_ip_available(): void { $request = new ServerRequest('GET', '/test'); $ip = RequestLogMiddleware::getClientIp($request); $this->assertNull($ip); } public function test_extract_response_code_handles_code_as_string(): void { $response = new Response(200, ['Content-Type' => 'application/json'], json_encode([ 'code' => '200', 'message' => 'success', ])); $code = RequestLogMiddleware::extractResponseCode($response); $this->assertSame(200, $code); } public function test_sanitize_body_handles_deeply_nested_structures(): void { $body = [ 'level1' => [ 'level2' => [ 'level3' => [ 'password' => 'deep_secret', 'token' => 'deep_token', 'name' => 'keep_this', ], ], ], ]; $result = RequestLogMiddleware::sanitizeBody($body); $this->assertSame('***', $result['level1']['level2']['level3']['password']); $this->assertSame('***', $result['level1']['level2']['level3']['token']); $this->assertSame('keep_this', $result['level1']['level2']['level3']['name']); } }