import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest';
import {
FAVORITE_ICON_MAX_BYTES,
detectFavoriteIconMime,
favoriteIconAbsolutePath,
favoriteIconExtension,
removeFavoriteIconFileBestEffort,
resolveFavoriteIconsDir,
} from './favorite-icon-files';
/**
* favorite-icon-files.spec — NEU (quick-260923-lrr).
*
* Erkennung (Muster dashboard-image-rules.spec.ts): PNG/JPEG/GIF/WebP wie
* `detectImageMime`, dazu ICO (Kopfstueck, kein CUR) und SVG (Praefix-Form,
* kein `` davor). Pfadbildung: Endung aus dem Typ, Segmente nur aus
* Buchstaben/Ziffern/Bindestrich, Ergebnis muss im Symbolverzeichnis liegen
* (T-LRR-01). `FAVORITE_ICONS_DIR` steuert das Verzeichnis in Tests, wie
* `DASHBOARD_IMAGES_DIR` es fuer die Bilderrahmen-Bilder tut.
*/
function bytes(...parts: (number[] | string)[]): Uint8Array {
const out: number[] = [];
for (const p of parts) {
if (typeof p === 'string') {
for (const ch of p) out.push(ch.charCodeAt(0));
} else {
out.push(...p);
}
}
return Uint8Array.from(out);
}
describe('detectFavoriteIconMime (quick-260923-lrr)', () => {
it('PNG/JPEG/GIF/WebP-Signaturen ergeben dieselben Typen wie detectImageMime', () => {
expect(
detectFavoriteIconMime(bytes([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], [0, 0, 0, 13])),
).toBe('image/png');
expect(detectFavoriteIconMime(bytes([0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10], 'JFIF'))).toBe('image/jpeg');
expect(detectFavoriteIconMime(bytes('GIF89a', [1, 0, 1, 0]))).toBe('image/gif');
expect(detectFavoriteIconMime(bytes('RIFF', [0x24, 0x00, 0x00, 0x00], 'WEBP', 'VP8 '))).toBe(
'image/webp',
);
});
it('Bytes 00 00 01 00 (mindestens 6 Bytes) ergeben image/x-icon', () => {
expect(detectFavoriteIconMime(bytes([0x00, 0x00, 0x01, 0x00, 0x01, 0x00]))).toBe('image/x-icon');
});
it('zu kurzes ICO-Kopfstueck (weniger als 6 Bytes) ergibt null', () => {
expect(detectFavoriteIconMime(bytes([0x00, 0x00, 0x01, 0x00]))).toBeNull();
});
it('00 00 02 00 (CUR-Cursor-Datei) ergibt null — nur Typ 1 (ICO) wird erkannt', () => {
expect(detectFavoriteIconMime(bytes([0x00, 0x00, 0x02, 0x00, 0x01, 0x00]))).toBeNull();
});
it('gueltige SVG-Formen ergeben image/svg+xml', () => {
expect(detectFavoriteIconMime(bytes(''))).toBe(
'image/svg+xml',
);
expect(
detectFavoriteIconMime(bytes('\n')),
).toBe('image/svg+xml');
// fuehrendes BOM
expect(
detectFavoriteIconMime(bytes([0xef, 0xbb, 0xbf], '')),
).toBe('image/svg+xml');
// fuehrendes Leerzeichen
expect(detectFavoriteIconMime(bytes(' '))).toBe('image/svg+xml');
// Kommentar vor