2020-08-23 15:53:25 +00:00
|
|
|
# test_timelines.py
|
|
|
|
#
|
|
|
|
# Part of kepi.
|
|
|
|
# Copyright (c) 2018-2020 Marnanel Thurman.
|
|
|
|
# Licensed under the GNU Public License v2.
|
|
|
|
|
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(name='kepi')
|
|
|
|
|
2020-04-16 15:22:45 +00:00
|
|
|
from rest_framework.test import APIClient, force_authenticate
|
|
|
|
from kepi.trilby_api.views import *
|
2019-12-25 23:21:43 +00:00
|
|
|
from kepi.trilby_api.tests import *
|
2020-04-16 15:22:45 +00:00
|
|
|
from kepi.trilby_api.models import *
|
2021-02-09 17:39:39 +00:00
|
|
|
from kepi.bowler_pub.tests import create_remote_person
|
2020-04-16 15:22:45 +00:00
|
|
|
from django.conf import settings
|
2020-10-30 23:05:25 +00:00
|
|
|
from unittest import skip
|
2021-02-09 17:39:39 +00:00
|
|
|
import httpretty
|
2019-12-25 23:21:43 +00:00
|
|
|
|
2020-04-16 15:22:45 +00:00
|
|
|
# Tests for timelines. API docs are here:
|
|
|
|
# https://docs.joinmastodon.org/methods/statuses/
|
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
class TimelineTestCase(TrilbyTestCase):
|
2020-04-16 15:22:45 +00:00
|
|
|
|
2021-02-07 20:30:03 +00:00
|
|
|
def add_status(self, source, visibility, content):
|
|
|
|
status = Status(
|
|
|
|
account = source,
|
|
|
|
content = content,
|
|
|
|
visibility = visibility,
|
|
|
|
)
|
|
|
|
status.save()
|
2020-04-22 15:47:01 +00:00
|
|
|
|
2021-02-07 20:30:03 +00:00
|
|
|
logger.info("Created status: %s", status)
|
2020-04-22 15:47:01 +00:00
|
|
|
|
2021-02-09 17:39:39 +00:00
|
|
|
return status
|
|
|
|
|
2021-02-07 20:30:03 +00:00
|
|
|
def timeline_contents(self,
|
2020-04-22 15:47:01 +00:00
|
|
|
path,
|
2021-02-09 17:39:39 +00:00
|
|
|
as_user = None,
|
|
|
|
):
|
2020-04-22 15:47:01 +00:00
|
|
|
|
|
|
|
details = sorted([x['content'] \
|
|
|
|
for x in self.get(
|
|
|
|
path = path,
|
|
|
|
as_user = as_user,
|
|
|
|
)])
|
|
|
|
|
2021-02-07 20:30:03 +00:00
|
|
|
result = ''
|
|
|
|
for detail in details:
|
|
|
|
|
|
|
|
if detail.startswith('<p>') and detail.endswith('</p>'):
|
|
|
|
detail = detail[3:-4]
|
|
|
|
|
|
|
|
result += detail
|
|
|
|
|
|
|
|
logger.info("Timeline contents for %s as %s...",
|
|
|
|
path,
|
|
|
|
as_user)
|
|
|
|
logger.info(" ...are %s",
|
|
|
|
result)
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
class TestPublicTimeline(TimelineTestCase):
|
|
|
|
|
|
|
|
def test_as_anon(self):
|
2021-02-07 20:30:03 +00:00
|
|
|
|
|
|
|
alice = create_local_person("alice")
|
2020-04-22 15:47:01 +00:00
|
|
|
|
2021-02-07 20:30:03 +00:00
|
|
|
self.add_status(source=alice, content='A', visibility='A')
|
|
|
|
self.add_status(source=alice, content='B', visibility='U')
|
|
|
|
self.add_status(source=alice, content='C', visibility='X')
|
|
|
|
self.add_status(source=alice, content='D', visibility='D')
|
2020-04-16 15:22:45 +00:00
|
|
|
|
2021-02-07 20:30:03 +00:00
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public',
|
|
|
|
as_user = None,
|
|
|
|
),
|
|
|
|
'A',
|
2020-04-22 15:47:01 +00:00
|
|
|
)
|
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
def test_as_user(self):
|
2021-02-07 20:30:03 +00:00
|
|
|
|
|
|
|
alice = create_local_person("alice")
|
|
|
|
|
|
|
|
self.add_status(source=alice, content='A', visibility='A')
|
|
|
|
self.add_status(source=alice, content='B', visibility='U')
|
|
|
|
self.add_status(source=alice, content='C', visibility='X')
|
|
|
|
self.add_status(source=alice, content='D', visibility='D')
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public',
|
|
|
|
as_user = alice,
|
|
|
|
),
|
|
|
|
'A',
|
|
|
|
)
|
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
def test_as_follower(self):
|
2021-02-07 20:30:03 +00:00
|
|
|
|
|
|
|
alice = create_local_person("alice")
|
|
|
|
george = create_local_person("george")
|
2020-04-22 15:54:36 +00:00
|
|
|
|
|
|
|
follow = Follow(
|
2021-02-07 20:30:03 +00:00
|
|
|
follower = george,
|
|
|
|
following = alice,
|
2020-09-30 14:44:16 +00:00
|
|
|
offer = None,
|
2020-04-22 15:54:36 +00:00
|
|
|
)
|
|
|
|
follow.save()
|
|
|
|
|
2021-02-07 20:30:03 +00:00
|
|
|
self.add_status(source=alice, content='A', visibility='A')
|
|
|
|
self.add_status(source=alice, content='B', visibility='U')
|
|
|
|
self.add_status(source=alice, content='C', visibility='X')
|
|
|
|
self.add_status(source=alice, content='D', visibility='D')
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public',
|
|
|
|
as_user = george,
|
|
|
|
),
|
|
|
|
'AC',
|
2020-04-22 15:54:36 +00:00
|
|
|
)
|
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
def test_as_stranger(self):
|
2021-02-07 20:30:03 +00:00
|
|
|
|
|
|
|
alice = create_local_person("alice")
|
|
|
|
henry = create_local_person("henry")
|
2020-04-22 15:54:36 +00:00
|
|
|
|
2021-02-07 20:30:03 +00:00
|
|
|
self.add_status(source=alice, content='A', visibility='A')
|
|
|
|
self.add_status(source=alice, content='B', visibility='U')
|
|
|
|
self.add_status(source=alice, content='C', visibility='X')
|
|
|
|
self.add_status(source=alice, content='D', visibility='D')
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public',
|
|
|
|
as_user = henry,
|
|
|
|
),
|
|
|
|
'A',
|
2020-04-22 15:54:36 +00:00
|
|
|
)
|
2020-04-16 15:22:45 +00:00
|
|
|
|
2021-02-09 17:39:39 +00:00
|
|
|
@httpretty.activate()
|
2021-02-09 17:42:10 +00:00
|
|
|
def test_local_and_remote(self):
|
2021-02-09 17:39:39 +00:00
|
|
|
|
|
|
|
alice = create_local_person("alice")
|
|
|
|
peter = create_remote_person(
|
|
|
|
remote_url = "https://example.com/users/peter",
|
|
|
|
name = "peter",
|
|
|
|
auto_fetch = True,
|
|
|
|
)
|
|
|
|
|
|
|
|
self.add_status(source=alice, content='A', visibility='A')
|
|
|
|
self.add_status(source=peter, content='B', visibility='A')
|
|
|
|
self.add_status(source=alice, content='C', visibility='A')
|
|
|
|
self.add_status(source=peter, content='D', visibility='A')
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public',
|
|
|
|
),
|
|
|
|
'ABCD',
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?local=true',
|
|
|
|
),
|
|
|
|
'AC',
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?local=false',
|
|
|
|
),
|
|
|
|
'ABCD',
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?remote=true',
|
|
|
|
),
|
|
|
|
'BD',
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?remote=false',
|
|
|
|
),
|
|
|
|
'ABCD',
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?local=true&remote=true',
|
|
|
|
),
|
|
|
|
'',
|
|
|
|
)
|
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
def test_only_media(self):
|
2021-02-09 17:39:39 +00:00
|
|
|
|
|
|
|
# We don't support added media at present anyway,
|
|
|
|
# so turning this on will always get the empty set
|
|
|
|
|
|
|
|
alice = create_local_person("alice")
|
|
|
|
|
|
|
|
self.add_status(source=alice, content='A', visibility='A')
|
|
|
|
self.add_status(source=alice, content='B', visibility='A')
|
|
|
|
self.add_status(source=alice, content='C', visibility='A')
|
|
|
|
self.add_status(source=alice, content='D', visibility='A')
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?only_media=true',
|
|
|
|
),
|
|
|
|
'',
|
|
|
|
)
|
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
def test_max_since_and_min(self):
|
2021-02-09 17:39:39 +00:00
|
|
|
|
|
|
|
alice = create_local_person("alice")
|
|
|
|
|
|
|
|
self.add_status(source=alice, content='A', visibility='A')
|
|
|
|
self.add_status(source=alice, content='B', visibility='A')
|
|
|
|
status_c = self.add_status(source=alice, content='C', visibility='A')
|
|
|
|
self.add_status(source=alice, content='D', visibility='A')
|
|
|
|
|
|
|
|
c_id = str(status_c.id)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?since='+c_id,
|
|
|
|
),
|
|
|
|
'D',
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?max_id='+c_id,
|
|
|
|
),
|
|
|
|
'ABC',
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?min_id='+c_id,
|
|
|
|
),
|
|
|
|
'CD',
|
|
|
|
)
|
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
def test_limit(self):
|
2021-02-09 17:39:39 +00:00
|
|
|
|
|
|
|
alice = create_local_person("alice")
|
|
|
|
|
|
|
|
alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
|
|
|
|
|
|
for i in range(len(alphabet)):
|
|
|
|
self.add_status(
|
|
|
|
source=alice,
|
|
|
|
content=alphabet[i],
|
|
|
|
visibility='A',
|
|
|
|
)
|
|
|
|
|
|
|
|
for i in range(len(alphabet)):
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public?limit='+str(i),
|
|
|
|
),
|
|
|
|
alphabet[:i],
|
|
|
|
)
|
|
|
|
|
|
|
|
# the default is specified as 20
|
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/public',
|
|
|
|
),
|
|
|
|
alphabet[:20],
|
|
|
|
message = 'default is 20',
|
|
|
|
)
|
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
class TestHomeTimeline(TimelineTestCase):
|
2021-02-09 17:39:39 +00:00
|
|
|
|
2021-02-09 17:42:10 +00:00
|
|
|
def test_as_user(self):
|
2021-02-07 20:30:03 +00:00
|
|
|
alice = create_local_person("alice")
|
|
|
|
|
|
|
|
self.add_status(source=alice, content='A', visibility='A')
|
|
|
|
self.add_status(source=alice, content='B', visibility='U')
|
|
|
|
self.add_status(source=alice, content='C', visibility='X')
|
|
|
|
self.add_status(source=alice, content='D', visibility='D')
|
2020-04-22 15:47:01 +00:00
|
|
|
|
2021-02-07 20:30:03 +00:00
|
|
|
self.assertEqual(
|
|
|
|
self.timeline_contents(
|
|
|
|
path = '/api/v1/timelines/home',
|
|
|
|
as_user = alice,
|
|
|
|
),
|
|
|
|
'ABCD',
|
2020-04-22 15:47:01 +00:00
|
|
|
)
|
2020-04-16 15:22:45 +00:00
|
|
|
|
2020-10-30 23:05:25 +00:00
|
|
|
@skip("to be implemented later")
|
2020-04-22 15:54:36 +00:00
|
|
|
def test_hashtag(self):
|
2020-10-26 22:29:55 +00:00
|
|
|
raise NotImplementedError()
|
2020-04-22 15:54:36 +00:00
|
|
|
|
2020-10-30 23:05:25 +00:00
|
|
|
@skip("to be implemented later")
|
2020-04-16 15:22:45 +00:00
|
|
|
def test_account_statuses(self):
|
|
|
|
# Special case: this isn't considered a timeline method
|
|
|
|
# in the API, but it's similar enough that we test it here
|
2020-10-26 22:29:55 +00:00
|
|
|
raise NotImplementedError()
|
2020-04-16 15:22:45 +00:00
|
|
|
|
2020-10-30 23:05:25 +00:00
|
|
|
@skip("to be implemented later")
|
2020-04-16 15:22:45 +00:00
|
|
|
def test_list(self):
|
2020-10-26 22:29:55 +00:00
|
|
|
raise NotImplementedError()
|