diff --git a/src/gradescopeapi/classes/_helpers/_course_helpers.py b/src/gradescopeapi/classes/_helpers/_course_helpers.py index 23ab416..182e4df 100644 --- a/src/gradescopeapi/classes/_helpers/_course_helpers.py +++ b/src/gradescopeapi/classes/_helpers/_course_helpers.py @@ -167,8 +167,13 @@ def get_course_members(soup: BeautifulSoup, course_id: str) -> list[Member]: data_url: str = rosterName_button.get("data-url", None) user_id = data_url.split("user_id=")[-1] - # fetch number of submissions from table cell - num_submissions = int(cells[num_submissions_column].text) + # fetch number of submissions from table cell. Some roster layouts have + # extra trailing action columns, so the heuristic column index can land + # on an empty/non-numeric cell; default to 0 rather than raising. + try: + num_submissions = int(cells[num_submissions_column].text) + except (ValueError, IndexError): + num_submissions = 0 # create Member object with all relevant info member_list.append( diff --git a/tests/test_roster_unit.py b/tests/test_roster_unit.py new file mode 100644 index 0000000..692719e --- /dev/null +++ b/tests/test_roster_unit.py @@ -0,0 +1,65 @@ +"""Unit tests for get_course_members — no network/credentials required. + +Builds a roster page from crafted HTML and checks that a roster whose +heuristic "# submissions" column is empty still parses (count defaults to 0), +and that a numeric count is read correctly. +""" +import json + +from bs4 import BeautifulSoup + +from gradescopeapi.classes._helpers._course_helpers import get_course_members + + +def _roster_html(rows): + headers = "".join(f"