diff --git a/BEFUNDE.md b/BEFUNDE.md index 8f6fab5..6a16ef5 100644 --- a/BEFUNDE.md +++ b/BEFUNDE.md @@ -1,5 +1,21 @@ # Bestandsaufnahme, 12.09.2026 +> **Stand 24.09.2026.** Dieses Dokument ist die Aufnahme vom 12.09. Was seither +> erledigt wurde, steht an Ort und Stelle durchgestrichen oder vermerkt; die +> Kurzfassung: +> +> | | | +> |---|---| +> | Punkte 1, 2, 2b, 3 (teilweise) | ✅ erledigt | +> | Go-Tests `documents`, `tags` | ✅ 12 Testfunktionen | +> | Go-Tests `sharing`, `rescan`, `audit`, `thumbnails` | **offen** | +> | Frontend-DOM-Tests | ✅ jsdom seit 18.09., 46 Tests | +> +> Dazwischen lag eine Woche Oberflächenarbeit, die hier nicht auftaucht, weil +> sie keine Befunde abarbeitete: Rückmeldungen mit Rückgängig, Platzhalter, +> Leerzustände, Sprache vereinheitlicht, `Intl`. Steht in +> [TESTING.md](TESTING.md). + Einmal durch die ganze Cloud: Code, Sicherheit, offene Enden. Geordnet nach dem, was passieren kann — nicht nach Aufwand. @@ -160,14 +176,14 @@ Zwei Tests in `pkg/middleware/logger_test.go` halten es fest. **Schwere: mittel. Nicht was heute kaputt ist, sondern was morgen still kaputtgeht.** -| Paket | Zeilen | Test | Aussenpruefung | +| Paket | Zeilen | Test (24.09.) | Aussenpruefung | |---|---:|---:|---| -| `internal/tags` | 1132 | **0** | keine | -| `internal/documents` (OCR, Volltext) | 1008 | **0** | keine | -| `internal/sharing` | 382 | **0** | Python-Selbsttest, 24 Prüfungen | -| `internal/rescan` | 479 | **0** | Python-Selbsttest, 20 Prüfungen | -| `internal/audit` | 207 | **0** | keine | -| `internal/thumbnails` | 113 | **0** | keine | +| `internal/tags` | 1338 | **4** ✅ | keine | +| `internal/documents` (OCR, Volltext) | 1243 | **8** ✅ | keine | +| `internal/sharing` | 347 | **0** | Python-Selbsttest, 24 Prüfungen | +| `internal/rescan` | 435 | **0** | Python-Selbsttest, 20 Prüfungen | +| `internal/audit` | 180 | **0** | keine | +| `internal/thumbnails` | 95 | **0** | keine | Bei `sharing` und `rescan` deckt wenigstens ein Selbsttest die Außenseite ab. Bei **`documents` und `tags` gar nichts** — und `documents` ist das Stück, das @@ -251,8 +267,16 @@ gibt: * **Die Fehlversuchssperren liegen im Arbeitsspeicher.** Ein Neustart des Containers hebt jede Sperre auf. Für den Hausgebrauch vertretbar; wer es anders will, braucht eine Tabelle. -* **Frontend ohne Komponententests.** `vitest` läuft jetzt (37 Tests), aber nur - über reine Funktionen — für DOM-Tests fehlt `jsdom` in den devDependencies. +* ~~**Frontend ohne Komponententests.**~~ ✅ **18.09.2026:** `jsdom` ist in den + devDependencies, die Umgebung bleibt `node` (schnell); wer ein DOM braucht, + schreibt `// @vitest-environment jsdom` an den Anfang seiner Datei. 46 Tests, + davon vier gegen ein DOM. Der erste davon hat sofort einen Fehler gefunden – + in der Behebung vom Vortag (`useBackClose`). + + **Was er nicht leistet, steht dabei:** Den ursprünglichen Fehler bildet jsdom + nicht ab; es verwirft einen Verlaufssprung, sobald `pushState` folgt. Dafür + bräuchte es einen echten Browser (Playwright). Nachgeprüft, nicht vermutet: + mit der alten, kaputten Fassung blieben alle Tests grün. --- diff --git a/TESTING.md b/TESTING.md index 71220ff..345cd51 100644 --- a/TESTING.md +++ b/TESTING.md @@ -1562,6 +1562,46 @@ bleibt `node` (schnell); wer ein DOM braucht, schreibt --- +## Ein Wächter für die Sprache (24.09.2026) + +Sechs Tage nach der Übersetzung fielen beim Nachsehen **fünf Reste** auf: +`label="Ganztägig"`, `aria-label="Kalendermenü"`, `label="Bearbeiten"` und +zweimal `"Löschen"`. Alle in **doppelt** gequoteten JSX-Attributen – die +Ersetzungsliste hatte nur die einfach gequoteten, und das damalige Prüfskript +hielt Einzelwörter ohne Leerzeichen für Bezeichner. + +Deshalb steht die Prüfung jetzt als Test (`src/sprache.test.ts`) statt als +Skript, das man einmal laufen lässt. Sie läuft bei jedem `npm test` mit. + +**Der erste Wächter taugte nichts, und das kam nur durch die Mutation heraus:** +Er prüfte allein auf Umlaute und liess `"Papierkorb ist leer"` anstandslos +durch. Wer einen Wächter baut, muss ihn einmal angreifen. + +Jetzt: Umlaute **plus** eine Liste häufiger deutscher Wörter mit Wortgrenzen +(sonst schlägt "ist" in "list" an). Kommentare werden vorher entfernt – und +zwar richtig, mit einem kleinen Durchlauf statt zeilenweise: Blockkommentare +haben Fortsetzungszeilen ohne führenden Stern, die beim ersten Versuch fünf +Fehlalarme erzeugt haben. + +Nachgewiesen an vier Mutationen, alle werden rot: + +| eingeschleuster Text | erkannt an | +|---|---| +| `Papierkorb ist leer` | "ist", "leer" | +| `Loeschen fehlgeschlagen` | "Loeschen", "fehlgeschlagen" | +| `Ganztägig` | Umlaut | +| `Bitte warten` | "bitte" | + +> **Ein Netz, kein Beweis.** Ein deutscher Satz ohne Umlaut und ohne eines der +> gelisteten Wörter käme durch – "Datum bereits vergeben" etwa. Der Test +> fängt, was erfahrungsgemäß passiert: ein vergessenes Attribut beim +> Übersetzen. Wer die Liste ergänzt, weil einmal etwas durchgerutscht ist, tut +> genau das Richtige. + +- [x] Gebautes Bündel enthält keine deutschen Oberflächentexte mehr – + gegengeprüft, dass die englischen drin sind (sonst prüfte der Grep nur + sich selbst) + ## Wochentage und Monate aus `Intl` (20.09.2026) Sechs handgeschriebene Arrays in drei Dateien, und `Intl` kam im ganzen Projekt diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3cdf2d3..c3e40c7 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -19,6 +19,7 @@ "@tailwindcss/vite": "^4.3.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", + "@types/node": "^26.6.2", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "jsdom": "^26.1.0", @@ -2914,6 +2915,16 @@ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==" }, + "node_modules/@types/node": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz", + "integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": "~8.9.0" + } + }, "node_modules/@types/react": { "version": "19.2.17", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", @@ -6371,6 +6382,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz", + "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index ad228b3..2f19de9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,6 +22,7 @@ "@tailwindcss/vite": "^4.3.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", + "@types/node": "^26.6.2", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "jsdom": "^26.1.0", diff --git a/frontend/src/components/calendar/EventDialog.tsx b/frontend/src/components/calendar/EventDialog.tsx index 47941a6..b589856 100644 --- a/frontend/src/components/calendar/EventDialog.tsx +++ b/frontend/src/components/calendar/EventDialog.tsx @@ -221,7 +221,7 @@ export default function EventDialog({ event, defaultStart, calendars, calendarId )}
Keine Termine für heute
', + ].join('\n') + writeFileSync(probe, inhalt) + const gefunden = deutscheTexte(probe) + expect(gefunden).toHaveLength(3) + expect(gefunden.join(' ')).toContain('Ganztägig') + expect(gefunden.join(' ')).not.toContain('Kommentar') + }) +}) diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index aab8a43..e2ceb49 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -4,7 +4,9 @@ "useDefineForClassFields": true, "lib": ["ES2022", "DOM", "DOM.Iterable"], // Vites Zusaetze zum Import: ?url, ?raw und der Seiteneffekt-Import von CSS. - "types": ["vite/client"], + // "node" kam am 24.09.2026 dazu: sprache.test.ts liest den Quelltext von + // der Platte, um deutschen Oberflaechentext zu finden. + "types": ["vite/client", "node"], "module": "ESNext", "skipLibCheck": true, "moduleResolution": "bundler",