"""Pytest configuration and fixtures""" import pytest import tempfile import os from faker import Faker from app import create_app, db from app.models import User, Product, Order, OrderItem fake = Faker() @pytest.fixture(scope='function') def app(): """Create application for testing with isolated database""" db_fd, db_path = tempfile.mkstemp() app = create_app(config_name='test') app.config.update({ 'TESTING': True, 'SQLALCHEMY_DATABASE_URI': f'sqlite:///{db_path}', 'WTF_CSRF_ENABLED': False, 'JWT_SECRET_KEY': 'test-secret-keytest-secret-keytest-secret-keytest-secret-keytest-secret-key', 'SERVER_NAME': 'localhost.localdomain' }) with app.app_context(): db.create_all() yield app db.session.remove() db.drop_all() os.close(db_fd) os.unlink(db_path) @pytest.fixture def client(app): """Test client for making requests""" return app.test_client() @pytest.fixture def runner(app): """Test CLI runner""" return app.test_cli_runner() @pytest.fixture def db_session(app): """Database session for tests""" with app.app_context(): yield db.session @pytest.fixture def admin_user(db_session): """Create an admin user for testing""" user = User( email=fake.email(), username=fake.user_name(), first_name=fake.first_name(), last_name=fake.last_name(), is_admin=True, is_active=True ) user.set_password('password123') db_session.add(user) db_session.commit() return user @pytest.fixture def regular_user(db_session): """Create a regular user for testing""" user = User( email=fake.email(), username=fake.user_name(), first_name=fake.first_name(), last_name=fake.last_name(), is_admin=False, is_active=True ) user.set_password('password123') db_session.add(user) db_session.commit() return user @pytest.fixture def inactive_user(db_session): """Create an inactive user for testing""" user = User( email=fake.email(), username=fake.user_name(), first_name=fake.first_name(), last_name=fake.last_name(), is_admin=False, is_active=False ) user.set_password('password123') db_session.add(user) db_session.commit() return user @pytest.fixture def product(db_session): """Create a product for testing""" product = Product( name=fake.sentence(nb_words=4)[:-1], # Remove period description=fake.paragraph(), price=fake.pydecimal(left_digits=2, right_digits=2, positive=True), stock=fake.pyint(min_value=0, max_value=100), image_url=fake.url() ) db_session.add(product) db_session.commit() return product @pytest.fixture def products(db_session): """Create multiple products for testing""" products = [] for _ in range(5): product = Product( name=fake.sentence(nb_words=4)[:-1], description=fake.paragraph(), price=fake.pydecimal(left_digits=2, right_digits=2, positive=True), stock=fake.pyint(min_value=0, max_value=100), image_url=fake.url() ) db_session.add(product) products.append(product) db_session.commit() return products @pytest.fixture def auth_headers(client, regular_user): """Get authentication headers for a regular user""" response = client.post('/api/auth/login', json={ 'email': regular_user.email, 'password': 'password123' }) data = response.get_json() token = data['access_token'] print(f"Auth headers token for user {regular_user.email}: {token[:50]}...") return {'Authorization': f'Bearer {token}'} @pytest.fixture def admin_headers(client, admin_user): """Get authentication headers for an admin user""" response = client.post('/api/auth/login', json={ 'email': admin_user.email, 'password': 'password123' }) data = response.get_json() token = data['access_token'] print(f"Admin headers token for user {admin_user.email}: {token[:50]}...") return {'Authorization': f'Bearer {token}'} @pytest.fixture def order(db_session, regular_user, products): """Create an order for testing""" order = Order( user_id=regular_user.id, total_amount=0.0, shipping_address=fake.address() ) db_session.add(order) db_session.flush() total_amount = 0 for i, product in enumerate(products[:2]): quantity = fake.pyint(min_value=1, max_value=5) order_item = OrderItem( order_id=order.id, product_id=product.id, quantity=quantity, price=product.price ) total_amount += float(product.price) * quantity db_session.add(order_item) order.total_amount = total_amount db_session.commit() return order