(mode, button)
| 8682 | const okAll = s.success; |
| 8683 | html += `<tr class="border-t border-slate-800"> |
| 8684 | <td class="px-2 py-1">${names[k]}</td> |
| 8685 | <td class="px-2 py-1 font-mono ${okAll ? 'text-gray-300' : 'text-red-300'}">${s.passed}/${s.total}</td> |
| 8686 | <td class="px-2 py-1">${_scapyLegLabel(s.scapy)}</td> |
| 8687 | <td class="px-2 py-1">${okAll ? '<span class="text-green-400">PASS</span>' : '<span class="text-red-300">FAIL</span>'}</td> |
| 8688 | </tr>`; |
| 8689 | // list any failing scenarios |
| 8690 | (s.scenarios || []).filter(x => !x.pass).forEach(x => { |
| 8691 | html += `<tr class="border-t border-slate-900"><td class="px-2 py-1 text-red-300 text-xs" colspan="4">↳ ${escapeHtml(x.name)}: expected ${escapeHtml(String(x.expect))}, got ${escapeHtml(String(x.got))}</td></tr>`; |
| 8692 | }); |
| 8693 | }); |
| 8694 | html += '</tbody></table>'; |
| 8695 | out.innerHTML = html; |
| 8696 | } catch (e) { |
| 8697 | out.innerHTML = '<p class="text-sm text-red-400">Failed: ' + escapeHtml(e.message) + '</p>'; |
| 8698 | } finally { |
| 8699 | _ndBusy(btn, false); |
| 8700 | } |
| 8701 | } |
| 8702 | |
| 8703 | // ---- DHCP Snooping (inline bridge) ----------------------------------------- |
| 8704 | function _snoopFillSelect(sel, nics, current) { |
| 8705 | if (!sel) return; |
| 8706 | sel.innerHTML = ''; |
| 8707 | nics.forEach(n => { |
| 8708 | const o = document.createElement('option'); |
no test coverage detected