feat: replay E2E fonctionnel — 25/25 actions, 0 retries, SomEngine via serveur

Validé sur PC Windows (DESKTOP-58D5CAC, 2560x1600) :
- 8 clics résolus visuellement (1 anchor_template, 1 som_text_match, 6 som_vlm)
- Score moyen 0.75, temps moyen 1.6s
- Texte tapé correctement (bonjour, test word, date, email)
- 0 retries, 2 actions non vérifiées (OK)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-03-31 14:04:41 +02:00
parent 5e0b53cfd1
commit a7de6a488b
79542 changed files with 6091757 additions and 1 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,252 @@
<!DOCTYPE html>
<html>
<head>
<title>Diagnostic Documentation - CORRIGÉ</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
.container { max-width: 900px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; }
.result { padding: 15px; margin: 10px 0; border-radius: 5px; border-left: 4px solid; }
.error { background: #f8d7da; color: #721c24; border-color: #dc3545; }
.success { background: #d4edda; color: #155724; border-color: #28a745; }
.info { background: #d1ecf1; color: #0c5460; border-color: #17a2b8; }
.warning { background: #fff3cd; color: #856404; border-color: #ffc107; }
textarea { width: 100%; height: 300px; font-family: monospace; font-size: 11px; }
.instructions { background: #e7f3ff; padding: 15px; border-radius: 5px; margin: 15px 0; }
.step { margin: 10px 0; padding: 10px; background: #f8f9fa; border-radius: 3px; }
.button { background: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin: 5px; }
</style>
</head>
<body>
<div class="container">
<h1>🧪 Diagnostic Documentation - SCRIPT CORRIGÉ</h1>
<div class="error result">
<strong>PROBLÈME IDENTIFIÉ:</strong><br>
Le script précédent avait une erreur de syntaxe JavaScript.<br>
Voici la version corrigée qui fonctionne.
</div>
<div class="instructions">
<h3>🔧 Instructions (version corrigée):</h3>
<div class="step">
<strong>1.</strong> Ouvrez <a href="http://localhost:3000" target="_blank">http://localhost:3000</a>
</div>
<div class="step">
<strong>2.</strong> Créez un élément de workflow (glissez depuis la palette)
</div>
<div class="step">
<strong>3.</strong> Cliquez sur l'élément pour ouvrir le panneau des propriétés
</div>
<div class="step">
<strong>4.</strong> Ouvrez F12 → Console
</div>
<div class="step">
<strong>5.</strong> Copiez le script ci-dessous (SANS erreur de syntaxe)
</div>
<div class="step">
<strong>6.</strong> Collez dans la console et appuyez sur Entrée
</div>
</div>
<h3>📋 Script de diagnostic CORRIGÉ:</h3>
<textarea readonly onclick="this.select()">
console.log('🧪 DIAGNOSTIC DOCUMENTATION - VERSION CORRIGÉE');
async function diagnosticDocumentation() {
console.log('');
console.log('1⃣ VÉRIFICATION ENVIRONNEMENT');
console.log('--------------------------------');
if (typeof React !== 'undefined') {
console.log('✅ React chargé');
} else {
console.log('❌ React non chargé - PROBLÈME CRITIQUE');
return;
}
console.log('');
console.log('2⃣ RECHERCHE ONGLETS');
console.log('----------------------');
const allTabs = document.querySelectorAll('[role="tab"], .MuiTab-root, [class*="tab"]');
console.log('📑 Onglets trouvés:', allTabs.length);
let documentationTab = null;
allTabs.forEach((tab, index) => {
const text = tab.textContent || '';
console.log(' Onglet', index + ':', '"' + text + '"');
if (text.toLowerCase().includes('documentation') ||
text.toLowerCase().includes('help') ||
text.toLowerCase().includes('aide')) {
documentationTab = tab;
console.log(' ✅ >>> ONGLET DOCUMENTATION TROUVÉ <<<');
}
});
if (!documentationTab) {
console.log('❌ PROBLÈME: Onglet Documentation non trouvé');
console.log('');
console.log('🔍 RECHERCHE ALTERNATIVE:');
const altElements = document.querySelectorAll('*');
let found = false;
Array.from(altElements).slice(0, 100).forEach(el => {
if (el.textContent && el.textContent.toLowerCase().includes('documentation')) {
console.log(' Trouvé "documentation" dans:', el.tagName, '-', el.textContent.substring(0, 50));
found = true;
}
});
if (!found) {
console.log(' Aucun élément contenant "documentation" trouvé');
}
return;
}
console.log('');
console.log('3⃣ TEST ACTIVATION ONGLET');
console.log('---------------------------');
const activeBefore = documentationTab.getAttribute('aria-selected') === 'true';
console.log('État AVANT clic:', activeBefore ? 'ACTIF' : 'INACTIF');
console.log('🖱️ Clic sur onglet Documentation...');
documentationTab.click();
await new Promise(resolve => setTimeout(resolve, 1500));
const activeAfter = documentationTab.getAttribute('aria-selected') === 'true';
console.log('État APRÈS clic:', activeAfter ? 'ACTIF' : 'INACTIF');
if (!activeAfter) {
console.log('❌ PROBLÈME: Onglet ne s\'active pas');
console.log('Debug état onglet:');
console.log(' aria-selected:', documentationTab.getAttribute('aria-selected'));
console.log(' classes:', documentationTab.className);
return;
}
console.log('');
console.log('4⃣ RECHERCHE CONTENU');
console.log('---------------------');
const panels = document.querySelectorAll('[role="tabpanel"]');
console.log('📋 Panneaux trouvés:', panels.length);
let contentFound = false;
panels.forEach((panel, i) => {
const isVisible = panel.offsetParent !== null &&
getComputedStyle(panel).display !== 'none';
const hasContent = panel.textContent.trim().length > 0;
const hasDocContent = panel.textContent.toLowerCase().includes('documentation') ||
panel.textContent.toLowerCase().includes('guide');
console.log(' Panneau', i + ':');
console.log(' Visible:', isVisible);
console.log(' A du contenu:', hasContent);
console.log(' Contenu doc:', hasDocContent);
if (hasContent) {
const preview = panel.textContent.substring(0, 100).replace(/\s+/g, ' ');
console.log(' Aperçu:', '"' + preview + '..."');
}
if (isVisible && hasDocContent) {
console.log(' ✅ >>> CONTENU DOCUMENTATION TROUVÉ <<<');
contentFound = true;
}
});
if (!contentFound) {
console.log('❌ PROBLÈME PRINCIPAL: Aucun contenu de documentation visible');
console.log('');
console.log('🔍 DIAGNOSTIC APPROFONDI');
console.log('-------------------------');
const docElements = document.querySelectorAll('[class*="documentation"], [class*="Documentation"]');
console.log('Composants documentation:', docElements.length);
const errorElements = document.querySelectorAll('[class*="error"], [class*="Error"]');
console.log('Éléments erreur:', errorElements.length);
try {
if (typeof TOOLS_DOCUMENTATION !== 'undefined') {
console.log('✅ TOOLS_DOCUMENTATION disponible');
} else {
console.log('❌ TOOLS_DOCUMENTATION non disponible');
}
} catch (e) {
console.log('⚠️ Erreur accès TOOLS_DOCUMENTATION:', e.message);
}
}
console.log('');
console.log('📊 RÉSUMÉ FINAL');
console.log('================');
console.log('Onglet Documentation trouvé:', documentationTab ? 'OUI' : 'NON');
console.log('Onglet s\'active au clic:', activeAfter ? 'OUI' : 'NON');
console.log('Contenu documentation visible:', contentFound ? 'OUI' : 'NON');
if (!contentFound) {
console.log('');
console.log('🚨 CONCLUSION: PROBLÈME CONFIRMÉ');
console.log('Le contenu de documentation ne s\'affiche pas correctement');
} else {
console.log('');
console.log('✅ CONCLUSION: Documentation fonctionne');
}
console.log('');
console.log('=== FIN DIAGNOSTIC ===');
}
diagnosticDocumentation().catch(error => {
console.error('❌ Erreur diagnostic:', error);
});
</textarea>
<div class="success result">
<h3>✅ Script corrigé:</h3>
<ul>
<li>Suppression des caractères d'échappement problématiques</li>
<li>Syntaxe JavaScript valide</li>
<li>Messages de debug plus clairs</li>
<li>Gestion d'erreur améliorée</li>
</ul>
</div>
<div class="warning result">
<h3>⚠️ Si le problème persiste:</h3>
<p>Essayez cette version encore plus simple :</p>
<textarea readonly onclick="this.select()" style="height: 150px;">
console.log('TEST SIMPLE DOCUMENTATION');
// Chercher onglets
const tabs = document.querySelectorAll('[role="tab"]');
console.log('Onglets:', tabs.length);
tabs.forEach((tab, i) => {
console.log(i + ':', tab.textContent);
if (tab.textContent.includes('Documentation')) {
console.log('>>> DOCUMENTATION TROUVÉ');
tab.click();
setTimeout(() => {
const panels = document.querySelectorAll('[role="tabpanel"]');
panels.forEach((p, j) => {
if (p.offsetParent !== null) {
console.log('Panel visible', j + ':', p.textContent.substring(0, 50));
}
});
}, 1000);
}
});
</textarea>
</div>
<div class="info result">
<h3>📞 Après le test:</h3>
<p><strong>Copiez TOUS les résultats</strong> et partagez-les pour identifier précisément le problème.</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,142 @@
<!DOCTYPE html>
<html>
<head>
<title>Diagnostic Documentation - Visual Workflow Builder</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
.container { max-width: 900px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; }
.result { padding: 15px; margin: 10px 0; border-radius: 5px; border-left: 4px solid; }
.error { background: #f8d7da; color: #721c24; border-color: #dc3545; }
.success { background: #d4edda; color: #155724; border-color: #28a745; }
.info { background: #d1ecf1; color: #0c5460; border-color: #17a2b8; }
.warning { background: #fff3cd; color: #856404; border-color: #ffc107; }
textarea { width: 100%; height: 350px; font-family: monospace; font-size: 11px; }
.instructions { background: #e7f3ff; padding: 15px; border-radius: 5px; margin: 15px 0; }
.step { margin: 10px 0; padding: 10px; background: #f8f9fa; border-radius: 3px; }
</style>
</head>
<body>
<div class="container">
<h1>🧪 Diagnostic Documentation - Visual Workflow Builder</h1>
<div class="error result">
<strong>PROBLÈME RAPPORTÉ:</strong><br>
L'onglet "Documentation" ne montre pas de contenu quand on clique dessus.<br>
Il y a un "effet de changement d'une fraction de seconde" mais pas de documentation visible.
</div>
<div class="instructions">
<h3>🔧 Instructions de test:</h3>
<div class="step">
<strong>1.</strong> Ouvrez <a href="http://localhost:3000" target="_blank">http://localhost:3000</a> dans un nouvel onglet
</div>
<div class="step">
<strong>2.</strong> Créez un élément de workflow (glissez un outil depuis la palette vers l'espace de travail)
</div>
<div class="step">
<strong>3.</strong> Cliquez sur l'élément créé pour ouvrir le panneau des propriétés à droite
</div>
<div class="step">
<strong>4.</strong> Ouvrez les outils de développement (F12) et allez dans l'onglet "Console"
</div>
<div class="step">
<strong>5.</strong> Copiez le script ci-dessous et collez-le dans la console
</div>
<div class="step">
<strong>6.</strong> Appuyez sur Entrée pour exécuter le script
</div>
<div class="step">
<strong>7.</strong> Copiez TOUS les résultats affichés dans la console
</div>
</div>
<h3>📋 Script de diagnostic:</h3>
<textarea readonly onclick="this.select()">
// === DIAGNOSTIC DOCUMENTATION VISUAL WORKFLOW BUILDER ===
console.log('🧪 DÉBUT DU DIAGNOSTIC DOCUMENTATION');
async function diagnosticComplet() {
console.log('\n1⃣ VÉRIFICATION ENVIRONNEMENT');
if (typeof React !== 'undefined') {
console.log('✅ React est chargé');
} else {
console.log('❌ React n\'est pas chargé - PROBLÈME CRITIQUE');
return;
}
console.log('\n2⃣ RECHERCHE DES ONGLETS');
const allTabs = document.querySelectorAll('[role="tab"], .MuiTab-root, [class*="tab"]');
console.log(`📑 ${allTabs.length} onglets trouvés`);
let documentationTab = null;
allTabs.forEach((tab, index) => {
const text = tab.textContent || '';
console.log(` ${index}: "${text}"`);
if (text.toLowerCase().includes('documentation')) {
documentationTab = tab;
console.log(' ✅ >>> ONGLET DOCUMENTATION TROUVÉ <<<');
}
});
if (!documentationTab) {
console.log('❌ PROBLÈME: Onglet Documentation non trouvé');
return;
}
console.log('\n3⃣ TEST ACTIVATION ONGLET');
const activeBefore = documentationTab.getAttribute('aria-selected') === 'true';
console.log(` Avant clic: ${activeBefore ? 'actif' : 'inactif'}`);
documentationTab.click();
await new Promise(resolve => setTimeout(resolve, 1000));
const activeAfter = documentationTab.getAttribute('aria-selected') === 'true';
console.log(` Après clic: ${activeAfter ? 'actif' : 'inactif'}`);
if (!activeAfter) {
console.log('❌ PROBLÈME: Onglet ne s\'active pas');
return;
}
console.log('\n4⃣ RECHERCHE CONTENU');
const panels = document.querySelectorAll('[role="tabpanel"]');
console.log(`📋 ${panels.length} panneaux trouvés`);
let contentFound = false;
panels.forEach((panel, i) => {
const visible = panel.offsetParent !== null;
const hasContent = panel.textContent.trim().length > 0;
console.log(` Panel ${i}: visible=${visible}, contenu=${hasContent}`);
if (visible && hasContent) {
console.log(' ✅ CONTENU TROUVÉ!');
console.log(` Aperçu: ${panel.textContent.substring(0, 100)}...`);
contentFound = true;
}
});
if (!contentFound) {
console.log('❌ PROBLÈME PRINCIPAL: Aucun contenu visible');
}
console.log('\n📊 RÉSUMÉ:');
console.log(` Onglet trouvé: ${documentationTab ? 'OUI' : 'NON'}`);
console.log(` Onglet actif: ${activeAfter ? 'OUI' : 'NON'}`);
console.log(` Contenu visible: ${contentFound ? 'OUI' : 'NON'}`);
}
diagnosticComplet().catch(console.error);
</textarea>
<div class="success result">
<h3>📞 Après le test:</h3>
<p><strong>Copiez TOUS les résultats de la console</strong> et partagez-les pour un diagnostic précis.</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,212 @@
/html>
<t>
</body>rip </sc });
});
:', error); accessibleend nonerveur front❌ Slog('console. {
error =>tch( .ca })
}
c erreur'); mais avend répondnterveur fro Se('⚠oge.l consol
{se } el e');
essibld accronten f Serveurle.log('✅nso co
ok) {sponse. if (re {
=> esponseen(rth . 00')
ost:30lhcahttp://lo fetch('
nectivitéest de con // Tn() {
d', functioontentLoadestener('DOMCddEventLient.a docum tatut
matique du stion auto // Vérifica>
<scriptv>
>
</di </div>
</ul/li>
persiste<e problèmi re d'écran s>📸 Captu <li r</li>
teuvigansole du naa correur dans l Toute eli>🔍 <li>
e-t-il ?</ s'affichcontenu✅ / ❌ Le li> <
clic ?</li>ive-t-il au glet s'actL'on<li>✅ / ❌ i>
sible ?</lest-il vition Documentaletng>✅ / ❌ L'o<li <ul>
p>
apporter :</llez rsté, veui avoir te <p>Après
t</h3>ort de Tes>📝 Rapph3 <
tep">ass="s <div cl>
</div>
></iframe"uilderkflow Bl Worisua"Vitle=t:3000" t/localhoshttp:/e src=" <ifram ion</h3>
e l'ApplicatAperçu d3>🖥️ <h">
ntainerrame-colass="if <div c
</div>>
</ul /li>
b<entationTanel DocumtiesPaperng> : Proroation</stIntégr✅ <strong> <li> /li>
n<umentatioolDoctoervice, cumentationSationTab, Doocument> : Dants</strongng>Compos✅ <stro <li> li>
ée</taurle resibation comp: Vers> ow</strongct Flea <strong>R>✅ <li >
</lirreurss eie sang> : Réusstion</stronng>Compila<li><stro
if)</li>:3000 (actst//localho: http:/strong> r Frontend<g>Serveuronst < <li>
<ul> 3>
Actuel</hatut<h3>📊 St
tep">lass="s <div c
</div>
</ul>
2</li>500le port répond sur nde backee lVérifiez qung> : d</strovice backen<strong>Ser <li> e</li>
ibl disponsit DevTools eac Utilisez Rng> :sants</stroat des compog>Ét<stron <li> /li>
work)< Net F12ent (s se chargchier fis lesue touez q : Vérifiau</strong>trong>Rése <li><s i>
s</lugeroerreurs des ez cherchConsole et 12 → : Ouvrez Ftrong>s</s'erreurConsole di><strong> <l <ul>
points :</p>s rifiez cep>Vé <
</h3>ste PersièmeProblSi le >⚠️ <h3ep">
st"warning<div class= >
iv </d
</div>
}
}, 1000);
});)}...`);
, 50ng(0nt.substril.textConte{i}: ${pane(` Panel $ole.log cons , i) => {
Each((panelforls.visiblePane
ength);anels.l, visiblePrès clic:'ibles apvisg('Panneaux loe.nsol co== null);
etParent ! => p.offser(pls).filt.from(panes = ArrayelPanleib const vis;
nel"]')le="tabpall('[roctorAuerySele document.qt panels = cons
=> {meout(() setTi);
ab.click(docT.');
e clic..log('Test dle.onso{
cdocTab) (
ifc cli le/ 4. Tester');
/TROUVÉ'NON 'TROUVÉ' : cTab ? doentation:', Docum('Ongletonsole.logon')
);
cati('documente().includesCasowertent.toL tab.textCon =>
.find(tabtabs) Array.from(st docTab =on
conentatilet Docum l'onghercher/ 3. C);
/ntent}"`)${tab.textCo}: "{i.log(` $ console =>tab, i)ach((tabs.forEth);
eng:', tabs.louvéss trgletsole.log('Ont');
con-rooMuiTab"], ."tab('[role=SelectorAll.queryument= doconst tabs nglets
cer les oerch
// 2. Chfined'); 'unde React !==', typeofct chargé:eag('Rconsole.loer React
Vérifi
// 1. =');
ENTATION ==OSTIC DOCUM=== DIAGNsole.log('con:
écutez F12) et exur (du navigateole nsvrez la coe">
// Ouodass="c<div cl
/p>
:<rs pas ne toujou ne fonctionntationcume Do l'onglet <p>Si
/h3>lème< de Probn Casic eost3>🛠️ Diagn <h
="step">ss<div cla
div>
<//ul>
<
isibles</li>age sont vd'uses es exempli>✅ L <l>
és</li documentil sontutde l'ores mètpara✅ Les <li> </li>
éons)accordpandables ( extions sontes sec✅ L <li> iche</li>
fftation s'aenu de docum>✅ Le conten <li>
/lis<essuique don cltif quand t devient acngleL'o <li>✅ li>
</est visibletation" ocumenL'onglet "D <li><ul>
on</h3>
Vérificatiints de Po <h3>🔍 ">
lass="stepv c <di div>
</</ol>
</li>
ffichervrait s'a l'outil dedeion documentat> : Laongtr contenu</sez lerifi>Véstrongi>< <l/li>
ion"<ocumentatet "Dz sur l'onglique : Cln</strong>ocumentationglet D'o lng>Testez <li><stro
e</li>vrir à droitevrait s'ouriétés du des prope pannea: L/strong> opriétés<es prng>Ouvrez lli><stro < é</li>
nt crér l'élémeiquez su Clg> :nt</stron'élémelectionnez lrong>Sé<li><st l</li>
de travai l'espace verspalette la il depuisoutsez un ong> : Glisent</str élémz ung>Crée><stron <li
</li> </a>
ilderw Bu Workfloir Visual">Ouvrttonlass="bu c="_blank"get3000" tar/localhost:ttp:/"h <a href=
onglet :l nouve> dans unrongn</stcatiol'applig>Ouvrez ><stron <li
<ol>
h3></e Testuctions d<h3>🎯 Instr p">
steass="iv cl
<div>
</d
/ul> <
on</li>xécutis d'en coureloppement ee dévrveur dli>Se <i>
éussie</lon ratili>Compil < </li>
corrigési>Imports <l
i>tible</lion compaé à la versestaurw rReact Flo <li> ul>
< s :</p>
rigéeorté cript ont éntaxe JavaScrs de syrreu<p>Les e 3>
rminée</h Teptcrition JavaS3>✅ Correc <h step">
uccess"sss=<div cla
on</h1>
tiet DocumentaglOnst Manuel - 🧪 Te <h1>>
r"="containediv class <ody>
>
<bhead
</tyle> </s }
e;
border: non px;
00: 6 height
th: 100%; wid ame {
ifr }
;
low: hidden overf
x;ius: 8p-radder bor e6;
d #dee2: 2px soli border 0;
: 20pxrgin ma
ntainer {me-co .ifra }
b3;
und: #0056 backgro {
tton:hover .bu }
x;
5p 10pxargin: m px;
dius: 4der-ra bor ne;
ion: nooratdec text-
or: white; col
#007bff;ground: ack b ;
g: 10px 20pxpaddin ock;
blay: inline-pl dis
{ .button }
px 0;
rgin: 10 ma ace;
mily: monosp font-fa s: 4px;
iuder-rador bpx;
ding: 10 pad f4;
f1f3ground: # back
ode { .c
} 721c24;
: # color45;
lor: #dc35-co bordera;
nd: #f8d7dackgrou berror {
.}
04;
564: #8lorco 7;
#ffc10olor: border-c
#fff3cd;: background ning {
.war }
724;
: #155color ;
#28a745-color: border
#d4edda;kground: bac
.success {
}dius: 4px;
ra border- 007bff;
x solid #left: 4pder- borf8f9fa;
ackground: # bpx;
padding: 15 x 0;
15pin: marg .step {
}
0.1);rgba(0,0,0, 0 2px 10px dow:-sha boxs: 8px;
order-radiu b px;
: 20ngdi pade;
whitround: kg bac ;
auton: 0 margi ;
00pxmax-width: 8 tainer {
on .c }
;
d: #f5f5f5ackgroun b 0px;
gin: 2 marrif;
ns-se samily: Arial,t-fa fon
body {yle>
<ste>
der</titlBuilorkflow Visual Wb -on Ta Documentatist <title>Te1.0">
ale=scl-ia, initevice-widthth=dent="wid cont"viewport"ame= <meta nF-8">
arset="UTta ch>
<mefr">
<headtml lang="tml>
<h<!DOCTYPE h

View File

@@ -0,0 +1,190 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Palette Cross-Machine VWB</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background: #0f172a;
color: #e2e8f0;
}
.test-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #1e293b;
border-radius: 12px;
border: 1px solid #334155;
}
.status {
padding: 10px;
margin: 10px 0;
border-radius: 8px;
font-weight: bold;
}
.success { background: #22c55e; color: white; }
.error { background: #ef4444; color: white; }
.warning { background: #f59e0b; color: white; }
.info { background: #3b82f6; color: white; }
button {
background: #1976d2;
color: white;
border: none;
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
margin: 5px;
}
button:hover {
background: #1565c0;
}
#results {
margin-top: 20px;
padding: 15px;
background: #334155;
border-radius: 8px;
}
</style>
</head>
<body>
<div class="test-container">
<h1>🧪 Test Palette Cross-Machine VWB</h1>
<p>Cette page teste la détection automatique d'URL et le fallback statique de la palette d'outils.</p>
<div class="status info">
📍 URL actuelle: <span id="currentUrl"></span>
</div>
<div>
<button onclick="testCatalogService()">🔍 Tester Service Catalogue</button>
<button onclick="testStaticFallback()">📦 Tester Fallback Statique</button>
<button onclick="testUrlDetection()">🌐 Tester Détection URL</button>
<button onclick="clearResults()">🧹 Effacer Résultats</button>
</div>
<div id="results"></div>
</div>
<script>
// Afficher l'URL actuelle
document.getElementById('currentUrl').textContent = window.location.href;
// Simuler le service catalogue (version simplifiée)
class TestCatalogService {
constructor() {
this.urls = [
window.location.origin,
'http://localhost:5004',
'http://127.0.0.1:5004'
];
this.staticActions = [
{ id: 'click_anchor', name: 'Cliquer sur Ancre', category: 'vision_ui' },
{ id: 'type_text', name: 'Saisir Texte', category: 'vision_ui' },
{ id: 'wait_for_anchor', name: 'Attendre Ancre', category: 'control' },
{ id: 'extract_text', name: 'Extraire Texte', category: 'data' },
{ id: 'hotkey', name: 'Raccourci Clavier', category: 'control' }
];
}
async testUrl(url) {
try {
const response = await fetch(`${url}/health`, {
method: 'GET',
timeout: 2000
});
return response.ok;
} catch (error) {
return false;
}
}
async detectWorkingUrl() {
for (const url of this.urls) {
if (await this.testUrl(url)) {
return url;
}
}
return null;
}
getStaticActions() {
return this.staticActions;
}
}
const catalogService = new TestCatalogService();
function addResult(message, type = 'info') {
const results = document.getElementById('results');
const div = document.createElement('div');
div.className = `status ${type}`;
div.innerHTML = message;
results.appendChild(div);
}
async function testCatalogService() {
addResult('🔍 Test du service catalogue en cours...', 'info');
const workingUrl = await catalogService.detectWorkingUrl();
if (workingUrl) {
addResult(`✅ Service catalogue détecté sur: ${workingUrl}`, 'success');
// Tester l'API catalogue
try {
const response = await fetch(`${workingUrl}/api/vwb/catalog/actions`);
if (response.ok) {
const data = await response.json();
addResult(`✅ API catalogue fonctionnelle: ${data.actions?.length || 0} actions`, 'success');
} else {
addResult(`❌ API catalogue non accessible (${response.status})`, 'error');
}
} catch (error) {
addResult(`❌ Erreur API catalogue: ${error.message}`, 'error');
}
} else {
addResult('❌ Aucun service catalogue détecté', 'error');
}
}
function testStaticFallback() {
addResult('📦 Test du fallback statique...', 'info');
const staticActions = catalogService.getStaticActions();
if (staticActions.length > 0) {
addResult(`✅ Catalogue statique disponible: ${staticActions.length} actions`, 'success');
staticActions.forEach(action => {
addResult(` - ${action.name} (${action.id})`, 'info');
});
} else {
addResult('❌ Catalogue statique vide', 'error');
}
}
async function testUrlDetection() {
addResult('🌐 Test de détection automatique d'URL...', 'info');
for (const url of catalogService.urls) {
addResult(`⏳ Test de ${url}...`, 'info');
const isWorking = await catalogService.testUrl(url);
if (isWorking) {
addResult(`✅ ${url} accessible`, 'success');
} else {
addResult(`❌ ${url} non accessible`, 'error');
}
}
}
function clearResults() {
document.getElementById('results').innerHTML = '';
}
// Test automatique au chargement
window.addEventListener('load', () => {
addResult('🚀 Page de test chargée - Prêt pour les tests', 'success');
});
</script>
</body>
</html>