createMock(UserLifecycleAuditRepository::class); $repository->expects($this->once())->method('latestSystemRun')->willReturn(null); $service = new UserLifecycleAuditDashboardService($repository); $this->assertNull($service->lastRun()); } public function testLastRunNormalizesRowToContractShape(): void { $repository = $this->createMock(UserLifecycleAuditRepository::class); $repository->method('latestSystemRun')->willReturn([ 'created_at' => '2026-04-25 12:00:00', 'status' => 'success', 'action' => 'deactivate', ]); $service = new UserLifecycleAuditDashboardService($repository); $row = $service->lastRun(); $this->assertIsArray($row); $this->assertSame('2026-04-25 12:00:00', $row['created_at']); $this->assertSame('success', $row['status']); $this->assertSame('deactivate', $row['action']); } public function testActionCountInWindowReturnsZeroForUnknownAction(): void { $repository = $this->createMock(UserLifecycleAuditRepository::class); $repository->expects($this->never())->method('countActionInWindow'); $service = new UserLifecycleAuditDashboardService($repository); $this->assertSame(0, $service->actionCountInWindow('not-a-real-action', 30)); } public function testActionCountInWindowReturnsZeroForUnknownStatus(): void { $repository = $this->createMock(UserLifecycleAuditRepository::class); $repository->expects($this->never())->method('countActionInWindow'); $service = new UserLifecycleAuditDashboardService($repository); $this->assertSame(0, $service->actionCountInWindow('deactivate', 30, 'not-a-status')); } public function testActionCountInWindowDelegatesNormalizedValuesToRepository(): void { $repository = $this->createMock(UserLifecycleAuditRepository::class); $repository->expects($this->once()) ->method('countActionInWindow') ->with('deactivate', 30, 'success') ->willReturn(7); $service = new UserLifecycleAuditDashboardService($repository); $this->assertSame(7, $service->actionCountInWindow('Deactivate', 30, 'Success')); } public function testSummaryByActionReturnsEmptyForUnknownStatus(): void { $repository = $this->createMock(UserLifecycleAuditRepository::class); $repository->expects($this->never())->method('sumByActionInWindow'); $service = new UserLifecycleAuditDashboardService($repository); $this->assertSame([], $service->summaryByAction(30, 'not-a-status')); } public function testSummaryByActionDelegatesNormalizedStatus(): void { $repository = $this->createMock(UserLifecycleAuditRepository::class); $repository->expects($this->once()) ->method('sumByActionInWindow') ->with(30, 'success') ->willReturn(['deactivate' => 4, 'delete' => 2]); $service = new UserLifecycleAuditDashboardService($repository); $this->assertSame( ['deactivate' => 4, 'delete' => 2], $service->summaryByAction(30, 'Success') ); } }