File size: 4,588 Bytes
6424951
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
"""Tests for input validation module."""

import pytest

from src.validation.inputs import (
    PlayerSearchInput,
    is_valid_search_term,
    validate_search_term,
)


class TestPlayerSearchInput:
    """Tests for PlayerSearchInput validation."""

    def test_valid_simple_name(self) -> None:
        """Test valid simple name passes validation."""
        result = PlayerSearchInput(search_term="James")
        assert result.search_term == "James"

    def test_valid_full_name(self) -> None:
        """Test valid full name passes validation."""
        result = PlayerSearchInput(search_term="LeBron James")
        assert result.search_term == "LeBron James"

    def test_valid_name_with_apostrophe(self) -> None:
        """Test name with apostrophe passes validation."""
        result = PlayerSearchInput(search_term="Shaquille O'Neal")
        assert result.search_term == "Shaquille O'Neal"

    def test_valid_name_with_period(self) -> None:
        """Test name with period passes validation."""
        result = PlayerSearchInput(search_term="J.R. Smith")
        assert result.search_term == "J.R. Smith"

    def test_valid_name_with_hyphen(self) -> None:
        """Test name with hyphen passes validation."""
        result = PlayerSearchInput(search_term="Kareem Abdul-Jabbar")
        assert result.search_term == "Kareem Abdul-Jabbar"

    def test_strips_whitespace(self) -> None:
        """Test that whitespace is stripped."""
        result = PlayerSearchInput(search_term="  James  ")
        assert result.search_term == "James"


class TestSqlInjectionRejection:
    """Tests for SQL injection pattern rejection."""

    @pytest.mark.parametrize(
        "malicious_input",
        [
            "'; DROP TABLE NBA;--",
            "James'; DELETE FROM NBA--",
            "' OR '1'='1",
            "James' UNION SELECT * FROM passwords--",
            "James; SELECT * FROM users",
            "/*comment*/James",
            "James*/DROP TABLE/*",
            "' OR 1=1--",
            "James' AND 1=1--",
            "Robert'); DROP TABLE Students;--",
        ],
    )
    def test_rejects_sql_injection(self, malicious_input: str) -> None:
        """Test that SQL injection patterns are rejected."""
        with pytest.raises(ValueError) as exc_info:
            PlayerSearchInput(search_term=malicious_input)

        # Should mention invalid characters
        assert "Invalid" in str(exc_info.value) or "invalid" in str(exc_info.value)

    @pytest.mark.parametrize(
        "invalid_input",
        [
            "James<script>",
            "James&nbsp;",
            "James@#$%",
            "James\\nNewline",
            "James\x00null",
        ],
    )
    def test_rejects_special_characters(self, invalid_input: str) -> None:
        """Test that special characters are rejected."""
        with pytest.raises(ValueError):
            PlayerSearchInput(search_term=invalid_input)

    def test_rejects_empty_string(self) -> None:
        """Test that empty string is rejected."""
        with pytest.raises(ValueError):
            PlayerSearchInput(search_term="")

    def test_rejects_too_long(self) -> None:
        """Test that overly long input is rejected."""
        with pytest.raises(ValueError):
            PlayerSearchInput(search_term="A" * 101)


class TestValidateSearchTerm:
    """Tests for validate_search_term helper function."""

    def test_returns_cleaned_term(self) -> None:
        """Test that valid term is returned cleaned."""
        result = validate_search_term("  James  ")
        assert result == "James"

    def test_returns_none_for_invalid(self) -> None:
        """Test that invalid input returns None."""
        result = validate_search_term("'; DROP TABLE--")
        assert result is None

    def test_returns_none_for_empty(self) -> None:
        """Test that empty input returns None."""
        result = validate_search_term("")
        assert result is None


class TestIsValidSearchTerm:
    """Tests for is_valid_search_term helper function."""

    def test_returns_true_for_valid(self) -> None:
        """Test returns True for valid input."""
        assert is_valid_search_term("James") is True
        assert is_valid_search_term("LeBron James") is True
        assert is_valid_search_term("O'Neal") is True

    def test_returns_false_for_invalid(self) -> None:
        """Test returns False for invalid input."""
        assert is_valid_search_term("'; DROP--") is False
        assert is_valid_search_term("") is False
        assert is_valid_search_term("<script>") is False