diff --git a/.gitignore b/.gitignore index aa9f6d1..68bbb03 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ members/logs/* logs/ /media/ node_modules/ -/.coverage +.coverage db.sqlite3 requirements_henu.txt /collected_static/ diff --git a/webapp/serializers.py b/webapp/serializers.py index e226812..25517ae 100644 --- a/webapp/serializers.py +++ b/webapp/serializers.py @@ -10,7 +10,7 @@ class SignupFormSerializer(serializers.HyperlinkedModelSerializer): fields = ('id', 'title', 'start_time', 'end_time', 'questions') -class EventSerializer(serializers.HyperlinkedModelSerializer): +class EventSerializer(serializers.ModelSerializer): signupForm = SignupFormSerializer(many=True, read_only=True, required=False) signup_id = serializers.PrimaryKeyRelatedField( many=True, @@ -25,8 +25,8 @@ class EventSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Event - fields = ('id', 'tag_id', 'tags', 'visible', 'title', 'description', - 'content', 'start_time', 'end_time', 'location', 'signup_id', 'signupForm') + fields = ('id', 'tag_id', 'tags', 'visible', 'title_fi', 'title_en', 'description_fi', 'description_en', + 'content_fi', 'content_en', 'start_time', 'end_time', 'location', 'signup_id', 'signupForm') depth = 1 def create(self, validated_data): @@ -79,7 +79,7 @@ class SavedQuestionsSerializer(serializers.ModelSerializer): class TagSerializer(serializers.ModelSerializer): class Meta: model = Tag - fields = ('id', 'slug', 'name', 'icon') + fields = ('id', 'slug', 'name_fi', 'name_en', 'icon') class FeedSerializer(serializers.ModelSerializer): @@ -91,8 +91,8 @@ class FeedSerializer(serializers.ModelSerializer): class Meta: model = Feed - fields = ('id', 'tags', 'tag_id', 'visible', 'title', 'description', - 'content', 'publish_time', 'autohide', 'autohide_enabled') + fields = ('id', 'tags', 'tag_id', 'visible', 'title_fi', 'title_en', 'description_fi', 'description_en', + 'content_fi', 'content_en', 'publish_time', 'autohide', 'autohide_enabled') depth = 1 def create(self, validated_data): diff --git a/webapp/tests.py b/webapp/tests.py deleted file mode 100644 index 067ea45..0000000 --- a/webapp/tests.py +++ /dev/null @@ -1,131 +0,0 @@ -"""Tests for webapp.""" - -from django.test import TestCase -from django.core.files import File -from django.contrib.auth.models import User -from rest_framework.test import APITestCase -from rest_framework import status -from rest_framework.test import force_authenticate -from webapp.models import Tag, Feed -from webapp.serializers import TagSerializer, FeedSerializer - -from collections import OrderedDict -from itertools import islice -import tempfile - - -class TagsTestCase(APITestCase): - - def setUp(self): - self.icon = tempfile.NamedTemporaryFile(suffix=".jpg").name - Tag.objects.create(slug='Party', name='Bileet', icon=self.icon) - - def test_get_single_tag(self): - self.assertEqual(Tag.objects.count(), 1) - response = self.client.get('/api/tags/', format='json') - self.assertTrue(status.is_success(response.status_code)) - - # We dont care about icon, so response is sliced - sliced_response = OrderedDict(islice(response.data['results'][0].items(), 3)) - tag1 = Tag.objects.get(slug="Party") - self.assertEqual(sliced_response, {'id': tag1.id, 'slug': 'Party', 'name': 'Bileet'}) - - def test_get_single_tag_serializer(self): - response = self.client.get('/api/tags/', format='json') - self.assertTrue(status.is_success(response.status_code)) - - tags = Tag.objects.all() - serializer = TagSerializer(tags, many=True) - # Icon on serializer is returned without protocol and domain - # Assert these individually - resp_icon = response.data['results'][0].pop('icon') - serial_icon = serializer.data[0].pop('icon') - self.assertEqual(response.data['results'], serializer.data) - self.assertEqual(resp_icon, "http://testserver" + serial_icon) - - def test_get_multiple_tags(self): - self.assertEqual(Tag.objects.count(), 1) - Tag.objects.create(slug='Freshmen', name='Fuksit', icon=self.icon) - Tag.objects.create(slug='International', name='Ulkkarit', icon=self.icon) - self.assertEqual(Tag.objects.count(), 3) - - response = self.client.get('/api/tags/', format='json') - self.assertTrue(status.is_success(response.status_code)) - - # We dont care about icon, so response is sliced - tag1 = Tag.objects.get(slug="Party") - sliced_response = OrderedDict(islice(response.data['results'][0].items(), 3)) - self.assertEqual(sliced_response, {'id': tag1.id, 'slug': 'Party', 'name': 'Bileet'}) - sliced_response = OrderedDict(islice(response.data['results'][1].items(), 3)) - tag2 = Tag.objects.get(slug="Freshmen") - self.assertEqual(sliced_response, {'id': tag2.id, 'slug': 'Freshmen', 'name': 'Fuksit'}) - sliced_response = OrderedDict(islice(response.data['results'][2].items(), 3)) - tag3 = Tag.objects.get(slug="International") - self.assertEqual(sliced_response, {'id': tag3.id, 'slug': 'International', 'name': 'Ulkkarit'}) - - def test_create_tag(self): - self.assertEqual(Tag.objects.count(), 1) - response = self.client.post('/api/tags/', {'slug': 'Test', 'name': 'Testinimi', 'icon': self.icon}, format='multipart') - self.assertFalse(status.is_success(response.status_code)) - self.assertEqual(Tag.objects.count(), 1) - - def test_invalid_tag(self): - self.assertEqual(Tag.objects.count(), 1) - response = self.client.get('/api/tags/15', format='json', follow=True) - self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) - - -class FeedTestCase(APITestCase): - - def setUp(self): - self.icon = tempfile.NamedTemporaryFile(suffix=".jpg").name - Tag.objects.create(slug='testtag1', name='test1', icon=self.icon) - tag1 = Tag.objects.get(slug="testtag1") - Tag.objects.create(slug="testtag2", name='test2', icon=self.icon) - tag2 = Tag.objects.get(slug="testtag2") - self.assertEqual(Tag.objects.count(), 2) - - Feed.objects.create(title="TestFeed", visible=True, description="diidadaapa", content="lorem ipsum") - Feed.objects.get(title="TestFeed").tags.add(tag1) - Feed.objects.get(title="TestFeed").tags.add(tag2) - self.assertEqual(Feed.objects.count(), 1) - self.assertEqual(Feed.objects.all()[0].tags.count(), 2) - - username, password = 'test_admin', 'password123' - self.authClient = User.objects.create_superuser(username, 'myemail@test.com', password) - - def test_get_feed(self): - response = self.client.get('/api/feed/', format='json') - self.assertTrue(status.is_success(response.status_code)) - - feeds = Feed.objects.all() - serializer = FeedSerializer(feeds, many=True) - - # DRF extends path given by serializer with the protocol and domain for icon - # Ignore tag on serializer and response. This is tested on TagTestCase. - # Note that we assume the length here to be 1 - response.data['results'][0].pop('tags') - serializer.data[0].pop('tags') - self.assertEqual(response.data['results'], serializer.data) - - def test_post_feed(self): - Tag.objects.create(slug="test1", name="testsds") - Tag.objects.create(slug="test2", name="testsdsd") - tag1_id = Tag.objects.get(slug="test1").id - tag2_id = Tag.objects.get(slug="test2").id - - data = {'tags': [tag1_id, tag2_id], 'title': 'testtitle', 'visible': 'True', 'description': 'liirumlaarum', 'content': 'lorem ipsum'} - # Try post without authentication - response = self.client.post('/api/feed/', data, format='multipart') - self.assertTrue(status.is_client_error(response.status_code)) - self.assertEqual(Feed.objects.count(), 1) - # Authenticate - self.client.force_authenticate(user=self.authClient) - response = self.client.post('/api/feed/', data, format='multipart') - # Return success and check object was created - self.assertTrue(status.is_success(response.status_code)) - self.assertEqual(Feed.objects.count(), 2) - - created = Feed.objects.get(title="testtitle") - print(created.tags) - # self.assertEqual(created.tags.count(), 2) diff --git a/webapp/tests/event_fixture.py b/webapp/tests/event_fixture.py new file mode 100644 index 0000000..e3aa8cc --- /dev/null +++ b/webapp/tests/event_fixture.py @@ -0,0 +1,36 @@ +from django.utils import timezone +from webapp.models import Event +from webapp.utils import month_from_now + + +def createEventObject(name="Testitapahtuma1", visible=True, start_time=timezone.now(), end_time=month_from_now(), tag_id=[], signup_id=[]): + return Event.objects.create( + title_fi=name, + title_en=f"title_en {name}", + visible=visible, + description_fi=f"desc_fi {name}", + description_en=f"desc_en {name}", + content_fi=f"content_fi {name}", + content_en=f"content_en {name}", + start_time=start_time, + end_time=end_time, + location=f"loc {name}" + ) + + +def createEventJSON(name="POST1", visible=True, start_time=timezone.now(), end_time=month_from_now(), tag_id=[], signup_id=[]): + return { + "tags": tag_id, + "tag_id": tag_id, + "visible": visible, + "title_fi": f"title_fi {name}", + "title_en": f"title_en {name}", + "description_fi": f"desc_fi {name}", + "description_en": f"desc_en {name}", + "content_fi": f"content_fi {name}", + "content_en": f"content_en {name}", + "start_time": start_time, + "end_time": end_time, + "signup_id": signup_id, + "location": f"loc {name}" + } diff --git a/webapp/tests/signup_fixture.py b/webapp/tests/signup_fixture.py new file mode 100644 index 0000000..a036274 --- /dev/null +++ b/webapp/tests/signup_fixture.py @@ -0,0 +1,37 @@ +from webapp.models import Signup, SignupForm +from django.utils import timezone +from webapp.utils import month_from_now + +import json + +ALL_QUESTION_TYPES = [ + {"id": "j5CeRZDvl", "name": "Asd", "type": "text", "options": []}, + {"id": "RHJhSoaLD", "name": "Asd2", "type": "radiobutton", "options": ["Yes", "no", "maybe"]}, + {"id": "i10d426d5", "name": "Asd3", "type": "checkbox", "options": ["A", "B", "C"]} +] + +ALL_QUESTION_TYPES_ANSWER = {"j5CeRZDvl": "Testi", "RHJhSoaLD": "maybe", "i10d426d5": ["B"]} + + +def createSignupForm(name="Form1", start_time=timezone.now(), end_time=month_from_now(), questions=ALL_QUESTION_TYPES, visible=True): + return SignupForm.objects.create( + title=name, + start_time=start_time, + end_time=end_time, + questions=questions, + visible=visible + ) + + +def createSignupObject(form, answer): + return Signup.objects.create( + signupForm=form, + answer=answer + ) + + +def createSignupJSON(form_id, answer): + return { + "signupForm_id": form_id, + "answer": json.dumps(answer) + } diff --git a/webapp/tests/tag_fixture.py b/webapp/tests/tag_fixture.py new file mode 100644 index 0000000..3b0cff5 --- /dev/null +++ b/webapp/tests/tag_fixture.py @@ -0,0 +1,15 @@ +from webapp.models import Tag +import tempfile + + +def createTagIcon(): + return tempfile.NamedTemporaryFile(suffix=".jpg").name + + +def tagBuilder(slug="Tag1", icon=createTagIcon()): + return Tag.objects.create( + slug=slug, + name_fi=slug + " name_fi", + name_en=slug + " name_en", + icon=icon + ) diff --git a/webapp/tests/test_contact.py b/webapp/tests/test_contact.py new file mode 100644 index 0000000..747fbf7 --- /dev/null +++ b/webapp/tests/test_contact.py @@ -0,0 +1,96 @@ +from django.test import TestCase +from django.contrib.auth.models import User +from django.utils import timezone +from rest_framework import status +from rest_framework.test import APITestCase + +from webapp.models import Official, Role, Occupation, Committee +from webapp.serializers import OccupationSerializer + + +URL = "/api/contacts/" +COMMITTEE = Committee.objects.create( + name_fi="Viestintä", + name_en="Communications" +) + + +def createRoleBoard(): + return Role.objects.create( + name_fi="Metsuri", + name_en="The lumberjack", + is_board=True, + description_fi="Toimikunta PJ", + description_en="Committee Chair" + ) + + +def createRoleNoBoard(): + return Role.objects.create( + name_fi="Toimari", + name_en="Official", + is_board=False, + description_fi="Toimikunta jäbä", + description_en="Committee dude(tte)", + committee=COMMITTEE + ) + + +def createOccupation(year, role=createRoleNoBoard(), dummydata=1): + occupation = Occupation.objects.create( + start_date=timezone.datetime(year, 1, 1), + end_date=timezone.datetime(year, 12, 31), + role=role + ) + + occupation.officials.add( + createPerson(dummydata) + ) + + return occupation + + +def createPerson(name): + return Official.objects.create( + user=User.objects.create_user(f"testi{name}", "test@test.tld", "password123"), + first_name=f"first{name}", + last_name=f"last{name}", + email="test@test.tld", + phone_number="+358501234567", + image="" + ) + + +class ContactsTestCase(APITestCase): + + def setUp(self): + createOccupation(timezone.now().year, role=createRoleBoard(), dummydata=1) + createOccupation(timezone.now().year, dummydata=2) + createOccupation(1970, role=createRoleBoard(), dummydata=3) + createOccupation(1970, dummydata=4) + + def test_get(self): + response = self.client.get(f"{URL}", format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + serializer = OccupationSerializer( + Occupation.by_year(2019), + many=True + ) + self.assertEqual(response.data["results"], serializer.data) + + def test_get_by_year(self): + response = self.client.get(f"{URL}?year=1970", format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + serializer = OccupationSerializer( + Occupation.by_year(1970), + many=True + ) + + self.assertEqual(response.data["results"], serializer.data) + + def test_by_year_empty(self): + response = self.client.get(f"{URL}?year=1971") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["results"], []) diff --git a/webapp/tests/test_event.py b/webapp/tests/test_event.py new file mode 100644 index 0000000..4ecc175 --- /dev/null +++ b/webapp/tests/test_event.py @@ -0,0 +1,159 @@ +from django.test import TestCase +from django.contrib.auth.models import User +from django.utils import timezone +from rest_framework import status +from rest_framework.test import APITestCase, APIRequestFactory, force_authenticate + +from webapp.models import Event +from webapp.serializers import EventSerializer +from webapp.tests.tag_fixture import tagBuilder, createTagIcon +from webapp.tests.event_fixture import createEventObject, createEventJSON +from webapp.tests.signup_fixture import createSignupForm + +URL = "/api/events/" + + +class EventTestCase(APITestCase): + + def setUp(self): + # Visible and relevant + test1 = createEventObject( + "Testitapahtuma1", + start_time=timezone.datetime(2019, 11, 9, 12, 0, 0)) + # Invisible but relevant + createEventObject( + "Testitapahtuma2", + visible=False, + start_time=timezone.datetime(2018, 11, 9, 12, 0, 0)) + # Visible but unrelevant + test2 = createEventObject( + "Testitapahtuma3", + visible=True, + start_time=timezone.datetime(2018, 12, 9, 12, 0, 0), + end_time=timezone.datetime(2018, 12, 9, 13, 0, 0)) + # Visible and relevant + createEventObject( + "Testitapahtuma4", + visible=True, + start_time=timezone.datetime(2018, 12, 9, 12, 0, 0)) + # Add some tags + tag1 = tagBuilder() + tag2 = tagBuilder("testtag2") + self.testTagId = tag1.id + test1.tags.add(tag1) + test2.tags.add(tag2) + self.testEventId = test1.id + self.assertEqual(Event.objects.count(), 4) + + self.signupFormId = createSignupForm().id + + username, password = "test_admin", "password123" + self.authClient = User.objects.create_superuser(username, "myemail@test.com", password) + + def test_get_current_events(self): + # Get from API + response = self.client.get(URL, format="json") + # Response 200 + self.assertTrue(response.status_code, status.HTTP_200_OK) + # Response should not have old events and invisible + self.assertEqual(len(response.data["results"]), 2) + # Check that serialized data is equal to received response + expected_events = EventSerializer( + Event.objects.filter(title_fi__in=("Testitapahtuma1", "Testitapahtuma4")).order_by("start_time"), + many=True, + context={ + "request": APIRequestFactory().get(r"http://testserver/api/events/") + } + ) + self.assertEqual(response.data["results"], expected_events.data) + + def test_get_events_since(self): + response = self.client.get(f"{URL}?since=2018-01-01", format="json") + self.assertTrue(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data["results"]), 3) + + expected_events = EventSerializer( + Event.objects.filter(title_fi__in=("Testitapahtuma1", "Testitapahtuma3", "Testitapahtuma4")).order_by("start_time"), + many=True, + context={ + "request": APIRequestFactory().get(r"http://testserver/api/events/") + } + ) + self.assertEqual(response.data["results"], expected_events.data) + + def test_get_single_event(self): + response = self.client.get(f"{URL}{self.testEventId}/", format="json") + self.assertEqual(response.status_code, status.HTTP_200_OK) + + serializer = EventSerializer( + Event.objects.get(title_fi="Testitapahtuma1"), + context={ + "request": APIRequestFactory().get(r"http://testserver/api/events/") + } + ) + self.assertEqual(response.data, serializer.data) + + def test_get_invalid_event(self): + response = self.client.get(f"{URL}200/", format="json") + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_post_event(self): + # Authenticate + self.client.force_authenticate(user=self.authClient) + response = self.client.post( + URL, + createEventJSON(tag_id=[self.testTagId], signup_id=[self.signupFormId]), + format="json" + ) + + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(Event.objects.count(), 5) + + def test_post_event_unauth(self): + response = self.client.post( + URL, + createEventJSON(tag_id=[self.testTagId], signup_id=[self.signupFormId]), + format="json" + ) + + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + self.assertEqual(Event.objects.count(), 4) + + def test_update_event(self): + # Authenticate + self.client.force_authenticate(user=self.authClient) + event = Event.objects.get(id=self.testEventId) + new = createEventJSON(name="Update1", signup_id=[self.signupFormId]) + response = self.client.put( + f"{URL}{self.testEventId}/", + new, + format="json" + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + event = Event.objects.get(id=self.testEventId) + self.assertEqual(event.title_fi, "title_fi Update1") + self.assertEqual(Event.objects.count(), 4) + + def test_update_event_unauth(self): + response = self.client.put( + f"{URL}{self.testEventId}/", + createEventJSON(name="Update1"), + format="json" + ) + + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + event = Event.objects.get(id=self.testEventId) + self.assertEqual(event.title_fi, "Testitapahtuma1") + self.assertEqual(Event.objects.count(), 4) + + def test_delete_event(self): + response = self.client.delete(f"{URL}{self.testEventId}/",) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + self.assertEqual(Event.objects.count(), 4) + + # Authenticate + self.client.force_authenticate(user=self.authClient) + response = self.client.delete(f"{URL}{self.testEventId}/") + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertEqual(Event.objects.count(), 3) diff --git a/webapp/tests/test_feed.py b/webapp/tests/test_feed.py new file mode 100644 index 0000000..6da4a77 --- /dev/null +++ b/webapp/tests/test_feed.py @@ -0,0 +1,64 @@ +from django.test import TestCase +from django.contrib.auth.models import User +from rest_framework import status +from rest_framework.test import APITestCase, APIRequestFactory, force_authenticate + +from webapp.models import Feed +from webapp.serializers import FeedSerializer +from webapp.tests.tag_fixture import tagBuilder + + +class FeedTestCase(APITestCase): + + def setUp(self): + tag1 = tagBuilder() + tag2 = tagBuilder("testtag2") + + feed = Feed.objects.create(title="TestFeed", visible=True, description="diidadaapa", content="lorem ipsum") + feed.tags.add(tag1) + feed.tags.add(tag2) + self.assertEqual(Feed.objects.count(), 1) + self.assertEqual(Feed.objects.all()[0].tags.count(), 2) + + username, password = "test_admin", "password123" + self.authClient = User.objects.create_superuser(username, "myemail@test.com", password) + + def test_get_feed(self): + response = self.client.get("/api/feed/", format="json") + self.assertTrue(status.is_success(response.status_code)) + + feeds = Feed.objects.all() + serializer = FeedSerializer( + feeds, many=True, + context={ + "request": APIRequestFactory().get(r"http://testserver/api/events/") + }) + self.assertEqual(response.data["results"], serializer.data) + + def test_post_feed(self): + tag1_id = tagBuilder("test1").id + tag2_id = tagBuilder("test2").id + + data = { + "tag_id": [tag1_id, tag2_id], + "title_fi": "testtitle", + "title_en": "testtitle", + "visible": "True", + "description_fi": "liirumlaarum", + "description_en": "liirumlaarum", + "content_fi": "lorem ipsum", + "content_en": "lorem ipsum" + } + # Try post without authentication + response = self.client.post("/api/feed/", data, format="json") + self.assertTrue(response.status_code, status.HTTP_401_UNAUTHORIZED) + self.assertEqual(Feed.objects.count(), 1) + # Authenticate + self.client.force_authenticate(user=self.authClient) + response = self.client.post("/api/feed/", data, format="json") + # Return success and check object was created + self.assertTrue(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(Feed.objects.count(), 2) + + created = Feed.objects.get(title_fi="testtitle") + self.assertEqual(created.tags.count(), 2) diff --git a/webapp/tests/test_signup.py b/webapp/tests/test_signup.py new file mode 100644 index 0000000..66b0427 --- /dev/null +++ b/webapp/tests/test_signup.py @@ -0,0 +1,93 @@ +from django.test import TestCase +from unittest import skip +from django.contrib.auth.models import User +from rest_framework import status +from rest_framework.test import APITestCase, force_authenticate + +from webapp.serializers import SignupSerializer, SignupFormSerializer +from webapp.models import Signup +from webapp.tests.event_fixture import createEventObject +from webapp.tests.signup_fixture import createSignupForm, createSignupObject, createSignupJSON, ALL_QUESTION_TYPES, ALL_QUESTION_TYPES_ANSWER + + +URL = "/api/signup/" + + +class SignupTestCase(APITestCase): + + def setUp(self): + self.signupForm = createSignupForm() + self.hiddenForm = createSignupForm(visible=False) + + self.signup1 = createSignupObject(self.signupForm, ALL_QUESTION_TYPES) + self.signup2 = createSignupObject(self.signupForm, []) + + username, password = "test_admin", "password123" + self.authClient = User.objects.create_superuser(username, "myemail@test.com", password) + + def test_get_signups(self): + expected = SignupSerializer( + self.signupForm.signup_set.all(), + many=True + ) + + # Unauthorized + response = self.client.get(URL, format="json") + self.assertTrue(response.status_code, status.HTTP_401_UNAUTHORIZED) + # Authenticate + self.client.force_authenticate(user=self.authClient) + response = self.client.get(URL, format="json") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["results"], expected.data) + + def test_get_single_signup(self): + id = self.signup1.id + expected = SignupSerializer( + Signup.objects.get(id=id) + ) + + # Unauthorized + response = self.client.get(f"{URL}{id}/", format="json") + self.assertTrue(response.status_code, status.HTTP_401_UNAUTHORIZED) + # Authenticate + self.client.force_authenticate(user=self.authClient) + response = self.client.get(f"{URL}{id}/", format="json") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data, expected.data) + + def test_create_signup(self): + new = createSignupJSON(self.signupForm.id, ALL_QUESTION_TYPES_ANSWER) + response = self.client.post(URL, new, format="json") + print(response.data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(Signup.objects.count(), 3) + + def test_create_signup_404_or_hidden(self): + new = createSignupJSON(3001, ALL_QUESTION_TYPES_ANSWER) + response = self.client.post(URL, new, format="json") + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(Signup.objects.count(), 2) + + new = createSignupJSON(self.hiddenForm.id, ALL_QUESTION_TYPES_ANSWER) + response = self.client.post(URL, new, format="json") + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(Signup.objects.count(), 2) + + @skip("NotImplemented") + def test_get_hidden_forms_admin(self): + pass + + @skip("NotImplemented") + def test_create_malformed_answer(self): + response = self.client.post(URL, createSignupJSON(self.signupForm.id, []), format="json") + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + # Update and Delete are available for super admin (Django Admin) + # and to the user that signed up (uid token) + @skip("NotImplemented") + def test_update_signup_token(self): + pass + + @skip("NotImplemented") + def test_delete_signup_token(self): + pass diff --git a/webapp/tests/test_tag.py b/webapp/tests/test_tag.py new file mode 100644 index 0000000..406ea2a --- /dev/null +++ b/webapp/tests/test_tag.py @@ -0,0 +1,79 @@ +from django.test import TestCase +from django.contrib.auth.models import User +from rest_framework import status +from rest_framework.test import APITestCase, APIRequestFactory, force_authenticate + +from webapp.models import Tag +from webapp.serializers import TagSerializer + + +from webapp.tests.tag_fixture import tagBuilder, createTagIcon + + +class TagsTestCase(APITestCase): + + def setUp(self): + self.icon = createTagIcon() + tag = tagBuilder("Party", icon=self.icon) + self.tag_id = tag.id + + tagBuilder("Off") + self.assertEqual(Tag.objects.count(), 2) + + username, password = 'test_admin', 'password123' + self.authClient = User.objects.create_superuser(username, 'myemail@test.com', password) + + def test_get_multiple_tags(self): + tagBuilder("Fuksi") + tagBuilder("Inter") + + expected = TagSerializer( + Tag.objects.all(), many=True, + context={ + "request": APIRequestFactory().get(r"http://testserver/api/events/") + }).data + + response = self.client.get('/api/tags/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data['results']), 4) + + self.assertEqual( + response.data['results'], + expected + ) + + def test_get_single_tag(self): + response = self.client.get(f"/api/tags/{self.tag_id}/", format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + serializer = TagSerializer( + Tag.objects.get(id=self.tag_id), + context={ + "request": APIRequestFactory().get(r"http://testserver/api/events/") + }) + self.assertEqual(response.data, serializer.data) + + def test_get_invalid_tag(self): + response = self.client.get('/api/tags/15/', format='json') + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + # READ ONLY API! Modify result code and count + def test_create_tag(self): + # Authenticate + self.client.force_authenticate(user=self.authClient) + response = self.client.post( + "/api/tags/", + { + "slug": "Test", + "name": "Testinimi", + "name_fi": "Testinimi", + "name_en": "Test name", + "icon": self.icon + }, + format='json' + ) + + # Method Not allowed! + self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) + # Not created + self.assertEqual(Tag.objects.count(), 2) diff --git a/webapp/tests/test_templateQuestions.py b/webapp/tests/test_templateQuestions.py new file mode 100644 index 0000000..05f1a8a --- /dev/null +++ b/webapp/tests/test_templateQuestions.py @@ -0,0 +1,80 @@ +from django.test import TestCase +from django.contrib.auth.models import User +from rest_framework import status +from rest_framework.test import APITestCase, force_authenticate + +from webapp.models import TemplateQuestion +from webapp.serializers import SavedQuestionsSerializer +from webapp.tests.signup_fixture import ALL_QUESTION_TYPES +import json + + +class TemplateQuestionCase(APITestCase): + def setUp(self): + self.questions = [ + TemplateQuestion.objects.create( + name="Testi1", + question=ALL_QUESTION_TYPES + ), + TemplateQuestion.objects.create( + name="Testi2", + question=ALL_QUESTION_TYPES + ) + ] + + username, password = "test_admin", "password123" + self.authClient = User.objects.create_superuser(username, "myemail@test.com", password) + + def test_get(self): + response = self.client.get("/api/questions/", format="json") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["results"], SavedQuestionsSerializer(self.questions, many=True).data) + response = self.client.get(f"/api/questions/{self.questions[0].id}/", format="json") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data, SavedQuestionsSerializer(self.questions[0]).data) + + def test_post(self): + new = { + "name": "testi3", + "question": json.dumps(ALL_QUESTION_TYPES) + } + response = self.client.post("/api/questions/", new, format="json") + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + self.assertEqual(TemplateQuestion.objects.count(), 2) + + # Authenticate + self.client.force_authenticate(user=self.authClient) + response = self.client.post("/api/questions/", new, format="json") + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(TemplateQuestion.objects.count(), 3) + + def test_update(self): + new = { + "name": "uusi testi2", + "question": json.dumps({}) + } + response = self.client.put(f"/api/questions/{self.questions[0].id}/", new, format="json") + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + self.assertEqual(TemplateQuestion.objects.count(), 2) + + # Authenticate + self.client.force_authenticate(user=self.authClient) + response = self.client.put(f"/api/questions/{self.questions[0].id}/", new, format="json") + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(TemplateQuestion.objects.count(), 2) + self.assertEqual( + TemplateQuestion.objects.get(id=self.questions[0].id).name, + "uusi testi2" + ) + + def test_delete(self): + response = self.client.delete(f"/api/questions/{self.questions[0].id}/", format="json") + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + self.assertEqual(TemplateQuestion.objects.count(), 2) + + # Authenticate + self.client.force_authenticate(user=self.authClient) + response = self.client.delete(f"/api/questions/{self.questions[0].id}/", format="json") + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertEqual(TemplateQuestion.objects.count(), 1) diff --git a/webapp/views.py b/webapp/views.py index 5824512..4f3f055 100644 --- a/webapp/views.py +++ b/webapp/views.py @@ -5,7 +5,7 @@ from django.utils import timezone from dealer.git import git from django.conf import settings from django.contrib.auth import authenticate -from django.http import HttpResponse +from django.http import HttpResponseBadRequest from django.shortcuts import redirect, render from django.views.decorators.http import require_http_methods from django_filters import rest_framework as filters @@ -36,6 +36,7 @@ class RootView(routers.APIRootView): class EventViewSet(viewsets.ModelViewSet): queryset = Event.objects.all() + ordering = ["start_time"] serializer_class = EventSerializer permission_classes = [IsAuthenticatedOrReadOnly] filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter) @@ -43,11 +44,13 @@ class EventViewSet(viewsets.ModelViewSet): search_fields = '__all__' def get_queryset(self): + if self.request.user.is_authenticated: + return Event.objects.all() + since = self.request.query_params.get('since', None) if since: return Event.objects.filter(visible=True, end_time__gt=since).order_by('start_time') - - return Event.objects.filter(visible=True).order_by('start_time') + return Event.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time') class SignupFormViewSet(viewsets.ModelViewSet): @@ -60,6 +63,8 @@ class SignupFormViewSet(viewsets.ModelViewSet): # search_fields = '__all__' def get_queryset(self): + if self.request.user.is_authenticated: + return SignupForm.objects.all().order_by('start_time') return SignupForm.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time') @@ -71,8 +76,18 @@ class SignupViewSet(viewsets.ModelViewSet): # filter_fields = '__all__' # search_fields = '__all__' - # def get_queryset(self): - # return Signup.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time') + def create(self, request, *args, **kwargs): + try: + form = SignupForm.objects.get(id=request.data["signupForm_id"]) + if (form.visible): + return super().create(request, *args, **kwargs) + except: + return HttpResponseBadRequest() + else: + return HttpResponseBadRequest() + + def update(self, request, *args, **kwargs): + return super().update(request, *args, **kwargs) class SavedQuestionsViewSet(viewsets.ModelViewSet): @@ -90,7 +105,10 @@ class FeedViewSet(viewsets.ModelViewSet): search_fields = '__all__' def get_queryset(self): - objs = Feed.objects.filter(visible=True).order_by('publish_time') + if self.request.user.is_authenticated: + return Feed.objects.all().order_by('publish_time') + else: + objs = Feed.objects.filter(visible=True).order_by('publish_time') result_ids = [] for obj in objs: @@ -127,14 +145,6 @@ class TagsViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [IsAuthenticatedOrReadOnly] -# -- OLD CODEBASE -- # - -@require_http_methods(["GET"]) -def main_index(request, *args, **kwargs): - """Render main page.""" - return render(request, "index.html", {}) - - @require_http_methods(["GET"]) def about_view(request, *args, **kwargs): """Render about page.""" @@ -146,8 +156,8 @@ def about_view(request, *args, **kwargs): latest_commit = repo.git("rev-parse HEAD").decode('utf-8') latest_date = repo.git("show -s --format=%ci " + latest_commit).decode('utf-8') latest_tag = repo.git("describe --tags " + repo.git("rev-list --tags --max-count=1").decode('utf-8')).decode('utf-8') - except Exception: - pass + except Exception as e: + print(f"Git failed:\n{e}") context = { 'commit': latest_commit, @@ -157,54 +167,6 @@ def about_view(request, *args, **kwargs): return render(request, "about.html", context) -@require_http_methods(["GET"]) -def guild_view(request, *args, **kwargs): - """Render "Guild" page.""" - return render(request, "guild.html", {}) - - -@require_http_methods(["GET"]) -def freshmen_view(request, *args, **kwargs): - """Render "Freshmen" page.""" - return render(request, "freshmen.html", {}) - - -@require_http_methods(["GET"]) -def jobs_view(request, *args, **kwargs): - """Render "Jobs" page.""" - return render(request, "jobs.html", {}) - - -@require_http_methods(["GET"]) -def event_calendar_view(request, *args, **kwargs): - """Render "Event calendar" page.""" - return render(request, "event_calendar.html", {}) - - -@require_http_methods(["GET"]) -def international_view(request, *args, **kwargs): - """Render "International" page.""" - return render(request, "international.html", {}) - - -@require_http_methods(["GET"]) -def sosso_view(request, *args, **kwargs): - """Render "Sössö" page.""" - return render(request, "sosso.html", {}) - - -@require_http_methods(["GET"]) -def contact_view(request, *args, **kwargs): - """Render "Contact" page.""" - committees = Committee.objects.order_by('name') - - context = { - "committees": committees - } - - return render(request, "contact.html", context) - - @require_http_methods(["GET"]) def nginx_jwt_resp(request, *args, **kwargs): cookie = request.COOKIES.get("jwt", None)