- 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>
726 lines
24 KiB
Python
726 lines
24 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Script de Test Debug - Propriétés d'Étapes VWB
|
||
Auteur : Dom, Alice, Kiro - 12 janvier 2026
|
||
|
||
Ce script teste en temps réel le problème des propriétés d'étapes vides
|
||
en créant un composant de test qui affiche les informations de débogage.
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
def create_debug_component():
|
||
"""Crée un composant de test pour déboguer les propriétés d'étapes."""
|
||
|
||
project_root = Path(__file__).parent.parent
|
||
frontend_path = project_root / "visual_workflow_builder" / "frontend"
|
||
|
||
# Créer le composant de test
|
||
test_component_path = frontend_path / "src" / "components" / "PropertiesDebugTest.tsx"
|
||
|
||
test_component_content = '''/**
|
||
* Composant de Test Debug - Propriétés d'Étapes
|
||
* Auteur : Dom, Alice, Kiro - 12 janvier 2026
|
||
*
|
||
* Ce composant teste et affiche les informations de débogage pour
|
||
* diagnostiquer le problème des propriétés d'étapes vides.
|
||
*/
|
||
|
||
import React, { useState, useCallback, useMemo } from 'react';
|
||
import {
|
||
Box,
|
||
Typography,
|
||
Button,
|
||
Card,
|
||
CardContent,
|
||
Alert,
|
||
Accordion,
|
||
AccordionSummary,
|
||
AccordionDetails,
|
||
Table,
|
||
TableBody,
|
||
TableCell,
|
||
TableContainer,
|
||
TableHead,
|
||
TableRow,
|
||
Paper,
|
||
Chip,
|
||
} from '@mui/material';
|
||
import {
|
||
ExpandMore as ExpandMoreIcon,
|
||
BugReport as BugIcon,
|
||
CheckCircle as CheckIcon,
|
||
Error as ErrorIcon,
|
||
} from '@mui/icons-material';
|
||
|
||
// Import des types
|
||
import { Step, StepType, StepExecutionState } from '../types';
|
||
|
||
// Import des hooks VWB
|
||
import { useVWBStepIntegration, useIsVWBStep, useVWBActionId } from '../hooks/useVWBStepIntegration';
|
||
|
||
// Configuration des paramètres (copie de PropertiesPanel)
|
||
interface ParameterConfig {
|
||
name: string;
|
||
label: string;
|
||
type: 'text' | 'number' | 'boolean' | 'select' | 'visual';
|
||
required?: boolean;
|
||
description?: string;
|
||
supportVariables?: boolean;
|
||
options?: { value: string; label: string }[];
|
||
defaultValue?: any;
|
||
min?: number;
|
||
max?: number;
|
||
}
|
||
|
||
const stepParametersConfig: Record<StepType, ParameterConfig[]> = {
|
||
click: [
|
||
{
|
||
name: 'target',
|
||
label: 'Élément cible',
|
||
type: 'visual',
|
||
required: true,
|
||
description: 'Sélectionner l\\'élément à cliquer',
|
||
},
|
||
{
|
||
name: 'clickType',
|
||
label: 'Type de clic',
|
||
type: 'select',
|
||
options: [
|
||
{ value: 'left', label: 'Clic gauche' },
|
||
{ value: 'right', label: 'Clic droit' },
|
||
{ value: 'double', label: 'Double-clic' },
|
||
],
|
||
defaultValue: 'left',
|
||
},
|
||
],
|
||
type: [
|
||
{
|
||
name: 'target',
|
||
label: 'Champ de saisie',
|
||
type: 'visual',
|
||
required: true,
|
||
description: 'Sélectionner le champ où saisir le texte',
|
||
},
|
||
{
|
||
name: 'text',
|
||
label: 'Texte à saisir',
|
||
type: 'text',
|
||
required: true,
|
||
supportVariables: true,
|
||
},
|
||
{
|
||
name: 'clearFirst',
|
||
label: 'Vider le champ d\\'abord',
|
||
type: 'boolean',
|
||
defaultValue: true,
|
||
},
|
||
],
|
||
wait: [
|
||
{
|
||
name: 'duration',
|
||
label: 'Durée (secondes)',
|
||
type: 'number',
|
||
required: true,
|
||
min: 0.1,
|
||
max: 60,
|
||
defaultValue: 1,
|
||
},
|
||
],
|
||
condition: [
|
||
{
|
||
name: 'condition',
|
||
label: 'Condition',
|
||
type: 'text',
|
||
required: true,
|
||
supportVariables: true,
|
||
description: 'Expression conditionnelle à évaluer',
|
||
},
|
||
],
|
||
extract: [
|
||
{
|
||
name: 'target',
|
||
label: 'Élément source',
|
||
type: 'visual',
|
||
required: true,
|
||
description: 'Sélectionner l\\'élément dont extraire les données',
|
||
},
|
||
{
|
||
name: 'attribute',
|
||
label: 'Attribut à extraire',
|
||
type: 'select',
|
||
options: [
|
||
{ value: 'text', label: 'Texte' },
|
||
{ value: 'value', label: 'Valeur' },
|
||
{ value: 'href', label: 'Lien (href)' },
|
||
{ value: 'src', label: 'Source (src)' },
|
||
],
|
||
defaultValue: 'text',
|
||
},
|
||
],
|
||
scroll: [
|
||
{
|
||
name: 'direction',
|
||
label: 'Direction',
|
||
type: 'select',
|
||
options: [
|
||
{ value: 'up', label: 'Vers le haut' },
|
||
{ value: 'down', label: 'Vers le bas' },
|
||
{ value: 'left', label: 'Vers la gauche' },
|
||
{ value: 'right', label: 'Vers la droite' },
|
||
],
|
||
defaultValue: 'down',
|
||
},
|
||
{
|
||
name: 'amount',
|
||
label: 'Quantité (pixels)',
|
||
type: 'number',
|
||
defaultValue: 300,
|
||
min: 1,
|
||
},
|
||
],
|
||
navigate: [
|
||
{
|
||
name: 'url',
|
||
label: 'URL de destination',
|
||
type: 'text',
|
||
required: true,
|
||
supportVariables: true,
|
||
},
|
||
],
|
||
screenshot: [
|
||
{
|
||
name: 'filename',
|
||
label: 'Nom du fichier',
|
||
type: 'text',
|
||
supportVariables: true,
|
||
description: 'Nom du fichier de capture (optionnel)',
|
||
},
|
||
],
|
||
};
|
||
|
||
/**
|
||
* Composant de test pour déboguer les propriétés d'étapes
|
||
*/
|
||
const PropertiesDebugTest: React.FC = () => {
|
||
const [selectedStepType, setSelectedStepType] = useState<StepType>('click');
|
||
const [testResults, setTestResults] = useState<any[]>([]);
|
||
|
||
// Hooks VWB
|
||
const { methods: vwbMethods } = useVWBStepIntegration();
|
||
|
||
// Créer une étape de test
|
||
const createTestStep = useCallback((stepType: StepType): Step => {
|
||
return {
|
||
id: `test_step_${Date.now()}`,
|
||
type: stepType,
|
||
name: `Test ${stepType}`,
|
||
position: { x: 100, y: 100 },
|
||
data: {
|
||
label: `Test ${stepType}`,
|
||
stepType: stepType,
|
||
parameters: {},
|
||
},
|
||
executionState: StepExecutionState.IDLE,
|
||
validationErrors: [],
|
||
};
|
||
}, []);
|
||
|
||
// Tester la résolution des paramètres
|
||
const testParameterResolution = useCallback((stepType: StepType) => {
|
||
console.log(`🧪 Test de résolution pour le type: ${stepType}`);
|
||
|
||
const testStep = createTestStep(stepType);
|
||
|
||
// Test 1: Configuration directe
|
||
const directConfig = stepParametersConfig[stepType];
|
||
|
||
// Test 2: Fonction getParameterConfig simulée
|
||
const getParameterConfig = (step: Step): ParameterConfig[] => {
|
||
if (!step) return [];
|
||
console.log(`🔍 Recherche config pour type: "${step.type}"`);
|
||
console.log(`🔍 Clés disponibles:`, Object.keys(stepParametersConfig));
|
||
console.log(`🔍 Type exact match:`, stepParametersConfig[step.type] !== undefined);
|
||
return stepParametersConfig[step.type] || [];
|
||
};
|
||
|
||
const resolvedConfig = getParameterConfig(testStep);
|
||
|
||
// Test 3: Hooks VWB
|
||
const isVWBStep = useIsVWBStep(testStep);
|
||
const vwbActionId = useVWBActionId(testStep);
|
||
|
||
const result = {
|
||
stepType,
|
||
testStep,
|
||
directConfig: directConfig || null,
|
||
directConfigLength: directConfig ? directConfig.length : 0,
|
||
resolvedConfig,
|
||
resolvedConfigLength: resolvedConfig.length,
|
||
isVWBStep,
|
||
vwbActionId,
|
||
configExists: stepParametersConfig[stepType] !== undefined,
|
||
timestamp: new Date().toISOString(),
|
||
};
|
||
|
||
console.log(`✅ Résultat test ${stepType}:`, result);
|
||
|
||
setTestResults(prev => [...prev, result]);
|
||
|
||
return result;
|
||
}, [createTestStep]);
|
||
|
||
// Tester tous les types d'étapes
|
||
const testAllStepTypes = useCallback(() => {
|
||
console.log('🚀 Test de tous les types d\\'étapes');
|
||
setTestResults([]);
|
||
|
||
const allTypes: StepType[] = ['click', 'type', 'wait', 'condition', 'extract', 'scroll', 'navigate', 'screenshot'];
|
||
|
||
allTypes.forEach(stepType => {
|
||
setTimeout(() => testParameterResolution(stepType), 100);
|
||
});
|
||
}, [testParameterResolution]);
|
||
|
||
// Analyser les résultats
|
||
const analysisResults = useMemo(() => {
|
||
if (testResults.length === 0) return null;
|
||
|
||
const totalTests = testResults.length;
|
||
const successfulResolutions = testResults.filter(r => r.resolvedConfigLength > 0).length;
|
||
const failedResolutions = testResults.filter(r => r.resolvedConfigLength === 0).length;
|
||
const vwbSteps = testResults.filter(r => r.isVWBStep).length;
|
||
|
||
return {
|
||
totalTests,
|
||
successfulResolutions,
|
||
failedResolutions,
|
||
vwbSteps,
|
||
successRate: (successfulResolutions / totalTests) * 100,
|
||
};
|
||
}, [testResults]);
|
||
|
||
return (
|
||
<Box sx={{ p: 3, maxWidth: 1200, margin: '0 auto' }}>
|
||
<Typography variant="h4" gutterBottom sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||
<BugIcon color="primary" />
|
||
Test Debug - Propriétés d'Étapes
|
||
</Typography>
|
||
|
||
<Typography variant="body1" color="text.secondary" sx={{ mb: 3 }}>
|
||
Ce composant teste la résolution des propriétés d'étapes pour diagnostiquer
|
||
pourquoi les paramètres apparaissent vides dans l'interface.
|
||
</Typography>
|
||
|
||
{/* Contrôles de test */}
|
||
<Card sx={{ mb: 3 }}>
|
||
<CardContent>
|
||
<Typography variant="h6" gutterBottom>
|
||
Contrôles de Test
|
||
</Typography>
|
||
|
||
<Box sx={{ display: 'flex', gap: 2, mb: 2 }}>
|
||
<Button
|
||
variant="contained"
|
||
onClick={testAllStepTypes}
|
||
startIcon={<BugIcon />}
|
||
>
|
||
Tester Tous les Types
|
||
</Button>
|
||
|
||
<Button
|
||
variant="outlined"
|
||
onClick={() => setTestResults([])}
|
||
>
|
||
Vider les Résultats
|
||
</Button>
|
||
</Box>
|
||
|
||
<Typography variant="body2" color="text.secondary">
|
||
Cliquez sur "Tester Tous les Types" pour exécuter les tests de résolution
|
||
des paramètres pour chaque type d'étape.
|
||
</Typography>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Analyse des résultats */}
|
||
{analysisResults && (
|
||
<Card sx={{ mb: 3 }}>
|
||
<CardContent>
|
||
<Typography variant="h6" gutterBottom sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||
{analysisResults.successRate === 100 ? (
|
||
<CheckIcon color="success" />
|
||
) : (
|
||
<ErrorIcon color="error" />
|
||
)}
|
||
Analyse des Résultats
|
||
</Typography>
|
||
|
||
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap', mb: 2 }}>
|
||
<Chip
|
||
label={`Total: ${analysisResults.totalTests}`}
|
||
color="primary"
|
||
/>
|
||
<Chip
|
||
label={`Succès: ${analysisResults.successfulResolutions}`}
|
||
color="success"
|
||
/>
|
||
<Chip
|
||
label={`Échecs: ${analysisResults.failedResolutions}`}
|
||
color="error"
|
||
/>
|
||
<Chip
|
||
label={`VWB: ${analysisResults.vwbSteps}`}
|
||
color="info"
|
||
/>
|
||
<Chip
|
||
label={`Taux: ${analysisResults.successRate.toFixed(1)}%`}
|
||
color={analysisResults.successRate === 100 ? 'success' : 'warning'}
|
||
/>
|
||
</Box>
|
||
|
||
{analysisResults.failedResolutions > 0 && (
|
||
<Alert severity="error" sx={{ mt: 2 }}>
|
||
<Typography variant="body2">
|
||
{analysisResults.failedResolutions} type(s) d'étapes ne résolvent pas leurs paramètres correctement.
|
||
Cela explique pourquoi les propriétés apparaissent vides dans l'interface.
|
||
</Typography>
|
||
</Alert>
|
||
)}
|
||
</CardContent>
|
||
</Card>
|
||
)}
|
||
|
||
{/* Configuration disponible */}
|
||
<Accordion sx={{ mb: 3 }}>
|
||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||
<Typography variant="h6">
|
||
Configuration stepParametersConfig Disponible
|
||
</Typography>
|
||
</AccordionSummary>
|
||
<AccordionDetails>
|
||
<TableContainer component={Paper}>
|
||
<Table size="small">
|
||
<TableHead>
|
||
<TableRow>
|
||
<TableCell>Type d'Étape</TableCell>
|
||
<TableCell>Nombre de Paramètres</TableCell>
|
||
<TableCell>Paramètres</TableCell>
|
||
</TableRow>
|
||
</TableHead>
|
||
<TableBody>
|
||
{Object.entries(stepParametersConfig).map(([stepType, config]) => (
|
||
<TableRow key={stepType}>
|
||
<TableCell>
|
||
<Chip label={stepType} size="small" />
|
||
</TableCell>
|
||
<TableCell>{config.length}</TableCell>
|
||
<TableCell>
|
||
{config.map(param => param.name).join(', ')}
|
||
</TableCell>
|
||
</TableRow>
|
||
))}
|
||
</TableBody>
|
||
</Table>
|
||
</TableContainer>
|
||
</AccordionDetails>
|
||
</Accordion>
|
||
|
||
{/* Résultats des tests */}
|
||
{testResults.length > 0 && (
|
||
<Accordion>
|
||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||
<Typography variant="h6">
|
||
Résultats Détaillés des Tests ({testResults.length})
|
||
</Typography>
|
||
</AccordionSummary>
|
||
<AccordionDetails>
|
||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
||
{testResults.map((result, index) => (
|
||
<Card key={index} variant="outlined">
|
||
<CardContent>
|
||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
||
<Typography variant="h6">
|
||
Test: {result.stepType}
|
||
</Typography>
|
||
<Chip
|
||
label={result.resolvedConfigLength > 0 ? 'SUCCÈS' : 'ÉCHEC'}
|
||
color={result.resolvedConfigLength > 0 ? 'success' : 'error'}
|
||
/>
|
||
</Box>
|
||
|
||
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 2 }}>
|
||
<Box>
|
||
<Typography variant="body2" color="text.secondary">
|
||
Configuration Directe
|
||
</Typography>
|
||
<Typography variant="body1">
|
||
{result.directConfigLength} paramètres
|
||
</Typography>
|
||
</Box>
|
||
|
||
<Box>
|
||
<Typography variant="body2" color="text.secondary">
|
||
Configuration Résolue
|
||
</Typography>
|
||
<Typography variant="body1">
|
||
{result.resolvedConfigLength} paramètres
|
||
</Typography>
|
||
</Box>
|
||
|
||
<Box>
|
||
<Typography variant="body2" color="text.secondary">
|
||
Est Action VWB
|
||
</Typography>
|
||
<Typography variant="body1">
|
||
{result.isVWBStep ? 'Oui' : 'Non'}
|
||
</Typography>
|
||
</Box>
|
||
|
||
<Box>
|
||
<Typography variant="body2" color="text.secondary">
|
||
Config Existe
|
||
</Typography>
|
||
<Typography variant="body1">
|
||
{result.configExists ? 'Oui' : 'Non'}
|
||
</Typography>
|
||
</Box>
|
||
</Box>
|
||
|
||
{result.resolvedConfigLength === 0 && result.configExists && (
|
||
<Alert severity="error" sx={{ mt: 2 }}>
|
||
<Typography variant="body2">
|
||
🚨 PROBLÈME IDENTIFIÉ: La configuration existe ({result.directConfigLength} paramètres)
|
||
mais la résolution retourne 0 paramètres. Cela indique un problème dans la logique
|
||
de résolution ou dans le mapping des types.
|
||
</Typography>
|
||
</Alert>
|
||
)}
|
||
|
||
<Accordion sx={{ mt: 2 }}>
|
||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||
<Typography variant="body2">
|
||
Détails Techniques
|
||
</Typography>
|
||
</AccordionSummary>
|
||
<AccordionDetails>
|
||
<Box component="pre" sx={{
|
||
fontSize: '0.75rem',
|
||
bgcolor: '#f5f5f5',
|
||
p: 1,
|
||
borderRadius: 1,
|
||
overflow: 'auto',
|
||
}}>
|
||
{JSON.stringify(result, null, 2)}
|
||
</Box>
|
||
</AccordionDetails>
|
||
</Accordion>
|
||
</CardContent>
|
||
</Card>
|
||
))}
|
||
</Box>
|
||
</AccordionDetails>
|
||
</Accordion>
|
||
)}
|
||
</Box>
|
||
);
|
||
};
|
||
|
||
export default PropertiesDebugTest;
|
||
'''
|
||
|
||
try:
|
||
# Créer le répertoire s'il n'existe pas
|
||
test_component_path.parent.mkdir(parents=True, exist_ok=True)
|
||
|
||
# Écrire le composant
|
||
with open(test_component_path, 'w', encoding='utf-8') as f:
|
||
f.write(test_component_content)
|
||
|
||
print(f"✅ Composant de test créé : {test_component_path}")
|
||
|
||
# Créer aussi un fichier de test simple
|
||
create_simple_test_script()
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ Erreur création composant de test : {e}")
|
||
return False
|
||
|
||
def create_simple_test_script():
|
||
"""Crée un script de test simple pour vérifier la logique."""
|
||
|
||
project_root = Path(__file__).parent.parent
|
||
test_script_path = project_root / "scripts" / "test_simple_proprietes_12jan2026.js"
|
||
|
||
test_script_content = '''/**
|
||
* Test Simple - Logique de Propriétés d'Étapes
|
||
* Auteur : Dom, Alice, Kiro - 12 janvier 2026
|
||
*
|
||
* Ce script teste la logique de base pour identifier le problème.
|
||
*/
|
||
|
||
// Configuration des paramètres (copie simplifiée)
|
||
const stepParametersConfig = {
|
||
click: [
|
||
{ name: 'target', label: 'Élément cible', type: 'visual', required: true },
|
||
{ name: 'clickType', label: 'Type de clic', type: 'select', defaultValue: 'left' },
|
||
],
|
||
type: [
|
||
{ name: 'target', label: 'Champ de saisie', type: 'visual', required: true },
|
||
{ name: 'text', label: 'Texte à saisir', type: 'text', required: true },
|
||
{ name: 'clearFirst', label: 'Vider le champ d\\'abord', type: 'boolean', defaultValue: true },
|
||
],
|
||
wait: [
|
||
{ name: 'duration', label: 'Durée (secondes)', type: 'number', required: true, defaultValue: 1 },
|
||
],
|
||
condition: [
|
||
{ name: 'condition', label: 'Condition', type: 'text', required: true },
|
||
],
|
||
extract: [
|
||
{ name: 'target', label: 'Élément source', type: 'visual', required: true },
|
||
{ name: 'attribute', label: 'Attribut à extraire', type: 'select', defaultValue: 'text' },
|
||
],
|
||
scroll: [
|
||
{ name: 'direction', label: 'Direction', type: 'select', defaultValue: 'down' },
|
||
{ name: 'amount', label: 'Quantité (pixels)', type: 'number', defaultValue: 300 },
|
||
],
|
||
navigate: [
|
||
{ name: 'url', label: 'URL de destination', type: 'text', required: true },
|
||
],
|
||
screenshot: [
|
||
{ name: 'filename', label: 'Nom du fichier', type: 'text' },
|
||
],
|
||
};
|
||
|
||
// Fonction de test (copie de PropertiesPanel)
|
||
function getParameterConfig(selectedStep) {
|
||
console.log('🔍 getParameterConfig appelée avec:', selectedStep);
|
||
|
||
if (!selectedStep) {
|
||
console.log('❌ selectedStep est null/undefined');
|
||
return [];
|
||
}
|
||
|
||
console.log('🔍 selectedStep.type:', selectedStep.type);
|
||
console.log('🔍 Type de selectedStep.type:', typeof selectedStep.type);
|
||
console.log('🔍 Clés disponibles dans stepParametersConfig:', Object.keys(stepParametersConfig));
|
||
|
||
const config = stepParametersConfig[selectedStep.type];
|
||
console.log('🔍 Configuration trouvée:', config);
|
||
console.log('🔍 Longueur de la configuration:', config ? config.length : 0);
|
||
|
||
const result = config || [];
|
||
console.log('✅ Résultat final:', result);
|
||
|
||
return result;
|
||
}
|
||
|
||
// Tests
|
||
console.log('🚀 Début des tests de logique de propriétés d\\'étapes');
|
||
console.log('=' .repeat(60));
|
||
|
||
const testSteps = [
|
||
{ id: 'test1', type: 'click', name: 'Test Click' },
|
||
{ id: 'test2', type: 'type', name: 'Test Type' },
|
||
{ id: 'test3', type: 'wait', name: 'Test Wait' },
|
||
{ id: 'test4', type: 'invalid', name: 'Test Invalid' },
|
||
{ id: 'test5', type: 'click_anchor', name: 'Test VWB Click' }, // Action VWB
|
||
];
|
||
|
||
testSteps.forEach((step, index) => {
|
||
console.log(`\\n🧪 Test ${index + 1}: ${step.name} (type: "${step.type}")`);
|
||
|
||
const config = getParameterConfig(step);
|
||
|
||
console.log(`📊 Résultat: ${config.length} paramètres trouvés`);
|
||
|
||
if (config.length > 0) {
|
||
console.log('✅ SUCCÈS - Paramètres disponibles:');
|
||
config.forEach(param => {
|
||
console.log(` - ${param.name}: ${param.label} (${param.type})`);
|
||
});
|
||
} else {
|
||
console.log('❌ ÉCHEC - Aucun paramètre trouvé');
|
||
|
||
// Diagnostic
|
||
if (stepParametersConfig[step.type]) {
|
||
console.log('🚨 PROBLÈME: Configuration existe mais non retournée!');
|
||
} else {
|
||
console.log('ℹ️ INFO: Aucune configuration pour ce type (normal pour les actions VWB)');
|
||
}
|
||
}
|
||
});
|
||
|
||
console.log('\\n' + '=' .repeat(60));
|
||
console.log('📊 RÉSUMÉ DES TESTS');
|
||
console.log('=' .repeat(60));
|
||
|
||
// Résumé
|
||
const results = testSteps.map(step => ({
|
||
type: step.type,
|
||
configExists: !!stepParametersConfig[step.type],
|
||
paramCount: getParameterConfig(step).length,
|
||
}));
|
||
|
||
results.forEach(result => {
|
||
const status = result.paramCount > 0 ? '✅' : '❌';
|
||
console.log(`${status} ${result.type}: ${result.paramCount} paramètres (config existe: ${result.configExists})`);
|
||
});
|
||
|
||
const successCount = results.filter(r => r.paramCount > 0).length;
|
||
const totalCount = results.length;
|
||
|
||
console.log(`\\n📈 Taux de succès: ${successCount}/${totalCount} (${((successCount/totalCount)*100).toFixed(1)}%)`);
|
||
|
||
if (successCount < totalCount) {
|
||
console.log('\\n🔧 RECOMMANDATIONS:');
|
||
console.log('1. Vérifier que tous les types d\\'étapes ont une configuration');
|
||
console.log('2. Vérifier la logique de détection des actions VWB');
|
||
console.log('3. Ajouter des logs dans le composant React pour déboguer en temps réel');
|
||
}
|
||
|
||
console.log('\\n✅ Tests terminés');
|
||
'''
|
||
|
||
try:
|
||
with open(test_script_path, 'w', encoding='utf-8') as f:
|
||
f.write(test_script_content)
|
||
|
||
print(f"✅ Script de test simple créé : {test_script_path}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ Erreur création script de test : {e}")
|
||
return False
|
||
|
||
def main():
|
||
"""Fonction principale."""
|
||
print("🧪 Création des outils de test pour déboguer les propriétés d'étapes")
|
||
|
||
success = create_debug_component()
|
||
|
||
if success:
|
||
print("\n✅ Outils de test créés avec succès!")
|
||
print("\n📋 PROCHAINES ÉTAPES:")
|
||
print("1. Intégrer le composant PropertiesDebugTest dans l'application")
|
||
print("2. Exécuter le script de test simple avec Node.js")
|
||
print("3. Analyser les résultats pour identifier le problème exact")
|
||
print("4. Implémenter la correction basée sur les résultats")
|
||
|
||
print("\n🔧 COMMANDES À EXÉCUTER:")
|
||
print("# Test simple JavaScript:")
|
||
print("node scripts/test_simple_proprietes_12jan2026.js")
|
||
print("\n# Intégrer le composant de test dans App.tsx (temporairement)")
|
||
print("# Puis tester dans le navigateur")
|
||
|
||
return 0
|
||
else:
|
||
print("\n❌ Échec de la création des outils de test")
|
||
return 1
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main()) |