diff --git a/.gitignore b/.gitignore index 5ac43f5e..356f859a 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,4 @@ pyproject.toml # Python environment .venv/ +.DS_Store diff --git a/django_components/management/__init__.py b/django_components/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/django_components/management/commands/__init__.py b/django_components/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/django_test_setup.py b/tests/django_test_setup.py index 421e3d9e..447ac100 100644 --- a/tests/django_test_setup.py +++ b/tests/django_test_setup.py @@ -14,7 +14,12 @@ if not settings.configured: MIDDLEWARE=[ "django_components.middleware.ComponentDependencyMiddleware" ], - DATABASES={}, + DATABASES={ + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": ":memory:", + } + }, ) django.setup() diff --git a/tests/test_startcomponent_command.py b/tests/test_startcomponent_command.py new file mode 100644 index 00000000..39831765 --- /dev/null +++ b/tests/test_startcomponent_command.py @@ -0,0 +1,123 @@ +import os +import tempfile +from io import StringIO +from shutil import rmtree + +from django.core.management import call_command +from django.core.management.base import CommandError +from django.test import TestCase + +from .django_test_setup import * # NOQA + + +class CreateComponentCommandTest(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.temp_dir = tempfile.mkdtemp() + + @classmethod + def tearDownClass(cls): + super().tearDownClass() + rmtree(cls.temp_dir) + + def test_default_file_names(self): + component_name = "defaultcomponent" + call_command("startcomponent", component_name, "--path", self.temp_dir) + + expected_files = [ + os.path.join(self.temp_dir, component_name, "script.js"), + os.path.join(self.temp_dir, component_name, "style.css"), + os.path.join(self.temp_dir, component_name, "template.html"), + ] + for file_path in expected_files: + self.assertTrue(os.path.exists(file_path)) + + def test_nondefault_creation(self): + component_name = "testcomponent" + call_command( + "startcomponent", + component_name, + "--path", + self.temp_dir, + "--js", + "test.js", + "--css", + "test.css", + "--template", + "test.html", + ) + + expected_files = [ + os.path.join(self.temp_dir, component_name, "test.js"), + os.path.join(self.temp_dir, component_name, "test.css"), + os.path.join(self.temp_dir, component_name, "test.html"), + os.path.join( + self.temp_dir, component_name, f"{component_name}.py" + ), + ] + + for file_path in expected_files: + self.assertTrue( + os.path.exists(file_path), f"File {file_path} was not created" + ) + + def test_dry_run(self): + component_name = "dryruncomponent" + call_command( + "startcomponent", + component_name, + "--path", + self.temp_dir, + "--dry-run", + ) + + component_path = os.path.join(self.temp_dir, component_name) + self.assertFalse(os.path.exists(component_path)) + + def test_force_overwrite(self): + component_name = "existingcomponent" + component_path = os.path.join(self.temp_dir, component_name) + os.makedirs(component_path) + + with open( + os.path.join(component_path, f"{component_name}.py"), "w" + ) as f: + f.write("hello world") + + call_command( + "startcomponent", + component_name, + "--path", + self.temp_dir, + "--force", + ) + + with open( + os.path.join(component_path, f"{component_name}.py"), "r" + ) as f: + self.assertNotIn("hello world", f.read()) + + def test_error_existing_component_no_force(self): + component_name = "existingcomponent_2" + component_path = os.path.join(self.temp_dir, component_name) + os.makedirs(component_path) + + with self.assertRaises(CommandError): + call_command( + "startcomponent", component_name, "--path", self.temp_dir + ) + + def test_verbose_output(self): + component_name = "verbosecomponent" + out = StringIO() + call_command( + "startcomponent", + component_name, + "--path", + self.temp_dir, + "--verbose", + stdout=out, + ) + output = out.getvalue() + self.assertIn("component at", output)