feat(web): Einstellungen → Desktop-App zeigt in der App den verbundenen Server
- DesktopAppSettings rendert im Desktop-Client (useIsDesktopClient) einen Block "Verbunden mit: {origin}" plus Hinweis auf "Server-Adresse ändern…" im Infobereich-Menü; im Browser bleibt der Block weg
- Neue i18n-Schlüssel settings.desktop.connectedTo/changeHint in de.json und en.json
- Test 4 (Cookie tessera_desktop=1) und Test 5 (ohne Cookie) ergänzt; RED zuerst (Test 4 schlug auf der Zielbehauptung fehl), dann GREEN
- Alle 431 Web-Tests und type-check grün
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { cleanup, render, screen } from '@testing-library/react';
|
||||
import { act, cleanup, render, screen } from '@testing-library/react';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { DESKTOP_COOKIE_NAME } from '@/lib/desktop-client';
|
||||
import { DesktopAppSettings } from './desktop-app-settings';
|
||||
|
||||
/**
|
||||
@@ -34,9 +35,14 @@ vi.mock('@/lib/desktop', async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
function clearDesktopCookie() {
|
||||
document.cookie = `${DESKTOP_COOKIE_NAME}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.clearAllMocks();
|
||||
clearDesktopCookie();
|
||||
});
|
||||
|
||||
const windowsFile = {
|
||||
@@ -102,4 +108,24 @@ describe('DesktopAppSettings (18-03)', () => {
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Test 4 (im Desktop-Client): zeigt verbundenen Server und Änderungshinweis', async () => {
|
||||
document.cookie = `${DESKTOP_COOKIE_NAME}=1; path=/`;
|
||||
loadDesktopLatest.mockResolvedValue(null);
|
||||
render(<DesktopAppSettings />);
|
||||
|
||||
expect(await screen.findByText('Verbunden mit: http://localhost:3000')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('Ändern über das Tessera-Symbol im Infobereich → „Server-Adresse ändern…“'),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByTestId('desktop-connected')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Test 5 (im Browser): kein Block ohne Desktop-Cookie', async () => {
|
||||
loadDesktopLatest.mockResolvedValue(null);
|
||||
render(<DesktopAppSettings />);
|
||||
await act(async () => {});
|
||||
|
||||
expect(screen.queryByTestId('desktop-connected')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocale, useTranslations } from 'next-intl';
|
||||
import { desktopDownloadUrl, type DesktopFileInfo, type DesktopLatestInfo, formatFileSize, loadDesktopLatest } from '@/lib/desktop';
|
||||
import { useIsDesktopClient } from '@/lib/desktop-client';
|
||||
|
||||
const BUTTON_CLASS =
|
||||
'inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2.5 text-sm font-medium text-primary-foreground hover:opacity-90';
|
||||
@@ -59,11 +60,17 @@ function DownloadButton({
|
||||
/**
|
||||
* Inhalt der Einstellungsseite "Desktop-App" (D-12): vier erklaerende
|
||||
* Saetze, dann Version/Downloads oder ein Hinweis, wenn der Server keine
|
||||
* Pakete traegt (`loadDesktopLatest()` liefert `null`).
|
||||
* Pakete traegt (`loadDesktopLatest()` liefert `null`). Im Desktop-Client
|
||||
* (260917-jn2) zusaetzlich ein Block "Verbunden mit: {origin}" -- `isDesktop`
|
||||
* ist im Server-HTML und im ersten Client-Render false (Hook mit
|
||||
* `useEffect`), der Block rendert also erst nach der Hydration, weshalb
|
||||
* `window.location.origin` hier direkt gelesen werden darf (kein
|
||||
* Hydration-Fehler).
|
||||
*/
|
||||
export function DesktopAppSettings() {
|
||||
const t = useTranslations('settings');
|
||||
const locale = useLocale();
|
||||
const isDesktop = useIsDesktopClient();
|
||||
const [info, setInfo] = useState<DesktopLatestInfo | null | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -85,6 +92,16 @@ export function DesktopAppSettings() {
|
||||
<p className="text-sm text-muted-foreground">{t('desktop.tray')}</p>
|
||||
<p className="text-sm text-muted-foreground">{t('desktop.update')}</p>
|
||||
|
||||
{isDesktop && (
|
||||
<div
|
||||
data-testid="desktop-connected"
|
||||
className="mt-4 space-y-1 rounded border border-border bg-muted/30 p-3 text-sm"
|
||||
>
|
||||
<p className="text-foreground">{t('desktop.connectedTo', { origin: window.location.origin })}</p>
|
||||
<p className="text-muted-foreground">{t('desktop.changeHint')}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{info === null && <p className="mt-4 text-sm text-muted-foreground">{t('desktop.unavailable')}</p>}
|
||||
|
||||
{info && (
|
||||
|
||||
Reference in New Issue
Block a user