fix(community): gemeinsames formatDate, Rechte beim Ausführen, Melden-Dialog abgesichert

formatDate liegt jetzt in pages/format.ts und wird von Meine Karten und der
Detailseite genutzt; LOGIN_NEEDED kommt aus account/with-login.ts. Ausblenden,
Löschen und Zurückziehen prüfen Admin- bzw. Autor-Recht beim Ausführen (auch nach
der Rückfrage). Ein werfendes showModal im Melden-Dialog zeigt einen Hinweis statt
eines unbehandelten Fehlers.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-04 15:35:44 +00:00
1 parent 3cec7151a6
commit be440bc8e9
7 files changed
+135 -40

No files matched your search

+84
View File
@@ -325,6 +325,74 @@ describe('Detailseite: Karte', () => {
});
});
describe('Detailseite: Rechte beim Ausführen', () => {
it('Admin-Recht verloren, Knopf noch im DOM: Ausblenden sendet nichts', async () => {
user = admin;
await mount();
const hide = buttonByText('Ausblenden')!;
user = stranger; // ohne auth-Ereignis: der alte Knopf steht noch da
hide.click();
await settle();
expect(setVisibility).not.toHaveBeenCalled();
expect(withLogin).not.toHaveBeenCalled();
});
it('Admin-Recht verloren, Knopf noch im DOM: Löschen fragt nicht einmal nach', async () => {
user = admin;
await mount();
const del = buttonByText('Löschen')!;
user = stranger;
del.click();
await settle();
expect(confirmEl()).toBeNull();
expect(withdrawCard).not.toHaveBeenCalled();
});
it('Autor-Prüfung beim Ausführen: ein anderer Nutzer kann nicht zurückziehen', async () => {
user = owner;
await mount();
const withdraw = buttonByText('Zurückziehen')!;
user = stranger;
withdraw.click();
await settle();
expect(confirmEl()).toBeNull();
expect(withdrawCard).not.toHaveBeenCalled();
});
it('Recht geht während der Rückfrage verloren: nach „Löschen“ im Dialog wird nichts gesendet', async () => {
user = admin;
await mount();
buttonByText('Löschen')!.click();
await settle();
expect(confirmEl()?.open).toBe(true);
login(stranger);
confirmButton('Löschen').click();
await settle();
expect(withdrawCard).not.toHaveBeenCalled();
expect(navigate).not.toHaveBeenCalled();
expect(errorText()).toBe('');
});
it('Recht geht während der Rückfrage verloren: auch Zurückziehen sendet nichts', async () => {
user = owner;
await mount();
buttonByText('Zurückziehen')!.click();
await settle();
login(null);
confirmButton('Zurückziehen').click();
await settle();
expect(withdrawCard).not.toHaveBeenCalled();
expect(navigate).not.toHaveBeenCalled();
});
it('ein Admin, der nicht Autor ist, kann nicht „zurückziehen“, aber löschen', async () => {
user = admin;
await mount();
expect(buttonTexts()).not.toContain('Zurückziehen');
expect(buttonTexts()).toContain('Löschen');
});
});
describe('Detailseite: Aufräumen', () => {
it('beim Verlassen wird der Auth-Abonnent abgemeldet, danach ändert sich nichts mehr', async () => {
await mount();
@@ -435,6 +503,22 @@ describe('Detailseite: Melden', () => {
expect(reportEl()).toBeNull();
});
it('lässt sich der Dialog nicht darstellen (showModal wirft), erscheint ein Hinweis statt eines unbehandelten Fehlers', async () => {
const spy = vi.spyOn(HTMLDialogElement.prototype, 'showModal').mockImplementation(() => {
throw new Error('nicht darstellbar');
});
try {
await mount();
buttonByText('Melden')!.click();
await settle();
expect(errorText()).toBe('Der Melden-Dialog konnte nicht geöffnet werden.');
expect(reportEl()).toBeNull();
expect(buttonByText('Melden')!.disabled).toBe(false);
} finally {
spy.mockRestore();
}
});
it('eine ausgeblendete Karte (nur Autor/Admin sehen sie) hat keinen Melden-Knopf', async () => {
user = owner;
getCard.mockResolvedValue(card({ hidden: true }));