Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more tests #395

Merged
merged 10 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions myhpi/core/markdown/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def breakify(self, match):
)


class QuorumPrepocessor(MinutesBasePreprocessor):
class QuorumPreprocessor(MinutesBasePreprocessor):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.patterns = [
Expand Down Expand Up @@ -138,11 +138,11 @@ class HeadingLevelPreprocessor(MinutesBasePreprocessor):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.patterns = [
(r"^#{1,5}", self.decrease),
(r"^#{1,5} ", self.decrease),
]

def decrease(self, match):
return f"{match.group(0)}#"
return f"#{match.group(0)}"


class InternalLinkPattern(LinkInlineProcessor):
Expand All @@ -158,6 +158,9 @@ def handleMatch(self, m, data=None):
def url(self, id):
return Page.objects.get(id=id).localized.get_url()

def default_pattern():
return r"\[(?P<title>[^\[]+)\]\(page:(?P<id>\d+)\)"


class ImagePattern(LinkInlineProcessor):
def handleMatch(self, m, data=None):
Expand All @@ -174,23 +177,26 @@ def handleMatch(self, m, data=None):
def url(self, id):
return Image.objects.get(id=id).get_rendition("width-800").url

def default_pattern():
return r"!\[(?P<title>[^\[]+)\]\(image:(?P<id>\d+)\)"


class MinuteExtension(Extension):
def extendMarkdown(self, md):
md.registerExtension(self)
md.preprocessors.register(VotePreprocessor(md), "votify", 200)
md.preprocessors.register(StartEndPreprocessor(md), "start_or_endify", 200)
md.preprocessors.register(BreakPreprocessor(md), "breakify", 200)
md.preprocessors.register(QuorumPrepocessor(md), "quorumify", 200)
md.preprocessors.register(QuorumPreprocessor(md), "quorumify", 200)
md.preprocessors.register(EnterLeavePreprocessor(md), "enter_or_leavify", 200)
md.preprocessors.register(HeadingLevelPreprocessor(md), "decrease", 200)
md.inlinePatterns.register(
InternalLinkPattern(r"\[(?P<title>[^\[]+)\]\(page:(?P<id>\d+)\)", md),
InternalLinkPattern(InternalLinkPattern.default_pattern(), md),
"InternalLinkPattern",
200,
)
md.inlinePatterns.register(
ImagePattern(r"!\[(?P<title>[^\[]+)\]\(image:(?P<id>\d+)\)", md),
ImagePattern(ImagePattern.default_pattern(), md),
"ImagePattern",
200,
)
17 changes: 12 additions & 5 deletions myhpi/polls/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,25 @@ def serve(self, request, *args, **kwargs):
elif request.method == "POST" and self.can_vote(request.user):
choices = request.POST.getlist("choice")
if len(choices) == 0:
messages.error(request, "You must at least select one choice.")
messages.error(request, "You must select at least one choice.")
elif len(choices) > self.max_allowed_answers:
messages.error(
request,
"You can only select up to {} options.".format(self.max_allowed_answers),
)
else:
confirmed_choices = 0
for choice_id in choices:
choice = self.choices.filter(id=choice_id)
choice.update(votes=F("votes") + 1)
self.participants.add(request.user)
messages.success(request, "Your vote has been counted.")
choice = self.choices.filter(id=choice_id).first()
if choice and choice.page == self:
choice.votes += 1
choice.save()
confirmed_choices += 1
else:
messages.error(request, "Invalid choice.")
if confirmed_choices > 0:
self.participants.add(request.user)
messages.success(request, "Your vote has been counted.")
return redirect(self.relative_url(self.get_site()))

return super().serve(request, *args, **kwargs)
Expand Down
67 changes: 64 additions & 3 deletions myhpi/tests/core/setup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.contrib.auth.models import Group, User
from wagtail.models import Site
from django.contrib.auth.models import Group, Permission, User
from wagtail.documents.models import Document
from wagtail.models import Collection, GroupCollectionPermission, Site

from myhpi.core.models import (
FirstLevelMenuItem,
Expand Down Expand Up @@ -41,7 +42,7 @@ def create_users():

def create_groups(users):
superuser, student, student_representative = users
students = Group.objects.create(name="Students")
students = Group.objects.create(name="Student")
fsr = Group.objects.create(name="Student Representative Group")

students.user_set.add(superuser)
Expand Down Expand Up @@ -228,12 +229,70 @@ def setup_minutes(group, students_group, parent, user):
return minutes, minutes_list


def create_collections(groups):
root_collection = Collection.get_first_root_node()
for group in groups:
group_collection = root_collection.add_child(name=f"{group.name} collection")
group_collection.save()
GroupCollectionPermission.objects.create(
group=group,
collection=group_collection,
permission=Permission.objects.get(
content_type__app_label="wagtaildocs", codename="add_document"
),
)
GroupCollectionPermission.objects.create(
group=group,
collection=group_collection,
permission=Permission.objects.get(
content_type__app_label="wagtaildocs", codename="change_document"
),
)
GroupCollectionPermission.objects.create(
group=group,
collection=group_collection,
permission=Permission.objects.get(
content_type__app_label="wagtaildocs", codename="choose_document"
),
)
yield group_collection


def get_test_image_file():
from django.core.files.uploadedfile import SimpleUploadedFile

image_file = SimpleUploadedFile(
name="test_image.jpg",
content=open("myhpi/tests/files/test_image.jpg", "rb").read(),
content_type="image/jpeg",
)
return image_file


def create_documents(collections):
documents = [
Document.objects.create(
title="First document",
file=get_test_image_file(),
collection=collections[0],
),
Document.objects.create(
title="Second document",
file=get_test_image_file(),
collection=collections[1],
),
]
return documents


def setup_data():
users = create_users()
groups = create_groups(users)
basic_pages = create_basic_page_structure()
information_pages = create_information_pages(groups, basic_pages["information_menu"])
minutes, minutes_list = setup_minutes(groups[1], groups[0], basic_pages["fsr_menu"], users[2])
collections = list(create_collections(groups))
documents = create_documents(collections)

return {
"basic_pages": basic_pages,
Expand All @@ -242,4 +301,6 @@ def setup_data():
"pages": information_pages,
"minutes": minutes,
"minutes_list": minutes_list,
"collections": collections,
"documents": documents,
}
49 changes: 49 additions & 0 deletions myhpi/tests/core/test_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from myhpi.core.auth import MyHPIOIDCAB
from myhpi.tests.core.utils import MyHPIPageTestCase


class AuthTests(MyHPIPageTestCase):
def setUp(self):
super().setUp()
self.auth_backend = MyHPIOIDCAB()

def test_create_user(self):
claims = {
"email": "ali.gator@example.org",
"given_name": "Ali",
"family_name": "Gator",
"sub": "ali.gator",
}
user = self.auth_backend.create_user(claims)
self.assertEqual(user.username, "ali.gator")
self.assertFalse(user.groups.filter(name="Student").exists())

matching_users = self.auth_backend.filter_users_by_claims(claims)
self.assertEqual(len(matching_users), 1)

def test_create_student(self):
claims = {
"email": "grace.hopper@student.uni-potsdam.example.com",
"given_name": "Grace",
"family_name": "Hopper",
"sub": "grace.hopper",
}
user = self.auth_backend.create_user(claims)
self.assertEqual(user.username, "grace.hopper")
self.assertEqual(user.email, "grace.hopper@student.example.com")
self.assertTrue(user.groups.filter(name="Student").exists())

def test_update_user(self):
claims = {
"email": "jw.goethe@weimar.de",
"given_name": "Johann Wolfgang",
"family_name": "Goethe",
"sub": "jw.goethe",
}
user = self.auth_backend.create_user(claims)
self.assertEqual(user.username, "jw.goethe")
self.assertEqual(user.last_name, "Goethe")
claims["family_name"] = "von Goethe"
user = self.auth_backend.update_user(user, claims)
self.assertEqual(user.first_name, "Johann Wolfgang")
self.assertEqual(user.last_name, "von Goethe")
41 changes: 41 additions & 0 deletions myhpi/tests/core/test_email_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from unittest import TestCase

from myhpi import settings
from myhpi.core.utils import (
alternative_emails,
email_belongs_to_domain,
replace_email_domain,
toggle_institution,
)


class EmailUtilTest(TestCase):
def test_email_belongs_to_domain(self):
emails = ["abc@example.com", "abc@myhpi.de"]
domains = ["example.com", "myhpi.de"]
for email, domain in zip(emails, domains):
self.assertTrue(email_belongs_to_domain(email, domain))
self.assertFalse(email_belongs_to_domain(emails[0], domains[1]))

def test_replace_email_domain(self):
email = "abc@example.com"
original_domain = "example.com"
new_domain = "myhpi.de"
self.assertEqual(replace_email_domain(email, original_domain, new_domain), "abc@myhpi.de")

def test_toggle_institution(self):
emails = ["user1@hpi.uni-potsdam.de", "user2@unrelated.com", "user3@hpi.de"]
expected = ["user1@hpi.de", "user2@unrelated.com", "user3@hpi.uni-potsdam.de"]
for email, expected_email in zip(emails, expected):
toggled = list(toggle_institution(email))
if not "unrelated" in email:
self.assertEqual(toggled[0], expected_email)

def test_alternative_emails(self):
email = "user@hpi.de"
alternatives = [
"user@hpi.uni-potsdam.de",
"user@student.hpi.de",
"user@student.hpi.uni-potsdam.de",
]
self.assertSetEqual(set(alternative_emails(email)), set(alternatives))
105 changes: 105 additions & 0 deletions myhpi/tests/core/test_polls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from datetime import datetime, timedelta

from myhpi.polls.models import Poll, PollChoice, PollList
from myhpi.tests.core.utils import MyHPIPageTestCase


class PollTests(MyHPIPageTestCase):
def setUp(self):
super().setUp()
self.poll_list = PollList(
title="Polls",
slug="polls",
path="0001000200010005",
depth=4,
is_public=True,
)
self.information_menu.add_child(instance=self.poll_list)

self.poll = Poll(
title="How are you?",
slug="how-are-you",
question="How are you?",
description="This is a poll to check how you are.",
start_date=datetime.now() - timedelta(days=1),
end_date=datetime.now() + timedelta(days=1),
max_allowed_answers=1,
results_visible=False,
is_public=True,
)

self.poll_list.add_child(instance=self.poll)

self.choice_good = PollChoice(
text="Good",
page=self.poll,
votes=0,
)
self.choice_good.save()
self.choice_bad = PollChoice(
text="Bad",
page=self.poll,
votes=0,
)
self.choice_bad.save()

def test_can_vote_once(self):
self.sign_in_as_student()
self.assertTrue(self.poll.can_vote(self.student))
self.poll.participants.add(self.student)
self.assertFalse(self.poll.can_vote(self.student))

def test_post_vote(self):
self.sign_in_as_student()
self.assertTrue(self.poll.can_vote(self.student))
self.client.post(
self.poll.url,
data={"choice": [self.choice_good.id]},
)
self.choice_good.refresh_from_db()
self.assertEqual(self.choice_good.votes, 1)
self.assertEqual(self.choice_good.percentage(), 100)
self.assertEqual(self.choice_bad.percentage(), 0)
self.assertFalse(self.poll.can_vote(self.student))

def test_post_vote_invalid_choice(self):
self.sign_in_as_student()
self.assertTrue(self.poll.can_vote(self.student))
self.client.post(
self.poll.url,
data={"choice": [self.choice_good.id + 9999]},
)
self.choice_good.refresh_from_db()
self.assertEqual(self.choice_good.votes, 0)
self.assertTrue(self.poll.can_vote(self.student))

def test_post_vote_no_choice(self):
self.sign_in_as_student()
self.assertTrue(self.poll.can_vote(self.student))
response = self.client.post(
self.poll.url,
data={"choice": []},
)
self.assertContains(response, "You must select at least one choice.")
self.assertTrue(self.poll.can_vote(self.student))

def test_post_vote_too_many_choices(self):
self.sign_in_as_student()
self.assertTrue(self.poll.can_vote(self.student))
response = self.client.post(
self.poll.url,
data={"choice": [self.choice_good.id, self.choice_bad.id]},
)
self.assertContains(response, "You can only select up to 1 options.", 1)
self.assertTrue(self.poll.can_vote(self.student))

def test_post_vote_before_start_date(self):
self.sign_in_as_student()
self.poll.start_date = datetime.now() + timedelta(days=1)
self.poll.save()
self.assertTrue(self.poll.can_vote(self.student))
response = self.client.post(
self.poll.url, data={"choice": [self.choice_good.id]}, follow=True
)
self.assertContains(response, "This poll has not yet started.")
self.assertTrue(self.poll.can_vote(self.student))
Loading
Loading