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

1import library_skills.workspace as workspace 1TUVWXYZ01

2from library_skills.python_env import find_project_root 1TUVWXYZ01

3 

4 

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

9 

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

13 

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

23 

24 

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 ) 

49 

50 found = workspace.find_uv_workspace(nested_member) 1jklmnopqr

51 

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 ] 

59 

60 

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 ) 

89 

90 found = workspace.find_node_workspace(nested_member) 1abcdefghi

91 

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

100 

101 

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 ) 

111 

112 found = workspace.find_node_workspace(api) 1BCDEFGHIJ

113 

114 assert found is not None 1BCDEFGHIJ

115 assert found.root == project 1BCDEFGHIJ

116 assert found.members == (api.resolve(),) 1BCDEFGHIJ

117 

118 

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

123 

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

127 

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