Skip to content
Closed

test #1900

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .claude/anthropic_key.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh

3 changes: 3 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"apiKeyHelper": ".claude/anthropic_key.sh"
}
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/copilot.data.migration.agent.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/copilot.data.migration.ask.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/copilot.data.migration.ask2agent.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/copilot.data.migration.edit.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/full-stack-fastapi-template.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions TASK_PROMPT.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
1) Add a toggle button on the main page to switch between dark mode and light mode. The selected mode should persist across page reloads (e.g., using local storage).
the defaulted mode should be system preference and gives us ability to switch it in the ui it should be available on all pages.
2) On the user items page, allow users to pick and upload images when adding new items. Implement the necessary backend API endpoint to handle image uploads and associate them with the items.
3) Implement a database seed script that inserts a test user with the username [email protected], password 12345678, and admin rights. Ensure this user is created only if it does not already exist.
Binary file added __pycache__/utils.cpython-313.pyc
Binary file not shown.
70 changes: 70 additions & 0 deletions backend/tests/test_api_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import pytest
from fastapi.testclient import TestClient
from unittest.mock import patch, MagicMock
from app.main import app
import json

client = TestClient(app)

def test_api_versioning():
"""Test API versioning and backward compatibility."""
# Test current API version
response = client.get("/api/v1/utils/health-check/")
assert response.status_code == 200

# Test that v1 endpoints are available
assert "/api/v1/" in str(response.url) or response.status_code == 200

def test_openapi_schema_validation():
"""Test OpenAPI schema is valid and complete."""
response = client.get("/openapi.json")
assert response.status_code == 200

schema = response.json()
assert "openapi" in schema
assert "info" in schema
assert "paths" in schema

def test_api_documentation_accessibility():
"""Test that API documentation is accessible."""
docs_response = client.get("/docs")
redoc_response = client.get("/redoc")

# At least one documentation endpoint should be available
assert docs_response.status_code == 200 or redoc_response.status_code == 200

def test_health_monitoring_endpoints():
"""Test health monitoring and status endpoints."""
health_response = client.get("/api/v1/utils/health-check/")
assert health_response.status_code == 200

# Verify health check response format
data = health_response.json()
assert isinstance(data, dict)

def test_api_error_response_format():
"""Test that API errors follow consistent format."""
# Make request to non-existent endpoint
response = client.get("/api/v1/nonexistent")
assert response.status_code == 404

# Verify error response is JSON
try:
error_data = response.json()
assert isinstance(error_data, dict)
except json.JSONDecodeError:
# Some APIs might return non-JSON 404s, which is also acceptable
pass

def test_request_id_tracking():
"""Test request ID tracking for debugging."""
response = client.get("/api/v1/utils/health-check/")

# Check if request ID is present in headers (implementation dependent)
request_id_headers = [
"x-request-id", "request-id", "x-trace-id"
]

has_request_id = any(header in response.headers for header in request_id_headers)
# This test is optional - not all APIs implement request ID tracking
assert response.status_code == 200 # Main assertion is that the endpoint works
35 changes: 35 additions & 0 deletions backend/tests/test_api_middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import pytest
from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_cors_headers():
"""Test CORS headers are properly set."""
response = client.options("/api/v1/users/me")
assert response.status_code in [200, 405]
# Check if CORS headers might be present
if "access-control-allow-origin" in response.headers:
assert response.headers["access-control-allow-origin"]

def test_api_version_consistency():
"""Test that all API endpoints use consistent versioning."""
# Test health check endpoint version
response = client.get("/api/v1/utils/health-check/")
assert response.status_code == 200

def test_content_type_headers():
"""Test that API returns proper content-type headers."""
response = client.get("/api/v1/utils/health-check/")
assert "application/json" in response.headers.get("content-type", "")

def test_response_time_performance():
"""Test basic response time performance."""
import time
start_time = time.time()
response = client.get("/api/v1/utils/health-check/")
end_time = time.time()

assert response.status_code == 200
# Response should be under 1 second for health check
assert (end_time - start_time) < 1.0
28 changes: 28 additions & 0 deletions backend/tests/test_authentication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import pytest
from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_login_valid_credentials():
"""Test login with valid credentials."""
response = client.post(
"/api/v1/login/access-token",
data={"username": "[email protected]", "password": "testpassword"}
)
assert response.status_code == 200
data = response.json()
assert "access_token" in data

def test_login_invalid_credentials():
"""Test login with invalid credentials."""
response = client.post(
"/api/v1/login/access-token",
data={"username": "[email protected]", "password": "wrongpassword"}
)
assert response.status_code == 400

def test_protected_route_without_token():
"""Test accessing protected route without token."""
response = client.get("/api/v1/users/me")
assert response.status_code == 401
29 changes: 29 additions & 0 deletions backend/tests/test_authorization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import pytest
from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_unauthorized_access():
"""Test accessing protected endpoints without authentication."""
response = client.get("/api/v1/users/me")
assert response.status_code == 401

def test_invalid_token_format():
"""Test using malformed authorization token."""
headers = {"Authorization": "InvalidTokenFormat"}
response = client.get("/api/v1/users/me", headers=headers)
assert response.status_code == 401

def test_expired_token():
"""Test using expired token."""
# This would require creating an expired token
headers = {"Authorization": "Bearer expired_token_here"}
response = client.get("/api/v1/users/me", headers=headers)
assert response.status_code == 401

def test_insufficient_permissions():
"""Test accessing admin endpoints with regular user token."""
headers = {"Authorization": "Bearer regular_user_token"}
response = client.get("/api/v1/admin/users/", headers=headers)
assert response.status_code in [401, 403, 404]
26 changes: 26 additions & 0 deletions backend/tests/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import pytest
from unittest.mock import patch
from app.core.config import Settings

def test_settings_initialization():
"""Test settings class initialization."""
settings = Settings()
assert hasattr(settings, 'SECRET_KEY')
assert hasattr(settings, 'PROJECT_NAME')

def test_database_url_construction():
"""Test database URL construction."""
settings = Settings()
# Should have postgres in the URL
assert 'postgresql' in str(settings.SQLALCHEMY_DATABASE_URI)

def test_cors_origins_parsing():
"""Test CORS origins parsing."""
with patch.dict('os.environ', {'BACKEND_CORS_ORIGINS': '["http://localhost:3000", "http://localhost:8000"]'}):
settings = Settings()
assert isinstance(settings.BACKEND_CORS_ORIGINS, list)

def test_environment_validation():
"""Test environment variable validation."""
settings = Settings()
assert settings.ENVIRONMENT in ['local', 'staging', 'production']
38 changes: 38 additions & 0 deletions backend/tests/test_crud_operations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import pytest
from sqlalchemy.orm import Session
from app.models import User, Item
from app.crud import create_user, get_user, update_user, delete_user

def test_create_user_crud(db: Session):
"""Test user creation through CRUD operations."""
user_data = {
"email": "[email protected]",
"password": "testpassword",
"full_name": "CRUD User"
}
user = create_user(db, user_data)
assert user.email == "[email protected]"
assert user.full_name == "CRUD User"

def test_get_user_by_email(db: Session):
"""Test retrieving user by email."""
# First create a user
user_data = {
"email": "[email protected]",
"password": "testpassword"
}
created_user = create_user(db, user_data)

# Then retrieve it
retrieved_user = get_user(db, email="[email protected]")
assert retrieved_user is not None
assert retrieved_user.email == "[email protected]"

def test_update_user_crud(db: Session):
"""Test user update through CRUD operations."""
user_data = {"email": "[email protected]", "password": "test"}
user = create_user(db, user_data)

update_data = {"full_name": "Updated Name"}
updated_user = update_user(db, user.id, update_data)
assert updated_user.full_name == "Updated Name"
36 changes: 36 additions & 0 deletions backend/tests/test_database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest
from sqlalchemy.orm import Session
from app.core.db import get_db
from app.models import User
from app.utils import generate_password_reset_token, verify_password_reset_token

def test_database_connection(db: Session):
"""Test database connection is working."""
result = db.execute("SELECT 1")
assert result.fetchone()[0] == 1

def test_user_model_creation(db: Session):
"""Test creating a user in the database."""
user_data = {
"email": "[email protected]",
"hashed_password": "hashedpassword123",
"full_name": "Test User"
}
user = User(**user_data)
db.add(user)
db.commit()
db.refresh(user)

assert user.id is not None
assert user.email == "[email protected]"
assert user.full_name == "Test User"

def test_database_rollback(db: Session):
"""Test database rollback functionality."""
user = User(email="[email protected]", hashed_password="test123")
db.add(user)
db.rollback()

# User should not exist after rollback
user_check = db.query(User).filter(User.email == "[email protected]").first()
assert user_check is None
Loading
Loading