Skip to content

Commit

Permalink
Add support for cursor pagination in AlertListOptions (#2512)
Browse files Browse the repository at this point in the history
Fixes: #2511.
  • Loading branch information
jporzucek committed Nov 4, 2022
1 parent 3bfe921 commit 020d9ae
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
4 changes: 4 additions & 0 deletions github/code-scanning.go
Expand Up @@ -121,6 +121,10 @@ type AlertListOptions struct {
// Return code scanning alerts for a specific branch reference. The ref must be formatted as heads/<branch name>.
Ref string `url:"ref,omitempty"`

ListCursorOptions

// Add ListOptions so offset pagination with integer type "page" query parameter is accepted
// since ListCursorOptions accepts "page" as string only.
ListOptions
}

Expand Down
126 changes: 126 additions & 0 deletions github/code-scanning_test.go
Expand Up @@ -293,6 +293,132 @@ func TestCodeScanningService_ListAlertsForOrg(t *testing.T) {
})
}

func TestCodeScanningService_ListAlertsForOrgLisCursorOptions(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/orgs/o/code-scanning/alerts", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{"state": "open", "ref": "heads/master", "per_page": "1", "before": "deadbeefb", "after": "deadbeefa"})
fmt.Fprint(w, `[{
"repository": {
"id": 1,
"name": "n",
"url": "url"
},
"rule_id":"js/trivial-conditional",
"rule_severity":"warning",
"rule_description":"Useless conditional",
"tool": {
"name": "CodeQL",
"guid": null,
"version": "1.4.0"
},
"rule": {
"id": "js/trivial-conditional",
"severity": "warning",
"description": "Useless conditional",
"name": "js/trivial-conditional",
"full_description": "Expression has no effect",
"help": "Expression has no effect"
},
"most_recent_instance": {
"ref": "refs/heads/main",
"state": "open",
"commit_sha": "abcdefg12345",
"message": {
"text": "This path depends on a user-provided value."
},
"location": {
"path": "spec-main/api-session-spec.ts",
"start_line": 917,
"end_line": 917,
"start_column": 7,
"end_column": 18
},
"classifications": [
"test"
]
},
"created_at":"2020-05-06T12:00:00Z",
"state":"open",
"closed_by":null,
"closed_at":null,
"url":"https://api.github.com/repos/o/r/code-scanning/alerts/25",
"html_url":"https://github.com/o/r/security/code-scanning/25"
}]`)
})

opts := &AlertListOptions{State: "open", Ref: "heads/master", ListCursorOptions: ListCursorOptions{PerPage: 1, Before: "deadbeefb", After: "deadbeefa"}}
ctx := context.Background()
alerts, _, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts)
if err != nil {
t.Errorf("CodeScanning.ListAlertsForOrg returned error: %v", err)
}

date := Timestamp{time.Date(2020, time.May, 06, 12, 00, 00, 0, time.UTC)}
want := []*Alert{
{
Repository: &Repository{
ID: Int64(1),
URL: String("url"),
Name: String("n"),
},
RuleID: String("js/trivial-conditional"),
RuleSeverity: String("warning"),
RuleDescription: String("Useless conditional"),
Tool: &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")},
Rule: &Rule{
ID: String("js/trivial-conditional"),
Severity: String("warning"),
Description: String("Useless conditional"),
Name: String("js/trivial-conditional"),
FullDescription: String("Expression has no effect"),
Help: String("Expression has no effect"),
},
CreatedAt: &date,
State: String("open"),
ClosedBy: nil,
ClosedAt: nil,
URL: String("https://api.github.com/repos/o/r/code-scanning/alerts/25"),
HTMLURL: String("https://github.com/o/r/security/code-scanning/25"),
MostRecentInstance: &MostRecentInstance{
Ref: String("refs/heads/main"),
State: String("open"),
CommitSHA: String("abcdefg12345"),
Message: &Message{
Text: String("This path depends on a user-provided value."),
},
Location: &Location{
Path: String("spec-main/api-session-spec.ts"),
StartLine: Int(917),
EndLine: Int(917),
StartColumn: Int(7),
EndColumn: Int(18),
},
Classifications: []string{"test"},
},
},
}
if !cmp.Equal(alerts, want) {
t.Errorf("CodeScanning.ListAlertsForOrg returned %+v, want %+v", *&alerts, *&want)
}

const methodName = "ListAlertsForOrg"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.CodeScanning.ListAlertsForOrg(ctx, "\n", opts)
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}

func TestCodeScanningService_ListAlertsForRepo(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()
Expand Down

0 comments on commit 020d9ae

Please sign in to comment.