Skip to content

Conversation

@vaishnaviij
Copy link

@vaishnaviij vaishnaviij commented Jul 29, 2025

  • Updated all timestamp field names in API responses to camelCase
  • Ensures consistency across backend responses

Summary by CodeRabbit

  • Style
    • Standardized field naming conventions across user, group, and expense models to use camelCase in API responses and snake_case internally.
    • Updated model configurations to improve consistency in serialization and deserialization.
  • Bug Fixes
    • Improved error handling and validation for access token verification.
  • Tests
    • Updated test data and assertions to match new field naming conventions and structure.
  • Chores
    • Removed outdated comments and simplified field definitions for clarity.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 29, 2025

Walkthrough

This set of changes standardizes the use of field aliases in Pydantic models across authentication, expenses, groups, and user modules, mapping internal snake_case attributes to camelCase JSON keys. It also updates related test data and fixtures to match the new naming conventions, and refactors a key authentication service function for improved robustness.

Changes

Cohort / File(s) Change Summary
Auth Schema Aliasing
backend/app/auth/schemas.py
Updated UserResponse model: created_at now uses Field(alias="createdAt") for camelCase JSON key mapping.
Auth Service Refactor
backend/app/auth/service.py
Refactored verify_access_token from class method to standalone async function, improved error handling, and explicit ObjectId conversion.
Expense Schema Aliasing & Cleanup
backend/app/expenses/schemas.py
Standardized datetime fields with Field aliases, removed inline comments, added model_config to FriendBalance.
Group Schema Aliasing & Config
backend/app/groups/schemas.py
All Pydantic models now use Field with explicit aliases, default values via Field, and model_config for population by name.
User Schema Aliasing & Minor Additions
backend/app/user/schemas.py
Changed field names to snake_case with camelCase aliases, added model_config, and introduced optional message in DeleteUserResponse.
Auth Test Data Update
backend/tests/auth/test_auth_routes.py
Updated test fixture keys from "created_at" to "createdAt" to match new schema aliasing.
Expense Test Import
backend/tests/expenses/test_expense_routes.py
Added import for get_current_user; no logic changes.
User Test Data Update
backend/tests/user/test_user_routes.py
Updated test mock data and assertions to use "imageURL" and "_id" instead of "imageUrl" and "id".

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API
    participant AuthService
    participant DB

    Client->>API: Sends request with JWT token
    API->>AuthService: Calls verify_access_token(token)
    AuthService->>AuthService: Decode JWT, extract user_id
    AuthService->>DB: Query user by ObjectId(user_id)
    DB-->>AuthService: Return user or error
    AuthService-->>API: Return user info or raise HTTP 401
    API-->>Client: Respond with user data or error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15-20 minutes

Possibly related PRs

  • Devasy23/splitwiser#25: Refactors user-related schemas and services for consistent field naming and datetime handling, conceptually related due to focus on schema standardization.
  • Devasy23/splitwiser#72: Updates model configuration style in UserResponse, related as both PRs modify configuration and aliasing in the same model.

Suggested labels

documentation, backend, api, api-consistency, enhancement

Poem

A hop, a skip, a schema tweak,
Aliases now are what we seek.
CamelCase and snake_case, friends,
Now play nicely, make amends.
Tests and services join the fun—
Consistency for everyone!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@netlify
Copy link

netlify bot commented Jul 29, 2025

Deploy Preview for splitwizer failed. Why did it fail? →

Name Link
🔨 Latest commit b2b2b8a
🔍 Latest deploy log https://app.netlify.com/projects/splitwizer/deploys/6888714611f42a000850f0ec

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
backend/app/groups/schemas.py (1)

8-12: LGTM! Consider optimizing redundant aliases.

The explicit Field aliases and model configuration are correctly implemented. However, since the aliases match the attribute names exactly (userId -> "userId"), they could be simplified by removing the alias parameter.

For fields where alias matches attribute name, you can simplify:

-    userId: str = Field(..., alias="userId")
+    userId: str = Field(...)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c7f054 and 5a8d6b7.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • backend/app/auth/schemas.py (1 hunks)
  • backend/app/auth/service.py (1 hunks)
  • backend/app/expenses/schemas.py (6 hunks)
  • backend/app/groups/schemas.py (1 hunks)
  • backend/app/user/schemas.py (1 hunks)
  • backend/tests/auth/test_auth_routes.py (3 hunks)
  • backend/tests/expenses/test_expense_routes.py (1 hunks)
  • backend/tests/user/test_user_routes.py (5 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
backend/**/*.py

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

Backend code must be implemented using FastAPI with Python 3.9+ and organized under the /backend/ directory.

Files:

  • backend/tests/expenses/test_expense_routes.py
  • backend/app/auth/schemas.py
  • backend/tests/auth/test_auth_routes.py
  • backend/app/groups/schemas.py
  • backend/tests/user/test_user_routes.py
  • backend/app/auth/service.py
  • backend/app/user/schemas.py
  • backend/app/expenses/schemas.py
backend/tests/**/*.py

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

Backend tests must be placed in the /backend/tests/ directory and run using pytest.

Files:

  • backend/tests/expenses/test_expense_routes.py
  • backend/tests/auth/test_auth_routes.py
  • backend/tests/user/test_user_routes.py
backend/app/{auth,user,groups,expenses}/**/*.py

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

backend/app/{auth,user,groups,expenses}/**/*.py: Backend services should be modular, with authentication and user registration in app/auth/, user profile management in app/user/, group management in app/groups/, and expense tracking in app/expenses/.
When adding a new API endpoint, add the route to the appropriate service router file in the backend.

Files:

  • backend/app/auth/schemas.py
  • backend/app/groups/schemas.py
  • backend/app/auth/service.py
  • backend/app/user/schemas.py
  • backend/app/expenses/schemas.py
backend/app/auth/**/*.py

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

JWT authentication with refresh token rotation must be implemented in the backend.

Files:

  • backend/app/auth/schemas.py
  • backend/app/auth/service.py
backend/app/expenses/**/*.py

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

backend/app/expenses/**/*.py: Support for different expense split types (equal, unequal, percentage-based) must be implemented in the expense tracking logic.
Settlements must track debt resolution between users in the expense tracking logic.

Files:

  • backend/app/expenses/schemas.py
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/{auth,user,groups,expenses}/**/*.py : Backend services should be modular, with authentication and user registration in app/auth/, user profile management in app/user/, group management in app/groups/, and expense tracking in app/expenses/.
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/expenses/**/*.py : Settlements must track debt resolution between users in the expense tracking logic.
backend/tests/expenses/test_expense_routes.py (3)

Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/{auth,user,groups,expenses}/**/*.py : When adding a new API endpoint, add the route to the appropriate service router file in the backend.

Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/expenses/**/*.py : Settlements must track debt resolution between users in the expense tracking logic.

Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/{auth,user,groups,expenses}/**/*.py : Backend services should be modular, with authentication and user registration in app/auth/, user profile management in app/user/, group management in app/groups/, and expense tracking in app/expenses/.

backend/tests/auth/test_auth_routes.py (1)

Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/{auth,user,groups,expenses}/**/*.py : When adding a new API endpoint, add the route to the appropriate service router file in the backend.

backend/app/auth/service.py (1)

Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/auth/security.py : To troubleshoot authentication issues, check JWT token handling in app/auth/security.py.

backend/app/expenses/schemas.py (2)

Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/expenses/**/*.py : Settlements must track debt resolution between users in the expense tracking logic.

Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/expenses/**/*.py : Support for different expense split types (equal, unequal, percentage-based) must be implemented in the expense tracking logic.

🧬 Code Graph Analysis (4)
backend/tests/auth/test_auth_routes.py (1)
backend/tests/user/test_user_service.py (3)
  • test_transform_user_document_with_updated_at_different_from_created_at (82-100)
  • test_transform_user_document_iso_str (110-113)
  • test_transform_user_document_iso_none (105-108)
backend/tests/user/test_user_routes.py (1)
backend/tests/user/test_user_service.py (5)
  • test_update_user_profile_success (165-191)
  • test_update_user_profile_user_not_found (195-208)
  • test_transform_user_document_with_updated_at_different_from_created_at (82-100)
  • test_transform_user_document_missing_optional_fields (63-80)
  • test_transform_user_document_all_fields (59-61)
backend/app/user/schemas.py (2)
backend/app/user/service.py (1)
  • update_user_profile (53-68)
backend/tests/user/test_user_service.py (1)
  • test_update_user_profile_success (165-191)
backend/app/expenses/schemas.py (1)
backend/app/expenses/service.py (1)
  • update_expense (240-360)
🪛 Ruff (0.12.2)
backend/tests/expenses/test_expense_routes.py

4-4: app.auth.dependencies.get_current_user imported but unused

Remove unused import: app.auth.dependencies.get_current_user

(F401)

backend/app/auth/service.py

307-307: Redefinition of unused ObjectId from line 16

Remove definition: ObjectId

(F811)


322-324: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🔇 Additional comments (10)
backend/app/auth/schemas.py (1)

47-47: LGTM! Proper camelCase aliasing implemented.

The created_at field correctly uses Field(alias="createdAt") to standardize timestamp fields to camelCase in API responses while maintaining snake_case internally. The existing populate_by_name=True configuration ensures backward compatibility.

backend/app/user/schemas.py (1)

14-15: LGTM! Consistent camelCase aliasing implemented.

The timestamp fields (created_at, updated_at) and image_url field are correctly aliased to camelCase format. The model_config = ConfigDict(populate_by_name=True) ensures flexible serialization/deserialization.

Also applies to: 17-17, 22-22, 25-25

backend/app/groups/schemas.py (2)

50-52: Excellent use of default_factory for mutable defaults.

Good practice using default_factory=list instead of a mutable default list. This prevents the common Python pitfall of shared mutable defaults across instances.


25-99: LGTM! Consistent schema standardization.

All models have been consistently updated with explicit Field aliases and proper model configuration. The changes align well with the PR objective of standardizing API response formats.

backend/app/expenses/schemas.py (6)

38-38: LGTM! Minor formatting cleanup.

The validator logic remains intact, just a minor formatting improvement.


69-69: Perfect alignment with PR objectives.

The Field alias for createdAt correctly maps the camelCase API response field to the snake_case database field created_at. This standardization improves API consistency.


81-81: Consistent datetime field aliasing.

Good use of Field alias to map editedAt to the database field edited_at, maintaining consistency with other datetime fields.


98-99: LGTM! Timestamp standardization completed.

Both createdAt and updatedAt fields properly aliased to their snake_case database equivalents. This completes the timestamp standardization objective.


115-116: Consistent settlement timestamp handling.

The Settlement model properly aliases both paidAt and createdAt fields, maintaining consistency with the timestamp standardization across all models.


193-195: FriendBalance model standardization completed.

The lastActivity field is properly aliased to last_activity and the model_config is correctly added for consistent serialization behavior.

Comment on lines +293 to +331
async def verify_access_token(self, token: str) -> Dict[str, Any]:
"""
Verifies an access token and retrieves the associated user.
Returns:
The user document corresponding to the token's subject.
Args:
token: The JWT access token to verify.
Raises:
HTTPException: If the token is invalid or the user does not exist.
"""
from app.auth.security import verify_token
Returns:
The user document corresponding to the token's subject.
payload = verify_token(token)
user_id = payload.get("sub")
Raises:
HTTPException: If the token is invalid or the user does not exist.
"""
from app.auth.security import verify_token
from bson import ObjectId

if not user_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token"
)
payload = verify_token(token)
user_id = payload.get("sub")

db = self.get_db()
user = await db.users.find_one({"_id": user_id})
if not user_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token"
)

if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found"
)
db = self.get_db()

try:
user = await db.users.find_one({"_id": ObjectId(user_id)})
except Exception:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user ID format"
)

if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found"
)

return user
return user
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical issues in function refactoring - function is broken

The refactoring from instance method to standalone function has introduced several critical issues:

  1. Function still references self: Line 317 calls self.get_db() but the function is no longer an instance method
  2. Redundant import: ObjectId is already imported at line 16, the import at line 307 is unnecessary
  3. Poor exception handling: The broad except Exception should use proper exception chaining

Apply this diff to fix the issues:

-async def verify_access_token(self, token: str) -> Dict[str, Any]:
+async def verify_access_token(token: str) -> Dict[str, Any]:
     """
     Verifies an access token and retrieves the associated user.

     Args:
         token: The JWT access token to verify.

     Returns:
         The user document corresponding to the token's subject.

     Raises:
         HTTPException: If the token is invalid or the user does not exist.
     """
     from app.auth.security import verify_token
-    from bson import ObjectId

     payload = verify_token(token)
     user_id = payload.get("sub")

     if not user_id:
         raise HTTPException(
             status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token"
         )

-    db = self.get_db()
+    db = get_database()

     try:
         user = await db.users.find_one({"_id": ObjectId(user_id)})
-    except Exception:
+    except Exception as e:
         raise HTTPException(
             status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user ID format"
-        )
+        ) from e

     if not user:
         raise HTTPException(
             status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found"
         )

     return user
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def verify_access_token(self, token: str) -> Dict[str, Any]:
"""
Verifies an access token and retrieves the associated user.
Returns:
The user document corresponding to the token's subject.
Args:
token: The JWT access token to verify.
Raises:
HTTPException: If the token is invalid or the user does not exist.
"""
from app.auth.security import verify_token
Returns:
The user document corresponding to the token's subject.
payload = verify_token(token)
user_id = payload.get("sub")
Raises:
HTTPException: If the token is invalid or the user does not exist.
"""
from app.auth.security import verify_token
from bson import ObjectId
if not user_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token"
)
payload = verify_token(token)
user_id = payload.get("sub")
db = self.get_db()
user = await db.users.find_one({"_id": user_id})
if not user_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token"
)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found"
)
db = self.get_db()
try:
user = await db.users.find_one({"_id": ObjectId(user_id)})
except Exception:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user ID format"
)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found"
)
return user
return user
async def verify_access_token(token: str) -> Dict[str, Any]:
"""
Verifies an access token and retrieves the associated user.
Args:
token: The JWT access token to verify.
Returns:
The user document corresponding to the token's subject.
Raises:
HTTPException: If the token is invalid or the user does not exist.
"""
from app.auth.security import verify_token
payload = verify_token(token)
user_id = payload.get("sub")
if not user_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token"
)
db = get_database()
try:
user = await db.users.find_one({"_id": ObjectId(user_id)})
except Exception as e:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user ID format"
) from e
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found"
)
return user
🧰 Tools
🪛 Ruff (0.12.2)

307-307: Redefinition of unused ObjectId from line 16

Remove definition: ObjectId

(F811)


322-324: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🤖 Prompt for AI Agents
In backend/app/auth/service.py between lines 293 and 331, the
verify_access_token function was refactored to a standalone function but still
references self.get_db(), which is invalid. Remove the self parameter and
replace self.get_db() with a proper database access method or pass the database
as a parameter. Also, remove the redundant import of ObjectId since it is
already imported at the top of the file. Finally, replace the broad except
Exception with a more specific exception for ObjectId conversion errors and use
exception chaining to preserve the original error context.

name: str
email: EmailStr
imageUrl: Optional[str] = None
image_url: Optional[str] = Field(default=None, alias="imageUrl")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify service layer field naming consistency.

The schema now uses image_url with alias "imageUrl", but the service layer may still be using the old field names.


🏁 Script executed:

#!/bin/bash
# Description: Check for field naming consistency between schemas and service layer
# Expected: Service layer should use snake_case field names or be updated accordingly

# Check user service for field usage
rg -A 3 -B 3 "imageUrl|image_url" backend/app/user/service.py

# Check for any remaining camelCase usage in service files that should be snake_case
rg -A 2 -B 2 "imageUrl.*=" backend/app/user/

Length of output: 829


Service layer should use snake_case internal field names

The service layer currently accesses and filters updates using "imageUrl" (camelCase), but the database still stores image_url. This mismatch can lead to missing data or failed updates. Update backend/app/user/service.py as follows:

• Change retrieval from user.get("imageUrl") to user.get("image_url").
• Replace "imageUrl" with "image_url" in the allowed set and update filters.

Example diff:

@@ backend/app/user/service.py
-    "imageUrl": user.get("imageUrl") or user.get("avatar"),
+    "imageUrl": user.get("image_url") or user.get("avatar"),

-    allowed = {"name", "imageUrl", "currency"}
+    allowed = {"name", "image_url", "currency"}

With model_config = ConfigDict(populate_by_name=True) in your Pydantic schemas, responses will continue to serialize image_url as imageUrl.

🤖 Prompt for AI Agents
In backend/app/user/schemas.py at line 12, the field uses alias "imageUrl" for
serialization, but in backend/app/user/service.py, update all internal
references from "imageUrl" to "image_url" to match the database field naming.
Specifically, change user.get("imageUrl") to user.get("image_url") and replace
"imageUrl" with "image_url" in any allowed field sets and filters. This ensures
consistent snake_case usage internally while preserving camelCase in API
responses via Pydantic's aliasing.

"hashed_password": "hashedpassword",
"name": "Existing User",
"created_at": "sometime", # Simplified for mock
"createdAt": "sometime", # Simplified for mock
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify database field naming convention.

The test data now uses "createdAt" in database documents, but typically databases use snake_case (created_at) internally while APIs expose camelCase through Pydantic aliases.

Also applies to: 174-174, 217-217


🏁 Script executed:

#!/bin/bash
# Description: Check if database operations use snake_case or camelCase field names
# Expected: Database operations should use snake_case, API responses use camelCase via aliases

# Check auth service for database field usage
rg -A 3 -B 3 "created_at|createdAt" backend/app/auth/service.py

# Check user service for database field usage  
rg -A 3 -B 3 "created_at|createdAt" backend/app/user/service.py

# Check database schemas/models
rg -A 3 -B 3 "created_at|createdAt" backend/app/models/

Length of output: 1603


Use snake_case for DB mocks; camelCase only in API responses

The auth service and user service both write/read created_at internally and expose createdAt via Pydantic aliases. Your tests are mocking database documents, so the mocks should use created_at. Only your assertions against the HTTP response should use createdAt.

Please update backend/tests/auth/test_auth_routes.py at the following locations:

  • Line 78:
  • "createdAt": "sometime", # Simplified for mock
  • "created_at": "sometime", # Simplified for mock
- Line 174:
```diff
-   "createdAt": some_timestamp,
+   "created_at": some_timestamp,
  • Line 217:
  • "createdAt": other_timestamp,
  • "created_at": other_timestamp,

Then, when verifying the endpoint’s JSON response, assert on `response.json()["createdAt"]` (the alias), not on the mock’s field name.

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
--- a/backend/tests/auth/test_auth_routes.py
+++ b/backend/tests/auth/test_auth_routes.py
@@ -75,7 +75,7 @@
       # Simplified mock document for user creation
       {
-            "createdAt": "sometime",  # Simplified for mock
+            "created_at": "sometime",  # Simplified for mock
           "email": "[email protected]",
           "id": str(user_id),
       }
@@ -171,7 +171,7 @@
       # Mock document for fetching auth tokens
       {
           "token": str(token),
-            "createdAt": some_timestamp,
+            "created_at": some_timestamp,
           "userId": str(user_id),
       }
@@ -214,7 +214,7 @@
       # Mock document for refresh-token rotation
       {
           "refreshToken": other_refresh_token,
-            "createdAt": other_timestamp,
+            "created_at": other_timestamp,
           "userId": str(user_id),
       }
🤖 Prompt for AI Agents
In backend/tests/auth/test_auth_routes.py at lines 78, 174, and 217, change the
mock database fields from camelCase (createdAt) to snake_case (created_at) to
match internal DB conventions. Then, in the test assertions that check the HTTP
response JSON, verify the alias field createdAt instead of created_at. This
ensures mocks reflect DB structure while assertions validate API response
format.

from unittest.mock import AsyncMock, patch

import pytest
from app.auth.dependencies import get_current_user
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove unused import.

The get_current_user import is not used in this file since the tests mock it via @patch decorators.

-from app.auth.dependencies import get_current_user
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from app.auth.dependencies import get_current_user
🧰 Tools
🪛 Ruff (0.12.2)

4-4: app.auth.dependencies.get_current_user imported but unused

Remove unused import: app.auth.dependencies.get_current_user

(F401)

🤖 Prompt for AI Agents
In backend/tests/expenses/test_expense_routes.py at line 4, the import of
get_current_user from app.auth.dependencies is unused because the tests mock
this dependency using @patch decorators. Remove this import statement to clean
up the code and avoid unnecessary imports.

"name": "Test User",
"email": TEST_USER_EMAIL,
"imageUrl": None,
"imageURL": None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix field naming inconsistencies in test data.

The test data has inconsistent field naming:

  1. Uses "imageURL" but the schema alias is "imageUrl" (note the lowercase 'u')
  2. Mixes "_id" and "id" - API responses should consistently use "id" since that's how the schema is aliased
-            "imageURL": None,
+            "imageUrl": None,
-            "_id": TEST_USER_ID,
+            "id": TEST_USER_ID,
-    assert data["imageURL"] == "http://example.com/avatar.png"
+    assert data["imageUrl"] == "http://example.com/avatar.png"
-    assert data["_id"] == TEST_USER_ID
+    assert data["id"] == TEST_USER_ID

Apply similar fixes to other occurrences in the file.

Also applies to: 49-49, 109-109, 126-126, 129-129

🤖 Prompt for AI Agents
In backend/tests/user/test_user_routes.py at lines 40, 49, 109, 126, and 129,
the test data uses inconsistent field names like "imageURL" instead of the
schema-aliased "imageUrl" and mixes "_id" with "id". Update all these
occurrences to use "imageUrl" with a lowercase 'u' and replace all "_id" fields
with "id" to match the API response schema consistently.

@netlify
Copy link

netlify bot commented Jul 29, 2025

Deploy Preview for splitwizer failed. Why did it fail? →

Name Link
🔨 Latest commit 5a8d6b7
🔍 Latest deploy log https://app.netlify.com/projects/splitwizer/deploys/68887154c933d60009c1858f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant