feat: update getVisibleSessions to only hide local sessions by name

- Replace getVisibleSessions filter logic: only hide sessions where
  sourceUrl is empty/absent AND name matches hidden_sessions list
- Remote sessions with the same name as a hidden local session now
  remain visible (task-7 spec requirement)
- Export getVisibleSessions in module.exports so tests can access it

Tests added:
- 'getVisibleSessions exported and filters hidden sessions': verifies
  export and that local hidden sessions are filtered
- 'getVisibleSessions hides local sessions by name but not remote
  sessions with same name': verifies remote sessions survive

All 155 tests pass.
This commit is contained in:
Brian Krabach
2026-03-30 23:22:55 -07:00
parent 48e87af3f8
commit 4ed8303b6e
2 changed files with 63 additions and 2 deletions
+10 -2
View File
@@ -520,13 +520,20 @@ function buildSidebarHTML(session, currentSession) {
/**
* Returns sessions with hidden session names removed.
* Only hides LOCAL sessions (those with empty/absent sourceUrl) matching the
* hidden_sessions list. Remote sessions with the same name remain visible.
* Consolidates the hidden-session filter used by all render paths.
* @param {object[]} sessions
* @returns {object[]}
*/
function getVisibleSessions(sessions) {
const hidden = (_serverSettings && _serverSettings.hidden_sessions) || [];
return (sessions || []).filter((s) => !hidden.includes(s.name));
var hidden = (_serverSettings && _serverSettings.hidden_sessions) || [];
return (sessions || []).filter(function(s) {
if (hidden.length > 0 && (!s.sourceUrl) && hidden.includes(s.name)) {
return false;
}
return true;
});
}
/**
@@ -1821,6 +1828,7 @@ if (typeof module !== 'undefined' && module.exports) {
escapeHtml,
buildTileHTML,
buildSidebarHTML,
getVisibleSessions,
renderSidebar,
initSidebar,
toggleSidebar,
+53
View File
@@ -2285,6 +2285,59 @@ test('pollSessions sets auth_required on 401 response', async () => {
app._setSources([]);
});
// --- getVisibleSessions (task-7) ---
test('getVisibleSessions exported and filters hidden sessions', () => {
// Verify getVisibleSessions is exported as a function
assert.strictEqual(typeof app.getVisibleSessions, 'function', 'getVisibleSessions should be exported as a function');
// Set up server settings with hidden_sessions
app._setServerSettings({ hidden_sessions: ['secret', 'hidden-local'] });
// Local sessions (no sourceUrl) matching hidden list should be filtered
const sessions = [
{ name: 'visible', sourceUrl: '' },
{ name: 'secret', sourceUrl: '' }, // local, should be hidden
{ name: 'hidden-local', sourceUrl: '' }, // local, should be hidden
{ name: 'other', sourceUrl: '' },
];
const result = app.getVisibleSessions(sessions);
assert.strictEqual(result.length, 2, 'should hide 2 local sessions matching the hidden list');
assert.ok(result.some((s) => s.name === 'visible'), 'visible should remain');
assert.ok(result.some((s) => s.name === 'other'), 'other should remain');
assert.ok(!result.some((s) => s.name === 'secret'), 'secret (local) should be hidden');
assert.ok(!result.some((s) => s.name === 'hidden-local'), 'hidden-local should be hidden');
// Clean up
app._setServerSettings(null);
});
test('getVisibleSessions hides local sessions by name but not remote sessions with same name', () => {
// Set server settings with a session name that exists both locally and remotely
app._setServerSettings({ hidden_sessions: ['shared-name'] });
const sessions = [
{ name: 'shared-name', sourceUrl: '' }, // local — should be hidden
{ name: 'shared-name', sourceUrl: 'https://remote.example.com' }, // remote — should remain visible
{ name: 'another', sourceUrl: '' }, // local, not in hidden list — should remain
];
const result = app.getVisibleSessions(sessions);
assert.strictEqual(result.length, 2, 'should show 2 sessions (remote + another)');
// The remote one should survive
const remote = result.find((s) => s.sourceUrl === 'https://remote.example.com');
assert.ok(remote, 'remote session with same name should not be hidden');
assert.strictEqual(remote.name, 'shared-name', 'remote session name should be shared-name');
// The local one should be hidden
assert.ok(!result.some((s) => s.sourceUrl === '' && s.name === 'shared-name'), 'local session with hidden name should be removed');
// another should remain
assert.ok(result.some((s) => s.name === 'another'), 'another should remain visible');
// Clean up
app._setServerSettings(null);
});
test('pollSessions sets unreachable and applies exponential backoff on network error', async () => {
const mockStatusEl = { textContent: '', className: '' };
const mockGrid = { innerHTML: '' };