"""Tests for preview-only workspace edits and explicit one-time application.""" from __future__ import annotations import tempfile import unittest from pathlib import Path from app import workspace class WorkspaceChangeTests(unittest.TestCase): def setUp(self) -> None: self.temporary = tempfile.TemporaryDirectory() self.root = Path(self.temporary.name).resolve() (self.root / "src").mkdir() def tearDown(self) -> None: self.temporary.cleanup() def test_create_preview_does_not_write_until_apply_and_is_one_time(self) -> None: preview = workspace.create_change_preview( self.root, "src/new.py", "create", "print('hello')\n", ) target = self.root / "src" / "new.py" self.assertFalse(target.exists()) self.assertIn("+print('hello')", str(preview["diff"])) result = workspace.apply_change_preview(str(preview["token"])) self.assertEqual(result["status"], "applied") self.assertEqual(target.read_text(encoding="utf-8"), "print('hello')\n") with self.assertRaisesRegex(ValueError, "انتهت صلاحية"): workspace.apply_change_preview(str(preview["token"])) def test_update_preview_detects_external_changes_before_apply(self) -> None: target = self.root / "src" / "existing.py" target.write_text("old = 1\n", encoding="utf-8") preview = workspace.create_change_preview( self.root, "src/existing.py", "update", "new = 2\n", ) self.assertIn("-old = 1", str(preview["diff"])) self.assertIn("+new = 2", str(preview["diff"])) target.write_text("external = 3\n", encoding="utf-8") with self.assertRaisesRegex(ValueError, "تغير الملف"): workspace.apply_change_preview(str(preview["token"])) self.assertEqual(target.read_text(encoding="utf-8"), "external = 3\n") def test_rejects_escape_hidden_unsupported_and_missing_parent_paths(self) -> None: invalid = [ ("../outside.py", "create", "escape"), (".env", "create", "hidden"), ("src/image.png", "create", "unsupported"), ("missing/new.py", "create", "parent does not exist"), ] for relative_path, operation, _reason in invalid: with self.subTest(path=relative_path): with self.assertRaises(ValueError): workspace.create_change_preview( self.root, relative_path, operation, "content\n" ) def test_rejects_create_overwrite_and_update_of_missing_file(self) -> None: target = self.root / "src" / "existing.py" target.write_text("value = 1\n", encoding="utf-8") with self.assertRaisesRegex(ValueError, "موجود بالفعل"): workspace.create_change_preview( self.root, "src/existing.py", "create", "value = 2\n" ) with self.assertRaisesRegex(ValueError, "غير موجود"): workspace.create_change_preview( self.root, "src/missing.py", "update", "value = 2\n" ) if __name__ == "__main__": unittest.main()