feat(quick-260916-dcz): CHANGELOG.md, Seite "Was ist neu" mit Kanalfilter, Versionszeile als Link, Bauzeit-Einbettung
- CHANGELOG.md (Wurzel): Unveroeffentlicht (bwo + dyv + diese Seite, 8 Punkte) und 1.0.0 – 2026-09-15 (11 Punkte aus den Handbuechern), Alltagssprache, echte Umlaute - next.config.ts liest CHANGELOG.md zur Bauzeit nach env.TESSERA_CHANGELOG_MD; .dockerignore-Ausnahme !CHANGELOG.md und COPY-Zeile im Web-Dockerfile - lib/changelog.ts: filterChangelogForChannel (live ohne Unveroeffentlicht, beta/dev mit "Noch nicht freigegeben (Beta)", leerer Abschnitt ausgeblendet), 10 Tests - Server-Seite /changelog (MDEditor.Markdown + rehype-sanitize, Hinweis auf Beta, Leer-Text), 3 Tests; Versionszeile ist Link mit aria-label, 2 Tests - de/en: sidebar.whatsNew und Namensraum changelog; Web-Suite 49/309, tsc 0 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
This commit is contained in:
@@ -4,9 +4,33 @@ import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
/**
|
||||
* AppVersionBadge.test — die Versionszeile unten in der Seitenleiste
|
||||
* (quick-260914-ku1). Vorlage: sidebar.test.tsx (next-intl-Mock, cleanup,
|
||||
* dynamischer Import nach dem Setzen der Mocks).
|
||||
* dynamischer Import nach dem Setzen der Mocks). Seit quick-260916-dcz ist die
|
||||
* Zeile ein Link zur Seite "Was ist neu" — deshalb der `next/link`-Mock, der
|
||||
* href, className, title, aria-label und data-testid durchreicht (Tests 5/6).
|
||||
*/
|
||||
|
||||
vi.mock('next/link', () => ({
|
||||
default: ({
|
||||
children,
|
||||
href,
|
||||
className,
|
||||
title,
|
||||
'aria-label': ariaLabel,
|
||||
'data-testid': testId,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
href: string;
|
||||
className?: string;
|
||||
title?: string;
|
||||
'aria-label'?: string;
|
||||
'data-testid'?: string;
|
||||
}) => (
|
||||
<a href={href} className={className} title={title} aria-label={ariaLabel} data-testid={testId}>
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('next-intl', () => ({
|
||||
useTranslations: (ns: string) => (key: string) => {
|
||||
const map: Record<string, Record<string, string>> = {
|
||||
@@ -14,6 +38,7 @@ vi.mock('next-intl', () => ({
|
||||
'channel.beta': 'Beta',
|
||||
'channel.live': 'Live',
|
||||
'channel.dev': 'Entwicklung',
|
||||
whatsNew: 'Was ist neu',
|
||||
},
|
||||
};
|
||||
return map[ns]?.[key] ?? key;
|
||||
@@ -95,4 +120,22 @@ describe('AppVersionBadge (quick-260914-ku1)', () => {
|
||||
expect(el).toHaveTextContent('dev · Entwicklung');
|
||||
expect(el.hasAttribute('title')).toBe(false);
|
||||
});
|
||||
|
||||
it('Test 5 (Link): die Versionszeile ist ein Link auf /changelog', async () => {
|
||||
mockLoad.mockResolvedValue(null);
|
||||
const AppVersionBadge = await importBadge();
|
||||
render(<AppVersionBadge />);
|
||||
|
||||
const el = screen.getByTestId('app-version');
|
||||
expect(el.tagName).toBe('A');
|
||||
expect(el).toHaveAttribute('href', '/changelog');
|
||||
});
|
||||
|
||||
it('Test 6 (aria-label): der Link traegt den Namen "Was ist neu"', async () => {
|
||||
mockLoad.mockResolvedValue(null);
|
||||
const AppVersionBadge = await importBadge();
|
||||
render(<AppVersionBadge />);
|
||||
|
||||
expect(screen.getByTestId('app-version')).toHaveAttribute('aria-label', 'Was ist neu');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { type ApiVersionInfo, appVersion, loadApiVersion } from '@/lib/app-version';
|
||||
|
||||
@@ -9,6 +10,8 @@ import { type ApiVersionInfo, appVersion, loadApiVersion } from '@/lib/app-versi
|
||||
* `v1.0.0 · Beta` oder lokal `dev · Entwicklung` (quick-260914-ku1).
|
||||
* Der Tooltip nennt den Web-Commit und, sobald geladen, die API-Version
|
||||
* samt Kanal. "Commit" und "API" sind in beiden Sprachen gleich.
|
||||
* Seit quick-260916-dcz ist die Zeile ein Link zur Seite "Was ist neu"
|
||||
* (/changelog); der Tooltip bleibt, der Linkname steht im aria-label.
|
||||
*/
|
||||
export function AppVersionBadge() {
|
||||
const t = useTranslations('sidebar');
|
||||
@@ -30,8 +33,14 @@ export function AppVersionBadge() {
|
||||
const title = parts.length > 0 ? parts.join(' · ') : undefined;
|
||||
|
||||
return (
|
||||
<span data-testid="app-version" className="block truncate text-xs text-muted-foreground" title={title}>
|
||||
<Link
|
||||
href="/changelog"
|
||||
data-testid="app-version"
|
||||
aria-label={t('whatsNew')}
|
||||
title={title}
|
||||
className="block truncate text-xs text-muted-foreground transition-colors hover:text-foreground hover:underline"
|
||||
>
|
||||
{appVersion.version} · {t(`channel.${appVersion.channel}`)}
|
||||
</span>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user