File size: 3,728 Bytes
68f6dba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
"""Tests for HTML utility functions."""

from unittest.mock import patch

from src.utils.html import escape_html


class TestEscapeHtml:
    """Tests for escape_html function."""

    def test_escapes_angle_brackets(self) -> None:
        """Verify < and > are escaped."""
        assert "&lt;" in escape_html("<div>")
        assert "&gt;" in escape_html("<div>")

    def test_escapes_ampersand(self) -> None:
        """Verify & is escaped."""
        assert "&amp;" in escape_html("a & b")

    def test_escapes_double_quotes(self) -> None:
        """Verify double quotes are escaped."""
        assert "&quot;" in escape_html('say "hello"')

    def test_escapes_single_quotes(self) -> None:
        """Verify single quotes are escaped."""
        assert "&#x27;" in escape_html("it's")

    def test_safe_strings_unchanged(self) -> None:
        """Verify safe strings pass through unmodified."""
        assert escape_html("Hello World") == "Hello World"
        assert escape_html("abc123") == "abc123"
        assert escape_html("") == ""


class TestSafeHeading:
    """Tests for safe_heading function."""

    def test_escapes_xss_payload(self) -> None:
        """Verify XSS payloads are escaped in heading output."""
        with patch("src.utils.html.st") as mock_st:
            from src.utils.html import safe_heading

            safe_heading("<script>alert(1)</script>")

            call_args = mock_st.markdown.call_args
            rendered_html = call_args[0][0]
            assert "<script>" not in rendered_html
            assert "&lt;script&gt;" in rendered_html

    def test_renders_correct_heading_level(self) -> None:
        """Verify heading level is used in output."""
        with patch("src.utils.html.st") as mock_st:
            from src.utils.html import safe_heading

            safe_heading("Title", level=3)

            rendered_html = mock_st.markdown.call_args[0][0]
            assert "<h3" in rendered_html
            assert "</h3>" in rendered_html

    def test_uses_unsafe_allow_html(self) -> None:
        """Verify markdown is called with unsafe_allow_html=True."""
        with patch("src.utils.html.st") as mock_st:
            from src.utils.html import safe_heading

            safe_heading("Title")

            mock_st.markdown.assert_called_once()
            assert mock_st.markdown.call_args[1]["unsafe_allow_html"] is True


class TestSafeParagraph:
    """Tests for safe_paragraph function."""

    def test_escapes_xss_payload(self) -> None:
        """Verify XSS payloads are escaped in paragraph output."""
        with patch("src.utils.html.st") as mock_st:
            from src.utils.html import safe_paragraph

            safe_paragraph("<img onerror=alert(1) src=x>")

            rendered_html = mock_st.markdown.call_args[0][0]
            assert "<img" not in rendered_html
            assert "&lt;img" in rendered_html

    def test_renders_paragraph_tag(self) -> None:
        """Verify paragraph tag is used in output."""
        with patch("src.utils.html.st") as mock_st:
            from src.utils.html import safe_paragraph

            safe_paragraph("Hello")

            rendered_html = mock_st.markdown.call_args[0][0]
            assert "<p " in rendered_html
            assert "</p>" in rendered_html
            assert "Hello" in rendered_html

    def test_uses_unsafe_allow_html(self) -> None:
        """Verify markdown is called with unsafe_allow_html=True."""
        with patch("src.utils.html.st") as mock_st:
            from src.utils.html import safe_paragraph

            safe_paragraph("Text")

            mock_st.markdown.assert_called_once()
            assert mock_st.markdown.call_args[1]["unsafe_allow_html"] is True