tests: update tests to use httpx.AsyncClient (#3984)
* Add async support and dependencies to pyproject.toml files - Added `asgi-lifespan>=2.1.0` to dependencies. - Configured `asyncio_mode` and `asyncio_default_fixture_loop_scope` for pytest. - Updated `tool.uv` section with `asgi-lifespan` in dev-dependencies. * Convert test fixtures to async and use AsyncClient for HTTP requests * Handle 'ImportFrom' nodes in AST validation to support module attribute imports * Convert test cases to use async HTTP client - Updated test cases in `test_database.py`, `test_endpoints.py`, `test_user.py`, `test_variable.py`, `test_files.py`, `test_chat_endpoint.py`, `test_misc.py`, `test_messages_endpoints.py`, `test_api_key.py`, `test_webhook.py`, and `test_login.py` to use `httpx.AsyncClient` instead of `fastapi.TestClient`. - Modified test functions to be asynchronous and use `await` for HTTP requests. - Adjusted fixtures and helper functions to support asynchronous operations. - Ensured consistency in endpoint paths and request methods across all test cases. * Refactor string concatenation to f-string in test_chat_endpoint.py * [autofix.ci] apply automated fixes * Refactor import validation to use pattern matching for AST nodes * Set `startup_timeout` and `shutdown_timeout` to `None` in `LifespanManager` for test files. * Convert test functions to async in `test_messages_endpoints.py` * Add `api_key_required` marker to assistant component tests --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
7e3d470845
commit
6febae599b
19 changed files with 444 additions and 322 deletions
|
|
@ -1,6 +1,7 @@
|
|||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
from langflow.services.auth.utils import create_super_user, get_password_hash
|
||||
from langflow.services.database.models.user import UserUpdate
|
||||
|
|
@ -22,14 +23,14 @@ def super_user(client):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def super_user_headers(client, super_user):
|
||||
async def super_user_headers(client: AsyncClient, super_user):
|
||||
settings_service = get_settings_service()
|
||||
auth_settings = settings_service.auth_settings
|
||||
login_data = {
|
||||
"username": auth_settings.SUPERUSER,
|
||||
"password": auth_settings.SUPERUSER_PASSWORD,
|
||||
}
|
||||
response = client.post("/api/v1/login", data=login_data)
|
||||
response = await client.post("api/v1/login", data=login_data)
|
||||
assert response.status_code == 200
|
||||
tokens = response.json()
|
||||
a_token = tokens["access_token"]
|
||||
|
|
@ -52,9 +53,8 @@ def deactivated_user():
|
|||
return user
|
||||
|
||||
|
||||
def test_user_waiting_for_approval(
|
||||
client,
|
||||
):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_user_waiting_for_approval(client: AsyncClient):
|
||||
# Create a user that is not active and has never logged in
|
||||
with session_getter(get_db_service()) as session:
|
||||
user = User(
|
||||
|
|
@ -67,50 +67,54 @@ def test_user_waiting_for_approval(
|
|||
session.commit()
|
||||
|
||||
login_data = {"username": "waitingforapproval", "password": "testpassword"}
|
||||
response = client.post("/api/v1/login", data=login_data)
|
||||
response = await client.post("api/v1/login", data=login_data)
|
||||
assert response.status_code == 400
|
||||
assert response.json()["detail"] == "Waiting for approval"
|
||||
|
||||
|
||||
def test_deactivated_user_cannot_login(client, deactivated_user):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_deactivated_user_cannot_login(client: AsyncClient, deactivated_user):
|
||||
login_data = {"username": deactivated_user.username, "password": "testpassword"}
|
||||
response = client.post("/api/v1/login", data=login_data)
|
||||
response = await client.post("api/v1/login", data=login_data)
|
||||
assert response.status_code == 401, response.json()
|
||||
assert response.json()["detail"] == "Inactive user", response.text
|
||||
|
||||
|
||||
def test_deactivated_user_cannot_access(client, deactivated_user, logged_in_headers):
|
||||
async def test_deactivated_user_cannot_access(client: AsyncClient, deactivated_user, logged_in_headers):
|
||||
# Assuming the headers for deactivated_user
|
||||
response = client.get("/api/v1/users", headers=logged_in_headers)
|
||||
assert response.status_code == 403, response.json()
|
||||
response = await client.get("api/v1/users/", headers=logged_in_headers)
|
||||
assert response.status_code == 403, response.status_code
|
||||
assert response.json()["detail"] == "The user doesn't have enough privileges", response.text
|
||||
|
||||
|
||||
def test_data_consistency_after_update(client, active_user, logged_in_headers, super_user_headers):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_data_consistency_after_update(client: AsyncClient, active_user, logged_in_headers, super_user_headers):
|
||||
user_id = active_user.id
|
||||
update_data = UserUpdate(is_active=False)
|
||||
|
||||
response = client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=super_user_headers)
|
||||
response = await client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=super_user_headers)
|
||||
assert response.status_code == 200, response.json()
|
||||
|
||||
# Fetch the updated user from the database
|
||||
response = client.get("/api/v1/users/whoami", headers=logged_in_headers)
|
||||
response = await client.get("api/v1/users/whoami", headers=logged_in_headers)
|
||||
assert response.status_code == 401, response.json()
|
||||
assert response.json()["detail"] == "User not found or is inactive."
|
||||
|
||||
|
||||
def test_data_consistency_after_delete(client, test_user, super_user_headers):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_data_consistency_after_delete(client: AsyncClient, test_user, super_user_headers):
|
||||
user_id = test_user.get("id")
|
||||
response = client.delete(f"/api/v1/users/{user_id}", headers=super_user_headers)
|
||||
response = await client.delete(f"/api/v1/users/{user_id}", headers=super_user_headers)
|
||||
assert response.status_code == 200, response.json()
|
||||
|
||||
# Attempt to fetch the deleted user from the database
|
||||
response = client.get("/api/v1/users", headers=super_user_headers)
|
||||
response = await client.get("api/v1/users/", headers=super_user_headers)
|
||||
assert response.status_code == 200
|
||||
assert all(user["id"] != user_id for user in response.json()["users"])
|
||||
|
||||
|
||||
def test_inactive_user(client):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_inactive_user(client: AsyncClient):
|
||||
# Create a user that is not active and has a last_login_at value
|
||||
with session_getter(get_db_service()) as session:
|
||||
user = User(
|
||||
|
|
@ -123,12 +127,13 @@ def test_inactive_user(client):
|
|||
session.commit()
|
||||
|
||||
login_data = {"username": "inactiveuser", "password": "testpassword"}
|
||||
response = client.post("/api/v1/login", data=login_data)
|
||||
response = await client.post("api/v1/login", data=login_data)
|
||||
assert response.status_code == 401
|
||||
assert response.json()["detail"] == "Inactive user"
|
||||
|
||||
|
||||
def test_add_user(client, test_user):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_add_user(client: AsyncClient, test_user):
|
||||
assert test_user["username"] == "testuser"
|
||||
|
||||
|
||||
|
|
@ -136,51 +141,55 @@ def test_add_user(client, test_user):
|
|||
# def test_read_current_user(client: TestClient, active_user):
|
||||
# # First we need to login to get the access token
|
||||
# login_data = {"username": "testuser", "password": "testpassword"}
|
||||
# response = client.post("/api/v1/login", data=login_data)
|
||||
# response = await client.post("api/v1/login", data=login_data)
|
||||
# assert response.status_code == 200
|
||||
|
||||
# headers = {"Authorization": f"Bearer {response.json()['access_token']}"}
|
||||
|
||||
# response = client.get("/api/v1/user", headers=headers)
|
||||
# response = await client.get("api/v1/user", headers=headers)
|
||||
# assert response.status_code == 200, response.json()
|
||||
# assert response.json()["username"] == "testuser"
|
||||
|
||||
|
||||
def test_read_all_users(client, super_user_headers):
|
||||
response = client.get("/api/v1/users", headers=super_user_headers)
|
||||
@pytest.mark.api_key_required
|
||||
async def test_read_all_users(client: AsyncClient, super_user_headers):
|
||||
response = await client.get("api/v1/users/", headers=super_user_headers)
|
||||
assert response.status_code == 200, response.json()
|
||||
assert isinstance(response.json()["users"], list)
|
||||
|
||||
|
||||
def test_normal_user_cant_read_all_users(client, logged_in_headers):
|
||||
response = client.get("/api/v1/users", headers=logged_in_headers)
|
||||
@pytest.mark.api_key_required
|
||||
async def test_normal_user_cant_read_all_users(client: AsyncClient, logged_in_headers):
|
||||
response = await client.get("api/v1/users/", headers=logged_in_headers)
|
||||
assert response.status_code == 403, response.json()
|
||||
assert response.json() == {"detail": "The user doesn't have enough privileges"}
|
||||
|
||||
|
||||
def test_patch_user(client, active_user, logged_in_headers):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_patch_user(client: AsyncClient, active_user, logged_in_headers):
|
||||
user_id = active_user.id
|
||||
update_data = UserUpdate(
|
||||
username="newname",
|
||||
)
|
||||
|
||||
response = client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=logged_in_headers)
|
||||
response = await client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=logged_in_headers)
|
||||
assert response.status_code == 200, response.json()
|
||||
update_data = UserUpdate(
|
||||
profile_image="new_image",
|
||||
)
|
||||
|
||||
response = client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=logged_in_headers)
|
||||
response = await client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=logged_in_headers)
|
||||
assert response.status_code == 200, response.json()
|
||||
|
||||
|
||||
def test_patch_reset_password(client, active_user, logged_in_headers):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_patch_reset_password(client: AsyncClient, active_user, logged_in_headers):
|
||||
user_id = active_user.id
|
||||
update_data = UserUpdate(
|
||||
password="newpassword",
|
||||
)
|
||||
|
||||
response = client.patch(
|
||||
response = await client.patch(
|
||||
f"/api/v1/users/{user_id}/reset-password",
|
||||
json=update_data.model_dump(),
|
||||
headers=logged_in_headers,
|
||||
|
|
@ -188,17 +197,18 @@ def test_patch_reset_password(client, active_user, logged_in_headers):
|
|||
assert response.status_code == 200, response.json()
|
||||
# Now we need to test if the new password works
|
||||
login_data = {"username": active_user.username, "password": "newpassword"}
|
||||
response = client.post("/api/v1/login", data=login_data)
|
||||
response = await client.post("api/v1/login", data=login_data)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_patch_user_wrong_id(client, active_user, logged_in_headers):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_patch_user_wrong_id(client: AsyncClient, active_user, logged_in_headers):
|
||||
user_id = "wrong_id"
|
||||
update_data = UserUpdate(
|
||||
username="newname",
|
||||
)
|
||||
|
||||
response = client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=logged_in_headers)
|
||||
response = await client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=logged_in_headers)
|
||||
assert response.status_code == 422, response.json()
|
||||
json_response = response.json()
|
||||
detail = json_response["detail"]
|
||||
|
|
@ -207,16 +217,18 @@ def test_patch_user_wrong_id(client, active_user, logged_in_headers):
|
|||
assert error["type"] == "uuid_parsing"
|
||||
|
||||
|
||||
def test_delete_user(client, test_user, super_user_headers):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_delete_user(client: AsyncClient, test_user, super_user_headers):
|
||||
user_id = test_user["id"]
|
||||
response = client.delete(f"/api/v1/users/{user_id}", headers=super_user_headers)
|
||||
response = await client.delete(f"/api/v1/users/{user_id}", headers=super_user_headers)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"detail": "User deleted"}
|
||||
|
||||
|
||||
def test_delete_user_wrong_id(client, test_user, super_user_headers):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_delete_user_wrong_id(client: AsyncClient, test_user, super_user_headers):
|
||||
user_id = "wrong_id"
|
||||
response = client.delete(f"/api/v1/users/{user_id}", headers=super_user_headers)
|
||||
response = await client.delete(f"/api/v1/users/{user_id}", headers=super_user_headers)
|
||||
assert response.status_code == 422
|
||||
json_response = response.json()
|
||||
detail = json_response["detail"]
|
||||
|
|
@ -225,8 +237,9 @@ def test_delete_user_wrong_id(client, test_user, super_user_headers):
|
|||
assert error["type"] == "uuid_parsing"
|
||||
|
||||
|
||||
def test_normal_user_cant_delete_user(client, test_user, logged_in_headers):
|
||||
@pytest.mark.api_key_required
|
||||
async def test_normal_user_cant_delete_user(client: AsyncClient, test_user, logged_in_headers):
|
||||
user_id = test_user["id"]
|
||||
response = client.delete(f"/api/v1/users/{user_id}", headers=logged_in_headers)
|
||||
response = await client.delete(f"/api/v1/users/{user_id}", headers=logged_in_headers)
|
||||
assert response.status_code == 403
|
||||
assert response.json() == {"detail": "The user doesn't have enough privileges"}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue