import unittest
from budget_sync.config import Config
from budget_sync.test.mock_bug import MockBug
-from budget_sync.test.mock_path import MockPath, DIR
+from budget_sync.test.mock_path import MockFilesystem, MockPath, DIR
from budget_sync.test.test_mock_path import make_filesystem_and_report_if_error
from budget_sync.budget_graph import BudgetGraph
from budget_sync.write_budget_markdown import (
self.assertEqual(markdown_escape("abc * def_k < &k"),
r"abc \* def\_k < &k")
+ def format_files_dict(self, files):
+ assert isinstance(files, dict)
+ files_list: "list[str]" = []
+ for path, contents in files.items():
+ assert isinstance(path, str)
+ if contents is DIR:
+ files_list.append(f" {path!r}: DIR,")
+ continue
+ assert isinstance(contents, bytes)
+ lines: "list[str]" = []
+ for line in contents.splitlines(keepends=True):
+ lines.append(f" {line!r}")
+ if len(lines) == 0:
+ files_list.append(f" {path!r}: b'',")
+ else:
+ lines_str = '\n'.join(lines)
+ files_list.append(f" {path!r}: (\n{lines_str}\n ),")
+ if len(files_list) == 0:
+ return "{}"
+ return "{\n" + "\n".join(files_list) + "\n}"
+
+ def assertFiles(self, expected_files, filesystem: MockFilesystem):
+ files = filesystem.files
+ self.assertIsInstance(expected_files, dict)
+ if files == expected_files:
+ return
+ files_str = self.format_files_dict(files)
+ expected_files_str = self.format_files_dict(expected_files)
+ self.assertEqual(
+ files, expected_files,
+ msg=f"\nfiles:\n{files_str}\nexpected:\n{expected_files_str}")
+
def test(self):
config = Config.from_str(
"""
with make_filesystem_and_report_if_error(self) as filesystem:
output_dir = MockPath("/output_dir/", filesystem=filesystem)
write_budget_markdown(budget_graph, output_dir)
- self.assertEqual({
- "/": DIR,
- "/output_dir": DIR,
- '/output_dir/person1.mdwn': b'<!-- autogenerated by '
- b'budget-sync -->\n\n# Person One (person1)\n\n\n\n#'
- b' Status Tracking\n\n',
- '/output_dir/person2.mdwn': b'<!-- autogenerated by '
- b'budget-sync -->\n\n# Person Two (person2)\n\n\n\n#'
- b' Status Tracking\n\n',
- }, filesystem.files)
+ self.assertFiles({
+ '/': DIR,
+ '/output_dir': DIR,
+ '/output_dir/person1.mdwn': (
+ b'<!-- autogenerated by budget-sync -->\n'
+ b'\n'
+ b'# Person One (person1)\n'
+ b'\n'
+ b'\n'
+ b'\n'
+ b'# Status Tracking\n'
+ b'\n'
+ ),
+ '/output_dir/person2.mdwn': (
+ b'<!-- autogenerated by budget-sync -->\n'
+ b'\n'
+ b'# Person Two (person2)\n'
+ b'\n'
+ b'\n'
+ b'\n'
+ b'# Status Tracking\n'
+ b'\n'
+ ),
+ }, filesystem)
+
+ def test2(self):
+ config = Config.from_str(
+ """
+ bugzilla_url = "https://bugzilla.example.com/"
+ [milestones]
+ "milestone 1" = { canonical_bug_id = 1 }
+ [people."person1"]
+ email = "person1@example.com"
+ full_name = "Person One"
+ [people."person2"]
+ full_name = "Person Two"
+ """)
+ budget_graph = BudgetGraph([
+ MockBug(bug_id=1,
+ cf_budget_parent=None,
+ cf_budget="700",
+ cf_total_budget="1000",
+ cf_nlnet_milestone="milestone 1",
+ cf_payees_list="",
+ summary="",
+ assigned_to="person1@example.com",
+ cf_is_in_nlnet_mou2="Yes"),
+ MockBug(bug_id=2,
+ cf_budget_parent=1,
+ cf_budget="100",
+ cf_total_budget="300",
+ cf_nlnet_milestone="milestone 1",
+ cf_payees_list="person2 = 100",
+ summary="",
+ assigned_to="person1@example.com",
+ cf_is_in_nlnet_mou2="Yes"),
+ MockBug(bug_id=3,
+ cf_budget_parent=2,
+ cf_budget="100",
+ cf_total_budget="200",
+ cf_nlnet_milestone="milestone 1",
+ cf_payees_list="person1 = 100",
+ summary="",
+ assigned_to="person1@example.com"),
+ MockBug(bug_id=4,
+ cf_budget_parent=3,
+ cf_budget="100",
+ cf_total_budget="100",
+ cf_nlnet_milestone="milestone 1",
+ cf_payees_list="person2 = 100",
+ summary="",
+ assigned_to="person1@example.com"),
+ ], config)
+ self.assertEqual([], budget_graph.get_errors())
+ with make_filesystem_and_report_if_error(self) as filesystem:
+ output_dir = MockPath("/output_dir/", filesystem=filesystem)
+ write_budget_markdown(budget_graph, output_dir)
+ self.assertFiles({
+ '/': DIR,
+ '/output_dir': DIR,
+ '/output_dir/person1.mdwn': (
+ b'<!-- autogenerated by budget-sync -->\n'
+ b'\n'
+ b'# Person One (person1)\n'
+ b'\n'
+ b'\n'
+ b'\n'
+ b'# Status Tracking\n'
+ b'\n'
+ b'\n'
+ b'## Payment not yet submitted\n'
+ b'\n'
+ b'\n'
+ b'### milestone 1\n'
+ b'\n'
+ b'* [Bug #3](https://bugzilla.example.com/show_bug.cgi?id=3):\n'
+ b' \n'
+ b' * €100 which is the total amount\n'
+ b' * the closest parent task which is in the MoU is\n'
+ b' [Bug #2](https://bugzilla.example.com/show_bug.cgi?id=2)\n'
+ ),
+ '/output_dir/person2.mdwn': (
+ b'<!-- autogenerated by budget-sync -->\n'
+ b'\n'
+ b'# Person Two (person2)\n'
+ b'\n'
+ b'\n'
+ b'\n'
+ b'# Status Tracking\n'
+ b'\n'
+ b'\n'
+ b'## Payment not yet submitted\n'
+ b'\n'
+ b'\n'
+ b'### milestone 1\n'
+ b'\n'
+ b'* [Bug #2](https://bugzilla.example.com/show_bug.cgi?id=2):\n'
+ b' \n'
+ b' * €100 which is the total amount\n'
+ b' * this task is in the MoU\n'
+ b'* [Bug #4](https://bugzilla.example.com/show_bug.cgi?id=4):\n'
+ b' \n'
+ b' * €100 which is the total amount\n'
+ b' * the closest parent task which is in the MoU is\n'
+ b' [Bug #2](https://bugzilla.example.com/show_bug.cgi?id=2)\n'
+ ),
+ }, filesystem)
# TODO: add more test cases