0]); expect($component['html']) ->toContainHtml('Count: 0'); expect($component['state']) ->toHaveState(['count' => 0, 'lastUpdate' => null]); }); it('renders with custom initial count', function () { $component = mountComponent('counter:test', ['count' => 42]); expect($component['html']) ->toContainHtml('Count: 42'); expect($component['state']) ->toHaveStateKey('count', 42); }); it('increments counter on action', function () { $component = mountComponent('counter:test', ['count' => 5]); $result = callAction($component, 'increment'); expect($result['state']) ->toHaveStateKey('count', 6); expect($result['html']) ->toContainHtml('Count: 6'); }); it('decrements counter on action', function () { $component = mountComponent('counter:test', ['count' => 5]); $result = callAction($component, 'decrement'); expect($result['state']) ->toHaveStateKey('count', 4); expect($result['html']) ->toContainHtml('Count: 4'); }); it('prevents negative counts on decrement', function () { $component = mountComponent('counter:test', ['count' => 0]); $result = callAction($component, 'decrement'); expect($result['state']) ->toHaveStateKey('count', 0); // Should stay at 0, not go negative }); it('resets counter to zero', function () { $component = mountComponent('counter:test', ['count' => 42]); $result = callAction($component, 'reset'); expect($result['state']) ->toHaveStateKey('count', 0); }); it('adds custom amount to counter', function () { $component = mountComponent('counter:test', ['count' => 10]); $result = callAction($component, 'addAmount', ['amount' => 15]); expect($result['state']) ->toHaveStateKey('count', 25); }); it('prevents negative counts when adding negative amount', function () { $component = mountComponent('counter:test', ['count' => 5]); $result = callAction($component, 'addAmount', ['amount' => -10]); expect($result['state']) ->toHaveStateKey('count', 0); // Should be capped at 0 }); it('dispatches counter:changed event on increment', function () { $component = mountComponent('counter:test', ['count' => 5]); $result = callAction($component, 'increment'); expect($result['events']) ->toHaveDispatchedEvent('counter:changed'); }); it('dispatches counter:changed event with correct data', function () { $component = mountComponent('counter:test', ['count' => 5]); $result = callAction($component, 'increment'); expect($result['events']) ->toHaveDispatchedEventWithData('counter:changed', [ 'component_id' => 'counter:test', 'old_value' => 5, 'new_value' => 6, 'change' => '+1', ]); }); it('dispatches milestone event at multiples of 10', function () { $component = mountComponent('counter:test', ['count' => 9]); $result = callAction($component, 'increment'); expect($result['events']) ->toHaveDispatchedEvent('counter:milestone'); }); it('does not dispatch milestone event when not at multiple of 10', function () { $component = mountComponent('counter:test', ['count' => 8]); $result = callAction($component, 'increment'); // Should have counter:changed but not milestone expect($result['events'])->toHaveDispatchedEvent('counter:changed'); $hasMilestone = false; foreach ($result['events'] as $event) { if ($event->name === 'counter:milestone') { $hasMilestone = true; } } expect($hasMilestone)->toBeFalse(); }); it('dispatches reset event on reset action', function () { $component = mountComponent('counter:test', ['count' => 42]); $result = callAction($component, 'reset'); expect($result['events']) ->toHaveDispatchedEventWithData('counter:reset', [ 'component_id' => 'counter:test', 'previous_value' => 42, ]); }); it('maintains component identity across actions', function () { $component = mountComponent('counter:test'); $result1 = callAction($component, 'increment'); $result2 = callAction($result1, 'increment'); expect($result2['componentId'])->toBe('counter:test'); expect($result2['state']['count'])->toBe(2); }); it('chains multiple actions correctly', function () { $component = mountComponent('counter:test', ['count' => 0]); $result = callAction($component, 'increment'); $result = callAction($result, 'increment'); $result = callAction($result, 'increment'); $result = callAction($result, 'decrement'); expect($result['state']['count'])->toBe(2); }); });