Files
go-github/github/classroom_test.go

698 lines
22 KiB
Go

// Copyright 2025 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"fmt"
"net/http"
"testing"
"github.com/google/go-cmp/cmp"
)
func TestClassroomService_GetAssignment(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)
mux.HandleFunc("/assignments/12", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{
"id": 12,
"public_repo": false,
"title": "Intro to Binaries",
"type": "individual",
"invite_link": "https://example.com/a/Lx7jiUgx",
"invitations_enabled": true,
"slug": "intro-to-binaries",
"students_are_repo_admins": false,
"feedback_pull_requests_enabled": true,
"max_teams": 0,
"max_members": 0,
"editor": "codespaces",
"accepted": 100,
"submitted": 40,
"passing": 10,
"language": "ruby",
"deadline": `+referenceTimeStr+`,
"starter_code_repository": {
"id": 1296269,
"full_name": "octocat/Hello-World",
"html_url": "https://example.com/octocat/Hello-World",
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
"private": false,
"default_branch": "main"
},
"classroom": {
"id": 1296269,
"name": "Programming Elixir",
"archived": false,
"url": "https://example.com/classrooms/programming"
}
}`)
})
ctx := t.Context()
assignment, _, err := client.Classroom.GetAssignment(ctx, 12)
if err != nil {
t.Errorf("Classroom.GetAssignment returned error: %v", err)
}
want := &ClassroomAssignment{
ID: new(int64(12)),
PublicRepo: new(false),
Title: new("Intro to Binaries"),
Type: new("individual"),
InviteLink: new("https://example.com/a/Lx7jiUgx"),
InvitationsEnabled: new(true),
Slug: new("intro-to-binaries"),
StudentsAreRepoAdmins: new(false),
FeedbackPullRequestsEnabled: new(true),
MaxTeams: new(0),
MaxMembers: new(0),
Editor: new("codespaces"),
Accepted: new(100),
Submitted: new(40),
Passing: new(10),
Language: new("ruby"),
Deadline: &referenceTimestamp,
StarterCodeRepository: &Repository{
ID: new(int64(1296269)),
FullName: new("octocat/Hello-World"),
HTMLURL: new("https://example.com/octocat/Hello-World"),
NodeID: new("MDEwOlJlcG9zaXRvcnkxMjk2MjY5"),
Private: new(false),
DefaultBranch: new("main"),
},
Classroom: &Classroom{
ID: new(int64(1296269)),
Name: new("Programming Elixir"),
Archived: new(false),
URL: new("https://example.com/classrooms/programming"),
},
}
if !cmp.Equal(assignment, want) {
t.Errorf("Classroom.GetAssignment returned %+v, want %+v", assignment, want)
}
const methodName = "GetAssignment"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.Classroom.GetAssignment(ctx, -1)
return err
})
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Classroom.GetAssignment(ctx, 12)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}
func TestClassroomService_GetClassroom(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)
mux.HandleFunc("/classrooms/1296269", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{
"id": 1296269,
"name": "Programming Elixir",
"archived": false,
"organization": {
"id": 1,
"login": "programming-elixir",
"node_id": "MDEyOk9yZ2FuaXphdGlvbjE=",
"html_url": "https://example.com/programming-elixir",
"name": "Learn how to build fault tolerant applications",
"avatar_url": "https://example.com/avatars/u/9919?v=4"
},
"url": "https://example.com/classrooms/programming"
}`)
})
ctx := t.Context()
classroom, _, err := client.Classroom.GetClassroom(ctx, 1296269)
if err != nil {
t.Errorf("Classroom.GetClassroom returned error: %v", err)
}
want := &Classroom{
ID: new(int64(1296269)),
Name: new("Programming Elixir"),
Archived: new(false),
Organization: &Organization{
ID: new(int64(1)),
Login: new("programming-elixir"),
NodeID: new("MDEyOk9yZ2FuaXphdGlvbjE="),
HTMLURL: new("https://example.com/programming-elixir"),
Name: new("Learn how to build fault tolerant applications"),
AvatarURL: new("https://example.com/avatars/u/9919?v=4"),
},
URL: new("https://example.com/classrooms/programming"),
}
if !cmp.Equal(classroom, want) {
t.Errorf("Classroom.GetClassroom returned %+v, want %+v", classroom, want)
}
const methodName = "GetClassroom"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.Classroom.GetClassroom(ctx, -1)
return err
})
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Classroom.GetClassroom(ctx, 1296269)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}
func TestClassroomService_ListClassrooms(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)
mux.HandleFunc("/classrooms", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{"page": "2", "per_page": "2"})
fmt.Fprint(w, `[
{
"id": 1296269,
"name": "Programming Elixir",
"archived": false,
"url": "https://example.com/classrooms/programming"
},
{
"id": 1296270,
"name": "Advanced Programming",
"archived": true,
"url": "https://example.com/classrooms/2-advanced-programming"
}
]`)
})
opt := &ListOptions{Page: 2, PerPage: 2}
ctx := t.Context()
classrooms, _, err := client.Classroom.ListClassrooms(ctx, opt)
if err != nil {
t.Errorf("Classroom.ListClassrooms returned error: %v", err)
}
want := []*Classroom{
{
ID: new(int64(1296269)),
Name: new("Programming Elixir"),
Archived: new(false),
URL: new("https://example.com/classrooms/programming"),
},
{
ID: new(int64(1296270)),
Name: new("Advanced Programming"),
Archived: new(true),
URL: new("https://example.com/classrooms/2-advanced-programming"),
},
}
if !cmp.Equal(classrooms, want) {
t.Errorf("Classroom.ListClassrooms returned %+v, want %+v", classrooms, want)
}
const methodName = "ListClassrooms"
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Classroom.ListClassrooms(ctx, opt)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}
func TestClassroomService_ListClassroomAssignments(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)
mux.HandleFunc("/classrooms/1296269/assignments", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{"page": "2", "per_page": "2"})
fmt.Fprint(w, `[
{
"id": 12,
"public_repo": false,
"title": "Intro to Binaries",
"type": "individual",
"invite_link": "https://example.com/a/Lx7jiUgx",
"invitations_enabled": true,
"slug": "intro-to-binaries",
"students_are_repo_admins": false,
"feedback_pull_requests_enabled": true,
"max_teams": 0,
"max_members": 0,
"editor": "codespaces",
"accepted": 100,
"submitted": 40,
"passing": 10,
"language": "ruby",
"deadline": `+referenceTimeStr+`,
"classroom": {
"id": 1296269,
"name": "Programming Elixir",
"archived": false,
"url": "https://example.com/classrooms/programming"
}
},
{
"id": 13,
"public_repo": true,
"title": "Advanced Programming",
"type": "group",
"invite_link": "https://example.com/a/AdvancedProg",
"invitations_enabled": true,
"slug": "advanced-programming",
"students_are_repo_admins": true,
"feedback_pull_requests_enabled": false,
"max_teams": 5,
"max_members": 3,
"editor": "vscode",
"accepted": 50,
"submitted": 25,
"passing": 20,
"language": "python",
"deadline": `+referenceTimeStr+`,
"classroom": {
"id": 1296269,
"name": "Programming Elixir",
"archived": false,
"url": "https://example.com/classrooms/programming"
}
}
]`)
})
opt := &ListOptions{Page: 2, PerPage: 2}
ctx := t.Context()
assignments, _, err := client.Classroom.ListClassroomAssignments(ctx, 1296269, opt)
if err != nil {
t.Errorf("Classroom.ListClassroomAssignments returned error: %v", err)
}
want := []*ClassroomAssignment{
{
ID: new(int64(12)),
PublicRepo: new(false),
Title: new("Intro to Binaries"),
Type: new("individual"),
InviteLink: new("https://example.com/a/Lx7jiUgx"),
InvitationsEnabled: new(true),
Slug: new("intro-to-binaries"),
StudentsAreRepoAdmins: new(false),
FeedbackPullRequestsEnabled: new(true),
MaxTeams: new(0),
MaxMembers: new(0),
Editor: new("codespaces"),
Accepted: new(100),
Submitted: new(40),
Passing: new(10),
Language: new("ruby"),
Deadline: &referenceTimestamp,
Classroom: &Classroom{
ID: new(int64(1296269)),
Name: new("Programming Elixir"),
Archived: new(false),
URL: new("https://example.com/classrooms/programming"),
},
},
{
ID: new(int64(13)),
PublicRepo: new(true),
Title: new("Advanced Programming"),
Type: new("group"),
InviteLink: new("https://example.com/a/AdvancedProg"),
InvitationsEnabled: new(true),
Slug: new("advanced-programming"),
StudentsAreRepoAdmins: new(true),
FeedbackPullRequestsEnabled: new(false),
MaxTeams: new(5),
MaxMembers: new(3),
Editor: new("vscode"),
Accepted: new(50),
Submitted: new(25),
Passing: new(20),
Language: new("python"),
Deadline: &referenceTimestamp,
Classroom: &Classroom{
ID: new(int64(1296269)),
Name: new("Programming Elixir"),
Archived: new(false),
URL: new("https://example.com/classrooms/programming"),
},
},
}
if !cmp.Equal(assignments, want) {
t.Errorf("Classroom.ListClassroomAssignments returned %+v, want %+v", assignments, want)
}
const methodName = "ListClassroomAssignments"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.Classroom.ListClassroomAssignments(ctx, -1, opt)
return err
})
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Classroom.ListClassroomAssignments(ctx, 1296269, opt)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}
func TestClassroomService_ListAcceptedAssignments(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)
mux.HandleFunc("/assignments/12/accepted_assignments", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{"page": "2", "per_page": "2"})
fmt.Fprint(w, `[
{
"id": 42,
"submitted": true,
"passing": true,
"commit_count": 5,
"grade": "10/10",
"students": [
{
"id": 1,
"login": "octocat",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"html_url": "https://github.com/octocat"
}
],
"repository": {
"id": 1296269,
"full_name": "octocat/Hello-World",
"html_url": "https://github.com/octocat/Hello-World",
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
"private": false,
"default_branch": "main"
},
"assignment": {
"id": 12,
"public_repo": false,
"title": "Intro to Binaries",
"type": "individual",
"invite_link": "https://example.com/a/Lx7jiUgx",
"invitations_enabled": true,
"slug": "intro-to-binaries",
"students_are_repo_admins": false,
"feedback_pull_requests_enabled": true,
"max_teams": 0,
"max_members": 0,
"editor": "codespaces",
"accepted": 100,
"submitted": 40,
"passing": 10,
"language": "ruby",
"deadline": `+referenceTimeStr+`,
"classroom": {
"id": 1296269,
"name": "Programming Elixir",
"archived": false,
"url": "https://example.com/classrooms/programming"
}
}
},
{
"id": 43,
"submitted": false,
"passing": false,
"commit_count": 2,
"grade": "5/10",
"students": [
{
"id": 2,
"login": "monalisa",
"avatar_url": "https://github.com/images/error/monalisa_happy.gif",
"html_url": "https://github.com/monalisa"
}
],
"repository": {
"id": 1296270,
"full_name": "monalisa/Hello-World",
"html_url": "https://github.com/monalisa/Hello-World",
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2Mjcw",
"private": true,
"default_branch": "main"
},
"assignment": {
"id": 12,
"public_repo": false,
"title": "Intro to Binaries",
"type": "individual",
"invite_link": "https://example.com/a/Lx7jiUgx",
"invitations_enabled": true,
"slug": "intro-to-binaries",
"students_are_repo_admins": false,
"feedback_pull_requests_enabled": true,
"max_teams": 0,
"max_members": 0,
"editor": "codespaces",
"accepted": 100,
"submitted": 40,
"passing": 10,
"language": "ruby",
"deadline": `+referenceTimeStr+`,
"classroom": {
"id": 1296269,
"name": "Programming Elixir",
"archived": false,
"url": "https://example.com/classrooms/programming"
}
}
}
]`)
})
ctx := t.Context()
opt := &ListOptions{Page: 2, PerPage: 2}
acceptedAssignments, _, err := client.Classroom.ListAcceptedAssignments(ctx, 12, opt)
if err != nil {
t.Errorf("Classroom.ListAcceptedAssignments returned error: %v", err)
}
want := []*AcceptedAssignment{
{
ID: new(int64(42)),
Submitted: new(true),
Passing: new(true),
CommitCount: new(5),
Grade: new("10/10"),
Students: []*ClassroomUser{
{
ID: new(int64(1)),
Login: new("octocat"),
AvatarURL: new("https://github.com/images/error/octocat_happy.gif"),
HTMLURL: new("https://github.com/octocat"),
},
},
Repository: &Repository{
ID: new(int64(1296269)),
FullName: new("octocat/Hello-World"),
HTMLURL: new("https://github.com/octocat/Hello-World"),
NodeID: new("MDEwOlJlcG9zaXRvcnkxMjk2MjY5"),
Private: new(false),
DefaultBranch: new("main"),
},
Assignment: &ClassroomAssignment{
ID: new(int64(12)),
PublicRepo: new(false),
Title: new("Intro to Binaries"),
Type: new("individual"),
InviteLink: new("https://example.com/a/Lx7jiUgx"),
InvitationsEnabled: new(true),
Slug: new("intro-to-binaries"),
StudentsAreRepoAdmins: new(false),
FeedbackPullRequestsEnabled: new(true),
MaxTeams: new(0),
MaxMembers: new(0),
Editor: new("codespaces"),
Accepted: new(100),
Submitted: new(40),
Passing: new(10),
Language: new("ruby"),
Deadline: &referenceTimestamp,
Classroom: &Classroom{
ID: new(int64(1296269)),
Name: new("Programming Elixir"),
Archived: new(false),
URL: new("https://example.com/classrooms/programming"),
},
},
},
{
ID: new(int64(43)),
Submitted: new(false),
Passing: new(false),
CommitCount: new(2),
Grade: new("5/10"),
Students: []*ClassroomUser{
{
ID: new(int64(2)),
Login: new("monalisa"),
AvatarURL: new("https://github.com/images/error/monalisa_happy.gif"),
HTMLURL: new("https://github.com/monalisa"),
},
},
Repository: &Repository{
ID: new(int64(1296270)),
FullName: new("monalisa/Hello-World"),
HTMLURL: new("https://github.com/monalisa/Hello-World"),
NodeID: new("MDEwOlJlcG9zaXRvcnkxMjk2Mjcw"),
Private: new(true),
DefaultBranch: new("main"),
},
Assignment: &ClassroomAssignment{
ID: new(int64(12)),
PublicRepo: new(false),
Title: new("Intro to Binaries"),
Type: new("individual"),
InviteLink: new("https://example.com/a/Lx7jiUgx"),
InvitationsEnabled: new(true),
Slug: new("intro-to-binaries"),
StudentsAreRepoAdmins: new(false),
FeedbackPullRequestsEnabled: new(true),
MaxTeams: new(0),
MaxMembers: new(0),
Editor: new("codespaces"),
Accepted: new(100),
Submitted: new(40),
Passing: new(10),
Language: new("ruby"),
Deadline: &referenceTimestamp,
Classroom: &Classroom{
ID: new(int64(1296269)),
Name: new("Programming Elixir"),
Archived: new(false),
URL: new("https://example.com/classrooms/programming"),
},
},
},
}
if !cmp.Equal(acceptedAssignments, want) {
t.Errorf("Classroom.ListAcceptedAssignments returned %+v, want %+v", acceptedAssignments, want)
}
const methodName = "ListAcceptedAssignments"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.Classroom.ListAcceptedAssignments(ctx, -1, opt)
return err
})
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Classroom.ListAcceptedAssignments(ctx, 12, opt)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}
func TestClassroomService_GetAssignmentGrades(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)
mux.HandleFunc("/assignments/12/grades", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `[
{
"assignment_name": "Intro to Binaries",
"assignment_url": "https://classroom.github.com/assignments/12",
"starter_code_url": "https://github.com/octocat/Hello-World",
"github_username": "octocat",
"roster_identifier": "student123",
"student_repository_name": "octocat/intro-to-binaries",
"student_repository_url": "https://github.com/octocat/intro-to-binaries",
"submission_timestamp": `+referenceTimeStr+`,
"points_awarded": 10,
"points_available": 10,
"group_name": "Team Alpha"
},
{
"assignment_name": "Intro to Binaries",
"assignment_url": "https://classroom.github.com/assignments/12",
"starter_code_url": "https://github.com/octocat/Hello-World",
"github_username": "monalisa",
"roster_identifier": "student456",
"student_repository_name": "monalisa/intro-to-binaries",
"student_repository_url": "https://github.com/monalisa/intro-to-binaries",
"submission_timestamp": `+referenceTimeStr+`,
"points_awarded": 8,
"points_available": 10,
"group_name": "Team Beta"
}
]`)
})
ctx := t.Context()
grades, _, err := client.Classroom.GetAssignmentGrades(ctx, 12)
if err != nil {
t.Errorf("Classroom.GetAssignmentGrades returned error: %v", err)
}
want := []*AssignmentGrade{
{
AssignmentName: new("Intro to Binaries"),
AssignmentURL: new("https://classroom.github.com/assignments/12"),
StarterCodeURL: new("https://github.com/octocat/Hello-World"),
GithubUsername: new("octocat"),
RosterIdentifier: new("student123"),
StudentRepositoryName: new("octocat/intro-to-binaries"),
StudentRepositoryURL: new("https://github.com/octocat/intro-to-binaries"),
SubmissionTimestamp: &referenceTimestamp,
PointsAwarded: new(10),
PointsAvailable: new(10),
GroupName: new("Team Alpha"),
},
{
AssignmentName: new("Intro to Binaries"),
AssignmentURL: new("https://classroom.github.com/assignments/12"),
StarterCodeURL: new("https://github.com/octocat/Hello-World"),
GithubUsername: new("monalisa"),
RosterIdentifier: new("student456"),
StudentRepositoryName: new("monalisa/intro-to-binaries"),
StudentRepositoryURL: new("https://github.com/monalisa/intro-to-binaries"),
SubmissionTimestamp: &referenceTimestamp,
PointsAwarded: new(8),
PointsAvailable: new(10),
GroupName: new("Team Beta"),
},
}
if !cmp.Equal(grades, want) {
t.Errorf("Classroom.GetAssignmentGrades returned %+v, want %+v", grades, want)
}
const methodName = "GetAssignmentGrades"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.Classroom.GetAssignmentGrades(ctx, -1)
return err
})
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Classroom.GetAssignmentGrades(ctx, 12)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}