mirror of
https://github.com/cloud-shuttle/leptos-shadcn-ui.git
synced 2025-12-22 22:00:00 +00:00
- Fixed compilation errors in menubar, combobox, and drawer packages - Updated to tailwind-rs-core v0.4.0 and tailwind-rs-wasm v0.4.0 for WASM compatibility - Cleaned up unused variable warnings across packages - Updated release documentation with WASM integration details - Demo working with dynamic color API and Tailwind CSS generation - All 25+ core components ready for crates.io publication Key features: ✅ WASM compatibility (no more tokio/mio dependencies) ✅ Dynamic Tailwind CSS class generation ✅ Type-safe color utilities ✅ Production-ready component library
124 lines
4.5 KiB
TypeScript
124 lines
4.5 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Visual Regression Tests @visual', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('/');
|
|
// Wait for the page to fully load
|
|
await page.waitForLoadState('networkidle');
|
|
await page.waitForSelector('h1', { timeout: 10000 });
|
|
});
|
|
|
|
test('should display the main hero section with correct styling', async ({ page }) => {
|
|
// Check that the hero section is visible and properly styled
|
|
const heroSection = page.locator('section').first();
|
|
await expect(heroSection).toBeVisible();
|
|
|
|
// Check for solid background color
|
|
const heroBackground = await heroSection.evaluate((el) => {
|
|
const styles = window.getComputedStyle(el);
|
|
return styles.backgroundColor;
|
|
});
|
|
expect(heroBackground).not.toBe('rgba(0, 0, 0, 0)'); // Should have a background color
|
|
|
|
// Check for the main heading
|
|
const mainHeading = page.locator('h1').first();
|
|
await expect(mainHeading).toContainText('🚀 WASM-Powered');
|
|
|
|
// Check for the subheading
|
|
const subHeading = page.locator('h2').first();
|
|
await expect(subHeading).toContainText('Component Showcase');
|
|
});
|
|
|
|
test('should display theme controls section', async ({ page }) => {
|
|
const themeSection = page.locator('section').nth(1);
|
|
await expect(themeSection).toBeVisible();
|
|
|
|
// Check for theme selection buttons
|
|
const themeButtons = page.locator('button').filter({ hasText: /default|light|dark/i });
|
|
await expect(themeButtons).toHaveCount(3);
|
|
|
|
// Check for color scheme buttons
|
|
const colorButtons = page.locator('button').filter({ hasText: /blue|green|purple/i });
|
|
await expect(colorButtons).toHaveCount(3);
|
|
});
|
|
|
|
test('should display component showcase section', async ({ page }) => {
|
|
const componentSection = page.locator('section').nth(2);
|
|
await expect(componentSection).toBeVisible();
|
|
|
|
// Check for component cards
|
|
const componentCards = page.locator('[class*="card"]');
|
|
await expect(componentCards.first()).toBeVisible();
|
|
|
|
// Check for component titles
|
|
const componentTitles = page.locator('h3, h4').filter({ hasText: /Button|Input|Card|Alert/i });
|
|
await expect(componentTitles.first()).toBeVisible();
|
|
});
|
|
|
|
test('should have proper responsive design', async ({ page }) => {
|
|
// Test desktop view
|
|
await page.setViewportSize({ width: 1920, height: 1080 });
|
|
await page.waitForTimeout(500);
|
|
|
|
const heroSection = page.locator('section').first();
|
|
const heroStyles = await heroSection.evaluate((el) => {
|
|
const styles = window.getComputedStyle(el);
|
|
return {
|
|
paddingTop: styles.paddingTop,
|
|
paddingBottom: styles.paddingBottom,
|
|
};
|
|
});
|
|
|
|
// Check that padding is appropriate for desktop
|
|
expect(parseInt(heroStyles.paddingTop)).toBeGreaterThan(50);
|
|
|
|
// Test mobile view
|
|
await page.setViewportSize({ width: 375, height: 667 });
|
|
await page.waitForTimeout(500);
|
|
|
|
const mobileHeroStyles = await heroSection.evaluate((el) => {
|
|
const styles = window.getComputedStyle(el);
|
|
return {
|
|
paddingTop: styles.paddingTop,
|
|
paddingBottom: styles.paddingBottom,
|
|
};
|
|
});
|
|
|
|
// Check that padding is adjusted for mobile
|
|
expect(parseInt(mobileHeroStyles.paddingTop)).toBeLessThan(parseInt(heroStyles.paddingTop));
|
|
});
|
|
|
|
test('should have proper color contrast and visibility', async ({ page }) => {
|
|
// Check that text is visible against backgrounds
|
|
const mainHeading = page.locator('h1').first();
|
|
const headingStyles = await mainHeading.evaluate((el) => {
|
|
const styles = window.getComputedStyle(el);
|
|
return {
|
|
color: styles.color,
|
|
backgroundImage: styles.backgroundImage,
|
|
};
|
|
});
|
|
|
|
// Check that the heading has visible text color
|
|
expect(headingStyles.color).not.toBe('rgba(0, 0, 0, 0)'); // Should have visible text
|
|
});
|
|
|
|
test('should display animated elements', async ({ page }) => {
|
|
// Check for animated overlay
|
|
const animatedOverlay = page.locator('div').filter({ hasText: '' }).first();
|
|
const overlayStyles = await animatedOverlay.evaluate((el) => {
|
|
const styles = window.getComputedStyle(el);
|
|
return {
|
|
animation: styles.animation,
|
|
backgroundImage: styles.backgroundImage,
|
|
};
|
|
});
|
|
|
|
// Check for pulse animation
|
|
expect(overlayStyles.animation).toContain('pulse');
|
|
// Check that overlay has a background color
|
|
expect(overlayStyles.backgroundColor).not.toBe('rgba(0, 0, 0, 0)');
|
|
});
|
|
});
|
|
|