Coverage for schemas.py: 82%

44 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-03 04:37 +0000

1""" 

2API Response Schema Validation using Pydantic models. 

3Validates API responses against expected schemas. 

4""" 

5 

6from pydantic import BaseModel, EmailStr, Field, validator 

7 

8# ========== Signup API Schemas ========== 

9 

10 

11class SignupRequestSchema(BaseModel): 

12 """Schema for signup request payload.""" 

13 

14 name: str = Field(..., min_length=3, max_length=80) 

15 email: EmailStr 

16 password: str = Field(..., min_length=8) 

17 confirm_password: str = Field(..., min_length=8) 

18 

19 @validator("name") 

20 def validate_name(cls, v): 

21 """Validate name doesn't contain numbers or special chars.""" 

22 if any(char.isdigit() for char in v): 

23 raise ValueError("Name should not contain numbers") 

24 return v 

25 

26 @validator("confirm_password") 

27 def passwords_match(cls, v, values): 

28 """Validate password and confirm_password match.""" 

29 if "password" in values and v != values["password"]: 

30 raise ValueError("Passwords do not match") 

31 return v 

32 

33 

34class SignupSuccessResponseSchema(BaseModel): 

35 """Schema for successful signup response.""" 

36 

37 message: str 

38 error: bool 

39 code: str 

40 data: dict | None = None 

41 

42 class Config: 

43 extra = "allow" # Allow additional fields 

44 

45 

46class ErrorDetailSchema(BaseModel): 

47 """Schema for error detail object.""" 

48 

49 field: str | None = None 

50 message: str 

51 code: str | None = None 

52 

53 

54class SignupErrorResponseSchema(BaseModel): 

55 """Schema for error response.""" 

56 

57 error: str | None = None 

58 errors: list[ErrorDetailSchema] | None = None 

59 message: str | None = None 

60 detail: str | None = None 

61 status_code: int | None = None 

62 

63 class Config: 

64 extra = "allow" 

65 

66 

67# ========== Validation Helper Functions ========== 

68 

69 

70def validate_response_schema(response_data: dict, schema: type[BaseModel]) -> tuple[bool, str | None]: 

71 """ 

72 Validates response data against a Pydantic schema. 

73 

74 Args: 

75 response_data: Dictionary containing API response 

76 schema: Pydantic model class to validate against 

77 

78 Returns: 

79 Tuple of (is_valid: bool, error_message: str or None) 

80 """ 

81 try: 

82 schema(**response_data) 

83 return True, None 

84 except Exception as e: 

85 return False, str(e) 

86 

87 

88def assert_response_schema( 

89 response_data: dict, schema: type[BaseModel], error_message: str = "Schema validation failed" 

90): 

91 """ 

92 Asserts that response data matches the expected schema. 

93 

94 Args: 

95 response_data: Dictionary containing API response 

96 schema: Pydantic model class to validate against 

97 error_message: Custom error message prefix 

98 

99 Raises: 

100 AssertionError: If validation fails 

101 """ 

102 is_valid, error = validate_response_schema(response_data, schema) 

103 assert is_valid, f"{error_message}: {error}"