queue = Mockery::mock(Queue::class); // Mock JobMetricsManager $this->metricsManager = Mockery::mock(JobMetricsManagerInterface::class); $this->componentId = ComponentId::create('queue-stats', 'test'); $this->initialState = QueueStatsState::empty(); }); afterEach(function () { Mockery::close(); }); it('polls and updates state with queue statistics', function () { // Mock queue stats $this->queue->shouldReceive('getStats') ->once() ->andReturn([ 'total_size' => 42, 'priority_breakdown' => ['high' => 10, 'medium' => 20, 'low' => 12], ]); $this->queue->shouldReceive('size') ->once() ->andReturn(42); // Mock metrics $jobMetrics = new JobMetrics( totalJobs: 1000, successfulJobs: 950, failedJobs: 50, avgExecutionTime: Duration::fromMilliseconds(123.45), successRate: 95.0 ); $this->metricsManager->shouldReceive('getAllQueueMetrics') ->once() ->with('1 hour') ->andReturn([$jobMetrics]); $component = new QueueStatsComponent( id: $this->componentId, state: $this->initialState, queue: $this->queue, metricsManager: $this->metricsManager ); $newState = $component->poll(); expect($newState)->toBeInstanceOf(QueueStatsState::class); expect($newState->currentQueueSize)->toBe(42); expect($newState->totalJobs)->toBe(1000); expect($newState->successfulJobs)->toBe(950); expect($newState->failedJobs)->toBe(50); expect($newState->successRate)->toBe(95.0); expect($newState->avgExecutionTimeMs)->toBe(123.45); expect($newState->lastUpdated)->not->toBe($this->initialState->lastUpdated); }); it('has correct poll interval', function () { $component = new QueueStatsComponent( id: $this->componentId, state: $this->initialState, queue: $this->queue, metricsManager: $this->metricsManager ); expect($component->getPollInterval())->toBe(5000); }); it('returns correct render data', function () { $state = new QueueStatsState( currentQueueSize: 10, totalJobs: 100, successfulJobs: 90, failedJobs: 10, successRate: 90.0, avgExecutionTimeMs: 50.0, lastUpdated: '2024-01-15 12:00:00' ); $component = new QueueStatsComponent( id: $this->componentId, state: $state, queue: $this->queue, metricsManager: $this->metricsManager ); $renderData = $component->getRenderData(); expect($renderData->templatePath)->toBe('livecomponent-queue-stats'); expect($renderData->data)->toHaveKey('componentId'); expect($renderData->data)->toHaveKey('stateJson'); expect($renderData->data)->toHaveKey('pollInterval'); expect($renderData->data['pollInterval'])->toBe(5000); expect($renderData->data['currentQueueSize'])->toBe(10); expect($renderData->data['totalJobs'])->toBe(100); expect($renderData->data['successRate'])->toBe(90.0); }); it('handles empty metrics gracefully', function () { $this->queue->shouldReceive('getStats') ->once() ->andReturn(['total_size' => 0]); $this->queue->shouldReceive('size') ->once() ->andReturn(0); $this->metricsManager->shouldReceive('getAllQueueMetrics') ->once() ->with('1 hour') ->andReturn([]); $component = new QueueStatsComponent( id: $this->componentId, state: $this->initialState, queue: $this->queue, metricsManager: $this->metricsManager ); $newState = $component->poll(); expect($newState->currentQueueSize)->toBe(0); expect($newState->totalJobs)->toBe(0); expect($newState->successfulJobs)->toBe(0); expect($newState->failedJobs)->toBe(0); }); });