fix(account): Konto-Menü zeichnet bei unverändertem Namen nicht neu (Dropdown und Fokus bleiben)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-05 07:46:02 +00:00
1 parent 04404ffdae
commit f46a69df68
2 files changed
+60 -1

No files matched your search

+51
View File
@@ -262,6 +262,57 @@ describe('Konto-Menü: Benutzername', () => {
expect(buttonByText('Benutzername ändern')).toBeDefined(); expect(buttonByText('Benutzername ändern')).toBeDefined();
}); });
it('meldet onUsernameChange denselben Namen noch einmal (Lesen des eigenen Profils nach dem Start), bleibt das Menü unangetastet: offen und mit dem Fokus', () => {
signedIn();
mocks.name = 'Kenso';
menu.ready();
avatar()!.click();
const before = { avatar: avatar(), panel: panel(), head: head() };
const signOut = buttonByText('Abmelden')!;
signOut.focus();
setName('u1', 'Kenso');
expect(avatar()).toBe(before.avatar); // dieselben Elemente, nichts wurde neu gebaut
expect(panel()).toBe(before.panel);
expect(head()).toBe(before.head);
expect(panel()?.hidden).toBe(false);
expect(avatar()?.getAttribute('aria-expanded')).toBe('true');
expect(document.activeElement).toBe(signOut);
expect(nameLine()?.textContent).toBe('@Kenso');
});
it('ein anderer Name oder nur eine andere Schreibweise zeichnet dagegen neu', () => {
signedIn();
mocks.name = 'kenso';
menu.ready();
const before = avatar();
setName('u1', 'Kenso'); // „kenso“ → „Kenso“ ist erlaubt (Spec § 4) und soll zu sehen sein
expect(avatar()).not.toBe(before);
expect(nameLine()?.textContent).toBe('@Kenso');
const second = avatar();
setName('u1', 'Mia');
expect(avatar()).not.toBe(second);
expect(nameLine()?.textContent).toBe('@Mia');
});
it('die Namensmeldung eines anderen Kontos ändert nichts am Menü des angemeldeten', () => {
signedIn();
mocks.name = 'Kenso'; // der Name des angemeldeten Kontos bleibt
menu.ready();
avatar()!.click();
const before = panel();
for (const fn of [...mocks.nameListeners]) fn('u2', 'Mia'); // das Konto u2 hat sich umbenannt (etwa in einem eben beendeten Aufruf)
expect(panel()).toBe(before);
expect(panel()?.hidden).toBe(false);
expect(nameLine()?.textContent).toBe('@Kenso');
});
it('abgemeldet bleibt der Anmelden-Knopf stehen, auch wenn ein Name gemeldet wird (das Konto, das speicherte, ist nicht mehr angemeldet)', () => {
menu.ready();
const signIn = buttonByText('Anmelden');
for (const fn of [...mocks.nameListeners]) fn('u2', 'Mia');
expect(buttonByText('Anmelden')).toBe(signIn);
});
it('nach dem Abmelden ist das Menü unabhängig vom Namen wieder „Anmelden“', () => { it('nach dem Abmelden ist das Menü unabhängig vom Namen wieder „Anmelden“', () => {
signedIn(); signedIn();
mocks.name = 'Kenso'; mocks.name = 'Kenso';
+9 -1
View File
@@ -20,10 +20,14 @@ export function mountAccountMenu(slot: HTMLElement): AccountMenu {
let isReady = false; let isReady = false;
// Hebt die Dokument-Listener des gerade offenen Menüs wieder auf (null: kein Menü gezeichnet). // Hebt die Dokument-Listener des gerade offenen Menüs wieder auf (null: kein Menü gezeichnet).
let detach: (() => void) | null = null; let detach: (() => void) | null = null;
// Der Name, den das gezeichnete Menü zeigt (null: keiner oder gar kein Konto-Menü). Meldet `onUsernameChange` denselben Namen noch einmal
// (etwa das Lesen des eigenen Profils nach dem Start), bleibt das Menü stehen: ein neu gebautes Dropdown wäre zu und verlöre den Fokus.
let shownName: string | null = null;
function render(): void { function render(): void {
detach?.(); detach?.();
detach = null; detach = null;
shownName = null;
if (!isReady) { if (!isReady) {
slot.replaceChildren(); slot.replaceChildren();
return; return;
@@ -50,6 +54,7 @@ export function mountAccountMenu(slot: HTMLElement): AccountMenu {
); );
// Mit Benutzernamen steht „@name“ oben und die E-Mail klein darunter; ohne Namen (noch nicht gelesen oder nicht gewählt) nur die E-Mail. // Mit Benutzernamen steht „@name“ oben und die E-Mail klein darunter; ohne Namen (noch nicht gelesen oder nicht gewählt) nur die E-Mail.
const name = myUsername(); const name = myUsername();
shownName = name;
const email = el('span', { class: 'account-email', title: user.email }, user.email); const email = el('span', { class: 'account-email', title: user.email }, user.email);
const head = el( const head = el(
'div', 'div',
@@ -112,7 +117,10 @@ export function mountAccountMenu(slot: HTMLElement): AccountMenu {
const off = onAuthChange(render); const off = onAuthChange(render);
// Der Name steht fest oder ändert sich (gelesen nach dem Start, gespeichert im Dialog): das Menü zeigt gleich den neuen. // Der Name steht fest oder ändert sich (gelesen nach dem Start, gespeichert im Dialog): das Menü zeigt gleich den neuen.
const offName = onUsernameChange(render); const offName = onUsernameChange(() => {
if (myUsername() === shownName) return; // nichts Neues zu zeigen (derselbe Name, oder ein anderes Konto hat gespeichert)
render();
});
render(); render();
return { return {