feat: feedback verbetering 05

This commit is contained in:
kodi
2026-03-15 15:30:55 +01:00
parent 61d0c8de41
commit ae6a9d8c45
13 changed files with 139 additions and 31 deletions
@@ -1,6 +1,7 @@
from __future__ import annotations
import asyncio
import errno
import sys
import tempfile
import threading
@@ -52,6 +53,11 @@ class BlockingMoveFilesystemAdapter(FilesystemAdapter):
super().move_file(source, destination)
class CrossDeviceMoveFilesystemAdapter(FilesystemAdapter):
def move_file(self, source: str, destination: str) -> None:
raise OSError(errno.EXDEV, "Invalid cross-device link")
class MoveApiGoldenTest(unittest.TestCase):
def setUp(self) -> None:
self.temp_dir = tempfile.TemporaryDirectory()
@@ -312,6 +318,59 @@ class MoveApiGoldenTest(unittest.TestCase):
self.assertTrue((self.root1 / "b.txt").exists())
self.assertFalse((target / "b.txt").exists())
def test_move_batch_cross_root_files_success(self) -> None:
first = self.root1 / "first.txt"
second = self.root1 / "second.txt"
first.write_text("a", encoding="utf-8")
second.write_text("b", encoding="utf-8")
response = self._request(
"POST",
"/api/files/move",
{
"sources": ["storage1/first.txt", "storage1/second.txt"],
"destination_base": "storage2",
},
)
self.assertEqual(response.status_code, 202)
detail = self._wait_task(response.json()["task_id"])
self.assertEqual(detail["status"], "completed")
self.assertEqual(detail["done_items"], 2)
self.assertEqual(detail["total_items"], 2)
self.assertTrue((self.root2 / "first.txt").exists())
self.assertTrue((self.root2 / "second.txt").exists())
self.assertFalse(first.exists())
self.assertFalse(second.exists())
def test_move_batch_cross_root_files_falls_back_from_exdev(self) -> None:
first = self.root1 / "first.txt"
second = self.root1 / "second.txt"
first.write_text("a", encoding="utf-8")
second.write_text("b", encoding="utf-8")
path_guard = PathGuard({"storage1": str(self.root1), "storage2": str(self.root2)})
self._set_services(path_guard=path_guard, filesystem=CrossDeviceMoveFilesystemAdapter())
response = self._request(
"POST",
"/api/files/move",
{
"sources": ["storage1/first.txt", "storage1/second.txt"],
"destination_base": "storage2",
},
)
self.assertEqual(response.status_code, 202)
detail = self._wait_task(response.json()["task_id"])
self.assertEqual(detail["status"], "completed")
self.assertEqual(detail["done_items"], 2)
self.assertEqual(detail["total_items"], 2)
self.assertTrue((self.root2 / "first.txt").exists())
self.assertTrue((self.root2 / "second.txt").exists())
self.assertFalse(first.exists())
self.assertFalse(second.exists())
def test_move_batch_cross_root_directories_blocked(self) -> None:
first = self.root1 / "first-dir"
second = self.root1 / "second-dir"
@@ -329,6 +388,26 @@ class MoveApiGoldenTest(unittest.TestCase):
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json()["error"]["code"], "invalid_request")
self.assertEqual(response.json()["error"]["message"], "Cross-root batch move with directories is not supported in v1")
def test_move_batch_cross_root_mixed_files_and_directories_blocked(self) -> None:
first = self.root1 / "first.txt"
first.write_text("a", encoding="utf-8")
second = self.root1 / "second-dir"
second.mkdir()
response = self._request(
"POST",
"/api/files/move",
{
"sources": ["storage1/first.txt", "storage1/second-dir"],
"destination_base": "storage2",
},
)
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json()["error"]["code"], "invalid_request")
self.assertEqual(response.json()["error"]["message"], "Cross-root batch move with directories is not supported in v1")
def test_move_batch_mixed_root_selection_blocked(self) -> None:
first = self.root1 / "first-dir"