Skip to content
Merged
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
51 changes: 51 additions & 0 deletions .github/workflows/backend-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Backend Tests

on:
pull_request:

jobs:
check_paths:
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.filter.outputs.backend }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3.0.2
id: filter
with:
filters: |
backend:
- 'src/backend/**'
- '.github/workflows/backend-tests.yaml'

test:
name: Test Backend
needs: check_paths
if: ${{ needs.check_paths.outputs.should_run == 'true' }}
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./src/backend

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install UV
uses: astral-sh/setup-uv@v5

- name: Set up Python
run: uv python install

- name: Install dependencies
run: |
uv sync --locked --dev

- name: Lint with Ruff
run: |
uv run ruff check --output-format=github --target-version=py313 src tests
uv run ruff format --diff --check --target-version=py313 src tests

- name: Run tests with coverage
run: |
uv run pytest
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,12 @@ repos:
hooks:
- id: commitizen
stages: [commit-msg]

- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.11.6
hooks:
# Run the linter.
- id: ruff
# Run the formatter.
- id: ruff-format
1 change: 1 addition & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[tools]
pre-commit = "latest"
python = "3.13"
ruff = "latest"
uv = "latest"

[settings]
Expand Down
7 changes: 7 additions & 0 deletions src/backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ authors = [{ name = "aadil96", email = "agwan96@gmail.com" }]
requires-python = ">=3.13"
dependencies = [
"fastapi>=0.121.2",
"httpx>=0.28.1",
"pytest>=9.0.1",
"pytest-asyncio>=1.3.0",
"ruff>=0.14.5",
"uvicorn>=0.38.0",
]

[project.scripts]
study-tracker-api = "backend.main:main"

[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "function"

[tool.hatch.build.targets.wheel]
packages = ["src/backend"]

Expand Down
Empty file added src/backend/tests/__init__.py
Empty file.
69 changes: 69 additions & 0 deletions src/backend/tests/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import os
from unittest import mock

from backend.config import (
APP_NAME,
API_HOST,
API_PORT,
DATA_DIR,
CORS_ALLOW_ORIGINS,
CORS_ALLOW_METHODS,
CORS_ALLOW_HEADERS,
CORS_ALLOW_CREDENTIALS,
)


def test_settings_default_values():
"""Test that Settings has the expected default values."""
assert APP_NAME == "DevOps Study Tracker"
assert API_HOST == "0.0.0.0"
assert API_PORT == 22112
assert DATA_DIR.endswith("data")

# Test CORS default values
assert CORS_ALLOW_ORIGINS == ["*"]
assert CORS_ALLOW_METHODS == ["*"]
assert CORS_ALLOW_HEADERS == ["*"]
assert CORS_ALLOW_CREDENTIALS is True


@mock.patch.dict(
os.environ,
{
"API_HOST": "127.0.0.1",
"API_PORT": "9000",
"CORS_ALLOW_ORIGINS": "https://example.com,https://api.example.com",
"CORS_ALLOW_METHODS": "GET,POST,PUT",
"CORS_ALLOW_HEADERS": "Content-Type,Authorization",
"CORS_ALLOW_CREDENTIALS": "false",
},
)
def test_settings_from_env():
"""Test that Settings loads values from environment variables."""
# Force reload of the config module to get updated environment variables
import importlib
import backend.config

importlib.reload(backend.config)

# Import the settings again after reload
from backend.config import (
API_HOST,
API_PORT,
CORS_ALLOW_ORIGINS,
CORS_ALLOW_METHODS,
CORS_ALLOW_HEADERS,
CORS_ALLOW_CREDENTIALS,
)

assert API_HOST == "127.0.0.1"
assert API_PORT == 9000

# Test CORS values from environment
assert CORS_ALLOW_ORIGINS == [
"https://example.com",
"https://api.example.com",
]
assert CORS_ALLOW_METHODS == ["GET", "POST", "PUT"]
assert CORS_ALLOW_HEADERS == ["Content-Type", "Authorization"]
assert CORS_ALLOW_CREDENTIALS is False
Loading