From 85da624437de9a2b03416d04fdfcc88dd9a709ec Mon Sep 17 00:00:00 2001 From: Andrei Rodrigues Date: Wed, 24 Jun 2026 21:04:05 -0300 Subject: [PATCH] feat: add code quality findings support --- github/code_quality.go | 94 ++++++++++++++ github/code_quality_test.go | 210 ++++++++++++++++++++++++++++++++ github/github-accessors.go | 176 ++++++++++++++++++++++++++ github/github-accessors_test.go | 194 +++++++++++++++++++++++++++++ github/github-iterators.go | 31 +++++ github/github-iterators_test.go | 72 +++++++++++ 6 files changed, 777 insertions(+) diff --git a/github/code_quality.go b/github/code_quality.go index 43a9efaa7d8..69fa4c44e03 100644 --- a/github/code_quality.go +++ b/github/code_quality.go @@ -10,6 +10,51 @@ import ( "fmt" ) +// CodeQualityFindingRule represents the rule associated with a code quality finding. +type CodeQualityFindingRule struct { + ID string `json:"id"` + Title string `json:"title"` + Description string `json:"description"` + Help *string `json:"help,omitempty"` + Severity string `json:"severity"` + Category string `json:"category"` +} + +// CodeQualityFindingLocation represents the location of a code quality finding. +type CodeQualityFindingLocation struct { + Path string `json:"path"` + StartLine *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` +} + +// CodeQualityFindingMessage represents the message of a code quality finding. +type CodeQualityFindingMessage struct { + Text string `json:"text"` + Markdown string `json:"markdown"` +} + +// CodeQualityFinding represents a single code quality finding. +type CodeQualityFinding struct { + Number int `json:"number"` + State string `json:"state"` + URL string `json:"url"` + Rule CodeQualityFindingRule `json:"rule"` + Location CodeQualityFindingLocation `json:"location"` + Message CodeQualityFindingMessage `json:"message"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +// ListCodeQualityFindingsOptions specifies the optional parameters to +// CodeQualityService.ListFindings. +type ListCodeQualityFindingsOptions struct { + State string `url:"state,omitempty"` + Direction string `url:"direction,omitempty"` + + ListCursorOptions +} + // CodeQualityService handles communication with the code quality related // methods of the GitHub API. // @@ -87,3 +132,52 @@ func (s *CodeQualityService) UpdateSetup(ctx context.Context, owner, repo string return result, resp, nil } + +// ListFindings lists code quality findings for a repository. +// +// GitHub API docs: https://docs.github.com/rest/code-quality/code-quality?apiVersion=2022-11-28#list-code-quality-findings-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-quality/findings +func (s *CodeQualityService) ListFindings(ctx context.Context, owner, repo string, opts *ListCodeQualityFindingsOptions) ([]*CodeQualityFinding, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-quality/findings", owner, repo) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, "GET", u, nil) + if err != nil { + return nil, nil, err + } + + var findings []*CodeQualityFinding + resp, err := s.client.Do(req, &findings) + if err != nil { + return nil, resp, err + } + + return findings, resp, nil +} + +// GetFinding gets a single code quality finding for a repository. +// +// GitHub API docs: https://docs.github.com/rest/code-quality/code-quality?apiVersion=2022-11-28#get-a-code-quality-finding +// +//meta:operation GET /repos/{owner}/{repo}/code-quality/findings/{finding_number} +func (s *CodeQualityService) GetFinding(ctx context.Context, owner, repo string, findingNumber int) (*CodeQualityFinding, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-quality/findings/%v", owner, repo, findingNumber) + + req, err := s.client.NewRequest(ctx, "GET", u, nil) + if err != nil { + return nil, nil, err + } + + var finding *CodeQualityFinding + resp, err := s.client.Do(req, &finding) + if err != nil { + return nil, resp, err + } + + return finding, resp, nil +} diff --git a/github/code_quality_test.go b/github/code_quality_test.go index b6f7e9c6562..2a90bf85702 100644 --- a/github/code_quality_test.go +++ b/github/code_quality_test.go @@ -182,3 +182,213 @@ func TestCodeQualityService_UpdateSetup_invalidOwner(t *testing.T) { _, _, err := client.CodeQuality.UpdateSetup(ctx, "%", "r", CodeQualityUpdateSetupRequest{}) testURLParseError(t, err) } + +func TestCodeQualityService_ListFindings(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/repos/o/r/code-quality/findings", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testFormValues(t, r, values{ + "state": "open", + "direction": "desc", + }) + fmt.Fprint(w, `[ + { + "number": 1, + "state": "open", + "url": "https://api.github.com/repos/o/r/code-quality/findings/1", + "rule": { + "id": "rule-1", + "title": "Example Rule", + "description": "An example rule description", + "help": "How to fix it", + "severity": "warning", + "category": "maintainability" + }, + "location": { + "path": "src/main.go", + "start_line": 10, + "end_line": 10, + "start_column": 1, + "end_column": 20 + }, + "message": { + "text": "Issue found", + "markdown": "**Issue found**" + }, + "created_at": `+referenceTimeStr+` + } + ]`) + }) + + ctx := t.Context() + opts := &ListCodeQualityFindingsOptions{ + State: "open", + Direction: "desc", + } + findings, _, err := client.CodeQuality.ListFindings(ctx, "o", "r", opts) + if err != nil { + t.Fatalf("CodeQuality.ListFindings returned error: %v", err) + } + + want := []*CodeQualityFinding{ + { + Number: 1, + State: "open", + URL: "https://api.github.com/repos/o/r/code-quality/findings/1", + Rule: CodeQualityFindingRule{ + ID: "rule-1", + Title: "Example Rule", + Description: "An example rule description", + Help: Ptr("How to fix it"), + Severity: "warning", + Category: "maintainability", + }, + Location: CodeQualityFindingLocation{ + Path: "src/main.go", + StartLine: Ptr(10), + EndLine: Ptr(10), + StartColumn: Ptr(1), + EndColumn: Ptr(20), + }, + Message: CodeQualityFindingMessage{ + Text: "Issue found", + Markdown: "**Issue found**", + }, + CreatedAt: &referenceTimestamp, + }, + } + if diff := cmp.Diff(want, findings); diff != "" { + t.Errorf("CodeQuality.ListFindings mismatch (-want +got):\n%v", diff) + } + + const methodName = "ListFindings" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.CodeQuality.ListFindings(ctx, "\n", "\n", opts) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.CodeQuality.ListFindings(ctx, "o", "r", opts) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestCodeQualityService_ListFindings_noOpts(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/repos/o/r/code-quality/findings", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[]`) + }) + + ctx := t.Context() + findings, _, err := client.CodeQuality.ListFindings(ctx, "o", "r", nil) + if err != nil { + t.Fatalf("CodeQuality.ListFindings returned error: %v", err) + } + + if len(findings) != 0 { + t.Errorf("CodeQuality.ListFindings returned %v findings, want 0", len(findings)) + } +} + +func TestCodeQualityService_GetFinding(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/repos/o/r/code-quality/findings/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "number": 1, + "state": "open", + "url": "https://api.github.com/repos/o/r/code-quality/findings/1", + "rule": { + "id": "rule-1", + "title": "Example Rule", + "description": "An example rule description", + "severity": "error", + "category": "reliability" + }, + "location": { + "path": "src/main.go", + "start_line": 5, + "end_line": 5 + }, + "message": { + "text": "Critical issue", + "markdown": "**Critical issue**" + }, + "created_at": `+referenceTimeStr+` + }`) + }) + + ctx := t.Context() + finding, _, err := client.CodeQuality.GetFinding(ctx, "o", "r", 1) + if err != nil { + t.Fatalf("CodeQuality.GetFinding returned error: %v", err) + } + + want := &CodeQualityFinding{ + Number: 1, + State: "open", + URL: "https://api.github.com/repos/o/r/code-quality/findings/1", + Rule: CodeQualityFindingRule{ + ID: "rule-1", + Title: "Example Rule", + Description: "An example rule description", + Severity: "error", + Category: "reliability", + }, + Location: CodeQualityFindingLocation{ + Path: "src/main.go", + StartLine: Ptr(5), + EndLine: Ptr(5), + }, + Message: CodeQualityFindingMessage{ + Text: "Critical issue", + Markdown: "**Critical issue**", + }, + CreatedAt: &referenceTimestamp, + } + if diff := cmp.Diff(want, finding); diff != "" { + t.Errorf("CodeQuality.GetFinding mismatch (-want +got):\n%v", diff) + } + + const methodName = "GetFinding" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.CodeQuality.GetFinding(ctx, "\n", "\n", 1) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.CodeQuality.GetFinding(ctx, "o", "r", 1) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestCodeQualityService_ListFindings_invalidOwner(t *testing.T) { + t.Parallel() + client, _, _ := setup(t) + + ctx := t.Context() + _, _, err := client.CodeQuality.ListFindings(ctx, "%", "r", nil) + testURLParseError(t, err) +} + +func TestCodeQualityService_GetFinding_invalidOwner(t *testing.T) { + t.Parallel() + client, _, _ := setup(t) + + ctx := t.Context() + _, _, err := client.CodeQuality.GetFinding(ctx, "%", "r", 1) + testURLParseError(t, err) +} diff --git a/github/github-accessors.go b/github/github-accessors.go index b5c01e9989b..1966adb011e 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -4806,6 +4806,166 @@ func (c *CodeQLDatabase) GetURL() string { return *c.URL } +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CodeQualityFinding) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetLocation returns the Location field. +func (c *CodeQualityFinding) GetLocation() CodeQualityFindingLocation { + if c == nil { + return CodeQualityFindingLocation{} + } + return c.Location +} + +// GetMessage returns the Message field. +func (c *CodeQualityFinding) GetMessage() CodeQualityFindingMessage { + if c == nil { + return CodeQualityFindingMessage{} + } + return c.Message +} + +// GetNumber returns the Number field. +func (c *CodeQualityFinding) GetNumber() int { + if c == nil { + return 0 + } + return c.Number +} + +// GetRule returns the Rule field. +func (c *CodeQualityFinding) GetRule() CodeQualityFindingRule { + if c == nil { + return CodeQualityFindingRule{} + } + return c.Rule +} + +// GetState returns the State field. +func (c *CodeQualityFinding) GetState() string { + if c == nil { + return "" + } + return c.State +} + +// GetURL returns the URL field. +func (c *CodeQualityFinding) GetURL() string { + if c == nil { + return "" + } + return c.URL +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (c *CodeQualityFindingLocation) GetEndColumn() int { + if c == nil || c.EndColumn == nil { + return 0 + } + return *c.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (c *CodeQualityFindingLocation) GetEndLine() int { + if c == nil || c.EndLine == nil { + return 0 + } + return *c.EndLine +} + +// GetPath returns the Path field. +func (c *CodeQualityFindingLocation) GetPath() string { + if c == nil { + return "" + } + return c.Path +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (c *CodeQualityFindingLocation) GetStartColumn() int { + if c == nil || c.StartColumn == nil { + return 0 + } + return *c.StartColumn +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (c *CodeQualityFindingLocation) GetStartLine() int { + if c == nil || c.StartLine == nil { + return 0 + } + return *c.StartLine +} + +// GetMarkdown returns the Markdown field. +func (c *CodeQualityFindingMessage) GetMarkdown() string { + if c == nil { + return "" + } + return c.Markdown +} + +// GetText returns the Text field. +func (c *CodeQualityFindingMessage) GetText() string { + if c == nil { + return "" + } + return c.Text +} + +// GetCategory returns the Category field. +func (c *CodeQualityFindingRule) GetCategory() string { + if c == nil { + return "" + } + return c.Category +} + +// GetDescription returns the Description field. +func (c *CodeQualityFindingRule) GetDescription() string { + if c == nil { + return "" + } + return c.Description +} + +// GetHelp returns the Help field if it's non-nil, zero value otherwise. +func (c *CodeQualityFindingRule) GetHelp() string { + if c == nil || c.Help == nil { + return "" + } + return *c.Help +} + +// GetID returns the ID field. +func (c *CodeQualityFindingRule) GetID() string { + if c == nil { + return "" + } + return c.ID +} + +// GetSeverity returns the Severity field. +func (c *CodeQualityFindingRule) GetSeverity() string { + if c == nil { + return "" + } + return c.Severity +} + +// GetTitle returns the Title field. +func (c *CodeQualityFindingRule) GetTitle() string { + if c == nil { + return "" + } + return c.Title +} + // GetLanguages returns the Languages slice if it's non-nil, nil otherwise. func (c *CodeQualitySetupConfiguration) GetLanguages() []string { if c == nil || c.Languages == nil { @@ -21918,6 +22078,22 @@ func (l *ListCheckSuiteResults) GetTotal() int { return *l.Total } +// GetDirection returns the Direction field. +func (l *ListCodeQualityFindingsOptions) GetDirection() string { + if l == nil { + return "" + } + return l.Direction +} + +// GetState returns the State field. +func (l *ListCodeQualityFindingsOptions) GetState() string { + if l == nil { + return "" + } + return l.State +} + // GetAfter returns the After field. func (l *ListCodeSecurityConfigurationRepositoriesOptions) GetAfter() string { if l == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index fe11f19855f..37fc83b8fb9 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -6130,6 +6130,184 @@ func TestCodeQLDatabase_GetURL(tt *testing.T) { c.GetURL() } +func TestCodeQualityFinding_GetCreatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + c := &CodeQualityFinding{CreatedAt: &zeroValue} + c.GetCreatedAt() + c = &CodeQualityFinding{} + c.GetCreatedAt() + c = nil + c.GetCreatedAt() +} + +func TestCodeQualityFinding_GetLocation(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFinding{} + c.GetLocation() + c = nil + c.GetLocation() +} + +func TestCodeQualityFinding_GetMessage(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFinding{} + c.GetMessage() + c = nil + c.GetMessage() +} + +func TestCodeQualityFinding_GetNumber(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFinding{} + c.GetNumber() + c = nil + c.GetNumber() +} + +func TestCodeQualityFinding_GetRule(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFinding{} + c.GetRule() + c = nil + c.GetRule() +} + +func TestCodeQualityFinding_GetState(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFinding{} + c.GetState() + c = nil + c.GetState() +} + +func TestCodeQualityFinding_GetURL(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFinding{} + c.GetURL() + c = nil + c.GetURL() +} + +func TestCodeQualityFindingLocation_GetEndColumn(tt *testing.T) { + tt.Parallel() + var zeroValue int + c := &CodeQualityFindingLocation{EndColumn: &zeroValue} + c.GetEndColumn() + c = &CodeQualityFindingLocation{} + c.GetEndColumn() + c = nil + c.GetEndColumn() +} + +func TestCodeQualityFindingLocation_GetEndLine(tt *testing.T) { + tt.Parallel() + var zeroValue int + c := &CodeQualityFindingLocation{EndLine: &zeroValue} + c.GetEndLine() + c = &CodeQualityFindingLocation{} + c.GetEndLine() + c = nil + c.GetEndLine() +} + +func TestCodeQualityFindingLocation_GetPath(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFindingLocation{} + c.GetPath() + c = nil + c.GetPath() +} + +func TestCodeQualityFindingLocation_GetStartColumn(tt *testing.T) { + tt.Parallel() + var zeroValue int + c := &CodeQualityFindingLocation{StartColumn: &zeroValue} + c.GetStartColumn() + c = &CodeQualityFindingLocation{} + c.GetStartColumn() + c = nil + c.GetStartColumn() +} + +func TestCodeQualityFindingLocation_GetStartLine(tt *testing.T) { + tt.Parallel() + var zeroValue int + c := &CodeQualityFindingLocation{StartLine: &zeroValue} + c.GetStartLine() + c = &CodeQualityFindingLocation{} + c.GetStartLine() + c = nil + c.GetStartLine() +} + +func TestCodeQualityFindingMessage_GetMarkdown(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFindingMessage{} + c.GetMarkdown() + c = nil + c.GetMarkdown() +} + +func TestCodeQualityFindingMessage_GetText(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFindingMessage{} + c.GetText() + c = nil + c.GetText() +} + +func TestCodeQualityFindingRule_GetCategory(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFindingRule{} + c.GetCategory() + c = nil + c.GetCategory() +} + +func TestCodeQualityFindingRule_GetDescription(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFindingRule{} + c.GetDescription() + c = nil + c.GetDescription() +} + +func TestCodeQualityFindingRule_GetHelp(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CodeQualityFindingRule{Help: &zeroValue} + c.GetHelp() + c = &CodeQualityFindingRule{} + c.GetHelp() + c = nil + c.GetHelp() +} + +func TestCodeQualityFindingRule_GetID(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFindingRule{} + c.GetID() + c = nil + c.GetID() +} + +func TestCodeQualityFindingRule_GetSeverity(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFindingRule{} + c.GetSeverity() + c = nil + c.GetSeverity() +} + +func TestCodeQualityFindingRule_GetTitle(tt *testing.T) { + tt.Parallel() + c := &CodeQualityFindingRule{} + c.GetTitle() + c = nil + c.GetTitle() +} + func TestCodeQualitySetupConfiguration_GetLanguages(tt *testing.T) { tt.Parallel() zeroValue := []string{} @@ -27634,6 +27812,22 @@ func TestListCheckSuiteResults_GetTotal(tt *testing.T) { l.GetTotal() } +func TestListCodeQualityFindingsOptions_GetDirection(tt *testing.T) { + tt.Parallel() + l := &ListCodeQualityFindingsOptions{} + l.GetDirection() + l = nil + l.GetDirection() +} + +func TestListCodeQualityFindingsOptions_GetState(tt *testing.T) { + tt.Parallel() + l := &ListCodeQualityFindingsOptions{} + l.GetState() + l = nil + l.GetState() +} + func TestListCodeSecurityConfigurationRepositoriesOptions_GetAfter(tt *testing.T) { tt.Parallel() l := &ListCodeSecurityConfigurationRepositoriesOptions{} diff --git a/github/github-iterators.go b/github/github-iterators.go index 7d0a13f0919..db1316dab38 100644 --- a/github/github-iterators.go +++ b/github/github-iterators.go @@ -1921,6 +1921,37 @@ func (s *ClassroomService) ListClassroomsIter(ctx context.Context, opts *ListOpt } } +// ListFindingsIter returns an iterator that paginates through all results of ListFindings. +func (s *CodeQualityService) ListFindingsIter(ctx context.Context, owner string, repo string, opts *ListCodeQualityFindingsOptions) iter.Seq2[*CodeQualityFinding, error] { + return func(yield func(*CodeQualityFinding, error) bool) { + // Create a copy of opts to avoid mutating the caller's struct + if opts == nil { + opts = &ListCodeQualityFindingsOptions{} + } else { + opts = Ptr(*opts) + } + + for { + results, resp, err := s.ListFindings(ctx, owner, repo, opts) + if err != nil { + yield(nil, err) + return + } + + for _, item := range results { + if !yield(item, nil) { + return + } + } + + if resp.After == "" { + break + } + opts.ListCursorOptions.After = resp.After + } + } +} + // ListAlertInstancesIter returns an iterator that paginates through all results of ListAlertInstances. func (s *CodeScanningService) ListAlertInstancesIter(ctx context.Context, owner string, repo string, id int64, opts *AlertInstancesListOptions) iter.Seq2[*MostRecentInstance, error] { return func(yield func(*MostRecentInstance, error) bool) { diff --git a/github/github-iterators_test.go b/github/github-iterators_test.go index 071516b9264..634bc4618c4 100644 --- a/github/github-iterators_test.go +++ b/github/github-iterators_test.go @@ -4119,6 +4119,78 @@ func TestClassroomService_ListClassroomsIter(t *testing.T) { } } +func TestCodeQualityService_ListFindingsIter(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + var callNum int + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + callNum++ + switch callNum { + case 1: + w.Header().Set("Link", `; rel="next"`) + fmt.Fprint(w, `[{},{},{}]`) + case 2: + fmt.Fprint(w, `[{},{},{},{}]`) + case 3: + fmt.Fprint(w, `[{},{}]`) + case 4: + w.WriteHeader(http.StatusNotFound) + case 5: + fmt.Fprint(w, `[{},{}]`) + } + }) + + iter := client.CodeQuality.ListFindingsIter(t.Context(), "", "", nil) + var gotItems int + for _, err := range iter { + gotItems++ + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + } + if want := 7; gotItems != want { + t.Errorf("client.CodeQuality.ListFindingsIter call 1 got %v items; want %v", gotItems, want) + } + + opts := &ListCodeQualityFindingsOptions{} + iter = client.CodeQuality.ListFindingsIter(t.Context(), "", "", opts) + gotItems = 0 + for _, err := range iter { + gotItems++ + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + } + if want := 2; gotItems != want { + t.Errorf("client.CodeQuality.ListFindingsIter call 2 got %v items; want %v", gotItems, want) + } + + iter = client.CodeQuality.ListFindingsIter(t.Context(), "", "", nil) + gotItems = 0 + for _, err := range iter { + gotItems++ + if err == nil { + t.Error("expected error; got nil") + } + } + if gotItems != 1 { + t.Errorf("client.CodeQuality.ListFindingsIter call 3 got %v items; want 1 (an error)", gotItems) + } + + iter = client.CodeQuality.ListFindingsIter(t.Context(), "", "", nil) + gotItems = 0 + iter(func(item *CodeQualityFinding, err error) bool { + gotItems++ + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + return false + }) + if gotItems != 1 { + t.Errorf("client.CodeQuality.ListFindingsIter call 4 got %v items; want 1 (an error)", gotItems) + } +} + func TestCodeScanningService_ListAlertInstancesIter(t *testing.T) { t.Parallel() client, mux, _ := setup(t)