DashboardPageTest.php 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Tests\Integration\App;
  4. use App\Auth\UserContext;
  5. use App\Tests\Integration\Support\AppTestCase;
  6. final class DashboardPageTest extends AppTestCase
  7. {
  8. protected function setUp(): void
  9. {
  10. $this->bootApp();
  11. $_SESSION['_user'] = (new UserContext(1, 'Admin', 'admin', null, UserContext::SOURCE_LOCAL))->toArray();
  12. $_SESSION['_last_active'] = time();
  13. $_SESSION['_authenticated_at'] = time();
  14. }
  15. public function testDashboardRendersStatsAndChartCanvas(): void
  16. {
  17. $this->enqueueApiResponse(200, [
  18. 'active_blocks' => 12,
  19. 'manual_blocks_count' => 3,
  20. 'allowlist_count' => 1,
  21. 'reports_24h' => 42,
  22. 'reports_24h_by_hour' => [
  23. ['hour' => '2026-04-29T10:00:00Z', 'count' => 7],
  24. ['hour' => '2026-04-29T11:00:00Z', 'count' => 35],
  25. ],
  26. 'top_reporters_24h' => [['name' => 'web-prod-01', 'count' => 30]],
  27. 'top_categories_24h' => [['slug' => 'brute_force', 'count' => 25]],
  28. 'blocked_ips_by_day_7d' => [
  29. 'days' => [
  30. '2026-04-23', '2026-04-24', '2026-04-25', '2026-04-26',
  31. '2026-04-27', '2026-04-28', '2026-04-29',
  32. ],
  33. 'series' => [
  34. ['category' => 'brute_force', 'counts' => [0, 2, 1, 0, 3, 5, 1]],
  35. ['category' => 'spam', 'counts' => [0, 1, 0, 0, 1, 2, 0]],
  36. ],
  37. ],
  38. 'jobs_status' => [['name' => 'recompute-scores', 'last_finished_at' => '2026-04-29T10:55:00Z', 'status' => 'success', 'overdue' => false]],
  39. 'reference_policy' => 'moderate',
  40. ]);
  41. $response = $this->request('GET', '/app/dashboard');
  42. self::assertSame(200, $response->getStatusCode());
  43. $body = (string) $response->getBody();
  44. self::assertStringContainsString('Dashboard', $body);
  45. self::assertStringContainsString('reports', $body);
  46. self::assertStringContainsString('id="reports-chart"', $body);
  47. self::assertStringContainsString('id="top-reporters-chart"', $body);
  48. self::assertStringContainsString('id="top-categories-chart"', $body);
  49. self::assertStringContainsString('id="blocked-ips-chart"', $body);
  50. self::assertStringContainsString('Blocked IPs', $body);
  51. self::assertStringContainsString('web-prod-01', $body);
  52. self::assertStringContainsString('brute_force', $body);
  53. self::assertStringContainsString('recompute-scores', $body);
  54. self::assertStringContainsString('moderate', $body);
  55. }
  56. public function testDashboardDegradesWhenApiUnreachable(): void
  57. {
  58. $this->enqueueApiException(new \GuzzleHttp\Exception\ConnectException(
  59. 'down',
  60. new \GuzzleHttp\Psr7\Request('GET', '/'),
  61. ));
  62. $this->enqueueApiException(new \GuzzleHttp\Exception\ConnectException(
  63. 'down',
  64. new \GuzzleHttp\Psr7\Request('GET', '/'),
  65. ));
  66. $response = $this->request('GET', '/app/dashboard');
  67. self::assertSame(200, $response->getStatusCode());
  68. $body = (string) $response->getBody();
  69. self::assertStringContainsString('Dashboard', $body);
  70. self::assertStringContainsString('API unreachable', $body);
  71. }
  72. }