🔧 fix(test_custom_component.py): fix import statements and formatting issues in test_custom_component.py
✨ feat(test_custom_component.py): add tests for list_flows, build_config methods in CustomComponent class 🔧 fix(test_custom_component.py): fix formatting issues in test_list_flows_multiple_queries test ✨ feat(test_custom_component.py): add tests for list_flows, build_config methods in CustomComponent class ✨ feat(test_custom_component.py): add test for return type of list_flows method in CustomComponent class ✨ feat(test_custom_component.py): add test for return type of build_config method in CustomComponent class ✨ feat(test_custom_component.py): add test for presence of 'fields' key in build_config method in CustomComponent class ✨ feat(test_custom_component.py): add test for type of 'fields' value in build_config method in CustomComponent class ✨ feat(test_custom_component.py): add test for type of keys in 'fields' value in build_config method in CustomComponent class ✨ feat(test_custom_component.py): add test for type of values in 'fields' value in build_config method in CustomComponent class
This commit is contained in:
parent
a89a9a3267
commit
d5ee293590
1 changed files with 115 additions and 31 deletions
|
|
@ -1,9 +1,12 @@
|
||||||
import ast
|
import ast
|
||||||
import pytest
|
import pytest
|
||||||
import types
|
import types
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
from unittest.mock import patch, MagicMock
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
from langflow.database.models.flow import Flow, FlowCreate
|
||||||
from langflow.interface.custom.base import CustomComponent
|
from langflow.interface.custom.base import CustomComponent
|
||||||
from langflow.interface.custom.component import (
|
from langflow.interface.custom.component import (
|
||||||
Component,
|
Component,
|
||||||
|
|
@ -57,7 +60,8 @@ def test_code_parser_get_tree():
|
||||||
|
|
||||||
def test_code_parser_syntax_error():
|
def test_code_parser_syntax_error():
|
||||||
"""
|
"""
|
||||||
Test the __get_tree method raises the CodeSyntaxError when given incorrect syntax.
|
Test the __get_tree method raises the
|
||||||
|
CodeSyntaxError when given incorrect syntax.
|
||||||
"""
|
"""
|
||||||
code_syntax_error = "zzz import os"
|
code_syntax_error = "zzz import os"
|
||||||
|
|
||||||
|
|
@ -86,7 +90,8 @@ def test_component_get_code_tree():
|
||||||
|
|
||||||
def test_component_code_null_error():
|
def test_component_code_null_error():
|
||||||
"""
|
"""
|
||||||
Test the get_function method raises the ComponentCodeNullError when the code is empty.
|
Test the get_function method raises the
|
||||||
|
ComponentCodeNullError when the code is empty.
|
||||||
"""
|
"""
|
||||||
component = Component(code="", function_entrypoint_name="")
|
component = Component(code="", function_entrypoint_name="")
|
||||||
with pytest.raises(ComponentCodeNullError):
|
with pytest.raises(ComponentCodeNullError):
|
||||||
|
|
@ -140,7 +145,8 @@ def test_custom_component_get_function():
|
||||||
|
|
||||||
def test_code_parser_parse_imports_import():
|
def test_code_parser_parse_imports_import():
|
||||||
"""
|
"""
|
||||||
Test the parse_imports method of the CodeParser class with an import statement.
|
Test the parse_imports method of the CodeParser
|
||||||
|
class with an import statement.
|
||||||
"""
|
"""
|
||||||
parser = CodeParser(code_default)
|
parser = CodeParser(code_default)
|
||||||
tree = parser._CodeParser__get_tree()
|
tree = parser._CodeParser__get_tree()
|
||||||
|
|
@ -152,7 +158,8 @@ def test_code_parser_parse_imports_import():
|
||||||
|
|
||||||
def test_code_parser_parse_imports_importfrom():
|
def test_code_parser_parse_imports_importfrom():
|
||||||
"""
|
"""
|
||||||
Test the parse_imports method of the CodeParser class with an import from statement.
|
Test the parse_imports method of the CodeParser
|
||||||
|
class with an import from statement.
|
||||||
"""
|
"""
|
||||||
parser = CodeParser("from os import path")
|
parser = CodeParser("from os import path")
|
||||||
tree = parser._CodeParser__get_tree()
|
tree = parser._CodeParser__get_tree()
|
||||||
|
|
@ -203,16 +210,18 @@ def test_code_parser_parse_global_vars():
|
||||||
|
|
||||||
def test_component_get_function_valid():
|
def test_component_get_function_valid():
|
||||||
"""
|
"""
|
||||||
Test the get_function method of the Component class with valid code and function_entrypoint_name.
|
Test the get_function method of the Component
|
||||||
|
class with valid code and function_entrypoint_name.
|
||||||
"""
|
"""
|
||||||
component = Component(code="def build(): pass", function_entrypoint_name="build")
|
component = Component(code="def build(): pass", function_entrypoint_name="build")
|
||||||
function = component.get_function()
|
my_function = component.get_function()
|
||||||
assert callable(function)
|
assert callable(my_function)
|
||||||
|
|
||||||
|
|
||||||
def test_custom_component_get_function_entrypoint_args():
|
def test_custom_component_get_function_entrypoint_args():
|
||||||
"""
|
"""
|
||||||
Test the get_function_entrypoint_args property of the CustomComponent class.
|
Test the get_function_entrypoint_args
|
||||||
|
property of the CustomComponent class.
|
||||||
"""
|
"""
|
||||||
custom_component = CustomComponent(
|
custom_component = CustomComponent(
|
||||||
code=code_default, function_entrypoint_name="build"
|
code=code_default, function_entrypoint_name="build"
|
||||||
|
|
@ -226,7 +235,8 @@ def test_custom_component_get_function_entrypoint_args():
|
||||||
|
|
||||||
def test_custom_component_get_function_entrypoint_return_type():
|
def test_custom_component_get_function_entrypoint_return_type():
|
||||||
"""
|
"""
|
||||||
Test the get_function_entrypoint_return_type property of the CustomComponent class.
|
Test the get_function_entrypoint_return_type
|
||||||
|
property of the CustomComponent class.
|
||||||
"""
|
"""
|
||||||
custom_component = CustomComponent(
|
custom_component = CustomComponent(
|
||||||
code=code_default, function_entrypoint_name="build"
|
code=code_default, function_entrypoint_name="build"
|
||||||
|
|
@ -248,7 +258,8 @@ def test_custom_component_get_main_class_name():
|
||||||
|
|
||||||
def test_custom_component_get_function_valid():
|
def test_custom_component_get_function_valid():
|
||||||
"""
|
"""
|
||||||
Test the get_function property of the CustomComponent class with valid code and function_entrypoint_name.
|
Test the get_function property of the CustomComponent
|
||||||
|
class with valid code and function_entrypoint_name.
|
||||||
"""
|
"""
|
||||||
custom_component = CustomComponent(
|
custom_component = CustomComponent(
|
||||||
code="def build(): pass", function_entrypoint_name="build"
|
code="def build(): pass", function_entrypoint_name="build"
|
||||||
|
|
@ -281,7 +292,8 @@ def test_code_parser_parse_arg_with_annotation():
|
||||||
|
|
||||||
def test_code_parser_parse_callable_details_no_args():
|
def test_code_parser_parse_callable_details_no_args():
|
||||||
"""
|
"""
|
||||||
Test the parse_callable_details method of the CodeParser class with a function with no arguments.
|
Test the parse_callable_details method of the
|
||||||
|
CodeParser class with a function with no arguments.
|
||||||
"""
|
"""
|
||||||
parser = CodeParser("")
|
parser = CodeParser("")
|
||||||
node = ast.FunctionDef(
|
node = ast.FunctionDef(
|
||||||
|
|
@ -328,7 +340,8 @@ def test_code_parser_parse_ann_assign():
|
||||||
|
|
||||||
def test_code_parser_parse_function_def_not_init():
|
def test_code_parser_parse_function_def_not_init():
|
||||||
"""
|
"""
|
||||||
Test the parse_function_def method of the CodeParser class with a function that is not __init__.
|
Test the parse_function_def method of the
|
||||||
|
CodeParser class with a function that is not __init__.
|
||||||
"""
|
"""
|
||||||
parser = CodeParser("")
|
parser = CodeParser("")
|
||||||
stmt = ast.FunctionDef(
|
stmt = ast.FunctionDef(
|
||||||
|
|
@ -347,7 +360,8 @@ def test_code_parser_parse_function_def_not_init():
|
||||||
|
|
||||||
def test_code_parser_parse_function_def_init():
|
def test_code_parser_parse_function_def_init():
|
||||||
"""
|
"""
|
||||||
Test the parse_function_def method of the CodeParser class with an __init__ function.
|
Test the parse_function_def method of the
|
||||||
|
CodeParser class with an __init__ function.
|
||||||
"""
|
"""
|
||||||
parser = CodeParser("")
|
parser = CodeParser("")
|
||||||
stmt = ast.FunctionDef(
|
stmt = ast.FunctionDef(
|
||||||
|
|
@ -386,7 +400,8 @@ def test_custom_component_class_template_validation_no_code():
|
||||||
|
|
||||||
def test_custom_component_get_code_tree_syntax_error():
|
def test_custom_component_get_code_tree_syntax_error():
|
||||||
"""
|
"""
|
||||||
Test the get_code_tree method of the CustomComponent class raises the CodeSyntaxError when given incorrect syntax.
|
Test the get_code_tree method of the CustomComponent class
|
||||||
|
raises the CodeSyntaxError when given incorrect syntax.
|
||||||
"""
|
"""
|
||||||
custom_component = CustomComponent(
|
custom_component = CustomComponent(
|
||||||
code="import os as", function_entrypoint_name="build"
|
code="import os as", function_entrypoint_name="build"
|
||||||
|
|
@ -397,7 +412,8 @@ def test_custom_component_get_code_tree_syntax_error():
|
||||||
|
|
||||||
def test_custom_component_get_function_entrypoint_args_no_args():
|
def test_custom_component_get_function_entrypoint_args_no_args():
|
||||||
"""
|
"""
|
||||||
Test the get_function_entrypoint_args property of the CustomComponent class with a build method with no arguments.
|
Test the get_function_entrypoint_args property of
|
||||||
|
the CustomComponent class with a build method with no arguments.
|
||||||
"""
|
"""
|
||||||
my_code = """
|
my_code = """
|
||||||
class MyMainClass(CustomComponent):
|
class MyMainClass(CustomComponent):
|
||||||
|
|
@ -426,7 +442,8 @@ class MyClass(CustomComponent):
|
||||||
|
|
||||||
def test_custom_component_get_main_class_name_no_main_class():
|
def test_custom_component_get_main_class_name_no_main_class():
|
||||||
"""
|
"""
|
||||||
Test the get_main_class_name property of the CustomComponent class when there is no main class.
|
Test the get_main_class_name property of the
|
||||||
|
CustomComponent class when there is no main class.
|
||||||
"""
|
"""
|
||||||
my_code = """
|
my_code = """
|
||||||
def build():
|
def build():
|
||||||
|
|
@ -439,7 +456,8 @@ def build():
|
||||||
|
|
||||||
def test_custom_component_build_not_implemented():
|
def test_custom_component_build_not_implemented():
|
||||||
"""
|
"""
|
||||||
Test the build method of the CustomComponent class raises the NotImplementedError.
|
Test the build method of the CustomComponent
|
||||||
|
class raises the NotImplementedError.
|
||||||
"""
|
"""
|
||||||
custom_component = CustomComponent(
|
custom_component = CustomComponent(
|
||||||
code="def build(): pass", function_entrypoint_name="build"
|
code="def build(): pass", function_entrypoint_name="build"
|
||||||
|
|
@ -469,21 +487,87 @@ def test_build_config_no_code():
|
||||||
assert component.get_function_entrypoint_return_type == ""
|
assert component.get_function_entrypoint_return_type == ""
|
||||||
|
|
||||||
|
|
||||||
def test_list_flows_multiple_queries():
|
@pytest.fixture
|
||||||
mock_flow_1 = MagicMock()
|
def component():
|
||||||
mock_flow_2 = MagicMock()
|
return CustomComponent(
|
||||||
|
field_config={
|
||||||
|
"fields": {
|
||||||
|
"llm": {"type": "str"},
|
||||||
|
"url": {"type": "str"},
|
||||||
|
"year": {"type": "int"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
session_getter_module = "langflow.database.base.session_getter"
|
|
||||||
|
|
||||||
with patch(session_getter_module) as mock_session_getter:
|
@pytest.fixture(scope="session")
|
||||||
mock_session = MagicMock()
|
def test_flow(db):
|
||||||
mock_session.query.return_value.all.side_effect = [[mock_flow_1], [mock_flow_2]]
|
flow_data = {
|
||||||
mock_session_getter.return_value.__enter__.return_value = mock_session
|
"nodes": [{"id": "1"}, {"id": "2"}],
|
||||||
|
"edges": [{"source": "1", "target": "2"}],
|
||||||
|
}
|
||||||
|
|
||||||
component = CustomComponent()
|
# Create flow
|
||||||
result = component.list_flows()
|
flow = FlowCreate(
|
||||||
|
id=uuid4(), name="Test Flow", description="Fixture flow", data=flow_data
|
||||||
|
)
|
||||||
|
|
||||||
# Only the result of the second query is returned
|
# Add to database
|
||||||
assert len(result) == 1
|
db.add(flow)
|
||||||
assert result[0] == mock_flow_2
|
db.commit()
|
||||||
assert mock_session.query.call_count == 2
|
|
||||||
|
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_list_flows_flow_objects(component):
|
||||||
|
flows = component.list_flows()
|
||||||
|
assert all(isinstance(flow, Flow) for flow in flows)
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_config_return_type(component):
|
||||||
|
config = component.build_config()
|
||||||
|
assert isinstance(config, dict)
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_config_has_fields(component):
|
||||||
|
config = component.build_config()
|
||||||
|
assert "fields" in config
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_config_fields_dict(component):
|
||||||
|
config = component.build_config()
|
||||||
|
assert isinstance(config["fields"], dict)
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_config_field_keys(component):
|
||||||
|
config = component.build_config()
|
||||||
|
assert all(isinstance(key, str) for key in config["fields"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_config_field_values_dict(component):
|
||||||
|
config = component.build_config()
|
||||||
|
assert all(isinstance(value, dict) for value in config["fields"].values())
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_config_field_value_keys(component):
|
||||||
|
config = component.build_config()
|
||||||
|
field_values = config["fields"].values()
|
||||||
|
assert all("type" in value for value in field_values)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue