mirror of
https://github.com/langgenius/dify.git
synced 2026-07-15 01:17:04 +08:00
186 lines
6.4 KiB
Python
186 lines
6.4 KiB
Python
import json
|
|
from pathlib import Path
|
|
|
|
from click.testing import CliRunner
|
|
|
|
from commands import data_migration
|
|
from commands.data_migration import (
|
|
ID_STRATEGY_CHOICES,
|
|
export_migration_data,
|
|
export_migration_data_template,
|
|
import_migration_data,
|
|
)
|
|
from services.data_migration.entities import (
|
|
ConflictStrategy,
|
|
ExportResult,
|
|
ImportOptions,
|
|
ImportResult,
|
|
MigrationPackage,
|
|
ReportContext,
|
|
)
|
|
|
|
|
|
class FakeSessionContext:
|
|
session: object
|
|
entered: bool
|
|
exited: bool
|
|
|
|
def __init__(self, session: object) -> None:
|
|
self.session = session
|
|
self.entered = False
|
|
self.exited = False
|
|
|
|
def __enter__(self) -> object:
|
|
self.entered = True
|
|
return self.session
|
|
|
|
def __exit__(self, *_args: object) -> None:
|
|
self.exited = True
|
|
|
|
|
|
def test_export_command_requires_input_and_output():
|
|
result = CliRunner().invoke(export_migration_data, [])
|
|
|
|
assert result.exit_code != 0
|
|
assert export_migration_data.name == "export-app-migration"
|
|
assert "--input" in result.output
|
|
assert "--output" in result.output
|
|
|
|
|
|
def test_import_command_requires_input_and_target_tenant_or_package_metadata():
|
|
result = CliRunner().invoke(import_migration_data, [])
|
|
|
|
assert result.exit_code != 0
|
|
assert import_migration_data.name == "import-app-migration"
|
|
assert "--input" in result.output
|
|
|
|
|
|
def test_import_command_does_not_expose_unimplemented_map_id_strategy():
|
|
assert ID_STRATEGY_CHOICES == ["preserve-id", "generate-new-id"]
|
|
|
|
|
|
def test_export_template_command_prints_scripted_json_template():
|
|
result = CliRunner().invoke(export_migration_data_template, [])
|
|
|
|
assert result.exit_code == 0
|
|
assert export_migration_data_template.name == "app-migration-template"
|
|
template = json.loads(result.output)
|
|
assert template == {
|
|
"source_tenant": {"mode": "single", "id": "", "name": "admin's Workspace"},
|
|
"apps": {"modes": ["workflow", "advanced-chat"], "ids": [], "all": True},
|
|
"include_referenced_tools": True,
|
|
"additional_tools": {"api_tools": [], "workflow_tools": [], "mcp_tools": []},
|
|
"include_secrets": False,
|
|
"import_options": {
|
|
"create_app_api_token_on_import": False,
|
|
"id_strategy": "preserve-id",
|
|
"conflict_strategy": "fail",
|
|
},
|
|
}
|
|
|
|
|
|
def test_export_template_command_writes_output_file(tmp_path):
|
|
output_file = tmp_path / "export-template.json"
|
|
|
|
result = CliRunner().invoke(export_migration_data_template, ["--output", str(output_file)])
|
|
|
|
assert result.exit_code == 0
|
|
assert f"Output written to {output_file}" in result.output
|
|
assert json.loads(output_file.read_text())["apps"]["all"] is True
|
|
|
|
|
|
def test_export_template_command_requires_overwrite_for_existing_output(tmp_path):
|
|
output_file = tmp_path / "export-template.json"
|
|
output_file.write_text("{}")
|
|
|
|
result = CliRunner().invoke(export_migration_data_template, ["--output", str(output_file)])
|
|
|
|
assert result.exit_code != 0
|
|
assert "already exists" in result.output
|
|
|
|
|
|
def test_export_command_uses_cli_owned_session(monkeypatch, tmp_path: Path):
|
|
session = object()
|
|
session_context = FakeSessionContext(session)
|
|
captured: dict[str, object] = {}
|
|
input_file = tmp_path / "export-config.json"
|
|
output_file = tmp_path / "migration-package.json"
|
|
input_file.write_text(json.dumps({"source_tenant": {"name": "source"}, "apps": {"all": True}}))
|
|
package = MigrationPackage.from_mapping({"metadata": {"version": "1", "source_scope": "single"}})
|
|
|
|
class FakeMigrationExportService:
|
|
def export(self, export_session, selection):
|
|
captured["session"] = export_session
|
|
captured["selection"] = selection
|
|
return ExportResult(package=package, report_items=[], report_context=ReportContext())
|
|
|
|
class FakeMigrationPackageService:
|
|
def save_package(self, package_to_save, path, *, overwrite):
|
|
captured["package"] = package_to_save
|
|
captured["path"] = path
|
|
captured["overwrite"] = overwrite
|
|
|
|
monkeypatch.setattr(data_migration.session_factory, "create_session", lambda: session_context)
|
|
monkeypatch.setattr(data_migration, "MigrationExportService", FakeMigrationExportService)
|
|
monkeypatch.setattr(data_migration, "MigrationPackageService", FakeMigrationPackageService)
|
|
|
|
result = CliRunner().invoke(
|
|
export_migration_data,
|
|
["--input", str(input_file), "--output", str(output_file)],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
assert captured["session"] is session
|
|
assert captured["package"] is package
|
|
assert captured["path"] == str(output_file)
|
|
assert captured["overwrite"] is False
|
|
assert session_context.entered
|
|
assert session_context.exited
|
|
|
|
|
|
def test_import_command_uses_cli_owned_session(monkeypatch, tmp_path: Path):
|
|
session = object()
|
|
session_context = FakeSessionContext(session)
|
|
captured: dict[str, object] = {}
|
|
input_file = tmp_path / "migration-package.json"
|
|
input_file.write_text("{}")
|
|
package = MigrationPackage.from_mapping(
|
|
{
|
|
"metadata": {
|
|
"version": "1",
|
|
"source_scope": "single",
|
|
"target_tenant": {"name": "target"},
|
|
"import_options": {"conflict_strategy": "fail"},
|
|
}
|
|
}
|
|
)
|
|
|
|
class FakeMigrationImportService:
|
|
def import_package(self, import_session, request):
|
|
captured["session"] = import_session
|
|
captured["request"] = request
|
|
return ImportResult(report_items=[], report_context=ReportContext(target_tenant="target"))
|
|
|
|
class FakeMigrationPackageService:
|
|
def load_package(self, path):
|
|
captured["path"] = path
|
|
return package
|
|
|
|
monkeypatch.setattr(data_migration.session_factory, "create_session", lambda: session_context)
|
|
monkeypatch.setattr(data_migration, "MigrationImportService", FakeMigrationImportService)
|
|
monkeypatch.setattr(data_migration, "MigrationPackageService", FakeMigrationPackageService)
|
|
|
|
result = CliRunner().invoke(
|
|
import_migration_data,
|
|
["--input", str(input_file), "--conflict-strategy", "skip"],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
assert captured["session"] is session
|
|
assert captured["path"] == str(input_file)
|
|
request = captured["request"]
|
|
assert request.package is package
|
|
assert request.options_override == ImportOptions(conflict_strategy=ConflictStrategy.SKIP)
|
|
assert session_context.entered
|
|
assert session_context.exited
|