diff options
-rw-r--r-- | mastodon/streaming.py | 1 | ||||
-rw-r--r-- | tests/cassettes/test_stream_direct.yaml | 95 | ||||
-rw-r--r-- | tests/test_streaming.py | 34 |
3 files changed, 127 insertions, 3 deletions
diff --git a/mastodon/streaming.py b/mastodon/streaming.py index 098863f..214ed1c 100644 --- a/mastodon/streaming.py +++ b/mastodon/streaming.py | |||
@@ -162,6 +162,7 @@ class CallbackStreamListener(StreamListener): | |||
162 | self.local_update_handler = local_update_handler | 162 | self.local_update_handler = local_update_handler |
163 | self.delete_handler = delete_handler | 163 | self.delete_handler = delete_handler |
164 | self.notification_handler = notification_handler | 164 | self.notification_handler = notification_handler |
165 | self.conversation_handler = conversation_handler | ||
165 | 166 | ||
166 | def on_update(self, status): | 167 | def on_update(self, status): |
167 | if self.update_handler != None: | 168 | if self.update_handler != None: |
diff --git a/tests/cassettes/test_stream_direct.yaml b/tests/cassettes/test_stream_direct.yaml new file mode 100644 index 0000000..3ac9404 --- /dev/null +++ b/tests/cassettes/test_stream_direct.yaml | |||
@@ -0,0 +1,95 @@ | |||
1 | interactions: | ||
2 | - request: | ||
3 | body: null | ||
4 | headers: | ||
5 | Accept: ['*/*'] | ||
6 | Accept-Encoding: ['gzip, deflate'] | ||
7 | Authorization: [Bearer __MASTODON_PY_TEST_ACCESS_TOKEN] | ||
8 | Connection: [keep-alive] | ||
9 | User-Agent: [python-requests/2.18.4] | ||
10 | method: GET | ||
11 | uri: http://localhost:3000/api/v1/instance/ | ||
12 | response: | ||
13 | body: {string: '{"uri":"localhost","title":"Mastodon","description":"","email":"","version":"2.9.1","urls":{"streaming_api":"ws://localhost:4000"},"stats":{"user_count":3,"status_count":20,"domain_count":0},"thumbnail":"http://localhost/packs/media/images/preview-9a17d32fc48369e8ccd910a75260e67d.jpg","languages":["en"],"registrations":true,"contact_account":null}'} | ||
14 | headers: | ||
15 | Cache-Control: ['max-age=300, public'] | ||
16 | Content-Type: [application/json; charset=utf-8] | ||
17 | Date: ['Fri, 11 Oct 2019 20:32:08 GMT'] | ||
18 | ETag: [W/"d8eabce6cff38f5ade8c631c932a3dc3"] | ||
19 | Referrer-Policy: [strict-origin-when-cross-origin] | ||
20 | Transfer-Encoding: [chunked] | ||
21 | Vary: ['Accept-Encoding, Origin'] | ||
22 | X-Content-Type-Options: [nosniff] | ||
23 | X-Download-Options: [noopen] | ||
24 | X-Frame-Options: [SAMEORIGIN] | ||
25 | X-Permitted-Cross-Domain-Policies: [none] | ||
26 | X-Request-Id: [65bee269-4e3b-44ce-b234-65b907986c10] | ||
27 | X-Runtime: ['0.033466'] | ||
28 | X-XSS-Protection: [1; mode=block] | ||
29 | content-length: ['349'] | ||
30 | status: {code: 200, message: OK} | ||
31 | - request: | ||
32 | body: visibility=direct&status=%40mastodonpy_test+todo+funny+text+here | ||
33 | headers: | ||
34 | Accept: ['*/*'] | ||
35 | Accept-Encoding: ['gzip, deflate'] | ||
36 | Authorization: [Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2] | ||
37 | Connection: [keep-alive] | ||
38 | Content-Length: ['64'] | ||
39 | Content-Type: [application/x-www-form-urlencoded] | ||
40 | User-Agent: [python-requests/2.18.4] | ||
41 | method: POST | ||
42 | uri: http://localhost:3000/api/v1/statuses | ||
43 | response: | ||
44 | body: {string: '{"id":"102945648378590632","created_at":"2019-10-11T20:32:13.525Z","in_reply_to_id":null,"in_reply_to_account_id":null,"sensitive":false,"spoiler_text":"","visibility":"direct","language":"en","uri":"http://localhost/users/admin/statuses/102945648378590632","url":"http://localhost/@admin/102945648378590632","replies_count":0,"reblogs_count":0,"favourites_count":0,"favourited":false,"reblogged":false,"muted":false,"content":"\u003cp\u003e\u003cspan | ||
45 | class=\"h-card\"\u003e\u003ca href=\"http://localhost/@mastodonpy_test\" class=\"u-url | ||
46 | mention\"\u003e@\u003cspan\u003emastodonpy_test\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e | ||
47 | todo funny text here\u003c/p\u003e","reblog":null,"application":{"name":"Mastodon.py | ||
48 | test suite","website":null},"account":{"id":"1","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2019-06-22T12:42:50.096Z","note":"\u003cp\u003e\u003c/p\u003e","url":"http://localhost/@admin","avatar":"http://localhost/avatars/original/missing.png","avatar_static":"http://localhost/avatars/original/missing.png","header":"http://localhost/headers/original/missing.png","header_static":"http://localhost/headers/original/missing.png","followers_count":2,"following_count":1,"statuses_count":19,"emojis":[],"fields":[]},"media_attachments":[],"mentions":[{"id":"1234567890123456","username":"mastodonpy_test","url":"http://localhost/@mastodonpy_test","acct":"mastodonpy_test"}],"tags":[],"emojis":[],"card":null,"poll":null}'} | ||
49 | headers: | ||
50 | Cache-Control: ['no-cache, no-store'] | ||
51 | Content-Type: [application/json; charset=utf-8] | ||
52 | Referrer-Policy: [strict-origin-when-cross-origin] | ||
53 | Transfer-Encoding: [chunked] | ||
54 | Vary: ['Accept-Encoding, Origin'] | ||
55 | X-Content-Type-Options: [nosniff] | ||
56 | X-Download-Options: [noopen] | ||
57 | X-Frame-Options: [SAMEORIGIN] | ||
58 | X-Permitted-Cross-Domain-Policies: [none] | ||
59 | X-Request-Id: [d328499a-7be2-4e47-b4ca-42a67efbb523] | ||
60 | X-Runtime: ['0.219320'] | ||
61 | X-XSS-Protection: [1; mode=block] | ||
62 | content-length: ['1487'] | ||
63 | status: {code: 200, message: OK} | ||
64 | - request: | ||
65 | body: null | ||
66 | headers: | ||
67 | Accept: ['*/*'] | ||
68 | Accept-Encoding: ['gzip, deflate'] | ||
69 | Authorization: [Bearer __MASTODON_PY_TEST_ACCESS_TOKEN] | ||
70 | Connection: [keep-alive] | ||
71 | User-Agent: [python-requests/2.18.4] | ||
72 | method: GET | ||
73 | uri: http://localhost:4000/api/v1/streaming/direct | ||
74 | response: | ||
75 | body: {string: 'event: conversation | ||
76 | |||
77 | data: {"id":"18","unread":true,"accounts":[{"id":"1","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2019-06-22T12:42:50.096Z","note":"<p></p>","url":"http://localhost/@admin","avatar":"http://localhost/avatars/original/missing.png","avatar_static":"http://localhost/avatars/original/missing.png","header":"http://localhost/headers/original/missing.png","header_static":"http://localhost/headers/original/missing.png","followers_count":2,"following_count":1,"statuses_count":19,"emojis":[],"fields":[]}],"last_status":{"id":"102945648378590632","created_at":"2019-10-11T20:32:13.525Z","in_reply_to_id":null,"in_reply_to_account_id":null,"sensitive":false,"spoiler_text":"","visibility":"direct","language":"en","uri":"http://localhost/users/admin/statuses/102945648378590632","url":"http://localhost/@admin/102945648378590632","replies_count":0,"reblogs_count":0,"favourites_count":0,"favourited":false,"reblogged":false,"muted":false,"content":"<p><span | ||
78 | class=\"h-card\"><a href=\"http://localhost/@mastodonpy_test\" class=\"u-url | ||
79 | mention\">@<span>mastodonpy_test</span></a></span> todo funny text here</p>","reblog":null,"application":{"name":"Mastodon.py | ||
80 | test suite","website":null},"account":{"id":"1","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2019-06-22T12:42:50.096Z","note":"<p></p>","url":"http://localhost/@admin","avatar":"http://localhost/avatars/original/missing.png","avatar_static":"http://localhost/avatars/original/missing.png","header":"http://localhost/headers/original/missing.png","header_static":"http://localhost/headers/original/missing.png","followers_count":2,"following_count":1,"statuses_count":19,"emojis":[],"fields":[]},"media_attachments":[],"mentions":[{"id":"1234567890123456","username":"mastodonpy_test","url":"http://localhost/@mastodonpy_test","acct":"mastodonpy_test"}],"tags":[],"emojis":[],"card":null,"poll":null}} | ||
81 | |||
82 | |||
83 | :'} | ||
84 | headers: | ||
85 | Access-Control-Allow-Headers: ['Authorization, Accept, Cache-Control'] | ||
86 | Access-Control-Allow-Methods: ['GET, OPTIONS'] | ||
87 | Access-Control-Allow-Origin: ['*'] | ||
88 | Connection: [keep-alive] | ||
89 | Content-Type: [text/event-stream] | ||
90 | Date: ['Fri, 11 Oct 2019 20:32:13 GMT'] | ||
91 | Transfer-Encoding: [chunked] | ||
92 | X-Powered-By: [Express] | ||
93 | X-Request-Id: [bcbbbb42-7096-4be8-b175-8fb71c2f136f] | ||
94 | status: {code: 200, message: OK} | ||
95 | version: 1 | ||
diff --git a/tests/test_streaming.py b/tests/test_streaming.py index a471c41..cddb79a 100644 --- a/tests/test_streaming.py +++ b/tests/test_streaming.py | |||
@@ -17,7 +17,7 @@ streaming_is_patched = False | |||
17 | real_connections = [] | 17 | real_connections = [] |
18 | close_connections = False | 18 | close_connections = False |
19 | 19 | ||
20 | def patchStreaming(): | 20 | def patch_streaming(): |
21 | global streaming_is_patched | 21 | global streaming_is_patched |
22 | global close_connections | 22 | global close_connections |
23 | if streaming_is_patched == True: | 23 | if streaming_is_patched == True: |
@@ -281,7 +281,7 @@ def test_multiline_payload(): | |||
281 | 281 | ||
282 | @pytest.mark.vcr(match_on=['path']) | 282 | @pytest.mark.vcr(match_on=['path']) |
283 | def test_stream_user(api, api2): | 283 | def test_stream_user(api, api2): |
284 | patchStreaming() | 284 | patch_streaming() |
285 | 285 | ||
286 | # Make sure we are in the right state to not receive updates from api2 | 286 | # Make sure we are in the right state to not receive updates from api2 |
287 | user = api2.account_verify_credentials() | 287 | user = api2.account_verify_credentials() |
@@ -331,7 +331,7 @@ def test_stream_user(api, api2): | |||
331 | 331 | ||
332 | @pytest.mark.vcr(match_on=['path']) | 332 | @pytest.mark.vcr(match_on=['path']) |
333 | def test_stream_user_local(api, api2): | 333 | def test_stream_user_local(api, api2): |
334 | patchStreaming() | 334 | patch_streaming() |
335 | 335 | ||
336 | # Make sure we are in the right state to not receive updates from api2 | 336 | # Make sure we are in the right state to not receive updates from api2 |
337 | user = api2.account_verify_credentials() | 337 | user = api2.account_verify_credentials() |
@@ -366,6 +366,34 @@ def test_stream_user_local(api, api2): | |||
366 | 366 | ||
367 | t.join() | 367 | t.join() |
368 | 368 | ||
369 | @pytest.mark.vcr(match_on=['path']) | ||
370 | def test_stream_direct(api, api2): | ||
371 | patch_streaming() | ||
372 | |||
373 | conversations = [] | ||
374 | listener = CallbackStreamListener( | ||
375 | conversation_handler = lambda x: conversations.append(x), | ||
376 | ) | ||
377 | |||
378 | def do_activities(): | ||
379 | time.sleep(5) | ||
380 | api2.status_post("@mastodonpy_test todo funny text here", visibility = "direct") | ||
381 | time.sleep(10) | ||
382 | streaming_close() | ||
383 | |||
384 | t = threading.Thread(args=(), target=do_activities) | ||
385 | t.start() | ||
386 | |||
387 | stream = None | ||
388 | try: | ||
389 | stream = api.stream_direct(listener, run_async=True) | ||
390 | time.sleep(20) | ||
391 | finally: | ||
392 | if stream != None: | ||
393 | stream.close() | ||
394 | |||
395 | assert len(conversations) == 1 | ||
396 | |||
369 | @pytest.mark.vcr() | 397 | @pytest.mark.vcr() |
370 | def test_stream_healthy(api_anonymous): | 398 | def test_stream_healthy(api_anonymous): |
371 | assert api_anonymous.stream_healthy() | 399 | assert api_anonymous.stream_healthy() |