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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
|
import pytest
from mastodon.Mastodon import MastodonAPIError, MastodonNotFoundError
import datetime
try:
import zoneinfo
timezone = zoneinfo.ZoneInfo
except:
import pytz
timezone = pytz.timezone
import vcr
import time
import pickle
import os
@pytest.mark.vcr()
def test_status(status, api):
status2 = api.status(status['id'])
assert status2
@pytest.mark.vcr()
def test_status_reply(status, api2):
status2 = api2.status_reply(status, "same!")
try:
assert status2
assert status2.mentions[0].id == status.account.id
finally:
api2.status_delete(status2['id'])
@pytest.mark.vcr()
def test_status_empty(api):
with pytest.raises(MastodonAPIError):
api.status_post('')
@pytest.mark.vcr()
def test_status_missing(api):
with pytest.raises(MastodonNotFoundError):
api.status(0)
# Messy and will only work if there is an internet connection that is decent, obviously.
# Also, deprecated, but still a good test (Mastodon.py tries to fake the old behaviour
# internally)
@pytest.mark.vcr()
def test_status_card(api):
import time
status = api.status_post("http://example.org/")
time.sleep(5) # Card generation may take time
card = api.status_card(status['id'])
try:
assert card
assert card.url == "http://example.org/"
finally:
api.status_delete(status['id'])
# Old-version card api
def test_status_card_pre_2_9_2(api):
with vcr.use_cassette('test_status_card.yaml', cassette_library_dir='tests/cassettes_pre_2_9_2', record_mode='none'):
import time
status = api.status_post("http://example.org/")
time.sleep(5) # Card generation may take time
api.verify_minimum_version("2.9.2", cached=False)
card = api.status_card(status['id'])
try:
assert card
assert card.url == "http://example.org/"
finally:
api.status_delete(status['id'])
@pytest.mark.vcr()
def test_status_context(status, api):
context = api.status_context(status['id'])
assert context
@pytest.mark.vcr()
def test_status_reblogged_by(status, api):
api.status_reblog(status['id'])
reblogs = api.status_reblogged_by(status['id'])
assert reblogs
@pytest.mark.vcr()
def test_status_reblog_visibility(status, api):
reblog_result = api.status_reblog(status['id'], visibility = 'unlisted')
assert reblog_result.visibility == 'unlisted'
@pytest.mark.vcr()
def test_status_favourited_by(status, api):
api.status_favourite(status['id'])
favourites = api.status_favourited_by(status['id'])
assert favourites
@pytest.mark.vcr()
def test_toot(api):
status = api.toot('Toot!')
try:
assert status
finally:
api.status_delete(status['id'])
@pytest.mark.vcr()
@pytest.mark.parametrize('visibility', (None, 'direct', 'private', 'unlisted', 'public',
pytest.param('foobar', marks=pytest.mark.xfail(strict=True))))
@pytest.mark.parametrize('spoiler_text', (None, 'Content warning'))
def test_status_post(api, visibility, spoiler_text):
status = api.status_post(
'Toot!',
visibility=visibility,
spoiler_text=spoiler_text)
try:
assert status
if visibility:
assert status['visibility'] == visibility
if spoiler_text:
assert status['spoiler_text'] == spoiler_text
finally:
api.status_delete(status['id'])
@pytest.mark.vcr()
def test_status_reblog_unreblog(status, api):
reblog = api.status_reblog(status['id'])
assert reblog
status = reblog['reblog']
assert status['reblogged']
status = api.status_unreblog(status['id'])
assert not status['reblogged']
@pytest.mark.vcr()
def test_status_fav_unfav(status, api):
status = api.status_favourite(status['id'])
assert status['favourited']
status = api.status_unfavourite(status['id'])
assert not status['favourited']
@pytest.mark.vcr()
def test_favourites(api):
favs = api.favourites()
assert isinstance(favs, list)
@pytest.mark.vcr()
def test_status_mute_unmute(status, api):
status = api.status_mute(status['id'])
assert status['muted']
status = api.status_unmute(status['id'])
assert not status['muted']
@pytest.mark.vcr()
def test_status_pin_unpin(status, api):
status = api.status_pin(status['id'])
assert status['pinned']
status = api.status_unpin(status['id'])
assert not status['pinned']
@pytest.mark.vcr(match_on=['path'])
def test_scheduled_status(api):
base_time = datetime.datetime(4000, 1, 1, 12, 13, 14, 0, timezone("Etc/GMT+2"))
the_future = base_time + datetime.timedelta(minutes=20)
scheduled_toot = api.status_post("please ensure adequate headroom", scheduled_at=the_future)
assert scheduled_toot
the_immediate_future = base_time + datetime.timedelta(minutes=10)
scheduled_toot_2 = api.scheduled_status_update(scheduled_toot, the_immediate_future)
assert scheduled_toot_2
assert scheduled_toot_2.id == scheduled_toot.id
assert scheduled_toot_2.scheduled_at < scheduled_toot.scheduled_at
scheduled_toot_list = api.scheduled_statuses()
assert scheduled_toot_2.id in map(lambda x: x.id, scheduled_toot_list)
scheduled_toot_3 = api.scheduled_status(scheduled_toot.id)
assert scheduled_toot_2.id == scheduled_toot_3.id
api.scheduled_status_delete(scheduled_toot_2)
scheduled_toot_list_2 = api.scheduled_statuses()
assert not scheduled_toot_2.id in map(lambda x: x.id, scheduled_toot_list_2)
if os.path.exists("tests/cassettes/test_scheduled_status_datetimeobjects.pkl"):
the_very_immediate_future = datetime.datetime.fromtimestamp(pickle.load(open("tests/cassettes/test_scheduled_status_datetimeobjects.pkl", 'rb')))
else:
the_very_immediate_future = datetime.datetime.now() + datetime.timedelta(seconds=5)
pickle.dump(the_very_immediate_future.timestamp(), open("tests/cassettes/test_scheduled_status_datetimeobjects.pkl", 'wb'))
scheduled_toot_4 = api.status_post("please ensure adequate headroom", scheduled_at=the_very_immediate_future)
time.sleep(15)
statuses = api.timeline_home()
scheduled_toot_list_3 = api.scheduled_statuses()
assert scheduled_toot_4.id in map(lambda x: x.id, statuses)
assert not scheduled_toot_4.id in map(lambda x: x.id, scheduled_toot_list_3)
# The following two tests need to be manually (!) ran 10 minutes apart when recording.
# Sorry, I can't think of a better way to test scheduled statuses actually work as intended.
@pytest.mark.vcr(match_on=['path'])
def test_scheduled_status_long_part1(api):
with vcr.use_cassette('test_scheduled_status_long_part1.yaml', cassette_library_dir='tests/cassettes_special', record_mode='once'):
if os.path.exists("tests/cassettes_special/test_scheduled_status_long_datetimeobjects.pkl"):
the_medium_term_future = datetime.datetime.fromtimestamp(pickle.load(open("tests/cassettes_special/test_scheduled_status_long_datetimeobjects.pkl", 'rb')))
else:
the_medium_term_future = datetime.datetime.now() + datetime.timedelta(minutes=6)
pickle.dump(the_medium_term_future.timestamp(), open("tests/cassettes_special/test_scheduled_status_long_datetimeobjects.pkl", 'wb'))
scheduled_toot = api.status_post(f"please ensure maximum headroom at {the_medium_term_future}", scheduled_at=the_medium_term_future)
scheduled_toot_list = api.scheduled_statuses()
assert scheduled_toot.id in map(lambda x: x.id, scheduled_toot_list)
pickle.dump(scheduled_toot.params.text, open("tests/cassettes_special/test_scheduled_status_long_text.pkl", 'wb'))
@pytest.mark.vcr(match_on=['path'])
def test_scheduled_status_long_part2(api):
with vcr.use_cassette('test_scheduled_status_long_part2.yaml', cassette_library_dir='tests/cassettes_special', record_mode='once'):
text = pickle.load(open("tests/cassettes_special/test_scheduled_status_long_text.pkl", 'rb'))
statuses = api.timeline_home()
print(text)
found_status = False
for status in statuses:
if text in status.content:
found_status = True
assert found_status
@pytest.mark.vcr()
def test_status_edit(api, api2):
status = api.status_post("the best editor? why, of course it is VS Code")
edit_list_1 = api2.status_history(status)
status_edited = api.status_update(status, "the best editor? why, of course it is the KDE Advanced Text Editor, Kate")
status_result = api2.status(status)
edit_list_2 = api2.status_history(status)
assert len(edit_list_1) == 0
assert len(edit_list_2) == 2
assert "the best editor? why, of course it is the KDE Advanced Text Editor, Kate" in status_result.content
source = api2.status_source(status)
assert source.text == "the best editor? why, of course it is the KDE Advanced Text Editor, Kate"
|