fix(settings): keep the language and save settings one after the other

This commit is contained in:
lobo committed 2026-09-29 13:27:31 +02:00
1 parent 14dd59f9e0
commit f605917874
25 files changed
+423 -98

No files matched your search

+10 -1
View File
@@ -71,7 +71,16 @@ export default function AppHeader({isAuthenticated, onLogout}) {
toast.error(t('NAV.VIEW_AS.ERROR'));
};
const toggleLanguage = () => setLanguage(i18n.language === 'de' ? 'en' : 'de');
// Unsaved, the next login would switch back to Auth's language.
const toggleLanguage = async () => {
try {
const response = await setLanguage(i18n.language === 'de' ? 'en' : 'de');
if (response && !response.ok) toast.error(t('SETTINGS.ERROR_SAVE'));
} catch (err) {
console.error('Language save error:', err);
toast.error(t('INFO.ERROR.NETWORK_FAILURE'));
}
};
const toggleTheme = () => setDarkMode(!isDarkMode);
const ThemeIcon = isDarkMode ? Sun : Moon;
+17
View File
@@ -2,14 +2,18 @@
import {afterEach, describe, expect, it, vi} from 'vitest';
import {cleanup, fireEvent, render, screen} from '@testing-library/react';
import {MemoryRouter} from 'react-router-dom';
import {toast} from 'sonner';
import {useTranslation} from 'react-i18next';
import AppHeader from './AppHeader.jsx';
import {PreferencesProvider} from '../context/PreferencesContext.jsx';
vi.mock('react-i18next', () => import('../test/i18n-mock.js'));
vi.mock('sonner', () => ({toast: {success: vi.fn(), error: vi.fn()}}));
afterEach(() => {
cleanup();
localStorage.clear();
useTranslation().i18n.language = 'de';
});
const loggedInAs = (me) => {
@@ -27,6 +31,19 @@ const loggedInAs = (me) => {
const openMenu = () => fireEvent.keyDown(screen.getByRole('button', {name: 'NAV.MENU'}), {key: 'Enter'});
describe('AppHeader', () => {
it('says so when Auth refuses the language switch', async () => {
loggedInAs({role: 'USER', activeRole: 'USER', settings: {language: 'de'}});
fetch.mockImplementation(async (url, init) => (init?.method === 'PUT'
? {ok: false, status: 500, json: async () => ({})}
: {ok: true, status: 200, json: async () => ({role: 'USER', activeRole: 'USER', settings: {language: 'de'}})}));
await screen.findByRole('button', {name: 'NAV.MENU'});
openMenu();
fireEvent.click(await screen.findByRole('menuitem', {name: /NAV.LANGUAGE/}));
await vi.waitFor(() => expect(toast.error).toHaveBeenCalledWith('SETTINGS.ERROR_SAVE'));
});
// jsdom applies no media queries, so the test hides the name the way the 380px breakpoint does.
it('keeps a name on the home link when a narrow phone hides the app name', () => {
render(