import { test, expect } from '@playwright/test'; test.describe('Tailwind-RS-Core Integration Tests @tailwind-rs-core', () => { test.beforeEach(async ({ page }) => { await page.goto('/'); await page.waitForLoadState('networkidle'); await page.waitForSelector('h1', { timeout: 10000 }); }); test('should generate dynamic classes using TailwindClasses API', async ({ page }) => { // Check that the page has proper Tailwind classes applied const body = page.locator('body'); const bodyClasses = await body.evaluate((el) => el.className); // Should have responsive classes expect(bodyClasses).toContain('min-h-screen'); expect(bodyClasses).toContain('transition-all'); expect(bodyClasses).toContain('duration-700'); // Check hero section for TailwindClasses API usage const heroSection = page.locator('section').first(); const heroClasses = await heroSection.evaluate((el) => el.className); // Should have classes generated by TailwindClasses API expect(heroClasses).toContain('text-white'); expect(heroClasses).toContain('py-24'); expect(heroClasses).toContain('relative'); expect(heroClasses).toContain('overflow-hidden'); expect(heroClasses).toContain('flex'); expect(heroClasses).toContain('items-center'); expect(heroClasses).toContain('justify-center'); }); test('should apply responsive classes correctly', async ({ page }) => { const heroSection = page.locator('section').first(); // Test desktop view await page.setViewportSize({ width: 1920, height: 1080 }); await page.waitForTimeout(500); const desktopStyles = await heroSection.evaluate((el) => { const styles = window.getComputedStyle(el); return { paddingTop: styles.paddingTop, paddingBottom: styles.paddingBottom, }; }); // Should have lg padding (py-24 = 6rem = 96px) expect(parseInt(desktopStyles.paddingTop)).toBeGreaterThanOrEqual(90); // Test tablet view await page.setViewportSize({ width: 768, height: 1024 }); await page.waitForTimeout(500); const tabletStyles = await heroSection.evaluate((el) => { const styles = window.getComputedStyle(el); return { paddingTop: styles.paddingTop, paddingBottom: styles.paddingBottom, }; }); // Should have md padding (py-20 = 5rem = 80px) expect(parseInt(tabletStyles.paddingTop)).toBeLessThan(parseInt(desktopStyles.paddingTop)); // Test mobile view await page.setViewportSize({ width: 375, height: 667 }); await page.waitForTimeout(500); const mobileStyles = await heroSection.evaluate((el) => { const styles = window.getComputedStyle(el); return { paddingTop: styles.paddingTop, paddingBottom: styles.paddingBottom, }; }); // Should have sm padding (py-16 = 4rem = 64px) expect(parseInt(mobileStyles.paddingTop)).toBeLessThan(parseInt(tabletStyles.paddingTop)); }); test('should merge custom classes with base classes', async ({ page }) => { // Check that custom classes are properly merged const heroSection = page.locator('section').first(); const heroClasses = await heroSection.evaluate((el) => el.className); // Should have both base classes and custom classes expect(heroClasses).toContain('text-white'); // base class expect(heroClasses).toContain('py-24'); // base class expect(heroClasses).toContain('flex'); // custom class expect(heroClasses).toContain('items-center'); // custom class expect(heroClasses).toContain('justify-center'); // custom class // Should have gradient background (custom class) const backgroundImage = await heroSection.evaluate((el) => { const styles = window.getComputedStyle(el); return styles.backgroundImage; }); expect(backgroundImage).toContain('gradient'); }); test('should apply state classes correctly', async ({ page }) => { // Check for hover states and transitions const buttons = page.locator('button'); const firstButton = buttons.first(); const buttonClasses = await firstButton.evaluate((el) => el.className); // Should have transition classes expect(buttonClasses).toMatch(/transition/); // Test hover state await firstButton.hover(); await page.waitForTimeout(100); // Check that hover styles are applied const hoverStyles = await firstButton.evaluate((el) => { const styles = window.getComputedStyle(el); return { transform: styles.transform, boxShadow: styles.boxShadow, }; }); // Should have some hover effect expect(hoverStyles.transform).not.toBe('none'); }); test('should generate color-specific classes dynamically', async ({ page }) => { // Get initial color classes const heroSection = page.locator('section').first(); const initialClasses = await heroSection.evaluate((el) => el.className); // Click on blue color const blueButton = page.locator('button').filter({ hasText: 'blue' }); await blueButton.click(); await page.waitForTimeout(500); const blueClasses = await heroSection.evaluate((el) => el.className); // Should have blue-specific classes expect(blueClasses).toMatch(/blue/); // Click on green color const greenButton = page.locator('button').filter({ hasText: 'green' }); await greenButton.click(); await page.waitForTimeout(500); const greenClasses = await heroSection.evaluate((el) => el.className); // Should have green-specific classes expect(greenClasses).toMatch(/green/); expect(greenClasses).not.toMatch(/blue/); // Click on purple color const purpleButton = page.locator('button').filter({ hasText: 'purple' }); await purpleButton.click(); await page.waitForTimeout(500); const purpleClasses = await heroSection.evaluate((el) => el.className); // Should have purple-specific classes expect(purpleClasses).toMatch(/purple/); expect(purpleClasses).not.toMatch(/green/); }); test('should apply theme-specific classes correctly', async ({ page }) => { // Get initial theme classes const body = page.locator('body'); const initialBackground = await body.evaluate((el) => { const styles = window.getComputedStyle(el); return styles.backgroundImage; }); // Click on light theme const lightThemeButton = page.locator('button').filter({ hasText: 'light' }); await lightThemeButton.click(); await page.waitForTimeout(500); const lightBackground = await body.evaluate((el) => { const styles = window.getComputedStyle(el); return styles.backgroundImage; }); // Should have light theme classes expect(lightBackground).not.toBe(initialBackground); expect(lightBackground).toContain('gradient'); // Click on dark theme const darkThemeButton = page.locator('button').filter({ hasText: 'dark' }); await darkThemeButton.click(); await page.waitForTimeout(500); const darkBackground = await body.evaluate((el) => { const styles = window.getComputedStyle(el); return styles.backgroundImage; }); // Should have dark theme classes expect(darkBackground).not.toBe(lightBackground); expect(darkBackground).toContain('gradient'); }); test('should validate class generation performance', async ({ page }) => { // Measure time for theme changes const startTime = Date.now(); // Perform multiple theme changes const lightThemeButton = page.locator('button').filter({ hasText: 'light' }); const darkThemeButton = page.locator('button').filter({ hasText: 'dark' }); const defaultThemeButton = page.locator('button').filter({ hasText: 'default' }); await lightThemeButton.click(); await page.waitForTimeout(100); await darkThemeButton.click(); await page.waitForTimeout(100); await defaultThemeButton.click(); await page.waitForTimeout(100); const endTime = Date.now(); const totalTime = endTime - startTime; // Theme changes should be fast (less than 1 second for all changes) expect(totalTime).toBeLessThan(1000); }); test('should handle class conflicts gracefully', async ({ page }) => { // Check that conflicting classes are handled properly const heroSection = page.locator('section').first(); // Get all applied classes const allClasses = await heroSection.evaluate((el) => el.className); const classArray = allClasses.split(' '); // Check for common conflicts const hasConflictingPadding = classArray.some(cls => cls.includes('py-') && classArray.some(other => other.includes('pt-') || other.includes('pb-') ) ); // Should not have conflicting padding classes expect(hasConflictingPadding).toBe(false); // Check for conflicting margin classes const hasConflictingMargin = classArray.some(cls => cls.includes('my-') && classArray.some(other => other.includes('mt-') || other.includes('mb-') ) ); // Should not have conflicting margin classes expect(hasConflictingMargin).toBe(false); }); });