feat(settings): link the Steam account through Steam
Build, Test & Push Frontend / quality-check (push) Successful in 16s
Build, Test & Push Frontend / docker (push) Successful in 25s

A Steam card in the settings links, verifies or unlinks the Steam
account through "Sign in through Steam". After the way back the page
shows the outcome and refreshes the session, so Core gets the new
Steam ID at once. Registration and settings no longer ask for a typed
Steam ID.
This commit is contained in:
lobo committed 2026-09-26 11:20:04 +02:00
1 parent 23ab5a91e7
commit ca75e6a530
13 files changed
+393 -86

No files matched your search

@@ -0,0 +1,56 @@
// @vitest-environment jsdom
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
import {act, cleanup, render, screen} from '@testing-library/react';
import {MemoryRouter} from 'react-router-dom';
import {toast} from 'sonner';
import SettingsPage from './SettingsPage.jsx';
import {PreferencesProvider} from '../context/PreferencesContext.jsx';
// Like react-i18next: a language change re-renders every subscriber with a fresh `t`.
vi.mock('react-i18next', async () => {
const {useSyncExternalStore} = await import('react');
const listeners = new Set();
const state = {language: 'de', t: (key) => key};
const i18n = {
get language() { return state.language; },
changeLanguage: vi.fn((language) => {
state.language = language;
state.t = (key) => key;
listeners.forEach((listener) => listener());
}),
};
const subscribe = (listener) => { listeners.add(listener); return () => listeners.delete(listener); };
return {useTranslation: () => ({t: useSyncExternalStore(subscribe, () => state.t), i18n}), i18n};
});
vi.mock('sonner', () => ({toast: {success: vi.fn(), error: vi.fn(), info: vi.fn()}}));
const profile = {
id: 1, email: 'a@b.de', role: 'USER', displayName: 'Lobo', steamId: '76561198005679788', steamIdVerified: true,
settings: {useDarkTheme: true, language: 'de', publicProfile: false},
};
describe('SettingsPage Steam toast', () => {
beforeEach(() => {
localStorage.setItem('tbp_session', '1');
globalThis.fetch = vi.fn(async (url, init) => (init?.method && init.method !== 'GET'
? {ok: true, status: 204, json: async () => { throw new SyntaxError('no body'); }}
: {ok: true, status: 200, json: async () => profile}));
});
afterEach(() => {
cleanup();
localStorage.clear();
vi.clearAllMocks();
});
it('shows the linked toast once, also after a language change', async () => {
render(<MemoryRouter initialEntries={['/settings?steam=linked']}><PreferencesProvider><SettingsPage/></PreferencesProvider></MemoryRouter>);
await screen.findByText('SETTINGS.STEAM_LINK.VERIFIED');
expect(toast.success).toHaveBeenCalledTimes(1);
const {i18n} = await import('react-i18next');
await act(async () => { i18n.changeLanguage('en'); });
expect(toast.success).toHaveBeenCalledTimes(1);
});
});