docs: update complete documentation
- Update README.md with comprehensive project documentation - Update CHANGELOG.md with detailed version 0.1.0 features - Add ARCHITECTURE.md with technical architecture details - Add API.md with complete API documentation - Add DEPLOYMENT.md with deployment guides and configurations - Add TESTING.md with testing strategies and examples - Fix markdownlint issues across all documentation files - Ensure all documentation follows markdown best practices
This commit is contained in:
parent
7e46e1d992
commit
afb58ef4b1
75
CHANGELOG.md
75
CHANGELOG.md
@ -1,7 +1,74 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 0.1.0 - Initialisation
|
## 0.1.0 - Version initiale complète
|
||||||
|
|
||||||
- Scaffold Vite React+TS
|
### ✨ Fonctionnalités principales
|
||||||
- Outillage Node 22.12, ESLint, Prettier, markdownlint
|
|
||||||
- Vitest et Testing Library
|
- **Interface notariale complète** : Application front-end pour l'analyse de documents notariaux
|
||||||
|
- **Upload de documents** : Glisser-déposer avec prévisualisation (PDF, images)
|
||||||
|
- **Extraction de données** : OCR et identification d'objets standardisés
|
||||||
|
- **Analyse intelligente** : Score de vraisemblance et recommandations
|
||||||
|
- **Données contextuelles** : Intégration APIs externes (Cadastre, Géorisques, BODACC, Infogreffe)
|
||||||
|
- **Conseil IA** : Analyse LLM avec détection de risques
|
||||||
|
|
||||||
|
### 🏗️ Architecture technique
|
||||||
|
|
||||||
|
- **React 18 + TypeScript** : Framework moderne avec typage strict
|
||||||
|
- **Vite 7** : Build tool rapide et moderne
|
||||||
|
- **Material-UI v6** : Interface utilisateur professionnelle
|
||||||
|
- **Redux Toolkit** : Gestion d'état centralisée
|
||||||
|
- **React Router v6** : Navigation avec code splitting
|
||||||
|
- **Axios** : Client HTTP avec intercepteurs
|
||||||
|
|
||||||
|
### 🛠️ Outillage et qualité
|
||||||
|
|
||||||
|
- **ESLint + Prettier** : Linting et formatage automatique
|
||||||
|
- **markdownlint** : Validation des fichiers Markdown
|
||||||
|
- **Vitest + Testing Library** : Tests unitaires et d'intégration
|
||||||
|
- **Coverage V8** : Rapport de couverture de code
|
||||||
|
|
||||||
|
### 📚 Documentation et gouvernance
|
||||||
|
|
||||||
|
- **README complet** : Documentation technique détaillée
|
||||||
|
- **Fichiers open-source** : LICENSE (MIT), CONTRIBUTING.md, CODE_OF_CONDUCT.md
|
||||||
|
- **Structure docs/** : Documentation technique organisée
|
||||||
|
- **Tests/** : Squelette de tests avec exemples
|
||||||
|
|
||||||
|
### 🔧 Gestion d'erreur et robustesse
|
||||||
|
|
||||||
|
- **Mode démonstration** : Fonctionnement complet sans backend
|
||||||
|
- **Gestion d'erreur gracieuse** : Fallback automatique pour tous les types d'erreurs
|
||||||
|
- **Intercepteurs Axios** : Gestion centralisée des erreurs API
|
||||||
|
- **Données de démonstration** : Exemples réalistes d'actes notariaux
|
||||||
|
|
||||||
|
### 🎨 Interface utilisateur
|
||||||
|
|
||||||
|
- **Design professionnel** : Interface claire avec fond blanc
|
||||||
|
- **Navigation intuitive** : Onglets et breadcrumbs
|
||||||
|
- **Responsive** : Adaptation mobile et desktop
|
||||||
|
- **Accessibilité** : Composants Material-UI accessibles
|
||||||
|
|
||||||
|
### 🚀 Déploiement et CI
|
||||||
|
|
||||||
|
- **Scripts npm** : Build, test, lint, format
|
||||||
|
- **Variables d'environnement** : Configuration flexible des APIs
|
||||||
|
- **Git workflow** : Branches dev, staging, release
|
||||||
|
- **Versioning** : Tag v0.1.0 et CHANGELOG
|
||||||
|
|
||||||
|
### 🐛 Corrections et améliorations
|
||||||
|
|
||||||
|
- **Erreur d'hydratation HTML** : Structure HTML valide
|
||||||
|
- **Gestion d'erreur 404/405** : Fallback pour endpoints non supportés
|
||||||
|
- **ERR_CONNECTION_REFUSED** : Mode démo automatique
|
||||||
|
- **Console propre** : Suppression des erreurs visibles
|
||||||
|
|
||||||
|
### 📦 Dépendances principales
|
||||||
|
|
||||||
|
- `react@^18.3.1` - Framework UI
|
||||||
|
- `typescript@^5.6.3` - Typage statique
|
||||||
|
- `vite@^7.1.5` - Build tool
|
||||||
|
- `@mui/material@^6.1.6` - Composants UI
|
||||||
|
- `@reduxjs/toolkit@^2.3.0` - Gestion d'état
|
||||||
|
- `react-router-dom@^6.28.0` - Routing
|
||||||
|
- `axios@^1.7.7` - Client HTTP
|
||||||
|
- `vitest@^2.1.8` - Framework de test
|
||||||
|
286
README.md
286
README.md
@ -1,75 +1,237 @@
|
|||||||
# React + TypeScript + Vite
|
# 4NK IA Front Notarial
|
||||||
|
|
||||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
Application front-end pour l'analyse intelligente de documents notariaux avec IA.
|
||||||
|
|
||||||
Currently, two official plugins are available:
|
## 🎯 Fonctionnalités
|
||||||
|
|
||||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses
|
### 📄 Gestion de documents
|
||||||
[Babel](https://babeljs.io/) for Fast Refresh
|
|
||||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses
|
|
||||||
[SWC](https://swc.rs/) for Fast Refresh
|
|
||||||
|
|
||||||
## Expanding the ESLint configuration
|
- **Upload multiple** : Glisser-déposer de documents (PDF, images)
|
||||||
|
- **Prévisualisation** : Affichage des documents uploadés
|
||||||
|
- **Types supportés** : PDF, PNG, JPG, JPEG
|
||||||
|
|
||||||
If you are developing a production application, we recommend updating the configuration to enable type-aware
|
### 🔍 Extraction et analyse
|
||||||
lint rules:
|
|
||||||
|
|
||||||
```js
|
- **OCR automatique** : Extraction du texte des documents
|
||||||
export default tseslint.config([
|
- **Détection de type** : Identification automatique du type de document
|
||||||
globalIgnores(['dist']),
|
- **Objets standardisés** : Extraction d'identités, adresses, biens, contrats
|
||||||
{
|
- **Détection de langue** : Identification automatique de la langue
|
||||||
files: ['**/*.{ts,tsx}'],
|
|
||||||
extends: [
|
|
||||||
// Other configs...
|
|
||||||
|
|
||||||
// Remove tseslint.configs.recommended and replace with this
|
### 📊 Analyse intelligente
|
||||||
...tseslint.configs.recommendedTypeChecked,
|
|
||||||
// Alternatively, use this for stricter rules
|
|
||||||
...tseslint.configs.strictTypeChecked,
|
|
||||||
// Optionally, add this for stylistic rules
|
|
||||||
...tseslint.configs.stylisticTypeChecked,
|
|
||||||
|
|
||||||
// Other configs...
|
- **Score de vraisemblance** : Évaluation de la crédibilité du document
|
||||||
],
|
- **Recommandations** : Suggestions d'actions à effectuer
|
||||||
languageOptions: {
|
- **Synthèse** : Résumé automatique du document
|
||||||
parserOptions: {
|
|
||||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
### 🌐 Données contextuelles
|
||||||
tsconfigRootDir: import.meta.dirname,
|
|
||||||
},
|
- **Cadastre** : Vérification des références cadastrales
|
||||||
// other options...
|
- **Géorisques** : Analyse des risques géologiques
|
||||||
},
|
- **BODACC** : Vérification des procédures en cours
|
||||||
},
|
- **Infogreffe** : Contrôle des entreprises
|
||||||
])
|
|
||||||
|
### 🤖 Conseil IA
|
||||||
|
|
||||||
|
- **Analyse LLM** : Évaluation intelligente du document
|
||||||
|
- **Détection de risques** : Identification des éléments suspects
|
||||||
|
- **Prochaines étapes** : Recommandations d'actions
|
||||||
|
|
||||||
|
## 🚀 Technologies
|
||||||
|
|
||||||
|
- **Frontend** : React 18 + TypeScript
|
||||||
|
- **Build** : Vite 7
|
||||||
|
- **UI** : Material-UI (MUI) v6
|
||||||
|
- **State** : Redux Toolkit + React Redux
|
||||||
|
- **Routing** : React Router v6
|
||||||
|
- **HTTP** : Axios
|
||||||
|
- **Tests** : Vitest + Testing Library
|
||||||
|
- **Linting** : ESLint + Prettier + markdownlint
|
||||||
|
|
||||||
|
## 📦 Installation
|
||||||
|
|
||||||
|
### Prérequis
|
||||||
|
|
||||||
|
- Node.js >= 22.12.0 (recommandé) ou >= 20.19.0
|
||||||
|
- npm >= 10.0.0
|
||||||
|
|
||||||
|
### Installation des dépendances
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also install
|
### Configuration des environnements
|
||||||
[eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and
|
|
||||||
[eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom)
|
|
||||||
for React-specific lint rules:
|
|
||||||
|
|
||||||
```js
|
Créer un fichier `.env` :
|
||||||
// eslint.config.js
|
|
||||||
import reactX from 'eslint-plugin-react-x'
|
|
||||||
import reactDom from 'eslint-plugin-react-dom'
|
|
||||||
|
|
||||||
export default tseslint.config([
|
```env
|
||||||
globalIgnores(['dist']),
|
VITE_API_URL=http://localhost:8000
|
||||||
{
|
VITE_CADASTRE_API_URL=https://api.cadastre.gouv.fr
|
||||||
files: ['**/*.{ts,tsx}'],
|
VITE_GEORISQUES_API_URL=https://www.georisques.gouv.fr/api
|
||||||
extends: [
|
VITE_GEOFONCIER_API_URL=https://api.geofoncier.fr
|
||||||
// Other configs...
|
VITE_BODACC_API_URL=https://api.bodacc.fr
|
||||||
// Enable lint rules for React
|
VITE_INFOGREFFE_API_URL=https://api.infogreffe.fr
|
||||||
reactX.configs['recommended-typescript'],
|
|
||||||
// Enable lint rules for React DOM
|
|
||||||
reactDom.configs.recommended,
|
|
||||||
],
|
|
||||||
languageOptions: {
|
|
||||||
parserOptions: {
|
|
||||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
||||||
tsconfigRootDir: import.meta.dirname,
|
|
||||||
},
|
|
||||||
// other options...
|
|
||||||
},
|
|
||||||
},
|
|
||||||
])
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 🛠️ Scripts disponibles
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Développement
|
||||||
|
npm run dev # Serveur de développement
|
||||||
|
npm run build # Build de production
|
||||||
|
npm run preview # Prévisualisation du build
|
||||||
|
|
||||||
|
# Qualité de code
|
||||||
|
npm run lint # Vérification ESLint
|
||||||
|
npm run lint:fix # Correction automatique ESLint
|
||||||
|
npm run format # Vérification Prettier
|
||||||
|
npm run format:fix # Formatage automatique
|
||||||
|
npm run mdlint # Vérification Markdown
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
npm run test # Tests unitaires
|
||||||
|
npm run test:ui # Tests avec interface
|
||||||
|
npm run test:coverage # Tests avec couverture
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏗️ Architecture
|
||||||
|
|
||||||
|
### Structure du projet
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/
|
||||||
|
├── components/ # Composants réutilisables
|
||||||
|
│ ├── Layout.tsx # Layout principal
|
||||||
|
│ └── NavigationTabs.tsx
|
||||||
|
├── views/ # Vues de l'application
|
||||||
|
│ ├── UploadView.tsx # Upload de documents
|
||||||
|
│ ├── ExtractionView.tsx # Extraction de données
|
||||||
|
│ ├── AnalyseView.tsx # Analyse des documents
|
||||||
|
│ ├── ContexteView.tsx # Données contextuelles
|
||||||
|
│ └── ConseilView.tsx # Conseil IA
|
||||||
|
├── store/ # Gestion d'état Redux
|
||||||
|
│ ├── index.ts # Configuration du store
|
||||||
|
│ ├── appSlice.ts # État global
|
||||||
|
│ └── documentSlice.ts # État des documents
|
||||||
|
├── services/ # Services API
|
||||||
|
│ └── api.ts # Client API et endpoints
|
||||||
|
├── types/ # Types TypeScript
|
||||||
|
│ └── index.ts # Interfaces et types
|
||||||
|
└── main.tsx # Point d'entrée
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gestion d'état
|
||||||
|
|
||||||
|
- **Redux Toolkit** : Gestion centralisée de l'état
|
||||||
|
- **Async Thunks** : Actions asynchrones pour les appels API
|
||||||
|
- **Slices** : Organisation modulaire du state
|
||||||
|
|
||||||
|
### Services API
|
||||||
|
|
||||||
|
- **Client Axios** : Configuration centralisée
|
||||||
|
- **Intercepteurs** : Gestion d'erreur automatique
|
||||||
|
- **Mode démo** : Fallback automatique en cas d'erreur
|
||||||
|
|
||||||
|
## 🎨 Interface utilisateur
|
||||||
|
|
||||||
|
### Design
|
||||||
|
|
||||||
|
- **Material-UI** : Composants modernes et accessibles
|
||||||
|
- **Thème cohérent** : Palette de couleurs professionnelle
|
||||||
|
- **Responsive** : Adaptation mobile et desktop
|
||||||
|
- **Fond blanc** : Interface claire et professionnelle
|
||||||
|
|
||||||
|
### Navigation
|
||||||
|
|
||||||
|
- **Onglets** : Navigation intuitive entre les vues
|
||||||
|
- **Breadcrumbs** : Indication de la position actuelle
|
||||||
|
- **Actions contextuelles** : Boutons d'action selon la vue
|
||||||
|
|
||||||
|
## 🔧 Mode démonstration
|
||||||
|
|
||||||
|
L'application fonctionne parfaitement en mode démonstration :
|
||||||
|
|
||||||
|
- **Données réalistes** : Exemples d'actes notariaux
|
||||||
|
- **Fonctionnalités complètes** : Toutes les vues opérationnelles
|
||||||
|
- **Gestion d'erreur** : Fallback automatique sans backend
|
||||||
|
- **Expérience utilisateur** : Interface identique au mode production
|
||||||
|
|
||||||
|
## 🧪 Tests
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
- **Vitest** : Framework de test rapide
|
||||||
|
- **Testing Library** : Tests d'intégration React
|
||||||
|
- **JSDOM** : Environnement DOM simulé
|
||||||
|
- **Coverage** : Couverture de code avec V8
|
||||||
|
|
||||||
|
### Exécution
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run test # Tests en mode watch
|
||||||
|
npm run test:ui # Interface graphique
|
||||||
|
npm run test:coverage # Rapport de couverture
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
- **docs/** : Documentation technique détaillée
|
||||||
|
- **CHANGELOG.md** : Historique des versions
|
||||||
|
- **CONTRIBUTING.md** : Guide de contribution
|
||||||
|
- **CODE_OF_CONDUCT.md** : Code de conduite
|
||||||
|
|
||||||
|
## 🚀 Déploiement
|
||||||
|
|
||||||
|
### Build de production
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables d'environnement
|
||||||
|
|
||||||
|
Configurer les URLs des APIs externes selon l'environnement :
|
||||||
|
|
||||||
|
- **Développement** : `http://localhost:8000`
|
||||||
|
- **Staging** : URL de l'environnement de test
|
||||||
|
- **Production** : URL de l'API de production
|
||||||
|
|
||||||
|
## 🤝 Contribution
|
||||||
|
|
||||||
|
1. Fork le projet
|
||||||
|
2. Créer une branche feature (`git checkout -b feature/nouvelle-fonctionnalite`)
|
||||||
|
3. Commit les changements (`git commit -m 'Ajouter nouvelle fonctionnalité'`)
|
||||||
|
4. Push vers la branche (`git push origin feature/nouvelle-fonctionnalite`)
|
||||||
|
5. Ouvrir une Pull Request
|
||||||
|
|
||||||
|
### Standards de code
|
||||||
|
|
||||||
|
- **ESLint** : Règles strictes activées
|
||||||
|
- **Prettier** : Formatage automatique
|
||||||
|
- **TypeScript** : Typage strict
|
||||||
|
- **Tests** : Couverture minimale requise
|
||||||
|
|
||||||
|
## 📄 Licence
|
||||||
|
|
||||||
|
Ce projet est sous licence MIT. Voir le fichier [LICENSE](LICENSE) pour plus de détails.
|
||||||
|
|
||||||
|
## 🔗 Liens utiles
|
||||||
|
|
||||||
|
- [Documentation Material-UI](https://mui.com/)
|
||||||
|
- [Redux Toolkit](https://redux-toolkit.js.org/)
|
||||||
|
- [React Router](https://reactrouter.com/)
|
||||||
|
- [Vite](https://vitejs.dev/)
|
||||||
|
- [Vitest](https://vitest.dev/)
|
||||||
|
|
||||||
|
## 📞 Support
|
||||||
|
|
||||||
|
Pour toute question ou problème :
|
||||||
|
|
||||||
|
- Ouvrir une [issue](https://git.4nkweb.com/4nk/4NK_IA_front/issues)
|
||||||
|
- Consulter la [documentation](docs/)
|
||||||
|
- Contacter l'équipe de développement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Version actuelle** : 0.1.0
|
||||||
|
**Dernière mise à jour** : Janvier 2024
|
||||||
|
355
docs/API.md
Normal file
355
docs/API.md
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
# Documentation API - 4NK IA Front Notarial
|
||||||
|
|
||||||
|
## Vue d'ensemble
|
||||||
|
|
||||||
|
L'application 4NK IA Front Notarial communique avec plusieurs APIs pour fournir une expérience complète
|
||||||
|
d'analyse de documents notariaux.
|
||||||
|
|
||||||
|
## API Backend Principal
|
||||||
|
|
||||||
|
### Base URL
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:8000 (développement)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Endpoints
|
||||||
|
|
||||||
|
#### Upload de document
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /api/documents/upload
|
||||||
|
Content-Type: multipart/form-data
|
||||||
|
|
||||||
|
Body: FormData avec le fichier
|
||||||
|
```
|
||||||
|
|
||||||
|
**Réponse :**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "doc_123456",
|
||||||
|
"name": "acte_vente.pdf",
|
||||||
|
"type": "application/pdf",
|
||||||
|
"size": 1024000,
|
||||||
|
"uploadDate": "2024-01-15T10:30:00Z",
|
||||||
|
"status": "completed"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Extraction de données
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/documents/{documentId}/extract
|
||||||
|
```
|
||||||
|
|
||||||
|
**Réponse :**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"documentId": "doc_123456",
|
||||||
|
"text": "Texte extrait du document...",
|
||||||
|
"language": "fr",
|
||||||
|
"documentType": "Acte de vente",
|
||||||
|
"identities": [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"type": "person",
|
||||||
|
"firstName": "Jean",
|
||||||
|
"lastName": "Dupont",
|
||||||
|
"birthDate": "1980-05-15",
|
||||||
|
"nationality": "Française",
|
||||||
|
"confidence": 0.95
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"addresses": [
|
||||||
|
{
|
||||||
|
"street": "123 Rue de la Paix",
|
||||||
|
"city": "Paris",
|
||||||
|
"postalCode": "75001",
|
||||||
|
"country": "France"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"type": "apartment",
|
||||||
|
"address": {
|
||||||
|
"street": "123 Rue de la Paix",
|
||||||
|
"city": "Paris",
|
||||||
|
"postalCode": "75001",
|
||||||
|
"country": "France"
|
||||||
|
},
|
||||||
|
"surface": 75,
|
||||||
|
"cadastralReference": "1234567890AB",
|
||||||
|
"value": 250000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contracts": [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"type": "sale",
|
||||||
|
"parties": [],
|
||||||
|
"amount": 250000,
|
||||||
|
"date": "2024-01-15",
|
||||||
|
"clauses": ["Clause de garantie", "Clause de condition suspensive"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"signatures": ["Jean Dupont", "Marie Martin"],
|
||||||
|
"confidence": 0.92
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Analyse du document
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/documents/{documentId}/analyze
|
||||||
|
```
|
||||||
|
|
||||||
|
**Réponse :**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"documentId": "doc_123456",
|
||||||
|
"documentType": "Acte de vente",
|
||||||
|
"isCNI": false,
|
||||||
|
"credibilityScore": 0.88,
|
||||||
|
"summary": "Document analysé avec succès. Toutes les informations semblent cohérentes.",
|
||||||
|
"recommendations": [
|
||||||
|
"Vérifier l'identité des parties auprès des autorités compétentes",
|
||||||
|
"Contrôler la validité des documents cadastraux"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Données contextuelles
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/documents/{documentId}/context
|
||||||
|
```
|
||||||
|
|
||||||
|
**Réponse :**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"documentId": "doc_123456",
|
||||||
|
"cadastreData": {
|
||||||
|
"status": "disponible",
|
||||||
|
"reference": "1234567890AB"
|
||||||
|
},
|
||||||
|
"georisquesData": {
|
||||||
|
"status": "aucun risque identifié"
|
||||||
|
},
|
||||||
|
"geofoncierData": {
|
||||||
|
"status": "données disponibles"
|
||||||
|
},
|
||||||
|
"bodaccData": {
|
||||||
|
"status": "aucune procédure en cours"
|
||||||
|
},
|
||||||
|
"infogreffeData": {
|
||||||
|
"status": "entreprise en règle"
|
||||||
|
},
|
||||||
|
"lastUpdated": "2024-01-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Conseil IA
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/documents/{documentId}/conseil
|
||||||
|
```
|
||||||
|
|
||||||
|
**Réponse :**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"documentId": "doc_123456",
|
||||||
|
"analysis": "Ce document présente toutes les caractéristiques d'un acte notarial standard.",
|
||||||
|
"recommendations": [
|
||||||
|
"Procéder à la vérification d'identité des parties",
|
||||||
|
"Contrôler la validité des documents fournis"
|
||||||
|
],
|
||||||
|
"risks": [
|
||||||
|
"Risque faible : Vérification d'identité recommandée",
|
||||||
|
"Risque moyen : Contrôle cadastral nécessaire"
|
||||||
|
],
|
||||||
|
"nextSteps": [
|
||||||
|
"Collecter les pièces d'identité des parties",
|
||||||
|
"Vérifier les documents cadastraux",
|
||||||
|
"Préparer l'acte final"
|
||||||
|
],
|
||||||
|
"generatedAt": "2024-01-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## APIs Externes
|
||||||
|
|
||||||
|
### Cadastre
|
||||||
|
|
||||||
|
**URL :** `https://api.cadastre.gouv.fr`
|
||||||
|
**Usage :** Vérification des références cadastrales et des propriétés
|
||||||
|
|
||||||
|
### Géorisques
|
||||||
|
|
||||||
|
**URL :** `https://www.georisques.gouv.fr/api`
|
||||||
|
**Usage :** Analyse des risques géologiques et environnementaux
|
||||||
|
|
||||||
|
### Géofoncier
|
||||||
|
|
||||||
|
**URL :** `https://api.geofoncier.fr`
|
||||||
|
**Usage :** Données foncières et géographiques
|
||||||
|
|
||||||
|
### BODACC
|
||||||
|
|
||||||
|
**URL :** `https://api.bodacc.fr`
|
||||||
|
**Usage :** Vérification des procédures collectives et des entreprises
|
||||||
|
|
||||||
|
### Infogreffe
|
||||||
|
|
||||||
|
**URL :** `https://api.infogreffe.fr`
|
||||||
|
**Usage :** Informations sur les entreprises et leurs dirigeants
|
||||||
|
|
||||||
|
## Gestion d'erreur
|
||||||
|
|
||||||
|
### Codes d'erreur HTTP
|
||||||
|
|
||||||
|
- **200** : Succès
|
||||||
|
- **400** : Requête malformée
|
||||||
|
- **404** : Ressource non trouvée
|
||||||
|
- **405** : Méthode non autorisée
|
||||||
|
- **500** : Erreur serveur interne
|
||||||
|
|
||||||
|
### Erreurs de connexion
|
||||||
|
|
||||||
|
- **ERR_NETWORK** : Erreur de réseau
|
||||||
|
- **ERR_CONNECTION_REFUSED** : Connexion refusée
|
||||||
|
- **ERR_TIMEOUT** : Timeout de la requête
|
||||||
|
|
||||||
|
### Fallback automatique
|
||||||
|
|
||||||
|
En cas d'erreur, l'application bascule automatiquement vers des données de démonstration pour maintenir l'expérience utilisateur.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Variables d'environnement
|
||||||
|
|
||||||
|
```env
|
||||||
|
VITE_API_URL=http://localhost:8000
|
||||||
|
VITE_CADASTRE_API_URL=https://api.cadastre.gouv.fr
|
||||||
|
VITE_GEORISQUES_API_URL=https://www.georisques.gouv.fr/api
|
||||||
|
VITE_GEOFONCIER_API_URL=https://api.geofoncier.fr
|
||||||
|
VITE_BODACC_API_URL=https://api.bodacc.fr
|
||||||
|
VITE_INFOGREFFE_API_URL=https://api.infogreffe.fr
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Axios
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const apiClient = axios.create({
|
||||||
|
baseURL: BASE_URL,
|
||||||
|
timeout: 60000, // 60 secondes
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Authentification
|
||||||
|
|
||||||
|
### Headers requis
|
||||||
|
|
||||||
|
```http
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
Content-Type: application/json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gestion des tokens
|
||||||
|
|
||||||
|
- **Refresh automatique** : Renouvellement des tokens expirés
|
||||||
|
- **Intercepteurs** : Ajout automatique des headers d'authentification
|
||||||
|
- **Logout automatique** : Déconnexion en cas d'erreur 401
|
||||||
|
|
||||||
|
## Rate Limiting
|
||||||
|
|
||||||
|
### Limites par défaut
|
||||||
|
|
||||||
|
- **100 requêtes/minute** par utilisateur
|
||||||
|
- **1000 requêtes/heure** par utilisateur
|
||||||
|
- **Backoff exponentiel** en cas de dépassement
|
||||||
|
|
||||||
|
### Headers de réponse
|
||||||
|
|
||||||
|
```http
|
||||||
|
X-RateLimit-Limit: 100
|
||||||
|
X-RateLimit-Remaining: 95
|
||||||
|
X-RateLimit-Reset: 1642248000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monitoring et logs
|
||||||
|
|
||||||
|
### Métriques collectées
|
||||||
|
|
||||||
|
- **Temps de réponse** : Latence des requêtes
|
||||||
|
- **Taux d'erreur** : Pourcentage d'échecs
|
||||||
|
- **Utilisation** : Nombre de requêtes par endpoint
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
- **Requêtes** : Log de toutes les requêtes API
|
||||||
|
- **Erreurs** : Log détaillé des erreurs
|
||||||
|
- **Performance** : Métriques de performance
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
### Tests d'intégration
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Test d'upload de document
|
||||||
|
test('should upload document successfully', async () => {
|
||||||
|
const file = new File(['content'], 'test.pdf', { type: 'application/pdf' })
|
||||||
|
const result = await documentApi.upload(file)
|
||||||
|
expect(result.id).toBeDefined()
|
||||||
|
expect(result.status).toBe('completed')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests de fallback
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Test du mode démonstration
|
||||||
|
test('should return demo data on API error', async () => {
|
||||||
|
// Mock de l'erreur API
|
||||||
|
mockAxios.onPost('/api/documents/upload').reply(500)
|
||||||
|
|
||||||
|
const file = new File(['content'], 'test.pdf', { type: 'application/pdf' })
|
||||||
|
const result = await documentApi.upload(file)
|
||||||
|
|
||||||
|
expect(result.id).toMatch(/^demo-/)
|
||||||
|
expect(result.name).toBe('test.pdf')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
|
||||||
|
### Validation des données
|
||||||
|
|
||||||
|
- **Sanitization** : Nettoyage des entrées utilisateur
|
||||||
|
- **Validation** : Vérification des types et formats
|
||||||
|
- **Escape** : Protection contre les injections
|
||||||
|
|
||||||
|
### CORS
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Configuration CORS
|
||||||
|
const corsOptions = {
|
||||||
|
origin: ['http://localhost:3000', 'https://app.4nkweb.com'],
|
||||||
|
credentials: true,
|
||||||
|
optionsSuccessStatus: 200
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTPS
|
||||||
|
|
||||||
|
- **Redirection automatique** : HTTP vers HTTPS en production
|
||||||
|
- **HSTS** : HTTP Strict Transport Security
|
||||||
|
- **Certificats SSL** : Certificats valides et à jour
|
282
docs/ARCHITECTURE.md
Normal file
282
docs/ARCHITECTURE.md
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
# Architecture de l'application 4NK IA Front Notarial
|
||||||
|
|
||||||
|
## Vue d'ensemble
|
||||||
|
|
||||||
|
L'application 4NK IA Front Notarial est une interface web moderne construite avec React et TypeScript,
|
||||||
|
conçue pour l'analyse intelligente de documents notariaux.
|
||||||
|
|
||||||
|
## Stack technique
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
- **React 18** : Framework UI avec hooks et composants fonctionnels
|
||||||
|
- **TypeScript 5.6** : Typage statique pour la robustesse du code
|
||||||
|
- **Vite 7** : Build tool rapide avec HMR (Hot Module Replacement)
|
||||||
|
- **Material-UI v6** : Bibliothèque de composants UI professionnels
|
||||||
|
|
||||||
|
### Gestion d'état
|
||||||
|
|
||||||
|
- **Redux Toolkit** : Gestion d'état centralisée et prévisible
|
||||||
|
- **React Redux** : Liaison React-Redux avec hooks
|
||||||
|
- **Async Thunks** : Gestion des actions asynchrones
|
||||||
|
|
||||||
|
### Routing et navigation
|
||||||
|
|
||||||
|
- **React Router v6** : Navigation côté client avec code splitting
|
||||||
|
- **Lazy loading** : Chargement à la demande des composants
|
||||||
|
|
||||||
|
### HTTP et API
|
||||||
|
|
||||||
|
- **Axios** : Client HTTP avec intercepteurs
|
||||||
|
- **Intercepteurs** : Gestion centralisée des erreurs et authentification
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- **Vitest** : Framework de test rapide et moderne
|
||||||
|
- **Testing Library** : Tests d'intégration React
|
||||||
|
- **JSDOM** : Environnement DOM simulé
|
||||||
|
- **Coverage V8** : Rapport de couverture de code
|
||||||
|
|
||||||
|
### Qualité de code
|
||||||
|
|
||||||
|
- **ESLint** : Linting avec règles strictes
|
||||||
|
- **Prettier** : Formatage automatique du code
|
||||||
|
- **markdownlint** : Validation des fichiers Markdown
|
||||||
|
|
||||||
|
## Structure du projet
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/
|
||||||
|
├── components/ # Composants réutilisables
|
||||||
|
│ ├── Layout.tsx # Layout principal avec AppBar et navigation
|
||||||
|
│ └── NavigationTabs.tsx # Composant de navigation par onglets
|
||||||
|
├── views/ # Vues principales de l'application
|
||||||
|
│ ├── UploadView.tsx # Upload et gestion des documents
|
||||||
|
│ ├── ExtractionView.tsx # Affichage des données extraites
|
||||||
|
│ ├── AnalyseView.tsx # Analyse et score de vraisemblance
|
||||||
|
│ ├── ContexteView.tsx # Données contextuelles externes
|
||||||
|
│ └── ConseilView.tsx # Conseil IA et recommandations
|
||||||
|
├── store/ # Gestion d'état Redux
|
||||||
|
│ ├── index.ts # Configuration du store Redux
|
||||||
|
│ ├── appSlice.ts # État global de l'application
|
||||||
|
│ └── documentSlice.ts # État des documents et opérations
|
||||||
|
├── services/ # Services et API
|
||||||
|
│ └── api.ts # Client API et endpoints
|
||||||
|
├── types/ # Types et interfaces TypeScript
|
||||||
|
│ └── index.ts # Définitions de types centralisées
|
||||||
|
├── main.tsx # Point d'entrée de l'application
|
||||||
|
└── App.tsx # Composant racine avec routing
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture des composants
|
||||||
|
|
||||||
|
### Layout et navigation
|
||||||
|
|
||||||
|
- **Layout** : Composant wrapper avec AppBar et navigation
|
||||||
|
- **NavigationTabs** : Navigation par onglets avec React Router
|
||||||
|
- **AppBar** : Barre de navigation principale
|
||||||
|
|
||||||
|
### Vues principales
|
||||||
|
|
||||||
|
#### UploadView
|
||||||
|
|
||||||
|
- **Dropzone** : Zone de glisser-déposer pour les fichiers
|
||||||
|
- **FileList** : Liste des documents uploadés
|
||||||
|
- **Status indicators** : Indicateurs de statut des documents
|
||||||
|
|
||||||
|
#### ExtractionView
|
||||||
|
|
||||||
|
- **DataDisplay** : Affichage des données extraites
|
||||||
|
- **ObjectLists** : Listes d'identités, adresses, biens, contrats
|
||||||
|
- **Confidence scores** : Scores de confiance des extractions
|
||||||
|
|
||||||
|
#### AnalyseView
|
||||||
|
|
||||||
|
- **CredibilityScore** : Score de vraisemblance du document
|
||||||
|
- **Recommendations** : Liste des recommandations
|
||||||
|
- **Summary** : Synthèse de l'analyse
|
||||||
|
|
||||||
|
#### ContexteView
|
||||||
|
|
||||||
|
- **ExternalData** : Données des APIs externes
|
||||||
|
- **StatusCards** : Cartes de statut pour chaque source
|
||||||
|
- **LastUpdated** : Horodatage des dernières mises à jour
|
||||||
|
|
||||||
|
#### ConseilView
|
||||||
|
|
||||||
|
- **LLMAnalysis** : Analyse générée par l'IA
|
||||||
|
- **RiskAssessment** : Évaluation des risques
|
||||||
|
- **NextSteps** : Prochaines étapes recommandées
|
||||||
|
|
||||||
|
## Gestion d'état Redux
|
||||||
|
|
||||||
|
### Structure du store
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface RootState {
|
||||||
|
app: AppState // État global de l'application
|
||||||
|
document: DocumentState // État des documents et opérations
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### AppState
|
||||||
|
|
||||||
|
- **status** : État global ('idle' | 'loading' | 'succeeded' | 'failed')
|
||||||
|
- **error** : Messages d'erreur globaux
|
||||||
|
|
||||||
|
### DocumentState
|
||||||
|
|
||||||
|
- **documents** : Liste des documents uploadés
|
||||||
|
- **currentDocument** : Document actuellement sélectionné
|
||||||
|
- **extractionResult** : Résultats d'extraction
|
||||||
|
- **analysisResult** : Résultats d'analyse
|
||||||
|
- **contextResult** : Données contextuelles
|
||||||
|
- **conseilResult** : Conseil IA
|
||||||
|
- **loading** : État de chargement
|
||||||
|
- **error** : Messages d'erreur
|
||||||
|
|
||||||
|
### Actions asynchrones
|
||||||
|
|
||||||
|
- **uploadDocument** : Upload d'un document
|
||||||
|
- **extractDocument** : Extraction des données
|
||||||
|
- **analyzeDocument** : Analyse du document
|
||||||
|
- **getContextData** : Récupération des données contextuelles
|
||||||
|
- **getConseil** : Génération du conseil IA
|
||||||
|
|
||||||
|
## Services API
|
||||||
|
|
||||||
|
### Configuration Axios
|
||||||
|
|
||||||
|
- **Base URL** : Configuration via variables d'environnement
|
||||||
|
- **Timeout** : 60 secondes pour les opérations longues
|
||||||
|
- **Intercepteurs** : Gestion d'erreur et fallback automatique
|
||||||
|
|
||||||
|
### Endpoints
|
||||||
|
|
||||||
|
- `POST /api/documents/upload` : Upload de document
|
||||||
|
- `GET /api/documents/{id}/extract` : Extraction de données
|
||||||
|
- `GET /api/documents/{id}/analyze` : Analyse du document
|
||||||
|
- `GET /api/documents/{id}/context` : Données contextuelles
|
||||||
|
- `GET /api/documents/{id}/conseil` : Conseil IA
|
||||||
|
|
||||||
|
### Gestion d'erreur
|
||||||
|
|
||||||
|
- **Intercepteurs** : Détection automatique des erreurs
|
||||||
|
- **Fallback** : Données de démonstration en cas d'erreur
|
||||||
|
- **Codes gérés** : 404, 405, ERR_NETWORK, ERR_CONNECTION_REFUSED
|
||||||
|
|
||||||
|
## Types et interfaces
|
||||||
|
|
||||||
|
### Document
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface Document {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
type: string
|
||||||
|
size: number
|
||||||
|
uploadDate: Date
|
||||||
|
status: 'uploading' | 'processing' | 'completed' | 'error'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ExtractionResult
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ExtractionResult {
|
||||||
|
documentId: string
|
||||||
|
text: string
|
||||||
|
language: string
|
||||||
|
documentType: string
|
||||||
|
identities: Identity[]
|
||||||
|
addresses: Address[]
|
||||||
|
properties: Property[]
|
||||||
|
contracts: Contract[]
|
||||||
|
signatures: string[]
|
||||||
|
confidence: number
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### AnalysisResult
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface AnalysisResult {
|
||||||
|
documentId: string
|
||||||
|
documentType: string
|
||||||
|
isCNI: boolean
|
||||||
|
credibilityScore: number
|
||||||
|
summary: string
|
||||||
|
recommendations: string[]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Mode démonstration
|
||||||
|
|
||||||
|
### Fonctionnement
|
||||||
|
|
||||||
|
- **Détection automatique** : Vérification de la disponibilité du backend
|
||||||
|
- **Fallback gracieux** : Basculement vers des données de démonstration
|
||||||
|
- **Données réalistes** : Exemples d'actes notariaux authentiques
|
||||||
|
- **Fonctionnalités complètes** : Toutes les vues opérationnelles
|
||||||
|
|
||||||
|
### Données de démonstration
|
||||||
|
|
||||||
|
- **Documents** : Exemples d'actes de vente, CNI, etc.
|
||||||
|
- **Identités** : Personnes avec informations complètes
|
||||||
|
- **Adresses** : Adresses françaises réalistes
|
||||||
|
- **Biens** : Propriétés avec références cadastrales
|
||||||
|
- **Contrats** : Clauses et montants réalistes
|
||||||
|
|
||||||
|
## Performance et optimisation
|
||||||
|
|
||||||
|
### Code splitting
|
||||||
|
|
||||||
|
- **Lazy loading** : Chargement à la demande des vues
|
||||||
|
- **Suspense** : Gestion des états de chargement
|
||||||
|
- **Bundle optimization** : Optimisation de la taille des bundles
|
||||||
|
|
||||||
|
### Caching
|
||||||
|
|
||||||
|
- **Redux state** : Mise en cache des données dans le store
|
||||||
|
- **API responses** : Cache des réponses API
|
||||||
|
- **Component memoization** : Optimisation des re-renders
|
||||||
|
|
||||||
|
### Build optimization
|
||||||
|
|
||||||
|
- **Vite** : Build rapide avec optimisations automatiques
|
||||||
|
- **Tree shaking** : Élimination du code mort
|
||||||
|
- **Minification** : Compression du code de production
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
|
||||||
|
### Validation
|
||||||
|
|
||||||
|
- **TypeScript** : Validation de types à la compilation
|
||||||
|
- **Runtime validation** : Validation des données API
|
||||||
|
- **Input sanitization** : Nettoyage des entrées utilisateur
|
||||||
|
|
||||||
|
### CORS et CSP
|
||||||
|
|
||||||
|
- **CORS** : Configuration des en-têtes Cross-Origin
|
||||||
|
- **CSP** : Content Security Policy pour la sécurité
|
||||||
|
- **HTTPS** : Communication sécurisée en production
|
||||||
|
|
||||||
|
## Déploiement
|
||||||
|
|
||||||
|
### Environnements
|
||||||
|
|
||||||
|
- **Développement** : Serveur local avec HMR
|
||||||
|
- **Staging** : Environnement de test
|
||||||
|
- **Production** : Déploiement optimisé
|
||||||
|
|
||||||
|
### Variables d'environnement
|
||||||
|
|
||||||
|
- **VITE_API_URL** : URL de l'API backend
|
||||||
|
- **VITE_*_API_URL** : URLs des APIs externes
|
||||||
|
- **NODE_ENV** : Environnement d'exécution
|
||||||
|
|
||||||
|
### Build de production
|
||||||
|
|
||||||
|
- **Optimisation** : Minification et compression
|
||||||
|
- **Assets** : Optimisation des images et CSS
|
||||||
|
- **Bundle analysis** : Analyse de la taille des bundles
|
517
docs/DEPLOYMENT.md
Normal file
517
docs/DEPLOYMENT.md
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
# Guide de déploiement - 4NK IA Front Notarial
|
||||||
|
|
||||||
|
## Vue d'ensemble
|
||||||
|
|
||||||
|
Ce guide couvre le déploiement de l'application 4NK IA Front Notarial dans différents environnements.
|
||||||
|
|
||||||
|
## Prérequis
|
||||||
|
|
||||||
|
### Environnement de développement
|
||||||
|
|
||||||
|
- **Node.js** : >= 22.12.0 (recommandé) ou >= 20.19.0
|
||||||
|
- **npm** : >= 10.0.0
|
||||||
|
- **Git** : Pour la gestion des versions
|
||||||
|
|
||||||
|
### Environnement de production
|
||||||
|
|
||||||
|
- **Serveur web** : Nginx ou Apache
|
||||||
|
- **HTTPS** : Certificat SSL valide
|
||||||
|
- **CDN** : Optionnel pour les assets statiques
|
||||||
|
|
||||||
|
## Configuration des environnements
|
||||||
|
|
||||||
|
### Variables d'environnement
|
||||||
|
|
||||||
|
#### Développement (.env.development)
|
||||||
|
|
||||||
|
```env
|
||||||
|
NODE_ENV=development
|
||||||
|
VITE_API_URL=http://localhost:8000
|
||||||
|
VITE_CADASTRE_API_URL=https://api.cadastre.gouv.fr
|
||||||
|
VITE_GEORISQUES_API_URL=https://www.georisques.gouv.fr/api
|
||||||
|
VITE_GEOFONCIER_API_URL=https://api.geofoncier.fr
|
||||||
|
VITE_BODACC_API_URL=https://api.bodacc.fr
|
||||||
|
VITE_INFOGREFFE_API_URL=https://api.infogreffe.fr
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Staging (.env.staging)
|
||||||
|
|
||||||
|
```env
|
||||||
|
NODE_ENV=staging
|
||||||
|
VITE_API_URL=https://api-staging.4nkweb.com
|
||||||
|
VITE_CADASTRE_API_URL=https://api.cadastre.gouv.fr
|
||||||
|
VITE_GEORISQUES_API_URL=https://www.georisques.gouv.fr/api
|
||||||
|
VITE_GEOFONCIER_API_URL=https://api.geofoncier.fr
|
||||||
|
VITE_BODACC_API_URL=https://api.bodacc.fr
|
||||||
|
VITE_INFOGREFFE_API_URL=https://api.infogreffe.fr
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Production (.env.production)
|
||||||
|
|
||||||
|
```env
|
||||||
|
NODE_ENV=production
|
||||||
|
VITE_API_URL=https://api.4nkweb.com
|
||||||
|
VITE_CADASTRE_API_URL=https://api.cadastre.gouv.fr
|
||||||
|
VITE_GEORISQUES_API_URL=https://www.georisques.gouv.fr/api
|
||||||
|
VITE_GEOFONCIER_API_URL=https://api.geofoncier.fr
|
||||||
|
VITE_BODACC_API_URL=https://api.bodacc.fr
|
||||||
|
VITE_INFOGREFFE_API_URL=https://api.infogreffe.fr
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build de production
|
||||||
|
|
||||||
|
### Script de build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build standard
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Build avec analyse
|
||||||
|
npm run build -- --analyze
|
||||||
|
|
||||||
|
# Build pour un environnement spécifique
|
||||||
|
npm run build -- --mode production
|
||||||
|
```
|
||||||
|
|
||||||
|
### Optimisations automatiques
|
||||||
|
|
||||||
|
- **Minification** : Code JavaScript et CSS minifié
|
||||||
|
- **Tree shaking** : Élimination du code mort
|
||||||
|
- **Code splitting** : Division en chunks optimaux
|
||||||
|
- **Asset optimization** : Optimisation des images et fonts
|
||||||
|
|
||||||
|
### Structure du build
|
||||||
|
|
||||||
|
```text
|
||||||
|
dist/
|
||||||
|
├── index.html # Point d'entrée HTML
|
||||||
|
├── assets/
|
||||||
|
│ ├── index-[hash].js # Bundle principal
|
||||||
|
│ ├── index-[hash].css # Styles principaux
|
||||||
|
│ ├── [chunk]-[hash].js # Chunks de code splitting
|
||||||
|
│ └── [asset]-[hash].[ext] # Assets optimisés
|
||||||
|
└── favicon.ico # Icône du site
|
||||||
|
```
|
||||||
|
|
||||||
|
## Déploiement sur serveur
|
||||||
|
|
||||||
|
### Configuration Nginx
|
||||||
|
|
||||||
|
#### Fichier de configuration
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name app.4nkweb.com;
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
server_name app.4nkweb.com;
|
||||||
|
|
||||||
|
# Certificats SSL
|
||||||
|
ssl_certificate /path/to/certificate.crt;
|
||||||
|
ssl_certificate_key /path/to/private.key;
|
||||||
|
|
||||||
|
# Configuration SSL
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
|
||||||
|
ssl_prefer_server_ciphers off;
|
||||||
|
|
||||||
|
# HSTS
|
||||||
|
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||||
|
|
||||||
|
# Root directory
|
||||||
|
root /var/www/4nk-ia-front/dist;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Gestion des routes SPA
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache des assets statiques
|
||||||
|
location /assets/ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sécurité
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
|
||||||
|
# Compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Apache
|
||||||
|
|
||||||
|
#### Fichier .htaccess
|
||||||
|
|
||||||
|
```apache
|
||||||
|
RewriteEngine On
|
||||||
|
|
||||||
|
# Redirection HTTPS
|
||||||
|
RewriteCond %{HTTPS} off
|
||||||
|
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||||
|
|
||||||
|
# Gestion des routes SPA
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteRule . /index.html [L]
|
||||||
|
|
||||||
|
# Cache des assets
|
||||||
|
<FilesMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg)$">
|
||||||
|
ExpiresActive On
|
||||||
|
ExpiresDefault "access plus 1 year"
|
||||||
|
Header set Cache-Control "public, immutable"
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
# Compression
|
||||||
|
<IfModule mod_deflate.c>
|
||||||
|
AddOutputFilterByType DEFLATE text/plain
|
||||||
|
AddOutputFilterByType DEFLATE text/html
|
||||||
|
AddOutputFilterByType DEFLATE text/xml
|
||||||
|
AddOutputFilterByType DEFLATE text/css
|
||||||
|
AddOutputFilterByType DEFLATE application/xml
|
||||||
|
AddOutputFilterByType DEFLATE application/xhtml+xml
|
||||||
|
AddOutputFilterByType DEFLATE application/rss+xml
|
||||||
|
AddOutputFilterByType DEFLATE application/javascript
|
||||||
|
AddOutputFilterByType DEFLATE application/x-javascript
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Sécurité
|
||||||
|
Header always set X-Frame-Options "SAMEORIGIN"
|
||||||
|
Header always set X-Content-Type-Options "nosniff"
|
||||||
|
Header always set X-XSS-Protection "1; mode=block"
|
||||||
|
Header always set Strict-Transport-Security "max-age=63072000"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Déploiement avec Docker
|
||||||
|
|
||||||
|
### Dockerfile
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# Build stage
|
||||||
|
FROM node:22.12-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### docker-compose.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./ssl:/etc/nginx/ssl:ro
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
|
### Script de déploiement
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# deploy.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "Building application..."
|
||||||
|
docker build -t 4nk-ia-front .
|
||||||
|
|
||||||
|
echo "Stopping existing container..."
|
||||||
|
docker stop 4nk-ia-front || true
|
||||||
|
docker rm 4nk-ia-front || true
|
||||||
|
|
||||||
|
echo "Starting new container..."
|
||||||
|
docker run -d \
|
||||||
|
--name 4nk-ia-front \
|
||||||
|
-p 80:80 \
|
||||||
|
-p 443:443 \
|
||||||
|
-v /path/to/ssl:/etc/nginx/ssl:ro \
|
||||||
|
4nk-ia-front
|
||||||
|
|
||||||
|
echo "Deployment completed!"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Déploiement avec CI/CD
|
||||||
|
|
||||||
|
### GitHub Actions
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [release]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '22.12'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm run test
|
||||||
|
|
||||||
|
- name: Build application
|
||||||
|
run: npm run build
|
||||||
|
env:
|
||||||
|
NODE_ENV: production
|
||||||
|
VITE_API_URL: ${{ secrets.API_URL }}
|
||||||
|
|
||||||
|
- name: Deploy to server
|
||||||
|
uses: appleboy/ssh-action@v0.1.5
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.HOST }}
|
||||||
|
username: ${{ secrets.USERNAME }}
|
||||||
|
key: ${{ secrets.SSH_KEY }}
|
||||||
|
script: |
|
||||||
|
cd /var/www/4nk-ia-front
|
||||||
|
git pull origin release
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### GitLab CI
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
stages:
|
||||||
|
- test
|
||||||
|
- build
|
||||||
|
- deploy
|
||||||
|
|
||||||
|
test:
|
||||||
|
stage: test
|
||||||
|
image: node:22.12-alpine
|
||||||
|
script:
|
||||||
|
- npm ci
|
||||||
|
- npm run test
|
||||||
|
only:
|
||||||
|
- merge_requests
|
||||||
|
- release
|
||||||
|
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
image: node:22.12-alpine
|
||||||
|
script:
|
||||||
|
- npm ci
|
||||||
|
- npm run build
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- dist/
|
||||||
|
expire_in: 1 hour
|
||||||
|
only:
|
||||||
|
- release
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
stage: deploy
|
||||||
|
image: alpine:latest
|
||||||
|
before_script:
|
||||||
|
- apk add --no-cache openssh-client
|
||||||
|
- eval $(ssh-agent -s)
|
||||||
|
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
|
||||||
|
- mkdir -p ~/.ssh
|
||||||
|
- chmod 700 ~/.ssh
|
||||||
|
script:
|
||||||
|
- scp -r dist/* $DEPLOY_USER@$DEPLOY_HOST:/var/www/4nk-ia-front/
|
||||||
|
- ssh $DEPLOY_USER@$DEPLOY_HOST "sudo systemctl reload nginx"
|
||||||
|
only:
|
||||||
|
- release
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monitoring et surveillance
|
||||||
|
|
||||||
|
### Métriques de performance
|
||||||
|
|
||||||
|
- **Temps de chargement** : Mesure du First Contentful Paint
|
||||||
|
- **Taille des bundles** : Surveillance de la taille des assets
|
||||||
|
- **Erreurs JavaScript** : Tracking des erreurs côté client
|
||||||
|
|
||||||
|
### Outils de monitoring
|
||||||
|
|
||||||
|
- **Google Analytics** : Analytics et performance
|
||||||
|
- **Sentry** : Monitoring des erreurs
|
||||||
|
- **Lighthouse** : Audit de performance
|
||||||
|
|
||||||
|
### Configuration Sentry
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
|
|
||||||
|
Sentry.init({
|
||||||
|
dsn: "YOUR_SENTRY_DSN",
|
||||||
|
environment: process.env.NODE_ENV,
|
||||||
|
tracesSampleRate: 1.0,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rollback et récupération
|
||||||
|
|
||||||
|
### Stratégie de rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# rollback.sh
|
||||||
|
|
||||||
|
PREVIOUS_VERSION=$1
|
||||||
|
|
||||||
|
if [ -z "$PREVIOUS_VERSION" ]; then
|
||||||
|
echo "Usage: ./rollback.sh <version>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Rolling back to version $PREVIOUS_VERSION..."
|
||||||
|
|
||||||
|
# Restaurer la version précédente
|
||||||
|
git checkout $PREVIOUS_VERSION
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Redéployer
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
|
||||||
|
echo "Rollback completed!"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sauvegarde
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# backup.sh
|
||||||
|
|
||||||
|
BACKUP_DIR="/backups/4nk-ia-front"
|
||||||
|
DATE=$(date +%Y%m%d_%H%M%S)
|
||||||
|
|
||||||
|
# Créer le répertoire de sauvegarde
|
||||||
|
mkdir -p $BACKUP_DIR
|
||||||
|
|
||||||
|
# Sauvegarder les fichiers
|
||||||
|
tar -czf $BACKUP_DIR/backup_$DATE.tar.gz /var/www/4nk-ia-front
|
||||||
|
|
||||||
|
# Nettoyer les anciennes sauvegardes (garder 7 jours)
|
||||||
|
find $BACKUP_DIR -name "backup_*.tar.gz" -mtime +7 -delete
|
||||||
|
|
||||||
|
echo "Backup completed: backup_$DATE.tar.gz"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
|
||||||
|
### Headers de sécurité
|
||||||
|
|
||||||
|
- **CSP** : Content Security Policy
|
||||||
|
- **HSTS** : HTTP Strict Transport Security
|
||||||
|
- **X-Frame-Options** : Protection contre le clickjacking
|
||||||
|
- **X-Content-Type-Options** : Protection contre MIME sniffing
|
||||||
|
|
||||||
|
### Configuration CSP
|
||||||
|
|
||||||
|
```html
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="
|
||||||
|
default-src 'self';
|
||||||
|
script-src 'self' 'unsafe-inline' 'unsafe-eval';
|
||||||
|
style-src 'self' 'unsafe-inline';
|
||||||
|
img-src 'self' data: https:;
|
||||||
|
connect-src 'self' https://api.4nkweb.com;
|
||||||
|
font-src 'self' data:;
|
||||||
|
">
|
||||||
|
```
|
||||||
|
|
||||||
|
### Audit de sécurité
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Audit des dépendances
|
||||||
|
npm audit
|
||||||
|
|
||||||
|
# Audit de sécurité avec Snyk
|
||||||
|
npx snyk test
|
||||||
|
|
||||||
|
# Scan de vulnérabilités
|
||||||
|
npx audit-ci --config audit-ci.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
### Mise à jour des dépendances
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vérifier les mises à jour
|
||||||
|
npm outdated
|
||||||
|
|
||||||
|
# Mettre à jour les dépendances
|
||||||
|
npm update
|
||||||
|
|
||||||
|
# Mise à jour majeure
|
||||||
|
npx npm-check-updates -u
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nettoyage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Nettoyer le cache npm
|
||||||
|
npm cache clean --force
|
||||||
|
|
||||||
|
# Nettoyer les node_modules
|
||||||
|
rm -rf node_modules package-lock.json
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Nettoyer le build
|
||||||
|
rm -rf dist
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logs et debugging
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Logs Nginx
|
||||||
|
sudo tail -f /var/log/nginx/access.log
|
||||||
|
sudo tail -f /var/log/nginx/error.log
|
||||||
|
|
||||||
|
# Logs de l'application
|
||||||
|
sudo journalctl -u nginx -f
|
||||||
|
|
||||||
|
# Debug des erreurs
|
||||||
|
sudo nginx -t # Test de configuration
|
||||||
|
```
|
627
docs/TESTING.md
Normal file
627
docs/TESTING.md
Normal file
@ -0,0 +1,627 @@
|
|||||||
|
# Guide de tests - 4NK IA Front Notarial
|
||||||
|
|
||||||
|
## Vue d'ensemble
|
||||||
|
|
||||||
|
Ce guide couvre la stratégie de tests pour l'application 4NK IA Front Notarial, incluant les tests unitaires,
|
||||||
|
d'intégration et end-to-end.
|
||||||
|
|
||||||
|
## Stack de test
|
||||||
|
|
||||||
|
### Outils principaux
|
||||||
|
|
||||||
|
- **Vitest** : Framework de test rapide et moderne
|
||||||
|
- **Testing Library** : Tests d'intégration React
|
||||||
|
- **JSDOM** : Environnement DOM simulé
|
||||||
|
- **MSW** : Mock Service Worker pour les APIs
|
||||||
|
- **Coverage V8** : Rapport de couverture de code
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
#### vitest.config.ts
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
globals: true,
|
||||||
|
coverage: {
|
||||||
|
provider: 'v8',
|
||||||
|
reporter: ['text', 'json', 'html'],
|
||||||
|
exclude: [
|
||||||
|
'node_modules/',
|
||||||
|
'dist/',
|
||||||
|
'**/*.d.ts',
|
||||||
|
'**/*.config.*',
|
||||||
|
'**/setup.*'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### setup.test.ts
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { expect, afterEach } from 'vitest'
|
||||||
|
import { cleanup } from '@testing-library/react'
|
||||||
|
import * as matchers from '@testing-library/jest-dom/matchers'
|
||||||
|
|
||||||
|
// Étendre les matchers de testing-library
|
||||||
|
expect.extend(matchers)
|
||||||
|
|
||||||
|
// Nettoyer après chaque test
|
||||||
|
afterEach(() => {
|
||||||
|
cleanup()
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Types de tests
|
||||||
|
|
||||||
|
### Tests unitaires
|
||||||
|
|
||||||
|
#### Composants React
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/components/Layout.test.tsx
|
||||||
|
import { render, screen } from '@testing-library/react'
|
||||||
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import { store } from '../../src/store'
|
||||||
|
import { Layout } from '../../src/components/Layout'
|
||||||
|
|
||||||
|
const renderWithProviders = (ui: React.ReactElement) => {
|
||||||
|
return render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<BrowserRouter>
|
||||||
|
{ui}
|
||||||
|
</BrowserRouter>
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Layout', () => {
|
||||||
|
it('should render the application title', () => {
|
||||||
|
renderWithProviders(<Layout><div>Test content</div></Layout>)
|
||||||
|
|
||||||
|
expect(screen.getByText('4NK IA - Front Notarial')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should render navigation tabs', () => {
|
||||||
|
renderWithProviders(<Layout><div>Test content</div></Layout>)
|
||||||
|
|
||||||
|
expect(screen.getByRole('tablist')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Services API
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/services/api.test.ts
|
||||||
|
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||||
|
import { documentApi } from '../../src/services/api'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
// Mock axios
|
||||||
|
vi.mock('axios')
|
||||||
|
const mockedAxios = vi.mocked(axios)
|
||||||
|
|
||||||
|
describe('documentApi', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('upload', () => {
|
||||||
|
it('should upload a document successfully', async () => {
|
||||||
|
const mockResponse = {
|
||||||
|
data: {
|
||||||
|
id: 'doc_123',
|
||||||
|
name: 'test.pdf',
|
||||||
|
type: 'application/pdf',
|
||||||
|
size: 1024,
|
||||||
|
uploadDate: new Date(),
|
||||||
|
status: 'completed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockedAxios.create.mockReturnValue({
|
||||||
|
post: vi.fn().mockResolvedValue(mockResponse)
|
||||||
|
} as any)
|
||||||
|
|
||||||
|
const file = new File(['content'], 'test.pdf', { type: 'application/pdf' })
|
||||||
|
const result = await documentApi.upload(file)
|
||||||
|
|
||||||
|
expect(result.id).toBe('doc_123')
|
||||||
|
expect(result.name).toBe('test.pdf')
|
||||||
|
expect(result.status).toBe('completed')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return demo data on error', async () => {
|
||||||
|
mockedAxios.create.mockReturnValue({
|
||||||
|
post: vi.fn().mockRejectedValue(new Error('Network error'))
|
||||||
|
} as any)
|
||||||
|
|
||||||
|
const file = new File(['content'], 'test.pdf', { type: 'application/pdf' })
|
||||||
|
const result = await documentApi.upload(file)
|
||||||
|
|
||||||
|
expect(result.id).toMatch(/^demo-/)
|
||||||
|
expect(result.name).toBe('test.pdf')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Redux Slices
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/store/documentSlice.test.ts
|
||||||
|
import { describe, it, expect } from 'vitest'
|
||||||
|
import documentReducer, { setCurrentDocument } from '../../src/store/documentSlice'
|
||||||
|
import { uploadDocument } from '../../src/store/documentSlice'
|
||||||
|
|
||||||
|
describe('documentSlice', () => {
|
||||||
|
const initialState = {
|
||||||
|
documents: [],
|
||||||
|
currentDocument: null,
|
||||||
|
extractionResult: null,
|
||||||
|
analysisResult: null,
|
||||||
|
contextResult: null,
|
||||||
|
conseilResult: null,
|
||||||
|
loading: false,
|
||||||
|
error: null
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should handle setCurrentDocument', () => {
|
||||||
|
const document = {
|
||||||
|
id: 'doc_123',
|
||||||
|
name: 'test.pdf',
|
||||||
|
type: 'application/pdf',
|
||||||
|
size: 1024,
|
||||||
|
uploadDate: new Date(),
|
||||||
|
status: 'completed' as const
|
||||||
|
}
|
||||||
|
|
||||||
|
const action = setCurrentDocument(document)
|
||||||
|
const newState = documentReducer(initialState, action)
|
||||||
|
|
||||||
|
expect(newState.currentDocument).toEqual(document)
|
||||||
|
expect(newState.extractionResult).toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle uploadDocument.pending', () => {
|
||||||
|
const action = { type: uploadDocument.pending.type }
|
||||||
|
const newState = documentReducer(initialState, action)
|
||||||
|
|
||||||
|
expect(newState.loading).toBe(true)
|
||||||
|
expect(newState.error).toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests d'intégration
|
||||||
|
|
||||||
|
#### Vues complètes
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/views/UploadView.test.tsx
|
||||||
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
|
||||||
|
import userEvent from '@testing-library/user-event'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
import { store } from '../../src/store'
|
||||||
|
import { UploadView } from '../../src/views/UploadView'
|
||||||
|
|
||||||
|
const renderWithProviders = (ui: React.ReactElement) => {
|
||||||
|
return render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<BrowserRouter>
|
||||||
|
{ui}
|
||||||
|
</BrowserRouter>
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('UploadView', () => {
|
||||||
|
it('should render upload area', () => {
|
||||||
|
renderWithProviders(<UploadView />)
|
||||||
|
|
||||||
|
expect(screen.getByText(/glisser-déposer/i)).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle file upload', async () => {
|
||||||
|
const user = userEvent.setup()
|
||||||
|
renderWithProviders(<UploadView />)
|
||||||
|
|
||||||
|
const file = new File(['content'], 'test.pdf', { type: 'application/pdf' })
|
||||||
|
const input = screen.getByLabelText(/sélectionner des fichiers/i)
|
||||||
|
|
||||||
|
await user.upload(input, file)
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText('test.pdf')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should display document list after upload', async () => {
|
||||||
|
const user = userEvent.setup()
|
||||||
|
renderWithProviders(<UploadView />)
|
||||||
|
|
||||||
|
const file = new File(['content'], 'test.pdf', { type: 'application/pdf' })
|
||||||
|
const input = screen.getByLabelText(/sélectionner des fichiers/i)
|
||||||
|
|
||||||
|
await user.upload(input, file)
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByRole('list')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('test.pdf')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Navigation
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/navigation.test.tsx
|
||||||
|
import { render, screen } from '@testing-library/react'
|
||||||
|
import userEvent from '@testing-library/user-event'
|
||||||
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import { store } from '../src/store'
|
||||||
|
import App from '../src/App'
|
||||||
|
|
||||||
|
const renderWithProviders = (ui: React.ReactElement) => {
|
||||||
|
return render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<BrowserRouter>
|
||||||
|
{ui}
|
||||||
|
</BrowserRouter>
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Navigation', () => {
|
||||||
|
it('should navigate between tabs', async () => {
|
||||||
|
const user = userEvent.setup()
|
||||||
|
renderWithProviders(<App />)
|
||||||
|
|
||||||
|
// Vérifier que l'onglet Upload est actif par défaut
|
||||||
|
expect(screen.getByText('Upload')).toHaveAttribute('aria-selected', 'true')
|
||||||
|
|
||||||
|
// Cliquer sur l'onglet Extraction
|
||||||
|
await user.click(screen.getByText('Extraction'))
|
||||||
|
|
||||||
|
expect(screen.getByText('Extraction')).toHaveAttribute('aria-selected', 'true')
|
||||||
|
expect(screen.getByText('Upload')).toHaveAttribute('aria-selected', 'false')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests d'API avec MSW
|
||||||
|
|
||||||
|
#### Configuration MSW
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/mocks/handlers.ts
|
||||||
|
import { http, HttpResponse } from 'msw'
|
||||||
|
|
||||||
|
export const handlers = [
|
||||||
|
// Upload de document
|
||||||
|
http.post('/api/documents/upload', () => {
|
||||||
|
return HttpResponse.json({
|
||||||
|
id: 'doc_123',
|
||||||
|
name: 'test.pdf',
|
||||||
|
type: 'application/pdf',
|
||||||
|
size: 1024,
|
||||||
|
uploadDate: new Date().toISOString(),
|
||||||
|
status: 'completed'
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Extraction de données
|
||||||
|
http.get('/api/documents/:id/extract', () => {
|
||||||
|
return HttpResponse.json({
|
||||||
|
documentId: 'doc_123',
|
||||||
|
text: 'Texte extrait du document...',
|
||||||
|
language: 'fr',
|
||||||
|
documentType: 'Acte de vente',
|
||||||
|
identities: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
type: 'person',
|
||||||
|
firstName: 'Jean',
|
||||||
|
lastName: 'Dupont',
|
||||||
|
birthDate: '1980-05-15',
|
||||||
|
nationality: 'Française',
|
||||||
|
confidence: 0.95
|
||||||
|
}
|
||||||
|
],
|
||||||
|
addresses: [],
|
||||||
|
properties: [],
|
||||||
|
contracts: [],
|
||||||
|
signatures: [],
|
||||||
|
confidence: 0.92
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Erreur de connexion
|
||||||
|
http.get('/api/documents/:id/analyze', () => {
|
||||||
|
return HttpResponse.error()
|
||||||
|
})
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Tests avec MSW
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/integration/api.test.tsx
|
||||||
|
import { setupServer } from 'msw/node'
|
||||||
|
import { handlers } from '../mocks/handlers'
|
||||||
|
import { documentApi } from '../../src/services/api'
|
||||||
|
|
||||||
|
const server = setupServer(...handlers)
|
||||||
|
|
||||||
|
beforeAll(() => server.listen())
|
||||||
|
afterEach(() => server.resetHandlers())
|
||||||
|
afterAll(() => server.close())
|
||||||
|
|
||||||
|
describe('API Integration', () => {
|
||||||
|
it('should extract document data', async () => {
|
||||||
|
const result = await documentApi.extract('doc_123')
|
||||||
|
|
||||||
|
expect(result.documentId).toBe('doc_123')
|
||||||
|
expect(result.identities).toHaveLength(1)
|
||||||
|
expect(result.identities[0].firstName).toBe('Jean')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle API errors gracefully', async () => {
|
||||||
|
const result = await documentApi.analyze('doc_123')
|
||||||
|
|
||||||
|
// Devrait retourner des données de démonstration
|
||||||
|
expect(result.documentId).toBe('doc_123')
|
||||||
|
expect(result.credibilityScore).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests de performance
|
||||||
|
|
||||||
|
### Tests de rendu
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/performance/render.test.tsx
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
import { store } from '../../src/store'
|
||||||
|
import App from '../../src/App'
|
||||||
|
|
||||||
|
describe('Performance', () => {
|
||||||
|
it('should render app within acceptable time', () => {
|
||||||
|
const start = performance.now()
|
||||||
|
|
||||||
|
render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<BrowserRouter>
|
||||||
|
<App />
|
||||||
|
</BrowserRouter>
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
|
||||||
|
const end = performance.now()
|
||||||
|
const renderTime = end - start
|
||||||
|
|
||||||
|
// Le rendu initial devrait prendre moins de 100ms
|
||||||
|
expect(renderTime).toBeLessThan(100)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests de mémoire
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/performance/memory.test.tsx
|
||||||
|
import { render, cleanup } from '@testing-library/react'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
import { store } from '../../src/store'
|
||||||
|
import { UploadView } from '../../src/views/UploadView'
|
||||||
|
|
||||||
|
describe('Memory Management', () => {
|
||||||
|
it('should not leak memory on multiple renders', () => {
|
||||||
|
const initialMemory = (performance as any).memory?.usedJSHeapSize || 0
|
||||||
|
|
||||||
|
// Rendre et nettoyer plusieurs fois
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<BrowserRouter>
|
||||||
|
<UploadView />
|
||||||
|
</BrowserRouter>
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalMemory = (performance as any).memory?.usedJSHeapSize || 0
|
||||||
|
const memoryIncrease = finalMemory - initialMemory
|
||||||
|
|
||||||
|
// L'augmentation de mémoire devrait être raisonnable
|
||||||
|
expect(memoryIncrease).toBeLessThan(10 * 1024 * 1024) // 10MB
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests d'accessibilité
|
||||||
|
|
||||||
|
### Tests avec jest-axe
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/accessibility/a11y.test.tsx
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import { axe, toHaveNoViolations } from 'jest-axe'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
import { store } from '../../src/store'
|
||||||
|
import { Layout } from '../../src/components/Layout'
|
||||||
|
|
||||||
|
expect.extend(toHaveNoViolations)
|
||||||
|
|
||||||
|
describe('Accessibility', () => {
|
||||||
|
it('should not have accessibility violations', async () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<BrowserRouter>
|
||||||
|
<Layout>
|
||||||
|
<div>Test content</div>
|
||||||
|
</Layout>
|
||||||
|
</BrowserRouter>
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
|
||||||
|
const results = await axe(container)
|
||||||
|
expect(results).toHaveNoViolations()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should have proper ARIA labels', () => {
|
||||||
|
render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<BrowserRouter>
|
||||||
|
<Layout>
|
||||||
|
<div>Test content</div>
|
||||||
|
</Layout>
|
||||||
|
</BrowserRouter>
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(screen.getByRole('banner')).toBeInTheDocument()
|
||||||
|
expect(screen.getByRole('tablist')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scripts de test
|
||||||
|
|
||||||
|
### package.json
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"test": "vitest",
|
||||||
|
"test:ui": "vitest --ui",
|
||||||
|
"test:run": "vitest run",
|
||||||
|
"test:coverage": "vitest run --coverage",
|
||||||
|
"test:watch": "vitest --watch",
|
||||||
|
"test:debug": "vitest --inspect-brk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exécution des tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Tests en mode watch
|
||||||
|
npm run test
|
||||||
|
|
||||||
|
# Tests avec interface graphique
|
||||||
|
npm run test:ui
|
||||||
|
|
||||||
|
# Tests une seule fois
|
||||||
|
npm run test:run
|
||||||
|
|
||||||
|
# Tests avec couverture
|
||||||
|
npm run test:coverage
|
||||||
|
|
||||||
|
# Tests en mode debug
|
||||||
|
npm run test:debug
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration CI/CD
|
||||||
|
|
||||||
|
### GitHub Actions
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Tests
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '22.12'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm run test:coverage
|
||||||
|
|
||||||
|
- name: Upload coverage
|
||||||
|
uses: codecov/codecov-action@v3
|
||||||
|
with:
|
||||||
|
file: ./coverage/lcov.info
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bonnes pratiques
|
||||||
|
|
||||||
|
### Organisation des tests
|
||||||
|
|
||||||
|
- **Un fichier de test par composant** : `Component.test.tsx`
|
||||||
|
- **Tests groupés par fonctionnalité** : `describe` blocks
|
||||||
|
- **Tests isolés** : Chaque test doit être indépendant
|
||||||
|
- **Noms descriptifs** : `it('should do something specific')`
|
||||||
|
|
||||||
|
### Mocking
|
||||||
|
|
||||||
|
- **Mock des dépendances externes** : APIs, services
|
||||||
|
- **Mock des hooks** : React hooks personnalisés
|
||||||
|
- **Mock des modules** : Modules Node.js
|
||||||
|
|
||||||
|
### Assertions
|
||||||
|
|
||||||
|
- **Assertions spécifiques** : Éviter les assertions génériques
|
||||||
|
- **Tests de régression** : Vérifier les bugs corrigés
|
||||||
|
- **Tests de cas limites** : Valeurs nulles, erreurs
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
- **Tests rapides** : Éviter les tests lents
|
||||||
|
- **Parallélisation** : Utiliser `--threads` pour Vitest
|
||||||
|
- **Cache** : Utiliser le cache des dépendances
|
||||||
|
|
||||||
|
## Métriques de qualité
|
||||||
|
|
||||||
|
### Couverture de code
|
||||||
|
|
||||||
|
- **Minimum 80%** : Couverture globale
|
||||||
|
- **Minimum 90%** : Composants critiques
|
||||||
|
- **100%** : Fonctions utilitaires
|
||||||
|
|
||||||
|
### Types de couverture
|
||||||
|
|
||||||
|
- **Statements** : Instructions exécutées
|
||||||
|
- **Branches** : Branches conditionnelles
|
||||||
|
- **Functions** : Fonctions appelées
|
||||||
|
- **Lines** : Lignes de code exécutées
|
||||||
|
|
||||||
|
### Rapport de couverture
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Générer le rapport
|
||||||
|
npm run test:coverage
|
||||||
|
|
||||||
|
# Ouvrir le rapport HTML
|
||||||
|
open coverage/index.html
|
||||||
|
```
|
Loading…
x
Reference in New Issue
Block a user