Coverage for tests/test_row_labels.py: 100%
72 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 networkx as nx
2import pytest
4from sankey_cashflow import RowLabels
7class TestInit:
9 def test_init(self, sample_row_labels):
10 assert len(sample_row_labels.data) == 2
11 assert 'House' in sample_row_labels._lookup
12 assert 'Groceries' in sample_row_labels._lookup
13 assert isinstance(sample_row_labels._digraph, nx.DiGraph)
15 def test_missing_required_column_raises(self):
16 with pytest.raises(Exception):
17 RowLabels([{'Category Name': 'House', 'Type': 'computed'}])
19 def test_duplicate_category_name_raises(self):
20 row = {
21 'Category Name': 'House', 'Type': 'computed', 'Source': 'Income', 'Target': 'House',
22 'Classification': 'Expense', 'Link color': '', 'Node color': '', 'Comments': ''
23 }
24 with pytest.raises(Exception):
25 RowLabels([row, dict(row)])
27 def test_empty_category_name_is_skipped(self):
28 row = {
29 'Category Name': '', 'Type': '', 'Source': '', 'Target': '',
30 'Classification': '', 'Link color': '', 'Node color': '', 'Comments': ''
31 }
32 labels = RowLabels([row])
33 assert labels._lookup == {}
35 def test_deductions_source_skips_dag_edge(self):
36 row = {
37 'Category Name': '401K', 'Type': '', 'Source': 'DEDUCTIONS', 'Target': '401K',
38 'Classification': '', 'Link color': '', 'Node color': '', 'Comments': ''
39 }
40 labels = RowLabels([row])
41 assert not labels._digraph.has_edge('DEDUCTIONS', '401K')
42 assert '401K' in labels._lookup
44 def test_s_tag_adds_node_not_edge(self):
45 row = {
46 'Category Name': 'Joe', 'Type': 's-tag', 'Source': '', 'Target': '',
47 'Classification': '', 'Link color': '', 'Node color': '', 'Comments': ''
48 }
49 labels = RowLabels([row])
50 assert labels._digraph.has_node('Joe')
51 assert labels._digraph.nodes['Joe']['type'] == 's-tag'
53 def test_tag_type_not_added_to_dag(self):
54 row = {
55 'Category Name': 'Ford', 'Type': 'tag', 'Source': 'Automotive', 'Target': 'Ford',
56 'Classification': '', 'Link color': '', 'Node color': '', 'Comments': ''
57 }
58 labels = RowLabels([row])
59 assert not labels._digraph.has_node('Ford')
62class TestPaths:
64 def test_get_longest_path(self, sample_row_labels):
65 longest_path = sample_row_labels.get_longest_path()
66 assert isinstance(longest_path, list)
67 assert len(longest_path) >= 1
69 def test_get_path(self, sample_row_labels):
70 path = sample_row_labels.get_path('Income', 'House')
71 assert isinstance(path, list)
72 assert path == ['Income', 'House']
74 def test_get_path_no_match_returns_none(self, sample_row_labels):
75 assert sample_row_labels.get_path('House', 'Income') is None
78class TestLabelLookup:
80 def test_get_label(self, sample_row_labels):
81 label = sample_row_labels.get_label('House')
82 assert label is not None
83 assert label['source'] == 'Income'
84 assert label['target'] == 'House'
86 def test_get_label_unknown_returns_none(self, sample_row_labels):
87 assert sample_row_labels.get_label('Nonexistent') is None
89 def test_get_attribute(self, sample_row_labels):
90 assert sample_row_labels.get_attribute('House', 'source') == 'Income'
91 assert sample_row_labels.get_attribute('House', 'target') == 'House'
92 assert sample_row_labels.get_attribute('House', 'classification') == 'Expense'
94 def test_get_attribute_unknown_attribute_raises(self, sample_row_labels):
95 with pytest.raises(Exception):
96 sample_row_labels.get_attribute('House', 'not_a_real_attribute')
98 def test_get_attribute_missing_label_uses_default(self, sample_row_labels):
99 source = sample_row_labels.get_attribute('Nonexistent', 'source')
100 assert source == 'Uncategorized'
101 target = sample_row_labels.get_attribute('Nonexistent', 'target')
102 assert target == 'Nonexistent'
104 def test_get_attribute_missing_label_no_default_returns_none(self, sample_row_labels):
105 assert sample_row_labels.get_attribute('Nonexistent', 'source', use_default=False) is None
108class TestPrintGraph:
110 def test_print_graph_writes_file(self, sample_row_labels, tmp_path):
111 out_file = tmp_path / 'test_graph.png'
112 sample_row_labels.print_graph(str(out_file))
113 assert out_file.is_file()