Compare commits
2 Commits
1c757fb76e
...
6999b3dd73
| Author | SHA1 | Date | |
|---|---|---|---|
| 6999b3dd73 | |||
| 4d6a27194f |
@ -33,9 +33,10 @@ test('instance name changed in the general settings form persists', async ({ bro
|
|||||||
// Scoped to the card: the page has several forms with status regions.
|
// Scoped to the card: the page has several forms with status regions.
|
||||||
await expect(generalCard.getByRole('status')).toHaveText(/^(Saved\.|Gespeichert\.)$/);
|
await expect(generalCard.getByRole('status')).toHaveText(/^(Saved\.|Gespeichert\.)$/);
|
||||||
|
|
||||||
// The TopBar shows the new name without a reload — the save invalidates
|
// The TopBar and the document title show the new name without a reload —
|
||||||
// the branding query the TopBar reads from.
|
// the save invalidates the branding query both read from (issue #323).
|
||||||
await expect(page.locator('.topbar__brand')).toHaveText(newName);
|
await expect(page.locator('.topbar__brand')).toHaveText(newName);
|
||||||
|
await expect(page).toHaveTitle(new RegExp(`${newName}$`));
|
||||||
|
|
||||||
// The proof the form really persisted: the value survives a reload and
|
// The proof the form really persisted: the value survives a reload and
|
||||||
// the api returns it.
|
// the api returns it.
|
||||||
|
|||||||
@ -34,7 +34,7 @@ test('mode marked: card, checkbox marking, and point-of-choice marking', async (
|
|||||||
// select value — compliant choice clears it, violating choice brings it
|
// select value — compliant choice clears it, violating choice brings it
|
||||||
// back, no save in between.
|
// back, no save in between.
|
||||||
const regField = page.locator('label.field', {
|
const regField = page.locator('label.field', {
|
||||||
has: page.locator('select[name="auth.registrationMode"]'),
|
has: page.locator('select[name="registrationMode"]'),
|
||||||
});
|
});
|
||||||
const regSelect = regField.locator('select');
|
const regSelect = regField.locator('select');
|
||||||
await regSelect.selectOption('open');
|
await regSelect.selectOption('open');
|
||||||
@ -72,7 +72,7 @@ test('mode hidden: rows disappear, notes mark the hiding, a11y clean', async ({
|
|||||||
|
|
||||||
// Value-listed control: the compliant registration mode keeps only its
|
// Value-listed control: the compliant registration mode keeps only its
|
||||||
// compliant choice (seed leaves it open = violating? then all options).
|
// compliant choice (seed leaves it open = violating? then all options).
|
||||||
const regSelect = page.locator('select[name="auth.registrationMode"]');
|
const regSelect = page.locator('select[name="registrationMode"]');
|
||||||
const regField = page.locator('label.field', { has: regSelect });
|
const regField = page.locator('label.field', { has: regSelect });
|
||||||
const optionCount = await regSelect.locator('option').count();
|
const optionCount = await regSelect.locator('option').count();
|
||||||
const marked = await regField.locator('.vs-nfd-mark').count();
|
const marked = await regField.locator('.vs-nfd-mark').count();
|
||||||
|
|||||||
@ -1,22 +1,33 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
import { useBranding } from '../branding/use-branding';
|
||||||
|
|
||||||
const APP_NAME = 'Dorfteich';
|
const APP_NAME = 'Dorfteich';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route-specific document title (issue #163, WCAG 2.4.2): joins the given
|
* Route-specific document title (issue #163, WCAG 2.4.2): joins the given
|
||||||
* parts with the app name ("Page — Pond — Dorfteich"). Empty/undefined
|
* parts with the instance name ("Page — Pond — My Wiki"). Empty/undefined
|
||||||
* parts are skipped, so callers can pass still-loading data directly.
|
* parts are skipped, so callers can pass still-loading data directly.
|
||||||
* Falls back to the bare app name on unmount.
|
* Falls back to the bare instance name on unmount.
|
||||||
|
*
|
||||||
|
* The trailing name is the OPERATOR'S instance name, not the product name
|
||||||
|
* (issue #323) — same reasoning as the TopBar brand (issue #306). Until
|
||||||
|
* the branding query resolves (or when it cannot, e.g. maintenance mode)
|
||||||
|
* the shipped default keeps the title stable, so an untouched instance
|
||||||
|
* reads exactly as before.
|
||||||
*/
|
*/
|
||||||
export function useDocumentTitle(...parts: (string | null | undefined)[]): void {
|
export function useDocumentTitle(...parts: (string | null | undefined)[]): void {
|
||||||
const joined = [...parts.filter(Boolean), APP_NAME].join(' — ');
|
const appName = useBranding()?.instanceName.trim() || APP_NAME;
|
||||||
|
const joined = [...parts.filter(Boolean), appName].join(' — ');
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = joined;
|
document.title = joined;
|
||||||
}, [joined]);
|
}, [joined]);
|
||||||
useEffect(
|
useEffect(
|
||||||
|
// On unmount only in effect: `joined` always changes with `appName`,
|
||||||
|
// so the title effect above re-runs right after this cleanup.
|
||||||
() => () => {
|
() => () => {
|
||||||
document.title = APP_NAME;
|
document.title = appName;
|
||||||
},
|
},
|
||||||
[],
|
[appName],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user