|
| 1 | +import socketserver |
1 | 2 | import tempfile |
| 3 | +import threading |
| 4 | +import urllib.request |
2 | 5 | from pathlib import Path |
3 | 6 |
|
4 | 7 | from typer.testing import CliRunner |
5 | 8 |
|
6 | 9 | from rockgarden import __version__ |
7 | | -from rockgarden.cli import app |
| 10 | +from rockgarden.cli import _make_handler, app |
8 | 11 |
|
9 | 12 | runner = CliRunner() |
10 | 13 |
|
@@ -124,3 +127,59 @@ def test_build_unhandled_error_shows_type_and_message(tmp_path, monkeypatch): |
124 | 127 | assert result.exit_code == 1 |
125 | 128 | assert "RuntimeError: something broke" in result.output |
126 | 129 | assert "Traceback" not in result.output |
| 130 | + |
| 131 | + |
| 132 | +def _start_serve_server(output_dir): |
| 133 | + """Start the real rockgarden handler on an OS-assigned port.""" |
| 134 | + handler = _make_handler(output_dir) |
| 135 | + |
| 136 | + # Suppress request logging during tests |
| 137 | + handler.log_message = lambda self, *a, **kw: None # type: ignore[assignment] |
| 138 | + |
| 139 | + class ReuseAddrServer(socketserver.TCPServer): |
| 140 | + allow_reuse_address = True |
| 141 | + |
| 142 | + httpd = ReuseAddrServer(("127.0.0.1", 0), handler) |
| 143 | + port = httpd.server_address[1] |
| 144 | + thread = threading.Thread(target=httpd.serve_forever, daemon=True) |
| 145 | + thread.start() |
| 146 | + return httpd, port |
| 147 | + |
| 148 | + |
| 149 | +def test_serve_custom_404(tmp_path): |
| 150 | + output_dir = tmp_path / "_site" |
| 151 | + output_dir.mkdir() |
| 152 | + (output_dir / "index.html").write_text("<h1>Home</h1>") |
| 153 | + (output_dir / "404.html").write_text("<h1>Custom Not Found</h1>") |
| 154 | + |
| 155 | + httpd, port = _start_serve_server(output_dir) |
| 156 | + try: |
| 157 | + try: |
| 158 | + urllib.request.urlopen(f"http://127.0.0.1:{port}/nonexistent") |
| 159 | + except urllib.error.HTTPError as e: |
| 160 | + assert e.code == 404 |
| 161 | + body = e.read().decode() |
| 162 | + assert "Custom Not Found" in body |
| 163 | + else: |
| 164 | + raise AssertionError("Expected 404 HTTPError") |
| 165 | + finally: |
| 166 | + httpd.shutdown() |
| 167 | + |
| 168 | + |
| 169 | +def test_serve_default_404_without_custom_page(tmp_path): |
| 170 | + output_dir = tmp_path / "_site" |
| 171 | + output_dir.mkdir() |
| 172 | + (output_dir / "index.html").write_text("<h1>Home</h1>") |
| 173 | + |
| 174 | + httpd, port = _start_serve_server(output_dir) |
| 175 | + try: |
| 176 | + try: |
| 177 | + urllib.request.urlopen(f"http://127.0.0.1:{port}/nonexistent") |
| 178 | + except urllib.error.HTTPError as e: |
| 179 | + assert e.code == 404 |
| 180 | + body = e.read().decode() |
| 181 | + assert "Custom Not Found" not in body |
| 182 | + else: |
| 183 | + raise AssertionError("Expected 404 HTTPError") |
| 184 | + finally: |
| 185 | + httpd.shutdown() |
0 commit comments