package main import ( "context" "errors" "os" "path/filepath" "strings" "testing" "munin/internal/export" "munin/internal/store" "munin/internal/workspace" ) // setupTwoWorkspaces legt eine Kontroll-Datenbank mit zwei Workspaces an, // jeder mit einem Projekt "plattform" und einem Eintrag. func setupTwoWorkspaces(t *testing.T) (*store.ControlStore, *workspace.Manager, []store.Workspace) { t.Helper() ctx := context.Background() dir := t.TempDir() control, err := store.OpenControl(filepath.Join(dir, "control.db")) if err != nil { t.Fatal(err) } t.Cleanup(func() { control.Close() }) workspaces := workspace.NewManager(store.NewSQLite("", dir)) t.Cleanup(func() { workspaces.Close() }) var all []store.Workspace for _, name := range []string{"Intern", "Vertrieb"} { w, err := control.CreateWorkspace(ctx, name) if err != nil { t.Fatal(err) } opened, err := workspaces.Get(w.ID) if err != nil { t.Fatal(err) } project, err := opened.Store.CreateProject(ctx, w.ID, "plattform", "Plattform", "") if err != nil { t.Fatal(err) } if _, err := opened.Store.PutEntry(ctx, store.EntryWrite{ ProjectID: project.ID, Slug: "wissen", Title: "Wissen", Content: "aus " + name, Source: store.SourceHuman, }); err != nil { t.Fatal(err) } all = append(all, w) } return control, workspaces, all } // TestForEachWorkspaceReachesAll: Die wiederkehrenden Aufgaben liefen // früher nur für den ältesten Workspace. Jetzt muss jeder drankommen. func TestForEachWorkspaceReachesAll(t *testing.T) { control, workspaces, all := setupTwoWorkspaces(t) seen := map[string]bool{} err := forEachWorkspace(context.Background(), control, workspaces, func(w store.Workspace, _ *workspace.Workspace) error { seen[w.ID] = true return nil }) if err != nil { t.Fatal(err) } for _, w := range all { if !seen[w.ID] { t.Errorf("Workspace %q wurde übersprungen", w.Name) } } } // TestForEachWorkspaceContinuesAfterError: Ein kaputter Workspace darf die // übrigen nicht aufhalten, der Fehler muss aber beim Aufrufer ankommen. func TestForEachWorkspaceContinuesAfterError(t *testing.T) { control, workspaces, all := setupTwoWorkspaces(t) broken := errors.New("kaputt") var calls int err := forEachWorkspace(context.Background(), control, workspaces, func(w store.Workspace, _ *workspace.Workspace) error { calls++ if w.ID == all[0].ID { return broken } return nil }) if calls != len(all) { t.Errorf("%d Aufrufe, erwartet %d — nach dem Fehler wurde abgebrochen", calls, len(all)) } if !errors.Is(err, broken) { t.Errorf("Fehler ging verloren: %v", err) } } // TestExportAllWritesEveryWorkspace prüft den Weg von -export und dem // täglichen Lauf: jeder Workspace in seinem eigenen Ordner, obwohl beide ein // Projekt "plattform" haben. func TestExportAllWritesEveryWorkspace(t *testing.T) { control, workspaces, all := setupTwoWorkspaces(t) target := t.TempDir() if _, err := exportAll(context.Background(), export.New(target), control, workspaces); err != nil { t.Fatal(err) } for _, w := range all { content, err := os.ReadFile(filepath.Join(target, w.ID, "plattform", "wissen.md")) if err != nil { t.Errorf("Workspace %q fehlt im Export: %v", w.Name, err) continue } if want := "aus " + w.Name; !strings.Contains(string(content), want) { t.Errorf("Workspace %q: %q fehlt im Inhalt", w.Name, want) } } }