diff --git a/calsocial/models.py b/calsocial/models.py index a21035b..f310619 100644 --- a/calsocial/models.py +++ b/calsocial/models.py @@ -317,6 +317,23 @@ class Profile(db.Model): # pylint: disable=too-few-public-methods return NotImplemented + def follow(self, follower): + """Make ``follower`` follow this profile + """ + + if not isinstance(follower, Profile): + raise TypeError('Folloer must be a Profile object') + + user_follow = UserFollow(follower=follower, followed=self, accepted_at=datetime.utcnow()) + db.session.add(user_follow) + notification = Notification(profile=self, + actor=follower, + item=self, + action=NotificationAction.follow) + db.session.add(notification) + + return user_follow + class Event(db.Model): """Database model for events diff --git a/tests/helpers.py b/tests/helpers.py index 47195a5..474fba7 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -23,14 +23,20 @@ import calsocial from calsocial.models import db -@pytest.fixture -def client(): - """Fixture that provides a Flask test client +def configure_app(): + """Set default configuration values for testing """ calsocial.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' calsocial.app.config['TESTING'] = True calsocial.app.config['WTF_CSRF_ENABLED'] = False + + +@pytest.fixture +def client(): + """Fixture that provides a Flask test client + """ + configure_app() client = calsocial.app.test_client() with calsocial.app.app_context(): @@ -49,3 +55,18 @@ def login(client, username, password, no_redirect=False): return client.post('/login', data={'email': username, 'password': password}, follow_redirects=not no_redirect) + + +@pytest.fixture +def database(): + """Fixture to provide all database tables in an active application context + """ + + configure_app() + + with calsocial.app.app_context(): + db.create_all() + + yield db + + db.drop_all() diff --git a/tests/test_follow.py b/tests/test_follow.py new file mode 100644 index 0000000..3309e1e --- /dev/null +++ b/tests/test_follow.py @@ -0,0 +1,55 @@ +# Calendar.social +# Copyright (C) 2018 Gergely Polonkai +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +"""Profile related tests for Calendar.social +""" + +import calsocial +from calsocial.models import db, Notification, NotificationAction, Profile, User + +from helpers import database + + +def test_profile_follow(database): + """Test the Profile.follow() method + """ + + follower_user = User(username='follower', + email='follower@example.com', + password='passworder', + active=True) + followed_user = User(username='followed', email='followed@example.com') + follower = Profile(display_name='Follower', user=follower_user) + followed = Profile(display_name='Followed', user=followed_user) + db.session.add_all([follower, followed]) + db.session.commit() + + user_follow = followed.follow(follower=follower) + db.session.commit() + + # The new follower record should have the fields set correctly + assert user_follow.followed == followed + assert user_follow.follower == follower + + # There should be a notification about the follow + notification = Notification.query.one() + + assert notification.actor == follower + assert notification.item == followed + assert notification.action == NotificationAction.follow + + assert follower in followed.follower_list + assert followed in follower.followed_list