0

Support all google classroom course work types.

Previously, only the assignment type course works are needed from school
tools. Now all the course work types need to be supported.

Bug: 396203403
Change-Id: I8594e52a253fc2e94a37ddb99fa85841e013418c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6261749
Reviewed-by: Benjamin Zielinski <bzielinski@google.com>
Commit-Queue: Zifan Zhang <zifanzhang@google.com>
Reviewed-by: Artsiom Mitrokhin <amitrokhin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1420594}
This commit is contained in:
Zifan Zhang
2025-02-14 10:30:50 -08:00
committed by Chromium LUCI CQ
parent 8834879be2
commit 036c0beb7a
9 changed files with 185 additions and 23 deletions

@ -61,6 +61,14 @@ struct Material {
MaterialType type;
};
// The assignment type.
enum AssignmentType {
kUnspecified,
kAssignment,
kShortAnswerQuestion,
kMultipleChoiceQuestion,
};
// Represents a course assignment.
struct Assignment {
string title;
@ -69,6 +77,7 @@ struct Assignment {
mojo_base.mojom.JSTime last_update_time;
// Assignment materials.
array<Material> materials;
AssignmentType type;
};
// Represents a browser window.

@ -191,8 +191,8 @@ void ClassroomPageHandlerImpl::OnListAssignmentsFetched(
}
for (const auto& item : result.value()->items()) {
if (item->type() !=
google_apis::classroom::CourseWorkItem::Type::kAssignment) {
if (item->type() ==
google_apis::classroom::CourseWorkItem::Type::kUnspecified) {
continue;
}
std::vector<mojom::MaterialPtr> materials = {};
@ -200,19 +200,19 @@ void ClassroomPageHandlerImpl::OnListAssignmentsFetched(
mojom::MaterialPtr material = mojom::Material::New();
material->title = apiMaterial->title();
switch (apiMaterial->type()) {
case (google_apis::classroom::Material::Type::kSharedDriveFile):
case google_apis::classroom::Material::Type::kSharedDriveFile:
material->type = mojom::MaterialType::kSharedDriveFile;
break;
case (google_apis::classroom::Material::Type::kYoutubeVideo):
case google_apis::classroom::Material::Type::kYoutubeVideo:
material->type = mojom::MaterialType::kYoutubeVideo;
break;
case (google_apis::classroom::Material::Type::kLink):
case google_apis::classroom::Material::Type::kLink:
material->type = mojom::MaterialType::kLink;
break;
case (google_apis::classroom::Material::Type::kForm):
case google_apis::classroom::Material::Type::kForm:
material->type = mojom::MaterialType::kForm;
break;
case (google_apis::classroom::Material::Type::kUnknown):
case google_apis::classroom::Material::Type::kUnknown:
default:
material->type = mojom::MaterialType::kUnknown;
break;
@ -226,6 +226,21 @@ void ClassroomPageHandlerImpl::OnListAssignmentsFetched(
assignment->url = item->alternate_link();
assignment->materials = std::move(materials);
assignment->last_update_time = std::move(item->last_update());
switch (item->type()) {
case google_apis::classroom::CourseWorkItem::Type::kAssignment:
assignment->type = mojom::AssignmentType::kAssignment;
break;
case google_apis::classroom::CourseWorkItem::Type::kShortAnswerQuestion:
assignment->type = mojom::AssignmentType::kShortAnswerQuestion;
break;
case google_apis::classroom::CourseWorkItem::Type::
kMultipleChoiceQuestion:
assignment->type = mojom::AssignmentType::kMultipleChoiceQuestion;
break;
case google_apis::classroom::CourseWorkItem::Type::kUnspecified:
default:
assignment->type = mojom::AssignmentType::kUnspecified;
}
fetched_assignments->push_back(std::move(assignment));
}

@ -609,11 +609,31 @@ TEST_F(ClassroomPageHandlerImplTest, ListAllAssignments) {
]
},
{
"id": "question-id",
"title": "question-title",
"alternateLink": "http://question-url.com",
"id": "short-answer-question-id",
"title": "short-answer-question-title",
"alternateLink": "http://short-answer-question-url.com",
"workType": "SHORT_ANSWER_QUESTION",
"updateTime": "2025-04-05T04:05:06.700Z"
},
{
"id": "multiple-choice-question-id",
"title": "multiple-choice-question-title",
"alternateLink": "http://multiple-choice-question-url.com",
"workType": "MULTIPLE_CHOICE_QUESTION",
"updateTime": "2025-04-05T04:05:06.700Z"
},
{
"id": "type-unspecified-id",
"title": "type-unspecified-title",
"alternateLink": "http://type-unspecified-url.com",
"workType": "COURSE_WORK_TYPE_UNSPECIFIED",
"updateTime": "2025-04-05T04:05:06.700Z"
},
{
"id": "no-type-id",
"title": "no-type-title",
"alternateLink": "http://no-type-url.com",
"updateTime": "2025-04-05T04:05:06.700Z"
}
]
})"))));
@ -633,10 +653,11 @@ TEST_F(ClassroomPageHandlerImplTest, ListAllAssignments) {
google_apis::test_util::CreateQuitCallback(&run_loop, callback.Get()));
run_loop.Run();
ASSERT_EQ(response.size(), 4u);
ASSERT_EQ(response.size(), 6u);
EXPECT_EQ(response.at(0)->title, "assignment-multiple-materials-title");
EXPECT_EQ(response.at(0)->url,
GURL("http://assignment-multiple-materials-url.com"));
EXPECT_EQ(response.at(0)->type, mojom::AssignmentType::kAssignment);
EXPECT_EQ(
google_apis::util::FormatTimeAsString(response.at(0)->last_update_time),
"2025-01-01T00:00:00.000Z");
@ -651,6 +672,7 @@ TEST_F(ClassroomPageHandlerImplTest, ListAllAssignments) {
EXPECT_EQ(response.at(1)->title, "assignment-link-materials-title");
EXPECT_EQ(response.at(1)->url,
GURL("http://assignment-link-materials-url.com"));
EXPECT_EQ(response.at(1)->type, mojom::AssignmentType::kAssignment);
EXPECT_EQ(
google_apis::util::FormatTimeAsString(response.at(1)->last_update_time),
"2025-01-02T01:02:03.400Z");
@ -662,6 +684,7 @@ TEST_F(ClassroomPageHandlerImplTest, ListAllAssignments) {
EXPECT_EQ(response.at(2)->title, "assignment-form-materials-title");
EXPECT_EQ(response.at(2)->url,
GURL("http://assignment-form-materials-url.com"));
EXPECT_EQ(response.at(2)->type, mojom::AssignmentType::kAssignment);
EXPECT_EQ(
google_apis::util::FormatTimeAsString(response.at(2)->last_update_time),
"2025-02-03T02:03:04.500Z");
@ -670,6 +693,7 @@ TEST_F(ClassroomPageHandlerImplTest, ListAllAssignments) {
EXPECT_EQ(response.at(2)->materials.at(0)->type, mojom::MaterialType::kForm);
EXPECT_EQ(response.at(3)->title, "assignment-unknown-materials-title");
EXPECT_EQ(response.at(3)->type, mojom::AssignmentType::kAssignment);
EXPECT_EQ(response.at(3)->url,
GURL("http://assignment-unknown-materials-url.com"));
EXPECT_EQ(
@ -678,6 +702,22 @@ TEST_F(ClassroomPageHandlerImplTest, ListAllAssignments) {
EXPECT_EQ(response.at(3)->materials.size(), 1u);
EXPECT_EQ(response.at(3)->materials.at(0)->type,
mojom::MaterialType::kUnknown);
EXPECT_EQ(response.at(4)->title, "short-answer-question-title");
EXPECT_EQ(response.at(4)->url, GURL("http://short-answer-question-url.com"));
EXPECT_EQ(response.at(4)->type, mojom::AssignmentType::kShortAnswerQuestion);
EXPECT_EQ(
google_apis::util::FormatTimeAsString(response.at(3)->last_update_time),
"2025-03-04T03:04:05.600Z");
EXPECT_EQ(response.at(5)->title, "multiple-choice-question-title");
EXPECT_EQ(response.at(5)->url,
GURL("http://multiple-choice-question-url.com"));
EXPECT_EQ(response.at(5)->type,
mojom::AssignmentType::kMultipleChoiceQuestion);
EXPECT_EQ(
google_apis::util::FormatTimeAsString(response.at(3)->last_update_time),
"2025-03-04T03:04:05.600Z");
}
TEST_F(ClassroomPageHandlerImplTest, ListAssignmentsOnHttpError) {

@ -52,6 +52,7 @@ export declare interface Assignment {
url: string;
lastUpdateTime: Date;
materials: Material[];
type: AssignmentType;
}
/**
@ -142,6 +143,16 @@ export enum MaterialType {
FORM = 4,
}
/**
* Declare course assignment type enum type
*/
export enum AssignmentType {
UNSPECIFIED = 0,
ASSIGNMENT = 1,
SHORT_ANSWER_QUESTION = 2,
MULTIPLE_CHOICE_QUESTION = 3,
}
/**
* Declare controlled tab
*/

@ -155,6 +155,7 @@ export class ClientDelegateFactory {
materials: assignment.materials.map((material: MaterialMojom) => {
return {title: material.title, type: material.type.valueOf()};
}),
type: assignment.type.valueOf(),
};
});
},

@ -64,6 +64,7 @@ class MockRemoteHandler extends PageHandlerRemote {
{title: 'material-title-1', type: 0},
{title: 'material-title-2', type: 1},
],
type: 0,
},
{
title: 'assignment-title2',
@ -73,6 +74,7 @@ class MockRemoteHandler extends PageHandlerRemote {
{title: 'material-title-3', type: 2},
{title: 'material-title-4', type: 3},
],
type: 1,
},
],
});
@ -375,6 +377,7 @@ suite('ClientDelegateTest', function() {
{title: 'material-title-1', type: 0},
{title: 'material-title-2', type: 1},
],
type: 0,
},
{
title: 'assignment-title2',
@ -384,6 +387,7 @@ suite('ClientDelegateTest', function() {
{title: 'material-title-3', type: 2},
{title: 'material-title-4', type: 3},
],
type: 1,
},
],
result);

@ -47,6 +47,10 @@ constexpr char kApiResponseCourseWorkItemMaterialFormKey[] = "form";
constexpr char kPublishedCourseWorkItemState[] = "PUBLISHED";
constexpr char kAssignmentCourseWorkItemType[] = "ASSIGNMENT";
constexpr char kShortAnswerQuestionCourseWorkItemType[] =
"SHORT_ANSWER_QUESTION";
constexpr char kMultipleChoiceQuestionCourseWorkItemType[] =
"MULTIPLE_CHOICE_QUESTION";
bool ConvertCourseWorkItemState(std::string_view input,
CourseWorkItem::State* output) {
@ -58,9 +62,15 @@ bool ConvertCourseWorkItemState(std::string_view input,
bool ConvertCourseWorkItemType(std::string_view input,
CourseWorkItem::Type* output) {
*output = input == kAssignmentCourseWorkItemType
? CourseWorkItem::Type::kAssignment
: CourseWorkItem::Type::kOther;
if (input == kAssignmentCourseWorkItemType) {
*output = CourseWorkItem::Type::kAssignment;
} else if (input == kShortAnswerQuestionCourseWorkItemType) {
*output = CourseWorkItem::Type::kShortAnswerQuestion;
} else if (input == kMultipleChoiceQuestionCourseWorkItemType) {
*output = CourseWorkItem::Type::kMultipleChoiceQuestion;
} else {
*output = CourseWorkItem::Type::kUnspecified;
}
return true;
}

@ -60,11 +60,11 @@ class CourseWorkItem {
};
// Course work item type.
// There are more types can be returned by the API, but current users only
// need "ASSIGNMENT" course work type.
enum class Type {
kAssignment,
kOther,
kShortAnswerQuestion,
kMultipleChoiceQuestion,
kUnspecified,
};
// Joined due date and due time of the course work item.
@ -124,7 +124,7 @@ class CourseWorkItem {
State state_ = State::kOther;
// Type of this course work item.
Type type_ = Type::kOther;
Type type_ = Type::kUnspecified;
// Absolute link to this course work in the Classroom web UI.
GURL alternate_link_;

@ -46,12 +46,38 @@ TEST(ClassroomApiCourseWorkResponseTypesTest, ConvertsCourseWork) {
},
{
"id": "course-work-item-2",
"title": "Math multiple choice question",
"title": "Math short answer question",
"state": "DRAFT",
"alternateLink": "https://classroom.google.com/c/ghi/a/jkl/details",
"creationTime": "2023-04-03T00:10:55.000Z",
"updateTime": "2023-04-04T00:10:55.000Z",
"workType": "SHORT_ANSWER_QUESTION"
},
{
"id": "course-work-item-3",
"title": "Math multiple choice question",
"state": "DRAFT",
"alternateLink": "https://classroom.google.com/c/ghi/a/jkl/details",
"creationTime": "2023-04-03T00:10:55.000Z",
"updateTime": "2023-04-04T00:10:55.000Z",
"workType": "MULTIPLE_CHOICE_QUESTION"
},
{
"id": "course-work-item-4",
"title": "Math type unspecified",
"state": "DRAFT",
"alternateLink": "https://classroom.google.com/c/ghi/a/jkl/details",
"creationTime": "2023-04-03T00:10:55.000Z",
"updateTime": "2023-04-04T00:10:55.000Z",
"workType": "COURSE_WORK_TYPE_UNSPECIFIED"
},
{
"id": "course-work-item-5",
"title": "Math no work type",
"state": "DRAFT",
"alternateLink": "https://classroom.google.com/c/ghi/a/jkl/details",
"creationTime": "2023-04-03T00:10:55.000Z",
"updateTime": "2023-04-04T00:10:55.000Z"
}
]
})");
@ -59,7 +85,7 @@ TEST(ClassroomApiCourseWorkResponseTypesTest, ConvertsCourseWork) {
const auto course_work = CourseWork::CreateFrom(raw_course_work.value());
ASSERT_TRUE(course_work);
EXPECT_EQ(course_work->items().size(), 2u);
EXPECT_EQ(course_work->items().size(), 5u);
EXPECT_TRUE(course_work->next_page_token().empty());
EXPECT_EQ(course_work->items().at(0)->id(), "course-work-item-1");
@ -79,8 +105,7 @@ TEST(ClassroomApiCourseWorkResponseTypesTest, ConvertsCourseWork) {
CourseWorkItem::Type::kAssignment);
EXPECT_EQ(course_work->items().at(1)->id(), "course-work-item-2");
EXPECT_EQ(course_work->items().at(1)->title(),
"Math multiple choice question");
EXPECT_EQ(course_work->items().at(1)->title(), "Math short answer question");
EXPECT_EQ(course_work->items().at(1)->state(), CourseWorkItem::State::kOther);
EXPECT_EQ(course_work->items().at(1)->alternate_link(),
"https://classroom.google.com/c/ghi/a/jkl/details");
@ -91,7 +116,54 @@ TEST(ClassroomApiCourseWorkResponseTypesTest, ConvertsCourseWork) {
"2023-04-03T00:10:55.000Z");
EXPECT_EQ(util::FormatTimeAsString(course_work->items().at(1)->last_update()),
"2023-04-04T00:10:55.000Z");
EXPECT_EQ(course_work->items().at(1)->type(), CourseWorkItem::Type::kOther);
EXPECT_EQ(course_work->items().at(1)->type(),
CourseWorkItem::Type::kShortAnswerQuestion);
EXPECT_EQ(course_work->items().at(2)->id(), "course-work-item-3");
EXPECT_EQ(course_work->items().at(2)->title(),
"Math multiple choice question");
EXPECT_EQ(course_work->items().at(2)->state(), CourseWorkItem::State::kOther);
EXPECT_EQ(course_work->items().at(2)->alternate_link(),
"https://classroom.google.com/c/ghi/a/jkl/details");
EXPECT_FALSE(course_work->items().at(2)->due_date_time());
EXPECT_FALSE(course_work->items().at(2)->due_date_time());
EXPECT_EQ(
util::FormatTimeAsString(course_work->items().at(2)->creation_time()),
"2023-04-03T00:10:55.000Z");
EXPECT_EQ(util::FormatTimeAsString(course_work->items().at(2)->last_update()),
"2023-04-04T00:10:55.000Z");
EXPECT_EQ(course_work->items().at(2)->type(),
CourseWorkItem::Type::kMultipleChoiceQuestion);
EXPECT_EQ(course_work->items().at(3)->id(), "course-work-item-4");
EXPECT_EQ(course_work->items().at(3)->title(), "Math type unspecified");
EXPECT_EQ(course_work->items().at(3)->state(), CourseWorkItem::State::kOther);
EXPECT_EQ(course_work->items().at(3)->alternate_link(),
"https://classroom.google.com/c/ghi/a/jkl/details");
EXPECT_FALSE(course_work->items().at(3)->due_date_time());
EXPECT_FALSE(course_work->items().at(3)->due_date_time());
EXPECT_EQ(
util::FormatTimeAsString(course_work->items().at(3)->creation_time()),
"2023-04-03T00:10:55.000Z");
EXPECT_EQ(util::FormatTimeAsString(course_work->items().at(3)->last_update()),
"2023-04-04T00:10:55.000Z");
EXPECT_EQ(course_work->items().at(3)->type(),
CourseWorkItem::Type::kUnspecified);
EXPECT_EQ(course_work->items().at(4)->id(), "course-work-item-5");
EXPECT_EQ(course_work->items().at(4)->title(), "Math no work type");
EXPECT_EQ(course_work->items().at(4)->state(), CourseWorkItem::State::kOther);
EXPECT_EQ(course_work->items().at(4)->alternate_link(),
"https://classroom.google.com/c/ghi/a/jkl/details");
EXPECT_FALSE(course_work->items().at(4)->due_date_time());
EXPECT_FALSE(course_work->items().at(4)->due_date_time());
EXPECT_EQ(
util::FormatTimeAsString(course_work->items().at(4)->creation_time()),
"2023-04-03T00:10:55.000Z");
EXPECT_EQ(util::FormatTimeAsString(course_work->items().at(4)->last_update()),
"2023-04-04T00:10:55.000Z");
EXPECT_EQ(course_work->items().at(4)->type(),
CourseWorkItem::Type::kUnspecified);
}
TEST(ClassroomApiCourseWorkResponseTypesTest, ConvertsNextPageToken) {