1
1
import pytest
2
+ import os
2
3
from typing import Generator
3
4
from sqlmodel import create_engine , Session , select
4
- from sqlalchemy import Engine
5
5
from fastapi .testclient import TestClient
6
6
from 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
9
9
from utils .core .auth import get_password_hash , create_access_token , create_refresh_token
10
10
from main import app
11
11
from datetime import datetime , UTC , timedelta
12
12
13
- # Load environment variables
14
- load_dotenv (override = True )
15
-
16
13
# Define a custom exception for test setup errors
17
14
class SetupError (Exception ):
18
15
"""Exception raised for errors in the test setup process."""
@@ -21,29 +18,41 @@ def __init__(self, message="An error occurred during test setup"):
21
18
super ().__init__ (self .message )
22
19
23
20
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 ):
26
45
"""
27
46
Create a new SQLModel engine for the test database.
28
47
Use PostgreSQL for testing to match production environment.
29
48
"""
30
49
# Use PostgreSQL for testing to match production environment
50
+ ensure_database_exists (get_connection_url ())
31
51
engine = create_engine (get_connection_url ())
32
- return engine
52
+ set_up_db ( drop = True )
33
53
54
+ yield engine
34
55
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
-
47
56
# Clean up after tests
48
57
tear_down_db ()
49
58
@@ -57,20 +66,7 @@ def session(engine) -> Generator[Session, None, None]:
57
66
yield session
58
67
59
68
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
74
70
def test_account (session : Session ) -> Account :
75
71
"""
76
72
Creates a test account in the database.
@@ -85,7 +81,7 @@ def test_account(session: Session) -> Account:
85
81
return account
86
82
87
83
88
- @pytest .fixture ()
84
+ @pytest .fixture
89
85
def test_user (session : Session , test_account : Account ) -> User :
90
86
"""
91
87
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:
103
99
return user
104
100
105
101
106
- @pytest .fixture ()
102
+ @pytest .fixture
107
103
def unauth_client (session : Session ) -> Generator [TestClient , None , None ]:
108
104
"""
109
105
Provides a TestClient instance without authentication.
@@ -112,7 +108,7 @@ def unauth_client(session: Session) -> Generator[TestClient, None, None]:
112
108
yield client
113
109
114
110
115
- @pytest .fixture ()
111
+ @pytest .fixture
116
112
def auth_client (session : Session , test_account : Account , test_user : User ) -> Generator [TestClient , None , None ]:
117
113
"""
118
114
Provides a TestClient instance with valid authentication tokens.
@@ -136,13 +132,13 @@ def test_organization(session: Session) -> Organization:
136
132
session .add (organization )
137
133
session .flush ()
138
134
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 :
140
140
pytest .fail ("Failed to get organization ID after flush" )
141
141
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
-
146
142
return organization
147
143
148
144
0 commit comments