import pytest from fastapi import status def test_create_user(client, auth_headers): """Test creating a new user.""" user_data = { "name": "newuser", "email": "newuser@example.com", "is_admin": False, "password": "newpassword123" } response = client.post("/users/", json=user_data, headers=auth_headers) assert response.status_code == 200 data = response.json() assert data["name"] == "newuser" assert data["email"] == "newuser@example.com" assert data["is_admin"] is False assert "id" in data assert "passwordhash" not in data # Password hash should not be in response def test_create_user_unauthorized(client): """Test creating a user without admin credentials.""" user_data = { "name": "unauthorized_user", "email": "unauthorized@example.com", "password": "password123" } response = client.post("/users/", json=user_data) assert response.status_code == 403 def test_get_users(client, auth_headers, admin_user, regular_user): """Test retrieving all users.""" response = client.get("/users/", headers=auth_headers) assert response.status_code == 200 users = response.json() assert len(users) >= 2 # At least admin_user and regular_user user_names = [user["name"] for user in users] assert admin_user.name in user_names assert regular_user.name in user_names def test_get_user_by_id(client, auth_headers, regular_user): """Test retrieving a specific user by ID.""" response = client.get(f"/users/{regular_user.id}", headers=auth_headers) assert response.status_code == 200 data = response.json() assert data["id"] == regular_user.id assert data["name"] == regular_user.name def test_get_nonexistent_user(client, auth_headers): """Test retrieving a non-existent user.""" response = client.get("/users/99999", headers=auth_headers) assert response.status_code == 404 assert "not found" in response.json()["detail"].lower() def test_update_user(client, auth_headers, regular_user): """Test updating a user.""" update_data = { "name": "updated_name", "email": "updated@example.com" } response = client.patch( f"/users/{regular_user.id}", json=update_data, headers=auth_headers ) assert response.status_code == 200 data = response.json() assert data["name"] == "updated_name" assert data["email"] == "updated@example.com" # Unchanged fields should remain the same assert data["is_admin"] == regular_user.is_admin def test_update_user_password(client, auth_headers, regular_user): """Test updating a user's password.""" update_data = { "password": "new_password_456" } response = client.patch( f"/users/{regular_user.id}", json=update_data, headers=auth_headers ) assert response.status_code == 200 # Verify password can be used for login login_response = client.post( "/token", data={"username": regular_user.name, "password": "new_password_456"} ) assert login_response.status_code == 200 def test_update_nonexistent_user(client, auth_headers): """Test updating a non-existent user.""" update_data = {"name": "updated"} response = client.patch("/users/99999", json=update_data, headers=auth_headers) assert response.status_code == 404 def test_delete_user(client, auth_headers, regular_user): """Test deleting a user.""" response = client.delete(f"/users/{regular_user.id}", headers=auth_headers) assert response.status_code == 200 assert "deleted successfully" in response.json()["message"].lower() # Verify user is deleted response = client.get(f"/users/{regular_user.id}", headers=auth_headers) assert response.status_code == 404 def test_delete_nonexistent_user(client, auth_headers): """Test deleting a non-existent user.""" response = client.delete("/users/99999", headers=auth_headers) assert response.status_code == 404 def test_user_operations_by_non_admin(client, user_auth_headers): """Test that non-admin users cannot perform admin operations.""" # Try to create a user response = client.post( "/users/", json={"name": "test", "password": "pass"}, headers=user_auth_headers ) assert response.status_code == 403 # Try to get users response = client.get("/users/", headers=user_auth_headers) assert response.status_code == 403 # Try to delete the admin user (if ID is known) # This would require knowing the admin user ID # response = client.delete(f"/users/{admin_id}", headers=user_auth_headers) # assert response.status_code == 403