Skip to content

Commit 4faca52

Browse files
fix(template): add .env bootstrap and devcontainer validation tests
Add initializeCommand to copy .env.example when .env is missing so devcontainer starts without manual setup. Add tests to verify rendered devcontainer JSON and YAML are valid across all option combinations.
1 parent 8ef0fca commit 4faca52

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

‎template/.devcontainer/devcontainer.json.jinja‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
],
77
"service": "web",
88
"workspaceFolder": "/app",
9+
"initializeCommand": "if [ ! -f .env ] && [ -f .env.example ]; then cp .env.example .env; fi",
910
"forwardPorts": [
1011
8000,
1112
5432,

‎tests/test_generation.py‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Functional tests for template project generation."""
22

3+
import json
34
import py_compile
45

56
import pytest
@@ -313,3 +314,64 @@ def test_both_auth_backends(generate):
313314
content = settings.read_text()
314315
assert "allauth" in content
315316
assert "simplejwt" in content or "SIMPLE_JWT" in content
317+
318+
319+
# Devcontainer Tests
320+
321+
322+
def test_devcontainer_files_exist(generate):
323+
"""Test that devcontainer files are always generated."""
324+
project = generate()
325+
assert (project / ".devcontainer/devcontainer.json").exists()
326+
assert (project / ".devcontainer/docker-compose.devcontainer.yml").exists()
327+
328+
329+
def test_devcontainer_json_is_valid_minimal(generate):
330+
"""Test that devcontainer.json is valid JSON with minimal options."""
331+
project = generate(cache="none", frontend="none", background_tasks="none", observability_level="minimal")
332+
content = (project / ".devcontainer/devcontainer.json").read_text()
333+
config = json.loads(content)
334+
assert config["service"] == "web"
335+
assert 8000 in config["forwardPorts"]
336+
assert 6379 not in config["forwardPorts"]
337+
338+
339+
def test_devcontainer_json_is_valid_all_options(generate):
340+
"""Test that devcontainer.json is valid JSON with all conditional options enabled."""
341+
project = generate(
342+
cache="redis",
343+
frontend="htmx-tailwind",
344+
frontend_bundling="vite",
345+
background_tasks="temporal",
346+
observability_level="full",
347+
)
348+
content = (project / ".devcontainer/devcontainer.json").read_text()
349+
config = json.loads(content)
350+
assert 6379 in config["forwardPorts"]
351+
assert 5173 in config["forwardPorts"]
352+
assert 7233 in config["forwardPorts"]
353+
assert 16686 in config["forwardPorts"]
354+
355+
356+
def test_devcontainer_compose_override_is_valid_yaml(generate):
357+
"""Test that the devcontainer compose override is valid YAML."""
358+
project = generate()
359+
content = (project / ".devcontainer/docker-compose.devcontainer.yml").read_text()
360+
config = yaml.safe_load(content)
361+
assert config["services"]["web"]["command"] == "sleep infinity"
362+
363+
364+
def test_devcontainer_uv_interpreter_path(generate):
365+
"""Test that uv projects use the venv interpreter path."""
366+
project = generate(dependency_manager="uv")
367+
content = (project / ".devcontainer/devcontainer.json").read_text()
368+
config = json.loads(content)
369+
assert config["customizations"]["vscode"]["settings"]["python.defaultInterpreterPath"] == "/app/.venv/bin/python"
370+
371+
372+
def test_devcontainer_poetry_interpreter_path(generate):
373+
"""Test that Poetry projects use the system interpreter path."""
374+
project = generate(dependency_manager="poetry")
375+
content = (project / ".devcontainer/devcontainer.json").read_text()
376+
config = json.loads(content)
377+
assert config["customizations"]["vscode"]["settings"]["python.defaultInterpreterPath"] == "/usr/local/bin/python"

0 commit comments

Comments
 (0)