mirror of
https://github.com/langgenius/dify.git
synced 2026-05-04 09:28:04 +08:00
Merge remote-tracking branch 'origin/main' into feat/trigger
This commit is contained in:
@ -58,6 +58,7 @@ def setup_account(request) -> Generator[Account, None, None]:
|
||||
name=name,
|
||||
password=secrets.token_hex(16),
|
||||
ip_address="localhost",
|
||||
language="en-US",
|
||||
)
|
||||
|
||||
with _CACHED_APP.test_request_context():
|
||||
|
||||
@ -2299,6 +2299,7 @@ class TestRegisterService:
|
||||
name=admin_name,
|
||||
password=admin_password,
|
||||
ip_address=ip_address,
|
||||
language="en-US",
|
||||
)
|
||||
|
||||
# Verify account was created
|
||||
@ -2348,6 +2349,7 @@ class TestRegisterService:
|
||||
name=admin_name,
|
||||
password=admin_password,
|
||||
ip_address=ip_address,
|
||||
language="en-US",
|
||||
)
|
||||
|
||||
# Verify no entities were created (rollback worked)
|
||||
|
||||
@ -6,6 +6,7 @@ from faker import Faker
|
||||
from core.tools.entities.api_entities import ToolProviderApiEntity
|
||||
from core.tools.entities.common_entities import I18nObject
|
||||
from core.tools.entities.tool_entities import ToolProviderType
|
||||
from libs.uuid_utils import uuidv7
|
||||
from models.tools import ApiToolProvider, BuiltinToolProvider, MCPToolProvider, WorkflowToolProvider
|
||||
from services.plugin.plugin_service import PluginService
|
||||
from services.tools.tools_transform_service import ToolTransformService
|
||||
@ -67,6 +68,7 @@ class TestToolTransformService:
|
||||
)
|
||||
elif provider_type == "workflow":
|
||||
provider = WorkflowToolProvider(
|
||||
id=str(uuidv7()),
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
@ -759,6 +761,7 @@ class TestToolTransformService:
|
||||
|
||||
# Create workflow tool provider
|
||||
provider = WorkflowToolProvider(
|
||||
id=str(uuidv7()),
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
|
||||
@ -109,3 +109,83 @@ def test_parse_openapi_to_tool_bundle_properties_all_of(app):
|
||||
assert tool_bundles[0].parameters[0].llm_description == "desc prop1"
|
||||
# TODO: support enum in OpenAPI
|
||||
# assert set(tool_bundles[0].parameters[0].options) == {"option1", "option2", "option3"}
|
||||
|
||||
|
||||
def test_parse_openapi_to_tool_bundle_default_value_type_casting(app):
|
||||
"""
|
||||
Test that default values are properly cast to match parameter types.
|
||||
This addresses the issue where array default values like [] cause validation errors
|
||||
when parameter type is inferred as string/number/boolean.
|
||||
"""
|
||||
openapi = {
|
||||
"openapi": "3.0.0",
|
||||
"info": {"title": "Test API", "version": "1.0.0"},
|
||||
"servers": [{"url": "https://example.com"}],
|
||||
"paths": {
|
||||
"/product/create": {
|
||||
"post": {
|
||||
"operationId": "createProduct",
|
||||
"summary": "Create a product",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"categories": {
|
||||
"description": "List of category identifiers",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"name": {
|
||||
"description": "Product name",
|
||||
"default": "Default Product",
|
||||
"type": "string",
|
||||
},
|
||||
"price": {"description": "Product price", "default": 0.0, "type": "number"},
|
||||
"available": {
|
||||
"description": "Product availability",
|
||||
"default": True,
|
||||
"type": "boolean",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {"200": {"description": "Default Response"}},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
with app.test_request_context():
|
||||
tool_bundles = ApiBasedToolSchemaParser.parse_openapi_to_tool_bundle(openapi)
|
||||
|
||||
assert len(tool_bundles) == 1
|
||||
bundle = tool_bundles[0]
|
||||
assert len(bundle.parameters) == 4
|
||||
|
||||
# Find parameters by name
|
||||
params_by_name = {param.name: param for param in bundle.parameters}
|
||||
|
||||
# Check categories parameter (array type with [] default)
|
||||
categories_param = params_by_name["categories"]
|
||||
assert categories_param.type == "array" # Will be detected by _get_tool_parameter_type
|
||||
assert categories_param.default is None # Array default [] is converted to None
|
||||
|
||||
# Check name parameter (string type with string default)
|
||||
name_param = params_by_name["name"]
|
||||
assert name_param.type == "string"
|
||||
assert name_param.default == "Default Product"
|
||||
|
||||
# Check price parameter (number type with number default)
|
||||
price_param = params_by_name["price"]
|
||||
assert price_param.type == "number"
|
||||
assert price_param.default == 0.0
|
||||
|
||||
# Check available parameter (boolean type with boolean default)
|
||||
available_param = params_by_name["available"]
|
||||
assert available_param.type == "boolean"
|
||||
assert available_param.default is True
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
from constants import COOKIE_NAME_ACCESS_TOKEN
|
||||
from libs.token import extract_access_token
|
||||
from constants import COOKIE_NAME_ACCESS_TOKEN, COOKIE_NAME_WEBAPP_ACCESS_TOKEN
|
||||
from libs.token import extract_access_token, extract_webapp_access_token
|
||||
|
||||
|
||||
class MockRequest:
|
||||
@ -14,10 +14,12 @@ def test_extract_access_token():
|
||||
return MockRequest(headers, cookies, args)
|
||||
|
||||
test_cases = [
|
||||
(_mock_request({"Authorization": "Bearer 123"}, {}, {}), "123"),
|
||||
(_mock_request({}, {COOKIE_NAME_ACCESS_TOKEN: "123"}, {}), "123"),
|
||||
(_mock_request({}, {}, {}), None),
|
||||
(_mock_request({"Authorization": "Bearer_aaa 123"}, {}, {}), None),
|
||||
(_mock_request({"Authorization": "Bearer 123"}, {}, {}), "123", "123"),
|
||||
(_mock_request({}, {COOKIE_NAME_ACCESS_TOKEN: "123"}, {}), "123", None),
|
||||
(_mock_request({}, {}, {}), None, None),
|
||||
(_mock_request({"Authorization": "Bearer_aaa 123"}, {}, {}), None, None),
|
||||
(_mock_request({}, {COOKIE_NAME_WEBAPP_ACCESS_TOKEN: "123"}, {}), None, "123"),
|
||||
]
|
||||
for request, expected in test_cases:
|
||||
assert extract_access_token(request) == expected # pyright: ignore[reportArgumentType]
|
||||
for request, expected_console, expected_webapp in test_cases:
|
||||
assert extract_access_token(request) == expected_console # pyright: ignore[reportArgumentType]
|
||||
assert extract_webapp_access_token(request) == expected_webapp # pyright: ignore[reportArgumentType]
|
||||
|
||||
@ -893,7 +893,7 @@ class TestRegisterService:
|
||||
mock_dify_setup.return_value = mock_dify_setup_instance
|
||||
|
||||
# Execute test
|
||||
RegisterService.setup("admin@example.com", "Admin User", "password123", "192.168.1.1")
|
||||
RegisterService.setup("admin@example.com", "Admin User", "password123", "192.168.1.1", "en-US")
|
||||
|
||||
# Verify results
|
||||
mock_create_account.assert_called_once_with(
|
||||
@ -925,6 +925,7 @@ class TestRegisterService:
|
||||
"Admin User",
|
||||
"password123",
|
||||
"192.168.1.1",
|
||||
"en-US",
|
||||
)
|
||||
|
||||
# Verify rollback operations were called
|
||||
|
||||
Reference in New Issue
Block a user