BoilerWorks

boilerworks / tests / test_renderer.py
Source Blame History 183 lines
0cb4a5e… anonymous 1 """Tests for boilerworks.renderer."""
0cb4a5e… anonymous 2
0cb4a5e… anonymous 3 from __future__ import annotations
0cb4a5e… anonymous 4
0cb4a5e… anonymous 5 from pathlib import Path
0cb4a5e… anonymous 6
0cb4a5e… anonymous 7 from boilerworks.renderer import (
0cb4a5e… anonymous 8 _SKIP_DIRS,
0cb4a5e… anonymous 9 _SKIP_EXTENSIONS,
0cb4a5e… anonymous 10 build_replacements,
0cb4a5e… anonymous 11 rename_boilerworks_paths,
0cb4a5e… anonymous 12 render_directory,
0cb4a5e… anonymous 13 render_file,
0cb4a5e… anonymous 14 )
0cb4a5e… anonymous 15
0cb4a5e… anonymous 16
0cb4a5e… anonymous 17 class TestBuildReplacements:
0cb4a5e… anonymous 18 def test_lowercase_replacement(self) -> None:
0cb4a5e… anonymous 19 r = build_replacements("my-app")
0cb4a5e… anonymous 20 assert r["boilerworks"] == "my-app"
0cb4a5e… anonymous 21
0cb4a5e… anonymous 22 def test_uppercase_replacement(self) -> None:
0cb4a5e… anonymous 23 r = build_replacements("my-app")
0cb4a5e… anonymous 24 assert r["BOILERWORKS"] == "MY-APP"
0cb4a5e… anonymous 25
0cb4a5e… anonymous 26 def test_title_replacement(self) -> None:
0cb4a5e… anonymous 27 r = build_replacements("my-app")
0cb4a5e… anonymous 28 assert r["Boilerworks"] == "My-App"
0cb4a5e… anonymous 29
0cb4a5e… anonymous 30 def test_underscore_prefix_replacement(self) -> None:
0cb4a5e… anonymous 31 r = build_replacements("my-app")
0cb4a5e… anonymous 32 assert r["boilerworks_"] == "my_app_"
0cb4a5e… anonymous 33
0cb4a5e… anonymous 34 def test_underscore_suffix_replacement(self) -> None:
0cb4a5e… anonymous 35 r = build_replacements("my-app")
0cb4a5e… anonymous 36 assert r["_boilerworks"] == "_my_app"
0cb4a5e… anonymous 37
0cb4a5e… anonymous 38 def test_single_word_project(self) -> None:
0cb4a5e… anonymous 39 r = build_replacements("myapp")
0cb4a5e… anonymous 40 assert r["boilerworks"] == "myapp"
0cb4a5e… anonymous 41 assert r["BOILERWORKS"] == "MYAPP"
0cb4a5e… anonymous 42
0cb4a5e… anonymous 43
0cb4a5e… anonymous 44 class TestRenderFile:
0cb4a5e… anonymous 45 def test_replaces_lowercase(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 46 f = tmp_path / "test.txt"
0cb4a5e… anonymous 47 f.write_text("APP_NAME=boilerworks")
0cb4a5e… anonymous 48 replacements = build_replacements("my-app")
0cb4a5e… anonymous 49 changed = render_file(f, replacements)
0cb4a5e… anonymous 50 assert changed is True
0cb4a5e… anonymous 51 assert f.read_text() == "APP_NAME=my-app"
0cb4a5e… anonymous 52
0cb4a5e… anonymous 53 def test_replaces_uppercase(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 54 f = tmp_path / "test.env"
0cb4a5e… anonymous 55 f.write_text("DB_NAME=BOILERWORKS_DB")
0cb4a5e… anonymous 56 replacements = build_replacements("my-app")
0cb4a5e… anonymous 57 render_file(f, replacements)
0cb4a5e… anonymous 58 assert f.read_text() == "DB_NAME=MY-APP_DB"
0cb4a5e… anonymous 59
0cb4a5e… anonymous 60 def test_no_match_returns_false(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 61 f = tmp_path / "test.txt"
0cb4a5e… anonymous 62 f.write_text("hello world")
0cb4a5e… anonymous 63 changed = render_file(f, build_replacements("my-app"))
0cb4a5e… anonymous 64 assert changed is False
0cb4a5e… anonymous 65 assert f.read_text() == "hello world"
0cb4a5e… anonymous 66
0cb4a5e… anonymous 67 def test_empty_file_unchanged(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 68 f = tmp_path / "empty.txt"
0cb4a5e… anonymous 69 f.write_text("")
0cb4a5e… anonymous 70 changed = render_file(f, build_replacements("my-app"))
0cb4a5e… anonymous 71 assert changed is False
0cb4a5e… anonymous 72 assert f.read_text() == ""
0cb4a5e… anonymous 73
0cb4a5e… anonymous 74 def test_binary_extension_skipped(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 75 f = tmp_path / "image.png"
0cb4a5e… anonymous 76 f.write_bytes(b"\x89PNG boilerworks")
0cb4a5e… anonymous 77 changed = render_file(f, build_replacements("my-app"))
0cb4a5e… anonymous 78 assert changed is False
0cb4a5e… anonymous 79 # File content unchanged
0cb4a5e… anonymous 80 assert b"boilerworks" in f.read_bytes()
0cb4a5e… anonymous 81
0cb4a5e… anonymous 82 def test_lock_extension_skipped(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 83 f = tmp_path / "uv.lock"
0cb4a5e… anonymous 84 f.write_text("boilerworks = 1.0")
0cb4a5e… anonymous 85 changed = render_file(f, build_replacements("my-app"))
0cb4a5e… anonymous 86 assert changed is False
0cb4a5e… anonymous 87
0cb4a5e… anonymous 88 def test_multiple_replacements_in_one_file(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 89 f = tmp_path / "settings.py"
0cb4a5e… anonymous 90 content = "APP = 'boilerworks'\nNAME = 'Boilerworks'\nKEY = 'BOILERWORKS'"
0cb4a5e… anonymous 91 f.write_text(content)
0cb4a5e… anonymous 92 render_file(f, build_replacements("cool-app"))
0cb4a5e… anonymous 93 result = f.read_text()
0cb4a5e… anonymous 94 assert "cool-app" in result
0cb4a5e… anonymous 95 assert "Cool-App" in result
0cb4a5e… anonymous 96 assert "COOL-APP" in result
0cb4a5e… anonymous 97 assert "boilerworks" not in result
0cb4a5e… anonymous 98
0cb4a5e… anonymous 99 def test_case_variant_python_module(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 100 f = tmp_path / "settings.py"
0cb4a5e… anonymous 101 f.write_text("from boilerworks_config import settings")
0cb4a5e… anonymous 102 replacements = build_replacements("myproject")
0cb4a5e… anonymous 103 render_file(f, replacements)
0cb4a5e… anonymous 104 assert f.read_text() == "from myproject_config import settings"
0cb4a5e… anonymous 105
0cb4a5e… anonymous 106
0cb4a5e… anonymous 107 class TestRenderDirectory:
0cb4a5e… anonymous 108 def test_renders_text_files(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 109 (tmp_path / "app.py").write_text("APP = 'boilerworks'")
0cb4a5e… anonymous 110 (tmp_path / "README.md").write_text("# boilerworks\n")
0cb4a5e… anonymous 111 modified = render_directory(tmp_path, build_replacements("newapp"))
0cb4a5e… anonymous 112 assert len(modified) == 2
0cb4a5e… anonymous 113
0cb4a5e… anonymous 114 def test_skips_excluded_dirs(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 115 skip_dir = tmp_path / "node_modules"
0cb4a5e… anonymous 116 skip_dir.mkdir()
0cb4a5e… anonymous 117 (skip_dir / "file.js").write_text("module.exports = 'boilerworks'")
0cb4a5e… anonymous 118 modified = render_directory(tmp_path, build_replacements("newapp"))
0cb4a5e… anonymous 119 assert not any("node_modules" in str(p) for p in modified)
0cb4a5e… anonymous 120 # Original file unchanged
0cb4a5e… anonymous 121 assert "boilerworks" in (skip_dir / "file.js").read_text()
0cb4a5e… anonymous 122
0cb4a5e… anonymous 123 def test_skips_git_dir(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 124 git_dir = tmp_path / ".git"
0cb4a5e… anonymous 125 git_dir.mkdir()
0cb4a5e… anonymous 126 (git_dir / "config").write_text("url = boilerworks")
0cb4a5e… anonymous 127 modified = render_directory(tmp_path, build_replacements("newapp"))
0cb4a5e… anonymous 128 assert not any(".git" in str(p) for p in modified)
0cb4a5e… anonymous 129
0cb4a5e… anonymous 130 def test_skips_binary_extensions(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 131 (tmp_path / "logo.png").write_bytes(b"\x89PNG boilerworks")
0cb4a5e… anonymous 132 (tmp_path / "app.py").write_text("# boilerworks")
0cb4a5e… anonymous 133 modified = render_directory(tmp_path, build_replacements("newapp"))
0cb4a5e… anonymous 134 modified_names = [p.name for p in modified]
0cb4a5e… anonymous 135 assert "logo.png" not in modified_names
0cb4a5e… anonymous 136 assert "app.py" in modified_names
0cb4a5e… anonymous 137
0cb4a5e… anonymous 138 def test_nested_directories(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 139 subdir = tmp_path / "src" / "config"
0cb4a5e… anonymous 140 subdir.mkdir(parents=True)
0cb4a5e… anonymous 141 (subdir / "settings.py").write_text("APP = 'boilerworks'")
0cb4a5e… anonymous 142 modified = render_directory(tmp_path, build_replacements("newapp"))
0cb4a5e… anonymous 143 assert len(modified) == 1
0cb4a5e… anonymous 144 assert (subdir / "settings.py").read_text() == "APP = 'newapp'"
0cb4a5e… anonymous 145
0cb4a5e… anonymous 146
0cb4a5e… anonymous 147 class TestRenameBoilerworksPaths:
0cb4a5e… anonymous 148 def test_renames_file_with_boilerworks(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 149 f = tmp_path / "boilerworks.iml"
0cb4a5e… anonymous 150 f.write_text("")
0cb4a5e… anonymous 151 renames = rename_boilerworks_paths(tmp_path, "my-project")
0cb4a5e… anonymous 152 assert len(renames) == 1
0cb4a5e… anonymous 153 assert not (tmp_path / "boilerworks.iml").exists()
0cb4a5e… anonymous 154 assert (tmp_path / "my-project.iml").exists()
0cb4a5e… anonymous 155
0cb4a5e… anonymous 156 def test_renames_directory_with_boilerworks(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 157 subdir = tmp_path / "boilerworks_config"
0cb4a5e… anonymous 158 subdir.mkdir()
0cb4a5e… anonymous 159 (subdir / "settings.py").write_text("")
0cb4a5e… anonymous 160 rename_boilerworks_paths(tmp_path, "myproject")
0cb4a5e… anonymous 161 assert not (tmp_path / "boilerworks_config").exists()
0cb4a5e… anonymous 162 assert (tmp_path / "myproject_config").exists()
0cb4a5e… anonymous 163
0cb4a5e… anonymous 164 def test_no_boilerworks_paths_unchanged(self, tmp_path: Path) -> None:
0cb4a5e… anonymous 165 f = tmp_path / "other_file.txt"
0cb4a5e… anonymous 166 f.write_text("content")
0cb4a5e… anonymous 167 renames = rename_boilerworks_paths(tmp_path, "myproject")
0cb4a5e… anonymous 168 assert len(renames) == 0
0cb4a5e… anonymous 169 assert f.exists()
0cb4a5e… anonymous 170
0cb4a5e… anonymous 171
0cb4a5e… anonymous 172 class TestSkipSets:
0cb4a5e… anonymous 173 def test_skip_dirs_contains_expected(self) -> None:
0cb4a5e… anonymous 174 assert ".git" in _SKIP_DIRS
0cb4a5e… anonymous 175 assert "node_modules" in _SKIP_DIRS
0cb4a5e… anonymous 176 assert "__pycache__" in _SKIP_DIRS
0cb4a5e… anonymous 177 assert ".venv" in _SKIP_DIRS
0cb4a5e… anonymous 178
0cb4a5e… anonymous 179 def test_skip_extensions_contains_expected(self) -> None:
0cb4a5e… anonymous 180 assert ".png" in _SKIP_EXTENSIONS
0cb4a5e… anonymous 181 assert ".lock" in _SKIP_EXTENSIONS
0cb4a5e… anonymous 182 assert ".pyc" in _SKIP_EXTENSIONS
0cb4a5e… anonymous 183 assert ".woff" in _SKIP_EXTENSIONS

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button