/** * Tests for hoover/components/applyconfirm.js — CancelConfirm * * Component-level tests: VNode structure of the cancel button. * Run with `node tests/test-cancelconfirm.js`. */ import { CancelConfirm, buildRows, SUBSYSTEM_LIST } from '../webui/static/hoover/components/applyconfirm.js'; let passed = 0; let failed = 0; function test(name, fn) { try { fn(); console.log(` \u2713 ${name}`); passed++; } catch (e) { console.error(` \u2717 ${name}: ${e.message}`); failed++; } } function assert(cond, msg) { if (!cond) throw new Error(msg || 'Assertion failed'); } function assertEq(a, b, msg) { if (a !== b) throw new Error(msg || `Expected ${b}, got ${a}`); } function assertIncludes(str, substr, msg) { if (!str.includes(substr)) throw new Error(msg || `Expected "${str}" to contain "${substr}"`); } console.log('Testing CancelConfirm component\n'); test('CancelConfirm renders a button vnode', () => { const vnode = CancelConfirm(); assertEq(vnode.tag, 'button'); }); test('CancelConfirm default label', () => { const vnode = CancelConfirm(); const text = vnode.ch.find(c => c.tag === '#text'); assert(text, 'should have text child'); assertEq(text.text, 'Cancel All Changes'); }); test('CancelConfirm default class is danger', () => { const vnode = CancelConfirm(); assertIncludes(vnode.props.class, 'btn-danger'); assertIncludes(vnode.props.class, 'btn'); }); test('CancelConfirm accepts a custom class', () => { const vnode = CancelConfirm({ cls: 'btn btn-sm btn-danger' }); assertEq(vnode.props.class, 'btn btn-sm btn-danger'); }); test('CancelConfirm accepts a custom label', () => { const vnode = CancelConfirm({ label: 'Discard Changes' }); const text = vnode.ch.find(c => c.tag === '#text'); assertEq(text.text, 'Discard Changes'); }); test('CancelConfirm has a click handler', () => { const vnode = CancelConfirm(); assert(typeof vnode.props['on:click'] === 'function', 'on:click should be a function'); }); // === shared modal row builder (used by the cancel modal) === test('buildRows still drives the cancel modal rows', () => { const data = { firewall: { needs_apply: true, changes: [{ summary: 'Zone internal: interfaces changed', detail: '' }] }, dnsmasq: { pending_changes: true, changes: [{ summary: 'x', detail: '' }] }, }; const rows = buildRows(data, {}); assertEq(rows.length, SUBSYSTEM_LIST.length); const fwRow = rows[0]; assertIncludes(fwRow.props.class, 'pending'); const dmRow = rows[1]; assertIncludes(dmRow.props.class, 'pending'); }); console.log(`\n${passed} passed, ${failed} failed`); process.exit(failed > 0 ? 1 : 0);