569 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			569 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# Plan de tests manuels - Bookmarks
 | 
						||
 | 
						||
## Préparation
 | 
						||
 | 
						||
### Environnement
 | 
						||
 | 
						||
- [X] Installer les dépendances: `npm install`
 | 
						||
- [X] Builder l'app: `npm run build`
 | 
						||
- [X] Lancer le serveur: `node server/index.mjs`
 | 
						||
- [X] Ouvrir http://localhost:3000
 | 
						||
- [X] Ouvrir les DevTools (F12)
 | 
						||
 | 
						||
### État initial
 | 
						||
 | 
						||
- [X] Vider `.obsidian/bookmarks.json` ou le supprimer
 | 
						||
- [X] Créer quelques notes de test dans `vault/`:
 | 
						||
  - `vault/test1.md`
 | 
						||
  - `vault/folder/test2.md`
 | 
						||
  - `vault/deep/path/test3.md`
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
## Tests critiques
 | 
						||
 | 
						||
### ✅ Test 1: Basename fallback (Affichage du titre)
 | 
						||
 | 
						||
**Objectif**: Vérifier que le basename s'affiche si `title` manque.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Naviguer vers la vue Bookmarks
 | 
						||
2. Ouvrir une note (ex: `vault/folder/test2.md`)
 | 
						||
3. Cliquer sur l'icône bookmark dans la toolbar
 | 
						||
4. **NE PAS** remplir le champ "Title"
 | 
						||
5. Cliquer sur "Save"
 | 
						||
6. Observer le panneau Bookmarks
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Le bookmark affiche "test2.md" (basename uniquement)
 | 
						||
- ❌ Le bookmark n'affiche PAS "folder/test2.md" (path complet)
 | 
						||
 | 
						||
**Résultat**: ✅ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 2: Bouton Supprimer dans la modal
 | 
						||
 | 
						||
**Objectif**: Vérifier que le bouton "Delete" apparaît et fonctionne.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Ajouter un bookmark pour `test1.md`
 | 
						||
2. Fermer la modal
 | 
						||
3. Rouvrir `test1.md`
 | 
						||
4. Cliquer à nouveau sur l'icône bookmark
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ La modal affiche le bouton "Delete" (rouge, à gauche)
 | 
						||
- ✅ Le bouton "Save" est toujours présent (bleu, à droite)
 | 
						||
 | 
						||
**Étapes suite**:
 | 
						||
5. Cliquer sur "Delete"
 | 
						||
6. Confirmer la suppression
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Le bookmark disparaît du panneau
 | 
						||
- ✅ La modal se ferme
 | 
						||
- ✅ Si on rouvre la modal, le bouton "Delete" n'est plus là
 | 
						||
 | 
						||
**Résultat**: ✅ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 3: Drag vers la racine (zone "Drop here to move to root")
 | 
						||
 | 
						||
**Objectif**: Vérifier que la zone de drop racine fonctionne.
 | 
						||
 | 
						||
**Préparation**:
 | 
						||
 | 
						||
1. Créer un groupe "Test Group"
 | 
						||
2. Ajouter 2 bookmarks dans ce groupe
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Observer la zone "Drop here to move to root" en haut de la liste
 | 
						||
2. Drag un bookmark depuis le groupe
 | 
						||
3. Survoler la zone "Drop here to move to root"
 | 
						||
4. Drop dans cette zone
 | 
						||
 | 
						||
**Résultat attendu pendant le drag**:
 | 
						||
 | 
						||
- ✅ La zone change de couleur (highlight bleu)
 | 
						||
- ✅ Le texte reste visible
 | 
						||
 | 
						||
**Résultat attendu après le drop**:
 | 
						||
 | 
						||
- ✅ Le bookmark apparaît à la racine (hors du groupe)
 | 
						||
- ✅ Le groupe contient maintenant 1 seul bookmark
 | 
						||
- ✅ La modification est persistée (recharger la page pour vérifier)
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ✅ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 4: Drag entre groupes
 | 
						||
 | 
						||
**Objectif**: Vérifier le drag & drop hiérarchique entre groupes.
 | 
						||
 | 
						||
**Préparation**:
 | 
						||
 | 
						||
1. Créer 2 groupes: "Groupe A" et "Groupe B"
 | 
						||
2. Ajouter un bookmark "Item 1" dans Groupe A
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Drag "Item 1" depuis Groupe A
 | 
						||
2. Survoler Groupe B (la bordure du groupe)
 | 
						||
3. Drop dans Groupe B
 | 
						||
 | 
						||
**Résultat attendu pendant le drag**:
 | 
						||
 | 
						||
- ✅ Groupe B affiche un highlight (bordure bleue ou fond coloré)
 | 
						||
 | 
						||
**Résultat attendu après le drop**:
 | 
						||
 | 
						||
- ✅ "Item 1" est maintenant dans Groupe B
 | 
						||
- ✅ Groupe A est vide (ou affiche "Drop items here")
 | 
						||
- ✅ La modification persiste après reload
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ✅ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 5: Détection de cycles (groupe dans lui-même)
 | 
						||
 | 
						||
**Objectif**: Empêcher de créer des boucles infinies.
 | 
						||
 | 
						||
**Préparation**:
 | 
						||
 | 
						||
1. Créer Groupe A
 | 
						||
2. Créer Groupe B **dans** Groupe A
 | 
						||
3. Ajouter un bookmark dans Groupe B
 | 
						||
 | 
						||
Structure:
 | 
						||
 | 
						||
```
 | 
						||
- Groupe A
 | 
						||
  - Groupe B
 | 
						||
    - Item
 | 
						||
```
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Drag Groupe A
 | 
						||
2. Tenter de le drop dans Groupe B
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Le drop est **rejeté** (rien ne se passe)
 | 
						||
- ✅ Un warning apparaît dans la console: "Cannot move a parent into its own descendant"
 | 
						||
- ✅ La structure reste inchangée
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ✅ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 6: Réordonnancement au sein d'un conteneur
 | 
						||
 | 
						||
**Objectif**: Vérifier qu'on peut changer l'ordre des items.
 | 
						||
 | 
						||
**Préparation**:
 | 
						||
 | 
						||
1. Créer 3 bookmarks à la racine:
 | 
						||
   - Bookmark 1
 | 
						||
   - Bookmark 2
 | 
						||
   - Bookmark 3
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Drag "Bookmark 3"
 | 
						||
2. Drop entre "Bookmark 1" et "Bookmark 2"
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ L'ordre devient: Bookmark 1, Bookmark 3, Bookmark 2
 | 
						||
- ✅ Aucun groupe n'est créé par erreur
 | 
						||
- ✅ L'ordre persiste après reload
 | 
						||
 | 
						||
**Résultat**: ✅ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 7: Sauvegarde atomique et backup
 | 
						||
 | 
						||
**Objectif**: Vérifier que la sauvegarde crée un backup et est atomique.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Ajouter un bookmark
 | 
						||
2. Attendre la sauvegarde automatique (800ms)
 | 
						||
3. Naviguer vers `vault/.obsidian/`
 | 
						||
4. Vérifier les fichiers
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ `bookmarks.json` existe
 | 
						||
- ✅ `bookmarks.json.bak` existe (backup)
 | 
						||
- ✅ Les deux fichiers sont valides JSON
 | 
						||
- ✅ `bookmarks.json` contient le nouveau bookmark
 | 
						||
 | 
						||
**Test d'intégrité**:
 | 
						||
5. Corrompre manuellement `bookmarks.json` (ajouter du texte invalide)
 | 
						||
6. Renommer `bookmarks.json.bak` → `bookmarks.json`
 | 
						||
7. Recharger l'app
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ L'app charge le backup sans erreur
 | 
						||
 | 
						||
**Résultat**: ✅ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 8: Préservation de l'ordre JSON
 | 
						||
 | 
						||
**Objectif**: Vérifier que l'ordre n'est pas modifié.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Créer 3 bookmarks dans cet ordre:
 | 
						||
   - Z-bookmark.md
 | 
						||
   - A-bookmark.md
 | 
						||
   - M-bookmark.md
 | 
						||
2. Sauvegarder
 | 
						||
3. Ouvrir `vault/.obsidian/bookmarks.json`
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ L'ordre dans le JSON est identique: Z, A, M
 | 
						||
- ❌ L'ordre n'est PAS alphabétique (A, M, Z)
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 9: Groupes sans titre
 | 
						||
 | 
						||
**Objectif**: Vérifier le fallback pour les groupes.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Dans le JSON, créer manuellement un groupe sans `title`:
 | 
						||
 | 
						||
```json
 | 
						||
{
 | 
						||
  "type": "group",
 | 
						||
  "ctime": 1234567890,
 | 
						||
  "items": []
 | 
						||
}
 | 
						||
```
 | 
						||
 | 
						||
2. Recharger l'app
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Le groupe affiche "(Sans nom)"
 | 
						||
- ✅ Le groupe est toujours fonctionnel (on peut y ajouter des items)
 | 
						||
 | 
						||
**Résultat**: ✅ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 10: Fichiers avec path complexe
 | 
						||
 | 
						||
**Objectif**: Tester le basename avec différents formats.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Créer des bookmarks sans title pour:
 | 
						||
   - `simple.md`
 | 
						||
   - `folder/nested.md`
 | 
						||
   - `deep/very/long/path/document.md`
 | 
						||
   - `path with spaces/file.md`
 | 
						||
   - `accents/éléphant.md`
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ "simple.md" affiche "simple.md"
 | 
						||
- ✅ "folder/nested.md" affiche "nested.md"
 | 
						||
- ✅ "deep/very/long/path/document.md" affiche "document.md"
 | 
						||
- ✅ "path with spaces/file.md" affiche "file.md"
 | 
						||
- ✅ "accents/éléphant.md" affiche "éléphant.md"
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 11: Suppression d'un path présent plusieurs fois
 | 
						||
 | 
						||
**Objectif**: `removePathEverywhere()` doit retirer toutes les occurrences.
 | 
						||
 | 
						||
**Préparation**:
 | 
						||
 | 
						||
1. Ajouter manuellement le même path dans 2 groupes différents:
 | 
						||
 | 
						||
```json
 | 
						||
{
 | 
						||
  "items": [
 | 
						||
    {
 | 
						||
      "type": "group",
 | 
						||
      "ctime": 1,
 | 
						||
      "title": "Group A",
 | 
						||
      "items": [
 | 
						||
        { "type": "file", "ctime": 10, "path": "test.md" }
 | 
						||
      ]
 | 
						||
    },
 | 
						||
    {
 | 
						||
      "type": "group",
 | 
						||
      "ctime": 2,
 | 
						||
      "title": "Group B",
 | 
						||
      "items": [
 | 
						||
        { "type": "file", "ctime": 20, "path": "test.md" }
 | 
						||
      ]
 | 
						||
    }
 | 
						||
  ]
 | 
						||
}
 | 
						||
```
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Ouvrir `test.md`
 | 
						||
2. Ouvrir la modal bookmark
 | 
						||
3. Cliquer sur "Delete"
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Le bookmark disparaît de Group A
 | 
						||
- ✅ Le bookmark disparaît de Group B
 | 
						||
- ✅ Les deux groupes sont maintenant vides
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 12: Responsive (Desktop vs Mobile)
 | 
						||
 | 
						||
**Objectif**: Vérifier l'adaptabilité.
 | 
						||
 | 
						||
**Desktop (>1024px)**:
 | 
						||
 | 
						||
1. Ouvrir l'app en plein écran
 | 
						||
2. Naviguer vers Bookmarks
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Panel latéral visible (fixe)
 | 
						||
- ✅ Largeur ~320-400px
 | 
						||
- ✅ Barre de recherche visible
 | 
						||
- ✅ Boutons d'action visibles
 | 
						||
 | 
						||
**Mobile (<1024px)**:
 | 
						||
 | 
						||
1. Réduire la fenêtre ou utiliser DevTools mode mobile
 | 
						||
2. Naviguer vers Bookmarks
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Panel en plein écran (drawer)
 | 
						||
- ✅ Navigation facile (pas de scroll horizontal)
 | 
						||
- ✅ Boutons assez grands pour le tactile (≥44px)
 | 
						||
 | 
						||
**Résultat**: ✅ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 13: Thème dark/light
 | 
						||
 | 
						||
**Objectif**: Vérifier le respect des thèmes.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Basculer en mode dark (si disponible)
 | 
						||
2. Observer le panneau Bookmarks
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Fond sombre (`bg-gray-900`)
 | 
						||
- ✅ Texte clair (`text-gray-100`)
 | 
						||
- ✅ Bordures visibles
 | 
						||
- ✅ Contraste suffisant (lisible)
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
3. Basculer en mode light
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Fond clair (`bg-white`)
 | 
						||
- ✅ Texte sombre (`text-gray-900`)
 | 
						||
- ✅ Pas de vestiges du mode dark
 | 
						||
 | 
						||
**Résultat**: ✅ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 14: Validation JSON (données corrompues)
 | 
						||
 | 
						||
**Objectif**: Vérifier que l'app ne crash pas avec un JSON invalide.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Modifier `bookmarks.json` pour le corrompre:
 | 
						||
 | 
						||
```json
 | 
						||
{
 | 
						||
  "items": [
 | 
						||
    {
 | 
						||
      "type": "invalid-type",
 | 
						||
      "ctime": "not-a-number"
 | 
						||
    }
 | 
						||
  ]
 | 
						||
}
 | 
						||
```
 | 
						||
 | 
						||
2. Recharger l'app
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Un message d'erreur clair s'affiche
 | 
						||
- ✅ L'app ne crash pas
 | 
						||
- ✅ On peut créer un nouveau bookmark (qui réinitialise le fichier)
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ✅ Test 15: Auto-save (debounce)
 | 
						||
 | 
						||
**Objectif**: Vérifier que l'auto-save fonctionne.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Ajouter un bookmark
 | 
						||
2. Observer le panneau (indicateur "Saving...")
 | 
						||
3. Attendre 800ms
 | 
						||
4. Vérifier que le fichier a été écrit
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ "Saving..." apparaît brièvement
 | 
						||
- ✅ Après 800ms, le fichier est mis à jour
 | 
						||
- ✅ `isDirty` passe à `false`
 | 
						||
 | 
						||
**Test de debounce**:
 | 
						||
5. Faire 3 modifications rapides (<800ms entre chaque)
 | 
						||
6. Attendre 800ms après la dernière
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Une seule sauvegarde est déclenchée (pas 3)
 | 
						||
- ✅ Le fichier final contient toutes les modifications
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
## Tests de régression
 | 
						||
 | 
						||
### ⚠️ Test R1: Compatibilité Obsidian
 | 
						||
 | 
						||
**Objectif**: S'assurer qu'Obsidian peut lire le fichier généré.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Créer plusieurs bookmarks dans ObsiViewer
 | 
						||
2. Ouvrir la vault dans Obsidian
 | 
						||
3. Ouvrir le panneau Bookmarks dans Obsidian
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Tous les bookmarks sont visibles
 | 
						||
- ✅ La hiérarchie est respectée
 | 
						||
- ✅ Les titres sont corrects
 | 
						||
- ✅ Cliquer sur un bookmark ouvre le bon fichier
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ⚠️ Test R2: Modifications depuis Obsidian
 | 
						||
 | 
						||
**Objectif**: Vérifier la bidirectionnalité.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Dans Obsidian, créer un nouveau bookmark
 | 
						||
2. Ajouter un groupe et y placer le bookmark
 | 
						||
3. Sauvegarder dans Obsidian
 | 
						||
4. Recharger ObsiViewer
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ Le nouveau bookmark apparaît
 | 
						||
- ✅ Le groupe est visible
 | 
						||
- ✅ Pas de corruption de données
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
### ⚠️ Test R3: Champs inconnus préservés
 | 
						||
 | 
						||
**Objectif**: Ne pas perdre les extensions Obsidian.
 | 
						||
 | 
						||
**Étapes**:
 | 
						||
 | 
						||
1. Ajouter manuellement dans `bookmarks.json`:
 | 
						||
 | 
						||
```json
 | 
						||
{
 | 
						||
  "type": "file",
 | 
						||
  "ctime": 123,
 | 
						||
  "path": "test.md",
 | 
						||
  "color": "#ff0000",
 | 
						||
  "icon": "star"
 | 
						||
}
 | 
						||
```
 | 
						||
 | 
						||
2. Charger dans ObsiViewer
 | 
						||
3. Modifier le titre du bookmark
 | 
						||
4. Sauvegarder
 | 
						||
5. Vérifier le JSON
 | 
						||
 | 
						||
**Résultat attendu**:
 | 
						||
 | 
						||
- ✅ `color` et `icon` sont toujours présents
 | 
						||
- ✅ Seul `title` a été modifié
 | 
						||
 | 
						||
**Résultat**: ⬜ PASS / ⬜ FAIL
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
## Récapitulatif
 | 
						||
 | 
						||
### Statistiques
 | 
						||
 | 
						||
- Tests critiques: **15**
 | 
						||
- Tests de régression: **3**
 | 
						||
- **Total**: **18 tests**
 | 
						||
 | 
						||
### Résultats
 | 
						||
 | 
						||
- ✅ PASS: ___ / 18
 | 
						||
- ❌ FAIL: ___ / 18
 | 
						||
- ⏭️ SKIP: ___ / 18
 | 
						||
 | 
						||
### Notes
 | 
						||
 | 
						||
_Ajouter ici toute observation, bug trouvé, ou amélioration suggérée._
 | 
						||
 | 
						||
---
 | 
						||
 | 
						||
**Date du test**: ___________
 | 
						||
**Testeur**: ___________
 | 
						||
**Version**: 2.0.0
 | 
						||
**Environnement**: Node v___ / Browser ___________
 |