File size: 4,217 Bytes
72f0375
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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 = '''<meta content="Public &amp; news" property="og:title">
<script>app.start(element, {
data: [null,{type:"data",data:{linkInfo:{channel:{
title:"Public & news",description:"a } and [ inside text",
participantsCount:5287,channelId:68067500157571},message:{text:"post"}}}}],
form:null});</script>'''


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(
            '<meta property="og:title" content="Public &amp; news">', "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("<b>1,2K</b>", html)
        self.assertIn("Public &amp; 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()