opencroc 1.6.4 โ†’ 1.6.6

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.
@@ -34,6 +34,7 @@
34
34
  .btn:disabled { opacity:.4; cursor:not-allowed; transform:none; }
35
35
  .btn.danger { background:#8b2035; }
36
36
  .btn.danger:hover { background:var(--red); }
37
+ .mode-select { background:var(--bg-card); color:var(--text); border:1px solid #333; border-radius:3px; font-family:inherit; font-size:10px; padding:4px 6px; }
37
38
  .header .stats { margin-left:auto; display:flex; gap:14px; font-size:11px; color:var(--text-dim); }
38
39
  .header .stats span { color:var(--accent); font-weight:bold; }
39
40
  .conn-dot { width:8px; height:8px; border-radius:50%; background:var(--red); transition:background .3s; }
@@ -107,6 +108,11 @@
107
108
  <div class="actions">
108
109
  <button class="btn" id="btn-scan" title="Scan project">๐Ÿ” Scan</button>
109
110
  <button class="btn" id="btn-pipeline" title="Run full pipeline">โ–ถ Pipeline</button>
111
+ <select id="run-mode" class="mode-select" title="Test run mode">
112
+ <option value="auto">Auto</option>
113
+ <option value="reuse">Reuse</option>
114
+ <option value="managed">Managed</option>
115
+ </select>
110
116
  <button class="btn" id="btn-run-tests" title="Run generated tests" disabled>๐Ÿงช Run Tests</button>
111
117
  <button class="btn" id="btn-reports" title="Generate reports" disabled>๐Ÿ“Š Reports</button>
112
118
  <button class="btn danger" id="btn-reset" title="Reset agents">โน Reset</button>
@@ -159,7 +165,7 @@ const S = {
159
165
  project:null, graph:{nodes:[],edges:[]}, agents:[], ws:null,
160
166
  pan:{x:0,y:0}, zoom:1, dragging:false, dragStart:{x:0,y:0},
161
167
  nodePos:new Map(), hoveredNode:null, running:false, _userPanned:false,
162
- generatedFiles:[], testMetrics:null, reports:[]
168
+ generatedFiles:[], testMetrics:null, testQuality:null, reports:[], runMode:'auto'
163
169
  };
164
170
 
165
171
  async function fetchProject(){
@@ -187,8 +193,18 @@ async function doReset(){
187
193
  }
188
194
  async function doRunTests(){
189
195
  if(S.running)return; S.running=true; updateBtns();
190
- addLog('๐Ÿงช Starting test execution...');
191
- try{await fetch('/api/run-tests',{method:'POST'});}
196
+ addLog('๐Ÿงช Starting test execution ('+S.runMode+')...');
197
+ try{
198
+ const r=await fetch('/api/run-tests',{
199
+ method:'POST',
200
+ headers:{'content-type':'application/json'},
201
+ body:JSON.stringify({mode:S.runMode}),
202
+ });
203
+ if(!r.ok){
204
+ const body=await r.json().catch(()=>({error:'unknown error'}));
205
+ throw new Error(body.error||('HTTP '+r.status));
206
+ }
207
+ }
192
208
  catch(e){addLog('Run tests failed: '+e.message,'error');S.running=false;updateBtns();}
193
209
  }
194
210
  async function doReports(){
@@ -200,6 +216,7 @@ async function doReports(){
200
216
  function updateBtns(){
201
217
  document.getElementById('btn-scan').disabled=S.running;
202
218
  document.getElementById('btn-pipeline').disabled=S.running;
219
+ document.getElementById('run-mode').disabled=S.running||S.generatedFiles.length===0;
203
220
  document.getElementById('btn-run-tests').disabled=S.running||S.generatedFiles.length===0;
204
221
  document.getElementById('btn-reports').disabled=S.running||S.generatedFiles.length===0;
205
222
  }
@@ -229,14 +246,19 @@ function connectWS(){
229
246
  else addLog('โŒ Pipeline failed: '+(m.payload.error||''),'error');
230
247
  setTimeout(fetchProject,500);
231
248
  }else if(m.type==='test:complete'){
232
- S.running=false; S.testMetrics=m.payload.metrics; updateBtns(); renderResults();
249
+ S.running=false; S.testMetrics=m.payload.metrics||null; S.testQuality=m.payload.quality||null; updateBtns(); renderResults();
233
250
  const met=m.payload.metrics;
234
251
  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)';
252
+ if(met){
253
+ document.getElementById('s-results').textContent=met.passed+'โœ“ '+met.failed+'โœ—';
254
+ document.getElementById('s-results').style.color=met.failed>0?'var(--red)':'var(--accent)';
255
+ }else{
256
+ document.getElementById('s-results').textContent='setup fail';
257
+ document.getElementById('s-results').style.color='var(--red)';
258
+ }
237
259
  const rb=document.getElementById('result-badge');
238
260
  rb.textContent=m.payload.total||0; rb.style.display='inline';
239
- rb.style.background=met.failed>0?'var(--red)':'var(--accent)';
261
+ rb.style.background=(met&&met.failed>0)?'var(--red)':'var(--accent)';
240
262
  }else if(m.type==='reports:generated'){
241
263
  S.running=false; S.reports=m.payload||[]; updateBtns(); renderReports();
242
264
  addLog('๐Ÿ“Š '+S.reports.length+' reports generated');
@@ -503,6 +525,7 @@ document.getElementById('btn-pipeline').addEventListener('click',doPipeline);
503
525
  document.getElementById('btn-reset').addEventListener('click',doReset);
504
526
  document.getElementById('btn-run-tests').addEventListener('click',doRunTests);
505
527
  document.getElementById('btn-reports').addEventListener('click',doReports);
528
+ document.getElementById('run-mode').addEventListener('change',e=>{S.runMode=e.target.value;});
506
529
 
507
530
  // Tab switching
508
531
  document.querySelectorAll('.panel-tabs .tab').forEach(tab=>{
@@ -549,10 +572,37 @@ document.addEventListener('keydown',e=>{
549
572
  // Test Results rendering
550
573
  function renderResults(){
551
574
  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;}
575
+ if(!S.testMetrics&&!S.testQuality){el.innerHTML='<div style="padding:12px;color:#555;font-size:10px">No test results yet. Run Tests first.</div>';return;}
576
+ const q=S.testQuality;
577
+ if(!S.testMetrics&&q){
578
+ el.innerHTML='<div style="padding:10px">'
579
+ +'<div style="font-size:13px;font-weight:bold;margin-bottom:8px">๐Ÿงช Test Execution Results</div>'
580
+ +'<div style="padding:10px;border-radius:4px;background:#2d0a12;color:var(--red);font-size:10px;margin-bottom:10px">Setup failed before test execution.</div>'
581
+ +'<div style="font-size:11px;margin-bottom:6px">Gate Level: <span style="color:'+(q.level==='fail'?'var(--red)':q.level==='warn'?'var(--orange)':'var(--accent)')+';font-weight:bold">'+q.level.toUpperCase()+'</span></div>'
582
+ +'<div style="font-size:10px;color:var(--text-dim)">Auth: '+q.authStatus+' | Backend: '+q.backendStatus+'</div>'
583
+ +'<div style="font-size:10px;color:var(--text-dim);margin-top:4px">Reasons: '+(q.reasons&&q.reasons.length?q.reasons.join(', '):'-')+'</div>'
584
+ +'</div>';
585
+ return;
586
+ }
553
587
  const m=S.testMetrics, total=m.passed+m.failed+m.skipped+m.timedOut;
554
588
  const passRate=total>0?Math.round(m.passed/total*100):0;
555
589
  const barColor=m.failed>0?'var(--red)':'var(--accent)';
590
+ let qualityHtml='';
591
+ if(q){
592
+ const gateColor=q.level==='fail'?'var(--red)':q.level==='warn'?'var(--orange)':'var(--accent)';
593
+ qualityHtml='<div style="margin-top:12px;padding-top:10px;border-top:1px solid #2a2a45">'
594
+ +'<div style="font-size:12px;font-weight:bold;margin-bottom:8px">๐Ÿงญ Execution Quality</div>'
595
+ +'<div style="display:grid;grid-template-columns:1fr 1fr;gap:6px;font-size:10px">'
596
+ +'<div style="background:#1a1a2e;padding:6px;border-radius:4px">Gate: <span style="color:'+gateColor+';font-weight:bold">'+q.level.toUpperCase()+'</span></div>'
597
+ +'<div style="background:#1a1a2e;padding:6px;border-radius:4px">Setup Fail: '+q.setupFail+'</div>'
598
+ +'<div style="background:#1a1a2e;padding:6px;border-radius:4px">Skip Ratio: '+Math.round((q.skipRatio||0)*100)+'%</div>'
599
+ +'<div style="background:#1a1a2e;padding:6px;border-radius:4px">Auth Fail Ratio: '+Math.round((q.authFailRatio||0)*100)+'%</div>'
600
+ +'<div style="background:#1a1a2e;padding:6px;border-radius:4px">Effective Rate: '+Math.round((q.effectiveExecutionRate||0)*100)+'%</div>'
601
+ +'<div style="background:#1a1a2e;padding:6px;border-radius:4px">Auth/Backend: '+q.authStatus+' / '+q.backendStatus+'</div>'
602
+ +'</div>'
603
+ +'<div style="font-size:10px;color:var(--text-dim);margin-top:6px">Reasons: '+(q.reasons&&q.reasons.length?q.reasons.join(', '):'-')+'</div>'
604
+ +'</div>';
605
+ }
556
606
  el.innerHTML='<div style="padding:10px">'
557
607
  +'<div style="font-size:13px;font-weight:bold;margin-bottom:8px">๐Ÿงช Test Execution Results</div>'
558
608
  +'<div style="display:flex;gap:12px;margin-bottom:10px">'
@@ -564,6 +614,7 @@ function renderResults(){
564
614
  +'<div style="background:#222;border-radius:3px;height:8px;overflow:hidden">'
565
615
  +'<div style="height:100%;width:'+passRate+'%;background:'+barColor+';transition:width .5s"></div></div>'
566
616
  +'<div style="text-align:center;font-size:10px;color:var(--text-dim);margin-top:4px">Pass Rate: '+passRate+'% ('+total+' total)</div>'
617
+ +qualityHtml
567
618
  +'</div>';
568
619
  }
569
620
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencroc",
3
- "version": "1.6.4",
3
+ "version": "1.6.6",
4
4
  "description": "AI-native E2E testing framework โ€” source-aware test generation, intelligent validation, and self-healing",
5
5
  "keywords": [
6
6
  "e2e",