Bisher standen nur Zahlen da. Jetzt kommen die Inhalte mit. Pull Requests und Issues: bis zu 50 offene je Liste, mit Nummer, Titel, Autor, Alter, Labels und Link. Bei GitHub und Gitea liefert der Issue-Endpunkt auch Pull Requests mit - die werden herausgefiltert. CI-Status des letzten Laufs auf dem Default-Branch: - GitHub ueber actions/runs; dort sind Lauf-Status und Ergebnis getrennt und werden auf einen Wert zusammengefuehrt - GitLab ueber pipelines - Gitea ueber den kombinierten Commit-Status. Das deckt Gitea Actions und externe Systeme wie Woodpecker gleichermassen ab - ein reiner Actions-Endpunkt existiert auf aelteren Instanzen nicht. Commit-Aktivitaet als Balkenreihe. Berechnet aus den ohnehin geholten Commits (jetzt 100 statt 15, angezeigt bleiben 15) statt ueber eigene Statistik-Endpunkte: die gibt es nicht bei allen drei Systemen, und bei GitHub antworten sie beim ersten Aufruf mit 202 und ohne Daten. Beim Testen gegen gitlab-runner fiel auf, dass alle 100 Commits in die letzten 30 Tage fielen - die frueheren Tage haetten faelschlich Null gezeigt, obwohl wir ueber sie nichts wissen. Die Kurve wird deshalb auf den tatsaechlich belegten Zeitraum gekuerzt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
110 lines
3.7 KiB
TypeScript
110 lines
3.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { guessProvider } from "./meta";
|
|
import { parseRepoUrl } from "./index";
|
|
import { ACTIVITY_DAYS, bucketCommitActivity } from "./types";
|
|
|
|
describe("parseRepoUrl", () => {
|
|
it("zerlegt eine gewoehnliche https-URL", () => {
|
|
expect(parseRepoUrl("https://github.com/vercel/swr")).toMatchObject({
|
|
host: "github.com",
|
|
owner: "vercel",
|
|
name: "swr",
|
|
guessedProvider: "GITHUB",
|
|
});
|
|
});
|
|
|
|
it("entfernt die Endung .git", () => {
|
|
expect(parseRepoUrl("https://github.com/vercel/swr.git")?.name).toBe("swr");
|
|
});
|
|
|
|
it("versteht SSH-Adressen", () => {
|
|
expect(parseRepoUrl("git@gitlab.com:gruppe/projekt.git")).toMatchObject({
|
|
host: "gitlab.com",
|
|
owner: "gruppe",
|
|
name: "projekt",
|
|
guessedProvider: "GITLAB",
|
|
});
|
|
});
|
|
|
|
it("behaelt verschachtelte GitLab-Gruppen", () => {
|
|
expect(parseRepoUrl("https://gitlab.com/gruppe/untergruppe/projekt")).toMatchObject({
|
|
owner: "gruppe/untergruppe",
|
|
name: "projekt",
|
|
});
|
|
});
|
|
|
|
it("schneidet GitLab-Oberflaechenpfade ab dem /-/ ab", () => {
|
|
expect(parseRepoUrl("https://gitlab.com/gruppe/projekt/-/tree/main")).toMatchObject({
|
|
owner: "gruppe",
|
|
name: "projekt",
|
|
});
|
|
});
|
|
|
|
it("kommt mit einer eigenen Gitea-Instanz zurecht", () => {
|
|
expect(parseRepoUrl("https://git.meine-firma.de/team/repo")).toMatchObject({
|
|
baseUrl: "https://git.meine-firma.de",
|
|
owner: "team",
|
|
name: "repo",
|
|
guessedProvider: "GITEA",
|
|
});
|
|
});
|
|
|
|
it("gibt null zurueck, wenn kein Repository erkennbar ist", () => {
|
|
expect(parseRepoUrl("https://github.com/nurbenutzer")).toBeNull();
|
|
expect(parseRepoUrl("")).toBeNull();
|
|
expect(parseRepoUrl("kein-url-artiger-text")).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("guessProvider", () => {
|
|
it("erkennt die grossen beiden am Hostnamen", () => {
|
|
expect(guessProvider("github.com")).toBe("GITHUB");
|
|
expect(guessProvider("gitlab.example.org")).toBe("GITLAB");
|
|
});
|
|
|
|
it("nimmt bei allem anderen Gitea an", () => {
|
|
expect(guessProvider("git.meine-firma.de")).toBe("GITEA");
|
|
});
|
|
});
|
|
|
|
describe("bucketCommitActivity", () => {
|
|
const dayMs = 24 * 60 * 60 * 1000;
|
|
const daysAgo = (days: number) => new Date(Date.now() - days * dayMs).toISOString();
|
|
|
|
it("liefert ohne Commits den vollen Zeitraum", () => {
|
|
expect(bucketCommitActivity([])).toHaveLength(ACTIVITY_DAYS);
|
|
});
|
|
|
|
it("sortiert den juengsten Commit ans Ende", () => {
|
|
const buckets = bucketCommitActivity([daysAgo(29), daysAgo(0)]);
|
|
expect(buckets).toHaveLength(ACTIVITY_DAYS);
|
|
expect(buckets[ACTIVITY_DAYS - 1]).toBe(1);
|
|
});
|
|
|
|
it("zaehlt mehrere Commits desselben Tages zusammen", () => {
|
|
const buckets = bucketCommitActivity([daysAgo(29), daysAgo(2), daysAgo(2), daysAgo(2)]);
|
|
expect(buckets[buckets.length - 3]).toBe(3);
|
|
});
|
|
|
|
it("kuerzt auf den belegten Zeitraum, statt Unbekanntes als Null zu zeigen", () => {
|
|
// Reicht die geholte Historie nur fuenf Tage zurueck, duerfen die
|
|
// 25 Tage davor nicht als "keine Commits" erscheinen.
|
|
const buckets = bucketCommitActivity([daysAgo(4), daysAgo(0)]);
|
|
expect(buckets).toHaveLength(5);
|
|
expect(buckets[0]).toBe(1);
|
|
expect(buckets[4]).toBe(1);
|
|
});
|
|
|
|
it("ignoriert unlesbare Werte", () => {
|
|
const buckets = bucketCommitActivity([null, "voelliger Unsinn"]);
|
|
expect(buckets).toHaveLength(ACTIVITY_DAYS);
|
|
expect(buckets.every((value) => value === 0)).toBe(true);
|
|
});
|
|
|
|
it("laesst aeltere Commits den vollen Zeitraum aufspannen", () => {
|
|
const buckets = bucketCommitActivity([daysAgo(100), daysAgo(1)]);
|
|
expect(buckets).toHaveLength(ACTIVITY_DAYS);
|
|
expect(buckets[ACTIVITY_DAYS - 2]).toBe(1);
|
|
});
|
|
});
|