fix(favorites): Logo auch fuer Seiten, die es per JavaScript setzen
hosteurope.de liefert im HTML nur einen leeren data:-Platzhalter, das echte Symbol setzt erst JavaScript; /favicon.ico antwortet mit HTML. Die Kachel zeigte deshalb nur den Buchstaben. Scheitert das gespeicherte Symbol, fragt getIconBytes jetzt einmal den DuckDuckGo-Symboldienst - nur fuer oeffentlich erreichbare Seiten, interne Hostnamen verlassen das Haus nicht; kennt der Dienst nichts (404), bleibt es beim Buchstaben. Wirkt auch fuer bestehende Favoriten. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -220,7 +220,11 @@ function expectBoundCall(
|
||||
}
|
||||
|
||||
function makeIconDiscovery(
|
||||
overrides: Partial<{ discoverFavoriteIconUrl: any; fetchIconBytes: any }> = {},
|
||||
overrides: Partial<{
|
||||
discoverFavoriteIconUrl: any;
|
||||
fetchIconBytes: any;
|
||||
fetchPublicServiceIconBytes: any;
|
||||
}> = {},
|
||||
) {
|
||||
return {
|
||||
discoverFavoriteIconUrl:
|
||||
@@ -229,6 +233,11 @@ function makeIconDiscovery(
|
||||
fetchIconBytes:
|
||||
overrides.fetchIconBytes ??
|
||||
vi.fn(async () => ({ contentType: 'image/png', body: Buffer.from('png') })),
|
||||
fetchPublicServiceIconBytes:
|
||||
overrides.fetchPublicServiceIconBytes ??
|
||||
vi.fn(async () => {
|
||||
throw new Error('icon service: unknown');
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -511,6 +520,35 @@ describe('FavoritesService — Bindung an forTenant() (260911-gwh)', () => {
|
||||
await expect(service.getIconBytes('t2', 'f1', 'user-a1')).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
|
||||
it('quick-261001-hbi: gespeichertes Symbol scheitert -> Symbol-Dienst mit der Seiten-URL', async () => {
|
||||
const prisma = makeFakePrisma([baseRow]);
|
||||
const iconDiscovery = makeIconDiscovery({
|
||||
fetchIconBytes: vi.fn(async () => {
|
||||
throw new Error('not an image');
|
||||
}),
|
||||
fetchPublicServiceIconBytes: vi.fn(async () => ({
|
||||
contentType: 'image/png',
|
||||
body: Buffer.from('ddg'),
|
||||
})),
|
||||
});
|
||||
const service = new FavoritesService(prisma as any, iconDiscovery as any);
|
||||
|
||||
const result = await service.getIconBytes('t1', 'f1', 'user-a1');
|
||||
|
||||
expect(iconDiscovery.fetchPublicServiceIconBytes).toHaveBeenCalledWith(baseRow.url);
|
||||
expect(result.body).toEqual(Buffer.from('ddg'));
|
||||
});
|
||||
|
||||
it('quick-261001-hbi: gespeichertes Symbol klappt -> Symbol-Dienst wird nicht gefragt', async () => {
|
||||
const prisma = makeFakePrisma([baseRow]);
|
||||
const iconDiscovery = makeIconDiscovery();
|
||||
const service = new FavoritesService(prisma as any, iconDiscovery as any);
|
||||
|
||||
await service.getIconBytes('t1', 'f1', 'user-a1');
|
||||
|
||||
expect(iconDiscovery.fetchPublicServiceIconBytes).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('fetchIconBytes wirft -> HttpException mit Status 502', async () => {
|
||||
const prisma = makeFakePrisma([baseRow]);
|
||||
const iconDiscovery = makeIconDiscovery({
|
||||
|
||||
Reference in New Issue
Block a user