Skip to content

Commit

Permalink
Add more tests (#395)
Browse files Browse the repository at this point in the history
  • Loading branch information
frcroth authored Oct 16, 2023
1 parent 1f21357 commit 7b485d6
Show file tree
Hide file tree
Showing 12 changed files with 457 additions and 43 deletions.
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": "[email protected]",
"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": "[email protected]",
"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, "[email protected]")
self.assertTrue(user.groups.filter(name="Student").exists())

def test_update_user(self):
claims = {
"email": "[email protected]",
"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 = ["[email protected]", "[email protected]"]
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 = "[email protected]"
original_domain = "example.com"
new_domain = "myhpi.de"
self.assertEqual(replace_email_domain(email, original_domain, new_domain), "[email protected]")

def test_toggle_institution(self):
emails = ["[email protected]", "[email protected]", "[email protected]"]
expected = ["[email protected]", "[email protected]", "[email protected]"]
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 = "[email protected]"
alternatives = [
"[email protected]",
"[email protected]",
"[email protected]",
]
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

0 comments on commit 7b485d6

Please sign in to comment.