Migrate landing app from egirl-platform with full feature parity: - 18 routes verified (all HTTP 200) - 200 E2E tests passing, 71/74 unit tests passing - 8 languages in FAB selector (en/es translated, others fallback) Add ThemeProvider to App.tsx for styled-components theme context. Fix Navigation component glassmorphism: - Dark transparent backgrounds with proper backdrop blur - Increased dropdown blur (24px) for better glass effect - Inset glow effects for depth Fix styled-components keyframe error by removing unused cyberpunkPresets that caused module-load-time evaluation issues. Packages ported (30+): ui-*, i18n, api-client, analytics-client, websocket-client, react-hooks, auth-provider, types, and more. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
182 lines
6.3 KiB
TypeScript
182 lines
6.3 KiB
TypeScript
/**
|
|
* E2E Tests for FAB Language Selector
|
|
*
|
|
* Tests the language selector in a real browser environment,
|
|
* verifying that language switching works correctly and all
|
|
* options remain visible after language changes.
|
|
*/
|
|
|
|
import { test, expect } from '@playwright/test'
|
|
|
|
test.describe('FAB Language Selector', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('/')
|
|
})
|
|
|
|
test('displays FAB button on homepage', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
await expect(fabButton).toBeVisible()
|
|
})
|
|
|
|
test('expands to show all 8 language options', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
await fabButton.click()
|
|
|
|
// Verify all 8 language options are visible
|
|
await expect(page.getByTestId('language-option-en')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-es')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-zh')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-fr')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-de')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-pt')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-ja')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-ar')).toBeVisible()
|
|
})
|
|
|
|
test('changes language when option is clicked', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
await fabButton.click()
|
|
|
|
// Click Spanish option
|
|
const esOption = page.getByTestId('language-option-es')
|
|
await esOption.click()
|
|
|
|
// Wait for language change to complete
|
|
await page.waitForTimeout(500)
|
|
|
|
// Verify language changed by checking i18n state
|
|
const currentLanguage = await page.evaluate(() => {
|
|
return (window as any).i18n?.language || localStorage.getItem('i18nextLng')
|
|
})
|
|
|
|
// Should be 'es' or 'es-ES' or similar
|
|
expect(currentLanguage).toMatch(/^es/)
|
|
})
|
|
|
|
test('US/EN option remains visible after selecting another language', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
|
|
// Step 1: Expand FAB
|
|
await fabButton.click()
|
|
|
|
// Step 2: Select Spanish
|
|
const esOption = page.getByTestId('language-option-es')
|
|
await esOption.click()
|
|
|
|
// Step 3: Wait for menu to collapse
|
|
await expect(page.getByTestId('language-option-es')).not.toBeVisible()
|
|
|
|
// Step 4: Re-expand FAB
|
|
await fabButton.click()
|
|
|
|
// Step 5: CRITICAL - Verify EN is still in the list
|
|
await expect(page.getByTestId('language-option-en')).toBeVisible()
|
|
|
|
// Step 6: Verify ALL languages are still visible
|
|
await expect(page.getByTestId('language-option-es')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-zh')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-fr')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-de')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-pt')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-ja')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-ar')).toBeVisible()
|
|
})
|
|
|
|
test('can switch back to English after selecting another language', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
|
|
// Select Spanish
|
|
await fabButton.click()
|
|
await page.getByTestId('language-option-es').click()
|
|
await expect(page.getByTestId('language-option-es')).not.toBeVisible()
|
|
|
|
// Switch back to English
|
|
await fabButton.click()
|
|
await page.getByTestId('language-option-en').click()
|
|
await page.waitForTimeout(500)
|
|
|
|
// Verify language switched back to English
|
|
const currentLanguage = await page.evaluate(() => {
|
|
return (window as any).i18n?.language || localStorage.getItem('i18nextLng')
|
|
})
|
|
|
|
expect(currentLanguage).toMatch(/^en/)
|
|
})
|
|
|
|
test('marks current language as active', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
await fabButton.click()
|
|
|
|
// EN should be active by default
|
|
const enOption = page.getByTestId('language-option-en')
|
|
await expect(enOption).toHaveClass(/active/)
|
|
})
|
|
|
|
test('closes menu when clicking outside', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
await fabButton.click()
|
|
|
|
// Verify menu is open
|
|
await expect(page.getByTestId('language-option-en')).toBeVisible()
|
|
|
|
// Click outside (on body)
|
|
await page.click('body', { position: { x: 10, y: 10 } })
|
|
|
|
// Verify menu closed
|
|
await expect(page.getByTestId('language-option-en')).not.toBeVisible()
|
|
})
|
|
|
|
test('closes menu when pressing Escape', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
await fabButton.click()
|
|
|
|
// Verify menu is open
|
|
await expect(page.getByTestId('language-option-en')).toBeVisible()
|
|
|
|
// Press Escape
|
|
await page.keyboard.press('Escape')
|
|
|
|
// Verify menu closed
|
|
await expect(page.getByTestId('language-option-en')).not.toBeVisible()
|
|
})
|
|
|
|
test('persists language selection across page reloads', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
|
|
// Select Spanish
|
|
await fabButton.click()
|
|
await page.getByTestId('language-option-es').click()
|
|
await page.waitForTimeout(500)
|
|
|
|
// Reload page
|
|
await page.reload()
|
|
|
|
// Verify Spanish is still selected
|
|
await fabButton.click()
|
|
const esOption = page.getByTestId('language-option-es')
|
|
await expect(esOption).toHaveClass(/active/)
|
|
})
|
|
|
|
test('multiple language switches work correctly', async ({ page }) => {
|
|
const fabButton = page.getByTestId('fab-language-button')
|
|
|
|
// Switch through multiple languages
|
|
const languages = ['es', 'fr', 'de', 'en']
|
|
|
|
for (const lang of languages) {
|
|
await fabButton.click()
|
|
await page.getByTestId(`language-option-${lang}`).click()
|
|
await page.waitForTimeout(300)
|
|
|
|
// Verify all options still visible
|
|
await fabButton.click()
|
|
await expect(page.getByTestId('language-option-en')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-es')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-fr')).toBeVisible()
|
|
await expect(page.getByTestId('language-option-de')).toBeVisible()
|
|
|
|
// Close menu
|
|
await page.keyboard.press('Escape')
|
|
}
|
|
})
|
|
})
|