test(260907-ipz): failing test fuer Einzahl im Loeschdialog
Der Loeschdialog schreibt bei genau einem Mitglied und einer Freigabe
faelschlich "1 Mitglieder und 1 Modul-Freigaben". Der Mock-Uebersetzer
in groups-page.test.tsx wird um eine ICU-Plural-Aufloesung erweitert
(nach dem Vorbild der bestehenden select-Aufloesung in
grants-matrix.test.tsx), und ein neuer Test mit
{ memberCount: 1, grantCount: 1 } nagelt den korrekten Einzahl-Text
fest. Der Test ist an dieser Stelle rot, da der Uebersetzungstext noch
nicht auf ICU-Plural umgestellt ist.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K5jtbGzC5Sf9npJ3JCjKhq
This commit is contained in:
@@ -3,8 +3,11 @@ import userEvent from '@testing-library/user-event';
|
|||||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
// Namespace-aware next-intl mock: dot-path keys resolve against the
|
// Namespace-aware next-intl mock: dot-path keys resolve against the
|
||||||
// namespace passed to useTranslations(ns), and {param} placeholders are
|
// namespace passed to useTranslations(ns), {param} placeholders are
|
||||||
// substituted the same way next-intl does for plain (non-ICU) values.
|
// substituted the same way next-intl does for plain (non-ICU) values, and
|
||||||
|
// ICU `plural` templates (`{name, plural, one {...} other {...}}`) are
|
||||||
|
// resolved against the numeric param, mirroring next-intl's own behaviour
|
||||||
|
// closely enough for text assertions.
|
||||||
const messages: Record<string, Record<string, unknown>> = {
|
const messages: Record<string, Record<string, unknown>> = {
|
||||||
'admin.groups': {
|
'admin.groups': {
|
||||||
title: 'Gruppen',
|
title: 'Gruppen',
|
||||||
@@ -72,6 +75,13 @@ function resolve(ns: string, key: string, params?: Record<string, unknown>): str
|
|||||||
}
|
}
|
||||||
if (typeof val !== 'string') return key;
|
if (typeof val !== 'string') return key;
|
||||||
if (params) {
|
if (params) {
|
||||||
|
val = val.replace(
|
||||||
|
/\{(\w+),\s*plural,\s*one\s*\{([^}]*)\}\s*other\s*\{([^}]*)\}\}/g,
|
||||||
|
(_match: string, name: string, one: string, other: string) => {
|
||||||
|
const branch = Number(params[name]) === 1 ? one : other;
|
||||||
|
return branch.replace(/#/g, String(params[name]));
|
||||||
|
},
|
||||||
|
);
|
||||||
for (const [k, v] of Object.entries(params)) {
|
for (const [k, v] of Object.entries(params)) {
|
||||||
val = val.replace(`{${k}}`, String(v));
|
val = val.replace(`{${k}}`, String(v));
|
||||||
}
|
}
|
||||||
@@ -477,6 +487,24 @@ describe('DeleteGroupDialog (via AdminGroupsPage)', () => {
|
|||||||
expect(screen.getByText(/2 Modul-Freigaben/)).toBeInTheDocument();
|
expect(screen.getByText(/2 Modul-Freigaben/)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('uses singular wording for exactly one member and one module grant', async () => {
|
||||||
|
vi.stubGlobal('fetch', buildRouterFetchMock({ impact: { memberCount: 1, grantCount: 1 } }));
|
||||||
|
|
||||||
|
render(<AdminGroupsPage />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText('Buchhaltung')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
const deleteButtons = screen.getAllByText('Löschen');
|
||||||
|
await userEvent.click(deleteButtons[deleteButtons.length - 1]);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText(/hat 1 Mitglied und 1 Modul-Freigabe\./)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
expect(screen.queryByText(/1 Mitglieder/)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it('stays open and shows a visible error when DELETE /groups/:id fails', async () => {
|
it('stays open and shows a visible error when DELETE /groups/:id fails', async () => {
|
||||||
vi.stubGlobal(
|
vi.stubGlobal(
|
||||||
'fetch',
|
'fetch',
|
||||||
|
|||||||
Reference in New Issue
Block a user