feat: add all domain layers (dotfiles, packages, remote, containers)
- Dotfiles: models, module resolution, path resolution, link planning - Packages: models, catalog parsing, resolution, install/remove planning - Remote: target parsing, SSH command building - Containers: image refs, mount resolution, container specs All domain code is pure functions + frozen dataclasses. 88 tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
99
tests/test_domain_dotfiles_modules.py
Normal file
99
tests/test_domain_dotfiles_modules.py
Normal file
@@ -0,0 +1,99 @@
|
||||
"""Tests for dotfiles module resolution -- the core bug fix."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from flow.core.errors import ConfigError
|
||||
from flow.domain.dotfiles.modules import (
|
||||
compute_mount_path,
|
||||
module_cache_dir,
|
||||
normalize_source,
|
||||
parse_module_ref,
|
||||
)
|
||||
|
||||
|
||||
class TestComputeMountPath:
|
||||
def test_nested_module(self):
|
||||
"""_shared/nvim/.config/nvim/_module.yaml -> .config/nvim"""
|
||||
result = compute_mount_path(
|
||||
module_yaml=Path("/dots/_shared/nvim/.config/nvim/_module.yaml"),
|
||||
package_dir=Path("/dots/_shared/nvim"),
|
||||
)
|
||||
assert result == Path(".config/nvim")
|
||||
|
||||
def test_root_level_module(self):
|
||||
"""_shared/nvim/_module.yaml -> Path('.')"""
|
||||
result = compute_mount_path(
|
||||
module_yaml=Path("/dots/_shared/nvim/_module.yaml"),
|
||||
package_dir=Path("/dots/_shared/nvim"),
|
||||
)
|
||||
assert result == Path(".")
|
||||
|
||||
def test_deeply_nested(self):
|
||||
result = compute_mount_path(
|
||||
module_yaml=Path("/dots/_shared/pkg/.config/a/b/c/_module.yaml"),
|
||||
package_dir=Path("/dots/_shared/pkg"),
|
||||
)
|
||||
assert result == Path(".config/a/b/c")
|
||||
|
||||
|
||||
class TestModuleCacheDir:
|
||||
def test_simple_name(self):
|
||||
result = module_cache_dir("_shared/nvim", Path("/home/x/.local/share/flow/modules"))
|
||||
assert result == Path("/home/x/.local/share/flow/modules/_shared--nvim")
|
||||
|
||||
def test_profile_name(self):
|
||||
result = module_cache_dir("linux-work/nvim", Path("/m"))
|
||||
assert result == Path("/m/linux-work--nvim")
|
||||
|
||||
|
||||
class TestNormalizeSource:
|
||||
def test_github_shorthand(self):
|
||||
assert normalize_source("github:org/repo") == "https://github.com/org/repo.git"
|
||||
|
||||
def test_full_url_passthrough(self):
|
||||
assert normalize_source("https://example.com/repo.git") == "https://example.com/repo.git"
|
||||
|
||||
def test_ssh_passthrough(self):
|
||||
assert normalize_source("git@github.com:org/repo.git") == "git@github.com:org/repo.git"
|
||||
|
||||
|
||||
class TestParseModuleRef:
|
||||
def test_branch_ref(self):
|
||||
raw = {"source": "github:org/nvim-config", "ref": {"branch": "main"}}
|
||||
ref = parse_module_ref(
|
||||
raw, package_id="_shared/nvim",
|
||||
mount_path=Path(".config/nvim"),
|
||||
modules_base=Path("/modules"),
|
||||
)
|
||||
assert ref.source == "https://github.com/org/nvim-config.git"
|
||||
assert ref.ref_type == "branch"
|
||||
assert ref.ref_value == "main"
|
||||
assert ref.mount_path == Path(".config/nvim")
|
||||
assert ref.cache_dir == Path("/modules/_shared--nvim")
|
||||
|
||||
def test_tag_ref(self):
|
||||
raw = {"source": "github:org/repo", "ref": {"tag": "v1.0"}}
|
||||
ref = parse_module_ref(raw, "p/x", Path("."), Path("/m"))
|
||||
assert ref.ref_type == "tag"
|
||||
assert ref.ref_value == "v1.0"
|
||||
|
||||
def test_missing_source_raises(self):
|
||||
with pytest.raises(ConfigError):
|
||||
parse_module_ref({}, "p/x", Path("."), Path("/m"))
|
||||
|
||||
def test_missing_ref_raises(self):
|
||||
raw = {"source": "github:org/repo"}
|
||||
with pytest.raises(ConfigError):
|
||||
parse_module_ref(raw, "p/x", Path("."), Path("/m"))
|
||||
|
||||
def test_ref_not_dict_raises(self):
|
||||
raw = {"source": "github:org/repo", "ref": "main"}
|
||||
with pytest.raises(ConfigError):
|
||||
parse_module_ref(raw, "p/x", Path("."), Path("/m"))
|
||||
|
||||
def test_ambiguous_ref_raises(self):
|
||||
raw = {"source": "github:org/repo", "ref": {"branch": "main", "tag": "v1"}}
|
||||
with pytest.raises(ConfigError):
|
||||
parse_module_ref(raw, "p/x", Path("."), Path("/m"))
|
||||
Reference in New Issue
Block a user