# LiveComponent E2E Tests End-to-End tests for LiveComponent system functionality. ## Prerequisites E2E tests require: - Running development server (`npm run dev`) - Test components deployed at test URLs - Playwright or similar E2E testing framework ## Test Setup ### Option 1: Playwright (Recommended) ```bash npm install --save-dev @playwright/test npx playwright install ``` ### Option 2: Puppeteer ```bash npm install --save-dev puppeteer jest-puppeteer ``` ## Planned E2E Test Suites ### Fragment Updates E2E Tests **File**: `FragmentUpdates.e2e.test.js` **Test Scenarios**: 1. **Single Fragment Update** - Load component with multiple fragments - Trigger action that updates single fragment - Verify only target fragment updated - Verify other fragments unchanged - Verify focus preserved 2. **Multiple Fragment Updates** - Trigger action with `data-lc-fragments="frag1,frag2"` - Verify both fragments updated - Verify unused fragments unchanged - Measure DOM mutation count 3. **Fragment Update with Events** - Update fragment that dispatches events - Verify event received by listeners - Verify event payload correct 4. **Nested Fragment Updates** - Update parent fragment containing child fragments - Verify proper nested patching - Verify no child components destroyed 5. **Fragment Update Performance** - Measure time for fragment update vs full render - Verify 70-95% DOM operation reduction - Measure bandwidth difference (60-90% reduction) **Example Implementation**: ```javascript describe('Fragment Updates E2E', () => { beforeEach(async () => { await page.goto('http://localhost:5173/live-component/demo'); }); test('updates single fragment without affecting others', async () => { // Find component const component = await page.$('[data-live-component="user-stats:1"]'); // Get initial fragment contents const initialHeader = await component.$eval( '[data-lc-fragment="header"]', el => el.textContent ); const initialStats = await component.$eval( '[data-lc-fragment="stats"]', el => el.textContent ); // Trigger action that updates only stats fragment await component.$eval( '[data-live-action="refreshStats"][data-lc-fragments="stats"]', btn => btn.click() ); // Wait for update await page.waitForTimeout(100); // Verify stats updated const newStats = await component.$eval( '[data-lc-fragment="stats"]', el => el.textContent ); expect(newStats).not.toBe(initialStats); // Verify header unchanged const newHeader = await component.$eval( '[data-lc-fragment="header"]', el => el.textContent ); expect(newHeader).toBe(initialHeader); }); test('preserves focus during fragment update', async () => { const input = await page.$('[data-live-component] input[name="search"]'); // Focus input and type await input.focus(); await input.type('test query'); // Trigger fragment update await page.click('[data-live-action="search"][data-lc-fragments="results"]'); await page.waitForTimeout(100); // Verify focus preserved const focusedElement = await page.evaluate(() => document.activeElement.name); expect(focusedElement).toBe('search'); // Verify selection preserved const selectionStart = await input.evaluate(el => el.selectionStart); const selectionEnd = await input.evaluate(el => el.selectionEnd); expect(selectionStart).toBe(10); expect(selectionEnd).toBe(10); }); }); ``` ### Multi-Component Batch Updates E2E Tests **File**: `BatchUpdates.e2e.test.js` **Test Scenarios**: 1. **Automatic Batching** - Queue multiple operations within 50ms window - Verify single HTTP request sent - Verify all components updated correctly 2. **Manual Batch Execution** - Execute batch with `LiveComponent.executeBatch()` - Verify all operations processed - Verify partial failures handled gracefully 3. **Batch with Fragments** - Batch multiple fragment updates - Verify fragments updated efficiently - Measure HTTP request reduction (60-80%) 4. **Batch Performance** - Compare batch vs individual requests - Measure latency reduction - Measure bandwidth reduction (~40%) 5. **Batch Error Handling** - Trigger batch with some invalid operations - Verify failed operations reported - Verify successful operations still applied - Verify error isolation (no cascade failures) **Example Implementation**: ```javascript describe('Batch Updates E2E', () => { beforeEach(async () => { await page.goto('http://localhost:5173/live-component/batch-demo'); }); test('batches multiple operations automatically', async () => { // Monitor network requests const requests = []; page.on('request', req => { if (req.url().includes('/live-component/batch')) { requests.push(req); } }); // Trigger multiple operations quickly await page.evaluate(() => { LiveComponent.queueBatchOperation({ componentId: 'counter:1', method: 'increment' }); LiveComponent.queueBatchOperation({ componentId: 'counter:2', method: 'increment' }); LiveComponent.queueBatchOperation({ componentId: 'counter:3', method: 'increment' }); }); // Wait for batch to flush await page.waitForTimeout(100); // Verify single batch request expect(requests.length).toBe(1); // Verify all counters updated const counter1 = await page.$eval('[data-live-component="counter:1"]', el => el.textContent); const counter2 = await page.$eval('[data-live-component="counter:2"]', el => el.textContent); const counter3 = await page.$eval('[data-live-component="counter:3"]', el => el.textContent); expect(counter1).toContain('1'); expect(counter2).toContain('1'); expect(counter3).toContain('1'); }); test('handles partial batch failures gracefully', async () => { const result = await page.evaluate(async () => { return await LiveComponent.executeBatch([ { componentId: 'valid:1', method: 'validAction' }, { componentId: 'invalid:999', method: 'nonexistent' }, { componentId: 'valid:2', method: 'validAction' } ], { autoApply: false }); }); expect(result.total_operations).toBe(3); expect(result.success_count).toBe(2); expect(result.failure_count).toBe(1); // Verify successful operations applied const valid1 = await page.$('[data-live-component="valid:1"]'); const valid2 = await page.$('[data-live-component="valid:2"]'); expect(valid1).not.toBeNull(); expect(valid2).not.toBeNull(); }); }); ``` ## Running E2E Tests ### Development ```bash # Start dev server npm run dev # Run E2E tests in another terminal npm run test:e2e # Run with UI npm run test:e2e:ui # Debug mode npm run test:e2e:debug ``` ### CI/CD ```bash # Headless mode npm run test:e2e:ci ``` ## Test Components E2E tests require test components deployed at known URLs: - `/live-component/demo` - Basic fragment update demo - `/live-component/batch-demo` - Batch update demo - `/live-component/performance` - Performance benchmark page ## Performance Validation E2E tests should validate the performance claims: - **Fragment Updates**: 60-90% bandwidth reduction, 70-95% DOM operation reduction - **Request Batching**: 60-80% request reduction, ~40% total bytes reduction ## Visual Regression Testing Consider adding visual regression tests using: - Playwright's screenshot comparison - Percy.io - Chromatic ## Accessibility Testing E2E tests should include a11y checks: - Focus management during updates - ARIA live regions for dynamic content - Keyboard navigation preservation ## Browser Coverage Test across: - Chrome/Chromium - Firefox - Safari - Edge ## Future Enhancements - [ ] Implement full Playwright test suite - [ ] Add visual regression tests - [ ] Add accessibility tests - [ ] Add mobile device tests - [ ] Add network throttling tests - [ ] Add WebSocket/SSE update tests - [ ] Add offline mode tests (PWA)