feat: add openLoginPopup function and delegated click handler for auth tile login buttons
- Add openLoginPopup(remoteUrl) function after buildOfflineTileHTML that strips trailing slashes from remoteUrl before appending /login and opens a popup window with width=500,height=600 - Wire up delegated click handler for .source-tile__login-btn buttons inside bindStaticEventListeners, right after the existing delegated kill-session handler - Export openLoginPopup from module.exports Tests: 4 new tests covering openLoginPopup export, window.open call with correct URL and dimensions, trailing slash handling (with and without)
This commit is contained in:
@@ -572,6 +572,16 @@ function buildOfflineTileHTML(source) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a login popup window for a remote muxplex instance.
|
||||||
|
* Strips trailing slashes from remoteUrl before appending /login.
|
||||||
|
* @param {string} remoteUrl - The base URL of the remote instance
|
||||||
|
*/
|
||||||
|
function openLoginPopup(remoteUrl) {
|
||||||
|
var baseUrl = remoteUrl.replace(/\/+$/, '');
|
||||||
|
window.open(baseUrl + '/login', '_blank', 'width=500,height=600');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -1874,6 +1884,14 @@ function bindStaticEventListeners() {
|
|||||||
if (name) killSession(name);
|
if (name) killSession(name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
var loginBtn = e.target.closest && e.target.closest('.source-tile__login-btn');
|
||||||
|
if (!loginBtn) return;
|
||||||
|
e.stopPropagation();
|
||||||
|
var url = loginBtn.dataset.url;
|
||||||
|
if (url) openLoginPopup(url);
|
||||||
|
});
|
||||||
|
|
||||||
on($('back-btn'), 'click', closeSession);
|
on($('back-btn'), 'click', closeSession);
|
||||||
var newSessionBtn = $('new-session-btn');
|
var newSessionBtn = $('new-session-btn');
|
||||||
if (newSessionBtn) on(newSessionBtn, 'click', function() { showNewSessionInput(newSessionBtn); });
|
if (newSessionBtn) on(newSessionBtn, 'click', function() { showNewSessionInput(newSessionBtn); });
|
||||||
@@ -2262,6 +2280,7 @@ if (typeof module !== 'undefined' && module.exports) {
|
|||||||
// Federation tiles
|
// Federation tiles
|
||||||
buildAuthTileHTML,
|
buildAuthTileHTML,
|
||||||
buildOfflineTileHTML,
|
buildOfflineTileHTML,
|
||||||
|
openLoginPopup,
|
||||||
formatLastSeen,
|
formatLastSeen,
|
||||||
// Test-only helpers
|
// Test-only helpers
|
||||||
_setCurrentSessions,
|
_setCurrentSessions,
|
||||||
|
|||||||
@@ -2977,3 +2977,49 @@ test('formatLastSeen returns days ago for diff >= 86400', () => {
|
|||||||
assert.match(app.formatLastSeen(twoDaysAgo), /^\d+d ago$/, 'should return Xd ago for diff >= 86400s');
|
assert.match(app.formatLastSeen(twoDaysAgo), /^\d+d ago$/, 'should return Xd ago for diff >= 86400s');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- openLoginPopup (task-5-login-popup-flow) ---
|
||||||
|
|
||||||
|
test('openLoginPopup is exported as a function', () => {
|
||||||
|
assert.strictEqual(typeof app.openLoginPopup, 'function', 'openLoginPopup should be exported as a function');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('openLoginPopup calls window.open with correct URL and dimensions', () => {
|
||||||
|
const openCalls = [];
|
||||||
|
const origOpen = globalThis.window.open;
|
||||||
|
globalThis.window.open = (url, target, features) => { openCalls.push({ url, target, features }); };
|
||||||
|
|
||||||
|
app.openLoginPopup('http://work:8088');
|
||||||
|
|
||||||
|
globalThis.window.open = origOpen;
|
||||||
|
|
||||||
|
assert.strictEqual(openCalls.length, 1, 'window.open should be called exactly once');
|
||||||
|
assert.strictEqual(openCalls[0].url, 'http://work:8088/login', 'url should be remoteUrl + /login');
|
||||||
|
assert.strictEqual(openCalls[0].target, '_blank', 'target should be _blank');
|
||||||
|
assert.ok(openCalls[0].features.includes('width=500'), 'features should include width=500');
|
||||||
|
assert.ok(openCalls[0].features.includes('height=600'), 'features should include height=600');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('openLoginPopup appends /login to URL without trailing slash', () => {
|
||||||
|
const openCalls = [];
|
||||||
|
const origOpen = globalThis.window.open;
|
||||||
|
globalThis.window.open = (url) => { openCalls.push(url); };
|
||||||
|
|
||||||
|
app.openLoginPopup('http://work:8088');
|
||||||
|
|
||||||
|
globalThis.window.open = origOpen;
|
||||||
|
|
||||||
|
assert.strictEqual(openCalls[0], 'http://work:8088/login', 'should append /login when no trailing slash');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('openLoginPopup handles URL with trailing slash', () => {
|
||||||
|
const openCalls = [];
|
||||||
|
const origOpen = globalThis.window.open;
|
||||||
|
globalThis.window.open = (url) => { openCalls.push(url); };
|
||||||
|
|
||||||
|
app.openLoginPopup('http://work:8088/');
|
||||||
|
|
||||||
|
globalThis.window.open = origOpen;
|
||||||
|
|
||||||
|
assert.strictEqual(openCalls[0], 'http://work:8088/login', 'should strip trailing slash then append /login');
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user