test(agent-task/capi): add tests for job-related methods
Signed-off-by: Babak K. Shandiz <babakks@github.com>
This commit is contained in:
parent
79602d3334
commit
be8e6f6491
1 changed files with 369 additions and 0 deletions
369
pkg/cmd/agent-task/capi/job_test.go
Normal file
369
pkg/cmd/agent-task/capi/job_test.go
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
package capi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/MakeNowJust/heredoc"
|
||||
"github.com/cli/cli/v2/internal/config"
|
||||
"github.com/cli/cli/v2/pkg/httpmock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetJobRequiresRepoAndJobID(t *testing.T) {
|
||||
client := &CAPIClient{}
|
||||
_, err := client.GetJob(context.Background(), "", "", "only-job-id")
|
||||
assert.EqualError(t, err, "owner, repo, and jobID are required")
|
||||
_, err = client.GetJob(context.Background(), "", "only-repo", "")
|
||||
assert.EqualError(t, err, "owner, repo, and jobID are required")
|
||||
_, err = client.GetJob(context.Background(), "only-owner", "", "")
|
||||
assert.EqualError(t, err, "owner, repo, and jobID are required")
|
||||
_, err = client.GetJob(context.Background(), "", "", "")
|
||||
assert.EqualError(t, err, "owner, repo, and jobID are required")
|
||||
}
|
||||
|
||||
func TestGetJob(t *testing.T) {
|
||||
sampleDateString := "2025-08-29T00:00:00Z"
|
||||
sampleDate, err := time.Parse(time.RFC3339, sampleDateString)
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
httpStubs func(*testing.T, *httpmock.Registry)
|
||||
wantErr string
|
||||
wantOut *Job
|
||||
}{
|
||||
{
|
||||
name: "job without PR",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("GET", "agents/swe/v1/jobs/OWNER/REPO/job123"), "api.githubcopilot.com"),
|
||||
httpmock.StatusStringResponse(200, heredoc.Docf(`
|
||||
{
|
||||
"job_id": "job123",
|
||||
"session_id": "sess1",
|
||||
"problem_statement": "Do the thing",
|
||||
"event_type": "foo",
|
||||
"content_filter_mode": "foo",
|
||||
"status": "foo",
|
||||
"result": "foo",
|
||||
"actor": {
|
||||
"id": 1,
|
||||
"login": "octocat"
|
||||
},
|
||||
"created_at": "%[1]s",
|
||||
"updated_at": "%[1]s"
|
||||
}`,
|
||||
sampleDateString,
|
||||
)),
|
||||
)
|
||||
},
|
||||
wantOut: &Job{
|
||||
ID: "job123",
|
||||
SessionID: "sess1",
|
||||
ProblemStatement: "Do the thing",
|
||||
EventType: "foo",
|
||||
ContentFilterMode: "foo",
|
||||
Status: "foo",
|
||||
Result: "foo",
|
||||
Actor: &JobActor{
|
||||
ID: 1,
|
||||
Login: "octocat",
|
||||
},
|
||||
CreatedAt: sampleDate,
|
||||
UpdatedAt: sampleDate,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "job with PR",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("GET", "agents/swe/v1/jobs/OWNER/REPO/job123"), "api.githubcopilot.com"),
|
||||
httpmock.StatusStringResponse(200, heredoc.Docf(`
|
||||
{
|
||||
"job_id": "job123",
|
||||
"session_id": "sess1",
|
||||
"problem_statement": "Do the thing",
|
||||
"event_type": "foo",
|
||||
"content_filter_mode": "foo",
|
||||
"status": "foo",
|
||||
"result": "foo",
|
||||
"actor": {
|
||||
"id": 1,
|
||||
"login": "octocat"
|
||||
},
|
||||
"created_at": "%[1]s",
|
||||
"updated_at": "%[1]s",
|
||||
"pull_request": {
|
||||
"id": 101,
|
||||
"number": 42
|
||||
}
|
||||
}`,
|
||||
sampleDateString,
|
||||
)),
|
||||
)
|
||||
},
|
||||
wantOut: &Job{
|
||||
ID: "job123",
|
||||
SessionID: "sess1",
|
||||
ProblemStatement: "Do the thing",
|
||||
EventType: "foo",
|
||||
ContentFilterMode: "foo",
|
||||
Status: "foo",
|
||||
Result: "foo",
|
||||
Actor: &JobActor{
|
||||
ID: 1,
|
||||
Login: "octocat",
|
||||
},
|
||||
CreatedAt: sampleDate,
|
||||
UpdatedAt: sampleDate,
|
||||
PullRequest: &JobPullRequest{
|
||||
ID: 101,
|
||||
Number: 42,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "job not found",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("GET", "agents/swe/v1/jobs/OWNER/REPO/job123"), "api.githubcopilot.com"),
|
||||
httpmock.StatusStringResponse(404, `{}`),
|
||||
)
|
||||
},
|
||||
wantErr: "failed to get job: 404 Not Found",
|
||||
},
|
||||
{
|
||||
name: "API error",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("GET", "agents/swe/v1/jobs/OWNER/REPO/job123"), "api.githubcopilot.com"),
|
||||
httpmock.StatusStringResponse(500, `{}`),
|
||||
)
|
||||
},
|
||||
wantErr: "failed to get job: 500 Internal Server Error",
|
||||
},
|
||||
{
|
||||
name: "invalid JSON response",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("GET", "agents/swe/v1/jobs/OWNER/REPO/job123"), "api.githubcopilot.com"),
|
||||
httpmock.StatusStringResponse(200, ``),
|
||||
)
|
||||
},
|
||||
wantErr: "failed to decode get job response: EOF",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
reg := &httpmock.Registry{}
|
||||
if tt.httpStubs != nil {
|
||||
tt.httpStubs(t, reg)
|
||||
}
|
||||
defer reg.Verify(t)
|
||||
|
||||
httpClient := &http.Client{Transport: reg}
|
||||
|
||||
cfg := config.NewBlankConfig()
|
||||
capiClient := NewCAPIClient(httpClient, cfg.Authentication())
|
||||
|
||||
job, err := capiClient.GetJob(context.Background(), "OWNER", "REPO", "job123")
|
||||
|
||||
if tt.wantErr != "" {
|
||||
require.EqualError(t, err, tt.wantErr)
|
||||
require.Nil(t, job)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.wantOut, job)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateJobRequiresRepoAndProblemStatement(t *testing.T) {
|
||||
client := &CAPIClient{}
|
||||
|
||||
_, err := client.CreateJob(context.Background(), "", "only-repo", "", "")
|
||||
assert.EqualError(t, err, "owner and repo are required")
|
||||
_, err = client.CreateJob(context.Background(), "only-owner", "", "", "")
|
||||
assert.EqualError(t, err, "owner and repo are required")
|
||||
_, err = client.CreateJob(context.Background(), "", "", "", "")
|
||||
assert.EqualError(t, err, "owner and repo are required")
|
||||
|
||||
_, err = client.CreateJob(context.Background(), "owner", "repo", "", "")
|
||||
assert.EqualError(t, err, "problem statement is required")
|
||||
}
|
||||
|
||||
func TestCreateJob(t *testing.T) {
|
||||
sampleDateString := "2025-08-29T00:00:00Z"
|
||||
sampleDate, err := time.Parse(time.RFC3339, sampleDateString)
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
baseBranch string
|
||||
httpStubs func(*testing.T, *httpmock.Registry)
|
||||
wantErr string
|
||||
wantOut *Job
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("POST", "agents/swe/v1/jobs/OWNER/REPO"), "api.githubcopilot.com"),
|
||||
httpmock.RESTPayload(201,
|
||||
heredoc.Docf(`
|
||||
{
|
||||
"job_id": "job123",
|
||||
"session_id": "sess1",
|
||||
"problem_statement": "Do the thing",
|
||||
"event_type": "foo",
|
||||
"content_filter_mode": "foo",
|
||||
"status": "foo",
|
||||
"result": "foo",
|
||||
"actor": {
|
||||
"id": 1,
|
||||
"login": "octocat"
|
||||
},
|
||||
"created_at": "%[1]s",
|
||||
"updated_at": "%[1]s"
|
||||
}
|
||||
`, sampleDateString),
|
||||
func(payload map[string]interface{}) {
|
||||
assert.Equal(t, "Do the thing", payload["problem_statement"])
|
||||
assert.Equal(t, "gh_cli", payload["event_type"])
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
wantOut: &Job{
|
||||
ID: "job123",
|
||||
SessionID: "sess1",
|
||||
ProblemStatement: "Do the thing",
|
||||
EventType: "foo",
|
||||
ContentFilterMode: "foo",
|
||||
Status: "foo",
|
||||
Result: "foo",
|
||||
Actor: &JobActor{
|
||||
ID: 1,
|
||||
Login: "octocat",
|
||||
},
|
||||
CreatedAt: sampleDate,
|
||||
UpdatedAt: sampleDate,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success with base branch",
|
||||
baseBranch: "some-branch",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("POST", "agents/swe/v1/jobs/OWNER/REPO"), "api.githubcopilot.com"),
|
||||
httpmock.RESTPayload(201,
|
||||
heredoc.Docf(`
|
||||
{
|
||||
"job_id": "job123",
|
||||
"session_id": "sess1",
|
||||
"problem_statement": "Do the thing",
|
||||
"event_type": "foo",
|
||||
"content_filter_mode": "foo",
|
||||
"status": "foo",
|
||||
"result": "foo",
|
||||
"actor": {
|
||||
"id": 1,
|
||||
"login": "octocat"
|
||||
},
|
||||
"created_at": "%[1]s",
|
||||
"updated_at": "%[1]s"
|
||||
}
|
||||
`, sampleDateString),
|
||||
func(payload map[string]interface{}) {
|
||||
assert.Equal(t, "Do the thing", payload["problem_statement"])
|
||||
assert.Equal(t, "gh_cli", payload["event_type"])
|
||||
assert.Equal(t, "refs/heads/some-branch", payload["pull_request"].(map[string]interface{})["base_ref"])
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
wantOut: &Job{
|
||||
ID: "job123",
|
||||
SessionID: "sess1",
|
||||
ProblemStatement: "Do the thing",
|
||||
EventType: "foo",
|
||||
ContentFilterMode: "foo",
|
||||
Status: "foo",
|
||||
Result: "foo",
|
||||
Actor: &JobActor{
|
||||
ID: 1,
|
||||
Login: "octocat",
|
||||
},
|
||||
CreatedAt: sampleDate,
|
||||
UpdatedAt: sampleDate,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "API error, included in response body",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("POST", "agents/swe/v1/jobs/OWNER/REPO"), "api.githubcopilot.com"),
|
||||
httpmock.StatusStringResponse(500, heredoc.Doc(`{
|
||||
"error": {
|
||||
"message": "some error"
|
||||
}
|
||||
}`)),
|
||||
)
|
||||
},
|
||||
wantErr: "failed to create job: some error",
|
||||
},
|
||||
{
|
||||
name: "API error",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("POST", "agents/swe/v1/jobs/OWNER/REPO"), "api.githubcopilot.com"),
|
||||
httpmock.StatusStringResponse(500, `{}`),
|
||||
)
|
||||
},
|
||||
wantErr: "failed to create job: 500 Internal Server Error",
|
||||
},
|
||||
{
|
||||
name: "invalid JSON response",
|
||||
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
|
||||
reg.Register(
|
||||
httpmock.WithHost(httpmock.REST("POST", "agents/swe/v1/jobs/OWNER/REPO"), "api.githubcopilot.com"),
|
||||
httpmock.StatusStringResponse(200, ``),
|
||||
)
|
||||
},
|
||||
wantErr: "failed to decode create job response: EOF",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
reg := &httpmock.Registry{}
|
||||
if tt.httpStubs != nil {
|
||||
tt.httpStubs(t, reg)
|
||||
}
|
||||
defer reg.Verify(t)
|
||||
|
||||
httpClient := &http.Client{Transport: reg}
|
||||
|
||||
cfg := config.NewBlankConfig()
|
||||
capiClient := NewCAPIClient(httpClient, cfg.Authentication())
|
||||
|
||||
job, err := capiClient.CreateJob(context.Background(), "OWNER", "REPO", "Do the thing", tt.baseBranch)
|
||||
|
||||
if tt.wantErr != "" {
|
||||
require.EqualError(t, err, tt.wantErr)
|
||||
require.Nil(t, job)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.wantOut, job)
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue