Coverage for tests / unit / cli / test_bare_cli.py: 100%

76 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-02-16 21:32 +0000

1import json 

2from pathlib import Path 

3from unittest.mock import patch 

4 

5from graphable.cli.bare_cli import run_bare 

6 

7 

8def test_bare_cli_info(): 

9 """Verify info command in Bare CLI.""" 

10 with ( 

11 patch("graphable.cli.bare_cli.info_command") as mock_info, 

12 patch("sys.argv", ["graphable", "info", "test.json"]), 

13 patch("sys.exit"), 

14 ): 

15 mock_info.return_value = { 

16 "nodes": 2, 

17 "edges": 1, 

18 "sources": ["A"], 

19 "sinks": ["B"], 

20 "project_duration": 10.0, 

21 "critical_path_length": 2, 

22 } 

23 run_bare() 

24 mock_info.assert_called_once_with( 

25 Path("test.json"), tag=None, upstream_of=None, downstream_of=None 

26 ) 

27 

28 

29def test_bare_cli_check_valid(): 

30 """Verify check command (valid) in Bare CLI.""" 

31 with ( 

32 patch("graphable.cli.bare_cli.check_command") as mock_check, 

33 patch("sys.argv", ["graphable", "check", "test.json"]), 

34 patch("sys.exit"), 

35 ): 

36 mock_check.return_value = {"valid": True, "error": None} 

37 run_bare() 

38 mock_check.assert_called_once() 

39 

40 

41def test_bare_cli_check_invalid(): 

42 """Verify check command (invalid) in Bare CLI.""" 

43 with ( 

44 patch("graphable.cli.bare_cli.check_command") as mock_check, 

45 patch("sys.argv", ["graphable", "check", "test.json"]), 

46 patch("graphable.cli.bare_cli.exit") as mock_exit, 

47 ): 

48 mock_check.return_value = {"valid": False, "error": "Test error"} 

49 run_bare() 

50 mock_exit.assert_called_once_with(1) 

51 

52 

53def test_bare_cli_reduce(): 

54 """Verify reduce command in Bare CLI.""" 

55 with ( 

56 patch("graphable.cli.bare_cli.reduce_command") as mock_reduce, 

57 patch("sys.argv", ["graphable", "reduce", "i.json", "o.json"]), 

58 patch("sys.exit"), 

59 ): 

60 run_bare() 

61 mock_reduce.assert_called_once_with( 

62 Path("i.json"), 

63 Path("o.json"), 

64 embed_checksum=False, 

65 tag=None, 

66 upstream_of=None, 

67 downstream_of=None, 

68 ) 

69 

70 

71def test_bare_cli_convert(): 

72 """Verify convert command in Bare CLI.""" 

73 with ( 

74 patch("graphable.cli.bare_cli.convert_command") as mock_convert, 

75 patch("sys.argv", ["graphable", "convert", "i.json", "o.yaml"]), 

76 patch("sys.exit"), 

77 ): 

78 run_bare() 

79 mock_convert.assert_called_once_with( 

80 Path("i.json"), 

81 Path("o.yaml"), 

82 embed_checksum=False, 

83 tag=None, 

84 upstream_of=None, 

85 downstream_of=None, 

86 ) 

87 

88 

89def test_bare_cli_render(): 

90 """Verify render command in Bare CLI.""" 

91 with ( 

92 patch("graphable.cli.bare_cli.render_command") as mock_render, 

93 patch( 

94 "sys.argv", 

95 ["graphable", "render", "i.json", "o.png", "--engine", "mermaid"], 

96 ), 

97 patch("sys.exit"), 

98 ): 

99 run_bare() 

100 mock_render.assert_called_once_with( 

101 Path("i.json"), 

102 Path("o.png"), 

103 engine="mermaid", 

104 tag=None, 

105 upstream_of=None, 

106 downstream_of=None, 

107 ) 

108 

109 

110def test_bare_cli_checksum(): 

111 """Verify checksum command in Bare CLI.""" 

112 with ( 

113 patch("graphable.cli.bare_cli.checksum_command") as mock_checksum, 

114 patch("sys.argv", ["graphable", "checksum", "test.json"]), 

115 patch("sys.exit"), 

116 ): 

117 mock_checksum.return_value = "hash" 

118 run_bare() 

119 mock_checksum.assert_called_once_with( 

120 Path("test.json"), tag=None, upstream_of=None, downstream_of=None 

121 ) 

122 

123 

124def test_bare_cli_verify_success(): 

125 """Verify verify command (success) in Bare CLI.""" 

126 with ( 

127 patch("graphable.cli.bare_cli.verify_command") as mock_verify, 

128 patch("sys.argv", ["graphable", "verify", "test.json"]), 

129 patch("sys.exit"), 

130 ): 

131 mock_verify.return_value = {"valid": True, "actual": "abc", "expected": "abc"} 

132 run_bare() 

133 mock_verify.assert_called_once_with( 

134 Path("test.json"), 

135 None, 

136 tag=None, 

137 upstream_of=None, 

138 downstream_of=None, 

139 ) 

140 

141 

142def test_bare_cli_verify_mismatch(): 

143 """Verify verify command (mismatch) in Bare CLI.""" 

144 with ( 

145 patch("graphable.cli.bare_cli.verify_command") as mock_verify, 

146 patch("sys.argv", ["graphable", "verify", "test.json"]), 

147 patch("graphable.cli.bare_cli.exit") as mock_exit, 

148 ): 

149 mock_verify.return_value = {"valid": False, "actual": "abc", "expected": "def"} 

150 run_bare() 

151 mock_verify.assert_called_once_with( 

152 Path("test.json"), 

153 None, 

154 tag=None, 

155 upstream_of=None, 

156 downstream_of=None, 

157 ) 

158 mock_exit.assert_called_once_with(1) 

159 

160 

161def test_bare_cli_verify_no_checksum(): 

162 """Verify verify command (no checksum) in Bare CLI.""" 

163 with ( 

164 patch("graphable.cli.bare_cli.verify_command") as mock_verify, 

165 patch("sys.argv", ["graphable", "verify", "test.json"]), 

166 patch("sys.exit"), 

167 ): 

168 mock_verify.return_value = {"valid": None, "actual": "abc", "expected": None} 

169 run_bare() 

170 mock_verify.assert_called_once_with( 

171 Path("test.json"), 

172 None, 

173 tag=None, 

174 upstream_of=None, 

175 downstream_of=None, 

176 ) 

177 

178 

179def test_bare_cli_write_checksum(): 

180 """Verify write-checksum command in Bare CLI.""" 

181 with ( 

182 patch("graphable.cli.bare_cli.write_checksum_command") as mock_write, 

183 patch("sys.argv", ["graphable", "write-checksum", "test.json", "test.blake2b"]), 

184 patch("sys.exit"), 

185 ): 

186 run_bare() 

187 mock_write.assert_called_once_with( 

188 Path("test.json"), 

189 Path("test.blake2b"), 

190 tag=None, 

191 upstream_of=None, 

192 downstream_of=None, 

193 ) 

194 

195 

196def test_bare_cli_diff_default(): 

197 """Verify diff command (JSON output) in Bare CLI.""" 

198 with ( 

199 patch("graphable.cli.bare_cli.diff_command") as mock_diff, 

200 patch("sys.argv", ["graphable", "diff", "v1.json", "v2.json"]), 

201 patch("sys.exit"), 

202 patch("builtins.print") as mock_print, 

203 ): 

204 mock_diff.return_value = { 

205 "added_nodes": ["C"], 

206 "removed_nodes": [], 

207 "modified_nodes": [], 

208 "added_edges": [("A", "B")], 

209 "removed_edges": [], 

210 "modified_edges": [], 

211 } 

212 run_bare() 

213 # Verify JSON was printed 

214 printed_call = mock_print.call_args_list[-1][0][0] 

215 data = json.loads(printed_call) 

216 assert "added_nodes" in data 

217 assert "added_edges" in data 

218 

219 

220def test_bare_cli_diff_visual(): 

221 """Verify diff command (visual) in Bare CLI.""" 

222 with ( 

223 patch("graphable.cli.bare_cli.diff_visual_command") as mock_diff_visual, 

224 patch("sys.argv", ["graphable", "diff", "v1.json", "v2.json", "-o", "d.svg"]), 

225 patch("sys.exit"), 

226 ): 

227 run_bare() 

228 mock_diff_visual.assert_called_once() 

229 

230 

231def test_bare_cli_serve(): 

232 """Verify serve command in Bare CLI.""" 

233 with ( 

234 patch("graphable.cli.commands.serve.serve_command") as mock_serve, 

235 patch("sys.argv", ["graphable", "serve", "test.json"]), 

236 patch("sys.exit"), 

237 ): 

238 run_bare() 

239 mock_serve.assert_called_once() 

240 

241 

242def test_bare_cli_no_command(): 

243 """Verify help is shown when no command is provided in Bare CLI.""" 

244 with ( 

245 patch("argparse.ArgumentParser.print_help") as mock_help, 

246 patch("sys.argv", ["graphable"]), 

247 patch("sys.exit"), 

248 ): 

249 run_bare() 

250 assert mock_help.called