test: Type test (#40371)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Asuka Minato
2026-08-10 11:13:17 +09:00
committed by GitHub
parent a7156a0702
commit 883944d289
19 changed files with 97 additions and 89 deletions
@@ -335,7 +335,7 @@ def test_normalize_wrapper_index_rejects_unstable_values(value):
assert _normalize_wrapper_index(value) is None
def test_parent_workflow_can_publish_span_context_keeps_unknown_parent_retryable(monkeypatch):
def test_parent_workflow_can_publish_span_context_keeps_unknown_parent_retryable(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(
"dify_trace_arize_phoenix.arize_phoenix_trace.db.session.query",
lambda model: _FakeQuery(None),
@@ -344,7 +344,7 @@ def test_parent_workflow_can_publish_span_context_keeps_unknown_parent_retryable
assert _parent_workflow_can_publish_span_context("missing-run") is True
def test_parent_workflow_can_publish_span_context_checks_parent_app_tracing(monkeypatch):
def test_parent_workflow_can_publish_span_context_checks_parent_app_tracing(monkeypatch: pytest.MonkeyPatch):
parent_run = SimpleNamespace(app_id="parent-app")
parent_app = SimpleNamespace(tracing=json.dumps({"enabled": True, "tracing_provider": "phoenix"}))
@@ -21,7 +21,7 @@ def _sha256(token: str) -> str:
@pytest.fixture(autouse=True)
def disable_enterprise(monkeypatch):
def disable_enterprise(monkeypatch: pytest.MonkeyPatch):
"""Default to CE behaviour for /openapi/v1 tests. Tests that exercise the
EE branch override this with their own monkeypatch in-test."""
from configs import dify_config
@@ -97,7 +97,7 @@ def _mock_db_session_close(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(db.session, "close", MagicMock())
def test_execute_llm(monkeypatch):
def test_execute_llm(monkeypatch: pytest.MonkeyPatch):
node = init_llm_node(
config={
"id": "llm",
@@ -201,7 +201,7 @@ def test_execute_llm(monkeypatch):
assert item.node_run_result.outputs.get("usage", {})["total_tokens"] > 0
def test_execute_llm_with_jinja2(monkeypatch):
def test_execute_llm_with_jinja2(monkeypatch: pytest.MonkeyPatch):
"""
Test execute LLM node with jinja2
"""
@@ -365,7 +365,7 @@ def test_archive_workflow_runs_raises_click_exception_when_tenant_plan_fails(
)
def test_delete_archived_workflow_runs_keeps_single_page_behavior_without_all_pages(monkeypatch):
def test_delete_archived_workflow_runs_keeps_single_page_behavior_without_all_pages(monkeypatch: pytest.MonkeyPatch):
deleter = _patch_bundle_deleter(
monkeypatch,
[_delete_summary(processed=2, succeeded=2, next_catalog_id=_CURSOR_1)],
@@ -384,7 +384,7 @@ def test_delete_archived_workflow_runs_keeps_single_page_behavior_without_all_pa
assert deleter.delete_batch.call_args.kwargs["limit"] == 2
def test_delete_archived_workflow_runs_all_pages_continues_until_empty_page(monkeypatch):
def test_delete_archived_workflow_runs_all_pages_continues_until_empty_page(monkeypatch: pytest.MonkeyPatch):
deleter = _patch_bundle_deleter(
monkeypatch,
[
@@ -407,7 +407,9 @@ def test_delete_archived_workflow_runs_all_pages_continues_until_empty_page(monk
]
def test_delete_archived_workflow_runs_all_pages_fetches_empty_page_after_exact_full_page(monkeypatch):
def test_delete_archived_workflow_runs_all_pages_fetches_empty_page_after_exact_full_page(
monkeypatch: pytest.MonkeyPatch,
):
deleter = _patch_bundle_deleter(
monkeypatch,
[
@@ -426,7 +428,7 @@ def test_delete_archived_workflow_runs_all_pages_fetches_empty_page_after_exact_
assert deleter.delete_batch.call_args_list[1].kwargs["after_catalog_id"] == _CURSOR_1
def test_delete_archived_workflow_runs_all_pages_stops_at_first_failed_page(monkeypatch):
def test_delete_archived_workflow_runs_all_pages_stops_at_first_failed_page(monkeypatch: pytest.MonkeyPatch):
failed_result = BundleOperationResult(
catalog_id=_CURSOR_2,
bundle_id="bundle-failed",
@@ -455,7 +457,7 @@ def test_delete_archived_workflow_runs_all_pages_stops_at_first_failed_page(monk
assert f"resume_after_catalog_id={_CURSOR_1}" in result.output
def test_delete_archived_workflow_runs_all_pages_fails_when_cursor_does_not_advance(monkeypatch):
def test_delete_archived_workflow_runs_all_pages_fails_when_cursor_does_not_advance(monkeypatch: pytest.MonkeyPatch):
deleter = _patch_bundle_deleter(
monkeypatch,
[_delete_summary(processed=1, succeeded=1, next_catalog_id=None)],
@@ -471,7 +473,7 @@ def test_delete_archived_workflow_runs_all_pages_fails_when_cursor_does_not_adva
assert "cursor did not advance" in result.output.lower()
def test_delete_archived_workflow_runs_all_pages_uses_preview_cursor_for_dry_run(monkeypatch):
def test_delete_archived_workflow_runs_all_pages_uses_preview_cursor_for_dry_run(monkeypatch: pytest.MonkeyPatch):
deleter = _patch_bundle_deleter(
monkeypatch,
[
@@ -492,7 +494,9 @@ def test_delete_archived_workflow_runs_all_pages_uses_preview_cursor_for_dry_run
]
def test_delete_archived_workflow_runs_dry_run_failure_separates_preview_and_destructive_cursors(monkeypatch):
def test_delete_archived_workflow_runs_dry_run_failure_separates_preview_and_destructive_cursors(
monkeypatch: pytest.MonkeyPatch,
):
failed_result = BundleOperationResult(
catalog_id=_CURSOR_2,
bundle_id="bundle-failed",
@@ -535,7 +539,7 @@ def test_delete_archived_workflow_runs_dry_run_failure_separates_preview_and_des
assert f"destructive_retry_after_catalog_id={_CURSOR_0}" in result.output
def test_delete_archived_workflow_runs_all_pages_starts_after_explicit_cursor(monkeypatch):
def test_delete_archived_workflow_runs_all_pages_starts_after_explicit_cursor(monkeypatch: pytest.MonkeyPatch):
deleter = _patch_bundle_deleter(monkeypatch, [_delete_summary(processed=0)])
result = CliRunner().invoke(
@@ -577,7 +581,7 @@ def test_delete_archived_workflow_runs_rejects_invalid_run_shard_options(monkeyp
deleter.delete_batch.assert_not_called()
def test_delete_archived_workflow_runs_passes_formatted_run_shard_to_service(monkeypatch):
def test_delete_archived_workflow_runs_passes_formatted_run_shard_to_service(monkeypatch: pytest.MonkeyPatch):
deleter = _patch_bundle_deleter(monkeypatch, [_delete_summary(processed=0)])
result = CliRunner().invoke(
@@ -605,7 +609,7 @@ def test_delete_archived_workflow_runs_passes_formatted_run_shard_to_service(mon
assert deleter.delete_batch.call_args.kwargs["shard"] == "03-of-16"
def test_delete_archived_workflow_runs_rejects_mixed_catalog_shards_before_delete(monkeypatch):
def test_delete_archived_workflow_runs_rejects_mixed_catalog_shards_before_delete(monkeypatch: pytest.MonkeyPatch):
deleter = _patch_bundle_deleter(monkeypatch, [_delete_summary(processed=0)])
deleter.validate_catalog_shards.side_effect = ValueError("unexpected shards: 00-of-01")
@@ -31,7 +31,7 @@ def test_parse_index_selection_supports_comma_indexes():
assert parse_index_selection("1, 3", ["a", "b", "c"]) == ["a", "c"]
def test_print_wizard_step_adds_separator(monkeypatch):
def test_print_wizard_step_adds_separator(monkeypatch: pytest.MonkeyPatch):
output_lines = []
monkeypatch.setattr("commands.data_migration.click.echo", output_lines.append)
@@ -45,7 +45,7 @@ def test_conflict_strategy_choices_exclude_replace():
assert CONFLICT_STRATEGY_CHOICES == ["fail", "skip", "update"]
def test_prompt_app_ids_explains_comma_selection_and_default(monkeypatch):
def test_prompt_app_ids_explains_comma_selection_and_default(monkeypatch: pytest.MonkeyPatch):
from commands.data_migration import _prompt_app_ids
prompts = []
@@ -67,7 +67,7 @@ def test_prompt_app_ids_explains_comma_selection_and_default(monkeypatch):
assert "Currently supported app types: workflow and chatflow." in output_lines
def test_prompt_tool_category_marks_auto_discovered_tools(monkeypatch):
def test_prompt_tool_category_marks_auto_discovered_tools(monkeypatch: pytest.MonkeyPatch):
output_lines = []
monkeypatch.setattr("commands.data_migration.click.echo", output_lines.append)
@@ -85,7 +85,7 @@ def test_prompt_tool_category_marks_auto_discovered_tools(monkeypatch):
assert output_lines[:2] == ["", "==== Custom API tools ===="]
def test_prompt_tool_category_explains_comma_selection_and_default(monkeypatch):
def test_prompt_tool_category_explains_comma_selection_and_default(monkeypatch: pytest.MonkeyPatch):
prompts = []
def capture_prompt(text, **kwargs):
@@ -110,7 +110,7 @@ def test_prompt_tool_category_explains_comma_selection_and_default(monkeypatch):
]
def test_prompt_output_file_shows_default(monkeypatch):
def test_prompt_output_file_shows_default(monkeypatch: pytest.MonkeyPatch):
prompts = []
def capture_prompt(text, **kwargs):
@@ -124,7 +124,7 @@ def test_prompt_output_file_shows_default(monkeypatch):
assert prompts[0][1]["show_default"] is True
def test_prompt_tool_category_marks_auto_by_detail_and_supports_multi_select(monkeypatch):
def test_prompt_tool_category_marks_auto_by_detail_and_supports_multi_select(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr("commands.data_migration.click.echo", lambda *_args, **_kwargs: None)
monkeypatch.setattr("commands.data_migration.click.prompt", lambda *args, **kwargs: "1,2")
@@ -159,7 +159,7 @@ def test_prompt_tool_category_marks_auto_by_value():
assert "1. [auto] embedded_workflow_as_tool (tool-1)" in output_lines
def test_print_auto_tools_lists_each_category(monkeypatch):
def test_print_auto_tools_lists_each_category(monkeypatch: pytest.MonkeyPatch):
output_lines = []
monkeypatch.setattr("commands.data_migration.click.echo", output_lines.append)
@@ -208,7 +208,7 @@ def test_resolve_mcp_tool_names_does_not_compare_non_uuid_identifier_to_uuid_id(
assert resolved == {provider.name: provider.id}
def test_prompt_additional_tools_prints_final_selection_when_skipped(monkeypatch):
def test_prompt_additional_tools_prints_final_selection_when_skipped(monkeypatch: pytest.MonkeyPatch):
output_lines = []
confirm_prompts = []
@@ -236,7 +236,7 @@ def test_prompt_additional_tools_prints_final_selection_when_skipped(monkeypatch
assert "- [auto] weather: 3bac3aa9-dd87-4351-9459-a7099137b028" in output_lines
def test_final_tool_selection_deduplicates_manual_tool_already_auto(monkeypatch):
def test_final_tool_selection_deduplicates_manual_tool_already_auto(monkeypatch: pytest.MonkeyPatch):
output_lines = []
monkeypatch.setattr("commands.data_migration.click.echo", output_lines.append)
@@ -259,7 +259,7 @@ def test_final_tool_selection_deduplicates_manual_tool_already_auto(monkeypatch)
assert not any(line.startswith("- [manual]") for line in output_lines)
def test_prompt_output_file_rejects_yes_no_typo(monkeypatch):
def test_prompt_output_file_rejects_yes_no_typo(monkeypatch: pytest.MonkeyPatch):
import click
import pytest
@@ -269,7 +269,7 @@ def test_prompt_output_file_rejects_yes_no_typo(monkeypatch):
_prompt_output_file()
def test_confirm_wizard_summary_shows_conflict_strategy(monkeypatch):
def test_confirm_wizard_summary_shows_conflict_strategy(monkeypatch: pytest.MonkeyPatch):
output_lines = []
confirm_prompts = []
@@ -298,7 +298,7 @@ def test_confirm_wizard_summary_shows_conflict_strategy(monkeypatch):
assert confirm_prompts == [("Write migration package? [y/n, default: y]", {"default": True, "show_default": False})]
def test_confirm_wizard_summary_shows_final_deduplicated_tool_selection(monkeypatch):
def test_confirm_wizard_summary_shows_final_deduplicated_tool_selection(monkeypatch: pytest.MonkeyPatch):
output_lines = []
monkeypatch.setattr("commands.data_migration.click.echo", output_lines.append)
@@ -343,7 +343,7 @@ def test_confirm_wizard_summary_shows_final_deduplicated_tool_selection(monkeypa
assert "- [manual] weather-id" not in output_lines
def test_import_options_prompts_explain_secrets_reuse_and_conflicts(monkeypatch):
def test_import_options_prompts_explain_secrets_reuse_and_conflicts(monkeypatch: pytest.MonkeyPatch):
from commands.data_migration import _prompt_import_options
output_lines = []
@@ -13,7 +13,7 @@ from services.snippet_dsl_service import ImportStatus, SnippetImportInfo
@pytest.fixture(autouse=True)
def _patch_snippet_service_factory(monkeypatch):
def _patch_snippet_service_factory(monkeypatch: pytest.MonkeyPatch):
def factory():
return snippets_module.SnippetService.__new__(snippets_module.SnippetService)
@@ -77,7 +77,7 @@ def test_load_or_create_persists_new_binding_on_caller(monkeypatch, home_snapsho
session.commit.assert_called_once_with()
def test_load_or_create_uses_exact_caller_binding(monkeypatch) -> None:
def test_load_or_create_uses_exact_caller_binding(monkeypatch: pytest.MonkeyPatch) -> None:
caller = SimpleNamespace(agent_workspace_binding_id="binding-1")
context = MagicMock()
context.__enter__.return_value = MagicMock()
@@ -97,7 +97,7 @@ def test_load_or_create_uses_exact_caller_binding(monkeypatch) -> None:
create.assert_not_called()
def test_normal_conversation_pointer_does_not_create_replacement_binding(monkeypatch) -> None:
def test_normal_conversation_pointer_does_not_create_replacement_binding(monkeypatch: pytest.MonkeyPatch) -> None:
caller = SimpleNamespace(agent_workspace_binding_id="unavailable-binding")
context = MagicMock()
get_binding = MagicMock(return_value=None)
@@ -115,7 +115,7 @@ def test_normal_conversation_pointer_does_not_create_replacement_binding(monkeyp
create.assert_not_called()
def test_save_snapshot_targets_binding(monkeypatch) -> None:
def test_save_snapshot_targets_binding(monkeypatch: pytest.MonkeyPatch) -> None:
save = MagicMock()
monkeypatch.setattr(AgentWorkspaceService, "save_binding_session_snapshot", save)
snapshot = CompositorSessionSnapshot(layers=[])
@@ -5,6 +5,7 @@ from typing import cast
from unittest.mock import MagicMock, patch
from uuid import UUID, uuid4
import pytest
from agenton.compositor import CompositorSessionSnapshot
from dify_agent.layers.ask_human import AskHumanToolResult
from dify_agent.protocol import (
@@ -702,7 +703,7 @@ def _pending_session(snapshot: CompositorSessionSnapshot) -> StoredWorkflowAgent
)
def test_agent_node_resumes_with_deferred_tool_results_after_submitted_form(monkeypatch):
def test_agent_node_resumes_with_deferred_tool_results_after_submitted_form(monkeypatch: pytest.MonkeyPatch):
# ENG-638: a submitted form re-enters _run; the human's answer is threaded
# into the second Agent run as deferred_tool_results.
snapshot = CompositorSessionSnapshot(layers=[])
@@ -726,7 +727,7 @@ def test_agent_node_resumes_with_deferred_tool_results_after_submitted_form(monk
assert any(isinstance(event, StreamCompletedEvent) for event in events)
def test_agent_node_repauses_when_resumed_form_still_waiting(monkeypatch):
def test_agent_node_repauses_when_resumed_form_still_waiting(monkeypatch: pytest.MonkeyPatch):
snapshot = CompositorSessionSnapshot(layers=[])
store = FakeSessionStore(snapshot=snapshot)
store.loaded_session = _pending_session(snapshot)
@@ -756,7 +757,7 @@ def test_agent_node_repauses_when_resumed_form_still_waiting(monkeypatch):
assert client.request is None # no second Agent run was created
def test_agent_node_expired_ask_human_failure_keeps_binding_identity(monkeypatch):
def test_agent_node_expired_ask_human_failure_keeps_binding_identity(monkeypatch: pytest.MonkeyPatch):
snapshot = CompositorSessionSnapshot(layers=[])
store = FakeSessionStore(snapshot=snapshot)
store.loaded_session = _pending_session(snapshot)
@@ -1007,7 +1007,7 @@ def test_provider_level_entry_unknown_provider_maps_to_declaration_not_found():
assert exc_info.value.error_code == "agent_tool_declaration_not_found"
def test_list_provider_tool_names_reads_builtin_provider(monkeypatch):
def test_list_provider_tool_names_reads_builtin_provider(monkeypatch: pytest.MonkeyPatch):
"""The default provider-tools lister maps ToolManager's provider controller
to the plain name list the expansion step consumes."""
from types import SimpleNamespace
@@ -299,7 +299,7 @@ def test_load_existing_pointer_rejects_conflicting_workflow_identity(monkeypatch
session.commit.assert_not_called()
def test_load_or_create_fails_before_binding_create_when_caller_row_is_missing(monkeypatch) -> None:
def test_load_or_create_fails_before_binding_create_when_caller_row_is_missing(monkeypatch: pytest.MonkeyPatch) -> None:
context = MagicMock()
session = context.__enter__.return_value
create = MagicMock()
@@ -348,7 +348,7 @@ def test_load_existing_scope_waits_for_caller_row_to_become_visible(monkeypatch:
assert sleep.call_count == 2
def test_save_snapshot_targets_binding(monkeypatch) -> None:
def test_save_snapshot_targets_binding(monkeypatch: pytest.MonkeyPatch) -> None:
save = MagicMock()
monkeypatch.setattr(AgentWorkspaceService, "save_binding_session_snapshot", save)
snapshot = CompositorSessionSnapshot(layers=[])
@@ -412,7 +412,7 @@ def test_retire_workflow_run_transitions_active_workspace(
assert workspace_ids == [workspace.id]
def test_retire_workflow_run_returns_existing_retired_workspace(monkeypatch) -> None:
def test_retire_workflow_run_returns_existing_retired_workspace(monkeypatch: pytest.MonkeyPatch) -> None:
workspace = _workspace_row(status=AgentWorkingResourceStatus.RETIRED)
context = MagicMock()
session = context.__enter__.return_value
@@ -1,5 +1,6 @@
import ssl
import pytest
import socketio
from extensions import ext_socketio
@@ -9,7 +10,7 @@ def test_socketio_server_uses_redis_manager() -> None:
assert isinstance(ext_socketio.sio.manager, socketio.RedisManager)
def test_create_socketio_client_manager_uses_pubsub_url_and_prefixed_channel(monkeypatch) -> None:
def test_create_socketio_client_manager_uses_pubsub_url_and_prefixed_channel(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(ext_socketio.dify_config, "PUBSUB_REDIS_URL", "redis://redis.example.com:6380/3")
monkeypatch.setattr(ext_socketio.dify_config, "REDIS_KEY_PREFIX", "tenant-a")
@@ -19,7 +20,7 @@ def test_create_socketio_client_manager_uses_pubsub_url_and_prefixed_channel(mon
assert manager.channel == "tenant-a:socketio"
def test_build_redis_options_includes_tls_options_for_rediss(monkeypatch) -> None:
def test_build_redis_options_includes_tls_options_for_rediss(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(ext_socketio.dify_config, "REDIS_SSL_CERT_REQS", "CERT_REQUIRED")
monkeypatch.setattr(ext_socketio.dify_config, "REDIS_SSL_CA_CERTS", "/ca.pem")
monkeypatch.setattr(ext_socketio.dify_config, "REDIS_SSL_CERTFILE", "/cert.pem")
@@ -33,7 +34,7 @@ def test_build_redis_options_includes_tls_options_for_rediss(monkeypatch) -> Non
assert options["ssl_keyfile"] == "/key.pem"
def test_build_redis_options_omits_socket_timeout(monkeypatch) -> None:
def test_build_redis_options_omits_socket_timeout(monkeypatch: pytest.MonkeyPatch) -> None:
# socket_timeout must not be passed to RedisManager because the pub/sub
# listen loop blocks indefinitely between messages; a read timeout there
# triggers an infinite reconnect storm (issue #39423).
@@ -191,7 +191,7 @@ def test_agent_package_rejects_null_file_id_for_available_assets(asset: dict) ->
AgentPackage.model_validate(package)
def test_import_warnings_cover_runtime_setup_removed_from_package(monkeypatch) -> None:
def test_import_warnings_cover_runtime_setup_removed_from_package(monkeypatch: pytest.MonkeyPatch) -> None:
soul = AgentSoulConfig.model_validate(
{
"tools": {
@@ -326,7 +326,7 @@ def test_graph_without_package_bindings_removes_portable_fields() -> None:
assert AGENT_NODE_JOB_DSL_KEY in graph["nodes"][0]["data"]
def test_import_agent_app_package_creates_config_and_unpublished_draft(monkeypatch) -> None:
def test_import_agent_app_package_creates_config_and_unpublished_draft(monkeypatch: pytest.MonkeyPatch) -> None:
session = Mock()
service = AgentDslService(session)
soul = AgentSoulConfig(config_note="portable")
@@ -465,7 +465,7 @@ def test_import_workflow_packages_rejects_invalid_package_binding(binding: dict,
)
def test_clone_inline_binding_copies_soul_and_drive_rows(monkeypatch) -> None:
def test_clone_inline_binding_copies_soul_and_drive_rows(monkeypatch: pytest.MonkeyPatch) -> None:
session = Mock()
service = AgentDslService(session)
target_agent = SimpleNamespace(id="target-agent")
@@ -505,7 +505,7 @@ def test_clone_inline_binding_copies_soul_and_drive_rows(monkeypatch) -> None:
)
def test_extract_package_dependencies_covers_model_tools_and_knowledge(monkeypatch) -> None:
def test_extract_package_dependencies_covers_model_tools_and_knowledge(monkeypatch: pytest.MonkeyPatch) -> None:
model_dependency = Mock(side_effect=lambda provider: f"model:{provider}")
tool_dependency = Mock(side_effect=lambda provider: f"tool:{provider}")
monkeypatch.setattr(
@@ -588,7 +588,7 @@ def test_create_imported_inline_agent_uses_import_provenance() -> None:
)
def test_create_workflow_only_agent_sets_backing_app_and_snapshot(monkeypatch) -> None:
def test_create_workflow_only_agent_sets_backing_app_and_snapshot(monkeypatch: pytest.MonkeyPatch) -> None:
session = Mock()
service = AgentDslService(session)
roster_service = Mock()
@@ -618,7 +618,7 @@ def test_create_workflow_only_agent_sets_backing_app_and_snapshot(monkeypatch) -
assert session.flush.call_count == 2
def test_resolve_package_soul_preserves_existing_and_marks_missing_knowledge(monkeypatch) -> None:
def test_resolve_package_soul_preserves_existing_and_marks_missing_knowledge(monkeypatch: pytest.MonkeyPatch) -> None:
soul = AgentSoulConfig.model_validate(
{
"config_skills": [{"name": "skill", "file_kind": "tool_file", "file_id": "skill-file"}],
@@ -139,7 +139,7 @@ def test_binary_skill_md_maps_to_404(sqlite_session: Session):
# ── real-path coverage: _invoke / passthrough ────────────────────────────────
def test_invoke_maps_missing_default_model_to_400(monkeypatch):
def test_invoke_maps_missing_default_model_to_400(monkeypatch: pytest.MonkeyPatch):
import services.agent.skill_tool_inference_service as module
from core.errors.error import ProviderTokenNotInitError
@@ -153,7 +153,7 @@ def test_invoke_maps_missing_default_model_to_400(monkeypatch):
assert exc_info.value.status_code == 400
def test_invoke_maps_model_failure_to_422_and_success_returns_text(monkeypatch):
def test_invoke_maps_model_failure_to_422_and_success_returns_text(monkeypatch: pytest.MonkeyPatch):
import services.agent.skill_tool_inference_service as module
fake_manager = MagicMock()
@@ -29,7 +29,7 @@ def _workflow(*, workflow_id: str = "workflow-1", version: str = Workflow.VERSIO
)
def test_inline_binding_from_another_node_is_cloned(monkeypatch) -> None:
def test_inline_binding_from_another_node_is_cloned(monkeypatch: pytest.MonkeyPatch) -> None:
session = Mock()
draft_workflow = _workflow()
monkeypatch.setattr(
@@ -214,7 +214,7 @@ def test_publish_binding_replacement_returns_only_previous_inline_agent(
assert copied.current_snapshot_id == "draft-inline-snapshot"
def test_inline_binding_reuses_existing_node_owned_agent(monkeypatch) -> None:
def test_inline_binding_reuses_existing_node_owned_agent(monkeypatch: pytest.MonkeyPatch) -> None:
session = Mock()
draft_workflow = _workflow()
existing_binding = WorkflowAgentNodeBinding(
@@ -262,7 +262,7 @@ def test_inline_binding_reuses_existing_node_owned_agent(monkeypatch) -> None:
clone.assert_not_called()
def test_resolve_existing_inline_binding_agent_returns_valid_agent_or_none(monkeypatch) -> None:
def test_resolve_existing_inline_binding_agent_returns_valid_agent_or_none(monkeypatch: pytest.MonkeyPatch) -> None:
binding = WorkflowAgentNodeBinding(
tenant_id="tenant-1",
app_id="app-1",
@@ -314,7 +314,7 @@ def test_resolve_roster_binding_rejects_unpublished_agent() -> None:
)
def test_clone_inline_graph_binding_for_node_clones_source(monkeypatch) -> None:
def test_clone_inline_graph_binding_for_node_clones_source(monkeypatch: pytest.MonkeyPatch) -> None:
session = Mock()
source_agent = SimpleNamespace(id="source-agent")
source_snapshot = SimpleNamespace(id="source-snapshot")
@@ -363,7 +363,7 @@ def test_clone_inline_graph_binding_for_node_rejects_missing_source(scalar_resul
)
def test_restore_clones_inline_binding_owned_by_published_workflow(monkeypatch) -> None:
def test_restore_clones_inline_binding_owned_by_published_workflow(monkeypatch: pytest.MonkeyPatch) -> None:
source = WorkflowAgentNodeBinding(
tenant_id="tenant-1",
app_id="app-1",
@@ -98,7 +98,7 @@ def test_export_config_parser_rejects_unsupported_app_modes():
)
def test_secret_free_api_tool_export_uses_masking_and_omits_credentials(monkeypatch):
def test_secret_free_api_tool_export_uses_masking_and_omits_credentials(monkeypatch: pytest.MonkeyPatch):
calls = []
def fake_get_api_provider(provider: str, tenant_id: str, mask: bool = True):
@@ -253,7 +253,7 @@ workflow:
assert result.error == "Snippet cannot contain the following node types: start"
def test_import_snippet_stores_pending_data_for_newer_dsl(monkeypatch):
def test_import_snippet_stores_pending_data_for_newer_dsl(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace(scalar=Mock(return_value=None)))
setex = Mock()
monkeypatch.setattr("services.snippet_dsl_service.redis_client.setex", setex)
@@ -310,7 +310,7 @@ workflow:
assert result.error == "Snippet not found"
def test_import_snippet_passes_dependencies_to_create_or_update(monkeypatch):
def test_import_snippet_passes_dependencies_to_create_or_update(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace(scalar=Mock(return_value=None)))
snippet = SimpleNamespace(id="snippet-1")
create_or_update = Mock(return_value=snippet)
@@ -342,7 +342,7 @@ workflow:
assert dependencies[0].value.plugin_unique_identifier == "langgenius/openai:0.0.1"
def test_import_snippet_rolls_back_when_create_or_update_raises(monkeypatch):
def test_import_snippet_rolls_back_when_create_or_update_raises(monkeypatch: pytest.MonkeyPatch):
session = SimpleNamespace(scalar=Mock(return_value=None), rollback=Mock())
service = SnippetDslService(session=session)
monkeypatch.setattr(service, "_create_or_update_snippet", Mock(side_effect=RuntimeError("boom")))
@@ -358,7 +358,7 @@ def test_import_snippet_rolls_back_when_create_or_update_raises(monkeypatch):
session.rollback.assert_called_once()
def test_confirm_import_returns_failed_when_pending_data_missing(monkeypatch):
def test_confirm_import_returns_failed_when_pending_data_missing(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace())
monkeypatch.setattr("services.snippet_dsl_service.redis_client.get", Mock(return_value=None))
@@ -370,7 +370,7 @@ def test_confirm_import_returns_failed_when_pending_data_missing(monkeypatch):
assert result.error == "Import information expired or does not exist"
def test_confirm_import_returns_failed_for_invalid_pending_payload(monkeypatch):
def test_confirm_import_returns_failed_for_invalid_pending_payload(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace())
monkeypatch.setattr("services.snippet_dsl_service.redis_client.get", Mock(return_value=object()))
@@ -382,7 +382,7 @@ def test_confirm_import_returns_failed_for_invalid_pending_payload(monkeypatch):
assert result.error == "Invalid import information"
def test_confirm_import_is_scoped_to_its_owner(monkeypatch):
def test_confirm_import_is_scoped_to_its_owner(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace(scalar=Mock(return_value=None)))
account = SimpleNamespace(id="account-1", current_tenant_id="tenant-1")
snippet = SimpleNamespace(id="snippet-new")
@@ -437,7 +437,7 @@ workflow:
redis_delete.assert_called_once_with(redis_key)
def test_confirm_import_returns_failed_for_non_mapping_yaml(monkeypatch):
def test_confirm_import_returns_failed_for_non_mapping_yaml(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace())
pending = SnippetPendingData(
import_mode="yaml-content",
@@ -454,7 +454,7 @@ def test_confirm_import_returns_failed_for_non_mapping_yaml(monkeypatch):
assert result.error == "Invalid YAML format: expected a dictionary"
def test_confirm_import_returns_failed_when_create_or_update_raises(monkeypatch):
def test_confirm_import_returns_failed_when_create_or_update_raises(monkeypatch: pytest.MonkeyPatch):
session = SimpleNamespace(scalar=Mock(return_value=None), rollback=Mock())
service = SnippetDslService(session=session)
pending = SnippetPendingData(
@@ -475,7 +475,7 @@ def test_confirm_import_returns_failed_when_create_or_update_raises(monkeypatch)
session.rollback.assert_called_once()
def test_check_dependencies_returns_empty_without_draft_workflow(monkeypatch):
def test_check_dependencies_returns_empty_without_draft_workflow(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace(get_bind=Mock()))
monkeypatch.setattr(
"services.snippet_dsl_service.SnippetService",
@@ -487,7 +487,7 @@ def test_check_dependencies_returns_empty_without_draft_workflow(monkeypatch):
assert result.leaked_dependencies == []
def test_check_dependencies_returns_generated_dependencies(monkeypatch):
def test_check_dependencies_returns_generated_dependencies(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace(get_bind=Mock()))
workflow = SimpleNamespace(graph_dict={"nodes": []})
leaked_dependencies = [
@@ -511,7 +511,7 @@ def test_check_dependencies_returns_generated_dependencies(monkeypatch):
assert result.leaked_dependencies[0].value.plugin_unique_identifier == "langgenius/openai:0.0.1"
def test_create_or_update_snippet_updates_existing_snippet_and_syncs_workflow(monkeypatch):
def test_create_or_update_snippet_updates_existing_snippet_and_syncs_workflow(monkeypatch: pytest.MonkeyPatch):
snippet = SimpleNamespace(
id="snippet-1",
tenant_id="tenant-1",
@@ -563,7 +563,7 @@ def test_create_or_update_snippet_updates_existing_snippet_and_syncs_workflow(mo
session.commit.assert_called_once()
def test_create_or_update_snippet_creates_new_snippet_and_flushes(monkeypatch):
def test_create_or_update_snippet_creates_new_snippet_and_flushes(monkeypatch: pytest.MonkeyPatch):
session = SimpleNamespace(add=Mock(), flush=Mock(), commit=Mock(), get_bind=Mock())
service = SnippetDslService(session=session)
snippet_service = SimpleNamespace(get_draft_workflow=Mock(return_value=None), sync_draft_workflow=Mock())
@@ -599,7 +599,7 @@ def test_create_or_update_snippet_creates_new_snippet_and_flushes(monkeypatch):
session.commit.assert_called_once()
def test_export_snippet_dsl_raises_without_draft_workflow(monkeypatch):
def test_export_snippet_dsl_raises_without_draft_workflow(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace(get_bind=Mock()))
monkeypatch.setattr(
"services.snippet_dsl_service.SnippetService",
@@ -610,7 +610,7 @@ def test_export_snippet_dsl_raises_without_draft_workflow(monkeypatch):
service.export_snippet_dsl(SimpleNamespace())
def test_export_snippet_dsl_returns_yaml(monkeypatch):
def test_export_snippet_dsl_returns_yaml(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace(get_bind=Mock()))
workflow = SimpleNamespace(
to_dict=Mock(return_value={"graph": {"nodes": []}}),
@@ -640,7 +640,7 @@ def test_export_snippet_dsl_returns_yaml(monkeypatch):
assert "input_fields:" in result
def test_append_workflow_export_data_filters_credentials_and_extracts_dependencies(monkeypatch):
def test_append_workflow_export_data_filters_credentials_and_extracts_dependencies(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace())
workflow_dict = {
"graph": {
@@ -698,7 +698,7 @@ def test_append_workflow_export_data_filters_credentials_and_extracts_dependenci
assert "credential_id" not in nodes[2]["data"]["agent_parameters"]["tools"]["value"][0]
def test_append_workflow_export_data_rewrites_knowledge_dataset_ids(monkeypatch):
def test_append_workflow_export_data_rewrites_knowledge_dataset_ids(monkeypatch: pytest.MonkeyPatch):
service = SnippetDslService(session=SimpleNamespace())
workflow_dict = {
"graph": {
@@ -73,7 +73,7 @@ def test_ensure_start_node_returns_workflow_when_start_already_exists():
assert result is workflow
def test_ensure_start_node_injects_virtual_start_for_root_candidates(monkeypatch):
def test_ensure_start_node_injects_virtual_start_for_root_candidates(monkeypatch: pytest.MonkeyPatch):
graph = {
"nodes": [
{"id": "llm-1", "data": {"type": "llm"}},
@@ -107,14 +107,14 @@ def test_ensure_start_node_injects_virtual_start_for_root_candidates(monkeypatch
make_transient.assert_called_once_with(workflow)
def test_parse_files_returns_empty_when_upload_config_disabled(monkeypatch):
def test_parse_files_returns_empty_when_upload_config_disabled(monkeypatch: pytest.MonkeyPatch):
workflow = _workflow({"nodes": [], "edges": []})
monkeypatch.setattr("services.snippet_generate_service.FileUploadConfigManager.convert", Mock(return_value=None))
assert SnippetGenerateService.parse_files(workflow, files=[{"id": "file-1"}]) == []
def test_parse_files_delegates_to_file_factory(monkeypatch):
def test_parse_files_delegates_to_file_factory(monkeypatch: pytest.MonkeyPatch):
workflow = _workflow({"nodes": [], "edges": []})
upload_config = SimpleNamespace(enabled=True)
files = [SimpleNamespace(id="file-1")]
@@ -130,7 +130,7 @@ def test_parse_files_delegates_to_file_factory(monkeypatch):
build_from_mappings.assert_called_once()
def test_generate_raises_when_draft_workflow_missing(monkeypatch):
def test_generate_raises_when_draft_workflow_missing(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(
"services.snippet_generate_service.SnippetService",
lambda *_args, **_kwargs: SimpleNamespace(get_draft_workflow=Mock(return_value=None)),
@@ -145,7 +145,7 @@ def test_generate_raises_when_draft_workflow_missing(monkeypatch):
)
def test_generate_delegates_to_workflow_generator_and_filters_stream(monkeypatch):
def test_generate_delegates_to_workflow_generator_and_filters_stream(monkeypatch: pytest.MonkeyPatch):
workflow = _workflow({"nodes": [{"id": "llm-1", "data": {"type": "llm"}}], "edges": []})
snippet = SimpleNamespace(id="snippet-1", tenant_id="tenant-1", input_fields_list=[])
user = SimpleNamespace(id="user-1")
@@ -186,7 +186,7 @@ def test_generate_delegates_to_workflow_generator_and_filters_stream(monkeypatch
workflow_generator_class.convert_to_event_stream.assert_called_once()
def test_run_published_delegates_to_workflow_generator_non_streaming(monkeypatch):
def test_run_published_delegates_to_workflow_generator_non_streaming(monkeypatch: pytest.MonkeyPatch):
workflow = _workflow({"nodes": [{"id": "llm-1", "data": {"type": "llm"}}], "edges": []})
snippet = SimpleNamespace(id="snippet-1", tenant_id="tenant-1", input_fields_list=[])
user = SimpleNamespace(id="user-1")
@@ -216,7 +216,7 @@ def test_run_published_delegates_to_workflow_generator_non_streaming(monkeypatch
assert kwargs["call_depth"] == 0
def test_ensure_start_node_for_worker_delegates(monkeypatch):
def test_ensure_start_node_for_worker_delegates(monkeypatch: pytest.MonkeyPatch):
workflow = _workflow({"nodes": [], "edges": []})
snippet = SimpleNamespace(input_fields_list=[])
ensure_start_node = Mock(return_value=workflow)
@@ -228,7 +228,7 @@ def test_ensure_start_node_for_worker_delegates(monkeypatch):
ensure_start_node.assert_called_once_with(workflow, snippet)
def test_run_draft_node_delegates_to_workflow_service(monkeypatch):
def test_run_draft_node_delegates_to_workflow_service(monkeypatch: pytest.MonkeyPatch):
workflow = _workflow({"nodes": [{"id": "llm-1", "data": {"type": "llm"}}], "edges": []})
snippet = SimpleNamespace(id="snippet-1", tenant_id="tenant-1")
account = SimpleNamespace(id="account-1")
@@ -262,7 +262,7 @@ def test_run_draft_node_delegates_to_workflow_service(monkeypatch):
assert kwargs["files"] == []
def test_run_draft_node_raises_when_draft_workflow_missing(monkeypatch):
def test_run_draft_node_raises_when_draft_workflow_missing(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(
"services.snippet_generate_service.SnippetService",
lambda *_args, **_kwargs: SimpleNamespace(get_draft_workflow=Mock(return_value=None)),
@@ -277,7 +277,7 @@ def test_run_draft_node_raises_when_draft_workflow_missing(monkeypatch):
)
def test_generate_single_iteration_delegates_to_workflow_generator(monkeypatch):
def test_generate_single_iteration_delegates_to_workflow_generator(monkeypatch: pytest.MonkeyPatch):
workflow = _workflow({"nodes": [{"id": "iteration-1", "data": {"type": "iteration"}}], "edges": []})
snippet = SimpleNamespace(id="snippet-1", tenant_id="tenant-1")
user = SimpleNamespace(id="user-1")
@@ -313,7 +313,7 @@ def test_generate_single_iteration_delegates_to_workflow_generator(monkeypatch):
workflow_generator_class.convert_to_event_stream.assert_called_once_with(response)
def test_generate_single_iteration_raises_when_draft_workflow_missing(monkeypatch):
def test_generate_single_iteration_raises_when_draft_workflow_missing(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(
"services.snippet_generate_service.SnippetService",
lambda *_args, **_kwargs: SimpleNamespace(get_draft_workflow=Mock(return_value=None)),
@@ -329,7 +329,7 @@ def test_generate_single_iteration_raises_when_draft_workflow_missing(monkeypatc
)
def test_generate_single_loop_delegates_to_workflow_generator(monkeypatch):
def test_generate_single_loop_delegates_to_workflow_generator(monkeypatch: pytest.MonkeyPatch):
workflow = _workflow({"nodes": [{"id": "loop-1", "data": {"type": "loop"}}], "edges": []})
snippet = SimpleNamespace(id="snippet-1", tenant_id="tenant-1")
user = SimpleNamespace(id="user-1")
@@ -365,7 +365,7 @@ def test_generate_single_loop_delegates_to_workflow_generator(monkeypatch):
workflow_generator_class.convert_to_event_stream.assert_called_once_with(response)
def test_generate_single_loop_raises_when_draft_workflow_missing(monkeypatch):
def test_generate_single_loop_raises_when_draft_workflow_missing(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(
"services.snippet_generate_service.SnippetService",
lambda *_args, **_kwargs: SimpleNamespace(get_draft_workflow=Mock(return_value=None)),
@@ -381,7 +381,7 @@ def test_generate_single_loop_raises_when_draft_workflow_missing(monkeypatch):
)
def test_run_published_raises_when_published_workflow_missing(monkeypatch):
def test_run_published_raises_when_published_workflow_missing(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(
"services.snippet_generate_service.SnippetService",
lambda *_args, **_kwargs: SimpleNamespace(get_published_workflow=Mock(return_value=None)),
@@ -1,9 +1,11 @@
from unittest.mock import Mock
import pytest
from services.tools.api_tools_manage_service import ApiToolManageService
def test_get_api_tool_provider_remote_schema_uses_ssrf_proxy_get(monkeypatch) -> None:
def test_get_api_tool_provider_remote_schema_uses_ssrf_proxy_get(monkeypatch: pytest.MonkeyPatch) -> None:
schema = """
{
"openapi": "3.0.0",
@@ -11,7 +11,7 @@ def test_initialize_created_app_rbac_access_task_uses_rbac_queue():
assert initialize_created_app_rbac_access_task.queue == APP_RBAC_QUEUE
def test_initialize_created_app_rbac_access_task_batches_workspace_members(monkeypatch):
def test_initialize_created_app_rbac_access_task_batches_workspace_members(monkeypatch: pytest.MonkeyPatch):
import tasks.initialize_created_app_rbac_access_task as task_module
from tasks.initialize_created_app_rbac_access_task import initialize_created_app_rbac_access_task
@@ -44,7 +44,7 @@ def test_initialize_created_app_rbac_access_task_batches_workspace_members(monke
assert call.kwargs["payload"].access_policy_ids == [task_module.APP_RBAC_DEFAULT_ACCESS_POLICY_ID]
def test_initialize_created_app_rbac_access_task_retries_on_failure(monkeypatch):
def test_initialize_created_app_rbac_access_task_retries_on_failure(monkeypatch: pytest.MonkeyPatch):
import tasks.initialize_created_app_rbac_access_task as task_module
from tasks.initialize_created_app_rbac_access_task import initialize_created_app_rbac_access_task