fix(favorites): Symbol-Adresse auch speichern, wenn nur der Browser sie laden kann
- API: ausdrueckliche iconUrl wird nur auf Form (http/https, <= 2048) geprueft und auch gespeichert, wenn der Server sie nicht abrufen kann; keine 422 mehr - Erkennung: Seite mit Fehlerstatus, aber HTML mit <link rel=icon>, liefert diesen Verweis (docuvita); og:image einer Fehlerseite zaehlt nicht - Kachel: Proxy -> iconUrl direkt im Browser (no-referrer, nur http/https) -> Origin-Favicon -> Buchstabe - Meldung iconUrlUnreachable (de/en) entfernt, Hinweis zum Vorrang angepasst Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -490,6 +490,75 @@ describe('FavoritesWidget', () => {
|
||||
expect(screen.getByTestId('letter-fallback-fav-id-1')).toHaveTextContent('G');
|
||||
});
|
||||
|
||||
it('ausdrueckliche Symbol-Adresse (260929-lh3): Proxy -> Browser laedt iconUrl direkt (no-referrer) -> Origin-Favicon -> Buchstabe', async () => {
|
||||
mockFetch.mockResolvedValue([
|
||||
{
|
||||
id: 'fav-id-9',
|
||||
widgetId: 'fav-1',
|
||||
title: 'Docuvita',
|
||||
url: 'https://docuvita.ctl.local/server/services/web/',
|
||||
iconUrl: 'https://docuvita.ctl.local/webclient/docuvita/resources/brandimage/favicon.ico',
|
||||
position: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
render(<FavoritesWidget instanceId="fav-1" config={{}} isEditMode={false} />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Docuvita')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
act(() => {
|
||||
fireEvent.error(screen.getByTestId('icon-proxy-fav-id-9'));
|
||||
});
|
||||
|
||||
const direct1 = screen.getByTestId('icon-direct-fav-id-9') as HTMLImageElement;
|
||||
expect(direct1.src).toBe(
|
||||
'https://docuvita.ctl.local/webclient/docuvita/resources/brandimage/favicon.ico',
|
||||
);
|
||||
expect(direct1.getAttribute('referrerpolicy')).toBe('no-referrer');
|
||||
|
||||
act(() => {
|
||||
fireEvent.error(direct1);
|
||||
});
|
||||
|
||||
const direct2 = screen.getByTestId('icon-direct-fav-id-9') as HTMLImageElement;
|
||||
expect(direct2.src).toBe('https://docuvita.ctl.local/favicon.ico');
|
||||
|
||||
act(() => {
|
||||
fireEvent.error(direct2);
|
||||
});
|
||||
|
||||
expect(screen.queryByTestId('icon-direct-fav-id-9')).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId('letter-fallback-fav-id-9')).toHaveTextContent('D');
|
||||
});
|
||||
|
||||
it('iconUrl mit Nicht-http-Schema wird NIE direkt geladen (javascript:/data:)', async () => {
|
||||
mockFetch.mockResolvedValue([
|
||||
{
|
||||
id: 'fav-id-8',
|
||||
widgetId: 'fav-1',
|
||||
title: 'Boese',
|
||||
url: 'https://boese.example',
|
||||
iconUrl: 'javascript:alert(1)',
|
||||
position: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
render(<FavoritesWidget instanceId="fav-1" config={{}} isEditMode={false} />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Boese')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
act(() => {
|
||||
fireEvent.error(screen.getByTestId('icon-proxy-fav-id-8'));
|
||||
});
|
||||
|
||||
const direct = screen.getByTestId('icon-direct-fav-id-8') as HTMLImageElement;
|
||||
expect(direct.src).toBe('https://boese.example/favicon.ico');
|
||||
});
|
||||
|
||||
it('kein Direktbild bei Nicht-http-URL', async () => {
|
||||
mockFetch.mockResolvedValue([
|
||||
{ id: 'fav-id-3', widgetId: 'fav-1', title: 'Ablage', url: 'ftp://files.example', iconUrl: null, position: 0 },
|
||||
@@ -730,8 +799,8 @@ describe('FavoritesWidget', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('updateFavorite wirft FavoriteRequestError(iconUrlUnreachable) -> Meldung im Formular (role alert), Formular bleibt offen, uploadFavoriteIcon NICHT aufgerufen', async () => {
|
||||
mockUpdate.mockRejectedValue(new FavoriteRequestError('iconUrlUnreachable'));
|
||||
it('updateFavorite wirft (z. B. 400 ungueltige Adresse) -> allgemeine Meldung favorites.error im Formular (role alert), Formular bleibt offen, uploadFavoriteIcon NICHT aufgerufen', async () => {
|
||||
mockUpdate.mockRejectedValue(new Error('Failed to update favorite'));
|
||||
|
||||
render(<FavoritesWidget instanceId="fav-1" config={{}} isEditMode={true} />);
|
||||
|
||||
@@ -753,7 +822,7 @@ describe('FavoritesWidget', () => {
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole('alert')).toHaveTextContent('favorites.iconUrlUnreachable');
|
||||
expect(screen.getByRole('alert')).toHaveTextContent('favorites.error');
|
||||
});
|
||||
expect(mockUploadIcon).not.toHaveBeenCalled();
|
||||
expect(screen.getByTestId('favorite-icon-upload-fav-id-1')).toBeInTheDocument();
|
||||
|
||||
Reference in New Issue
Block a user