# LiveComponents E2E Integration Tests Comprehensive end-to-end integration tests for LiveComponents cross-cutting features: **Partial Rendering**, **Batch Operations**, and **Server-Sent Events (SSE)**. ## Overview This test suite validates the seamless integration of multiple LiveComponents features working together in real-world scenarios. It ensures that partial rendering, batch operations, and real-time updates work harmoniously without conflicts or state inconsistencies. ## Test Categories ### 1. Partial Rendering Tests (6 tests) **Purpose**: Validate fragment-based updates without full component re-rendering **Tests**: 1. **Update only targeted fragment without full component re-render** - Triggers fragment-specific action - Verifies only fragment HTML updated - Ensures component timestamp unchanged (no full render) - Validates DOM patch efficiency 2. **Update multiple fragments in single request** - Updates 2+ fragments simultaneously - Verifies all fragments updated correctly - Ensures only 1 HTTP request sent - Validates network efficiency 3. **Preserve component state during partial render** - Sets component state before fragment update - Triggers fragment update - Verifies state preserved after update - Validates state consistency 4. **Handle nested fragment updates** - Updates parent fragment containing child fragment - Verifies parent and child both updated - Ensures sibling fragments NOT updated - Validates selective rendering 5. **Apply morphing algorithm for minimal DOM changes** - Counts DOM nodes before update - Applies small content change - Verifies node count unchanged (morphing, not replacement) - Validates morphing stats (added/removed/updated) 6. **Handle fragment-not-found gracefully** - Calls action with non-existent fragment ID - Verifies error message displayed - Ensures component remains functional - Validates error recovery ### 2. Batch Operations Tests (6 tests) **Purpose**: Validate efficient execution of multiple actions in single request **Tests**: 1. **Execute multiple actions in single batch request** - Batches 3 different actions - Verifies only 1 HTTP request sent - Ensures all actions executed successfully - Validates batch efficiency 2. **Maintain action execution order in batch** - Batches 3 actions in specific order - Logs execution sequence - Verifies actions executed in correct order - Validates deterministic execution 3. **Rollback batch on action failure** - Batches successful + failing + successful actions - Verifies entire batch rolled back on failure - Ensures no partial state changes - Validates transactional behavior 4. **Handle partial batch execution with continueOnError flag** - Batches actions with `continueOnError: true` - Includes failing action in middle - Verifies successful actions still execute - Validates partial execution mode 5. **Support batch with mixed action types** - Batches sync + async + fragment update actions - Verifies all action types execute correctly - Ensures type compatibility - Validates heterogeneous batching 6. **Batch state updates efficiently** - Batches 10 state update actions - Verifies final state correct - Ensures only 1 state update event fired (optimization) - Validates state batching ### 3. Server-Sent Events (SSE) Tests (8 tests) **Purpose**: Validate real-time server-to-client communication **Tests**: 1. **Establish SSE connection for real-time updates** - Enables SSE - Verifies connection state OPEN (readyState === 1) - Ensures connection indicator visible - Validates connection establishment 2. **Receive and apply server-pushed updates** - Establishes SSE connection - Simulates server push event - Verifies component updated automatically - Validates push handling 3. **Handle SSE reconnection on connection loss** - Establishes connection - Simulates connection close - Verifies reconnecting indicator shown - Ensures automatic reconnection after retry period 4. **Support multiple SSE event types** - Sends different event types (update, notification, sync) - Logs received events - Verifies all types processed correctly - Validates event type handling 5. **Batch SSE updates for performance** - Sends 20 rapid SSE updates - Verifies final value correct - Ensures renders < updates (batching optimization) - Validates performance optimization 6. **Close SSE connection when component unmounts** - Establishes connection - Unmounts component - Verifies connection closed (readyState === 2) - Validates cleanup 7. **Handle SSE authentication and authorization** - Tests SSE with valid auth token - Verifies authenticated connection - Tests SSE with invalid token - Ensures auth error displayed 8. **Support SSE with custom event filters** - Enables SSE with priority filter - Sends events with different priorities - Verifies only filtered events processed - Validates client-side filtering ### 4. Integration Tests (4 tests) **Purpose**: Validate combined usage of multiple features **Tests**: 1. **Combine partial rendering with batch operations** - Batches multiple fragment updates + state changes - Verifies only 1 request sent - Ensures all fragments and state updated - Validates feature synergy 2. **Push partial updates via SSE** - Sends SSE event with fragment update - Verifies fragment updated via SSE - Ensures no full component render - Validates SSE + partial rendering 3. **Batch SSE-triggered actions efficiently** - Sends 5 rapid SSE events triggering actions - Verifies actions batched (< 5 executions) - Ensures final state correct - Validates SSE + batching 4. **Maintain consistency across all integration features** - Complex scenario: batch + partial + SSE simultaneously - Starts batch with fragment updates - Sends SSE update during batch execution - Verifies all updates applied correctly - Validates state consistency ## Quick Start ### Prerequisites ```bash # Ensure Playwright is installed npm install # Install browsers npx playwright install chromium # Ensure development server is running make up ``` ### Running Integration Tests ```bash # Run all integration tests npm run test:integration # Run with visible browser (debugging) npm run test:integration:headed # Run in debug mode (step through tests) npm run test:integration:debug # Run specific test category npx playwright test integration.spec.js --grep "Partial Rendering" npx playwright test integration.spec.js --grep "Batch Operations" npx playwright test integration.spec.js --grep "Server-Sent Events" npx playwright test integration.spec.js --grep "Integration:" ``` ## Test Page Requirements ### HTML Structure The test page `/livecomponents/test/integration` must include: ```html LiveComponents Integration Tests
initial
Original Content
Fragment 1
Fragment 2
Child
Sibling

Paragraph 1

Paragraph 2

0
Original
false
Initial
0
``` ### Component Actions The `IntegrationTestComponent` must implement: ```php use App\Framework\LiveComponents\LiveComponent; use App\Framework\LiveComponents\Attributes\Action; use App\Framework\LiveComponents\Attributes\Fragment; final readonly class IntegrationTestComponent extends LiveComponent { #[Action] #[Fragment('target-fragment')] public function updateFragment(array $params = []): array { $fragmentId = $params['fragmentId'] ?? 'target-fragment'; if (!$this->hasFragment($fragmentId)) { return ['error' => 'Fragment not found']; } return [ 'fragments' => [ $fragmentId => '
Updated
' ] ]; } #[Action] public function updateMultipleFragments(): array { return [ 'fragments' => [ 'fragment-1' => '
Fragment 1 Updated
', 'fragment-2' => '
Fragment 2 Updated
' ] ]; } #[Action] public function saveState(string $value): void { $this->state->set('savedValue', $value); } #[Action] #[Fragment('parent-fragment')] public function updateNestedFragment(): array { return [ 'fragments' => [ 'parent-fragment' => '
Parent Updated
Child Updated
' ] ]; } #[Action] #[Fragment('morph-fragment')] public function smallUpdate(): array { return [ 'fragments' => [ 'morph-fragment' => '

Paragraph 1 Updated

Paragraph 2

' ] ]; } #[Action] public function incrementCounter(): void { $current = $this->state->get('counter', 0); $this->state->set('counter', $current + 1); } #[Action] public function updateText(string $text): void { $this->state->set('text', $text); } #[Action] public function toggleFlag(): void { $current = $this->state->get('flag', false); $this->state->set('flag', !$current); } #[Action] public function action1(): void { // Log execution $this->logExecution('action1'); } #[Action] public function action2(): void { $this->logExecution('action2'); } #[Action] public function action3(): void { $this->logExecution('action3'); } #[Action] public function failingAction(): void { throw new \RuntimeException('Intentional failure for testing'); } #[Action] public function syncAction(): array { return ['success' => true]; } #[Action] public function asyncAction(): array { // Simulate async operation usleep(100000); // 100ms return ['success' => true]; } #[Action] #[Fragment('fragment-result')] public function fragmentAction(): array { return [ 'fragments' => [ 'fragment-result' => '
Fragment Action Complete
' ] ]; } public function enableSSE(array $options = []): void { // SSE setup logic $this->sseEnabled = true; } public function validateStateConsistency(): bool { // State validation logic return true; } } ``` ### SSE Endpoint The SSE endpoint `/live-component/sse/{componentId}` must support: ```php use App\Framework\LiveComponents\SSE\SseStream; final readonly class LiveComponentSseController { #[Route('/live-component/sse/{componentId}', method: Method::GET)] public function stream(string $componentId, Request $request): Response { $authToken = $request->headers->get('Authorization'); if (!$this->validateAuthToken($authToken)) { return new Response(status: Status::UNAUTHORIZED); } $stream = new SseStream(); // Set headers $response = new Response( status: Status::OK, headers: [ 'Content-Type' => 'text/event-stream', 'Cache-Control' => 'no-cache', 'Connection' => 'keep-alive' ] ); // Event loop while ($connection->isAlive()) { $event = $this->eventQueue->poll($componentId); if ($event) { $stream->send($event->type, $event->data); } usleep(100000); // 100ms polling interval } return $response; } } ``` ## Performance Expectations ### Partial Rendering - **Fragment Update Latency**: <50ms for small fragments (<5KB) - **DOM Morphing Efficiency**: 0 node additions/removals for content-only changes - **Memory Impact**: <1MB per fragment update ### Batch Operations - **Network Savings**: 1 request for N actions (vs. N requests) - **Execution Time**: Linear O(N) for N batched actions - **Rollback Overhead**: <10ms for transaction rollback ### Server-Sent Events - **Connection Establishment**: <500ms - **Event Latency**: <100ms from server send to client receive - **Reconnection Time**: <2s after connection loss - **Batching Window**: 50-100ms for update batching ## Troubleshooting ### Fragment Updates Not Working **Symptoms**: - Fragment content doesn't update - Full component re-renders instead **Solutions**: 1. **Verify Fragment Attribute**: ```php #[Fragment('target-fragment')] public function updateFragment(): array ``` 2. **Check Fragment ID in Response**: ```php return [ 'fragments' => [ 'target-fragment' => '
Updated
' ] ]; ``` 3. **Ensure Fragment Exists in DOM**: ```html
Original
``` ### Batch Operations Failing **Symptoms**: - Individual actions execute separately - Multiple HTTP requests sent **Solutions**: 1. **Use Batch API Correctly**: ```javascript component.batch() .call('action1') .call('action2') .execute(); // Don't forget .execute() ``` 2. **Check Batch Support**: ```javascript if (component.supportsBatch) { // Batching available } ``` ### SSE Connection Issues **Symptoms**: - SSE connection not established - Events not received **Solutions**: 1. **Check SSE Endpoint**: ```bash curl -N https://localhost/live-component/sse/integration:test \ -H "Authorization: Bearer token" ``` 2. **Verify Headers**: ``` Content-Type: text/event-stream Cache-Control: no-cache Connection: keep-alive ``` 3. **Test Auth Token**: ```javascript component.enableSSE({ authToken: 'valid-token-123' }); ``` 4. **Check Browser Console**: ```javascript component.sse.addEventListener('error', (e) => { console.error('SSE Error:', e); }); ``` ## CI/CD Integration ### GitHub Actions ```yaml name: Integration Tests on: push: branches: [main, develop] pull_request: branches: [main] jobs: integration-tests: runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm ci - name: Install Playwright run: npx playwright install --with-deps chromium - name: Start dev server run: | make up sleep 10 - name: Run Integration Tests run: npm run test:integration - name: Upload test results if: always() uses: actions/upload-artifact@v3 with: name: integration-test-results path: test-results/ - name: Upload test report if: always() uses: actions/upload-artifact@v3 with: name: playwright-report path: playwright-report/ ``` ## Best Practices ### 1. Test Organization - Group related tests with `test.describe()` - Use descriptive test names - Follow AAA pattern (Arrange, Act, Assert) ### 2. State Management - Reset component state between tests - Use `beforeEach` for consistent setup - Avoid test interdependencies ### 3. Async Handling - Use `page.waitForTimeout()` conservatively - Prefer `page.waitForSelector()` or `page.waitForFunction()` - Set appropriate timeouts for network operations ### 4. Error Handling - Test both success and failure paths - Verify error messages and recovery - Check graceful degradation ### 5. Performance Testing - Track request counts - Measure render times - Monitor memory usage - Validate batching efficiency ## Resources - [Playwright Documentation](https://playwright.dev/) - [LiveComponents Framework Guide](../../../docs/livecomponents/README.md) - [Fragment Rendering Guide](../../../docs/livecomponents/FRAGMENTS.md) - [Batch Operations Guide](../../../docs/livecomponents/BATCH.md) - [SSE Integration Guide](../../../docs/livecomponents/SSE.md) ## Support For issues or questions: 1. Check troubleshooting section above 2. Review LiveComponents documentation 3. Inspect browser console and network tab 4. Run tests in headed mode for visual debugging 5. Create GitHub issue with test output and environment details