ajhahn.de
← eeco
Go 71 lines
package cockpit

import (
	"strings"
	"testing"
)

func TestCursorRender_Structure(t *testing.T) {
	pb := loadHandover(t)
	out, err := cursorRenderer{}.Render(pb)
	if err != nil {
		t.Fatalf("Render: %v", err)
	}
	got := string(out)

	if !strings.HasPrefix(got, "---\ndescription: ") {
		t.Errorf("output does not open with .mdc frontmatter:\n%s", got[:min(120, len(got))])
	}
	for _, want := range []string{"globs:", "alwaysApply: false", advisoryBanner, "## " + headingForbidden, "## " + headingAllowed, "## " + headingOutput} {
		if !strings.Contains(got, want) {
			t.Errorf("rendered .mdc missing %q", want)
		}
	}
	// Every forbidden phrase must appear verbatim (honesty: can't silently drop).
	for _, ph := range pb.Intent.Forbidden {
		if !strings.Contains(got, ph) {
			t.Errorf("rendered .mdc missing forbidden phrase %q", ph)
		}
	}
	// Every step heading is present.
	if n := strings.Count(got, "## "+headingStep); n < len(pb.Steps) {
		t.Errorf("rendered .mdc has %d step headings, want >= %d", n, len(pb.Steps))
	}
}

func TestCursorRender_Deterministic(t *testing.T) {
	pb := loadHandover(t)
	a, err := cursorRenderer{}.Render(pb)
	if err != nil {
		t.Fatal(err)
	}
	b, err := cursorRenderer{}.Render(pb)
	if err != nil {
		t.Fatal(err)
	}
	if string(a) != string(b) {
		t.Error("cursor render not deterministic")
	}
}

func TestCursorRelPath(t *testing.T) {
	pb := loadHandover(t)
	if got := (cursorRenderer{}).RelPath(pb); got != ".cursor/rules/handover.mdc" {
		t.Errorf("RelPath = %q, want .cursor/rules/handover.mdc", got)
	}
}

func TestCursorRender_RejectsMultilineDescription(t *testing.T) {
	pb := loadHandover(t)
	pb.Description = "line one\nline two"
	if _, err := (cursorRenderer{}).Render(pb); err == nil {
		t.Error("expected an error for a multi-line description")
	}
}

func TestCursorEnforcement(t *testing.T) {
	if got := (cursorRenderer{}).Enforcement(); got != EnforcementAdvisory {
		t.Errorf("cursor enforcement = %v, want advisory", got)
	}
}