11import pytest
2+ import os
23from typing import Generator
34from sqlmodel import create_engine , Session , select
4- from sqlalchemy import Engine
55from fastapi .testclient import TestClient
66from dotenv import load_dotenv
7- from utils .core .db import get_connection_url , tear_down_db , set_up_db , create_default_roles
8- from utils .core .models import User , PasswordResetToken , EmailUpdateToken , Organization , Role , Account , Invitation
7+ from utils .core .db import get_connection_url , tear_down_db , set_up_db , create_default_roles , ensure_database_exists
8+ from utils .core .models import User , Organization , Role , Account , Invitation
99from utils .core .auth import get_password_hash , create_access_token , create_refresh_token
1010from main import app
1111from datetime import datetime , UTC , timedelta
1212
13- # Load environment variables
14- load_dotenv (override = True )
15-
1613# Define a custom exception for test setup errors
1714class SetupError (Exception ):
1815 """Exception raised for errors in the test setup process."""
@@ -21,29 +18,41 @@ def __init__(self, message="An error occurred during test setup"):
2118 super ().__init__ (self .message )
2219
2320
24- @pytest .fixture (scope = "session" )
25- def engine () -> Engine :
21+ @pytest .fixture
22+ def env_vars (monkeypatch ):
23+ load_dotenv ()
24+
25+ # monkeypatch remaining env vars
26+ with monkeypatch .context () as m :
27+ # Get valid db user, password, host, and port from env
28+ m .setenv ("DB_HOST" , os .getenv ("DB_HOST" , "127.0.0.1" ))
29+ m .setenv ("DB_PORT" , os .getenv ("DB_PORT" , "5432" ))
30+ m .setenv ("DB_USER" , os .getenv ("DB_USER" , "postgres" ))
31+ m .setenv ("DB_PASSWORD" , os .getenv ("DB_PASSWORD" , "postgres" ))
32+ m .setenv ("SECRET_KEY" , "testsecretkey" )
33+ m .setenv ("HOST_NAME" , "Test Organization" )
34+ m .setenv ("DB_NAME" , "qual2db4-test-db" )
35+ m .setenv ("RESEND_API_KEY" , "test" )
36+ m .
setenv (
"EMAIL_FROM" ,
"[email protected] " )
37+ m .setenv ("QUALTRICS_BASE_URL" , "test" )
38+ m .setenv ("QUALTRICS_API_TOKEN" , "test" )
39+ m .setenv ("BASE_URL" , "http://localhost:8000" )
40+ yield
41+
42+
43+ @pytest .fixture
44+ def engine (env_vars ):
2645 """
2746 Create a new SQLModel engine for the test database.
2847 Use PostgreSQL for testing to match production environment.
2948 """
3049 # Use PostgreSQL for testing to match production environment
50+ ensure_database_exists (get_connection_url ())
3151 engine = create_engine (get_connection_url ())
32- return engine
52+ set_up_db ( drop = True )
3353
54+ yield engine
3455
35- @pytest .fixture (scope = "session" , autouse = True )
36- def set_up_database (engine ) -> Generator [None , None , None ]:
37- """
38- Set up the test database before running the test suite.
39- Drop all tables and recreate them to ensure a clean state.
40- """
41- # Drop and recreate all tables using the helpers from db.py
42- tear_down_db ()
43- set_up_db (drop = False )
44-
45- yield
46-
4756 # Clean up after tests
4857 tear_down_db ()
4958
@@ -57,20 +66,7 @@ def session(engine) -> Generator[Session, None, None]:
5766 yield session
5867
5968
60- @pytest .fixture (autouse = True )
61- def clean_db (session : Session ) -> None :
62- """
63- Cleans up the database tables before each test.
64- """
65- # Don't delete permissions as they are required for tests
66- for model in (PasswordResetToken , EmailUpdateToken , User , Role , Organization , Account ):
67- for record in session .exec (select (model )).all ():
68- session .delete (record )
69-
70- session .commit ()
71-
72-
73- @pytest .fixture ()
69+ @pytest .fixture
7470def test_account (session : Session ) -> Account :
7571 """
7672 Creates a test account in the database.
@@ -85,7 +81,7 @@ def test_account(session: Session) -> Account:
8581 return account
8682
8783
88- @pytest .fixture ()
84+ @pytest .fixture
8985def test_user (session : Session , test_account : Account ) -> User :
9086 """
9187 Creates a test user in the database linked to the test account.
@@ -103,7 +99,7 @@ def test_user(session: Session, test_account: Account) -> User:
10399 return user
104100
105101
106- @pytest .fixture ()
102+ @pytest .fixture
107103def unauth_client (session : Session ) -> Generator [TestClient , None , None ]:
108104 """
109105 Provides a TestClient instance without authentication.
@@ -112,7 +108,7 @@ def unauth_client(session: Session) -> Generator[TestClient, None, None]:
112108 yield client
113109
114110
115- @pytest .fixture ()
111+ @pytest .fixture
116112def auth_client (session : Session , test_account : Account , test_user : User ) -> Generator [TestClient , None , None ]:
117113 """
118114 Provides a TestClient instance with valid authentication tokens.
@@ -136,13 +132,13 @@ def test_organization(session: Session) -> Organization:
136132 session .add (organization )
137133 session .flush ()
138134
139- if organization .id is None :
135+ if organization .id :
136+ # Use the utility function to create default roles and assign permissions
137+ # This function handles the commit internally
138+ create_default_roles (session , organization .id , check_first = False )
139+ else :
140140 pytest .fail ("Failed to get organization ID after flush" )
141141
142- # Use the utility function to create default roles and assign permissions
143- # This function handles the commit internally
144- create_default_roles (session , organization .id , check_first = False )
145-
146142 return organization
147143
148144
0 commit comments