fix: unify theme system - fix theme switching persistence
- Unified localStorage key to 'theme-preference' across all components
- Fixed header.tsx using wrong localStorage key ('theme' instead of 'theme-preference')
- Added localStorage hybrid persistence for instant theme changes
- Removed router.refresh() which was causing stale data revert
- Replaced Blue theme with Sepia
- Consolidated auth() calls to prevent race conditions
- Updated UserSettingsData types to include all themes
This commit is contained in:
568
keep-notes/tests/settings.spec.ts
Normal file
568
keep-notes/tests/settings.spec.ts
Normal file
@@ -0,0 +1,568 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
/**
|
||||
* Tests complets pour les Settings UX (Story 11-2)
|
||||
*
|
||||
* Ce fichier teste toutes les fonctionnalités implémentées:
|
||||
* - General Settings: Notifications (Email), Privacy (Analytics)
|
||||
* - Profile Settings: Language, Font Size, Show Recent Notes
|
||||
* - Appearance Settings: Theme Persistence (Light/Dark/Auto)
|
||||
* - SettingsSearch: Functional search with filtering
|
||||
*
|
||||
* Prérequis:
|
||||
* - Être connecté avec un compte utilisateur
|
||||
* - Avoir accès aux pages de settings
|
||||
* - Base de données avec les nouveaux champs (emailNotifications, anonymousAnalytics)
|
||||
*/
|
||||
|
||||
test.describe('Settings UX - Story 11-2', () => {
|
||||
// Variables pour stocker les credentials
|
||||
let email: string
|
||||
let password: string
|
||||
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
// Les credentials seront fournis par l'utilisateur
|
||||
console.log('Credentials nécessaires pour exécuter les tests')
|
||||
console.log('Veuillez fournir email et password')
|
||||
})
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Se connecter avant chaque test
|
||||
await page.goto('http://localhost:3000/login')
|
||||
await page.fill('input[name="email"]', email)
|
||||
await page.fill('input[name="password"]', password)
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// Attendre la connexion et vérifier qu'on est sur la page d'accueil
|
||||
await page.waitForURL('**/main**')
|
||||
await expect(page).toHaveURL(/\/main/)
|
||||
})
|
||||
|
||||
/**
|
||||
* Tests pour General Settings
|
||||
*/
|
||||
test.describe('General Settings', () => {
|
||||
test('devrait afficher la page General Settings', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Vérifier le titre de la page
|
||||
const title = await page.textContent('h1')
|
||||
expect(title).toContain('General')
|
||||
|
||||
// Vérifier que les sections sont présentes
|
||||
await expect(page.locator('#language')).toBeVisible()
|
||||
await expect(page.locator('#notifications')).toBeVisible()
|
||||
await expect(page.locator('#privacy')).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait avoir le toggle Email Notifications', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Scroll vers la section notifications
|
||||
await page.locator('#notifications').scrollIntoViewIfNeeded()
|
||||
|
||||
// Vérifier que le toggle est présent
|
||||
const emailToggle = page.getByRole('switch', { name: /email notifications/i })
|
||||
await expect(emailToggle).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait pouvoir activer/désactiver Email Notifications', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Scroll vers la section notifications
|
||||
await page.locator('#notifications').scrollIntoViewIfNeeded()
|
||||
|
||||
// Récupérer l'état initial du toggle
|
||||
const emailToggle = page.getByRole('switch', { name: /email notifications/i })
|
||||
const initialState = await emailToggle.getAttribute('aria-checked')
|
||||
const initialEnabled = initialState === 'true'
|
||||
|
||||
// Cliquer sur le toggle
|
||||
await emailToggle.click()
|
||||
|
||||
// Attendre un peu pour l'opération asynchrone
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Vérifier que l'état a changé
|
||||
const newState = await emailToggle.getAttribute('aria-checked')
|
||||
const newEnabled = newState === 'true'
|
||||
expect(newEnabled).toBe(!initialEnabled)
|
||||
|
||||
// Vérifier qu'un toast de succès apparaît
|
||||
await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
|
||||
})
|
||||
|
||||
test('devrait avoir le toggle Anonymous Analytics', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Scroll vers la section privacy
|
||||
await page.locator('#privacy').scrollIntoViewIfNeeded()
|
||||
|
||||
// Vérifier que le toggle est présent
|
||||
const analyticsToggle = page.getByRole('switch', { name: /anonymous analytics/i })
|
||||
await expect(analyticsToggle).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait pouvoir activer/désactiver Anonymous Analytics', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Scroll vers la section privacy
|
||||
await page.locator('#privacy').scrollIntoViewIfNeeded()
|
||||
|
||||
// Récupérer l'état initial du toggle
|
||||
const analyticsToggle = page.getByRole('switch', { name: /anonymous analytics/i })
|
||||
const initialState = await analyticsToggle.getAttribute('aria-checked')
|
||||
const initialEnabled = initialState === 'true'
|
||||
|
||||
// Cliquer sur le toggle
|
||||
await analyticsToggle.click()
|
||||
|
||||
// Attendre un peu pour l'opération asynchrone
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Vérifier que l'état a changé
|
||||
const newState = await analyticsToggle.getAttribute('aria-checked')
|
||||
const newEnabled = newState === 'true'
|
||||
expect(newEnabled).toBe(!initialEnabled)
|
||||
|
||||
// Vérifier qu'un toast de succès apparaît
|
||||
await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
|
||||
})
|
||||
|
||||
test('devrait avoir le composant SettingsSearch', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Vérifier que la barre de recherche est présente
|
||||
const searchInput = page.getByPlaceholder(/search/i)
|
||||
await expect(searchInput).toBeVisible()
|
||||
|
||||
// Vérifier l'icône de recherche
|
||||
await expect(page.locator('svg').filter({ hasText: '' }).first()).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait filtrer les sections avec SettingsSearch', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Cliquer sur la barre de recherche
|
||||
const searchInput = page.getByPlaceholder(/search/i)
|
||||
await searchInput.click()
|
||||
|
||||
// Taper "notification"
|
||||
await searchInput.fill('notification')
|
||||
|
||||
// Vérifier que la section notifications est visible
|
||||
await expect(page.locator('#notifications')).toBeVisible()
|
||||
|
||||
// Vérifier que les autres sections ne sont plus visibles (ou sont filtrées)
|
||||
// Note: Cela dépend de l'implémentation exacte du filtrage
|
||||
})
|
||||
|
||||
test('devrait effacer la recherche avec le bouton X', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
const searchInput = page.getByPlaceholder(/search/i)
|
||||
await searchInput.fill('test')
|
||||
|
||||
// Vérifier que le bouton X apparaît
|
||||
const clearButton = page.getByRole('button', { name: /clear search/i })
|
||||
await expect(clearButton).toBeVisible()
|
||||
|
||||
// Cliquer sur le bouton X
|
||||
await clearButton.click()
|
||||
|
||||
// Vérifier que la recherche est vide
|
||||
await expect(searchInput).toHaveValue('')
|
||||
})
|
||||
|
||||
test('devrait effacer la recherche avec la touche Escape', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
const searchInput = page.getByPlaceholder(/search/i)
|
||||
await searchInput.fill('test')
|
||||
|
||||
// Appuyer sur Escape
|
||||
await page.keyboard.press('Escape')
|
||||
|
||||
// Vérifier que la recherche est vide
|
||||
await expect(searchInput).toHaveValue('')
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Tests pour Profile Settings
|
||||
*/
|
||||
test.describe('Profile Settings', () => {
|
||||
test('devrait afficher la page Profile Settings', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/profile')
|
||||
|
||||
// Vérifier le titre de la page
|
||||
const title = await page.textContent('h1')
|
||||
expect(title).toContain('Profile')
|
||||
|
||||
// Vérifier les sections
|
||||
await expect(page.getByText(/display name/i)).toBeVisible()
|
||||
await expect(page.getByText(/email/i)).toBeVisible()
|
||||
await expect(page.getByText(/language preferences/i)).toBeVisible()
|
||||
await expect(page.getByText(/display settings/i)).toBeVisible()
|
||||
await expect(page.getByText(/change password/i)).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait avoir le sélecteur de langue', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/profile')
|
||||
|
||||
// Scroll vers la section language
|
||||
await page.getByText(/language preferences/i).scrollIntoViewIfNeeded()
|
||||
|
||||
// Vérifier que le sélecteur est présent
|
||||
const languageSelect = page.locator('#language')
|
||||
await expect(languageSelect).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait pouvoir changer la langue', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/profile')
|
||||
|
||||
// Scroll vers la section language
|
||||
await page.getByText(/language preferences/i).scrollIntoViewIfNeeded()
|
||||
|
||||
// Cliquer sur le sélecteur
|
||||
const languageSelect = page.locator('#language')
|
||||
await languageSelect.click()
|
||||
|
||||
// Sélectionner une langue (ex: français)
|
||||
await page.getByRole('option', { name: /français/i }).click()
|
||||
|
||||
// Vérifier qu'un toast de succès apparaît
|
||||
await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
|
||||
})
|
||||
|
||||
test('devrait avoir le sélecteur de taille de police', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/profile')
|
||||
|
||||
// Scroll vers la section display settings
|
||||
await page.getByText(/display settings/i).scrollIntoViewIfNeeded()
|
||||
|
||||
// Vérifier que le sélecteur est présent
|
||||
const fontSizeSelect = page.locator('#fontSize')
|
||||
await expect(fontSizeSelect).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait pouvoir changer la taille de police', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/profile')
|
||||
|
||||
// Scroll vers la section display settings
|
||||
await page.getByText(/display settings/i).scrollIntoViewIfNeeded()
|
||||
|
||||
// Cliquer sur le sélecteur
|
||||
const fontSizeSelect = page.locator('#fontSize')
|
||||
await fontSizeSelect.click()
|
||||
|
||||
// Sélectionner une taille (ex: large)
|
||||
await page.getByRole('option', { name: /large/i }).click()
|
||||
|
||||
// Vérifier qu'un toast de succès apparaît
|
||||
await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
|
||||
|
||||
// Vérifier que la taille de police a changé (vérifier la variable CSS)
|
||||
const rootFontSize = await page.evaluate(() => {
|
||||
return getComputedStyle(document.documentElement).getPropertyValue('--user-font-size')
|
||||
})
|
||||
expect(rootFontSize).toBeTruthy()
|
||||
})
|
||||
|
||||
test('devrait avoir le toggle Show Recent Notes', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/profile')
|
||||
|
||||
// Scroll vers la section display settings
|
||||
await page.getByText(/display settings/i).scrollIntoViewIfNeeded()
|
||||
|
||||
// Vérifier que le toggle est présent
|
||||
const recentNotesToggle = page.getByRole('switch', { name: /show recent notes/i })
|
||||
await expect(recentNotesToggle).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait pouvoir activer/désactiver Show Recent Notes', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/profile')
|
||||
|
||||
// Scroll vers la section display settings
|
||||
await page.getByText(/display settings/i).scrollIntoViewIfNeeded()
|
||||
|
||||
// Récupérer l'état initial du toggle
|
||||
const recentNotesToggle = page.getByRole('switch', { name: /show recent notes/i })
|
||||
const initialState = await recentNotesToggle.getAttribute('aria-checked')
|
||||
const initialEnabled = initialState === 'true'
|
||||
|
||||
// Cliquer sur le toggle
|
||||
await recentNotesToggle.click()
|
||||
|
||||
// Attendre un peu pour l'opération asynchrone
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Vérifier que l'état a changé
|
||||
const newState = await recentNotesToggle.getAttribute('aria-checked')
|
||||
const newEnabled = newState === 'true'
|
||||
expect(newEnabled).toBe(!initialEnabled)
|
||||
|
||||
// Vérifier qu'un toast de succès apparaît
|
||||
await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
|
||||
})
|
||||
|
||||
test('devrait pouvoir changer le nom d\'affichage', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/profile')
|
||||
|
||||
// Remplir le champ nom
|
||||
const nameInput = page.getByLabel(/display name/i)
|
||||
const newName = 'Test User ' + Date.now()
|
||||
await nameInput.fill(newName)
|
||||
|
||||
// Soumettre le formulaire
|
||||
await page.getByRole('button', { name: /save/i }).click()
|
||||
|
||||
// Vérifier qu'un toast de succès apparaît
|
||||
await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
|
||||
|
||||
// Recharger la page et vérifier que le nom a été sauvegardé
|
||||
await page.reload()
|
||||
await expect(nameInput).toHaveValue(newName)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Tests pour Appearance Settings
|
||||
*/
|
||||
test.describe('Appearance Settings', () => {
|
||||
test('devrait afficher la page Appearance Settings', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/appearance')
|
||||
|
||||
// Vérifier le titre de la page
|
||||
const title = await page.textContent('h1')
|
||||
expect(title).toContain('Appearance')
|
||||
|
||||
// Vérifier les sections
|
||||
await expect(page.getByText(/theme/i)).toBeVisible()
|
||||
await expect(page.getByText(/typography/i)).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait avoir le sélecteur de thème', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/appearance')
|
||||
|
||||
// Vérifier que le sélecteur est présent
|
||||
const themeSelect = page.locator('#theme')
|
||||
await expect(themeSelect).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait pouvoir changer le thème pour Light', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/appearance')
|
||||
|
||||
// Cliquer sur le sélecteur de thème
|
||||
const themeSelect = page.locator('#theme')
|
||||
await themeSelect.click()
|
||||
|
||||
// Sélectionner "Light"
|
||||
await page.getByRole('option', { name: /light/i }).click()
|
||||
|
||||
// Vérifier que le thème est appliqué immédiatement
|
||||
await expect(page.locator('html')).toHaveClass(/light/)
|
||||
await expect(page.locator('html')).not.toHaveClass(/dark/)
|
||||
|
||||
// Vérifier qu'un toast de succès apparaît
|
||||
await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
|
||||
|
||||
// Vérifier que le thème est sauvegardé dans localStorage
|
||||
const localStorageTheme = await page.evaluate(() => {
|
||||
return localStorage.getItem('theme')
|
||||
})
|
||||
expect(localStorageTheme).toBe('light')
|
||||
})
|
||||
|
||||
test('devrait pouvoir changer le thème pour Dark', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/appearance')
|
||||
|
||||
// Cliquer sur le sélecteur de thème
|
||||
const themeSelect = page.locator('#theme')
|
||||
await themeSelect.click()
|
||||
|
||||
// Sélectionner "Dark"
|
||||
await page.getByRole('option', { name: /dark/i }).click()
|
||||
|
||||
// Vérifier que le thème est appliqué immédiatement
|
||||
await expect(page.locator('html')).toHaveClass(/dark/)
|
||||
await expect(page.locator('html')).not.toHaveClass(/light/)
|
||||
|
||||
// Vérifier qu'un toast de succès apparaît
|
||||
await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
|
||||
|
||||
// Vérifier que le thème est sauvegardé dans localStorage
|
||||
const localStorageTheme = await page.evaluate(() => {
|
||||
return localStorage.getItem('theme')
|
||||
})
|
||||
expect(localStorageTheme).toBe('dark')
|
||||
})
|
||||
|
||||
test('devrait pouvoir changer le thème pour Auto', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/appearance')
|
||||
|
||||
// Cliquer sur le sélecteur de thème
|
||||
const themeSelect = page.locator('#theme')
|
||||
await themeSelect.click()
|
||||
|
||||
// Sélectionner "Auto"
|
||||
await page.getByRole('option', { name: /auto/i }).click()
|
||||
|
||||
// Vérifier qu'un toast de succès apparaît
|
||||
await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
|
||||
|
||||
// Vérifier que le thème est sauvegardé dans localStorage
|
||||
const localStorageTheme = await page.evaluate(() => {
|
||||
return localStorage.getItem('theme')
|
||||
})
|
||||
expect(localStorageTheme).toBe('auto')
|
||||
})
|
||||
|
||||
test('devrait charger le thème depuis localStorage', async ({ page }) => {
|
||||
// Définir le thème dans localStorage avant de charger la page
|
||||
await page.goto('about:blank')
|
||||
await page.evaluate(() => {
|
||||
localStorage.setItem('theme', 'dark')
|
||||
})
|
||||
|
||||
// Aller sur la page Appearance Settings
|
||||
await page.goto('http://localhost:3000/settings/appearance')
|
||||
|
||||
// Attendre que la page charge
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
// Vérifier que le thème est chargé et appliqué
|
||||
const themeSelect = page.locator('#theme')
|
||||
await expect(themeSelect).toHaveValue('dark')
|
||||
|
||||
// Vérifier que le thème est appliqué au DOM
|
||||
await expect(page.locator('html')).toHaveClass(/dark/)
|
||||
})
|
||||
|
||||
test('devrait persister le thème après rechargement de page', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/appearance')
|
||||
|
||||
// Changer le thème pour dark
|
||||
const themeSelect = page.locator('#theme')
|
||||
await themeSelect.click()
|
||||
await page.getByRole('option', { name: /dark/i }).click()
|
||||
|
||||
// Attendre que le thème soit appliqué
|
||||
await expect(page.locator('html')).toHaveClass(/dark/)
|
||||
|
||||
// Recharger la page
|
||||
await page.reload()
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
// Vérifier que le thème est toujours appliqué
|
||||
await expect(page.locator('html')).toHaveClass(/dark/)
|
||||
await expect(themeSelect).toHaveValue('dark')
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Tests d'intégration cross-pages
|
||||
*/
|
||||
test.describe('Integration Tests', () => {
|
||||
test('devrait naviguer entre les pages de settings', async ({ page }) => {
|
||||
// Commencer sur General Settings
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Cliquer sur Appearance dans la navigation
|
||||
await page.getByRole('link', { name: /appearance/i }).click()
|
||||
await expect(page).toHaveURL(/\/settings\/appearance/)
|
||||
|
||||
// Cliquer sur Profile dans la navigation
|
||||
await page.getByRole('link', { name: /profile/i }).click()
|
||||
await expect(page).toHaveURL(/\/settings\/profile/)
|
||||
|
||||
// Cliquer sur General dans la navigation
|
||||
await page.getByRole('link', { name: /general/i }).click()
|
||||
await expect(page).toHaveURL(/\/settings\/general/)
|
||||
})
|
||||
|
||||
test('devrait persister les settings entre les pages', async ({ page }) => {
|
||||
// Changer le thème sur Appearance Settings
|
||||
await page.goto('http://localhost:3000/settings/appearance')
|
||||
const themeSelect = page.locator('#theme')
|
||||
await themeSelect.click()
|
||||
await page.getByRole('option', { name: /dark/i }).click()
|
||||
await expect(page.locator('html')).toHaveClass(/dark/)
|
||||
|
||||
// Aller sur General Settings et vérifier que le thème est toujours appliqué
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
await expect(page.locator('html')).toHaveClass(/dark/)
|
||||
|
||||
// Aller sur Profile Settings et vérifier que le thème est toujours appliqué
|
||||
await page.goto('http://localhost:3000/settings/profile')
|
||||
await expect(page.locator('html')).toHaveClass(/dark/)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Tests de responsive design
|
||||
*/
|
||||
test.describe('Responsive Design', () => {
|
||||
test('devrait fonctionner sur mobile', async ({ page }) => {
|
||||
// Simuler un viewport mobile
|
||||
await page.setViewportSize({ width: 375, height: 667 })
|
||||
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Vérifier que la page est utilisable
|
||||
await expect(page.locator('h1')).toBeVisible()
|
||||
await expect(page.getByPlaceholder(/search/i)).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait fonctionner sur tablet', async ({ page }) => {
|
||||
// Simuler un viewport tablet
|
||||
await page.setViewportSize({ width: 768, height: 1024 })
|
||||
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Vérifier que la page est utilisable
|
||||
await expect(page.locator('h1')).toBeVisible()
|
||||
await expect(page.getByPlaceholder(/search/i)).toBeVisible()
|
||||
})
|
||||
|
||||
test('devrait fonctionner sur desktop', async ({ page }) => {
|
||||
// Simuler un viewport desktop
|
||||
await page.setViewportSize({ width: 1280, height: 800 })
|
||||
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
|
||||
// Vérifier que la page est utilisable
|
||||
await expect(page.locator('h1')).toBeVisible()
|
||||
await expect(page.getByPlaceholder(/search/i)).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Tests de performance
|
||||
*/
|
||||
test.describe('Performance Tests', () => {
|
||||
test('devrait charger rapidement General Settings', async ({ page }) => {
|
||||
const startTime = Date.now()
|
||||
await page.goto('http://localhost:3000/settings/general')
|
||||
await page.waitForLoadState('networkidle')
|
||||
const loadTime = Date.now() - startTime
|
||||
|
||||
// La page devrait charger en moins de 2 secondes
|
||||
expect(loadTime).toBeLessThan(2000)
|
||||
})
|
||||
|
||||
test('devrait appliquer le thème rapidement', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000/settings/appearance')
|
||||
|
||||
const themeSelect = page.locator('#theme')
|
||||
const startTime = Date.now()
|
||||
await themeSelect.click()
|
||||
await page.getByRole('option', { name: /dark/i }).click()
|
||||
await page.waitForSelector('html.dark', { timeout: 1000 })
|
||||
const applyTime = Date.now() - startTime
|
||||
|
||||
// Le thème devrait être appliqué en moins de 500ms
|
||||
expect(applyTime).toBeLessThan(500)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user