import { test, expect } from '@playwright/test'; /** * Assistant Widget Positioning Tests * * Tests that assistant widget never covers primary actions */ test.describe('Assistant Widget Positioning', () => { test('ChatControl button does not cover primary actions', async ({ page }) => { await page.goto('/'); await page.waitForLoadState('networkidle'); // ChatControl button is the floating assistant button const chatButton = page.locator('button:has-text("Bot"), [class*="robot"], [class*="assistant"]'); const buttonCount = await chatButton.count(); if (buttonCount > 0) { // Get primary action buttons (e.g., in header, main content) const primaryActions = page.locator('header button, main button[type="submit"], main button:not([variant="ghost"])'); const actionCount = await primaryActions.count(); if (actionCount > 0) { const chatBox = await chatButton.first().boundingBox(); if (chatBox) { // Check that chat button is positioned in a corner (bottom-right) const viewportWidth = await page.evaluate(() => window.innerWidth); const viewportHeight = await page.evaluate(() => window.innerHeight); // Chat button should be in bottom-right corner const inBottomRight = ( chatBox.x + chatBox.width > viewportWidth - 100 && chatBox.y + chatBox.height > viewportHeight - 100 ); expect(inBottomRight).toBe(true); } } } }); test('ChatControl modal has proper z-index and backdrop', async ({ page }) => { await page.goto('/'); await page.waitForLoadState('networkidle'); const chatButton = page.locator('button:has-text("Bot"), [class*="robot"], [class*="assistant"]'); const buttonCount = await chatButton.count(); if (buttonCount > 0) { // Click to open chat await chatButton.first().click(); // Wait for modal to appear await page.waitForTimeout(500); // Check for backdrop const backdrop = page.locator('[style*="backdrop"], .backdrop, [style*="blur"]'); const hasBackdrop = await backdrop.count() > 0; // ChatControl should have backdrop when open expect(hasBackdrop).toBe(true); // Check z-index of modal const modal = page.locator('[role="dialog"], .modal, [style*="fixed"][style*="bottom"]'); const modalCount = await modal.count(); if (modalCount > 0) { const zIndex = await modal.first().evaluate((el) => { const computed = window.getComputedStyle(el); return parseInt(computed.zIndex) || 0; }); // Modal should have high z-index expect(zIndex).toBeGreaterThan(1000); } } }); test('ChatControl can be dismissed and does not block primary actions', async ({ page }) => { await page.goto('/'); await page.waitForLoadState('networkidle'); const chatButton = page.locator('button:has-text("Bot"), [class*="robot"], [class*="assistant"]'); const buttonCount = await chatButton.count(); if (buttonCount > 0) { // Click to open chat await chatButton.first().click(); await page.waitForTimeout(500); // Check if there's a close button const closeButton = page.locator('button:has-text("Close"), button:has-text("X"), [aria-label="close"]'); const closeCount = await closeButton.count(); if (closeCount > 0) { await closeButton.first().click(); await page.waitForTimeout(500); } // After closing, primary actions should be accessible const primaryActions = page.locator('header button, main button[type="submit"]'); const actionCount = await primaryActions.count(); if (actionCount > 0) { await expect(primaryActions.first()).toBeVisible(); await expect(primaryActions.first()).toBeEnabled(); } } }); });