opencroc 1.5.1 โ†’ 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -47,6 +47,15 @@ interface PlaywrightOverrides {
47
47
  navigationTimeout?: number;
48
48
  }
49
49
  interface RuntimeConfig {
50
+ server?: {
51
+ command?: string;
52
+ args?: string[];
53
+ cwd?: string;
54
+ healthUrl?: string;
55
+ startTimeoutMs?: number;
56
+ pollIntervalMs?: number;
57
+ reuseExisting?: boolean;
58
+ };
50
59
  /** Authentication strategy */
51
60
  auth?: {
52
61
  /** Login API URL for credential-based auth */
@@ -107,6 +107,8 @@
107
107
  <div class="actions">
108
108
  <button class="btn" id="btn-scan" title="Scan project">๐Ÿ” Scan</button>
109
109
  <button class="btn" id="btn-pipeline" title="Run full pipeline">โ–ถ Pipeline</button>
110
+ <button class="btn" id="btn-run-tests" title="Run generated tests" disabled>๐Ÿงช Run Tests</button>
111
+ <button class="btn" id="btn-reports" title="Generate reports" disabled>๐Ÿ“Š Reports</button>
110
112
  <button class="btn danger" id="btn-reset" title="Reset agents">โน Reset</button>
111
113
  </div>
112
114
  <div class="stats">
@@ -114,6 +116,7 @@
114
116
  <div>Models: <span id="s-mdl">-</span></div>
115
117
  <div>APIs: <span id="s-api">-</span></div>
116
118
  <div>Tests: <span id="s-files">-</span></div>
119
+ <div id="s-results-wrap" style="display:none">Results: <span id="s-results" style="color:var(--accent)">-</span></div>
117
120
  </div>
118
121
  <div class="conn-dot" id="conn-dot" title="WebSocket"></div>
119
122
  </header>
@@ -134,9 +137,13 @@
134
137
  <div class="panel-tabs">
135
138
  <button class="tab active" data-tab="log">๐Ÿ“‹ Log</button>
136
139
  <button class="tab" data-tab="files">๐Ÿ“„ Tests <span id="file-badge" style="display:none;background:var(--accent);color:#000;border-radius:8px;padding:0 5px;font-size:9px;margin-left:3px">0</span></button>
140
+ <button class="tab" data-tab="results">๐Ÿงช Results <span id="result-badge" style="display:none;background:var(--accent);color:#000;border-radius:8px;padding:0 5px;font-size:9px;margin-left:3px">0</span></button>
141
+ <button class="tab" data-tab="reports">๐Ÿ“Š Reports</button>
137
142
  </div>
138
143
  <div class="log-list" id="log-list"></div>
139
144
  <div class="file-list" id="file-list" style="display:none"></div>
145
+ <div class="file-list" id="results-panel" style="display:none"></div>
146
+ <div class="file-list" id="reports-panel" style="display:none"></div>
140
147
  </div>
141
148
 
142
149
  <section class="office" id="croc-office"></section>
@@ -152,7 +159,7 @@ const S = {
152
159
  project:null, graph:{nodes:[],edges:[]}, agents:[], ws:null,
153
160
  pan:{x:0,y:0}, zoom:1, dragging:false, dragStart:{x:0,y:0},
154
161
  nodePos:new Map(), hoveredNode:null, running:false, _userPanned:false,
155
- generatedFiles:[]
162
+ generatedFiles:[], testMetrics:null, reports:[]
156
163
  };
157
164
 
158
165
  async function fetchProject(){
@@ -178,9 +185,23 @@ async function doReset(){
178
185
  try{await fetch('/api/reset',{method:'POST'});}catch(e){addLog('Reset failed','error');}
179
186
  S.running=false; updateBtns(); addLog('โน Agents reset');
180
187
  }
188
+ async function doRunTests(){
189
+ if(S.running)return; S.running=true; updateBtns();
190
+ addLog('๐Ÿงช Starting test execution...');
191
+ try{await fetch('/api/run-tests',{method:'POST'});}
192
+ catch(e){addLog('Run tests failed: '+e.message,'error');S.running=false;updateBtns();}
193
+ }
194
+ async function doReports(){
195
+ if(S.running)return; S.running=true; updateBtns();
196
+ addLog('๐Ÿ“Š Generating reports...');
197
+ try{await fetch('/api/reports/generate',{method:'POST'});}
198
+ catch(e){addLog('Report gen failed: '+e.message,'error');S.running=false;updateBtns();}
199
+ }
181
200
  function updateBtns(){
182
201
  document.getElementById('btn-scan').disabled=S.running;
183
202
  document.getElementById('btn-pipeline').disabled=S.running;
203
+ document.getElementById('btn-run-tests').disabled=S.running||S.generatedFiles.length===0;
204
+ document.getElementById('btn-reports').disabled=S.running||S.generatedFiles.length===0;
184
205
  }
185
206
 
186
207
  function connectWS(){
@@ -207,6 +228,18 @@ function connectWS(){
207
228
  if(m.payload.status==='success') addLog('โœ… Pipeline complete!');
208
229
  else addLog('โŒ Pipeline failed: '+(m.payload.error||''),'error');
209
230
  setTimeout(fetchProject,500);
231
+ }else if(m.type==='test:complete'){
232
+ S.running=false; S.testMetrics=m.payload.metrics; updateBtns(); renderResults();
233
+ const met=m.payload.metrics;
234
+ document.getElementById('s-results-wrap').style.display='';
235
+ document.getElementById('s-results').textContent=met.passed+'โœ“ '+met.failed+'โœ—';
236
+ document.getElementById('s-results').style.color=met.failed>0?'var(--red)':'var(--accent)';
237
+ const rb=document.getElementById('result-badge');
238
+ rb.textContent=m.payload.total||0; rb.style.display='inline';
239
+ rb.style.background=met.failed>0?'var(--red)':'var(--accent)';
240
+ }else if(m.type==='reports:generated'){
241
+ S.running=false; S.reports=m.payload||[]; updateBtns(); renderReports();
242
+ addLog('๐Ÿ“Š '+S.reports.length+' reports generated');
210
243
  }
211
244
  }catch{}
212
245
  };
@@ -468,6 +501,8 @@ function esc(s){return s?s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>
468
501
  document.getElementById('btn-scan').addEventListener('click',doScan);
469
502
  document.getElementById('btn-pipeline').addEventListener('click',doPipeline);
470
503
  document.getElementById('btn-reset').addEventListener('click',doReset);
504
+ document.getElementById('btn-run-tests').addEventListener('click',doRunTests);
505
+ document.getElementById('btn-reports').addEventListener('click',doReports);
471
506
 
472
507
  // Tab switching
473
508
  document.querySelectorAll('.panel-tabs .tab').forEach(tab=>{
@@ -477,6 +512,8 @@ document.querySelectorAll('.panel-tabs .tab').forEach(tab=>{
477
512
  const t=tab.getAttribute('data-tab');
478
513
  document.getElementById('log-list').style.display=t==='log'?'':'none';
479
514
  document.getElementById('file-list').style.display=t==='files'?'':'none';
515
+ document.getElementById('results-panel').style.display=t==='results'?'':'none';
516
+ document.getElementById('reports-panel').style.display=t==='reports'?'':'none';
480
517
  });
481
518
  });
482
519
 
@@ -509,6 +546,58 @@ document.addEventListener('keydown',e=>{
509
546
  if(e.key==='Escape') document.getElementById('file-preview').classList.remove('visible');
510
547
  });
511
548
 
549
+ // Test Results rendering
550
+ function renderResults(){
551
+ const el=document.getElementById('results-panel');
552
+ if(!S.testMetrics){el.innerHTML='<div style="padding:12px;color:#555;font-size:10px">No test results yet. Run Tests first.</div>';return;}
553
+ const m=S.testMetrics, total=m.passed+m.failed+m.skipped+m.timedOut;
554
+ const passRate=total>0?Math.round(m.passed/total*100):0;
555
+ const barColor=m.failed>0?'var(--red)':'var(--accent)';
556
+ el.innerHTML='<div style="padding:10px">'
557
+ +'<div style="font-size:13px;font-weight:bold;margin-bottom:8px">๐Ÿงช Test Execution Results</div>'
558
+ +'<div style="display:flex;gap:12px;margin-bottom:10px">'
559
+ +'<div style="flex:1;text-align:center;background:#0d2818;padding:8px;border-radius:4px"><div style="font-size:20px;color:var(--accent)">'+m.passed+'</div><div style="font-size:9px;color:var(--text-dim)">PASSED</div></div>'
560
+ +'<div style="flex:1;text-align:center;background:#2d0a12;padding:8px;border-radius:4px"><div style="font-size:20px;color:var(--red)">'+m.failed+'</div><div style="font-size:9px;color:var(--text-dim)">FAILED</div></div>'
561
+ +'<div style="flex:1;text-align:center;background:#1a1a2e;padding:8px;border-radius:4px"><div style="font-size:20px;color:var(--orange)">'+m.skipped+'</div><div style="font-size:9px;color:var(--text-dim)">SKIPPED</div></div>'
562
+ +'<div style="flex:1;text-align:center;background:#1a1a2e;padding:8px;border-radius:4px"><div style="font-size:20px;color:var(--blue)">'+m.timedOut+'</div><div style="font-size:9px;color:var(--text-dim)">TIMEOUT</div></div>'
563
+ +'</div>'
564
+ +'<div style="background:#222;border-radius:3px;height:8px;overflow:hidden">'
565
+ +'<div style="height:100%;width:'+passRate+'%;background:'+barColor+';transition:width .5s"></div></div>'
566
+ +'<div style="text-align:center;font-size:10px;color:var(--text-dim);margin-top:4px">Pass Rate: '+passRate+'% ('+total+' total)</div>'
567
+ +'</div>';
568
+ }
569
+
570
+ // Reports rendering
571
+ function renderReports(){
572
+ const el=document.getElementById('reports-panel');
573
+ if(!S.reports.length){el.innerHTML='<div style="padding:12px;color:#555;font-size:10px">No reports generated yet. Click Reports to generate.</div>';return;}
574
+ el.innerHTML='<div style="padding:10px"><div style="font-size:13px;font-weight:bold;margin-bottom:8px">๐Ÿ“Š Generated Reports</div>'
575
+ +S.reports.map(r=>{
576
+ const icon=r.format==='html'?'๐ŸŒ':r.format==='json'?'๐Ÿ“‹':'๐Ÿ“';
577
+ const sizeKB=(r.size/1024).toFixed(1);
578
+ return '<div class="file-item" data-format="'+esc(r.format)+'" style="cursor:pointer">'
579
+ +'<div class="fname">'+icon+' '+esc(r.filename)+'</div>'
580
+ +'<div class="fmeta">'+r.format.toUpperCase()+' โ€” '+sizeKB+' KB</div></div>';
581
+ }).join('')+'</div>';
582
+ el.querySelectorAll('.file-item').forEach(item=>{
583
+ item.addEventListener('click',async()=>{
584
+ const fmt=item.getAttribute('data-format');
585
+ try{
586
+ const r=await fetch('/api/reports/'+fmt);
587
+ const content=await r.text();
588
+ if(fmt==='html'){
589
+ const w=window.open('','_blank','width=900,height=700');
590
+ w.document.write(content);w.document.close();
591
+ }else{
592
+ document.getElementById('fp-title').textContent='report.'+fmt;
593
+ document.getElementById('fp-code').textContent=content;
594
+ document.getElementById('file-preview').classList.add('visible');
595
+ }
596
+ }catch(e){addLog('Failed to load report: '+e.message,'error');}
597
+ });
598
+ });
599
+ }
600
+
512
601
  (async()=>{setupCanvas();await fetchProject();connectWS();addLog('๐ŸŠ OpenCroc Studio ready');
513
602
  window.addEventListener('resize',()=>{layoutGraph();renderCanvas();});})();
514
603
  </script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencroc",
3
- "version": "1.5.1",
3
+ "version": "1.6.1",
4
4
  "description": "AI-native E2E testing framework โ€” source-aware test generation, intelligent validation, and self-healing",
5
5
  "keywords": [
6
6
  "e2e",