chore: enhance project initialization by adding post-task handling and improving file overwrite behavior
Some checks failed
CI / test (3.13) (push) Failing after 31s
Some checks failed
CI / test (3.13) (push) Failing after 31s
This commit is contained in:
@@ -20,7 +20,6 @@ import jinja2
|
||||
from jinja2 import Environment, FileSystemLoader, StrictUndefined
|
||||
|
||||
from quickbot_cli.cli import (
|
||||
apply_optionals,
|
||||
ask_variables,
|
||||
load_template_spec,
|
||||
render_tree,
|
||||
@@ -237,38 +236,71 @@ class TestEdgeCases:
|
||||
|
||||
mock_subprocess_run.assert_not_called()
|
||||
|
||||
def test_apply_optionals_with_missing_directories(self, temp_dir: Path) -> None:
|
||||
"""Test apply_optionals with missing directories."""
|
||||
# Don't create any directories, just test the function
|
||||
apply_optionals(temp_dir, include_alembic=False, include_i18n=False)
|
||||
|
||||
# Should not raise any errors
|
||||
def test_post_tasks_with_missing_directories(self, temp_dir: Path) -> None:
|
||||
"""Post tasks should tolerate missing directories and files."""
|
||||
spec = {
|
||||
"post_tasks": [
|
||||
{
|
||||
"when": "{{ not include_alembic }}",
|
||||
"run": [
|
||||
"rm",
|
||||
"-rf",
|
||||
"alembic",
|
||||
"scripts/migrations_apply.sh",
|
||||
"scripts/migrations_generate.sh",
|
||||
],
|
||||
},
|
||||
{
|
||||
"when": "{{ not include_i18n }}",
|
||||
"run": [
|
||||
"rm",
|
||||
"-rf",
|
||||
"locales",
|
||||
"scripts/babel_compile.sh",
|
||||
"scripts/babel_extract.sh",
|
||||
"scripts/babel_init.sh",
|
||||
"scripts/babel_update.sh",
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
run_post_tasks(spec, {"include_alembic": False, "include_i18n": False}, temp_dir)
|
||||
assert True
|
||||
|
||||
def test_apply_optionals_with_partial_structure(self, temp_dir: Path) -> None:
|
||||
"""Test apply_optionals with partial directory structure."""
|
||||
# Create only some of the expected directories
|
||||
def test_post_tasks_with_partial_structure(self, temp_dir: Path) -> None:
|
||||
"""Post tasks should handle partial directory structure."""
|
||||
(temp_dir / "alembic").mkdir()
|
||||
(temp_dir / "scripts").mkdir()
|
||||
(temp_dir / "scripts" / "migrations_generate.sh").write_text("script")
|
||||
|
||||
# Don't create locales or babel scripts
|
||||
|
||||
apply_optionals(temp_dir, include_alembic=False, include_i18n=True)
|
||||
|
||||
# Alembic should be removed
|
||||
spec = {
|
||||
"post_tasks": [
|
||||
{
|
||||
"when": "{{ not include_alembic }}",
|
||||
"run": [
|
||||
"rm",
|
||||
"-rf",
|
||||
"alembic",
|
||||
"scripts/migrations_generate.sh",
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
run_post_tasks(spec, {"include_alembic": False}, temp_dir)
|
||||
assert not (temp_dir / "alembic").exists()
|
||||
assert not (temp_dir / "scripts" / "migrations_generate.sh").exists()
|
||||
|
||||
def test_apply_optionals_with_files_instead_of_directories(self, temp_dir: Path) -> None:
|
||||
"""Test apply_optionals with files instead of directories."""
|
||||
# Create files with names that match expected directories
|
||||
def test_post_tasks_with_files_instead_of_directories(self, temp_dir: Path) -> None:
|
||||
"""Post tasks should remove files named like directories as well."""
|
||||
(temp_dir / "alembic").write_text("not a directory")
|
||||
(temp_dir / "locales").write_text("not a directory")
|
||||
|
||||
apply_optionals(temp_dir, include_alembic=False, include_i18n=False)
|
||||
|
||||
# Files should be removed
|
||||
spec = {
|
||||
"post_tasks": [
|
||||
{"when": "{{ not include_alembic }}", "run": ["rm", "-rf", "alembic"]},
|
||||
{"when": "{{ not include_i18n }}", "run": ["rm", "-rf", "locales"]},
|
||||
]
|
||||
}
|
||||
run_post_tasks(spec, {"include_alembic": False, "include_i18n": False}, temp_dir)
|
||||
assert not (temp_dir / "alembic").exists()
|
||||
assert not (temp_dir / "locales").exists()
|
||||
|
||||
@@ -302,12 +334,14 @@ class TestErrorHandling:
|
||||
with pytest.raises((SystemExit, Exception)):
|
||||
ask_variables(spec, non_interactive)
|
||||
|
||||
def test_render_tree_with_file_exists_error(self, temp_dir: Path) -> None:
|
||||
"""Test that render_tree raises FileExistsError when overwrite is disabled."""
|
||||
def test_render_tree_skips_existing_when_overwrite_disabled(
|
||||
self, temp_dir: Path, mock_typer_secho: MagicMock
|
||||
) -> None:
|
||||
"""Existing files are skipped (not overwritten) when overwrite is disabled."""
|
||||
template_root = temp_dir / "template"
|
||||
template_root.mkdir()
|
||||
|
||||
template_file = template_root / "main.py.j2"
|
||||
template_file = template_root / "main.py"
|
||||
template_file.write_text("app = FastAPI(title='{{ project_name }}')")
|
||||
|
||||
output_dir = temp_dir / "output"
|
||||
@@ -320,8 +354,13 @@ class TestErrorHandling:
|
||||
context: dict[str, Any] = {"project_name": "test"}
|
||||
env = Environment(autoescape=True)
|
||||
|
||||
with pytest.raises(FileExistsError):
|
||||
render_tree(env, template_root, output_dir, context, overwrite=False)
|
||||
render_tree(env, template_root, output_dir, context, overwrite=False)
|
||||
# Ensure original content remains
|
||||
assert (output_dir / "main.py").read_text() == "existing content"
|
||||
# Should show warning
|
||||
mock_typer_secho.assert_called_with(
|
||||
f"Warning: Skipping existing file: {output_dir / 'main.py'}", fg=typer.colors.YELLOW
|
||||
)
|
||||
|
||||
def test_render_tree_with_jinja_render_error(self, temp_dir: Path, mock_typer_secho: MagicMock) -> None:
|
||||
"""Test that render_tree logs and re-raises when Jinja rendering fails."""
|
||||
@@ -418,23 +457,23 @@ class TestBoundaryConditions:
|
||||
)
|
||||
assert deep_file.exists()
|
||||
|
||||
def test_apply_optionals_with_many_files(self, temp_dir: Path) -> None:
|
||||
"""Test apply_optionals with many files to process."""
|
||||
# Create many files
|
||||
def test_post_tasks_with_many_files(self, temp_dir: Path) -> None:
|
||||
"""Post tasks should remove only specific optional module directories."""
|
||||
for i in range(100):
|
||||
(temp_dir / f"file_{i}.txt").write_text(f"content {i}")
|
||||
|
||||
# Create the expected structure
|
||||
(temp_dir / "alembic").mkdir()
|
||||
(temp_dir / "locales").mkdir()
|
||||
|
||||
# Should not raise any errors
|
||||
apply_optionals(temp_dir, include_alembic=False, include_i18n=False)
|
||||
|
||||
# Only the specific optional modules should be removed, not the random files
|
||||
spec = {
|
||||
"post_tasks": [
|
||||
{"when": "{{ not include_alembic }}", "run": ["rm", "-rf", "alembic"]},
|
||||
{"when": "{{ not include_i18n }}", "run": ["rm", "-rf", "locales"]},
|
||||
]
|
||||
}
|
||||
run_post_tasks(spec, {"include_alembic": False, "include_i18n": False}, temp_dir)
|
||||
assert not (temp_dir / "alembic").exists()
|
||||
assert not (temp_dir / "locales").exists()
|
||||
# Random files should still exist
|
||||
assert (temp_dir / "file_0.txt").exists()
|
||||
assert (temp_dir / "file_50.txt").exists()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user