Files
Fulfillment-Backend/tests/fixture_loader.py

104 lines
3.3 KiB
Python

import json
import os
from datetime import datetime
from pathlib import Path
from typing import Any
from sqlalchemy import text, Table, insert
from sqlalchemy.ext.asyncio import AsyncSession
from models import User, Role, WorkShift, PayrollScheme, PayRate, user_pay_rate
from models.work_shifts import WorkShiftPause
class FixtureLoader:
def __init__(self, fixture_path: str = "fixtures"):
project_root = Path(__file__).parent
self.fixture_path = project_root / fixture_path
@staticmethod
def _fixtures_to_load() -> list[tuple[str, Any]]:
return [
("roles", Role),
("payroll_schemas", PayrollScheme),
("pay_rates", PayRate),
("users", User),
("work_shifts", WorkShift),
("work_shift_pauses", WorkShiftPause),
]
@staticmethod
def _many_to_many_fixtures() -> list[tuple[str, Table]]:
return [
("user_pay_rates", user_pay_rate),
]
async def load_fixtures(self, db: AsyncSession):
file_postfix = ".json"
for fixture_file, model in self._fixtures_to_load():
await self._load_model_fixtures(db, fixture_file + file_postfix, model)
for fixture_file, table in self._many_to_many_fixtures():
await self._load_m2m_fixtures(db, fixture_file + file_postfix, table)
async def _load_model_fixtures(
self,
db: AsyncSession,
fixture_file: str,
model: Any,
):
"""Load fixtures for a specific model"""
fixture_path = os.path.join(self.fixture_path, fixture_file)
if not os.path.exists(fixture_path):
print(f"Fixture file {fixture_path} not found")
return 0
with open(fixture_path, "r") as f:
data = json.load(f)
for item_data in data:
converted_data = {}
for key, value in item_data.items():
if isinstance(value, str) and len(value) == 19:
try:
# Try to parse as datetime
converted_data[key] = datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
except ValueError:
# If it fails, keep the original value
converted_data[key] = value
else:
converted_data[key] = value
db_item = model(**converted_data)
db.add(db_item)
await db.commit()
async def _load_m2m_fixtures(
self,
db: AsyncSession,
fixture_file: str,
table: Table,
):
"""Load fixtures for many-to-many association tables"""
fixture_path = os.path.join(self.fixture_path, fixture_file)
if not os.path.exists(fixture_path):
print(f"Fixture file {fixture_path} not found")
return 0
with open(fixture_path, "r") as f:
data = json.load(f)
# Use SQLAlchemy insert for association tables
if data:
await db.execute(insert(table), data)
await db.commit()
async def clear_fixtures(self, db: AsyncSession):
"""Clear all fixture data (useful for testing)"""
for fixture_file, _ in self._fixtures_to_load()[::-1]:
await db.execute(text("DELETE FROM " + fixture_file))
await db.commit()