---
title: Frontend — Patterns : Tests
domain: frontend
bucket: patterns
tags: [tests, react-native, jest, styles, ui]
applies_to: [implementation, review]
severity: medium
validated_on: 2026-04-07
source_projects: [app-alexandrie, RL799_V2]
---
# Frontend — Patterns : Tests
> Extrait de la base de connaissance Lead_tech. Voir `knowledge/frontend/patterns/README.md` pour l'index complet.
---
## Pattern : Tests de styles React Native sans renderer JSX
### Synthèse
- **Objectif** : tester les tokens et styles de composants React Native dans un environnement Jest `testEnvironment: node` sans renderer JSX.
- **Contexte** : config Jest avec `transform: { '^.+\\.ts$': 'ts-jest' }` — les `.tsx` ne sont pas transformés.
- **Quand l'utiliser** : tokens de thème, logique pure, valeurs de style exportées.
- **Quand l'éviter** : rendu conditionnel (styles dynamiques inline) — nécessite `@testing-library/react-native`.
### Analyse
- **Avantages** :
- teste que le composant utilise les bons tokens, pas seulement que les tokens ont des valeurs
- détecte les régressions de style sans renderer
- rapide, aucune config Jest supplémentaire
- **Limites / vigilance** :
- ne teste pas le style calculé au runtime (style conditionnel dynamique)
### Validation
- Validé le : 19-03-2026
- Contexte technique : React Native / Jest / ts-jest — app-alexandrie story 0.2
### Implémentation
```typescript
// Button.tsx — exporter le StyleSheet avec un nom préfixé
export const buttonStyles = StyleSheet.create({
base: { borderRadius: 20, height: 57 },
primary: { backgroundColor: colors.primary },
});
export function Button(...) { ... }
// ui-components.spec.ts — importer et vérifier les tokens
import { buttonStyles } from './Button';
import { colors } from '@/theme';
it('variante primary utilise colors.primary', () => {
expect(buttonStyles.primary.backgroundColor).toBe(colors.primary);
});
```
### Deux niveaux de tests UI recommandés
1. `.spec.ts` (node) : tokens, valeurs, logique pure
2. `.spec.tsx` (config séparée avec renderer) : rendu visuel, interactions
---
## Pattern : Niveaux de test frontend Vue
### Synthèse
- **Objectif** : clarifier quand utiliser chaque niveau de test frontend Vue (structurel, composant monté, E2E).
- **Contexte** : les tests frontend du projet sont du string-matching sur le source `.vue` (`readFileSync` + `includes`). Ce pattern est rapide mais ne valide pas le comportement réel.
- **Quand l'utiliser** : à chaque choix de stratégie de test sur un composant Vue.
### Niveaux
| Niveau | Outil | Quand l'utiliser |
|--------|-------|-----------------|
| Structurel (string-matching) | `node:test` + `readFileSync` | Smoke tests : vérifier qu'un composant contient les imports, props, slots attendus. Acceptable pour MVP/sprint rapide. |
| Composant monté | `@vue/test-utils` + `vitest` | Valider le comportement interactif (toggle, emit, slots conditionnels). Obligatoire dès qu'il y a de la logique UI. |
| E2E | Playwright | Parcours critiques multi-pages. |
### Règle
Si un test vérifie un *comportement* (ex: "le menu se ferme après clic"), il doit monter le composant, pas chercher une string dans le source.
### Validation
- Validé le : 03-04-2026
- Contexte technique : Vue 3 / node:test — RL799_V2 story 6A.8
---
## Pattern : Vérifier l'ordre DOM avec `compareDocumentPosition`, pas `boundingBox`
### Synthèse
- **Objectif** : valider l'ordre réel des éléments dans le DOM, indépendamment du rendu CSS.
- **Contexte** : tests E2E Playwright qui doivent vérifier l'ordre d'affichage de sections ou d'éléments.
- **Quand l'utiliser** : toute assertion d'ordre dans un test E2E.
- **Quand l'éviter** : si on veut explicitement tester la position visuelle CSS (rare).
### Analyse
- **Avantages** :
- vérifie l'ordre DOM réel, insensible aux propriétés CSS (`flex-order`, `position`, `transform`)
- pas de `null` en retour (contrairement à `boundingBox()` hors viewport)
- déterministe
- **Limites / vigilance** :
- ne vérifie pas la position visuelle — si le test doit valider un rendu CSS spécifique, `boundingBox` reste pertinent
### Validation
- Validé le : 08-04-2026
- Contexte technique : Playwright / E2E — RL799_V2 story 17-5
### Implémentation
```ts
const aBeforeB = await page.evaluate(() => {
const a = document.querySelector('[data-testid="section-a"]');
const b = document.querySelector('[data-testid="section-b"]');
if (!a || !b) return false;
return (a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
});
expect(aBeforeB).toBe(true);
```
### Risque associé
`boundingBox().y` vérifie la position visuelle rendue par CSS, pas l'ordre dans le DOM. De plus `boundingBox()` retourne `null` pour les éléments hors viewport → crash non déterministe.
---
## Pattern : Sélecteurs E2E stables orientés intention
### Synthèse
Les tests E2E doivent cibler des sélecteurs stables (`data-testid`, role/name) et non la structure CSS/XPath.
### Analyse
Les classes et la structure DOM changent fréquemment sans régression fonctionnelle.
### Validation
- Validé le : 14-04-2026
- Contexte technique : Playwright / sélecteurs robustes — RL799_V2
- Ce pattern s'applique à Playwright/Cypress sur toutes les UIs réactives.
### Implémentation
- Préférer `data-testid` paramétré par identifiant métier stable.
- Éviter `locator.first()` si l'ordre peut muter.
- Isoler les tests mutateurs avec stratégie de remise à l'état (snapshot/restore).