tests.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. """
  2. A series of tests to establish that the command-line bash completion works.
  3. """
  4. import os
  5. import sys
  6. import unittest
  7. from django.apps import apps
  8. from django.core.management import ManagementUtility
  9. from django.test.utils import captured_stdout
  10. class BashCompletionTests(unittest.TestCase):
  11. """
  12. Testing the Python level bash completion code.
  13. This requires setting up the environment as if we got passed data
  14. from bash.
  15. """
  16. def setUp(self):
  17. self.old_DJANGO_AUTO_COMPLETE = os.environ.get('DJANGO_AUTO_COMPLETE')
  18. os.environ['DJANGO_AUTO_COMPLETE'] = '1'
  19. def tearDown(self):
  20. if self.old_DJANGO_AUTO_COMPLETE:
  21. os.environ['DJANGO_AUTO_COMPLETE'] = self.old_DJANGO_AUTO_COMPLETE
  22. else:
  23. del os.environ['DJANGO_AUTO_COMPLETE']
  24. def _user_input(self, input_str):
  25. """
  26. Set the environment and the list of command line arguments.
  27. This sets the bash variables $COMP_WORDS and $COMP_CWORD. The former is
  28. an array consisting of the individual words in the current command
  29. line, the latter is the index of the current cursor position, so in
  30. case a word is completed and the cursor is placed after a whitespace,
  31. $COMP_CWORD must be incremented by 1:
  32. * 'django-admin start' -> COMP_CWORD=1
  33. * 'django-admin startproject' -> COMP_CWORD=1
  34. * 'django-admin startproject ' -> COMP_CWORD=2
  35. """
  36. os.environ['COMP_WORDS'] = input_str
  37. idx = len(input_str.split(' ')) - 1 # Index of the last word
  38. comp_cword = idx + 1 if input_str.endswith(' ') else idx
  39. os.environ['COMP_CWORD'] = str(comp_cword)
  40. sys.argv = input_str.split()
  41. def _run_autocomplete(self):
  42. util = ManagementUtility(argv=sys.argv)
  43. with captured_stdout() as stdout:
  44. try:
  45. util.autocomplete()
  46. except SystemExit:
  47. pass
  48. return stdout.getvalue().strip().split('\n')
  49. def test_django_admin_py(self):
  50. "django_admin.py will autocomplete option flags"
  51. self._user_input('django-admin sqlmigrate --verb')
  52. output = self._run_autocomplete()
  53. self.assertEqual(output, ['--verbosity='])
  54. def test_manage_py(self):
  55. "manage.py will autocomplete option flags"
  56. self._user_input('manage.py sqlmigrate --verb')
  57. output = self._run_autocomplete()
  58. self.assertEqual(output, ['--verbosity='])
  59. def test_custom_command(self):
  60. "A custom command can autocomplete option flags"
  61. self._user_input('django-admin test_command --l')
  62. output = self._run_autocomplete()
  63. self.assertEqual(output, ['--list'])
  64. def test_subcommands(self):
  65. "Subcommands can be autocompleted"
  66. self._user_input('django-admin sql')
  67. output = self._run_autocomplete()
  68. self.assertEqual(output, ['sqlflush sqlmigrate sqlsequencereset'])
  69. def test_completed_subcommand(self):
  70. "Show option flags in case a subcommand is completed"
  71. self._user_input('django-admin startproject ') # Trailing whitespace
  72. output = self._run_autocomplete()
  73. for item in output:
  74. self.assertTrue(item.startswith('--'))
  75. def test_help(self):
  76. "No errors, just an empty list if there are no autocomplete options"
  77. self._user_input('django-admin help --')
  78. output = self._run_autocomplete()
  79. self.assertEqual(output, [''])
  80. def test_app_completion(self):
  81. "Application names will be autocompleted for an AppCommand"
  82. self._user_input('django-admin sqlmigrate a')
  83. output = self._run_autocomplete()
  84. a_labels = sorted(app_config.label
  85. for app_config in apps.get_app_configs()
  86. if app_config.label.startswith('a'))
  87. self.assertEqual(output, a_labels)