Files
nebula/src/lib/activity.test.ts
T
florian.wildeandClaude Opus 5 af562584ad feat(projects): Aktivitaetsverlauf je Projekt
Was ist hier eigentlich passiert - eine Zeitleiste auf der Projektseite
beantwortet das jetzt: Statuswechsel, Notizen, Aufgaben, neue Commits.

Der Verlauf soll erzaehlen, nicht protokollieren. Deshalb bekommen Status
und Repo-Verknuepfung einen eigenen Eintrag, waehrend alle uebrigen Felder
zu einem zusammengefasst werden - sonst ertraenkt eine Feinjustage der Farbe
alles Wichtige. Ein Titel, der sich aendert, kommt gar nicht vor.

Beim Abgleich ist Zurueckhaltung noch wichtiger: er laeuft im Zweifel
stuendlich. Vermerkt wird nur, wenn der letzte Commit ein anderer ist als
beim letzten Mal, und beim ersten Abgleich gar nicht - dass ein Repo Commits
hat, ist keine Neuigkeit. Fehlschlaege stehen nur beim Uebergang in den
Fehlerzustand drin, sonst schlaegt ein abgelaufenes Token stuendlich neu auf.

Der Text wird beim Schreiben formuliert, nicht beim Anzeigen. Ein Eintrag
soll auch dann lesbar bleiben, wenn es die Notiz, um die es ging, laengst
nicht mehr gibt.

Zweihundert Eintraege je Projekt bleiben erhalten, der taegliche Durchgang
stutzt den Rest. Der Export nimmt den Verlauf nicht mit - er beschriebe, was
in dieser Instanz passiert ist, und verwiese auf Konten, die es anderswo
nicht gibt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 12:36:19 +02:00

58 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from "vitest";
import { describeFields, describeStatus, shorten } from "./activity";
describe("describeFields", () => {
it("nennt ein einzelnes Feld beim Namen", () => {
expect(describeFields(["name"])).toBe("Name geändert");
});
it("zaehlt zwei und drei Felder auf", () => {
expect(describeFields(["name", "tags"])).toBe("Name und Tags geändert");
expect(describeFields(["name", "tags", "priority"])).toBe(
"Name, Tags und Priorität geändert",
);
});
it("fasst ab vier Feldern zusammen, statt eine Litanei zu bilden", () => {
expect(describeFields(["name", "tags", "priority", "accent"])).toBe("4 Felder geändert");
});
it("zaehlt zusammengehoerende Felder nur einmal", () => {
// repoOwner und repoName sind fuer den Leser eine einzige Aenderung.
expect(describeFields(["repoOwner", "repoName"])).toBe("Repository geändert");
});
it("liefert null, wenn nichts Nennenswertes dabei war", () => {
// slug wird nur mitgeschrieben, wenn sich der Name aendert – der Name
// steht dann ohnehin schon in der Liste.
expect(describeFields([])).toBeNull();
expect(describeFields(["slug", "updatedAt"])).toBeNull();
});
});
describe("describeStatus", () => {
it("uebersetzt beide Seiten in die Anzeigenamen", () => {
expect(describeStatus("IDEA", "IN_DEVELOPMENT")).toBe("Status: Idee → In Entwicklung");
});
it("laesst unbekannte Werte stehen, statt sie zu verschlucken", () => {
expect(describeStatus("IDEA", "PHANTASIE")).toBe("Status: Idee → PHANTASIE");
});
});
describe("shorten", () => {
it("laesst Kurzes unangetastet", () => {
expect(shorten("Kurzer Titel")).toBe("Kurzer Titel");
});
it("kuerzt auf die vorgegebene Laenge einschliesslich Auslassungszeichen", () => {
const gekuerzt = shorten("x".repeat(100), 20);
expect(gekuerzt).toHaveLength(20);
expect(gekuerzt.endsWith("…")).toBe(true);
});
it("macht aus Zeilenumbruechen eine Zeile", () => {
expect(shorten("Erste Zeile\n\n zweite Zeile ")).toBe("Erste Zeile zweite Zeile");
});
});