fix: restore default title when device name cleared, fix stale comments, set title at load

This commit is contained in:
Brian Krabach
2026-03-31 06:36:49 -07:00
parent bee74f5c1b
commit 4e78f6f5ac
23 changed files with 66 additions and 7 deletions
+7 -7
View File
@@ -1792,9 +1792,7 @@ function openSettings() {
}
// Update document.title from device_name setting
if (ss && ss.device_name) {
document.title = ss.device_name;
}
document.title = (ss && ss.device_name) || 'muxplex';
// Multi-device enabled checkbox (with smart default: checked if remote_instances non-empty)
const multiDeviceEnabledEl = $('setting-multi-device-enabled');
@@ -2351,7 +2349,7 @@ function bindStaticEventListeners() {
on($('setting-device-name'), 'input', function() {
clearTimeout(_deviceNameDebounceTimer);
var val = this.value;
if (val) document.title = val;
document.title = val || 'muxplex';
_deviceNameDebounceTimer = setTimeout(function() {
patchServerSetting('device_name', val).then(function() {
_sources = buildSources(_serverSettings);
@@ -2359,7 +2357,7 @@ function bindStaticEventListeners() {
}, 500);
});
// Sessions tab — add remote instance button
// Multi-Device tab — add remote instance button
on($('add-remote-instance-btn'), 'click', function() {
var container = $('setting-remote-instances');
if (container) {
@@ -2367,7 +2365,7 @@ function bindStaticEventListeners() {
}
});
// Sessions tab — delegated remove handler on remote instances container
// Multi-Device tab — delegated remove handler on remote instances container
var remoteInstancesContainer = $('setting-remote-instances');
if (remoteInstancesContainer) {
remoteInstancesContainer.addEventListener('click', function(e) {
@@ -2519,7 +2517,9 @@ document.addEventListener('DOMContentLoaded', () => {
restoreState()
.then(() => {
startPolling();
loadServerSettings();
loadServerSettings().then(function() {
document.title = _serverSettings.device_name || 'muxplex';
});
startHeartbeat();
bindStaticEventListeners();
})
+59
View File
@@ -3564,3 +3564,62 @@ test('CSS style.css has scrollbar-width none for fit mode pre to hide scrollbar'
'style.css must have scrollbar-width: none for hidden scrollbar in fit mode pre'
);
});
// --- document.title quality fixes ---
test('device name input handler restores default title when value is cleared', () => {
const source = fs.readFileSync(new URL('../app.js', import.meta.url), 'utf8');
// Must use fallback form, not the conditional-only form
assert.ok(
source.includes("document.title = val || 'muxplex'"),
"device name input handler must set document.title = val || 'muxplex' to restore default when cleared"
);
assert.ok(
!source.includes("if (val) document.title = val"),
"device name input handler must NOT use conditional 'if (val) document.title = val' (skips restore)"
);
});
test('openSettings restores default title unconditionally when device_name is absent', () => {
const source = fs.readFileSync(new URL('../app.js', import.meta.url), 'utf8');
assert.ok(
source.includes("document.title = (ss && ss.device_name) || 'muxplex'"),
"openSettings must set document.title = (ss && ss.device_name) || 'muxplex' unconditionally"
);
assert.ok(
!source.includes("if (ss && ss.device_name) {\n document.title = ss.device_name;\n }"),
"openSettings must NOT use conditional block that skips restore when device_name is absent"
);
});
test('remote instance event listener comments say Multi-Device tab not Sessions tab', () => {
const source = fs.readFileSync(new URL('../app.js', import.meta.url), 'utf8');
assert.ok(
!source.includes('// Sessions tab \u2014 add remote instance button'),
"comment for add-remote-instance-btn must say 'Multi-Device tab', not 'Sessions tab'"
);
assert.ok(
!source.includes('// Sessions tab \u2014 delegated remove handler'),
"comment for delegated remove handler must say 'Multi-Device tab', not 'Sessions tab'"
);
assert.ok(
source.includes('// Multi-Device tab \u2014 add remote instance button'),
"add-remote-instance-btn comment must say '// Multi-Device tab \u2014 add remote instance button'"
);
assert.ok(
source.includes('// Multi-Device tab \u2014 delegated remove handler'),
"delegated remove handler comment must say '// Multi-Device tab \u2014 delegated remove handler'"
);
});
test('DOMContentLoaded sets document.title from server settings at page load', () => {
const source = fs.readFileSync(new URL('../app.js', import.meta.url), 'utf8');
// Find the DOMContentLoaded block
const domIdx = source.indexOf("document.addEventListener('DOMContentLoaded'");
assert.ok(domIdx !== -1, 'DOMContentLoaded handler must exist');
const domBlock = source.substring(domIdx, domIdx + 800);
assert.ok(
domBlock.includes("document.title = _serverSettings.device_name || 'muxplex'"),
"DOMContentLoaded must set document.title = _serverSettings.device_name || 'muxplex' after loadServerSettings resolves"
);
});