import { test, expect } from '@playwright/test'; /** * LiveComponents: Progressive Enhancement Tests * * Tests data-lc-boost functionality for automatic AJAX links and forms */ test.describe('LiveComponents Progressive Enhancement', () => { test.beforeEach(async ({ page }) => { await page.goto('/'); }); test('should find boost containers', async ({ page }) => { const boostContainers = page.locator('[data-lc-boost="true"]'); const count = await boostContainers.count(); // This test just verifies the selector works // Actual boost containers may or may not exist expect(count).toBeGreaterThanOrEqual(0); }); test('should mark links in boost containers', async ({ page }) => { const boostContainer = page.locator('[data-lc-boost="true"]').first(); const containerCount = await boostContainer.count(); if (containerCount === 0) { test.skip(); return; } // Find links within boost container const links = boostContainer.locator('a[href]'); const linkCount = await links.count(); if (linkCount === 0) { test.skip(); return; } // Links should be marked (or at least exist) const firstLink = links.first(); expect(firstLink).toBeVisible(); }); test('should mark forms in boost containers', async ({ page }) => { const boostContainer = page.locator('[data-lc-boost="true"]').first(); const containerCount = await boostContainer.count(); if (containerCount === 0) { test.skip(); return; } // Find forms within boost container const forms = boostContainer.locator('form[action]'); const formCount = await forms.count(); if (formCount === 0) { test.skip(); return; } // Forms should exist const firstForm = forms.first(); expect(firstForm).toBeVisible(); }); test('should handle link clicks in boost containers', async ({ page }) => { const boostContainer = page.locator('[data-lc-boost="true"]').first(); const containerCount = await boostContainer.count(); if (containerCount === 0) { test.skip(); return; } const link = boostContainer.locator('a[href]:not([target="_blank"])').first(); const linkCount = await link.count(); if (linkCount === 0) { test.skip(); return; } const href = await link.getAttribute('href'); if (!href || href === '#' || href.startsWith('javascript:')) { test.skip(); return; } // Click link (should be handled via AJAX) await link.click(); // Wait for potential navigation await page.waitForTimeout(2000); // Page should still be loaded (or navigated) expect(page.url()).toBeTruthy(); }); test('should handle form submissions in boost containers', async ({ page }) => { const boostContainer = page.locator('[data-lc-boost="true"]').first(); const containerCount = await boostContainer.count(); if (containerCount === 0) { test.skip(); return; } // Find form without data-live-action (boost should handle it) const form = boostContainer.locator('form[action]:not([data-live-action])').first(); const formCount = await form.count(); if (formCount === 0) { test.skip(); return; } // Form should exist expect(form).toBeVisible(); }); test('should respect opt-out (data-lc-boost="false")', async ({ page }) => { const optOutLink = page.locator('a[data-lc-boost="false"]').first(); const count = await optOutLink.count(); if (count === 0) { test.skip(); return; } // Link should exist and be clickable expect(optOutLink).toBeVisible(); }); test('should skip special links (mailto, tel, javascript)', async ({ page }) => { const boostContainer = page.locator('[data-lc-boost="true"]').first(); const containerCount = await boostContainer.count(); if (containerCount === 0) { test.skip(); return; } // Find special links const mailtoLink = boostContainer.locator('a[href^="mailto:"]').first(); const telLink = boostContainer.locator('a[href^="tel:"]').first(); // These should exist but not be boosted // We can't easily test the boost behavior, but we can verify they exist if (await mailtoLink.count() > 0) { expect(mailtoLink).toBeVisible(); } if (await telLink.count() > 0) { expect(telLink).toBeVisible(); } }); });