mirror of
https://github.com/langgenius/dify.git
synced 2026-04-22 11:47:40 +08:00
Merge remote-tracking branch 'origin/main' into feat/support-agent-sandbox
# Conflicts: # api/.env.example # api/uv.lock # web/app/components/app/create-app-modal/index.tsx # web/app/components/app/create-from-dsl-modal/index.tsx # web/app/components/apps/app-card.tsx # web/pnpm-lock.yaml
This commit is contained in:
@ -3,6 +3,7 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
# Getting the absolute path of the current file's directory
|
||||
ABS_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
@ -36,6 +37,7 @@ import sys
|
||||
|
||||
sys.path.insert(0, PROJECT_DIR)
|
||||
|
||||
from core.db.session_factory import configure_session_factory, session_factory
|
||||
from extensions import ext_redis
|
||||
|
||||
|
||||
@ -102,3 +104,18 @@ def reset_secret_key():
|
||||
yield
|
||||
finally:
|
||||
dify_config.SECRET_KEY = original
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def _unit_test_engine():
|
||||
engine = create_engine("sqlite:///:memory:")
|
||||
yield engine
|
||||
engine.dispose()
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _configure_session_factory(_unit_test_engine):
|
||||
try:
|
||||
session_factory.get_session_maker()
|
||||
except RuntimeError:
|
||||
configure_session_factory(_unit_test_engine, expire_on_commit=False)
|
||||
|
||||
@ -31,6 +31,13 @@ def _load_app_module():
|
||||
|
||||
def schema_model(self, name, schema):
|
||||
self.models[name] = schema
|
||||
return schema
|
||||
|
||||
def model(self, name, model_dict=None, **kwargs):
|
||||
"""Register a model with the namespace (flask-restx compatibility)."""
|
||||
if model_dict is not None:
|
||||
self.models[name] = model_dict
|
||||
return model_dict
|
||||
|
||||
def _decorator(self, obj):
|
||||
return obj
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
"""Primarily used for testing merged cell scenarios"""
|
||||
|
||||
import io
|
||||
import os
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
from docx import Document
|
||||
@ -56,6 +58,42 @@ def test_parse_row():
|
||||
assert extractor._parse_row(row, {}, 3) == gt[idx]
|
||||
|
||||
|
||||
def test_init_downloads_via_ssrf_proxy(monkeypatch):
|
||||
doc = Document()
|
||||
doc.add_paragraph("hello")
|
||||
buf = io.BytesIO()
|
||||
doc.save(buf)
|
||||
docx_bytes = buf.getvalue()
|
||||
|
||||
calls: list[tuple[str, object]] = []
|
||||
|
||||
class FakeResponse:
|
||||
status_code = 200
|
||||
content = docx_bytes
|
||||
|
||||
def close(self) -> None:
|
||||
calls.append(("close", None))
|
||||
|
||||
def fake_get(url: str, **kwargs):
|
||||
calls.append(("get", (url, kwargs)))
|
||||
return FakeResponse()
|
||||
|
||||
monkeypatch.setattr(we, "ssrf_proxy", SimpleNamespace(get=fake_get))
|
||||
|
||||
extractor = WordExtractor("https://example.com/test.docx", "tenant_id", "user_id")
|
||||
try:
|
||||
assert calls
|
||||
assert calls[0][0] == "get"
|
||||
url, kwargs = calls[0][1]
|
||||
assert url == "https://example.com/test.docx"
|
||||
assert kwargs.get("timeout") is None
|
||||
assert extractor.web_path == "https://example.com/test.docx"
|
||||
assert extractor.file_path != extractor.web_path
|
||||
assert Path(extractor.file_path).read_bytes() == docx_bytes
|
||||
finally:
|
||||
extractor.temp_file.close()
|
||||
|
||||
|
||||
def test_extract_images_from_docx(monkeypatch):
|
||||
external_bytes = b"ext-bytes"
|
||||
internal_bytes = b"int-bytes"
|
||||
|
||||
@ -138,6 +138,7 @@ class TestDatasetServiceUpdateDataset:
|
||||
"services.dataset_service.DatasetCollectionBindingService.get_dataset_collection_binding"
|
||||
) as mock_get_binding,
|
||||
patch("services.dataset_service.deal_dataset_vector_index_task") as mock_task,
|
||||
patch("services.dataset_service.regenerate_summary_index_task") as mock_regenerate_task,
|
||||
patch(
|
||||
"services.dataset_service.current_user", create_autospec(Account, instance=True)
|
||||
) as mock_current_user,
|
||||
@ -147,6 +148,7 @@ class TestDatasetServiceUpdateDataset:
|
||||
"model_manager": mock_model_manager,
|
||||
"get_binding": mock_get_binding,
|
||||
"task": mock_task,
|
||||
"regenerate_task": mock_regenerate_task,
|
||||
"current_user": mock_current_user,
|
||||
}
|
||||
|
||||
@ -549,6 +551,13 @@ class TestDatasetServiceUpdateDataset:
|
||||
# Verify vector index task was triggered
|
||||
mock_internal_provider_dependencies["task"].delay.assert_called_once_with("dataset-123", "update")
|
||||
|
||||
# Verify regenerate summary index task was triggered (when embedding_model changes)
|
||||
mock_internal_provider_dependencies["regenerate_task"].delay.assert_called_once_with(
|
||||
"dataset-123",
|
||||
regenerate_reason="embedding_model_changed",
|
||||
regenerate_vectors_only=True,
|
||||
)
|
||||
|
||||
# Verify return value
|
||||
assert result == dataset
|
||||
|
||||
|
||||
Reference in New Issue
Block a user