package db import ( "errors" "testing" ) func TestCreatePullNumbersPerRepo(t *testing.T) { database := openTestDB(t) ownerID, _ := CreateUser(database, "josie", "hash") repoA, _ := CreateRepo(database, ownerID, "alpha", "", "public") repoB, _ := CreateRepo(database, ownerID, "beta", "", "public") first, err := CreatePull(database, repoA.ID, "one", "body", "main", "feature", ownerID, "josie", "", false) if err != nil { t.Fatalf("CreatePull A1: %v", err) } second, err := CreatePull(database, repoA.ID, "two", "body", "main", "feature2", ownerID, "josie", "", false) if err != nil { t.Fatalf("CreatePull A2: %v", err) } other, err := CreatePull(database, repoB.ID, "other", "body", "main", "feature", 0, "guest", "[EMAIL]", true) if err != nil { t.Fatalf("CreatePull B1: %v", err) } if first.Number != 1 || second.Number != 2 || other.Number != 1 { t.Errorf("numbers = %d, %d, %d, want 1, 2, 1", first.Number, second.Number, other.Number) } if first.State != "open" { t.Errorf("default state = %q, want open", first.State) } if !other.Pending || other.AuthorID.Valid { t.Errorf("guest pull = %+v, want pending with NULL author_id", other) } if !first.AuthorID.Valid || first.AuthorID.Int64 != ownerID { t.Errorf("owner pull AuthorID = %+v, want %d", first.AuthorID, ownerID) } if _, err := GetPullByNumber(database, repoB.ID, 2); !errors.Is(err, ErrNotFound) { t.Errorf("cross-repo pull err = %v, want ErrNotFound", err) } } func TestListPullsFilters(t *testing.T) { database := openTestDB(t) ownerID, _ := CreateUser(database, "josie", "hash") repo, _ := CreateRepo(database, ownerID, "alpha", "", "public") open, _ := CreatePull(database, repo.ID, "open", "", "main", "feature", ownerID, "josie", "", false) closed, _ := CreatePull(database, repo.ID, "closed", "", "main", "feature2", ownerID, "josie", "", false) merged, _ := CreatePull(database, repo.ID, "merged", "", "main", "feature3", ownerID, "josie", "", false) pending, _ := CreatePull(database, repo.ID, "pending", "", "main", "feature4", 0, "guest", "", true) if err := SetPullState(database, repo.ID, closed.Number, "closed"); err != nil { t.Fatalf("SetPullState closed: %v", err) } if err := SetPullMerged(database, repo.ID, merged.Number, "deadbeef"); err != nil { t.Fatalf("SetPullMerged: %v", err) } public, err := ListPulls(database, repo.ID, false, "") if err != nil { t.Fatalf("ListPulls public: %v", err) } if len(public) != 3 { t.Errorf("public pulls = %d, want 3 (pending hidden)", len(public)) } owner, _ := ListPulls(database, repo.ID, true, "") if len(owner) != 4 || !owner[0].Pending { t.Errorf("owner pulls = %+v, want 4 with pending first", owner) } openList, _ := ListPulls(database, repo.ID, true, "open") if len(openList) != 2 { t.Errorf("open pulls = %d, want 2 (open + pending)", len(openList)) } closedList, _ := ListPulls(database, repo.ID, true, "closed") if len(closedList) != 1 || closedList[0].Number != closed.Number { t.Errorf("closed pulls = %+v, want the closed one", closedList) } mergedList, _ := ListPulls(database, repo.ID, true, "merged") if len(mergedList) != 1 || mergedList[0].MergeCommit != "deadbeef" || !mergedList[0].MergedAt.Valid { t.Errorf("merged pulls = %+v, want merged with commit and timestamp", mergedList) } _ = open _ = pending } func TestSetPullStateReopen(t *testing.T) { database := openTestDB(t) ownerID, _ := CreateUser(database, "josie", "hash") repo, _ := CreateRepo(database, ownerID, "alpha", "", "public") pull, _ := CreatePull(database, repo.ID, "t", "", "main", "feature", ownerID, "josie", "", false) if err := SetPullState(database, repo.ID, pull.Number, "closed"); err != nil { t.Fatalf("close: %v", err) } closed, _ := GetPullByNumber(database, repo.ID, pull.Number) if closed.State != "closed" || !closed.ClosedAt.Valid { t.Errorf("after close = %+v, want closed with closed_at", closed) } if err := SetPullState(database, repo.ID, pull.Number, "open"); err != nil { t.Fatalf("reopen: %v", err) } reopened, _ := GetPullByNumber(database, repo.ID, pull.Number) if reopened.ClosedAt.Valid { t.Error("closed_at set after reopen, want NULL") } } func TestApproveAndDeletePull(t *testing.T) { database := openTestDB(t) ownerID, _ := CreateUser(database, "josie", "hash") repo, _ := CreateRepo(database, ownerID, "alpha", "", "public") pull, _ := CreatePull(database, repo.ID, "guest pr", "", "main", "feature", 0, "guest", "", true) if _, err := CreatePullComment(database, pull.ID, "reply", ownerID, "josie", "", false); err != nil { t.Fatalf("CreatePullComment: %v", err) } if pending, _ := CountPending(database, repo.ID); pending != 1 { t.Errorf("CountPending = %d, want 1", pending) } if err := ApprovePull(database, repo.ID, pull.Number); err != nil { t.Fatalf("ApprovePull: %v", err) } got, _ := GetPullByNumber(database, repo.ID, pull.Number) if got.Pending { t.Error("pull still pending after approve") } if err := DeletePull(database, repo.ID, pull.Number); err != nil { t.Fatalf("DeletePull: %v", err) } if _, err := GetPullByNumber(database, repo.ID, pull.Number); !errors.Is(err, ErrNotFound) { t.Errorf("pull after delete err = %v, want ErrNotFound", err) } comments, _ := ListPullComments(database, pull.ID, true) if len(comments) != 0 { t.Errorf("comments after cascade = %d, want 0", len(comments)) } } func TestPullCommentsModeration(t *testing.T) { database := openTestDB(t) ownerID, _ := CreateUser(database, "josie", "hash") repo, _ := CreateRepo(database, ownerID, "alpha", "", "public") pull, _ := CreatePull(database, repo.ID, "t", "", "main", "feature", ownerID, "josie", "", false) ownerComment, _ := CreatePullComment(database, pull.ID, "owner", ownerID, "josie", "", false) guestComment, _ := CreatePullComment(database, pull.ID, "guest", 0, "guest", "", true) public, _ := ListPullComments(database, pull.ID, false) if len(public) != 1 || public[0].ID != ownerComment.ID { t.Errorf("public comments = %+v, want only the owner one", public) } if err := ApprovePullComment(database, pull.ID, guestComment.ID); err != nil { t.Fatalf("ApprovePullComment: %v", err) } if pending, _ := CountPending(database, repo.ID); pending != 0 { t.Errorf("CountPending after approve = %d, want 0", pending) } if err := DeletePullComment(database, pull.ID, guestComment.ID); err != nil { t.Fatalf("DeletePullComment: %v", err) } if err := ApprovePullComment(database, pull.ID+999, ownerComment.ID); !errors.Is(err, ErrNotFound) { t.Errorf("approve wrong pull err = %v, want ErrNotFound", err) } }