Files
website-v2/users/tests/test_models.py

225 lines
7.0 KiB
Python

import pytest
from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.exceptions import ValidationError
from pytest_django.asserts import assertQuerySetEqual
from ..models import Preferences
User = get_user_model()
def test_regular_user(user):
assert user.is_active is True
assert user.is_staff is False
assert user.is_superuser is False
def test_staff_user(staff_user):
assert staff_user.is_active is True
assert staff_user.is_staff is True
assert staff_user.is_superuser is False
def test_super_user(super_user):
assert super_user.is_active is True
assert super_user.is_staff is True
assert super_user.is_superuser is True
def test_profile_image_filename_root(user):
assert user.profile_image_filename_root == f"profile-{user.id}"
def test_user_model_image_validator(user):
"""
Test that the `image` field on the User model only accepts certain file types.
"""
# Valid image file
valid_image = SimpleUploadedFile(
"test.jpg", b"file_content", content_type="image/jpeg"
)
user.profile_image = valid_image
# This should not raise any errors
user.full_clean()
# Invalid image file
invalid_image = SimpleUploadedFile(
"test.pdf", b"file_content", content_type="application/pdf"
)
user.profile_image = invalid_image
# This should raise a ValidationError
with pytest.raises(ValidationError):
user.full_clean()
def test_user_model_image_file_size(user):
"""
Test that the `image` field rejects files larger than a specific size.
"""
valid_image = SimpleUploadedFile(
"test.jpg", b"a" * (1 * 1024 * 1024 - 1), content_type="image/jpeg"
)
user.profile_image = valid_image
# This should not raise any errors
user.full_clean()
# This should fail (just over 1MB)
invalid_image = SimpleUploadedFile(
"too_large.jpg", b"a" * (1 * 1024 * 1024 + 1), content_type="image/jpeg"
)
user.profile_image = invalid_image
# This should raise a ValidationError for file size
with pytest.raises(ValidationError):
user.full_clean()
def test_claim(user):
user.claimed = False
user.save()
user.refresh_from_db()
assert not user.claimed
user.claim()
user.refresh_from_db()
assert user.claimed
def test_find_contributor_by_email(user):
found_user = User.objects.find_contributor(email=user.email)
assert found_user == user
def test_find_contributor_by_email_not_found():
non_existent_email = "nonexistent@email.com"
found_user = User.objects.find_contributor(email=non_existent_email)
assert found_user is None
def test_find_contributor_not_author_or_maintainer(user: User):
found_user = User.objects.find_contributor(display_name=user.display_name)
assert found_user is None
def test_find_contributor_by_display_name_not_found():
non_existent_name = "Nonexistent User"
found_user = User.objects.find_contributor(display_name=non_existent_name)
assert found_user is None
def test_find_contributor_by_display_name_multiple_results(user, staff_user):
staff_user.display_name = user.display_name
staff_user.save()
found_user = User.objects.find_contributor(display_name=user.display_name)
assert found_user is None
def test_find_contributor_no_args():
found_user = User.objects.find_contributor()
assert found_user is None
def test_find_contributor_is_author(user, library):
library.authors.add(user)
library.save()
found_user = User.objects.find_contributor(display_name=user.display_name)
assert found_user == user
def test_find_contributor_is_maintainer(user, library_version):
library_version.maintainers.add(user)
library_version.save()
found_user = User.objects.find_contributor(display_name=user.display_name)
assert found_user == user
def test_preferences(user):
assert Preferences.objects.get(user=user) == user.preferences
assert user.preferences.notifications == {
"own-news-approved": [Preferences.NEWS_TYPES_WILDCARD],
"others-news-posted": [],
"others-news-needs-moderation": [Preferences.NEWS_TYPES_WILDCARD],
"terms-changed": [False],
}
def test_preferences_set_value_terms(user):
notification_type = "terms-changed"
attr_name = f"allow_notification_{notification_type.replace('-', '_')}"
assert user.preferences.notifications[notification_type] == [False]
assert getattr(user.preferences, attr_name) is False
# Opt in
setattr(user.preferences, attr_name, True)
assert user.preferences.notifications[notification_type] == [True]
assert getattr(user.preferences, attr_name) is True
@pytest.mark.parametrize(
"notification_type, default",
[
("own-news-approved", [Preferences.NEWS_TYPES_WILDCARD]),
("others-news-posted", []),
("others-news-needs-moderation", [Preferences.NEWS_TYPES_WILDCARD]),
],
)
def test_preferences_set_value(user, notification_type, default):
attr_name = f"allow_notification_{notification_type.replace('-', '_')}"
# default value
assert user.preferences.notifications[notification_type] == default
assert getattr(user.preferences, attr_name) == (
Preferences.ALL_NEWS_TYPES
if Preferences.NEWS_TYPES_WILDCARD in default
else default
)
# set empty list
setattr(user.preferences, attr_name, [])
assert getattr(user.preferences, attr_name) == []
assert user.preferences.notifications[notification_type] == []
# set a few values
setattr(user.preferences, attr_name, ["link", "blogpost"])
assert getattr(user.preferences, attr_name) == ["blogpost", "link"]
assert user.preferences.notifications[notification_type] == ["blogpost", "link"]
# set all values
setattr(user.preferences, attr_name, list(reversed(Preferences.ALL_NEWS_TYPES)))
assert getattr(user.preferences, attr_name) == Preferences.ALL_NEWS_TYPES
assert user.preferences.notifications[notification_type] == [
Preferences.NEWS_TYPES_WILDCARD
]
@pytest.mark.parametrize("news_type", Preferences.ALL_NEWS_TYPES)
def test_manager_preferences_shortcuts(tp, make_user, news_type):
# user does not allow notifications
make_user(email="u1@example.com", allow_notification_others_news_posted=[])
# allows nofitications for all news type
u2 = make_user(
email="u2@example.com",
allow_notification_others_news_posted=[Preferences.NEWS_TYPES_WILDCARD],
)
# allows only for the same type as entry
u3 = make_user(
email="u3@example.com", allow_notification_others_news_posted=[news_type]
)
# allows for any other type except entry's
make_user(
email="u4@example.com",
allow_notification_others_news_posted=[
t for t in Preferences.ALL_NEWS_TYPES if t != news_type
],
)
with tp.assertNumQueriesLessThan(2, verbose=True):
result = User.objects.allow_notification_others_news_posted(news_type)
assertQuerySetEqual(result, [u2, u3], ordered=False)