inital
This commit is contained in:
@@ -0,0 +1 @@
|
||||
"""Tests package."""
|
||||
@@ -0,0 +1,99 @@
|
||||
"""Pytest configuration and fixtures."""
|
||||
import pytest
|
||||
from app import create_app
|
||||
from app.extensions import db as _db
|
||||
from app.models import User, Organization, OrganizationMember
|
||||
from app.services.auth_service import AuthService
|
||||
from app.utils.constants import OrganizationRole
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def app():
|
||||
"""Create application for testing."""
|
||||
app = create_app("testing")
|
||||
return app
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def db(app):
|
||||
"""Create database for testing."""
|
||||
with app.app_context():
|
||||
_db.create_all()
|
||||
yield _db
|
||||
_db.session.remove()
|
||||
_db.drop_all()
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def client(app, db):
|
||||
"""Create test client."""
|
||||
return app.test_client()
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def test_user(db):
|
||||
"""Create a test user."""
|
||||
email = "test@example.com"
|
||||
password = "TestPassword123!"
|
||||
full_name = "Test User"
|
||||
|
||||
user = AuthService.register_user(
|
||||
email=email,
|
||||
password=password,
|
||||
full_name=full_name,
|
||||
)
|
||||
|
||||
# Store password for testing
|
||||
user._test_password = password
|
||||
|
||||
return user
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def test_organization(db, test_user):
|
||||
"""Create a test organization."""
|
||||
from app.services.organization_service import OrganizationService
|
||||
|
||||
org = OrganizationService.create_organization(
|
||||
name="Test Organization",
|
||||
slug="test-org",
|
||||
owner_user_id=test_user.id,
|
||||
description="A test organization",
|
||||
)
|
||||
|
||||
return org
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def authenticated_client(client, test_user):
|
||||
"""Create authenticated test client."""
|
||||
# Login
|
||||
response = client.post(
|
||||
"/api/v1/auth/login",
|
||||
json={
|
||||
"email": test_user.email,
|
||||
"password": test_user._test_password,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
return client
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def second_test_user(db):
|
||||
"""Create a second test user."""
|
||||
email = "second@example.com"
|
||||
password = "TestPassword123!"
|
||||
full_name = "Second User"
|
||||
|
||||
user = AuthService.register_user(
|
||||
email=email,
|
||||
password=password,
|
||||
full_name=full_name,
|
||||
)
|
||||
|
||||
user._test_password = password
|
||||
|
||||
return user
|
||||
@@ -0,0 +1 @@
|
||||
"""Integration tests package."""
|
||||
@@ -0,0 +1,107 @@
|
||||
"""Integration tests for authentication flow."""
|
||||
import pytest
|
||||
import json
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
class TestAuthFlow:
|
||||
"""Integration tests for authentication endpoints."""
|
||||
|
||||
def test_register_login_logout_flow(self, client, db):
|
||||
"""Test complete registration, login, and logout flow."""
|
||||
# Register
|
||||
register_data = {
|
||||
"email": "integration@example.com",
|
||||
"password": "TestPassword123!",
|
||||
"password_confirm": "TestPassword123!",
|
||||
"full_name": "Integration Test",
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/auth/register",
|
||||
data=json.dumps(register_data),
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
assert "user" in data["data"]
|
||||
assert data["data"]["user"]["email"] == "integration@example.com"
|
||||
|
||||
# Logout
|
||||
response = client.post("/api/v1/auth/logout")
|
||||
assert response.status_code == 200
|
||||
|
||||
# Login
|
||||
login_data = {
|
||||
"email": "integration@example.com",
|
||||
"password": "TestPassword123!",
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/auth/login",
|
||||
data=json.dumps(login_data),
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
assert "user" in data["data"]
|
||||
|
||||
# Logout again
|
||||
response = client.post("/api/v1/auth/logout")
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_get_current_user_authenticated(self, authenticated_client):
|
||||
"""Test getting current user when authenticated."""
|
||||
response = authenticated_client.get("/api/v1/auth/me")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
assert "user" in data["data"]
|
||||
|
||||
def test_get_current_user_unauthenticated(self, client):
|
||||
"""Test getting current user when not authenticated."""
|
||||
response = client.get("/api/v1/auth/me")
|
||||
|
||||
assert response.status_code == 401
|
||||
data = response.get_json()
|
||||
assert data["success"] is False
|
||||
|
||||
def test_invalid_credentials(self, client, test_user):
|
||||
"""Test login with invalid credentials."""
|
||||
login_data = {
|
||||
"email": test_user.email,
|
||||
"password": "WrongPassword123!",
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/auth/login",
|
||||
data=json.dumps(login_data),
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 401
|
||||
data = response.get_json()
|
||||
assert data["success"] is False
|
||||
|
||||
def test_duplicate_registration(self, client, test_user):
|
||||
"""Test registering with existing email."""
|
||||
register_data = {
|
||||
"email": test_user.email,
|
||||
"password": "TestPassword123!",
|
||||
"password_confirm": "TestPassword123!",
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/auth/register",
|
||||
data=json.dumps(register_data),
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 409
|
||||
data = response.get_json()
|
||||
assert data["success"] is False
|
||||
@@ -0,0 +1 @@
|
||||
"""Unit tests package."""
|
||||
@@ -0,0 +1,76 @@
|
||||
"""Unit tests for models."""
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
from app.models import User, Organization
|
||||
from app.utils.constants import UserStatus
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestUserModel:
|
||||
"""Tests for User model."""
|
||||
|
||||
def test_create_user(self, db):
|
||||
"""Test creating a user."""
|
||||
user = User(
|
||||
email="test@example.com",
|
||||
full_name="Test User",
|
||||
status=UserStatus.ACTIVE,
|
||||
)
|
||||
user.save()
|
||||
|
||||
assert user.id is not None
|
||||
assert user.email == "test@example.com"
|
||||
assert user.full_name == "Test User"
|
||||
assert user.status == UserStatus.ACTIVE
|
||||
assert user.created_at is not None
|
||||
assert user.deleted_at is None
|
||||
|
||||
def test_user_to_dict(self, test_user):
|
||||
"""Test user to_dict method."""
|
||||
user_dict = test_user.to_dict()
|
||||
|
||||
assert "id" in user_dict
|
||||
assert "email" in user_dict
|
||||
assert user_dict["email"] == test_user.email
|
||||
assert "created_at" in user_dict
|
||||
|
||||
def test_user_soft_delete(self, test_user):
|
||||
"""Test soft deleting a user."""
|
||||
test_user.delete(soft=True)
|
||||
|
||||
assert test_user.deleted_at is not None
|
||||
assert isinstance(test_user.deleted_at, datetime)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestOrganizationModel:
|
||||
"""Tests for Organization model."""
|
||||
|
||||
def test_create_organization(self, db):
|
||||
"""Test creating an organization."""
|
||||
org = Organization(
|
||||
name="Test Org",
|
||||
slug="test-org",
|
||||
description="Test organization",
|
||||
)
|
||||
org.save()
|
||||
|
||||
assert org.id is not None
|
||||
assert org.name == "Test Org"
|
||||
assert org.slug == "test-org"
|
||||
assert org.is_active is True
|
||||
assert org.created_at is not None
|
||||
|
||||
def test_organization_to_dict(self, test_organization):
|
||||
"""Test organization to_dict method."""
|
||||
org_dict = test_organization.to_dict()
|
||||
|
||||
assert "id" in org_dict
|
||||
assert "name" in org_dict
|
||||
assert org_dict["name"] == test_organization.name
|
||||
assert "slug" in org_dict
|
||||
|
||||
def test_get_member_count(self, test_organization):
|
||||
"""Test getting member count."""
|
||||
count = test_organization.get_member_count()
|
||||
assert count == 1 # Only the owner
|
||||
@@ -0,0 +1 @@
|
||||
"""Services unit tests package."""
|
||||
@@ -0,0 +1,102 @@
|
||||
"""Unit tests for AuthService."""
|
||||
import pytest
|
||||
from app.services.auth_service import AuthService
|
||||
from app.exceptions.auth_exceptions import InvalidCredentialsError
|
||||
from app.exceptions.validation_exceptions import EmailAlreadyExistsError
|
||||
from app.utils.constants import UserStatus, AuthMethodType
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestAuthService:
|
||||
"""Tests for AuthService."""
|
||||
|
||||
def test_register_user(self, db):
|
||||
"""Test user registration."""
|
||||
email = "newuser@example.com"
|
||||
password = "SecurePassword123!"
|
||||
full_name = "New User"
|
||||
|
||||
user = AuthService.register_user(
|
||||
email=email,
|
||||
password=password,
|
||||
full_name=full_name,
|
||||
)
|
||||
|
||||
assert user.id is not None
|
||||
assert user.email == email.lower()
|
||||
assert user.full_name == full_name
|
||||
assert user.status == UserStatus.ACTIVE
|
||||
assert user.has_password_auth()
|
||||
|
||||
def test_register_duplicate_email(self, db, test_user):
|
||||
"""Test registering with duplicate email."""
|
||||
with pytest.raises(EmailAlreadyExistsError):
|
||||
AuthService.register_user(
|
||||
email=test_user.email,
|
||||
password="SomePassword123!",
|
||||
)
|
||||
|
||||
def test_authenticate_success(self, db, test_user):
|
||||
"""Test successful authentication."""
|
||||
user = AuthService.authenticate(
|
||||
email=test_user.email,
|
||||
password=test_user._test_password,
|
||||
)
|
||||
|
||||
assert user.id == test_user.id
|
||||
assert user.last_login_at is not None
|
||||
|
||||
def test_authenticate_wrong_password(self, db, test_user):
|
||||
"""Test authentication with wrong password."""
|
||||
with pytest.raises(InvalidCredentialsError):
|
||||
AuthService.authenticate(
|
||||
email=test_user.email,
|
||||
password="WrongPassword123!",
|
||||
)
|
||||
|
||||
def test_authenticate_nonexistent_user(self, db):
|
||||
"""Test authentication with non-existent email."""
|
||||
with pytest.raises(InvalidCredentialsError):
|
||||
AuthService.authenticate(
|
||||
email="nonexistent@example.com",
|
||||
password="SomePassword123!",
|
||||
)
|
||||
|
||||
def test_create_session(self, app, db, test_user):
|
||||
"""Test creating a session."""
|
||||
with app.test_request_context():
|
||||
session = AuthService.create_session(test_user)
|
||||
|
||||
assert session.id is not None
|
||||
assert session.user_id == test_user.id
|
||||
assert session.token is not None
|
||||
assert session.is_active()
|
||||
|
||||
def test_change_password(self, app, db, test_user):
|
||||
"""Test changing password."""
|
||||
with app.test_request_context():
|
||||
new_password = "NewPassword456!"
|
||||
|
||||
AuthService.change_password(
|
||||
user=test_user,
|
||||
current_password=test_user._test_password,
|
||||
new_password=new_password,
|
||||
)
|
||||
|
||||
# Verify can login with new password
|
||||
user = AuthService.authenticate(
|
||||
email=test_user.email,
|
||||
password=new_password,
|
||||
)
|
||||
|
||||
assert user.id == test_user.id
|
||||
|
||||
def test_change_password_wrong_current(self, app, db, test_user):
|
||||
"""Test changing password with wrong current password."""
|
||||
with app.test_request_context():
|
||||
with pytest.raises(InvalidCredentialsError):
|
||||
AuthService.change_password(
|
||||
user=test_user,
|
||||
current_password="WrongPassword123!",
|
||||
new_password="NewPassword456!",
|
||||
)
|
||||
Reference in New Issue
Block a user