Files
kandev/apps/backend/internal/github/commit_detail_test.go
T
2026-08-05 20:45:59 +01:00

182 lines
6.5 KiB
Go

package github
import (
"context"
"encoding/json"
"errors"
"strings"
"testing"
ws "github.com/kandev/kandev/pkg/websocket"
)
func TestPRCommitStatsAreMarkedUnavailable(t *testing.T) {
commits, err := parsePRCommitsJSON(`[
{
"sha": "1111111111111111111111111111111111111111",
"commit": {
"message": "Remote commit",
"author": {"date": "2026-08-04T10:00:00Z"}
},
"author": {"login": "octocat"}
}
]`)
if err != nil {
t.Fatalf("parse PR commits: %v", err)
}
encoded, err := json.Marshal(commits)
if err != nil {
t.Fatalf("marshal PR commits: %v", err)
}
if !strings.Contains(string(encoded), `"stats_available":false`) {
t.Fatalf("PR commit stats availability = %s, want explicit false", encoded)
}
}
func TestParsePRCommitDetailJSONMergesPages(t *testing.T) {
detail, err := parsePRCommitDetailJSON(`[
{
"sha": "2222222222222222222222222222222222222222",
"commit": {
"message": "Remote detail\nbody",
"author": {"name": "Octo Cat", "date": "2026-08-04T11:00:00Z"}
},
"author": {"login": "octocat"},
"stats": {"additions": 7, "deletions": 3, "total": 10},
"files": [
{"filename": "one.txt", "status": "modified", "additions": 4, "deletions": 1, "patch": "@@ -1 +1 @@\n-old\n+new"},
{"filename": "duplicate.txt", "status": "added", "additions": 1, "deletions": 0}
]
},
{
"sha": "2222222222222222222222222222222222222222",
"commit": {"message": "ignored page metadata", "author": {"name": "Other", "date": "2026-08-05T11:00:00Z"}},
"author": {"login": "other"},
"stats": {"additions": 99, "deletions": 99, "total": 198},
"files": [
{"filename": "duplicate.txt", "status": "added", "additions": 1, "deletions": 0},
{"filename": "two.txt", "status": "removed", "additions": 0, "deletions": 2, "patch": "@@ -1 +0,0 @@\n-gone"}
]
}
]`)
if err != nil {
t.Fatalf("parse PR commit detail: %v", err)
}
if detail.SHA != "2222222222222222222222222222222222222222" || detail.Message != "Remote detail\nbody" {
t.Fatalf("metadata = %#v", detail)
}
if detail.AuthorLogin != "octocat" || detail.AuthorName != "Octo Cat" || detail.AuthorDate != "2026-08-04T11:00:00Z" {
t.Fatalf("author = %#v", detail)
}
if detail.Additions != 7 || detail.Deletions != 3 || detail.FilesChanged != 3 {
t.Fatalf("stats = %#v", detail)
}
if len(detail.Files) != 3 {
t.Fatalf("files = %#v, want three provider-ordered unique files", detail.Files)
}
if detail.Files[0].Filename != "one.txt" || detail.Files[1].Filename != "duplicate.txt" || detail.Files[2].Filename != "two.txt" {
t.Fatalf("file order = %#v", detail.Files)
}
if !strings.Contains(detail.Files[0].Patch, "diff --git a/one.txt b/one.txt") {
t.Fatalf("file patch = %q, want complete diff", detail.Files[0].Patch)
}
}
func TestParsePRCommitDetailJSONRejectsEmptyPayloads(t *testing.T) {
for _, payload := range []string{`null`, `[null]`, `{}`, `[{}]`} {
t.Run(payload, func(t *testing.T) {
if _, err := parsePRCommitDetailJSON(payload); err == nil {
t.Fatalf("parsePRCommitDetailJSON(%q) succeeded, want malformed payload error", payload)
}
})
}
}
func TestGetPRCommitDetailForWorkspaceUsesAuthorizedClient(t *testing.T) {
const sha = "3333333333333333333333333333333333333333"
client := NewMockClient()
client.AddRepos("test-user", []GitHubRepo{{FullName: "acme/widget", Owner: "acme", Name: "widget"}})
client.AddPRCommitDetail("acme", "widget", sha, PRCommitDetail{
SHA: sha,
Files: []PRFile{{Filename: "remote.txt", Status: "modified", Patch: "remote patch"}},
})
svc := newWorkspaceAuthenticatedTestService(t, client, nil, "workspace-1")
detail, err := svc.GetPRCommitDetailForWorkspace(context.Background(), "workspace-1", "", "acme", "widget", sha)
if err != nil {
t.Fatalf("GetPRCommitDetailForWorkspace: %v", err)
}
if detail.SHA != sha || len(detail.Files) != 1 || detail.Files[0].Filename != "remote.txt" {
t.Fatalf("detail = %#v", detail)
}
}
func TestGetPRCommitDetailForWorkspaceRejectsUnsafeSHA(t *testing.T) {
svc := &Service{workspaceAuthorizer: func(context.Context, string) error {
return errors.New("workspace lookup should not run")
}}
_, err := svc.GetPRCommitDetailForWorkspace(context.Background(), "workspace-1", "", "acme", "widget", "main")
if err == nil || !strings.Contains(err.Error(), "invalid commit SHA") {
t.Fatalf("error = %v, want invalid commit SHA before provider access", err)
}
}
func TestWSGetPRCommitDetailRoutesWorkspaceRequest(t *testing.T) {
const sha = "4444444444444444444444444444444444444444"
client := NewMockClient()
client.AddRepos("test-user", []GitHubRepo{{FullName: "acme/widget", Owner: "acme", Name: "widget"}})
client.AddPRCommitDetail("acme", "widget", sha, PRCommitDetail{SHA: sha, Message: "remote commit"})
svc := newWorkspaceAuthenticatedTestService(t, client, nil, "workspace-1")
message, err := ws.NewRequest("request-1", "github.pr_commit.get", map[string]any{
"workspace_id": "workspace-1", "owner": "acme", "repo": "widget", "sha": sha,
})
if err != nil {
t.Fatalf("create request: %v", err)
}
response, err := wsGetPRCommitDetail(svc, testLogger(t))(context.Background(), message)
if err != nil {
t.Fatalf("handler error: %v", err)
}
if response.Type != ws.MessageTypeResponse {
t.Fatalf("response type = %q, want response", response.Type)
}
var body struct {
Commit PRCommitDetail `json:"commit"`
}
if err := json.Unmarshal(response.Payload, &body); err != nil {
t.Fatalf("decode response: %v", err)
}
if body.Commit.SHA != sha || body.Commit.Message != "remote commit" {
t.Fatalf("response body = %#v", body)
}
}
func TestWSGetPRCommitDetailReturnsWorkspaceAuthorizationError(t *testing.T) {
svc := NewService(NewMockClient(), AuthMethodPAT, nil, nil, nil, testLogger(t))
denied := errors.New("workspace not found")
svc.SetWorkspaceAuthorizer(func(_ context.Context, workspaceID string) error {
if workspaceID != "workspace-1" {
t.Fatalf("workspaceID = %q", workspaceID)
}
return denied
})
message, err := ws.NewRequest("request-1", "github.pr_commit.get", map[string]any{
"workspace_id": "workspace-1", "owner": "acme", "repo": "widget",
"sha": "5555555555555555555555555555555555555555",
})
if err != nil {
t.Fatalf("create request: %v", err)
}
response, err := wsGetPRCommitDetail(svc, testLogger(t))(context.Background(), message)
if err != nil {
t.Fatalf("handler error: %v", err)
}
if response.Type != ws.MessageTypeError || !strings.Contains(string(response.Payload), denied.Error()) {
t.Fatalf("response = %#v, want workspace authorization error", response)
}
}