setUpComponentTest(); }); it('onUpdate() is called after action execution', function () { // Track if onUpdate was called $GLOBALS['test_update_called'] = false; // Create component that implements LifecycleAware $component = new class (ComponentId::fromString('test:update')) implements LiveComponentContract, LifecycleAware { public function __construct( private ComponentId $id ) { } public function getId(): ComponentId { return $this->id; } public function getData(): ComponentData { return ComponentData::fromArray(['count' => 0]); } public function getRenderData(): RenderData { return new RenderData('test', ['count' => 0]); } public function increment(): ComponentData { return ComponentData::fromArray(['count' => 1]); } public function onMount(): void { } public function onUpdate(): void { $GLOBALS['test_update_called'] = true; } public function onDestroy(): void { } }; // Execute action $handler = $this->container->get(LiveComponentHandler::class); $params = ActionParameters::fromArray(['_csrf_token' => $this->generateCsrfToken($component)]); $result = $handler->handle($component, 'increment', $params); // Verify onUpdate was called expect($GLOBALS['test_update_called'])->toBeTrue(); expect($result->state->data['count'])->toBe(1); unset($GLOBALS['test_update_called']); }); it('works with Timer component', function () { $timer = new \App\Application\LiveComponents\Timer\TimerComponent( id: ComponentId::fromString('timer:test') ); expect($timer)->toBeInstanceOf(LifecycleAware::class); expect($timer)->toBeInstanceOf(LiveComponentContract::class); $data = $timer->getData(); expect($data->toArray())->toHaveKeys(['seconds', 'isRunning', 'startedAt', 'logs']); });