Merge develop and retain guest retention beside PBS navigation

This commit is contained in:
Jonatan
2026-10-16 23:56:46 +02:00
47 changed files with 2096 additions and 156 deletions
+43
View File
@@ -24,3 +24,46 @@ for (const [data, error, expected] of [
assert.equal(sandbox.exports.ProxmoxDashboard().type, expected)
}
console.log('PASS: PBS dashboard routing and loading gate do not mount PVE prewarmers')
// The PVE Backup tab keeps native guest retention alongside jobs when adding
// its PBS connection view. Exercise the shipped JSX for all three selections.
const backupSource = fs.readFileSync(path.join(__dirname, '../components/backup-tab.tsx'), 'utf8')
const backupTree = ts.createSourceFile('backup-tab.tsx', backupSource, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX)
const backupTab = backupTree.statements.find(node => ts.isFunctionDeclaration(node) && node.name?.text === 'BackupTab')
assert.ok(backupTab, 'Backup tab must keep a platform-specific view switch')
const backupCode = ts.transpileModule(ts.createPrinter().printNode(ts.EmitHint.Unspecified, backupTab, backupTree), {
compilerOptions: { module: ts.ModuleKind.CommonJS, jsx: ts.JsxEmit.ReactJSX },
}).outputText
const HostBackup = () => {}, VmBackupJobs = () => {}, BackupStorageRetention = () => {}, PBSPanel = () => {}
for (const [view, expected] of [
['host', [HostBackup]], ['guests', [VmBackupJobs, BackupStorageRetention]], ['pbs', [PBSPanel]],
]) {
const selected = []
const sandbox = {
exports: {}, HostBackup, VmBackupJobs, BackupStorageRetention, PBSPanel, DatabaseBackup: () => {},
useT: () => key => key, useState: () => [view, value => selected.push(value)],
require: () => ({ jsx: (type, props) => ({ type, props }), jsxs: (type, props) => ({ type, props }), Fragment: Symbol('Fragment') }),
}
vm.runInNewContext(backupCode, sandbox)
const visible = [], mountedHosts = [], buttons = []
const components = new Set([HostBackup, VmBackupJobs, BackupStorageRetention, PBSPanel])
function walk(node, hidden = false) {
if (Array.isArray(node)) { node.forEach(item => walk(item, hidden)); return }
if (!node || typeof node !== 'object') return
hidden ||= node.props?.className === 'hidden'
if (node.type === HostBackup) mountedHosts.push(node)
if (components.has(node.type) && !hidden) visible.push(node.type)
if (node.type === 'button') buttons.push(node)
walk(node.props?.children, hidden)
}
walk(sandbox.exports.BackupTab())
assert.deepEqual(visible, expected, `visible backup panels for ${view}`)
assert.equal(mountedHosts.length, 1, 'host backup progress must stay mounted across view changes')
assert.equal(buttons.length, 3)
assert.equal(buttons.filter(button => button.props['aria-pressed']).length, 1)
const pbsButton = buttons.find(button => button.props.children === 'pbs.title')
assert.ok(pbsButton, 'PBS navigation button must exist')
pbsButton.props.onClick()
assert.deepEqual(selected, ['pbs'])
}
console.log('PASS: host progress stays mounted, guest jobs and retention stay together, and PBS navigation remains separate')