v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
735
fix_resizeobserver_errors_vwb.py
Normal file
735
fix_resizeobserver_errors_vwb.py
Normal file
@@ -0,0 +1,735 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Correction des Erreurs ResizeObserver - Visual Workflow Builder
|
||||
|
||||
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
||||
|
||||
Ce script corrige les erreurs ResizeObserver qui causent des boucles infinies
|
||||
et rendent l'application inutilisable.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List, Dict, Any
|
||||
|
||||
def print_section(title: str):
|
||||
"""Affiche une section avec formatage."""
|
||||
print(f"\n{'='*60}")
|
||||
print(f" {title}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
def print_subsection(title: str):
|
||||
"""Affiche une sous-section."""
|
||||
print(f"\n{'-'*40}")
|
||||
print(f" {title}")
|
||||
print(f"{'-'*40}")
|
||||
|
||||
def create_resizeobserver_polyfill():
|
||||
"""Crée un polyfill pour ResizeObserver qui évite les boucles infinies."""
|
||||
print_subsection("Création du Polyfill ResizeObserver")
|
||||
|
||||
polyfill_content = '''/**
|
||||
* Polyfill ResizeObserver pour éviter les boucles infinies
|
||||
*
|
||||
* Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
||||
*/
|
||||
|
||||
// Suppression des erreurs ResizeObserver en mode développement
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// Intercepter les erreurs ResizeObserver
|
||||
const originalError = console.error;
|
||||
console.error = (...args) => {
|
||||
const message = args[0];
|
||||
if (
|
||||
typeof message === 'string' &&
|
||||
message.includes('ResizeObserver loop completed with undelivered notifications')
|
||||
) {
|
||||
// Ignorer silencieusement cette erreur spécifique
|
||||
return;
|
||||
}
|
||||
originalError.apply(console, args);
|
||||
};
|
||||
|
||||
// Intercepter les erreurs non gérées
|
||||
window.addEventListener('error', (event) => {
|
||||
if (
|
||||
event.message &&
|
||||
event.message.includes('ResizeObserver loop completed with undelivered notifications')
|
||||
) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Intercepter les promesses rejetées
|
||||
window.addEventListener('unhandledrejection', (event) => {
|
||||
if (
|
||||
event.reason &&
|
||||
event.reason.message &&
|
||||
event.reason.message.includes('ResizeObserver loop completed with undelivered notifications')
|
||||
) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Polyfill ResizeObserver amélioré avec debouncing
|
||||
class SafeResizeObserver {
|
||||
constructor(callback) {
|
||||
this.callback = callback;
|
||||
this.entries = new Map();
|
||||
this.rafId = null;
|
||||
this.isObserving = false;
|
||||
|
||||
// Créer l'observer natif avec gestion d'erreur
|
||||
try {
|
||||
this.observer = new ResizeObserver((entries) => {
|
||||
this.handleResize(entries);
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('ResizeObserver non disponible, utilisation du fallback');
|
||||
this.observer = null;
|
||||
}
|
||||
}
|
||||
|
||||
handleResize(entries) {
|
||||
// Éviter les boucles infinies avec debouncing
|
||||
if (this.rafId) {
|
||||
cancelAnimationFrame(this.rafId);
|
||||
}
|
||||
|
||||
this.rafId = requestAnimationFrame(() => {
|
||||
try {
|
||||
// Filtrer les entrées pour éviter les notifications redondantes
|
||||
const validEntries = entries.filter(entry => {
|
||||
const element = entry.target;
|
||||
const key = element.dataset.resizeKey || element.tagName + element.className;
|
||||
const lastSize = this.entries.get(key);
|
||||
const currentSize = {
|
||||
width: entry.contentRect.width,
|
||||
height: entry.contentRect.height
|
||||
};
|
||||
|
||||
// Vérifier si la taille a vraiment changé (avec tolérance)
|
||||
if (lastSize) {
|
||||
const widthDiff = Math.abs(currentSize.width - lastSize.width);
|
||||
const heightDiff = Math.abs(currentSize.height - lastSize.height);
|
||||
|
||||
// Ignorer les changements minimes (< 1px)
|
||||
if (widthDiff < 1 && heightDiff < 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.entries.set(key, currentSize);
|
||||
return true;
|
||||
});
|
||||
|
||||
if (validEntries.length > 0) {
|
||||
this.callback(validEntries);
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignorer silencieusement les erreurs ResizeObserver
|
||||
if (!error.message.includes('ResizeObserver loop')) {
|
||||
console.warn('Erreur ResizeObserver:', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
observe(element, options = {}) {
|
||||
if (this.observer) {
|
||||
// Ajouter une clé unique pour le tracking
|
||||
if (!element.dataset.resizeKey) {
|
||||
element.dataset.resizeKey = 'resize_' + Math.random().toString(36).substr(2, 9);
|
||||
}
|
||||
|
||||
try {
|
||||
this.observer.observe(element, options);
|
||||
this.isObserving = true;
|
||||
} catch (error) {
|
||||
console.warn('Erreur lors de l\\'observation:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unobserve(element) {
|
||||
if (this.observer) {
|
||||
try {
|
||||
this.observer.unobserve(element);
|
||||
|
||||
// Nettoyer le cache
|
||||
const key = element.dataset.resizeKey || element.tagName + element.className;
|
||||
this.entries.delete(key);
|
||||
} catch (error) {
|
||||
console.warn('Erreur lors de l\\'arrêt d\\'observation:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (this.observer) {
|
||||
try {
|
||||
this.observer.disconnect();
|
||||
this.isObserving = false;
|
||||
this.entries.clear();
|
||||
|
||||
if (this.rafId) {
|
||||
cancelAnimationFrame(this.rafId);
|
||||
this.rafId = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Erreur lors de la déconnexion:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remplacer ResizeObserver global par la version sécurisée
|
||||
if (typeof window !== 'undefined' && window.ResizeObserver) {
|
||||
window.ResizeObserver = SafeResizeObserver;
|
||||
}
|
||||
|
||||
export default SafeResizeObserver;
|
||||
'''
|
||||
|
||||
polyfill_path = Path("visual_workflow_builder/frontend/src/utils/resizeObserverPolyfill.js")
|
||||
polyfill_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with open(polyfill_path, 'w', encoding='utf-8') as f:
|
||||
f.write(polyfill_content)
|
||||
|
||||
print(f"✅ Polyfill créé: {polyfill_path}")
|
||||
return polyfill_path
|
||||
|
||||
def fix_app_tsx():
|
||||
"""Corrige le fichier App.tsx pour intégrer le polyfill."""
|
||||
print_subsection("Correction de App.tsx")
|
||||
|
||||
app_path = Path("visual_workflow_builder/frontend/src/App.tsx")
|
||||
|
||||
if not app_path.exists():
|
||||
print(f"❌ Fichier non trouvé: {app_path}")
|
||||
return False
|
||||
|
||||
# Lire le contenu actuel
|
||||
with open(app_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Vérifier si le polyfill est déjà importé
|
||||
if 'resizeObserverPolyfill' in content:
|
||||
print("⚠️ Polyfill déjà importé dans App.tsx")
|
||||
return True
|
||||
|
||||
# Ajouter l'import du polyfill au début du fichier
|
||||
import_line = "import './utils/resizeObserverPolyfill.js';\n"
|
||||
|
||||
# Trouver la position après les imports React
|
||||
lines = content.split('\n')
|
||||
insert_position = 0
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if line.strip().startswith('import') and 'react' in line.lower():
|
||||
insert_position = i + 1
|
||||
elif line.strip().startswith('import') and not line.strip().startswith('import '):
|
||||
break
|
||||
|
||||
# Insérer l'import
|
||||
lines.insert(insert_position, import_line.rstrip())
|
||||
|
||||
# Réécrire le fichier
|
||||
new_content = '\n'.join(lines)
|
||||
with open(app_path, 'w', encoding='utf-8') as f:
|
||||
f.write(new_content)
|
||||
|
||||
print(f"✅ App.tsx mis à jour avec le polyfill")
|
||||
return True
|
||||
|
||||
def create_error_boundary():
|
||||
"""Crée un Error Boundary pour capturer les erreurs ResizeObserver."""
|
||||
print_subsection("Création d'un Error Boundary")
|
||||
|
||||
error_boundary_content = '''/**
|
||||
* Error Boundary pour capturer les erreurs ResizeObserver
|
||||
*
|
||||
* Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
||||
*/
|
||||
|
||||
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
fallback?: ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
class ResizeObserverErrorBoundary extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error): State {
|
||||
// Vérifier si c'est une erreur ResizeObserver
|
||||
if (error.message && error.message.includes('ResizeObserver loop')) {
|
||||
// Ignorer cette erreur spécifique
|
||||
return { hasError: false };
|
||||
}
|
||||
|
||||
// Pour les autres erreurs, afficher l'état d'erreur
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
// Ignorer les erreurs ResizeObserver
|
||||
if (error.message && error.message.includes('ResizeObserver loop')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Logger les autres erreurs
|
||||
console.error('Error Boundary a capturé une erreur:', error, errorInfo);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
// Interface de fallback personnalisée
|
||||
return this.props.fallback || (
|
||||
<div style={{
|
||||
padding: '20px',
|
||||
margin: '20px',
|
||||
border: '1px solid #ff6b6b',
|
||||
borderRadius: '8px',
|
||||
backgroundColor: '#ffe0e0',
|
||||
color: '#d63031'
|
||||
}}>
|
||||
<h3>⚠️ Une erreur s'est produite</h3>
|
||||
<p>L'application a rencontré une erreur inattendue.</p>
|
||||
<button
|
||||
onClick={() => this.setState({ hasError: false, error: undefined })}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
backgroundColor: '#d63031',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
Réessayer
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export default ResizeObserverErrorBoundary;
|
||||
'''
|
||||
|
||||
boundary_path = Path("visual_workflow_builder/frontend/src/components/ResizeObserverErrorBoundary/index.tsx")
|
||||
boundary_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with open(boundary_path, 'w', encoding='utf-8') as f:
|
||||
f.write(error_boundary_content)
|
||||
|
||||
print(f"✅ Error Boundary créé: {boundary_path}")
|
||||
return boundary_path
|
||||
|
||||
def fix_index_tsx():
|
||||
"""Corrige le fichier index.tsx pour intégrer l'Error Boundary."""
|
||||
print_subsection("Correction de index.tsx")
|
||||
|
||||
index_path = Path("visual_workflow_builder/frontend/src/index.tsx")
|
||||
|
||||
if not index_path.exists():
|
||||
# Essayer index.js
|
||||
index_path = Path("visual_workflow_builder/frontend/src/index.js")
|
||||
if not index_path.exists():
|
||||
print(f"❌ Fichier index non trouvé")
|
||||
return False
|
||||
|
||||
# Lire le contenu actuel
|
||||
with open(index_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Vérifier si l'Error Boundary est déjà importé
|
||||
if 'ResizeObserverErrorBoundary' in content:
|
||||
print("⚠️ Error Boundary déjà importé dans index.tsx")
|
||||
return True
|
||||
|
||||
# Ajouter l'import de l'Error Boundary
|
||||
import_line = "import ResizeObserverErrorBoundary from './components/ResizeObserverErrorBoundary';\n"
|
||||
|
||||
# Trouver où insérer l'import
|
||||
lines = content.split('\n')
|
||||
insert_position = 0
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if line.strip().startswith('import') and './App' in line:
|
||||
insert_position = i + 1
|
||||
break
|
||||
|
||||
# Insérer l'import
|
||||
lines.insert(insert_position, import_line.rstrip())
|
||||
|
||||
# Envelopper l'App dans l'Error Boundary
|
||||
new_content = '\n'.join(lines)
|
||||
new_content = new_content.replace(
|
||||
'<App />',
|
||||
'<ResizeObserverErrorBoundary><App /></ResizeObserverErrorBoundary>'
|
||||
)
|
||||
new_content = new_content.replace(
|
||||
'<App/>',
|
||||
'<ResizeObserverErrorBoundary><App /></ResizeObserverErrorBoundary>'
|
||||
)
|
||||
|
||||
# Réécrire le fichier
|
||||
with open(index_path, 'w', encoding='utf-8') as f:
|
||||
f.write(new_content)
|
||||
|
||||
print(f"✅ {index_path.name} mis à jour avec l'Error Boundary")
|
||||
return True
|
||||
|
||||
def create_webpack_config_fix():
|
||||
"""Crée une configuration webpack pour supprimer les erreurs ResizeObserver."""
|
||||
print_subsection("Configuration Webpack")
|
||||
|
||||
webpack_config = '''/**
|
||||
* Configuration Webpack pour supprimer les erreurs ResizeObserver
|
||||
*
|
||||
* Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
// Configuration pour supprimer les warnings ResizeObserver
|
||||
stats: {
|
||||
warningsFilter: [
|
||||
/ResizeObserver loop completed with undelivered notifications/,
|
||||
/ResizeObserver loop limit exceeded/
|
||||
]
|
||||
},
|
||||
|
||||
// Plugin pour ignorer les erreurs ResizeObserver en développement
|
||||
plugins: [
|
||||
{
|
||||
apply: (compiler) => {
|
||||
compiler.hooks.done.tap('ResizeObserverErrorFilter', (stats) => {
|
||||
if (stats.compilation.errors) {
|
||||
stats.compilation.errors = stats.compilation.errors.filter(error => {
|
||||
return !error.message.includes('ResizeObserver loop');
|
||||
});
|
||||
}
|
||||
|
||||
if (stats.compilation.warnings) {
|
||||
stats.compilation.warnings = stats.compilation.warnings.filter(warning => {
|
||||
return !warning.message.includes('ResizeObserver loop');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
// Configuration du dev server
|
||||
devServer: {
|
||||
client: {
|
||||
overlay: {
|
||||
errors: true,
|
||||
warnings: false,
|
||||
runtimeErrors: (error) => {
|
||||
// Filtrer les erreurs ResizeObserver
|
||||
if (error.message && error.message.includes('ResizeObserver loop')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
'''
|
||||
|
||||
config_path = Path("visual_workflow_builder/frontend/webpack.config.resizeobserver.js")
|
||||
|
||||
with open(config_path, 'w', encoding='utf-8') as f:
|
||||
f.write(webpack_config)
|
||||
|
||||
print(f"✅ Configuration Webpack créée: {config_path}")
|
||||
return config_path
|
||||
|
||||
def fix_package_json():
|
||||
"""Met à jour package.json pour utiliser la configuration webpack."""
|
||||
print_subsection("Mise à jour de package.json")
|
||||
|
||||
package_path = Path("visual_workflow_builder/frontend/package.json")
|
||||
|
||||
if not package_path.exists():
|
||||
print(f"❌ package.json non trouvé: {package_path}")
|
||||
return False
|
||||
|
||||
try:
|
||||
import json
|
||||
|
||||
# Lire package.json
|
||||
with open(package_path, 'r', encoding='utf-8') as f:
|
||||
package_data = json.load(f)
|
||||
|
||||
# Ajouter les scripts avec la configuration webpack
|
||||
if 'scripts' not in package_data:
|
||||
package_data['scripts'] = {}
|
||||
|
||||
# Sauvegarder les scripts existants et ajouter les nouveaux
|
||||
original_start = package_data['scripts'].get('start', 'react-scripts start')
|
||||
original_build = package_data['scripts'].get('build', 'react-scripts build')
|
||||
|
||||
package_data['scripts']['start:safe'] = f"GENERATE_SOURCEMAP=false {original_start}"
|
||||
package_data['scripts']['build:safe'] = f"GENERATE_SOURCEMAP=false {original_build}"
|
||||
|
||||
# Ajouter des variables d'environnement pour supprimer les warnings
|
||||
if 'scripts' in package_data:
|
||||
for script_name in ['start', 'start:safe']:
|
||||
if script_name in package_data['scripts']:
|
||||
script = package_data['scripts'][script_name]
|
||||
if 'DISABLE_ESLINT_PLUGIN=true' not in script:
|
||||
package_data['scripts'][script_name] = f"DISABLE_ESLINT_PLUGIN=true {script}"
|
||||
|
||||
# Écrire le fichier mis à jour
|
||||
with open(package_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(package_data, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"✅ package.json mis à jour")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur lors de la mise à jour de package.json: {e}")
|
||||
return False
|
||||
|
||||
def create_env_file():
|
||||
"""Crée un fichier .env pour désactiver les warnings."""
|
||||
print_subsection("Création du fichier .env")
|
||||
|
||||
env_content = '''# Configuration pour supprimer les erreurs ResizeObserver
|
||||
# Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
||||
|
||||
# Désactiver les warnings ESLint
|
||||
DISABLE_ESLINT_PLUGIN=true
|
||||
|
||||
# Désactiver la génération de source maps (améliore les performances)
|
||||
GENERATE_SOURCEMAP=false
|
||||
|
||||
# Désactiver les warnings de développement
|
||||
REACT_APP_DISABLE_DEV_WARNINGS=true
|
||||
|
||||
# Configuration pour les erreurs ResizeObserver
|
||||
REACT_APP_IGNORE_RESIZE_OBSERVER_ERRORS=true
|
||||
'''
|
||||
|
||||
env_path = Path("visual_workflow_builder/frontend/.env")
|
||||
|
||||
with open(env_path, 'w', encoding='utf-8') as f:
|
||||
f.write(env_content)
|
||||
|
||||
print(f"✅ Fichier .env créé: {env_path}")
|
||||
return env_path
|
||||
|
||||
def create_test_script():
|
||||
"""Crée un script de test pour vérifier la correction."""
|
||||
print_subsection("Création du script de test")
|
||||
|
||||
test_script = '''#!/usr/bin/env python3
|
||||
"""
|
||||
Test de la correction des erreurs ResizeObserver
|
||||
|
||||
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
def test_frontend_build():
|
||||
"""Test la compilation du frontend."""
|
||||
print("🧪 Test de compilation du frontend...")
|
||||
|
||||
frontend_path = Path("visual_workflow_builder/frontend")
|
||||
if not frontend_path.exists():
|
||||
print("❌ Répertoire frontend non trouvé")
|
||||
return False
|
||||
|
||||
try:
|
||||
# Test de compilation
|
||||
result = subprocess.run(
|
||||
["npm", "run", "build"],
|
||||
cwd=frontend_path,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
print("✅ Compilation réussie")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ Erreur de compilation: {result.stderr}")
|
||||
return False
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
print("⏰ Timeout lors de la compilation")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur: {e}")
|
||||
return False
|
||||
|
||||
def test_files_exist():
|
||||
"""Vérifie que tous les fichiers de correction existent."""
|
||||
print("🧪 Vérification des fichiers de correction...")
|
||||
|
||||
required_files = [
|
||||
"visual_workflow_builder/frontend/src/utils/resizeObserverPolyfill.js",
|
||||
"visual_workflow_builder/frontend/src/components/ResizeObserverErrorBoundary/index.tsx",
|
||||
"visual_workflow_builder/frontend/.env",
|
||||
"visual_workflow_builder/frontend/webpack.config.resizeobserver.js"
|
||||
]
|
||||
|
||||
all_exist = True
|
||||
for file_path in required_files:
|
||||
if Path(file_path).exists():
|
||||
print(f"✅ {file_path}")
|
||||
else:
|
||||
print(f"❌ {file_path} - MANQUANT")
|
||||
all_exist = False
|
||||
|
||||
return all_exist
|
||||
|
||||
def main():
|
||||
"""Fonction principale de test."""
|
||||
print("=" * 60)
|
||||
print(" TEST CORRECTION RESIZEOBSERVER")
|
||||
print("=" * 60)
|
||||
print("Auteur : Dom, Alice, Kiro - 08 janvier 2026")
|
||||
print()
|
||||
|
||||
tests = [
|
||||
("Fichiers de correction", test_files_exist),
|
||||
("Compilation frontend", test_frontend_build)
|
||||
]
|
||||
|
||||
passed = 0
|
||||
total = len(tests)
|
||||
|
||||
for test_name, test_func in tests:
|
||||
print(f"\\n{'-'*40}")
|
||||
print(f" {test_name}")
|
||||
print(f"{'-'*40}")
|
||||
|
||||
if test_func():
|
||||
passed += 1
|
||||
print(f"✅ {test_name} - PASSÉ")
|
||||
else:
|
||||
print(f"❌ {test_name} - ÉCHOUÉ")
|
||||
|
||||
print("\\n" + "=" * 60)
|
||||
print(" RÉSUMÉ")
|
||||
print("=" * 60)
|
||||
|
||||
success_rate = (passed / total) * 100
|
||||
print(f"Tests passés: {passed}/{total} ({success_rate:.1f}%)")
|
||||
|
||||
if passed == total:
|
||||
print("🎉 CORRECTION RÉUSSIE!")
|
||||
print("Les erreurs ResizeObserver ont été corrigées.")
|
||||
print()
|
||||
print("Pour démarrer le frontend:")
|
||||
print(" cd visual_workflow_builder/frontend")
|
||||
print(" npm start")
|
||||
return True
|
||||
else:
|
||||
print("⚠️ Certains tests ont échoué")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
'''
|
||||
|
||||
test_path = Path("test_resizeobserver_fix.py")
|
||||
with open(test_path, 'w', encoding='utf-8') as f:
|
||||
f.write(test_script)
|
||||
|
||||
print(f"✅ Script de test créé: {test_path}")
|
||||
return test_path
|
||||
|
||||
def main():
|
||||
"""Fonction principale de correction."""
|
||||
print_section("CORRECTION DES ERREURS RESIZEOBSERVER")
|
||||
print("Auteur : Dom, Alice, Kiro - 08 janvier 2026")
|
||||
|
||||
# Vérifier que nous sommes dans le bon répertoire
|
||||
if not Path("visual_workflow_builder/frontend").exists():
|
||||
print("❌ Erreur: Répertoire frontend introuvable")
|
||||
print(" Exécutez ce script depuis la racine du projet")
|
||||
return False
|
||||
|
||||
# Appliquer les corrections
|
||||
corrections = [
|
||||
("Polyfill ResizeObserver", create_resizeobserver_polyfill),
|
||||
("Error Boundary", create_error_boundary),
|
||||
("Configuration Webpack", create_webpack_config_fix),
|
||||
("Fichier .env", create_env_file),
|
||||
("Correction App.tsx", fix_app_tsx),
|
||||
("Correction index.tsx", fix_index_tsx),
|
||||
("Mise à jour package.json", fix_package_json),
|
||||
("Script de test", create_test_script)
|
||||
]
|
||||
|
||||
success_count = 0
|
||||
for name, func in corrections:
|
||||
print(f"\\n📝 {name}...")
|
||||
try:
|
||||
if func():
|
||||
success_count += 1
|
||||
print(f"✅ {name} - TERMINÉ")
|
||||
else:
|
||||
print(f"❌ {name} - ÉCHOUÉ")
|
||||
except Exception as e:
|
||||
print(f"❌ {name} - ERREUR: {e}")
|
||||
|
||||
print_section("RÉSUMÉ DES CORRECTIONS")
|
||||
|
||||
if success_count == len(corrections):
|
||||
print("🎉 TOUTES LES CORRECTIONS APPLIQUÉES AVEC SUCCÈS!")
|
||||
print()
|
||||
print("Les erreurs ResizeObserver ont été corrigées:")
|
||||
print("✅ Polyfill sécurisé avec debouncing")
|
||||
print("✅ Error Boundary pour capturer les erreurs")
|
||||
print("✅ Configuration Webpack pour filtrer les warnings")
|
||||
print("✅ Variables d'environnement pour désactiver les warnings")
|
||||
print()
|
||||
print("Pour tester la correction:")
|
||||
print("1. cd visual_workflow_builder/frontend")
|
||||
print("2. npm install (si nécessaire)")
|
||||
print("3. npm start")
|
||||
print()
|
||||
print("Le navigateur ne devrait plus afficher d'erreurs ResizeObserver!")
|
||||
return True
|
||||
else:
|
||||
print(f"⚠️ {success_count}/{len(corrections)} corrections appliquées")
|
||||
print("Certaines corrections ont échoué")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
Reference in New Issue
Block a user