|
8 | 8 | import pytest |
9 | 9 |
|
10 | 10 | from voluptuous import ( |
11 | | - ALLOW_EXTRA, PREVENT_EXTRA, REMOVE_EXTRA, All, AllInvalid, Any, Clamp, Coerce, Contains, |
12 | | - ContainsInvalid, Date, Datetime, Email, EmailInvalid, Equal, ExactSequence, |
13 | | - Exclusive, Extra, FqdnUrl, In, Inclusive, InInvalid, Invalid, IsDir, IsFile, Length, |
14 | | - Literal, LiteralInvalid, Marker, Match, MatchInvalid, Maybe, MultipleInvalid, NotIn, |
15 | | - NotInInvalid, Number, Object, Optional, PathExists, Range, Remove, Replace, |
16 | | - Required, Schema, Self, SomeOf, TooManyValid, TypeInvalid, Union, Unordered, Url, |
17 | | - UrlInvalid, raises, validate, |
| 11 | + ALLOW_EXTRA, PREVENT_EXTRA, REMOVE_EXTRA, All, AllInvalid, Any, Clamp, Coerce, |
| 12 | + Contains, ContainsInvalid, Date, Datetime, Email, EmailInvalid, Equal, |
| 13 | + ExactSequence, Exclusive, Extra, FqdnUrl, In, Inclusive, InInvalid, Invalid, IsDir, |
| 14 | + IsFile, Length, Literal, LiteralInvalid, Marker, Match, MatchInvalid, Maybe, |
| 15 | + MultipleInvalid, NotIn, NotInInvalid, Number, Object, Optional, PathExists, Range, |
| 16 | + Remove, Replace, Required, Schema, Self, SomeOf, TooManyValid, TypeInvalid, Union, |
| 17 | + Unordered, Url, UrlInvalid, raises, validate, |
18 | 18 | ) |
19 | 19 | from voluptuous.humanize import humanize_error |
20 | 20 | from voluptuous.util import Capitalize, Lower, Strip, Title, Upper |
@@ -1846,3 +1846,147 @@ def test_exception(): |
1846 | 1846 | assert str(ctx.value.errors) == f"[{invalid_scalar_excp_repr}]" |
1847 | 1847 | ctx.value.add("Test Error") |
1848 | 1848 | assert str(ctx.value.errors) == f"[{invalid_scalar_excp_repr}, 'Test Error']" |
| 1849 | + |
| 1850 | + |
| 1851 | +# Additional tests for humanize.py module to improve coverage |
| 1852 | +def test_humanize_error_with_nested_getitem_keyerror(): |
| 1853 | + """Test _nested_getitem with KeyError (line 19-22).""" |
| 1854 | + from voluptuous.humanize import _nested_getitem |
| 1855 | + |
| 1856 | + # Test KeyError handling |
| 1857 | + data = {'a': {'b': 1}} |
| 1858 | + path = ['a', 'c'] # 'c' doesn't exist in {'b': 1} |
| 1859 | + result = _nested_getitem(data, path) |
| 1860 | + assert result is None |
| 1861 | + |
| 1862 | + |
| 1863 | +def test_humanize_error_with_nested_getitem_indexerror(): |
| 1864 | + """Test _nested_getitem with IndexError (line 19-22).""" |
| 1865 | + from voluptuous.humanize import _nested_getitem |
| 1866 | + |
| 1867 | + # Test IndexError handling |
| 1868 | + data = {'a': [1, 2, 3]} |
| 1869 | + path = ['a', 5] # Index 5 doesn't exist in [1, 2, 3] |
| 1870 | + result = _nested_getitem(data, path) |
| 1871 | + assert result is None |
| 1872 | + |
| 1873 | + |
| 1874 | +def test_humanize_error_with_nested_getitem_typeerror(): |
| 1875 | + """Test _nested_getitem with TypeError (line 19-22).""" |
| 1876 | + from voluptuous.humanize import _nested_getitem |
| 1877 | + |
| 1878 | + # Test TypeError handling - data is not subscriptable |
| 1879 | + data = 42 # int is not subscriptable |
| 1880 | + path = ['a'] |
| 1881 | + result = _nested_getitem(data, path) |
| 1882 | + assert result is None |
| 1883 | + |
| 1884 | + |
| 1885 | +def test_humanize_error_with_long_error_message(): |
| 1886 | + """Test humanize_error with long error message that gets truncated (line 45).""" |
| 1887 | + from voluptuous.humanize import MAX_VALIDATION_ERROR_ITEM_LENGTH, humanize_error |
| 1888 | + |
| 1889 | + # Create a very long string that will be truncated |
| 1890 | + long_string = "x" * (MAX_VALIDATION_ERROR_ITEM_LENGTH + 10) |
| 1891 | + data = {'a': long_string} |
| 1892 | + schema = Schema({'a': int}) |
| 1893 | + |
| 1894 | + with pytest.raises(MultipleInvalid) as ctx: |
| 1895 | + schema(data) |
| 1896 | + |
| 1897 | + error_message = humanize_error(data, ctx.value, max_sub_error_length=50) |
| 1898 | + assert "..." in error_message |
| 1899 | + assert len(error_message.split("Got ")[1]) <= 53 # 50 + 3 for "..." |
| 1900 | + |
| 1901 | + |
| 1902 | +def test_validate_with_humanized_errors_success(): |
| 1903 | + """Test validate_with_humanized_errors with successful validation (line 54-57).""" |
| 1904 | + from voluptuous.humanize import validate_with_humanized_errors |
| 1905 | + |
| 1906 | + schema = Schema({'a': int, 'b': str}) |
| 1907 | + data = {'a': 42, 'b': 'hello'} |
| 1908 | + |
| 1909 | + result = validate_with_humanized_errors(data, schema) |
| 1910 | + assert result == data |
| 1911 | + |
| 1912 | + |
| 1913 | +def test_validate_with_humanized_errors_failure(): |
| 1914 | + """Test validate_with_humanized_errors with validation failure (line 54-57).""" |
| 1915 | + from voluptuous.humanize import Error, validate_with_humanized_errors |
| 1916 | + |
| 1917 | + schema = Schema({'a': int, 'b': str}) |
| 1918 | + data = {'a': 'not an int', 'b': 123} |
| 1919 | + |
| 1920 | + with pytest.raises(Error) as ctx: |
| 1921 | + validate_with_humanized_errors(data, schema) |
| 1922 | + |
| 1923 | + error_message = str(ctx.value) |
| 1924 | + assert "expected int for dictionary value @ data['a']" in error_message |
| 1925 | + assert "expected str for dictionary value @ data['b']" in error_message |
| 1926 | + assert "Got 'not an int'" in error_message |
| 1927 | + assert "Got 123" in error_message |
| 1928 | + |
| 1929 | + |
| 1930 | +def test_validate_with_humanized_errors_custom_max_length(): |
| 1931 | + """Test validate_with_humanized_errors with custom max_sub_error_length.""" |
| 1932 | + from voluptuous.humanize import Error, validate_with_humanized_errors |
| 1933 | + |
| 1934 | + schema = Schema({'a': int}) |
| 1935 | + data = {'a': 'not an int'} |
| 1936 | + |
| 1937 | + with pytest.raises(Error) as ctx: |
| 1938 | + validate_with_humanized_errors(data, schema, max_sub_error_length=10) |
| 1939 | + |
| 1940 | + error_message = str(ctx.value) |
| 1941 | + assert "..." in error_message # Should be truncated |
| 1942 | + |
| 1943 | + |
| 1944 | +def test_humanize_error_with_multiple_invalid(): |
| 1945 | + """Test humanize_error with MultipleInvalid containing multiple errors.""" |
| 1946 | + from voluptuous.humanize import humanize_error |
| 1947 | + |
| 1948 | + schema = Schema({'a': int, 'b': str, 'c': [int]}) |
| 1949 | + data = {'a': 'not an int', 'b': 123, 'c': ['not an int']} |
| 1950 | + |
| 1951 | + with pytest.raises(MultipleInvalid) as ctx: |
| 1952 | + schema(data) |
| 1953 | + |
| 1954 | + error_message = humanize_error(data, ctx.value) |
| 1955 | + # Should contain all three error messages |
| 1956 | + assert "expected int for dictionary value @ data['a']" in error_message |
| 1957 | + assert "expected str for dictionary value @ data['b']" in error_message |
| 1958 | + assert "expected int @ data['c'][0]" in error_message |
| 1959 | + |
| 1960 | + |
| 1961 | +def test_humanize_error_with_single_invalid(): |
| 1962 | + """Test humanize_error with single Invalid error.""" |
| 1963 | + from voluptuous.humanize import humanize_error |
| 1964 | + |
| 1965 | + schema = Schema({'a': int}) |
| 1966 | + data = {'a': 'not an int'} |
| 1967 | + |
| 1968 | + with pytest.raises(MultipleInvalid) as ctx: |
| 1969 | + schema(data) |
| 1970 | + |
| 1971 | + error_message = humanize_error(data, ctx.value) |
| 1972 | + assert "expected int for dictionary value @ data['a']" in error_message |
| 1973 | + assert "Got 'not an int'" in error_message |
| 1974 | + |
| 1975 | + |
| 1976 | +def test_humanize_error_with_none_data(): |
| 1977 | + """Test humanize_error with None data.""" |
| 1978 | + from voluptuous.humanize import _nested_getitem, humanize_error |
| 1979 | + |
| 1980 | + # Test _nested_getitem with None data |
| 1981 | + result = _nested_getitem(None, ['a']) |
| 1982 | + assert result is None |
| 1983 | + |
| 1984 | + # Test humanize_error with None data |
| 1985 | + schema = Schema({'a': int}) |
| 1986 | + data = None |
| 1987 | + |
| 1988 | + with pytest.raises(MultipleInvalid) as ctx: |
| 1989 | + schema(data) |
| 1990 | + |
| 1991 | + error_message = humanize_error(data, ctx.value) |
| 1992 | + assert "expected a dictionary" in error_message |
0 commit comments