diff --git a/milestones.go b/milestones.go index d46ea3e..f5df222 100644 --- a/milestones.go +++ b/milestones.go @@ -2,6 +2,7 @@ package forge import ( "context" + "iter" "dappco.re/go/core/forge/types" ) @@ -20,6 +21,18 @@ func newMilestoneService(c *Client) *MilestoneService { return &MilestoneService{client: c} } +// List returns a single page of milestones for a repository. +func (s *MilestoneService) List(ctx context.Context, params Params, opts ListOptions) (*PagedResult[types.Milestone], error) { + path := ResolvePath("/api/v1/repos/{owner}/{repo}/milestones", params) + return ListPage[types.Milestone](ctx, s.client, path, nil, opts) +} + +// Iter returns an iterator over all milestones for a repository. +func (s *MilestoneService) Iter(ctx context.Context, params Params) iter.Seq2[types.Milestone, error] { + path := ResolvePath("/api/v1/repos/{owner}/{repo}/milestones", params) + return ListIter[types.Milestone](ctx, s.client, path, nil) +} + // ListAll returns all milestones for a repository. func (s *MilestoneService) ListAll(ctx context.Context, params Params) ([]types.Milestone, error) { path := ResolvePath("/api/v1/repos/{owner}/{repo}/milestones", params) diff --git a/milestones_test.go b/milestones_test.go index 04f0b9e..f225d57 100644 --- a/milestones_test.go +++ b/milestones_test.go @@ -5,11 +5,92 @@ import ( json "github.com/goccy/go-json" "net/http" "net/http/httptest" + "reflect" "testing" "dappco.re/go/core/forge/types" ) +func TestMilestoneService_List_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Path != "/api/v1/repos/core/go-forge/milestones" { + t.Errorf("wrong path: %s", r.URL.Path) + } + if got := r.URL.Query().Get("page"); got != "1" { + t.Errorf("got page=%q, want %q", got, "1") + } + if got := r.URL.Query().Get("limit"); got != "1" { + t.Errorf("got limit=%q, want %q", got, "1") + } + w.Header().Set("X-Total-Count", "2") + json.NewEncoder(w).Encode([]types.Milestone{{ID: 2, Title: "v2.0"}}) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + page, err := f.Milestones.List(context.Background(), Params{"owner": "core", "repo": "go-forge"}, ListOptions{Page: 1, Limit: 1}) + if err != nil { + t.Fatal(err) + } + if page.Page != 1 { + t.Errorf("got page=%d, want 1", page.Page) + } + if page.TotalCount != 2 { + t.Errorf("got total=%d, want 2", page.TotalCount) + } + if !page.HasMore { + t.Error("expected HasMore=true") + } + if len(page.Items) != 1 || page.Items[0].Title != "v2.0" { + t.Fatalf("unexpected items: %+v", page.Items) + } +} + +func TestMilestoneService_Iter_Good(t *testing.T) { + requests := 0 + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requests++ + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Path != "/api/v1/repos/core/go-forge/milestones" { + t.Errorf("wrong path: %s", r.URL.Path) + } + switch requests { + case 1: + if got := r.URL.Query().Get("page"); got != "1" { + t.Errorf("got page=%q, want %q", got, "1") + } + w.Header().Set("X-Total-Count", "2") + json.NewEncoder(w).Encode([]types.Milestone{{ID: 1, Title: "v1.0"}}) + case 2: + if got := r.URL.Query().Get("page"); got != "2" { + t.Errorf("got page=%q, want %q", got, "2") + } + w.Header().Set("X-Total-Count", "2") + json.NewEncoder(w).Encode([]types.Milestone{{ID: 2, Title: "v2.0"}}) + default: + t.Fatalf("unexpected request %d", requests) + } + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + var got []string + for milestone, err := range f.Milestones.Iter(context.Background(), Params{"owner": "core", "repo": "go-forge"}) { + if err != nil { + t.Fatal(err) + } + got = append(got, milestone.Title) + } + if !reflect.DeepEqual(got, []string{"v1.0", "v2.0"}) { + t.Fatalf("got %v", got) + } +} + func TestMilestoneService_ListAll_Good(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet {