diff --git a/ofx_processor/utils/ynab.py b/ofx_processor/utils/ynab.py index 01b5c48..641595a 100644 --- a/ofx_processor/utils/ynab.py +++ b/ofx_processor/utils/ynab.py @@ -72,7 +72,7 @@ def push_transactions(transactions, account): created = set() for transaction in data["transactions"]: - matched_id = transaction["matched_transaction_id"] + matched_id = transaction.get("matched_transaction_id") if not matched_id or matched_id not in created: created.add(transaction["id"]) diff --git a/tests/test_end_to_end.py b/tests/test_end_to_end.py index 6ac102b..eb27189 100644 --- a/tests/test_end_to_end.py +++ b/tests/test_end_to_end.py @@ -7,6 +7,7 @@ from click.testing import CliRunner from ofx_processor.processors.bpvf import BpvfProcessor from ofx_processor.processors.ce import CeProcessor from ofx_processor.processors.revolut import RevolutProcessor +from ofx_processor.utils import utils from ofx_processor.utils import ynab from ofx_processor.utils.ynab import config @@ -51,3 +52,133 @@ class ConfigEditTestCase(unittest.TestCase): runner.invoke(cli, ["config", "edit"]) edit.assert_called_once_with(filename=expected_filename) + + +class DataTestCase(unittest.TestCase): + @mock.patch("requests.post") + def test_revolut_sends_data_only_created(self, post): + ynab.DEFAULT_CONFIG_DIR = "tests/samples" + post.return_value.json.return_value = { + "data": { + "transactions": [ + { + "id": "ynab_existing:1", + "matched_transaction_id": "imported_matched:2", + }, + { + "id": "imported_matched:2", + "matched_transaction_id": "ynab_existing:1", + }, + { + "id": "imported_matched:3", + "matched_transaction_id": "ynab_existing:4", + }, + { + "id": "ynab_existing:4", + "matched_transaction_id": "imported_matched:3", + }, + {"id": "created:5", "matched_transaction_id": None}, + {"id": "created:6", "matched_transaction_id": None}, + {"id": "created:7", "matched_transaction_id": None}, + {"id": "created:8", "matched_transaction_id": None}, + {"id": "created:9", "matched_transaction_id": None}, + {"id": "created:10", "matched_transaction_id": None}, + {"id": "created:11", "matched_transaction_id": None}, + ], + "duplicate_import_ids": [], + } + } + from ofx_processor.main import cli + + # This is run at import time and the cli module is already imported before this test + # so we need to re-run the add_command to make it available. + utils.discover_processors(cli) + + runner = CliRunner() + result = runner.invoke(cli, ["revolut", "tests/samples/revolut.csv"]) + + self.assertEqual(result.exit_code, 0) + self.assertIn("Processed 9 transactions total.", result.output) + self.assertIn("9 transactions created in YNAB.", result.output) + self.assertNotIn("transactions ignored (duplicates).", result.output) + + @mock.patch("requests.post") + def test_revolut_sends_data_some_created_some_duplicates(self, post): + ynab.DEFAULT_CONFIG_DIR = "tests/samples" + post.return_value.json.return_value = { + "data": { + "transactions": [ + { + "id": "ynab_existing:1", + "matched_transaction_id": "imported_matched:2", + }, + { + "id": "imported_matched:2", + "matched_transaction_id": "ynab_existing:1", + }, + { + "id": "imported_matched:3", + "matched_transaction_id": "ynab_existing:4", + }, + { + "id": "ynab_existing:4", + "matched_transaction_id": "imported_matched:3", + }, + {"id": "created:5", "matched_transaction_id": None}, + ], + "duplicate_import_ids": [ + "duplicate:6", + "duplicate:7", + "duplicate:8", + "duplicate:9", + "duplicate:10", + "duplicate:11", + ], + } + } + from ofx_processor.main import cli + + # This is run at import time and the cli module is already imported before this test + # so we need to re-run the add_command to make it available. + utils.discover_processors(cli) + + runner = CliRunner() + result = runner.invoke(cli, ["revolut", "tests/samples/revolut.csv"]) + + self.assertEqual(result.exit_code, 0) + self.assertIn("Processed 9 transactions total.", result.output) + self.assertIn("3 transactions created in YNAB.", result.output) + self.assertIn("6 transactions ignored (duplicates).", result.output) + + @mock.patch("requests.post") + def test_revolut_sends_data_only_duplicates(self, post): + ynab.DEFAULT_CONFIG_DIR = "tests/samples" + post.return_value.json.return_value = { + "data": { + "transactions": [], + "duplicate_import_ids": [ + "duplicate:1", + "duplicate:2", + "duplicate:3", + "duplicate:4", + "duplicate:5", + "duplicate:6", + "duplicate:7", + "duplicate:8", + "duplicate:9", + ], + } + } + from ofx_processor.main import cli + + # This is run at import time and the cli module is already imported before this test + # so we need to re-run the add_command to make it available. + utils.discover_processors(cli) + + runner = CliRunner() + result = runner.invoke(cli, ["revolut", "tests/samples/revolut.csv"]) + + self.assertEqual(result.exit_code, 0) + self.assertIn("Processed 9 transactions total.", result.output) + self.assertNotIn("transactions created in YNAB.", result.output) + self.assertIn("9 transactions ignored (duplicates).", result.output) diff --git a/tests/test_revolut_processor.py b/tests/test_revolut_processor.py index a3366a8..5760a7e 100644 --- a/tests/test_revolut_processor.py +++ b/tests/test_revolut_processor.py @@ -85,16 +85,5 @@ class RevolutProcessorTestCase(unittest.TestCase): self.assertListEqual(transactions, expected_transactions) -# class RevolutEndToEndTestCase(unittest.TestCase): -# def test_data_sent_to_ynab(self): -# with open("tests/samples/config.ini") as config_file: -# config_content = config_file.read() -# -# with mock.patch("__main__.open", mock.mock_open(read_data=config_content)) as m: -# pass -# print(config_content) -# self.assertTrue(False) - - if __name__ == "__main__": unittest.main() # pragma: nocover