1. import os.path
    
  2. 
    
  3. from django.core.exceptions import ValidationError
    
  4. from django.forms import FilePathField
    
  5. from django.test import SimpleTestCase
    
  6. 
    
  7. PATH = os.path.dirname(os.path.abspath(__file__))
    
  8. 
    
  9. 
    
  10. def fix_os_paths(x):
    
  11.     if isinstance(x, str):
    
  12.         if x.startswith(PATH):
    
  13.             x = x[len(PATH) :]
    
  14.         return x.replace("\\", "/")
    
  15.     elif isinstance(x, tuple):
    
  16.         return tuple(fix_os_paths(list(x)))
    
  17.     elif isinstance(x, list):
    
  18.         return [fix_os_paths(y) for y in x]
    
  19.     else:
    
  20.         return x
    
  21. 
    
  22. 
    
  23. class FilePathFieldTest(SimpleTestCase):
    
  24.     expected_choices = [
    
  25.         ("/filepathfield_test_dir/__init__.py", "__init__.py"),
    
  26.         ("/filepathfield_test_dir/a.py", "a.py"),
    
  27.         ("/filepathfield_test_dir/ab.py", "ab.py"),
    
  28.         ("/filepathfield_test_dir/b.py", "b.py"),
    
  29.         ("/filepathfield_test_dir/c/__init__.py", "__init__.py"),
    
  30.         ("/filepathfield_test_dir/c/d.py", "d.py"),
    
  31.         ("/filepathfield_test_dir/c/e.py", "e.py"),
    
  32.         ("/filepathfield_test_dir/c/f/__init__.py", "__init__.py"),
    
  33.         ("/filepathfield_test_dir/c/f/g.py", "g.py"),
    
  34.         ("/filepathfield_test_dir/h/__init__.py", "__init__.py"),
    
  35.         ("/filepathfield_test_dir/j/__init__.py", "__init__.py"),
    
  36.     ]
    
  37.     path = os.path.join(PATH, "filepathfield_test_dir") + "/"
    
  38. 
    
  39.     def assertChoices(self, field, expected_choices):
    
  40.         self.assertEqual(fix_os_paths(field.choices), expected_choices)
    
  41. 
    
  42.     def test_fix_os_paths(self):
    
  43.         self.assertEqual(fix_os_paths(self.path), ("/filepathfield_test_dir/"))
    
  44. 
    
  45.     def test_nonexistent_path(self):
    
  46.         with self.assertRaisesMessage(FileNotFoundError, "nonexistent"):
    
  47.             FilePathField(path="nonexistent")
    
  48. 
    
  49.     def test_no_options(self):
    
  50.         f = FilePathField(path=self.path)
    
  51.         expected = [
    
  52.             ("/filepathfield_test_dir/README", "README"),
    
  53.         ] + self.expected_choices[:4]
    
  54.         self.assertChoices(f, expected)
    
  55. 
    
  56.     def test_clean(self):
    
  57.         f = FilePathField(path=self.path)
    
  58.         msg = "'Select a valid choice. a.py is not one of the available choices.'"
    
  59.         with self.assertRaisesMessage(ValidationError, msg):
    
  60.             f.clean("a.py")
    
  61.         self.assertEqual(
    
  62.             fix_os_paths(f.clean(self.path + "a.py")), "/filepathfield_test_dir/a.py"
    
  63.         )
    
  64. 
    
  65.     def test_match(self):
    
  66.         f = FilePathField(path=self.path, match=r"^.*?\.py$")
    
  67.         self.assertChoices(f, self.expected_choices[:4])
    
  68. 
    
  69.     def test_recursive(self):
    
  70.         f = FilePathField(path=self.path, recursive=True, match=r"^.*?\.py$")
    
  71.         expected = [
    
  72.             ("/filepathfield_test_dir/__init__.py", "__init__.py"),
    
  73.             ("/filepathfield_test_dir/a.py", "a.py"),
    
  74.             ("/filepathfield_test_dir/ab.py", "ab.py"),
    
  75.             ("/filepathfield_test_dir/b.py", "b.py"),
    
  76.             ("/filepathfield_test_dir/c/__init__.py", "c/__init__.py"),
    
  77.             ("/filepathfield_test_dir/c/d.py", "c/d.py"),
    
  78.             ("/filepathfield_test_dir/c/e.py", "c/e.py"),
    
  79.             ("/filepathfield_test_dir/c/f/__init__.py", "c/f/__init__.py"),
    
  80.             ("/filepathfield_test_dir/c/f/g.py", "c/f/g.py"),
    
  81.             ("/filepathfield_test_dir/h/__init__.py", "h/__init__.py"),
    
  82.             ("/filepathfield_test_dir/j/__init__.py", "j/__init__.py"),
    
  83.         ]
    
  84.         self.assertChoices(f, expected)
    
  85. 
    
  86.     def test_allow_folders(self):
    
  87.         f = FilePathField(path=self.path, allow_folders=True, allow_files=False)
    
  88.         self.assertChoices(
    
  89.             f,
    
  90.             [
    
  91.                 ("/filepathfield_test_dir/c", "c"),
    
  92.                 ("/filepathfield_test_dir/h", "h"),
    
  93.                 ("/filepathfield_test_dir/j", "j"),
    
  94.             ],
    
  95.         )
    
  96. 
    
  97.     def test_recursive_no_folders_or_files(self):
    
  98.         f = FilePathField(
    
  99.             path=self.path, recursive=True, allow_folders=False, allow_files=False
    
  100.         )
    
  101.         self.assertChoices(f, [])
    
  102. 
    
  103.     def test_recursive_folders_without_files(self):
    
  104.         f = FilePathField(
    
  105.             path=self.path, recursive=True, allow_folders=True, allow_files=False
    
  106.         )
    
  107.         self.assertChoices(
    
  108.             f,
    
  109.             [
    
  110.                 ("/filepathfield_test_dir/c", "c"),
    
  111.                 ("/filepathfield_test_dir/h", "h"),
    
  112.                 ("/filepathfield_test_dir/j", "j"),
    
  113.                 ("/filepathfield_test_dir/c/f", "c/f"),
    
  114.             ],
    
  115.         )