feat: add buildAuthTileHTML for auth-required federation tiles
- Add buildAuthTileHTML(source) function to frontend/app.js after buildSidebarHTML - Function renders an <article class='source-tile source-tile--auth'> with device name, login button (with data-url), and hint text - HTML-escapes both name and url to prevent XSS - Export buildAuthTileHTML under '// Federation tiles' comment in module.exports - Add 5 tests covering: export, article class, device name, login button data-url, HTML escaping Task: task-2-build-auth-tile-html
This commit is contained in:
@@ -524,6 +524,23 @@ function buildSidebarHTML(session, currentSession) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the HTML string for an auth-required source tile.
|
||||||
|
* @param {{ name: string, url: string }} source
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function buildAuthTileHTML(source) {
|
||||||
|
const escapedName = escapeHtml(source.name || '');
|
||||||
|
const escapedUrl = escapeHtml(source.url || '');
|
||||||
|
return (
|
||||||
|
'<article class="source-tile source-tile--auth">' +
|
||||||
|
'<span class="source-tile__name">' + escapedName + '</span>' +
|
||||||
|
'<button class="source-tile__login-btn" data-url="' + escapedUrl + '">Log in</button>' +
|
||||||
|
'<span class="source-tile__hint">Authenticate to see sessions</span>' +
|
||||||
|
'</article>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns sessions with hidden session names removed.
|
* Returns sessions with hidden session names removed.
|
||||||
* Only hides LOCAL sessions (those with empty/absent sourceUrl) matching the
|
* Only hides LOCAL sessions (those with empty/absent sourceUrl) matching the
|
||||||
@@ -2200,6 +2217,8 @@ if (typeof module !== 'undefined' && module.exports) {
|
|||||||
mergeSources,
|
mergeSources,
|
||||||
// Filter bar
|
// Filter bar
|
||||||
renderFilterBar,
|
renderFilterBar,
|
||||||
|
// Federation tiles
|
||||||
|
buildAuthTileHTML,
|
||||||
// Test-only helpers
|
// Test-only helpers
|
||||||
_setCurrentSessions,
|
_setCurrentSessions,
|
||||||
_setViewMode,
|
_setViewMode,
|
||||||
|
|||||||
@@ -2835,3 +2835,32 @@ test('Phase 2 end-to-end: buildSources → tagSessions → mergeSources produces
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- buildAuthTileHTML ---
|
||||||
|
|
||||||
|
test('buildAuthTileHTML is exported as a function', () => {
|
||||||
|
assert.strictEqual(typeof app.buildAuthTileHTML, 'function');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('buildAuthTileHTML returns article with source-tile--auth class', () => {
|
||||||
|
const html = app.buildAuthTileHTML({ name: 'Dev Server', url: 'http://dev:8088' });
|
||||||
|
assert.ok(html.startsWith('<article'), 'html should start with <article');
|
||||||
|
assert.ok(html.includes('source-tile--auth'), 'html should include source-tile--auth class');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('buildAuthTileHTML includes device name', () => {
|
||||||
|
const html = app.buildAuthTileHTML({ name: 'Dev Server', url: 'http://dev:8088' });
|
||||||
|
assert.ok(html.includes('Dev Server'), 'html should include the device name');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('buildAuthTileHTML includes login button with data-url attribute', () => {
|
||||||
|
const html = app.buildAuthTileHTML({ name: 'Dev Server', url: 'http://dev:8088' });
|
||||||
|
assert.ok(html.includes('source-tile__login-btn'), 'html should include source-tile__login-btn class');
|
||||||
|
assert.ok(html.includes('data-url="http://dev:8088"'), 'html should include data-url attribute with correct value');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('buildAuthTileHTML escapes HTML in device name', () => {
|
||||||
|
const html = app.buildAuthTileHTML({ name: '<script>alert(1)</script>', url: '' });
|
||||||
|
assert.ok(!html.includes('<script>alert(1)</script>'), 'raw script tag should not appear in html');
|
||||||
|
assert.ok(html.includes('<script>'), 'escaped script tag should appear in html');
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user