Files
michaelschiemer/tests/Feature/LiveComponents/CounterComponentTest.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

182 lines
5.7 KiB
PHP

<?php
declare(strict_types=1);
/**
* LiveComponent Testing Example: CounterComponent
*
* Demonstrates usage of Pest helper functions for LiveComponent testing:
* - mountComponent() - Mount component with initial state
* - callAction() - Execute component actions
* - callActionWithFragments() - Execute actions with fragment updates
* - Custom Expectations: toHaveState, toContainHtml, toHaveDispatchedEvent
*/
use function Pest\LiveComponents\mountComponent;
use function Pest\LiveComponents\callAction;
describe('CounterComponent', function () {
it('renders initial counter state', function () {
$component = mountComponent('counter:test', ['count' => 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);
});
});