Coverage for tests / test_workspace.py: 100%
78 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-03 20:19 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-03 20:19 +0000
1import library_skills.workspace as workspace 1TUVWXYZ01
2from library_skills.python_env import find_project_root 1TUVWXYZ01
5def test_find_uv_workspace_handles_invalid_and_missing_workspace_tables(tmp_path): 1TUVWXYZ01
6 project = tmp_path / "project" 1stuvwxyzA
7 project.mkdir() 1stuvwxyzA
8 pyproject = project / "pyproject.toml" 1stuvwxyzA
10 pyproject.write_text("[tool.uv.workspace\n", encoding="utf-8") 1stuvwxyzA
11 assert workspace.find_uv_workspace(project) is None 1stuvwxyzA
12 assert workspace._read_pyproject(pyproject) == {} 1stuvwxyzA
14 assert workspace._has_uv_workspace({}) is False 1stuvwxyzA
15 assert workspace._has_uv_workspace({"tool": {"uv": "not-table"}}) is False 1stuvwxyzA
16 assert workspace._find_workspace_members(project, {}) == [] 1stuvwxyzA
17 assert ( 1stuvwxyzA
18 workspace._find_workspace_members(project, {"tool": {"uv": {"workspace": {}}}})
19 == []
20 )
21 assert workspace._get_workspace_table({}) is None 1stuvwxyzA
22 assert workspace._get_workspace_table({"tool": {"uv": "not-table"}}) is None 1stuvwxyzA
25def test_find_uv_workspace_filters_members_and_selects_nearest_member(tmp_path): 1TUVWXYZ01
26 project = tmp_path / "project" 1jklmnopqr
27 api = project / "packages" / "api" 1jklmnopqr
28 nested_member = api / "plugins" / "demo" 1jklmnopqr
29 ignored = project / "packages" / "ignored" 1jklmnopqr
30 skipped = project / "packages" / "skip-one" 1jklmnopqr
31 not_project = project / "packages" / "not-project" 1jklmnopqr
32 file_match = project / "packages" / "file" 1jklmnopqr
33 for directory in (api, nested_member, ignored, skipped, not_project): 1jklmnopqr
34 directory.mkdir(parents=True) 1jklmnopqr
35 file_match.parent.mkdir(parents=True, exist_ok=True) 1jklmnopqr
36 file_match.write_text("not a directory", encoding="utf-8") 1jklmnopqr
37 for directory in (api, nested_member, ignored, skipped): 1jklmnopqr
38 (directory / "pyproject.toml").write_text( 1jklmnopqr
39 "[project]\nname = 'demo'\n", encoding="utf-8"
40 )
41 (project / "pyproject.toml").write_text( 1jklmnopqr
42 """
43[tool.uv.workspace]
44members = [1, "packages/*", "packages/api/plugins/*"]
45exclude = [1, "packages/ignored", "packages/skip-*"]
46""",
47 encoding="utf-8",
48 )
50 found = workspace.find_uv_workspace(nested_member) 1jklmnopqr
52 assert found is not None 1jklmnopqr
53 assert found.root == project 1jklmnopqr
54 assert found.members == (api.resolve(), nested_member.resolve()) 1jklmnopqr
55 assert found.current_member == nested_member.resolve() 1jklmnopqr
56 assert workspace.workspace_dependency_files(found) == [ 1jklmnopqr
57 nested_member.resolve() / "pyproject.toml"
58 ]
61def test_find_node_workspace_filters_members_and_selects_nearest_member(tmp_path): 1TUVWXYZ01
62 project = tmp_path / "project" 1abcdefghi
63 api = project / "packages" / "api" 1abcdefghi
64 nested_member = api / "plugins" / "demo" 1abcdefghi
65 ignored = project / "packages" / "ignored" 1abcdefghi
66 skipped = project / "packages" / "skip-one" 1abcdefghi
67 not_project = project / "packages" / "not-project" 1abcdefghi
68 file_match = project / "packages" / "file" 1abcdefghi
69 for directory in (api, nested_member, ignored, skipped, not_project): 1abcdefghi
70 directory.mkdir(parents=True) 1abcdefghi
71 file_match.parent.mkdir(parents=True, exist_ok=True) 1abcdefghi
72 file_match.write_text("not a directory", encoding="utf-8") 1abcdefghi
73 for directory in (api, nested_member, ignored): 1abcdefghi
74 (directory / "package.json").write_text('{"name": "demo"}', encoding="utf-8") 1abcdefghi
75 (project / "package.json").write_text( 1abcdefghi
76 """
77{
78 "workspaces": [
79 1,
80 "packages/*",
81 "packages/api/plugins/*",
82 "!packages/ignored",
83 "!packages/skip-*"
84 ]
85}
86""",
87 encoding="utf-8",
88 )
90 found = workspace.find_node_workspace(nested_member) 1abcdefghi
92 assert found is not None 1abcdefghi
93 assert found.root == project 1abcdefghi
94 assert found.members == (api.resolve(), nested_member.resolve()) 1abcdefghi
95 assert found.current_member == nested_member.resolve() 1abcdefghi
96 assert workspace.node_workspace_dependency_files(found) == [ 1abcdefghi
97 nested_member.resolve() / "package.json"
98 ]
99 assert find_project_root(nested_member) == project 1abcdefghi
102def test_find_node_workspace_supports_npm_object_form(tmp_path): 1TUVWXYZ01
103 project = tmp_path / "project" 1BCDEFGHIJ
104 api = project / "apps" / "api" 1BCDEFGHIJ
105 api.mkdir(parents=True) 1BCDEFGHIJ
106 (api / "package.json").write_text('{"name": "api"}', encoding="utf-8") 1BCDEFGHIJ
107 (project / "package.json").write_text( 1BCDEFGHIJ
108 '{"workspaces": {"packages": ["apps/*"]}}',
109 encoding="utf-8",
110 )
112 found = workspace.find_node_workspace(api) 1BCDEFGHIJ
114 assert found is not None 1BCDEFGHIJ
115 assert found.root == project 1BCDEFGHIJ
116 assert found.members == (api.resolve(),) 1BCDEFGHIJ
119def test_find_node_workspace_handles_invalid_and_non_object_package_json(tmp_path): 1TUVWXYZ01
120 project = tmp_path / "project" 1KLMNOPQRS
121 project.mkdir() 1KLMNOPQRS
122 package_json = project / "package.json" 1KLMNOPQRS
124 package_json.write_text("{", encoding="utf-8") 1KLMNOPQRS
125 assert workspace.find_node_workspace(project) is None 1KLMNOPQRS
126 assert workspace._read_package_json(package_json) == {} 1KLMNOPQRS
128 package_json.write_text("[]", encoding="utf-8") 1KLMNOPQRS
129 assert workspace.find_node_workspace(project) is None 1KLMNOPQRS
130 assert workspace._read_package_json(package_json) == {} 1KLMNOPQRS