2022-11-17 15:38:52 +00:00
|
|
|
"""Unit tests for pages.py."""
|
2023-06-20 18:22:54 +00:00
|
|
|
from granary import atom, microformats2, rss
|
2023-01-28 23:07:05 +00:00
|
|
|
from granary.tests.test_as1 import (
|
|
|
|
ACTOR,
|
|
|
|
COMMENT,
|
2023-01-19 23:25:56 +00:00
|
|
|
NOTE,
|
|
|
|
)
|
2023-02-09 16:23:31 +00:00
|
|
|
from oauth_dropins.webutil import util
|
2023-01-28 23:07:05 +00:00
|
|
|
|
2023-05-30 23:36:18 +00:00
|
|
|
# import first so that Fake is defined before URL routes are registered
|
|
|
|
from .testutil import Fake, TestCase
|
|
|
|
|
2023-06-02 05:00:47 +00:00
|
|
|
from activitypub import ActivityPub
|
2023-06-20 18:22:54 +00:00
|
|
|
from models import Object, Follower
|
2023-05-26 23:07:36 +00:00
|
|
|
|
2023-06-20 18:22:54 +00:00
|
|
|
from .test_web import ACTOR_AS2, REPOST_AS2
|
2023-02-09 04:22:16 +00:00
|
|
|
|
2023-06-02 05:00:47 +00:00
|
|
|
ACTOR_WITH_PREFERRED_USERNAME = {
|
|
|
|
**ACTOR,
|
|
|
|
'preferredUsername': 'me',
|
|
|
|
}
|
2022-11-17 15:38:52 +00:00
|
|
|
|
2023-06-20 18:22:54 +00:00
|
|
|
|
2022-11-17 15:38:52 +00:00
|
|
|
def contents(activities):
|
2023-01-28 23:07:05 +00:00
|
|
|
return [(a.get('object') or a)['content'] for a in activities]
|
2022-11-17 15:38:52 +00:00
|
|
|
|
|
|
|
|
2023-05-26 23:07:36 +00:00
|
|
|
class PagesTest(TestCase):
|
2023-02-09 04:22:16 +00:00
|
|
|
EXPECTED = contents([COMMENT, NOTE])
|
2022-11-17 15:38:52 +00:00
|
|
|
|
2022-11-22 23:21:53 +00:00
|
|
|
def setUp(self):
|
|
|
|
super().setUp()
|
2023-03-19 22:43:55 +00:00
|
|
|
self.user = self.make_user('user.com')
|
2022-11-22 23:21:53 +00:00
|
|
|
|
2022-12-02 19:08:24 +00:00
|
|
|
def test_user(self):
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com')
|
2022-12-02 19:08:24 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2023-05-30 23:36:18 +00:00
|
|
|
def test_user_fake(self):
|
|
|
|
self.make_user('foo.com', cls=Fake)
|
2023-06-11 15:14:17 +00:00
|
|
|
got = self.client.get('/fa/foo.com')
|
2023-05-30 23:36:18 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2023-06-04 04:48:15 +00:00
|
|
|
def test_user_readable_id_activitypub_address(self):
|
2023-06-23 19:22:37 +00:00
|
|
|
user = self.make_user('http://foo', cls=ActivityPub,
|
2023-06-16 04:22:20 +00:00
|
|
|
obj_as2=ACTOR_WITH_PREFERRED_USERNAME)
|
2023-06-04 04:48:15 +00:00
|
|
|
self.assertEqual('@me@plus.google.com', user.ap_address())
|
2023-06-02 05:00:47 +00:00
|
|
|
|
2023-06-11 15:14:17 +00:00
|
|
|
got = self.client.get('/ap/@me@plus.google.com')
|
2023-06-02 05:00:47 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2023-06-23 19:22:37 +00:00
|
|
|
# TODO: can't handle slashes in id segment of path. is that ok?
|
|
|
|
# got = self.client.get('/ap/http%3A//foo')
|
|
|
|
# self.assert_equals(302, got.status_code)
|
|
|
|
# self.assert_equals('/ap/@me@plus.google.com', got.headers['Location'])
|
2023-06-02 05:00:47 +00:00
|
|
|
|
2023-06-07 18:51:31 +00:00
|
|
|
def test_user_web_custom_username_doesnt_redirect(self):
|
|
|
|
"""https://github.com/snarfed/bridgy-fed/issues/534"""
|
2023-06-27 03:22:06 +00:00
|
|
|
self.user.obj = Object(id='a', as2={
|
2023-06-07 18:51:31 +00:00
|
|
|
**ACTOR_AS2,
|
|
|
|
'url': 'acct:baz@user.com',
|
2023-06-27 03:22:06 +00:00
|
|
|
})
|
|
|
|
self.user.obj.put()
|
2023-06-07 18:51:31 +00:00
|
|
|
self.user.put()
|
|
|
|
self.assertEqual('baz', self.user.username())
|
|
|
|
|
|
|
|
got = self.client.get('/web/@baz@user.com')
|
|
|
|
self.assert_equals(404, got.status_code)
|
|
|
|
|
|
|
|
got = self.client.get('/web/baz')
|
|
|
|
self.assert_equals(404, got.status_code)
|
|
|
|
|
|
|
|
got = self.client.get('/web/user.com')
|
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
self.assertIn('@baz@user.com', got.get_data(as_text=True))
|
|
|
|
|
2023-01-28 23:07:05 +00:00
|
|
|
def test_user_objects(self):
|
|
|
|
self.add_objects()
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com')
|
2023-01-24 03:20:31 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2022-12-02 19:08:24 +00:00
|
|
|
def test_user_not_found(self):
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/bar.com')
|
2022-11-22 23:21:53 +00:00
|
|
|
self.assert_equals(404, got.status_code)
|
|
|
|
|
2023-05-30 03:16:15 +00:00
|
|
|
def test_user_not_direct(self):
|
|
|
|
self.user.direct = False
|
|
|
|
self.user.put()
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com')
|
2023-05-30 03:16:15 +00:00
|
|
|
self.assert_equals(404, got.status_code)
|
|
|
|
|
2023-06-04 04:48:15 +00:00
|
|
|
def test_user_web_redirect(self):
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/user/user.com')
|
|
|
|
self.assert_equals(301, got.status_code)
|
|
|
|
self.assert_equals('/web/user.com', got.headers['Location'])
|
|
|
|
|
2022-12-02 19:08:24 +00:00
|
|
|
def test_user_use_instead(self):
|
2023-06-07 18:51:31 +00:00
|
|
|
self.make_user('bar.com', use_instead=self.user.key)
|
2022-12-02 19:08:24 +00:00
|
|
|
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/bar.com')
|
2023-06-07 18:51:31 +00:00
|
|
|
self.assert_equals(302, got.status_code)
|
2023-05-30 21:08:13 +00:00
|
|
|
self.assert_equals('/web/user.com', got.headers['Location'])
|
2022-12-02 19:08:24 +00:00
|
|
|
|
2023-06-07 18:51:31 +00:00
|
|
|
got = self.client.get('/web/user.com')
|
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2023-03-03 18:07:54 +00:00
|
|
|
def test_user_object_bare_string_id(self):
|
2023-06-15 22:09:03 +00:00
|
|
|
Object(id='a', users=[self.user.key], labels=['notification'],
|
|
|
|
as2=REPOST_AS2).put()
|
2023-03-03 18:07:54 +00:00
|
|
|
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com')
|
2023-03-03 18:07:54 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2023-03-24 05:04:09 +00:00
|
|
|
def test_user_object_url_object(self):
|
2023-05-23 06:09:36 +00:00
|
|
|
with self.request_context:
|
2023-06-09 19:56:45 +00:00
|
|
|
Object(id='a', users=[self.user.key], labels=['notification'], our_as1={
|
2023-03-24 05:04:09 +00:00
|
|
|
**REPOST_AS2,
|
|
|
|
'object': {
|
|
|
|
'id': 'https://mas.to/toot/id',
|
|
|
|
'url': {'value': 'http://foo', 'displayName': 'bar'},
|
|
|
|
},
|
|
|
|
}).put()
|
|
|
|
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com')
|
2023-03-24 05:04:09 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2023-05-24 13:49:54 +00:00
|
|
|
def test_user_before(self):
|
|
|
|
self.add_objects()
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get(f'/web/user.com?before={util.now().isoformat()}')
|
2023-05-24 13:49:54 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
|
|
|
def test_user_after(self):
|
|
|
|
self.add_objects()
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get(f'/web/user.com?after={util.now().isoformat()}')
|
2023-05-24 13:49:54 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
|
|
|
def test_user_before_bad(self):
|
|
|
|
self.add_objects()
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com?before=nope')
|
2023-05-24 13:49:54 +00:00
|
|
|
self.assert_equals(400, got.status_code)
|
|
|
|
|
|
|
|
def test_user_before_and_after(self):
|
|
|
|
self.add_objects()
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com?before=2024-01-01+01:01:01&after=2023-01-01+01:01:01')
|
2023-05-24 13:49:54 +00:00
|
|
|
self.assert_equals(400, got.status_code)
|
|
|
|
|
2023-01-19 23:25:56 +00:00
|
|
|
def test_followers(self):
|
2023-06-06 21:50:20 +00:00
|
|
|
Follower.get_or_create(
|
|
|
|
to=self.user,
|
2023-06-16 04:22:20 +00:00
|
|
|
from_=self.make_user('unused', cls=Fake, obj_as2={
|
2023-06-12 22:50:47 +00:00
|
|
|
**ACTOR,
|
2023-06-27 03:22:06 +00:00
|
|
|
'id': 'unused',
|
2023-06-12 22:50:47 +00:00
|
|
|
'url': 'http://stored/users/follow',
|
|
|
|
}))
|
2023-06-06 21:50:20 +00:00
|
|
|
Follower.get_or_create(
|
|
|
|
to=self.user,
|
|
|
|
from_=self.make_user('masto/user', cls=Fake,
|
2023-06-16 04:22:20 +00:00
|
|
|
obj_as2=ACTOR_WITH_PREFERRED_USERNAME))
|
2023-06-06 21:50:20 +00:00
|
|
|
|
|
|
|
got = self.client.get('/web/user.com/followers')
|
2023-01-19 23:25:56 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
|
|
|
body = got.get_data(as_text=True)
|
2023-06-12 22:50:47 +00:00
|
|
|
self.assertIn('@follow@stored', body)
|
2023-06-02 03:58:42 +00:00
|
|
|
self.assertIn('@me@plus.google.com', body)
|
2023-01-19 23:25:56 +00:00
|
|
|
|
2023-05-30 23:36:18 +00:00
|
|
|
def test_followers_fake(self):
|
|
|
|
self.make_user('foo.com', cls=Fake)
|
2023-06-11 15:14:17 +00:00
|
|
|
got = self.client.get('/fa/foo.com/followers')
|
2023-05-30 23:36:18 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2023-01-19 23:25:56 +00:00
|
|
|
def test_followers_empty(self):
|
2023-06-06 21:50:20 +00:00
|
|
|
got = self.client.get('/web/user.com/followers')
|
2023-01-19 23:25:56 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
self.assertNotIn('class="follower', got.get_data(as_text=True))
|
|
|
|
|
2022-11-22 23:21:53 +00:00
|
|
|
def test_followers_user_not_found(self):
|
2023-06-06 21:50:20 +00:00
|
|
|
got = self.client.get('/web/nope.com/followers')
|
2022-11-22 23:21:53 +00:00
|
|
|
self.assert_equals(404, got.status_code)
|
|
|
|
|
2023-05-30 21:08:13 +00:00
|
|
|
def test_followers_redirect(self):
|
|
|
|
got = self.client.get('/user/user.com/followers')
|
|
|
|
self.assert_equals(301, got.status_code)
|
|
|
|
self.assert_equals('/web/user.com/followers', got.headers['Location'])
|
|
|
|
|
2023-01-19 23:25:56 +00:00
|
|
|
def test_following(self):
|
2023-06-06 21:50:20 +00:00
|
|
|
Follower.get_or_create(
|
|
|
|
from_=self.user,
|
2023-06-16 04:22:20 +00:00
|
|
|
to=self.make_user('unused', cls=Fake, obj_as2={
|
2023-06-12 22:50:47 +00:00
|
|
|
**ACTOR,
|
2023-06-27 03:22:06 +00:00
|
|
|
'id': 'unused',
|
2023-06-12 22:50:47 +00:00
|
|
|
'url': 'http://stored/users/follow',
|
|
|
|
}))
|
2023-06-06 21:50:20 +00:00
|
|
|
Follower.get_or_create(
|
|
|
|
from_=self.user,
|
|
|
|
to=self.make_user('masto/user', cls=Fake,
|
2023-06-16 04:22:20 +00:00
|
|
|
obj_as2=ACTOR_WITH_PREFERRED_USERNAME))
|
2023-06-06 21:50:20 +00:00
|
|
|
|
|
|
|
got = self.client.get('/web/user.com/following')
|
2023-01-19 23:25:56 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
|
|
|
body = got.get_data(as_text=True)
|
2023-06-12 22:50:47 +00:00
|
|
|
self.assertIn('@follow@stored', body)
|
2023-01-19 23:25:56 +00:00
|
|
|
self.assertIn('masto/user', body)
|
|
|
|
|
|
|
|
def test_following_empty(self):
|
2023-06-06 21:50:20 +00:00
|
|
|
got = self.client.get('/web/user.com/following')
|
2023-01-19 23:25:56 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
self.assertNotIn('class="follower', got.get_data(as_text=True))
|
|
|
|
|
2023-05-30 23:36:18 +00:00
|
|
|
def test_following_fake(self):
|
|
|
|
self.make_user('foo.com', cls=Fake)
|
2023-06-11 15:14:17 +00:00
|
|
|
got = self.client.get('/fa/foo.com/following')
|
2023-05-30 23:36:18 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2022-11-22 23:21:53 +00:00
|
|
|
def test_following_user_not_found(self):
|
2023-06-06 21:50:20 +00:00
|
|
|
got = self.client.get('/web/nope.com/following')
|
2022-11-22 23:21:53 +00:00
|
|
|
self.assert_equals(404, got.status_code)
|
|
|
|
|
2023-05-30 21:08:13 +00:00
|
|
|
def test_following_redirect(self):
|
|
|
|
got = self.client.get('/user/user.com/following')
|
|
|
|
self.assert_equals(301, got.status_code)
|
|
|
|
self.assert_equals('/web/user.com/following', got.headers['Location'])
|
|
|
|
|
2023-02-09 16:23:31 +00:00
|
|
|
def test_following_before_empty(self):
|
2023-06-06 21:50:20 +00:00
|
|
|
got = self.client.get(f'/web/user.com/following?before={util.now().isoformat()}')
|
2023-02-09 16:23:31 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
|
|
|
def test_following_after_empty(self):
|
2023-06-06 21:50:20 +00:00
|
|
|
got = self.client.get(f'/web/user.com/following?after={util.now().isoformat()}')
|
2023-02-09 16:23:31 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2022-11-22 23:21:53 +00:00
|
|
|
def test_feed_user_not_found(self):
|
2023-06-06 21:50:20 +00:00
|
|
|
got = self.client.get('/web/nope.com/feed')
|
2022-11-22 23:21:53 +00:00
|
|
|
self.assert_equals(404, got.status_code)
|
|
|
|
|
2023-05-30 23:36:18 +00:00
|
|
|
def test_feed_web_redirect(self):
|
2023-03-19 22:43:55 +00:00
|
|
|
got = self.client.get('/user/user.com/feed')
|
2023-05-30 21:08:13 +00:00
|
|
|
self.assert_equals(301, got.status_code)
|
|
|
|
self.assert_equals('/web/user.com/feed', got.headers['Location'])
|
|
|
|
|
2023-05-30 23:36:18 +00:00
|
|
|
def test_feed_fake(self):
|
|
|
|
self.make_user('foo.com', cls=Fake)
|
2023-06-11 15:14:17 +00:00
|
|
|
got = self.client.get('/fa/foo.com/feed')
|
2023-05-30 23:36:18 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
|
2023-05-30 21:08:13 +00:00
|
|
|
def test_feed_html_empty(self):
|
|
|
|
got = self.client.get('/web/user.com/feed')
|
2022-11-17 15:38:52 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
self.assert_equals([], microformats2.html_to_activities(got.text))
|
|
|
|
|
|
|
|
def test_feed_html(self):
|
2023-01-28 23:07:05 +00:00
|
|
|
self.add_objects()
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com/feed')
|
2022-11-17 15:38:52 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
self.assert_equals(self.EXPECTED,
|
|
|
|
contents(microformats2.html_to_activities(got.text)))
|
|
|
|
|
|
|
|
def test_feed_atom_empty(self):
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com/feed?format=atom')
|
2022-11-17 15:38:52 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
self.assert_equals([], atom.atom_to_activities(got.text))
|
|
|
|
|
|
|
|
def test_feed_atom(self):
|
2023-01-28 23:07:05 +00:00
|
|
|
self.add_objects()
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com/feed?format=atom')
|
2022-11-17 15:38:52 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
self.assert_equals(self.EXPECTED, contents(atom.atom_to_activities(got.text)))
|
|
|
|
|
|
|
|
def test_feed_rss_empty(self):
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com/feed?format=rss')
|
2022-11-17 15:38:52 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
self.assert_equals([], rss.to_activities(got.text))
|
|
|
|
|
|
|
|
def test_feed_rss(self):
|
2023-01-28 23:07:05 +00:00
|
|
|
self.add_objects()
|
2023-05-30 21:08:13 +00:00
|
|
|
got = self.client.get('/web/user.com/feed?format=rss')
|
2022-11-17 15:38:52 +00:00
|
|
|
self.assert_equals(200, got.status_code)
|
|
|
|
self.assert_equals(self.EXPECTED, contents(rss.to_activities(got.text)))
|
2023-05-26 23:36:45 +00:00
|
|
|
|
|
|
|
def test_nodeinfo(self):
|
|
|
|
# just check that it doesn't crash
|
|
|
|
self.client.get('/nodeinfo.json')
|