Coverage for tests / config / test_config_loader.py: 100%

95 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Tests for config_loader module.""" 

2 

3from pathlib import Path 

4 

5from assertpy import assert_that 

6 

7from lintro.config.config_loader import ( 

8 _convert_pyproject_to_config, 

9 _parse_defaults, 

10 _parse_enforce_config, 

11 _parse_execution_config, 

12 _parse_tool_config, 

13 _parse_tools_config, 

14 clear_config_cache, 

15 get_default_config, 

16 load_config, 

17) 

18 

19 

20def test_empty_data() -> None: 

21 """Should return EnforceConfig with None values.""" 

22 config = _parse_enforce_config({}) 

23 

24 assert_that(config.line_length).is_none() 

25 assert_that(config.target_python).is_none() 

26 

27 

28def test_execution_config_empty_data() -> None: 

29 """Should return execution config defaults.""" 

30 config = _parse_execution_config({}) 

31 

32 assert_that(config.enabled_tools).is_equal_to([]) 

33 assert_that(config.tool_order).is_equal_to("priority") 

34 assert_that(config.fail_fast).is_false() 

35 assert_that(config.parallel).is_true() 

36 

37 

38def test_string_enabled_tools() -> None: 

39 """Should convert single tool string to list.""" 

40 data = {"enabled_tools": "ruff"} 

41 

42 config = _parse_execution_config(data) 

43 

44 assert_that(config.enabled_tools).is_equal_to(["ruff"]) 

45 

46 

47def test_tool_config_empty_data() -> None: 

48 """Should return default ToolConfig.""" 

49 config = _parse_tool_config({}) 

50 

51 assert_that(config.enabled).is_true() 

52 assert_that(config.config_source).is_none() 

53 

54 

55def test_disabled_tool() -> None: 

56 """Should parse enabled=False.""" 

57 data = {"enabled": False} 

58 

59 config = _parse_tool_config(data) 

60 

61 assert_that(config.enabled).is_false() 

62 

63 

64def test_tools_config_empty_data() -> None: 

65 """Should return empty dict for tools config.""" 

66 config = _parse_tools_config({}) 

67 

68 assert_that(config).is_equal_to({}) 

69 

70 

71def test_with_bool_values() -> None: 

72 """Should handle bool as enabled flag.""" 

73 data = { 

74 "ruff": True, 

75 "prettier": False, 

76 } 

77 

78 config = _parse_tools_config(data) 

79 

80 assert_that(config["ruff"].enabled).is_true() 

81 assert_that(config["prettier"].enabled).is_false() 

82 

83 

84def test_defaults_empty_data() -> None: 

85 """Should return empty dict for defaults.""" 

86 defaults = _parse_defaults({}) 

87 

88 assert_that(defaults).is_equal_to({}) 

89 

90 

91def test_case_normalization() -> None: 

92 """Tool names should be lowercased.""" 

93 data = {"PRETTIER": {"singleQuote": True}} 

94 

95 defaults = _parse_defaults(data) 

96 

97 assert_that(defaults).contains("prettier") 

98 assert_that(defaults).does_not_contain("PRETTIER") 

99 

100 

101def test_convert_pyproject_empty_data() -> None: 

102 """Should return structure with empty sections.""" 

103 result = _convert_pyproject_to_config({}) 

104 

105 assert_that(result).contains("enforce") 

106 assert_that(result).contains("execution") 

107 assert_that(result).contains("defaults") 

108 assert_that(result).contains("tools") 

109 

110 

111def test_enforce_settings() -> None: 

112 """Should extract enforce settings.""" 

113 data = { 

114 "line_length": 88, 

115 "target_python": "py313", 

116 } 

117 

118 result = _convert_pyproject_to_config(data) 

119 

120 assert_that(result["enforce"]["line_length"]).is_equal_to(88) 

121 assert_that(result["enforce"]["target_python"]).is_equal_to("py313") 

122 

123 

124def test_tool_sections() -> None: 

125 """Should extract tool-specific sections.""" 

126 data = { 

127 "ruff": {"enabled": True}, 

128 "markdownlint": {"enabled": False}, 

129 } 

130 

131 result = _convert_pyproject_to_config(data) 

132 

133 assert_that(result["tools"]["ruff"]).is_equal_to({"enabled": True}) 

134 assert_that(result["tools"]["markdownlint"]).is_equal_to({"enabled": False}) 

135 

136 

137def test_execution_settings() -> None: 

138 """Should extract execution settings.""" 

139 data = { 

140 "tool_order": "alphabetical", 

141 "fail_fast": True, 

142 } 

143 

144 result = _convert_pyproject_to_config(data) 

145 

146 assert_that(result["execution"]["tool_order"]).is_equal_to("alphabetical") 

147 assert_that(result["execution"]["fail_fast"]).is_true() 

148 

149 

150def test_load_yaml_config_with_defaults(tmp_path: Path) -> None: 

151 """Should load .lintro-config.yaml file with defaults section. 

152 

153 Args: 

154 tmp_path: Temporary directory path for test files. 

155 """ 

156 config_content = """\ 

157defaults: 

158 prettier: 

159 singleQuote: true 

160 tabWidth: 2 

161""" 

162 config_file = tmp_path / ".lintro-config.yaml" 

163 config_file.write_text(config_content) 

164 

165 import os 

166 

167 original_cwd = os.getcwd() 

168 try: 

169 os.chdir(tmp_path) 

170 clear_config_cache() 

171 

172 config = load_config() 

173 

174 assert_that(config.get_tool_defaults("prettier")["singleQuote"]).is_true() 

175 assert_that(config.get_tool_defaults("prettier")["tabWidth"]).is_equal_to(2) 

176 finally: 

177 os.chdir(original_cwd) 

178 

179 

180def test_load_explicit_path(tmp_path: Path) -> None: 

181 """Should load from explicit path. 

182 

183 Args: 

184 tmp_path: Temporary directory path for test files. 

185 """ 

186 config_content = """\ 

187enforce: 

188 line_length: 120 

189""" 

190 config_file = tmp_path / "custom-config.yaml" 

191 config_file.write_text(config_content) 

192 

193 config = load_config(config_path=str(config_file)) 

194 

195 assert_that(config.enforce.line_length).is_equal_to(120) 

196 

197 

198def test_returns_default_when_no_config(tmp_path: Path) -> None: 

199 """Should return default config when no file found. 

200 

201 Args: 

202 tmp_path: Temporary directory path for test files. 

203 """ 

204 import os 

205 

206 original_cwd = os.getcwd() 

207 try: 

208 os.chdir(tmp_path) 

209 clear_config_cache() 

210 

211 config = load_config(allow_pyproject_fallback=False) 

212 

213 # Should get default empty config 

214 assert_that(config.enforce.line_length).is_none() 

215 finally: 

216 os.chdir(original_cwd) 

217 

218 

219def test_returns_sensible_defaults() -> None: 

220 """Should return config with sensible defaults.""" 

221 config = get_default_config() 

222 

223 assert_that(config.enforce.line_length).is_equal_to(88) 

224 # target_python is None to let tools infer from requires-python 

225 assert_that(config.enforce.target_python).is_none() 

226 assert_that(config.execution.tool_order).is_equal_to("priority")