# tests/test_docker_build.py import os import shutil import subprocess import sys import time import pytest import requests IMAGE_NAME = "manual_slop:test" CONTAINER_NAME = "manual_slop_test_container" WEB_PORT = 18080 HOOK_PORT = 18999 def _docker_daemon_ready() -> bool: result = subprocess.run( ["docker", "info"], capture_output=True, text=True, timeout=10, ) return result.returncode == 0 def _start_docker_desktop() -> bool: if sys.platform != "win32": return False docker_paths = [ os.path.expandvars(r"%ProgramFiles%\Docker\Docker\Docker Desktop.exe"), os.path.expandvars(r"%LOCALAPPDATA%\Docker\Docker Desktop.exe"), r"C:\Program Files\Docker\Docker\Docker Desktop.exe", r"C:\Users\Ed\AppData\Local\Docker\Docker Desktop.exe", ] for path in docker_paths: if os.path.exists(path): try: subprocess.Popen([path], shell=False) return True except Exception: pass service_result = subprocess.run( ["net", "start", "com.docker.service"], capture_output=True, text=True, timeout=10, ) if service_result.returncode == 0: return True return False def _wait_for_docker(timeout: int = 60) -> bool: start = time.time() while time.time() - start < timeout: if _docker_daemon_ready(): return True time.sleep(2) return False @pytest.fixture(scope="module") def ensure_docker(): """Ensure Docker daemon is running before running tests.""" if os.environ.get("RUN_DOCKER_TEST") != "1": pytest.skip("Set RUN_DOCKER_TEST=1 to enable") if not shutil.which("docker"): pytest.skip("Docker CLI not installed") if _docker_daemon_ready(): yield return started = _start_docker_desktop() if not started: pytest.skip( "Docker daemon not running and Docker Desktop not found/installed. " "Please install Docker Desktop on this system." ) ready = _wait_for_docker() if not ready: pytest.skip("Docker daemon did not become ready within 60s") yield @pytest.mark.docker def test_docker_image_builds(ensure_docker, tmp_path): """Build the Docker image. Slow; opt-in.""" repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) result = subprocess.run( ["docker", "build", "-t", IMAGE_NAME, "."], cwd=repo_root, capture_output=True, text=True, timeout=600, ) assert result.returncode == 0, f"Docker build failed: {result.stderr}" @pytest.mark.docker def test_docker_container_starts_and_responds(ensure_docker): """Run the container, verify web and hook endpoints respond.""" _cleanup_container() repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) result = subprocess.run( [ "docker", "run", "-d", "--name", CONTAINER_NAME, "-p", f"{WEB_PORT}:8080", "-p", f"{HOOK_PORT}:8999", IMAGE_NAME, ], cwd=repo_root, capture_output=True, text=True, timeout=30, ) assert result.returncode == 0, f"Docker run failed: {result.stderr}" try: start = time.time() ready = False while time.time() - start < 90: try: r = requests.get(f"http://127.0.0.1:{HOOK_PORT}/status", timeout=1) if r.status_code == 200: ready = True break except (requests.ConnectionError, requests.Timeout): pass time.sleep(1) assert ready, "Container hook API did not respond within 90s" r = requests.get(f"http://127.0.0.1:{WEB_PORT}/", timeout=5) assert r.status_code == 200 body = r.content.lower() assert b" None: subprocess.run( ["docker", "rm", "-f", CONTAINER_NAME], capture_output=True, )