import os import time import unittest from unittest.mock import Mock, patch import app import max_api URL = "https://max.ru/vkontakte/AaE-viFyB3E" MID = "mid.ffffc217ccd5157d01a13ebe21720771" PAGE = ''' ''' def page_response(): return Mock(status_code=200, text=PAGE) class MaxPublicPostTests(unittest.TestCase): def test_hydration_and_message_id(self): title, channel_id = max_api.parse_public_post(PAGE, "vkontakte") self.assertEqual(title, "Public & news") self.assertEqual(channel_id, 68067500157571) self.assertEqual(max_api.message_id_from_link(channel_id, "AaE-viFyB3E"), MID) def test_missing_hydration_preserves_meta_title(self): title, channel_id = max_api.parse_public_post( '', "vkontakte", ) self.assertEqual(title, "Public & news") self.assertIsNone(channel_id) def test_bad_post_id_is_rejected(self): with self.assertRaises(ValueError): max_api.message_id_from_link(68067500157571, "bad") @patch.dict(os.environ, {"MAX_ACCESS_TOKEN": "test-token"}) def test_public_post_views_and_credentials(self): session = Mock() session.get.side_effect = [page_response(), Mock(status_code=200, json=lambda: { "body": {"mid": MID}, "stat": {"views": 1197}, "url": URL, })] self.assertEqual(max_api.get_public_post( session, "vkontakte", "AaE-viFyB3E", URL, (5, 8), ), ("Public & news", 1197)) public_request, api_request = session.get.call_args_list self.assertNotIn("headers", public_request.kwargs) self.assertEqual(api_request.args[0], max_api.API_BASE_URL + "/messages/" + MID) self.assertEqual(api_request.kwargs["headers"], {"Authorization": "test-token"}) self.assertEqual(api_request.kwargs["verify"], max_api.CA_FILE) self.assertFalse(api_request.kwargs["allow_redirects"]) @patch.dict(os.environ, {"MAX_ACCESS_TOKEN": "test-token"}) def test_denied_and_missing_counter_are_unknown_not_zero(self): for response in [Mock(status_code=403), Mock(status_code=200, json=lambda: { "body": {"mid": MID}, "stat": {}, }), Mock(status_code=200, json=lambda: { "body": {"mid": "different"}, "stat": {"views": 9999}, })]: with self.subTest(status=response.status_code): session = Mock() session.get.side_effect = [page_response(), response] self.assertEqual(max_api.get_public_post( session, "vkontakte", "AaE-viFyB3E", URL, (5, 8), ), ("Public & news", None)) @patch.dict(os.environ, {"MAX_ACCESS_TOKEN": "test-token"}) def test_real_zero_is_preserved(self): session = Mock() session.get.side_effect = [page_response(), Mock(status_code=200, json=lambda: { "body": {"mid": MID}, "stat": {"views": 0}, })] self.assertEqual(max_api.get_public_post( session, "vkontakte", "AaE-viFyB3E", URL, (5, 8), )[1], 0) def test_output_keeps_max_counters_and_partial_sum(self): lines = [("max", URL, "vkontakte", "AaE-viFyB3E"), ("max", "https://max.ru/other/AaE-viFyB3E", "other", "AaE-viFyB3E")] with patch.object(app, "resolve_max", return_value={ URL: ("Public & news", 1197), lines[1][1]: ("Other", None), }): html, text, _, _, errors, max_count = app.build_output(lines, time.monotonic() + 10) self.assertIn("1,2K", html) self.assertIn("Public & news", html) self.assertIn("1,2K", text) self.assertIn("Постов без данных о просмотрах: 1.", text) self.assertEqual(len(errors), 1) self.assertEqual(max_count, 2) if __name__ == "__main__": unittest.main()