Coverage for tests/test_cli.py: 100%
75 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-05 04:36 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-05 04:36 +0000
1import pytest
3import sankey_cashflow.cli as cli_module
4from sankey_cashflow.cli import build_arg_parser
7class TestBuildArgParser:
9 def test_defaults(self):
10 args = build_arg_parser().parse_args([])
11 assert args.source is None
12 assert args.sheet is None
13 assert args.srcmap is None
14 assert args.range is False
15 assert args.separate_tax is False
16 assert args.verbose is False
17 assert args.creds is None
18 assert args.distributions is False
19 assert args.tags is None
20 assert args.exclude is None
21 assert args.tag_override is False
22 assert args.stores is None
23 assert args.all_time is False
24 assert args.feed_in is False
25 assert args.audit is False
26 assert args.recurring is False
27 assert args.hover is None
28 assert args.dtype is None
30 def test_parses_source_and_srcmap(self):
31 args = build_arg_parser().parse_args(['-s', 'data.csv', '--srcmap', 'labels.csv'])
32 assert args.source == 'data.csv'
33 assert args.srcmap == 'labels.csv'
35 def test_parses_store_true_flags(self):
36 args = build_arg_parser().parse_args([
37 '-r', '--separate_tax', '-v', '--distributions', '--tag_override',
38 '--all_time', '--feed_in', '--audit', '--recurring'
39 ])
40 assert args.range is True
41 assert args.separate_tax is True
42 assert args.verbose is True
43 assert args.distributions is True
44 assert args.tag_override is True
45 assert args.all_time is True
46 assert args.feed_in is True
47 assert args.audit is True
48 assert args.recurring is True
50 def test_parses_string_options(self):
51 args = build_arg_parser().parse_args([
52 '--tags', 'Ford, Dodge', '--exclude', 'Onetime', '--stores', "Trader Joe's",
53 '--hover', 'Description', '--dtype', 'line', '--creds', 'creds.json', '-t', 'Sheet1'
54 ])
55 assert args.tags == 'Ford, Dodge'
56 assert args.exclude == 'Onetime'
57 assert args.stores == "Trader Joe's"
58 assert args.hover == 'Description'
59 assert args.dtype == 'line'
60 assert args.creds == 'creds.json'
61 assert args.sheet == 'Sheet1'
64class TestMainEndToEnd:
65 """
66 Integration tests driving cli.main() the same way the installed `sankeyd` command would,
67 against sample_data/. save_report() and Figure.show() are stubbed out so tests don't write
68 report files into the repo or try to open a browser.
69 """
71 def test_main_runs_sankey_pipeline(self, monkeypatch):
72 monkeypatch.setattr(cli_module, 'save_report', lambda *a, **kw: None)
73 shown = []
74 monkeypatch.setattr('plotly.graph_objects.Figure.show', lambda self, *a, **kw: shown.append(True))
75 cli_module.main([
76 '--source', 'sample_data/expenses.csv', '--srcmap', 'sample_data/labels.csv', '--all_time'
77 ])
78 assert shown == [True]
80 def test_main_runs_line_pipeline(self, monkeypatch):
81 monkeypatch.setattr(cli_module, 'save_report', lambda *a, **kw: None)
82 monkeypatch.setattr('builtins.input', lambda *a, **kw: 'week')
83 shown = []
84 monkeypatch.setattr('plotly.graph_objects.Figure.show', lambda self, *a, **kw: shown.append(True))
85 cli_module.main([
86 '--source', 'sample_data/expenses.csv', '--srcmap', 'sample_data/labels.csv', '--all_time',
87 '--dtype', 'line'
88 ])
89 assert shown == [True]
91 def test_main_audit_mode_exits_without_generating_diagram(self, monkeypatch, tmp_path):
92 monkeypatch.setattr(cli_module, 'save_report', lambda *a, **kw: None)
93 audit_csv = tmp_path / 'bank.csv'
94 audit_csv.write_text('Date,Amount,Description\n1/1/23,-4000.00,Boeing\n')
95 monkeypatch.setattr('builtins.input', lambda *a, **kw: str(audit_csv))
96 shown = []
97 monkeypatch.setattr('plotly.graph_objects.Figure.show', lambda self, *a, **kw: shown.append(True))
98 with pytest.raises(SystemExit):
99 cli_module.main([
100 '--source', 'sample_data/expenses.csv', '--srcmap', 'sample_data/labels.csv',
101 '--all_time', '--audit'
102 ])
103 assert shown == []
105 def test_main_invalid_source_raises(self):
106 # Fails during AppSettings construction/validation, before any fetch_data() call -
107 # this is a plain Exception, not the SystemExit that fetch_data()'s own failure path raises.
108 with pytest.raises(Exception):
109 cli_module.main(['--source', 'does_not_exist.csv'])