diff --git a/.gitignore b/.gitignore index 41af326..cd571e1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ lib .DS_Store .mm .monarchmoney.egg-info +.pytest_cache .venv .vscode *.pyc diff --git a/tests/get_account_holdings.json b/tests/get_account_holdings.json new file mode 100644 index 0000000..119e2c2 --- /dev/null +++ b/tests/get_account_holdings.json @@ -0,0 +1,117 @@ +{ + "portfolio": { + "aggregateHoldings": { + "edges": [ + { + "node": { + "id": "800000001", + "quantity": 101, + "basis": 101, + "totalValue": 202, + "securityPriceChangeDollars": null, + "securityPriceChangePercent": null, + "lastSyncedAt": "2024-02-18", + "holdings": [ + { + "id": "9000000001", + "type": null, + "typeDisplay": "ETF", + "name": "iShares S&P CA AMT-Free Municipal Bd", + "ticker": "CMF", + "closingPrice": 2, + "isManual": false, + "closingPriceUpdatedAt": "2024-02-16T00:00:00+00:00", + "__typename": "Holding" + } + ], + "security": { + "id": "80084056431098865", + "name": "iShares S&P CA AMT-Free Municipal Bd", + "type": "etf", + "ticker": "CMF", + "typeDisplay": "ETF", + "currentPrice": 2, + "currentPriceUpdatedAt": "2024-02-16T21:00:04.365428+00:00", + "closingPrice": 2, + "closingPriceUpdatedAt": "2023-12-06T00:00:00+00:00", + "oneDayChangePercent": 0.01, + "oneDayChangeDollars": 0.02, + "__typename": "Security" + }, + "__typename": "AggregateHolding" + }, + "__typename": "AggregateHoldingEdge" + }, + { + "node": { + "id": "700000002", + "quantity": 100.0, + "basis": 10.0, + "totalValue": 10000.0, + "securityPriceChangeDollars": null, + "securityPriceChangePercent": null, + "lastSyncedAt": "2024-02-18", + "holdings": [ + { + "id": "140451241456451803", + "type": null, + "typeDisplay": "Stock", + "name": "Alphabet Inc - Ordinary Shares - Class C", + "ticker": "GOOG", + "closingPrice": 100.00, + "isManual": false, + "closingPriceUpdatedAt": "2024-02-16T00:00:00+00:00", + "__typename": "Holding" + } + ], + "security": { + "id": "78663618892209419", + "name": "Google Inc.", + "type": "equity", + "ticker": "GOOG", + "typeDisplay": "Stock", + "currentPrice": 100.00, + "currentPriceUpdatedAt": "2024-02-16T21:05:46.879464+00:00", + "closingPrice": 100.00, + "closingPriceUpdatedAt": "2023-12-07T07:00:00+00:00", + "oneDayChangePercent": 0, + "oneDayChangeDollars": 0, + "__typename": "Security" + }, + "__typename": "AggregateHolding" + }, + "__typename": "AggregateHoldingEdge" + }, + { + "node": { + "id": "92233844174242672", + "quantity": 5000, + "basis": 0.0, + "totalValue": 5000, + "securityPriceChangeDollars": null, + "securityPriceChangePercent": null, + "lastSyncedAt": "2024-02-18", + "holdings": [ + { + "id": "92233844174242672", + "type": null, + "typeDisplay": "Cash", + "name": "U S Dollar", + "ticker": "CUR:USD", + "closingPrice": null, + "isManual": false, + "closingPriceUpdatedAt": null, + "__typename": "Holding" + } + ], + "security": null, + "__typename": "AggregateHolding" + }, + "__typename": "AggregateHoldingEdge" + } + ], + "__typename": "AggregateHoldingConnection" + }, + "__typename": "Portfolio" + } +} \ No newline at end of file diff --git a/tests/test_monarchmoney.py b/tests/test_monarchmoney.py index 5c62af6..c0bed65 100644 --- a/tests/test_monarchmoney.py +++ b/tests/test_monarchmoney.py @@ -130,6 +130,49 @@ async def test_get_account_type_options(self, mock_execute_async): "Expected third account type option name to be 'real_estate'", ) + @patch.object(Client, "execute_async") + async def test_get_account_holdings(self, mock_execute_async): + """ + Test the get_account_holdings method. + """ + # Mock the execute_async method to return a test result + mock_execute_async.return_value = TestMonarchMoney.loadTestData( + filename="get_account_holdings.json", + ) + + # Call the get_account_holdings method + result = await self.monarch_money.get_account_holdings(account_id=1234) + + # Assert that the execute_async method was called once + mock_execute_async.assert_called_once() + + # Assert that the result is not None + self.assertIsNotNone(result, "Expected result to not be None") + + # Assert that the result matches the expected output + self.assertEqual( + len(result["portfolio"]["aggregateHoldings"]["edges"]), + 3, + "Expected 3 holdings", + ) + self.assertEqual( + result["portfolio"]["aggregateHoldings"]["edges"][0]["node"]["quantity"], + 101, + "Expected first holding to be 101 in quantity", + ) + self.assertEqual( + result["portfolio"]["aggregateHoldings"]["edges"][1]["node"]["totalValue"], + 10000, + "Expected second holding to be 10000 in total value", + ) + self.assertEqual( + result["portfolio"]["aggregateHoldings"]["edges"][2]["node"]["holdings"][0][ + "name" + ], + "U S Dollar", + "Expected third holding name to be 'U S Dollar'", + ) + @classmethod def loadTestData(cls, filename) -> dict: filename = f"{os.path.dirname(os.path.realpath(__file__))}/{filename}"