tests: update env.py and conftest so tests use unique databases (#3654)
* Refactor Alembic environment script to simplify database connection logic and remove unused imports * Refactor test client fixture to use TemporaryDirectory and UUID for database path * Add `reload_engine` method to reinitialize the database engine * Add cleanup steps to test fixtures to ensure proper resource management - Added cleanup steps to various pytest fixtures to ensure temporary directories, database entries, and other resources are properly cleaned up after tests. - Modified fixtures to use `yield` for better resource management. - Ensured database connections are closed and tables are dropped after tests. - Improved temporary directory handling with context managers. * Add unit test to verify return type of list_flows method in custom component * Refactor tests in `test_custom_component.py` to remove unused imports and fixtures, and update existing fixtures for consistency. * Add debug checks for user existence in `test_user_waiting_for_approval` test * Fix import order and add flow_id validation in transaction handling - Corrected the import order in `utils.py`. - Added validation for `flow_id` in the transaction handling logic to ensure it is set correctly. * Add function to delete transactions by flow ID in CRUD module * Add cleanup for transactions and vertex builds in test teardown - Introduced `_delete_transactions_and_vertex_builds` function to remove transactions and vertex builds associated with a user. - Updated `user` fixture to call the new cleanup function before deleting the user. * Refactor flow_id assignment logic in `utils.py` to improve readability and correctness * [autofix.ci] apply automated fixes * Refactor test to use pytest's tmp_path fixture for temporary directory creation * Convert `test_user_waiting_for_approval` to an async test function --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
4e36dcc2ad
commit
2adda780c9
9 changed files with 179 additions and 149 deletions
|
|
@ -1,6 +1,3 @@
|
|||
from pathlib import Path
|
||||
from tempfile import tempdir
|
||||
|
||||
import pytest
|
||||
|
||||
from langflow.__main__ import app
|
||||
|
|
@ -15,13 +12,9 @@ def default_settings():
|
|||
]
|
||||
|
||||
|
||||
def test_components_path(runner, client, default_settings):
|
||||
# Create a foldr in the tmp directory
|
||||
|
||||
temp_dir = Path(tempdir)
|
||||
def test_components_path(runner, client, default_settings, tmp_path):
|
||||
# create a "components" folder
|
||||
temp_dir = temp_dir / "components"
|
||||
temp_dir.mkdir(exist_ok=True)
|
||||
temp_dir = tmp_path / "components"
|
||||
|
||||
result = runner.invoke(
|
||||
app,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import ast
|
||||
import types
|
||||
from textwrap import dedent
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from langchain_core.documents import Document
|
||||
|
|
@ -10,8 +9,6 @@ from langflow.custom import Component, CustomComponent
|
|||
from langflow.custom.code_parser.code_parser import CodeParser, CodeSyntaxError
|
||||
from langflow.custom.custom_component.base_component import BaseComponent, ComponentCodeNullError
|
||||
from langflow.custom.utils import build_custom_component_template
|
||||
from langflow.services.database.models.flow import FlowCreate
|
||||
from langflow.services.settings.feature_flags import FEATURE_FLAGS
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -460,9 +457,8 @@ def test_build_config_no_code():
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def component(client, active_user):
|
||||
return CustomComponent(
|
||||
user_id=active_user.id,
|
||||
def component():
|
||||
yield CustomComponent(
|
||||
field_config={
|
||||
"fields": {
|
||||
"llm": {"type": "str"},
|
||||
|
|
@ -473,41 +469,6 @@ def component(client, active_user):
|
|||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def test_flow(db):
|
||||
flow_data = {
|
||||
"nodes": [{"id": "1"}, {"id": "2"}],
|
||||
"edges": [{"source": "1", "target": "2"}],
|
||||
}
|
||||
|
||||
# Create flow
|
||||
flow = FlowCreate(id=uuid4(), name="Test Flow", description="Fixture flow", data=flow_data)
|
||||
|
||||
# Add to database
|
||||
db.add(flow)
|
||||
db.commit()
|
||||
|
||||
yield flow
|
||||
|
||||
# Clean up
|
||||
db.delete(flow)
|
||||
db.commit()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def db(app):
|
||||
# Setup database for tests
|
||||
yield app.db
|
||||
|
||||
# Teardown
|
||||
app.db.drop_all()
|
||||
|
||||
|
||||
def test_list_flows_return_type(component):
|
||||
flows = component.list_flows()
|
||||
assert isinstance(flows, list)
|
||||
|
||||
|
||||
def test_build_config_return_type(component):
|
||||
config = component.build_config()
|
||||
assert isinstance(config, dict)
|
||||
|
|
@ -539,19 +500,11 @@ def test_build_config_field_value_keys(component):
|
|||
assert all("type" in value for value in field_values)
|
||||
|
||||
|
||||
def test_custom_component_multiple_outputs(code_component_with_multiple_outputs, active_user):
|
||||
frontnd_node_dict, _ = build_custom_component_template(code_component_with_multiple_outputs, active_user.id)
|
||||
def test_custom_component_multiple_outputs(code_component_with_multiple_outputs):
|
||||
frontnd_node_dict, _ = build_custom_component_template(code_component_with_multiple_outputs)
|
||||
assert frontnd_node_dict["outputs"][0]["types"] == ["Text"]
|
||||
|
||||
|
||||
def test_feature_flags_add_toolkit_output(active_user, code_component_with_multiple_outputs):
|
||||
frontnd_node_dict, _ = build_custom_component_template(code_component_with_multiple_outputs, active_user.id)
|
||||
len_outputs = len(frontnd_node_dict["outputs"])
|
||||
FEATURE_FLAGS.add_toolkit_output = True
|
||||
frontnd_node_dict, _ = build_custom_component_template(code_component_with_multiple_outputs, active_user.id)
|
||||
assert len(frontnd_node_dict["outputs"]) == len_outputs + 1
|
||||
|
||||
|
||||
def test_custom_component_subclass_from_lctoolcomponent():
|
||||
# Import LCToolComponent and create a subclass
|
||||
code = dedent("""
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
import pytest
|
||||
|
||||
from langflow.custom import Component
|
||||
from langflow.custom.custom_component.custom_component import CustomComponent
|
||||
from langflow.custom.utils import build_custom_component_template
|
||||
from langflow.field_typing.constants import Data
|
||||
from langflow.services.settings.feature_flags import FEATURE_FLAGS
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def code_component_with_multiple_outputs():
|
||||
with open("src/backend/tests/data/component_multiple_outputs.py") as f:
|
||||
code = f.read()
|
||||
return Component(_code=code)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -23,3 +33,16 @@ def test_list_flows_flow_objects(component):
|
|||
are_flows = [isinstance(flow, Data) for flow in flows]
|
||||
flow_types = [type(flow) for flow in flows]
|
||||
assert all(are_flows), f"Expected all flows to be Data objects, got {flow_types}"
|
||||
|
||||
|
||||
def test_list_flows_return_type(component):
|
||||
flows = component.list_flows()
|
||||
assert isinstance(flows, list)
|
||||
|
||||
|
||||
def test_feature_flags_add_toolkit_output(active_user, code_component_with_multiple_outputs):
|
||||
frontnd_node_dict, _ = build_custom_component_template(code_component_with_multiple_outputs, active_user.id)
|
||||
len_outputs = len(frontnd_node_dict["outputs"])
|
||||
FEATURE_FLAGS.add_toolkit_output = True
|
||||
frontnd_node_dict, _ = build_custom_component_template(code_component_with_multiple_outputs, active_user.id)
|
||||
assert len(frontnd_node_dict["outputs"]) == len_outputs + 1
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from datetime import datetime
|
|||
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
from sqlmodel import select
|
||||
|
||||
from langflow.services.auth.utils import create_super_user, get_password_hash
|
||||
from langflow.services.database.models.user import UserUpdate
|
||||
|
|
@ -53,13 +54,23 @@ def deactivated_user():
|
|||
return user
|
||||
|
||||
|
||||
@pytest.mark.api_key_required
|
||||
async def test_user_waiting_for_approval(client: AsyncClient):
|
||||
async def test_user_waiting_for_approval(client):
|
||||
username = "waitingforapproval"
|
||||
password = "testpassword"
|
||||
|
||||
# Debug: Check if the user already exists
|
||||
with session_getter(get_db_service()) as session:
|
||||
existing_user = session.exec(select(User).where(User.username == username)).first()
|
||||
if existing_user:
|
||||
pytest.fail(
|
||||
f"User {username} already exists before the test. Database URL: {get_db_service().database_url}"
|
||||
)
|
||||
|
||||
# Create a user that is not active and has never logged in
|
||||
with session_getter(get_db_service()) as session:
|
||||
user = User(
|
||||
username="waitingforapproval",
|
||||
password=get_password_hash("testpassword"),
|
||||
username=username,
|
||||
password=get_password_hash(password),
|
||||
is_active=False,
|
||||
last_login_at=None,
|
||||
)
|
||||
|
|
@ -71,6 +82,14 @@ async def test_user_waiting_for_approval(client: AsyncClient):
|
|||
assert response.status_code == 400
|
||||
assert response.json()["detail"] == "Waiting for approval"
|
||||
|
||||
# Debug: Check if the user still exists after the test
|
||||
with session_getter(get_db_service()) as session:
|
||||
existing_user = session.exec(select(User).where(User.username == username)).first()
|
||||
if existing_user:
|
||||
print(f"User {username} still exists after the test. This is expected.")
|
||||
else:
|
||||
pytest.fail(f"User {username} does not exist after the test. This is unexpected.")
|
||||
|
||||
|
||||
@pytest.mark.api_key_required
|
||||
async def test_deactivated_user_cannot_login(client: AsyncClient, deactivated_user):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue