Coverage for tests / unit / ai / test_paths.py: 100%
43 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Tests for AI path utilities."""
3from __future__ import annotations
5import os
6from pathlib import PurePosixPath
8from assertpy import assert_that
10from lintro.ai.paths import (
11 OUTSIDE_WORKSPACE_SENTINEL,
12 relative_path,
13 resolve_workspace_file,
14 resolve_workspace_root,
15 to_provider_path,
16)
19def _normalize(path: str) -> str:
20 """Normalize a path to POSIX form for cross-platform comparison."""
21 return str(PurePosixPath(path.replace("\\", "/")))
24def test_paths_relative_for_cwd_child():
25 """Verify absolute path under cwd is converted to a relative path."""
26 cwd = os.getcwd()
27 abs_path = os.path.join(cwd, "src", "main.py")
28 result = relative_path(abs_path)
29 assert_that(_normalize(result)).is_equal_to("src/main.py")
32def test_paths_already_relative():
33 """Verify an already-relative path is returned unchanged."""
34 result = relative_path("src/main.py")
35 assert_that(_normalize(result)).is_equal_to("src/main.py")
38def test_paths_relative_on_empty():
39 """Verify relative_path handles an empty string without raising."""
40 result = relative_path("")
41 assert_that(result).is_type_of(str)
44def test_paths_resolve_workspace_root_from_config(tmp_path):
45 """Verify workspace root is resolved as the parent directory of the config file."""
46 config = tmp_path / ".lintro-config.yaml"
47 config.write_text("ai:\n enabled: true\n", encoding="utf-8")
49 root = resolve_workspace_root(str(config))
50 assert_that(root).is_equal_to(tmp_path.resolve())
53def test_paths_resolve_workspace_file_accepts_inside(tmp_path):
54 """Verify a file inside the workspace root resolves successfully."""
55 inside = tmp_path / "src" / "main.py"
56 inside.parent.mkdir(parents=True)
57 inside.write_text("x = 1\n", encoding="utf-8")
59 resolved = resolve_workspace_file(str(inside), tmp_path)
60 assert_that(resolved).is_equal_to(inside.resolve())
63def test_paths_resolve_workspace_file_rejects_outside(tmp_path):
64 """Paths outside the workspace root are rejected."""
65 outside = tmp_path.parent / "outside-lintro-paths.py"
66 resolved = resolve_workspace_file(str(outside), tmp_path)
67 assert_that(resolved).is_none()
70def test_paths_to_provider_path_is_workspace_relative(tmp_path):
71 """Verify to_provider_path returns a workspace-relative path."""
72 file_path = tmp_path / "pkg" / "module.py"
73 file_path.parent.mkdir(parents=True)
74 file_path.write_text("x = 1\n", encoding="utf-8")
76 provider_path = to_provider_path(str(file_path), tmp_path)
77 assert_that(_normalize(provider_path)).is_equal_to("pkg/module.py")
80def test_paths_to_provider_path_falls_back_without_leaking_absolute(tmp_path):
81 """Absolute paths outside workspace return the sentinel marker."""
82 outside_path = str(tmp_path.parent / "secret" / "main.py")
83 provider_path = to_provider_path(outside_path, tmp_path)
84 assert_that(provider_path).is_equal_to(OUTSIDE_WORKSPACE_SENTINEL)