Skip to content

Commit 8d2b468

Browse files
authored
chore: Improving coverage (#16)
* Improving coverage * More coverage * reformat * coverage on exception * More coverage on branches * More coverage * More coverage * Don't use assert
1 parent ca125eb commit 8d2b468

File tree

8 files changed

+1020
-6
lines changed

8 files changed

+1020
-6
lines changed

src/smartschool/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from .agenda import SmartschoolHours, SmartschoolLessons, SmartschoolMomentInfos
22
from .courses import CourseCondensed, Courses, DocumentOrFolderItem, FileItem, FolderItem, TopNavCourses
33
from .credentials import EnvCredentials, PathCredentials
4-
from .exceptions import SmartSchoolAuthenticationError, SmartSchoolDownloadError, SmartSchoolException
4+
from .exceptions import SmartSchoolAuthenticationError, SmartSchoolDownloadError, SmartSchoolException, SmartSchoolParsingError
55
from .future_tasks import FutureTasks
66
from .messages import (
77
AdjustMessageLabel,
@@ -47,6 +47,7 @@
4747
"SmartSchoolAuthenticationError",
4848
"SmartSchoolDownloadError",
4949
"SmartSchoolException",
50+
"SmartSchoolParsingError",
5051
"Smartschool",
5152
"SmartschoolHours",
5253
"SmartschoolLessons",

src/smartschool/common.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,10 @@ def bs4_html(html: str | bytes | Response) -> BeautifulSoup:
150150
def get_all_values_from_form(html: BeautifulSoup, form_selector: str):
151151
"""Extract form input values from HTML."""
152152
form = html.select(form_selector)
153-
assert len(form) == 1, f"We should have only 1 form. We got {len(form)}!"
153+
154+
if len(form) != 1:
155+
raise AssertionError(f"We should have only 1 form. We got {len(form)}!")
156+
154157
form = form[0]
155158

156159
all_inputs = form.find_all(["input", "button", "textarea", "select"])
@@ -218,7 +221,9 @@ def fill_form(response: Response, form_selector, values: dict[str, str]) -> dict
218221
else:
219222
data[name] = input_["value"]
220223

221-
assert len(values) == 0, f"You didn't use: {sorted(values)}"
224+
if len(values) != 0:
225+
raise AssertionError(f"You didn't use: {sorted(values)}")
226+
222227
return data
223228

224229

tests/courses_e2e_tests.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44

55
from smartschool import Smartschool, TopNavCourses
6-
from smartschool.courses import CourseCondensed, FolderItem
6+
from smartschool.courses import CourseCondensed, FolderItem, InternetShortcut
77

88

99
@pytest.fixture
@@ -55,8 +55,9 @@ def test_full_workflow(courses: list[CourseCondensed], tmp_path):
5555
assert pptx_file.filename == "Persoonlijke kunstinteresse.pptx"
5656

5757

58-
def test_shortcut_via_window_open_click(courses: list[CourseCondensed], tmp_path):
58+
def test_shortcut_via_inline_link(courses: list[CourseCondensed], tmp_path):
5959
shortcut = courses[4].items[1].items[8] # chemie / oefeningen en verbetersleutels / shortcut
60+
6061
assert shortcut.name == "extra oefeningen elektrolyten en ionisatie+dissociatie"
6162
assert shortcut.filename == "extra oefeningen elektrolyten en ionisatie_dissociatie.url"
6263
assert shortcut.mime_type == "html"
@@ -78,3 +79,17 @@ def test_shortcut_via_iframe_src(courses: list[CourseCondensed], tmp_path):
7879
assert shortcut.size_kb == pytest.approx(1485.0)
7980
assert shortcut.last_modified == datetime(2020, 6, 19, 11, 20).astimezone()
8081
assert shortcut.link == "https://www.youtube.com/embed/Zm-g5PpzsEE"
82+
83+
84+
def test_shortcut_via_onclick(courses: list[CourseCondensed], tmp_path):
85+
shortcut = courses[-1].items[0].items[-1] # Wiskunde / Binnemans / shortcut
86+
87+
assert isinstance(shortcut, InternetShortcut)
88+
assert shortcut.name == "Puntensysteem portfolio"
89+
assert shortcut.parent.name == "4AEC, 4CNW - J. Binnemans"
90+
assert shortcut.filename == "Puntensysteem portfolio.url"
91+
assert shortcut.id == 464462
92+
assert shortcut.mime_type == "html"
93+
assert shortcut.size_kb == pytest.approx(415.0)
94+
assert shortcut.last_modified == datetime(2024, 10, 9, 20, 43).astimezone()
95+
assert shortcut.link == "/Documents/Download/Index/htm/1/courseID/1975/docID/464462/ssID/49"

tests/courses_folder_item_tests.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import pytest
2+
from requests import RequestException
3+
4+
from smartschool import CourseCondensed, FolderItem, Smartschool, SmartSchoolException, SmartSchoolParsingError
5+
6+
7+
@pytest.fixture
8+
def folder(session: Smartschool) -> FolderItem:
9+
return FolderItem(
10+
session=session,
11+
parent=None,
12+
course=CourseCondensed(
13+
session=session,
14+
name="Course",
15+
teacher="Teacher",
16+
url="url",
17+
),
18+
name="Name",
19+
)
20+
21+
22+
def test_get_folder_html_exception_handling(folder, mocker):
23+
"""Test exception is wrapped in SmartSchoolException."""
24+
mocker.patch.object(folder.session, "get", side_effect=RequestException("Network error"))
25+
26+
with pytest.raises(SmartSchoolException, match="Failed to fetch folder HTML: Network error"):
27+
folder._get_folder_html()
28+
29+
30+
def test_get_mime_from_row_image_return_none(folder, mocker):
31+
"""Test return None when no background-image found."""
32+
mock_row = mocker.Mock()
33+
mock_div = mocker.Mock()
34+
mock_div.get.return_value = "color: red; font-size: 12px"
35+
mock_row.select_one.return_value = mock_div
36+
37+
result = folder._get_mime_from_row_image(mock_row)
38+
39+
assert result is None
40+
41+
42+
def test_get_mime_from_row_image_continue_branch(folder, mocker):
43+
"""Test continue branch when entry is empty."""
44+
mock_row = mocker.Mock()
45+
mock_div = mocker.Mock()
46+
mock_div.get.return_value = " ; ; background-image: url(/mime_type_pdf/icon.png)"
47+
mock_row.select_one.return_value = mock_div
48+
49+
result = folder._get_mime_from_row_image(mock_row)
50+
51+
assert result == "pdf"
52+
53+
54+
def test_parse_folder_row_exception(folder, mocker):
55+
"""Test exception when no smsc_cm_link found."""
56+
mock_row = mocker.Mock()
57+
mock_link = mocker.Mock()
58+
mock_link.get.return_value = ["other_class", "different_class"] # no smsc_cm_link
59+
mock_row.select.return_value = [mock_link]
60+
61+
with pytest.raises(SmartSchoolParsingError, match="No browse URL found"):
62+
folder._parse_folder_row(mock_row)

tests/planner_tests.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import pytest
12
import time_machine
23

34
from smartschool import Smartschool
4-
from smartschool.planner import PlannedElements
5+
from smartschool.planner import ApplicableAssignmentTypes, PlannedElements
56

67

78
@time_machine.travel("2025-05-06")
@@ -13,3 +14,17 @@ def test_periods_happy_flow(session: Smartschool):
1314
assert sut[0].courses[0].name == "Godsdienst"
1415
assert sut[0].plannedElementType == "planned-placeholders"
1516
assert not sut[0].unconfirmed
17+
18+
19+
def test_applicable_assignment_types(session: Smartschool):
20+
sut = list(ApplicableAssignmentTypes(session))
21+
22+
assert len(sut) == 7
23+
24+
obj = sut[0]
25+
assert obj.abbreviation == "-"
26+
assert obj.id == "12657aa0-3b29-4977-925b-e2a0f133f2ba"
27+
assert obj.isVisible is True
28+
assert obj.name == "-"
29+
assert obj.platformId == 49
30+
assert obj.weight == pytest.approx(1.0)

0 commit comments

Comments
 (0)