"""Tests for containers domain.""" from pathlib import Path from flow.domain.containers.models import ContainerSpec, ImageRef, Mount from flow.domain.containers.resolution import ( build_container_spec, container_name, parse_image_ref, resolve_mounts, ) class TestParseImageRef: def test_simple_name(self): ref = parse_image_ref("devbox") assert ref.registry == "registry.tomastm.com" assert ref.repo == "devbox" assert ref.tag == "latest" def test_with_tag(self): ref = parse_image_ref("devbox:v2") assert ref.tag == "v2" def test_full_ref(self): ref = parse_image_ref("ghcr.io/user/image:main") assert ref.registry == "ghcr.io" assert ref.repo == "user/image" assert ref.tag == "main" def test_full_image_string(self): ref = parse_image_ref("devbox") assert ref.full == "registry.tomastm.com/devbox:latest" class TestContainerName: def test_basic(self): assert container_name("devbox") == "dev-devbox" class TestResolveMounts: def test_projects_mount(self, tmp_path): projects = tmp_path / "projects" projects.mkdir() mounts = resolve_mounts( tmp_path, filesystem_check=lambda p: p.exists(), project_path=str(projects), ) project_mounts = [m for m in mounts if m.target == "/workspace"] assert len(project_mounts) == 1 def test_dotfiles_mount(self, tmp_path): dotfiles = tmp_path / "dotfiles" dotfiles.mkdir() mounts = resolve_mounts( tmp_path, filesystem_check=lambda p: p.exists(), dotfiles_dir=dotfiles, ) assert any(m.target.endswith("/flow/dotfiles") for m in mounts) def test_socket_path_mount(self, tmp_path): sock = tmp_path / "docker.sock" sock.write_text("") mounts = resolve_mounts( tmp_path, filesystem_check=lambda p: p.exists(), socket_path=sock, ) socket_mounts = [m for m in mounts if m.target == "/var/run/docker.sock"] assert len(socket_mounts) == 1 assert socket_mounts[0].source == sock def test_no_socket_path(self, tmp_path): mounts = resolve_mounts(tmp_path, filesystem_check=lambda p: p.exists()) assert not any(m.target == "/var/run/docker.sock" for m in mounts) def test_filesystem_check_controls_standard_mounts(self, tmp_path): mounts = resolve_mounts(tmp_path, filesystem_check=lambda p: False) # No standard mounts present when filesystem_check returns False. assert not any(m.target == "/home/dev/.ssh" for m in mounts) assert not any(m.target.endswith("/flow/dotfiles") for m in mounts) class TestBuildContainerSpec: def test_basic(self): image = ImageRef(registry="reg", repo="img", tag="v1", label="reg/img") spec = build_container_spec("api", image, []) assert spec.name == "dev-api" assert spec.labels["dev.name"] == "api" def test_with_mounts(self): image = ImageRef(registry="reg", repo="img", tag="v1", label="reg/img") mounts = [Mount(source=Path("/a"), target="/b")] spec = build_container_spec("api", image, mounts) assert len(spec.mounts) == 1 class TestMount: def test_fields(self): m = Mount(source=Path("/src"), target="/dst") assert m.source == Path("/src") assert m.target == "/dst" assert m.readonly is False def test_readonly(self): m = Mount(source=Path("/src"), target="/dst", readonly=True) assert m.readonly is True