test: Schnellsuche und Issue-Uebernahme abdecken, Version 0.9.0
CI / pruefen (push) Has been cancelled

Zwei neue Ende-zu-Ende-Tests: die Palette findet Projekt und Notiz und
oeffnet den Treffer mit Enter; die Uebernahme meldet ohne Repo-Stand einen
Hinweis statt still zu scheitern. Damit sind es 15.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-26 11:36:44 +02:00
co-authored by Claude Opus 5
parent 75460c8cf4
commit fa5fd78318
6 changed files with 64 additions and 3 deletions
+26
View File
@@ -117,6 +117,19 @@ Der Status ist **direkt auf der Projektkarte** umschaltbar, ohne den Detailberei
- **Archiv** ist standardmäßig ausgeblendet und per Schalter einblendbar. - **Archiv** ist standardmäßig ausgeblendet und per Schalter einblendbar.
- **Leerzustände** mit direktem Einstieg statt einer leeren Fläche. - **Leerzustände** mit direktem Einstieg statt einer leeren Fläche.
### Schnellsuche
**`Strg+K`** (auf dem Mac `Cmd+K`) öffnet überall eine Palette:
- **Projekte** nach Name, Kurzbeschreibung und Tags — ohne Eingabe stehen die letzten
gleich bereit
- **Notizen** über dieselbe Volltextsuche wie im Board, entprellt ab zwei Zeichen
- **Bereiche**: Dashboard, Git-Verbindungen, Mein Konto, Admin-Einstellungen
Bedienung über Tastatur: Pfeile wählen, `Enter` öffnet, `Esc` schließt. Die Projektliste
wird beim ersten Öffnen geholt und dann behalten — sie bei jedem Tastendruck neu zu laden
wäre Verschwendung.
### Kanban ### Kanban
Spalten je Status, Karten per Ziehen verschiebbar. Der Wechsel wird sofort angezeigt und Spalten je Status, Karten per Ziehen verschiebbar. Der Wechsel wird sofort angezeigt und
@@ -152,6 +165,19 @@ Blockiert · Erledigt**.
- Erledigtes wird durchgestrichen; der Zeitpunkt wird festgehalten und beim Zurückziehen - Erledigtes wird durchgestrichen; der Zeitpunkt wird festgehalten und beim Zurückziehen
wieder gelöscht. wieder gelöscht.
### Aus Git-Issues übernehmen
Im Git-Panel, Reiter *Issues*: ein Klick macht aus den offenen Issues Aufgaben — Titel,
Labels und ein Link zurück ins Git-System.
- Grundlage ist der **zuletzt geholte Stand**, hier wird nichts nachgeladen. Ein Klick
soll nicht ungefragt fremde APIs ansprechen; wer den neuesten Stand will, gleicht
vorher ab.
- Die Issue-Nummer bleibt an der Aufgabe und ist je Projekt eindeutig. Ein zweiter Klick
legt deshalb **keine Dubletten** an, auch wenn die Aufgabe inzwischen verschoben oder
umbenannt wurde.
- Ohne Repo-Stand meldet der Server das mit einem Hinweis statt still nichts zu tun.
### Fortschritt aus Aufgaben ### Fortschritt aus Aufgaben
Pro Projekt umschaltbar. Ist es an, ergibt sich der Fortschritt aus dem Anteil erledigter Pro Projekt umschaltbar. Ist es an, ergibt sich der Fortschritt aus dem Anteil erledigter
+1
View File
@@ -347,6 +347,7 @@ ausschließlich Daten des angemeldeten Kontos.
| `POST` | `/api/projects/:id/sync` | Repo-Daten vom Git-System holen | | `POST` | `/api/projects/:id/sync` | Repo-Daten vom Git-System holen |
| `GET` `POST` | `/api/projects/:id/tasks` | Aufgaben des Projekts | | `GET` `POST` | `/api/projects/:id/tasks` | Aufgaben des Projekts |
| `PATCH` | `/api/projects/:id/tasks/reorder` | Neue Reihenfolge nach dem Ziehen | | `PATCH` | `/api/projects/:id/tasks/reorder` | Neue Reihenfolge nach dem Ziehen |
| `POST` | `/api/projects/:id/tasks/from-issues` | Offene Issues als Aufgaben übernehmen |
| `PATCH` `DELETE` | `/api/tasks/:id` | Aufgabe ändern / löschen | | `PATCH` `DELETE` | `/api/tasks/:id` | Aufgabe ändern / löschen |
| `GET` `POST` | `/api/projects/:id/notes` | Notizen des Projekts | | `GET` `POST` | `/api/projects/:id/notes` | Notizen des Projekts |
| `PATCH` `DELETE` | `/api/notes/:id` | Notiz ändern / löschen | | `PATCH` `DELETE` | `/api/notes/:id` | Notiz ändern / löschen |
+1 -2
View File
@@ -63,12 +63,10 @@ Voraussetzung, falls du das Projekt veröffentlichen willst.
| Idee | Aufwand | Nutzen | | Idee | Aufwand | Nutzen |
| --- | --- | --- | | --- | --- | --- |
| Schnellsuche per `Strg+K` | `S` | Springt direkt zu Projekt oder Aktion |
| Suchtreffer in Notizen hervorheben | `S` | In der Notiz selbst, nicht nur in der Trefferliste | | Suchtreffer in Notizen hervorheben | `S` | In der Notiz selbst, nicht nur in der Trefferliste |
| Mehrfachauswahl im Board | `S` | Status oder Tags für mehrere auf einmal | | Mehrfachauswahl im Board | `S` | Status oder Tags für mehrere auf einmal |
| Aktivitätsverlauf je Projekt | `S` | Wer hat wann was geändert | | Aktivitätsverlauf je Projekt | `S` | Wer hat wann was geändert |
| Wiederkehrende Aufgaben | `M` | Etwa „jeden Montag Abhängigkeiten prüfen" | | Wiederkehrende Aufgaben | `M` | Etwa „jeden Montag Abhängigkeiten prüfen" |
| Aufgaben aus Git-Issues übernehmen | `M` | Offene Issues als Aufgaben einhängen |
| Projektvorlagen | `S` | Neues Projekt mit vorgefüllten Tags und Notizen | | Projektvorlagen | `S` | Neues Projekt mit vorgefüllten Tags und Notizen |
| Hell/Dunkel umschaltbar | `M` | Aktuell nur dunkel | | Hell/Dunkel umschaltbar | `M` | Aktuell nur dunkel |
| Eigenes Logo und Farbe | `S` | Ergänzt `APP_NAME` | | Eigenes Logo und Farbe | `S` | Ergänzt `APP_NAME` |
@@ -112,6 +110,7 @@ Damit klar ist, was **nicht** kommt und warum:
| **v0.6.0** Ende-zu-Ende-Tests mit Playwright, CI-Pipeline für Gitea Actions | ✓ | | **v0.6.0** Ende-zu-Ende-Tests mit Playwright, CI-Pipeline für Gitea Actions | ✓ |
| **v0.7.0** Benachrichtigungen über ntfy, Webhook und E-Mail | ✓ | | **v0.7.0** Benachrichtigungen über ntfy, Webhook und E-Mail | ✓ |
| **v0.8.0** Stillstehende Projekte melden, Schwelle im Adminbereich | ✓ | | **v0.8.0** Stillstehende Projekte melden, Schwelle im Adminbereich | ✓ |
| **v0.9.0** Schnellsuche per `Strg+K`, Aufgaben aus Git-Issues | ✓ |
Zur Entscheidung beim Export: Git-Tokens gehen **nicht** mit. Die Verbindung wird nur Zur Entscheidung beim Export: Git-Tokens gehen **nicht** mit. Die Verbindung wird nur
beschrieben, das Token ist nach dem Import neu zu hinterlegen. Snapshots bleiben beschrieben, das Token ist nach dem Import neu zu hinterlegen. Snapshots bleiben
+14
View File
@@ -184,6 +184,20 @@ test("Aufgaben: Reihenfolge, abgeleiteter Fortschritt, fremde IDs", async ({ req
expect(unveraendert.status).toBe("TODO"); expect(unveraendert.status).toBe("TODO");
}); });
test("Issues als Aufgaben uebernehmen, ohne Dubletten", async ({ request }) => {
await login(request, ADMIN);
const projekt = (
await (await request.post("/api/projects", { data: { name: "Issue-Projekt" } })).json()
).project;
// Ohne Repo-Stand gibt es nichts zu uebernehmen – und das sagt der Server auch.
const ohneStand = await request.post(`/api/projects/${projekt.id}/tasks/from-issues`, {
data: {},
});
expect(ohneStand.status()).toBe(409);
});
test("Export enthaelt keine Geheimnisse, Import beachtet die Strategie", async ({ request }) => { test("Export enthaelt keine Geheimnisse, Import beachtet die Strategie", async ({ request }) => {
await login(request, ADMIN); await login(request, ADMIN);
+21
View File
@@ -98,6 +98,27 @@ test("Volltextsuche findet Notizen", async ({ page }) => {
await expect(page.getByText("Treffer in Notizen")).toBeVisible(); await expect(page.getByText("Treffer in Notizen")).toBeVisible();
}); });
test("Schnellsuche findet Projekt und Notiz", async ({ page }) => {
await page.keyboard.press("Control+k");
await expect(page.getByRole("dialog", { name: "Schnellsuche" })).toBeVisible();
// Ohne Eingabe stehen Projekte und Bereiche bereit.
await expect(page.getByRole("dialog").getByText("Oberflaechentest")).toBeVisible();
await page.getByPlaceholder(/Projekt, Notiz oder Bereich/).fill("Zaunkoenig");
await expect(page.getByRole("dialog").getByText(/in Oberflaechentest/)).toBeVisible();
// Enter springt zum ersten Treffer.
await page.keyboard.press("Enter");
await expect(page.getByRole("heading", { name: "Oberflaechentest" })).toBeVisible();
// Escape schliesst wieder.
await page.keyboard.press("Control+k");
await expect(page.getByRole("dialog", { name: "Schnellsuche" })).toBeVisible();
await page.keyboard.press("Escape");
await expect(page.getByRole("dialog", { name: "Schnellsuche" })).toBeHidden();
});
test("Abmelden fuehrt zurueck zur Anmeldung", async ({ page }) => { test("Abmelden fuehrt zurueck zur Anmeldung", async ({ page }) => {
await page.getByRole("button", { name: /Benutzermenue/ }).click(); await page.getByRole("button", { name: /Benutzermenue/ }).click();
await page.getByRole("menuitem", { name: "Abmelden" }).click(); await page.getByRole("menuitem", { name: "Abmelden" }).click();
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "nebula", "name": "nebula",
"version": "0.8.0", "version": "0.9.0",
"private": true, "private": true,
"description": "Nebula – Dashboard fuer Vibe-Coding Projekte mit Git-Anbindung (GitHub, GitLab, Gitea)", "description": "Nebula – Dashboard fuer Vibe-Coding Projekte mit Git-Anbindung (GitHub, GitLab, Gitea)",
"scripts": { "scripts": {