from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.options import Options from selenium.common.exceptions import NoSuchElementException from selenium import webdriver from django.test import LiveServerTestCase import requests from statistics import mean import mock import pandas as pd import base64 import datetime as dt import json import os import random import re import tempfile import time import itertools from django.test import override_settings from datetime import datetime from io import StringIO, BytesIO from time import sleep import mock import pandas as pd import pytz from administration.models import VerificationReport, VerificationSetting from administration.utils import id_generator from authentication.models import User from bs4 import BeautifulSoup from digipus.settings import TIME_ZONE from django.conf import settings from django.contrib import messages as dj_messages from django.contrib.auth import get_user_model from django.core import mail, serializers from django.core.exceptions import PermissionDenied, ValidationError from django.core.files.uploadedfile import SimpleUploadedFile, InMemoryUploadedFile from django.core.files import File from django.core.management import call_command from django.db.utils import IntegrityError from pytz import timezone, UTC from django.test import (Client, RequestFactory, TestCase, TransactionTestCase, override_settings) from django.urls import resolve, reverse from django.utils import timezone from app.forms import SuntingProfilForm, year_choices, GuestBookForm from app.utils.fileManagementUtil import (get_random_filename, remove_image_exifdata) from app.utils.PasswordValidator import PasswordPolicyValidator from app.views import UploadMateriHTML, add_rating_materi from .models import (Category, Comment, DislikeComment, DownloadStatistics, Like, LikeComment, Materi, Rating, RatingContributor, ReadLater, ReqMaterial, Review, ViewStatistics, GuestBook, AdminNotification, NotifikasiKontributor) from .services import DetailMateriService from .views import (DaftarKatalog, DashboardKontributorView, DetailMateri, KatalogPerKontributorView, MateriFavorite, PasswordChangeViews, PostsView, ProfilView, ReqMateriView, RevisiMateriView, SuksesLoginAdminView, LaporanMateri, SuksesLoginKontributorView, SuntingProfilView, UploadMateriExcelView, UploadMateriView, password_success) ERROR_403_MESSAGE = "Kamu harus login untuk mengakses halaman ini" class DaftarKatalogTest(TestCase): def test_daftar_katalog_url_exist(self): url = "/" response = Client().get(f"{url}") self.assertEqual(response.status_code, 200) def test_daftar_katalog_using_daftar_katalog_template(self): response = Client().get("/") self.assertTemplateUsed(response, "app/katalog_materi.html") def test_daftar_katalog_using_daftar_katalog_func(self): found = resolve("/") self.assertEqual(found.func.__name__, DaftarKatalog.as_view().__name__) def test_fields(self): materi = Materi() materi.title = "tes" materi.cover = "https://cache.umusic.com/_sites/billieeilish/v2/images/pic-red.jpg" materi.author = "input" materi.save() resp = Materi.objects.get(id=materi.id) self.assertEqual(resp, materi) class DaftarKatalogSortingByJumlahUnduhTest(TestCase): def setUp(self): self.client = Client() self.contributor_credential = { "email": "kontributor@gov.id", "password": "passwordtest" } self.contributor_credential_2 = { "email": "kontributor2@gov.id", "password": "passwordtest" } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor 1", is_contributor=True) self.contributor2 = get_user_model().objects.create_user( **self.contributor_credential_2, name="Kontributor 2", is_contributor=True) self.cover = SimpleUploadedFile( "Cherprang_Areekul40_nJM9dGt.jpg", b"Test file") self.content = SimpleUploadedFile("Bahan_PA_RKK.pdf", b"Test file") Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content).save() time.sleep(1) Materi(title="Materi 2", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 2", status="APPROVE", cover=self.cover, content=self.content).save() self.last_uploaded_material = Materi.objects.last() material_unduh_url = f"/materi/{self.last_uploaded_material.id}/unduh" self.client.get(material_unduh_url) def test_sorting_by_jumlah_unduh(self): response = self.client.get("/?sort=jumlah_unduh") self.assertRegex(str(response.content), rf'.*Materi 2.*Materi 1.*') class DaftarKatalogSortingByJumlahTampilanTest(TestCase): def setUp(self): self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True ) self.client = Client() content = b"Test file" self.cover = SimpleUploadedFile( "cover.jpg", content ) self.content = SimpleUploadedFile( "content.txt", content ) Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="PENDING", cover=self.cover, content=self.content).save() Materi(title="Materi 2", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="PENDING", cover=self.cover, content=self.content).save() self.materi2 = Materi.objects.last() self.url = f"/materi/{self.materi2.id}/view" def sorting_by_jumlah_tampilan(self): self.client.get(self.url) response = self.client.get("/?sort=jumlah_tampilan") self.assertRegex(str(response.content), rf'.*Materi 2.*Materi 1.*') class DaftarKatalogSortingByTerhangatTest(TestCase): @classmethod def generate_view_materi(cls, materi, view_count): for _ in itertools.repeat(None, view_count): ViewStatistics.objects.create(materi=materi) def get_displayed_materi_in_number(self): response = self.client.get("/?sort=terhangat") lst = [int(id) for id in re.findall(r"Materi\s(\d+)[^\d]", response.content.decode())] return lst def setUp(self): self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.contributor = get_user_model().objects.create_user( name="Kontributor", is_contributor=True, **self.contributor_credential, ) self.client = Client() content = b"Test file" self.cover = SimpleUploadedFile( "cover.jpg", content ) self.content = SimpleUploadedFile( "content.txt", content ) self.materi_data = { "author": "Reyhan", "uploader": self.contributor, "publisher": "Publisher", "descriptions": "Deskripsi Materi", "status": "APPROVE", "cover": self.cover, "content": self.content, } def test_1_week_difference_give_1_hot_score_difference(self): materi1 = Materi.objects.create( title='Materi 1', date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC), **self.materi_data ) materi2 = Materi.objects.create( title='Materi 2', date_created=datetime(2020, 10, 8, 7, 0, 0, tzinfo=UTC), **self.materi_data ) materi3 = Materi.objects.create( title='Materi 3', date_created=datetime(2020, 10, 15, 7, 0, 0, tzinfo=UTC), **self.materi_data ) self.generate_view_materi(materi1, 1) self.generate_view_materi(materi2, 1) self.generate_view_materi(materi3, 1) self.assertAlmostEqual(materi3.hot_score - materi2.hot_score, 1) self.assertAlmostEqual(materi2.hot_score - materi1.hot_score, 1) def test_10_exponential_view_count_difference_give_1_hot_score_difference(self): materi1 = Materi.objects.create( title='Materi 1', date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC), **self.materi_data ) materi2 = Materi.objects.create( title='Materi 2', date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC), **self.materi_data ) materi3 = Materi.objects.create( title='Materi 3', date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC), **self.materi_data ) self.generate_view_materi(materi1, 1) self.generate_view_materi(materi2, 10) self.generate_view_materi(materi3, 100) self.assertAlmostEqual(materi3.hot_score - materi2.hot_score, 1) self.assertAlmostEqual(materi2.hot_score - materi1.hot_score, 1) def test_0_and_1_views_has_the_same_hot_score(self): materi1 = Materi.objects.create( title='Materi 1', date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC), **self.materi_data ) materi2 = Materi.objects.create( title='Materi 2', date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC), **self.materi_data ) self.generate_view_materi(materi1, 0) self.generate_view_materi(materi2, 1) self.assertAlmostEqual(materi1.hot_score, materi2.hot_score) def test_page_has_option_sort_by_hottest(self): response = self.client.get("/") self.assertIn("terhangat", response.content.decode()) def test_page_display_sort_by_hottest(self): materi1 = Materi.objects.create( title='Materi 1', date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC), **self.materi_data ) materi2 = Materi.objects.create( title='Materi 2', date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC), **self.materi_data ) materi3 = Materi.objects.create( title='Materi 3', date_created=datetime(2020, 10, 8, 7, 0, 0, tzinfo=UTC), **self.materi_data ) materi4 = Materi.objects.create( title='Materi 4', date_created=datetime(2020, 10, 9, 7, 0, 0, tzinfo=UTC), **self.materi_data ) self.generate_view_materi(materi1, 11) self.generate_view_materi(materi2, 10) self.generate_view_materi(materi3, 1) self.generate_view_materi(materi4, 1) lst = self.get_displayed_materi_in_number() self.assertEqual(lst, [4, 1, 3, 2]) def test_prefer_newest_materi_if_hot_score_is_same(self): materi1 = Materi.objects.create( title='Materi 1', date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC), **self.materi_data ) materi2 = Materi.objects.create( title='Materi 2', date_created=datetime(2020, 10, 8, 7, 0, 0, tzinfo=UTC), **self.materi_data ) self.generate_view_materi(materi1, 10) self.generate_view_materi(materi2, 1) lst = self.get_displayed_materi_in_number() self.assertEqual(lst, [2, 1]) class DaftarKatalogSortingByJumlahKomentarTest(TestCase): def setUp(self): self.client = Client() self.contributor_credential = { "email": "kontributor@gov.id", "password": "passwordtest" } self.contributor_credential_2 = { "email": "kontributor2@gov.id", "password": "passwordtest" } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor 1", is_contributor=True) self.contributor2 = get_user_model().objects.create_user( **self.contributor_credential_2, name="Kontributor 2", is_contributor=True) self.cover = SimpleUploadedFile( "Cherprang_Areekul40_nJM9dGt.jpg", b"Test file") self.content = SimpleUploadedFile("Bahan_PA_RKK.pdf", b"Test file") Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content).save() time.sleep(1) Materi(title="Materi 2", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 2", status="APPROVE", cover=self.cover, content=self.content).save() self.last_uploaded_material = Materi.objects.last() url = f"/materi/{self.last_uploaded_material.id}/" self.client.login(**self.contributor_credential_2) self.client.post( url, {"comment": "This is new comment by Kontributor 2"}) def test_sorting_by_jumlah_komentar(self): response = self.client.get("/?sort=jumlah_komentar") self.assertRegex(str(response.content), rf'.*Materi 2.*Materi 1.*') class DaftarKatalogPerKontributorTest(TestCase): def setUp(self): self.client = Client() self.contributor_credential = { "email": "kontributor@gov.id", "password": "passwordtest" } self.contributor_credential_2 = { "email": "kontributor2@gov.id", "password": "passwordtest" } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor 1", is_contributor=True) self.contributor2 = get_user_model().objects.create_user( **self.contributor_credential_2, name="Kontributor 2", is_contributor=True) self.cover = SimpleUploadedFile( "Cherprang_Areekul40_nJM9dGt.jpg", b"Test file") self.content = SimpleUploadedFile("Bahan_PA_RKK.pdf", b"Test file") Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content).save() Materi(title="Materi 2", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 2", status="APPROVE", cover=self.cover, content=self.content).save() Materi(title="Materi 3", author="Agas", uploader=self.contributor2, publisher="Kelas SC", descriptions="Deskripsi Materi 3", status="APPROVE", cover=self.cover, content=self.content).save() self.url = f"/profil/{self.contributor.email}/" def test_katalog_per_kontributor_url_exist(self): response = self.client.get(self.url) self.assertEqual(response.status_code, 200) def test_katalog_per_kontributor_using_katalog_kontri_template(self): response = self.client.get(self.url) self.assertTemplateUsed(response, "app/katalog_kontri.html") def test_katalog_per_kontributor_using_katalog_per_kontributor_func(self): found = resolve(self.url) self.assertEqual(found.func.__name__, KatalogPerKontributorView.as_view().__name__) # def test_katalog_per_kontributor_show_daftar_materi_kontributor(self): # response = self.client.get(self.url) # list_materi = Materi.objects.filter(uploader=self.contributor) # data = response.context_data["materi_list"] # self.assertEqual(len(list_materi), len(data)) def test_count_materi_per_contributor(self): response = self.client.get(self.url) list_materi = Materi.objects.filter(uploader=self.contributor) jumlah = response.context_data["materi_list"] self.assertEqual(len(list_materi), len(jumlah)) class DetailMateriTest(TestCase): def _get_materi_info_html(self, info_name, info_value): info_html = '
' info_html += f'
{info_name}
' + '
' info_html += f'

{info_value}

' + \ '
' return info_html def check_materi_info_in_html(self, info_name, info_value, html_content): expected_content = self._get_materi_info_html(info_name, info_value) self.assertIn(expected_content, re.sub(">\s*<", "><", html_content)) def check_materi_info_not_in_html(self, info_name, info_value, html_content): expected_content = self._get_materi_info_html(info_name, info_value) self.assertNotIn(expected_content, re.sub(">\s*<", "><", html_content)) def setUp(self): self.client = Client() self.admin_credential = { "email": "admin@gov.id", "password": "passwordtest" } self.contributor_credential = { "email": "kontributor@gov.id", "password": "passwordtest" } self.anonymous_credential = { "email": "anonymous@gov.id", "password": "passwordtest" } self.admin = get_user_model().objects.create_user( **self.admin_credential, name="Admin", is_admin=True) self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True) self.anonymous = get_user_model().objects.create_user( **self.anonymous_credential, name="Anonymous" ) self.cover = SimpleUploadedFile( "ExampleCover921.jpg", b"Test file") self.content = SimpleUploadedFile("ExampleFile921.pdf", b"Test file") self.materi1 = Materi.objects.create(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content) self.materi2 = Materi.objects.create(title="Materi 2", author="Agad", uploader=self.contributor, publisher="Kelas SM", descriptions="Deskripsi Materi 2", status="APPROVE", cover=self.cover, content=self.content) self.url = "/materi/" + str(self.materi1.id) + "/" self.download_url1 = self.url + "unduh" self.url2 = "/materi/" + str(self.materi2.id) + "/" self.download_url2 = self.url2 + "unduh" self.like_url = '/materi/like/' self.dcount_info_name = "Jumlah Download" self.lcount_info_name = "Jumlah Like" self.materi_with_published_date = Materi.objects.create(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content, date_modified=timezone.now(), date_created=timezone.now()) self.materi_with_published_date_url = "/materi/" + \ str(self.materi_with_published_date.id) + "/" VerificationReport.objects.create(report='{"feedback": "Something", "kriteria": [{"title": "Kriteria 1", "status": true},' + ' {"title": "Kriteria 2", "status": true}, {"title": "Kriteria 3", "status": true}]}', timestamp="2020-10-09 06:21:33", status="Diterima", materi=self.materi_with_published_date, user=self.materi_with_published_date.uploader) def test_detail_materi_url_exist(self): response = Client().get(self.url) self.assertEqual(response.status_code, 200) self.assertNotEqual(response.status_code, 404) def test_detail_materi_using_detail_materi_template(self): response = Client().get(self.url) self.assertTemplateUsed(response, "app/detail_materi.html") def test_detail_materi_using_detail_materi_func(self): found = resolve(self.url) self.assertEqual(found.func.__name__, DetailMateri.as_view().__name__) def test_category_models_can_create_new_object(self): test = Category.objects.create( id="1", name="medis", description="kategori medis") count = Category.objects.all().count() self.assertEqual(1, count) self.assertNotEqual(0, count) self.assertEqual(test.__str__(), "medis") self.assertNotEqual(test.__str__(), "saul") def test_comment_models_can_create_new_object(self): test = Comment.objects.create( username="saul", profile="121212", comment="232323") count = Comment.objects.all().count() self.assertEqual(1, count) self.assertNotEqual(0, count) self.assertEqual(test.__str__(), "saul") self.assertNotEqual(test.__str__(), "userlain") def test_post_blank_comment(self): url = self.url self.client.login(**self.anonymous_credential) response = self.client.post(url, {"comment": ""}) self.assertIn("error_message", response.context) self.assertIn("Anda belum menuliskan komentar", response.context["error_message"]) def test_post_blank_report(self): url = self.url self.client.login(**self.anonymous_credential) response = self.client.post(url, {"report": ""}) self.assertIn("error_message", response.context) self.assertIn("Anda belum menuliskan komentar", response.context["error_message"]) def test_comment_rendered_to_template(self): url = self.url self.client.login(**self.contributor_credential) self.client.post(url, {"comment": "This is my new comment"}) response = Client().get(url) self.assertContains(response, "This is my new comment") def test_report_rendered_to_template(self): url = self.url self.client.login(**self.contributor_credential) self.client.post(url, {"report": "This is my new comment"}) response = Client().get(url) self.assertEqual(response.status_code, 200) def test_comment_by_admin(self): url = self.url self.client.login(**self.admin_credential) self.client.post(url, {"comment": "This is new comment by Admin"}) response = self.client.get(url) self.assertContains(response, "Admin") def test_comment_by_kontributor(self): url = self.url self.client.login(**self.contributor_credential) self.client.post( url, {"comment": "This is new comment by Contributor"}) response = self.client.get(url) self.assertContains(response, "Kontributor") def test_comment_by_anonymous(self): url = self.url self.client.get("/logout/") self.client.login(**self.anonymous_credential) self.client.post(url, {"comment": "This is new comment by Anonymous"}) response = self.client.get(url) self.assertContains(response, "Anonymous") def test_comment_disliked_by_anonymous(self): url_materi = self.url self.client.get("/logout/") self.client.login(**self.anonymous_credential) self.client.post( url_materi, {"comment": "This is new comment by Anonymous"}) comment = Comment.objects.get( comment="This is new comment by Anonymous").id response = self.client.get(url_materi) session_id = response.context["session_id"] payload = {"comment": comment, "session_id": session_id} self.client.post("/comment/dislike/", payload) num_of_comment_dislikes = DislikeComment.objects.filter( comment=comment).count() self.assertEqual(num_of_comment_dislikes, 0) def test_comment_liked_by_anonymous(self): url_materi = self.url self.client.get("/logout/") self.client.login(**self.anonymous_credential) self.client.post( url_materi, {"comment": "This is new comment by Anonymous"}) comment = Comment.objects.get( comment="This is new comment by Anonymous").id response = self.client.get(url_materi) session_id = response.context["session_id"] payload = {"comment": comment, "session_id": session_id} self.client.post("/comment/like/", payload) num_of_comment_likes = LikeComment.objects.filter( comment=comment).count() self.assertEqual(num_of_comment_likes, 0) def test_comment_undisliked_by_anonymous(self): url_materi = self.url self.client.get("/logout/") self.client.login(**self.anonymous_credential) self.client.post( url_materi, {"comment": "This is new comment by Anonymous"}) comment = Comment.objects.get( comment="This is new comment by Anonymous") response = self.client.get(url_materi) session_id = response.context["session_id"] payload = {"comment": comment, "session_id": session_id} self.client.post("/comment/dislike/", payload) self.client.post("/comment/dislike/", payload) num_of_comment_dislikes = DislikeComment.objects.filter( comment=comment, session_id=session_id).count() self.assertEqual(num_of_comment_dislikes, 0) def test_comment_unliked_by_anonymous(self): url_materi = self.url self.client.get("/logout/") self.client.login(**self.anonymous_credential) self.client.post( url_materi, {"comment": "This is new comment by Anonymous"}) comment = Comment.objects.get( comment="This is new comment by Anonymous") response = self.client.get(url_materi) session_id = response.context["session_id"] payload = {"comment": comment, "session_id": session_id} self.client.post("/comment/like/", payload) self.client.post("/comment/like/", payload) num_of_comment_likes = LikeComment.objects.filter( comment=comment, session_id=session_id).count() self.assertEqual(num_of_comment_likes, 0) def test_comment_new_does_not_have_dislike(self): url_materi = self.url self.client.get("/logout/") self.client.login(**self.anonymous_credential) response = self.client.get(url_materi) session_id = response.context["session_id"] self.client.post( url_materi, {"comment": "This is new comment by Anonymous"}) comment = Comment.objects.get( comment="This is new comment by Anonymous") comment_dislike_counter = DislikeComment.objects.filter( comment=comment, session_id=session_id).count() self.assertEqual(comment_dislike_counter, 0) def test_comment_new_does_not_have_like(self): url_materi = self.url self.client.get("/logout/") self.client.login(**self.anonymous_credential) response = self.client.get(url_materi) session_id = response.context["session_id"] self.client.post( url_materi, {"comment": "This is new comment by Anonymous"}) comment = Comment.objects.get( comment="This is new comment by Anonymous") comment_like_counter = LikeComment.objects.filter( comment=comment, session_id=session_id).count() self.assertEqual(comment_like_counter, 0) def test_comment_sends_email_to_contributor_that_subscribes(self): contributor_subscribed = get_user_model().objects.create_user( email="contributor_subscribing@gov.id", password="passwordtest", name="Kontributor-subscribed", is_contributor=True, is_subscribing_to_material_comments=True ) material = Materi.objects.create(title="Materi-subscribed", author="Tester", uploader=contributor_subscribed, publisher="Kelas PMPL", descriptions="Deskripsi Materi subscribed", status="APPROVE", cover=self.cover, content=self.content) url = "/materi/" + str(material.id) + "/" # comment with other user self.client.login(**self.contributor_credential) prev_outbox_count = len(mail.outbox) comment_content = "Test comment should send email" self.client.post( url, {"comment": comment_content}) current_outbox_count = len(mail.outbox) # Comment notification email sent self.assertEqual(current_outbox_count, prev_outbox_count + 1) def test_comment_doesnt_send_email_to_contributor_that_not_subscribes(self): contributor_not_subscribed = get_user_model().objects.create_user( email="contributor_not_subscribing@gov.id", password="passwordtest", name="Kontributor-not-subscribed", is_contributor=True, is_subscribing_to_material_comments=False ) material = Materi.objects.create(title="Materi-not-subscribed", author="Tester", uploader=contributor_not_subscribed, publisher="Kelas PMPL", descriptions="Deskripsi Materi non-subscribed", status="APPROVE", cover=self.cover, content=self.content) url = "/materi/" + str(material.id) + "/" # comment with other user self.client.login(**self.contributor_credential) prev_outbox_count = len(mail.outbox) comment_content = "Test comment should not send email" self.client.post( url, {"comment": comment_content}) current_outbox_count = len(mail.outbox) # Comment notification email not sent self.assertEqual(current_outbox_count, prev_outbox_count) def test_comment_doesnt_send_email_to_contributor_that_self_commenting(self): contributor_subscribed_credentials = { "email": "contributor_subscribing@gov.id", "password": "passwordtest" } contributor_subscribed = get_user_model().objects.create_user( **contributor_subscribed_credentials, name="Kontributor-subscribed", is_contributor=True, is_subscribing_to_material_comments=True ) material = Materi.objects.create(title="Materi-subscribed", author="Tester", uploader=contributor_subscribed, publisher="Kelas PMPL", descriptions="Deskripsi Materi subscribed", status="APPROVE", cover=self.cover, content=self.content) url = "/materi/" + str(material.id) + "/" # comment with the same user self.client.login(**contributor_subscribed_credentials) prev_outbox_count = len(mail.outbox) comment_content = "Test comment should not send email for self-comments" self.client.post( url, {"comment": comment_content}) current_outbox_count = len(mail.outbox) # Comment notification email not sent self.assertEqual(current_outbox_count, prev_outbox_count) def test_detail_materi_contains_comment_count(self): url = self.url self.client.login(**self.contributor_credential) response = self.client.get(url) self.assertContains(response, "Komentar (0)") self.client.post( url, {"comment": "This is new comment by Contributor"}) self.client.post( url, {"comment": "This is new comment by Contributor"}) response = self.client.get(url) self.assertContains(response, "Komentar (2)") def test_detail_materi_contains_form_comment(self): self.client.login(**self.contributor_credential) response = self.client.get(self.url) self.assertContains(response, "Beri komentar...") def test_detail_materi_not_contains_form_comment(self): response = self.client.get(self.url) self.assertNotContains(response, "Beri komentar...") self.assertContains( response, "Login terlebih dahulu untuk berkomentar") def create_and_delete_comment(self, is_admin=False, is_contributor=False): url = self.url self.client.login(**self.admin_credential) self.client.post(url, {"comment": "This is new comment by Anonymous"}) delete_url = "/delete/" + str(self.materi1.id) + "/" + str( Comment.objects.get(comment="This is new comment by Anonymous").id) if is_admin: self.client.login(**self.admin_credential) if is_contributor: self.client.login(**self.contributor_credential) if not is_admin and not is_contributor: self.client.login(**self.anonymous_credential) response = self.client.get(delete_url) return response def test_delete_comments_by_admin(self): self.create_and_delete_comment(is_admin=True) count = Comment.objects.all().filter( comment="This is new comment by Anonymous").count() self.assertEqual(count, 0) def test_delete_comments_by_contributor(self): response = self.create_and_delete_comment(is_contributor=True) self.assertRaises(PermissionDenied) self.assertEqual(response.status_code, 403) count = Comment.objects.all().filter( comment="This is new comment by Anonymous").count() self.assertEqual(count, 1) def test_delete_comments_by_anonymous(self): response = self.create_and_delete_comment() self.assertRaises(PermissionDenied) self.assertEqual(response.status_code, 403) count = Comment.objects.all().filter( comment="This is new comment by Anonymous").count() self.assertEqual(count, 1) def test_review_models_can_create_new_object(self): test = Review.objects.create( username="saul", profile="121212", review="232323") count = Review.objects.all().count() self.assertEqual(1, count) self.assertNotEqual(0, count) self.assertEqual(test.__str__(), "saul") self.assertNotEqual(test.__str__(), "userlain") def test_post_blank_review(self): url = self.url self.client.login(**self.anonymous_credential) response = self.client.post(url, {"review": ""}) self.assertIn("error_message", response.context) self.assertIn("Anda belum menuliskan komentar", response.context["error_message"]) def test_review_rendered_to_template(self): url = self.url self.client.login(**self.contributor_credential) self.client.post(url, {"review": "This is my new review"}) response = Client().get(url) self.assertContains(response, "This is my new review") def test_review_by_admin(self): url = self.url self.client.login(**self.admin_credential) self.client.post(url, {"review": "This is new review by Admin"}) response = self.client.get(url) self.assertContains(response, "Admin") def test_review_by_kontributor(self): url = self.url self.client.login(**self.contributor_credential) self.client.post( url, {"review": "This is new review by Contributor"}) response = self.client.get(url) self.assertContains(response, "Kontributor") def test_review_by_anonymous(self): url = self.url self.client.get("/logout/") self.client.login(**self.anonymous_credential) self.client.post(url, {"review": "This is new review by Anonymous"}) response = self.client.get(url) self.assertContains(response, "Anonymous") def create_and_delete_review(self, is_admin=False, is_contributor=False): url = self.url self.client.login(**self.admin_credential) self.client.post(url, {"review": "A review by Anonymous"}) delete_url = "/review/delete/" + str(self.materi1.id) + "/" + str( Review.objects.get(review="A review by Anonymous").id) if is_admin: self.client.login(**self.admin_credential) if is_contributor: self.client.login(**self.contributor_credential) if not is_admin and not is_contributor: self.client.login(**self.anonymous_credential) response = self.client.get(delete_url) return response def test_delete_review_by_admin(self): self.create_and_delete_review(is_admin=True) count = Review.objects.all().filter(review="A review by Anonymous").count() self.assertEqual(count, 0) def test_delete_review_by_contributor(self): response = self.create_and_delete_review(is_contributor=True) self.assertRaises(PermissionDenied) self.assertEqual(response.status_code, 403) count = Review.objects.all().filter(review="A review by Anonymous").count() self.assertEqual(count, 1) def test_delete_review_by_regular_user(self): response = self.create_and_delete_review() self.assertRaises(PermissionDenied) self.assertEqual(response.status_code, 403) count = Review.objects.all().filter(review="A review by Anonymous").count() self.assertEqual(count, 1) def test_detail_materi_contains_review_count(self): url = self.url self.client.login(**self.contributor_credential) review = "This is new review by Contributor" response = self.client.get(url) self.assertContains(response, "Review (0)") self.client.post( url, {"review": review}) self.client.post( url, {"review": review}) response = self.client.get(url) self.assertContains(response, "Review (2)") def test_detail_materi_contains_form_review(self): self.client.login(**self.contributor_credential) response = self.client.get(self.url) self.assertContains(response, "Beri Review") def test_detail_materi_not_contains_form_review(self): response = self.client.get(self.url) self.assertNotContains(response, "Beri Review") self.assertContains( response, "Login terlebih dahulu untuk Membuat review") def test_tombol_citasiAPA(self): response = self.client.get(self.url) self.assertContains(response, "Citate APA") def test_hasil_citasi_APA_materi_has_no_published_date(self): response = self.client.get(self.url) expected = self.materi1.author + \ " . (n.d) . " + self.materi1.title + " . " + self.materi1.publisher self.assertIn(expected, response.context["citationAPA"]) self.assertIn(expected, response.context["citationAPA"]) def test_hasil_citasi_APA_materi_has_published_date(self): response = self.client.get(self.materi_with_published_date_url) published_date = self.materi_with_published_date.published_date.strftime( "%Y-%m-%d %H:%M") expected = ( self.materi_with_published_date.author + " . (" + published_date + ") . " + self.materi_with_published_date.title + " . " + self.materi_with_published_date.publisher ) self.assertIn(expected, response.context["citationAPA"]) def test_citation_IEEE_button(self): response = self.client.get(self.url) self.assertContains(response, "Citate IEEE") def test_citation_IEEE_materi_has_no_published_date(self): response = self.client.get(self.url) current_date = timezone.now() current_day = str(current_date.day) current_month = current_date.strftime("%b") current_year = str(current_date.year) expected = ( "Agas, " + "Materi 1. " + "Kelas SC, n.d. " + "Accessed on: " + current_month + ". " + current_day + ", " + current_year + ". [Online]. " + "Available: http://testserver" + self.url ) self.assertIn(expected, response.context["citationIEEE"]) def test_citation_IEEE_materi_has_published_date(self): response = self.client.get(self.materi_with_published_date_url) current_date = timezone.now() current_day = str(current_date.day) current_month = current_date.strftime("%b") current_year = str(current_date.year) published_date = self.materi_with_published_date.published_date.strftime( '%Y') expected = "Agas, " + \ "Materi 1. " + \ "Kelas SC, " + published_date + ". " +\ "Accessed on: " + current_month + ". " + current_day + ", " + current_year + \ ". [Online]. " + \ "Available: http://testserver" + self.materi_with_published_date_url self.assertIn(expected, response.context["citationIEEE"]) def test_tombol_bagikan_google_drive(self): response = Client().get(self.url) self.assertContains(response, 'Google Drive') @mock.patch("app.services.GoogleDriveUploadService.upload_to_gdrive") def test_save_to_gdrive_with_nonexistent_materi(self, mock_upload_to_gdrive): response = self.client.get('/materi/%s/save-to-gdrive/' % 0) mock_upload_to_gdrive.assert_not_called() self.assertEqual(response.status_code, 404) @mock.patch("app.services.GoogleDriveUploadService.upload_to_gdrive") def test_save_to_gdrive_with_valid_materi(self, mock_upload_to_gdrive): response = self.client.get( '/materi/%s/save-to-gdrive/' % self.materi1.id, follow=True) last_url, status_code = response.redirect_chain[-1] mock_upload_to_gdrive.assert_called_once() self.assertEqual(last_url, '/materi/%d/' % self.materi1.id) self.assertEqual(status_code, 302) def test_download_count_is_in_init_context(self): context = {} DetailMateriService.init_materi_download_count(context, self.materi1) self.assertIn('materi_download_count', context.keys()) def test_download_count_is_integer(self): context = {} DetailMateriService.init_materi_download_count(context, self.materi1) self.assertEqual(type(context['materi_download_count']), int) def test_download_count_when_no_download(self): context = {} DetailMateriService.init_materi_download_count(context, self.materi1) self.assertEqual(context['materi_download_count'], 0) def test_download_count_when_single_download(self): self.client.get(self.download_url1) context = {} DetailMateriService.init_materi_download_count(context, self.materi1) self.assertEqual(context['materi_download_count'], 1) def test_download_count_when_multiple_download(self): self.client.get(self.download_url1) self.client.get(self.download_url1) self.client.get(self.download_url1) context = {} DetailMateriService.init_materi_download_count(context, self.materi1) self.assertEqual(context['materi_download_count'], 3) def test_different_material_has_different_download_count(self): self.client.get(self.download_url1) self.client.get(self.download_url1) self.client.get(self.download_url1) self.client.get(self.download_url2) self.client.get(self.download_url2) context1 = {} context2 = {} DetailMateriService.init_materi_download_count(context1, self.materi1) DetailMateriService.init_materi_download_count(context2, self.materi2) self.assertNotEqual( context1['materi_download_count'], context2['materi_download_count']) self.assertEqual(context1['materi_download_count'], 3) self.assertEqual(context2['materi_download_count'], 2) def test_download_count_displayed_on_template_when_no_download(self): response = self.client.get(self.url) html = response.content.decode("utf-8") self.check_materi_info_in_html(self.dcount_info_name, 0, html) def test_download_count_displayed_on_template_when_single_download(self): self.client.get(self.download_url1) response = self.client.get(self.url) html = response.content.decode("utf-8") self.check_materi_info_in_html(self.dcount_info_name, 1, html) def test_download_count_displayed_on_template_when_multiple_download(self): self.client.get(self.download_url1) self.client.get(self.download_url1) self.client.get(self.download_url1) self.client.get(self.download_url1) response = self.client.get(self.url) html = response.content.decode("utf-8") self.check_materi_info_in_html(self.dcount_info_name, 4, html) def test_different_material_has_different_download_count_on_templates(self): self.client.get(self.download_url1) self.client.get(self.download_url1) self.client.get(self.download_url2) self.client.get(self.download_url2) self.client.get(self.download_url2) self.client.get(self.download_url2) response = self.client.get(self.url) response2 = self.client.get(self.url2) html = response.content.decode("utf-8") html2 = response2.content.decode("utf-8") dcount_materi1 = self.materi1.unduh.all().count() dcount_materi2 = self.materi2.unduh.all().count() self.check_materi_info_in_html( self.dcount_info_name, dcount_materi1, html) self.check_materi_info_not_in_html( self.dcount_info_name, dcount_materi2, html) self.check_materi_info_in_html( self.dcount_info_name, dcount_materi2, html2) self.check_materi_info_not_in_html( self.dcount_info_name, dcount_materi1, html2) def test_like_count_displayed_on_template_when_no_like(self): response = self.client.get(self.url) html = response.content.decode("utf-8") self.check_materi_info_in_html(self.lcount_info_name, 0, html) def test_like_count_displayed_on_template_when_single_like(self): payload = { 'materi_id': self.materi1.id, 'session_id': "dummysession" } self.client.post(self.like_url, payload) response = self.client.get(self.url) html = response.content.decode("utf-8") self.check_materi_info_in_html(self.lcount_info_name, 1, html) def test_like_count_displayed_on_template_when_multiple_like(self): payload1 = { 'materi_id': self.materi1.id, 'session_id': "dummysession1" } payload2 = { 'materi_id': self.materi1.id, 'session_id': "dummysession2" } self.client.post(self.like_url, payload1) self.client.post(self.like_url, payload2) response = self.client.get(self.url) html = response.content.decode("utf-8") self.check_materi_info_in_html(self.lcount_info_name, 2, html) def test_like_count_displayed_on_template_when_unlike(self): payload = { 'materi_id': self.materi1.id, 'session_id': "dummysession" } # Like materi once self.client.post(self.like_url, payload) response = self.client.get(self.url) html = response.content.decode("utf-8") self.check_materi_info_in_html(self.lcount_info_name, 1, html) # Like it again, resulting in unlike self.client.post(self.like_url, payload) response = self.client.get(self.url) html = response.content.decode("utf-8") self.check_materi_info_in_html(self.lcount_info_name, 0, html) class PostsViewTest(TestCase): @classmethod def generate_posts_data(cls, user): POST_COUNT = 3 COMMENTS_COUNT_PER_POST = [1, 0, 3] LIKES_COUNT_PER_POST = [5, 4, 2] assert POST_COUNT == len(COMMENTS_COUNT_PER_POST) sample_file = SimpleUploadedFile("Test.jpg", b"Test file") sample_category = Category.objects.create(name="Test Category") post_comment_group_dict = {} for i in range(POST_COUNT): post = Materi.objects.create( uploader=user, cover=sample_file, content=sample_file, ) post.categories.add(sample_category) post_comment_group_dict[post.id] = { "data": post, "comments": [], } for j in range(LIKES_COUNT_PER_POST[i]): Like.objects.create( timestamp=timezone.now(), materi=post, session_id=("dummysession-" + str(i) + '-' + str(j)) ) time.sleep(0.1) for i, post_id in enumerate(post_comment_group_dict): post = post_comment_group_dict[post_id]["data"] for _ in range(COMMENTS_COUNT_PER_POST[i]): comment = Comment.objects.create(materi=post) post_comment_group_dict[post_id]["comments"].append(comment) # order by latest (-timestamp) post_comment_group_dict[post_id]["comments"].reverse() return post_comment_group_dict @classmethod def setUpTestData(cls): cls.url = '/posts/' cls.user_credentials = { "email": "user@email.com", "password": "justpass" } cls.user = User.objects.create_user( **cls.user_credentials, is_contributor=True) cls.data = cls.generate_posts_data(cls.user) def _request_as_user(self): self.client.login(**self.user_credentials) return self.client.get(self.url) def test_url_resolves_to_posts_view(self): found = resolve(self.url) self.assertEqual(found.func.__name__, PostsView.as_view().__name__) def test_returns_200_on_authenticated_access(self): response = self._request_as_user() self.assertEqual(response.status_code, 200) def test_returns_403_on_unauthenticated_access(self): response = self.client.get(self.url) self.assertRaises(PermissionDenied) self.assertEqual(response.status_code, 403) html = response.content.decode("utf-8") self.assertIn(ERROR_403_MESSAGE, html) def test_returns_correct_template(self): response = self._request_as_user() self.assertTemplateUsed(response, "user_uploaded_posts.html") def test_success_returns_correct_comment_post_groupings_by_context(self): post_comment_group_dict = self.data response = self._request_as_user() response_user = response.context_data["user"] self.assertEqual(response_user, self.user) response_data = response.context_data["posts"] actual_data = post_comment_group_dict self.assertDictEqual(response_data, actual_data) def test_html_contains_grouped_posts_and_comments(self): response = self._request_as_user() posts = list(self.data.keys()) comments = { i: [comment.id for comment in self.data[post_id]["comments"]] for i, post_id in enumerate(posts) } self.assertRegex( str(response.content), rf'.*(
)' + rf'.*(
)' + rf'.*(
)' + rf'.*(
)' + rf'.*(
)' + rf'.*(
)' + rf'.*(
)' ) def test_like_count_written_correctly_on_template(self): response = self._request_as_user() for _, post_id in enumerate(self.data): post = self.data[post_id]["data"] self.assertContains( response, '' + str(post.like_count) + '', ) class TemplateLoaderTest(TestCase): def test_template_loader_url_exist(self): url = "/test-page.html" response = Client().get(url) self.assertEqual(response.status_code, 200) def test_template_loader_using_template_loader_template(self): url = "/test-page.html" response = Client().get(url) expected_template_name = "test-page.html" self.assertTemplateUsed(response, expected_template_name) def test_template_loader_using_template_loader_func(self): url = "/test-page.html" found = resolve(url) expected_view_name = "pages" self.assertEqual(found.func.__name__, expected_view_name) def test_template_loader_handle_non_existent_html(self): url = "/test.html" expected_template_name = "error-404.html" response = Client().get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, expected_template_name) class UploadPageTest(TestCase): def setUp(self): self.client = Client() self.user = User.objects._create_user(email="kontributor@gov.id", password="kontributor", is_contributor=True) self.admin = User.objects.create_admin(email="admin@gov.id", password="admin") def test_upload_page_using_login_func(self): found = resolve("/unggah/") self.assertEqual(found.func.__name__, UploadMateriView.as_view().__name__) def test_upload_page_url_is_exist(self): # Positive test self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.get("/unggah/") self.assertEqual(response.status_code, 200) # Negative tests self.client.login(email="kontributor@gov.id", password="kontributor") response = Client().get("/fake/") self.assertEqual(response.status_code, 404) def test_upload_page_url_admin_doesnt_exist(self): self.client.login(email="admin@gov.id", password="admin") response = self.client.get("/unggah/") self.assertEqual(response.status_code, 403) def test_upload_page_url_admin_cant_upload(self): self.client.login(email="admin@gov.id", password="admin") response = self.client.post("/unggah/") self.assertEqual(response.status_code, 403) def test_upload_page_template(self): url = "/unggah/" self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.get(url) expected_template_name = "unggah.html" self.assertTemplateUsed(response, expected_template_name) def test_upload_page_title(self): self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.get("/unggah/") # Positive tests self.assertContains(response, "Unggah Materi") # Negative tests self.assertNotContains(response, "Anything") def test_upload_page_form_field(self): self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.get("/unggah/") # Positive tests self.assertContains(response, "title") # Negative tests self.assertNotContains(response, "anything") class UploadExcelPageTest(TestCase): def setUp(self): self.client = Client() self.user = User.objects._create_user(email="kontributor@gov.id", password="kontributor", is_contributor=True) def test_upload_excel_page_using_login_func(self): found = resolve("/unggah_excel/") self.assertEqual(found.func.__name__, UploadMateriExcelView.as_view().__name__) def test_uplaod_excel_page_url_is_exist(self): # Positive test self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.get("/unggah_excel/") self.assertEqual(response.status_code, 200) # Negative tests self.client.login(email="kontributor@gov.id", password="kontributor") response = Client().get("/fake/") self.assertEqual(response.status_code, 404) def test_upload_excel_page_template(self): url = "/unggah_excel/" self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.get(url) expected_template_name = "unggah_excel.html" self.assertTemplateUsed(response, expected_template_name) def test_upload_excel_page_title(self): self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.get("/unggah_excel/") # Positive tests self.assertContains(response, "Unggah Materi dari Excel") # Negative tests self.assertNotContains(response, "Anything") def test_upload_excel_page_form_field(self): self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.get("/unggah_excel/") # Positive tests self.assertContains(response, "File (*.xlsx)") # Negative tests self.assertNotContains(response, "anything") def create_dummy_excel(self, field_lengths={}, categories=[]): title1 = "Hands-On Machine Learning with Scikit-Learn and TensorFlow: Concepts, Tools, and Techniques to Build Intelligent Systems" author1 = "Aurelien Geron, Aurelien Geron, Aurelien Geron" publisher1 = "O'Reilly Media, O'Reilly Media, O'Reilly Media" categories1 = "Machine Learning,Deep Learning,Computer Science" description1 = "A series of Deep Learning breakthroughs have boosted the whole field of machine learning over the last decade. Now that machine learning is thriving, even programmers who know close to nothing about this technology can use simple, efficient tools to implement programs capable of learning from data. This practical book shows you how." if 'title' in field_lengths: title1 = title1[:field_lengths['title']] if 'author' in field_lengths: author1 = author1[:field_lengths['author']] if 'publisher' in field_lengths: publisher1 = publisher1[:field_lengths['publisher']] if len(categories) > 0: categories1 = ','.join(categories) data_frame = pd.DataFrame({ 'Title': [title1], 'Author': [author1], 'Publisher': [publisher1], 'Categories': [categories1], 'Description': [description1], }) file_path = os.path.join(settings.MEDIA_ROOT, 'dummy.xlsx') # pylint: disable=abstract-class-instantiated writer = pd.ExcelWriter( file_path, engine='xlsxwriter') data_frame.to_excel(writer, index=0) writer.save() return file_path, data_frame def test_upload_excel_upload_file_title_error(self): self.client.login(email="kontributor@gov.id", password="kontributor") field_lengths = { 'author': 30, 'publisher': 30, } file_name, data_frame = self.create_dummy_excel( field_lengths=field_lengths) with open(file_name, 'rb') as fp: response = self.client.post("/unggah_excel/", {'excel': fp}) messages = list(dj_messages.get_messages(response.wsgi_request)) msg_text = messages[0].message self.assertIn('Title', msg_text) def test_upload_excel_upload_file_author_error(self): self.client.login(email="kontributor@gov.id", password="kontributor") field_lengths = { 'title': 50, 'publisher': 30, } file_name, data_frame = self.create_dummy_excel( field_lengths=field_lengths) with open(file_name, 'rb') as fp: response = self.client.post("/unggah_excel/", {'excel': fp}) messages = list(dj_messages.get_messages(response.wsgi_request)) msg_text = messages[0].message self.assertIn('Author', msg_text) def test_upload_excel_upload_file_publisher_error(self): self.client.login(email="kontributor@gov.id", password="kontributor") field_lengths = { 'title': 50, 'author': 30, } file_name, data_frame = self.create_dummy_excel( field_lengths=field_lengths) with open(file_name, 'rb') as fp: response = self.client.post("/unggah_excel/", {'excel': fp}) messages = list(dj_messages.get_messages(response.wsgi_request)) msg_text = messages[0].message self.assertIn('Publisher', msg_text) def test_upload_excel_upload_file_categories_error(self): self.client.login(email="kontributor@gov.id", password="kontributor") field_lengths = { 'title': 50, 'author': 30, 'publisher': 30, } file_name, data_frame = self.create_dummy_excel( field_lengths=field_lengths) with open(file_name, 'rb') as fp: response = self.client.post("/unggah_excel/", {'excel': fp}) messages = list(dj_messages.get_messages(response.wsgi_request)) msg_text = messages[0].message self.assertIn('Kategori', msg_text) def test_upload_excel_upload_file_success(self): self.client.login(email="kontributor@gov.id", password="kontributor") Category(name='Computer Science').save() Category(name='Machine Learning').save() Category(name='Deep Learning').save() field_lengths = { 'title': 50, 'author': 30, 'publisher': 30, } categories = ['Computer Science', 'Machine Learning', 'Deep Learning'] file_name, data_frame = self.create_dummy_excel( field_lengths=field_lengths, categories=categories) with open(file_name, 'rb') as fp: self.client.post("/unggah_excel/", {'excel': fp}) title = data_frame['Title'][0] materi = Materi.objects.get(title=title) default_path = 'book-cover-placeholder.png' self.assertTrue(materi) self.assertEquals(materi.cover.name, default_path) self.assertTrue(os.path.exists( os.path.join(settings.MEDIA_ROOT, default_path))) def test_upload_excel_download_template(self): self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.get("/unggah_excel/?template=1") self.assertEquals( response['Content-Type'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') self.assertEquals(response['Content-Disposition'], 'attachment; filename=template.xlsx') class DashboardKontributorViewTest(TestCase): def setUp(self): self.client = Client() self.kontributor = User.objects.create_contributor(email="kontributor@gov.id", password="kontributor") self.admin = User.objects.create_admin(email="admin@gov.id", password="admin") self.url = "/dashboard/" self.view = DashboardKontributorView self.template_name = "dashboard.html" def test_dashboard_kontributor_view(self): found = resolve(self.url) self.assertEqual(found.func.__name__, self.view.as_view().__name__) def test_dashboard_kontributor_template(self): # Login self.client.login(email="kontributor@gov.id", password="kontributor") # Test response = self.client.get(self.url) self.assertTemplateUsed(response, self.template_name) # Logout self.client.logout() def test_dashboard_kontributor_url(self): # Login self.client.login(email="kontributor@gov.id", password="kontributor") # Test response = self.client.get(self.url) self.assertEqual(response.status_code, 200) # Logout self.client.logout() def test_dashboard_kontributor_access(self): # Kontributor # Login self.client.login(email="kontributor@gov.id", password="kontributor") # Test response = self.client.get(self.url) self.assertEqual(response.status_code, 200) # Logout self.client.logout() # Admin # Login self.client.login(email="admin@gov.id", password="admin") # Test response = self.client.get(self.url) self.assertEqual(response.status_code, 403) html = response.content.decode("utf-8") self.assertIn(ERROR_403_MESSAGE, html) # Logout self.client.logout() # Anonim # Test response = self.client.get(self.url) self.assertEqual(response.status_code, 403) html = response.content.decode("utf-8") self.assertIn(ERROR_403_MESSAGE, html) class DeleteMateriTest(TestCase): def setUp(self): self.client = Client() self.admin_credential = { "email": "admin@gov.id", "password": id_generator() } self.superuser_credential = { "email": "superuser@gov.id", "password": id_generator() } self.contributor_credential = { "email": "contributor@gov.id", "password": id_generator() } self.admin = get_user_model().objects.create_user( **self.admin_credential, name="Admin", is_admin=True) self.superuser = get_user_model().objects.create_user( **self.superuser_credential, name="Superuser", is_admin=True, is_superuser=True) self.content = SimpleUploadedFile( "content.txt", b"Test") self.cover = SimpleUploadedFile( "flower.jpg", b"Test file") self.contributor = User.objects.create_contributor( **self.contributor_credential) Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content).save() self.materi1 = Materi.objects.first() self.url = "/materi/" + str(self.materi1.id) + "/delete" def test_url_delete_materi_is_success_as_contributor(self): self.client.login(**self.contributor_credential) response = self.client.get(self.url) self.assertEqual(response.status_code, 302) def test_url_soft_delete_materi_is_success_as_admin(self): self.client.login(**self.admin_credential) response = self.client.get(self.url) self.assertEqual(response.status_code, 302) self.materi1.refresh_from_db() self.assertNotEqual(self.materi1.deleted_at, None) def test_url_soft_delete_materi_is_success_as_superuser(self): self.client.login(**self.superuser_credential) response = self.client.get(self.url) self.assertEqual(response.status_code, 302) self.materi1.refresh_from_db() self.assertNotEqual(self.materi1.deleted_at, None) class ProfilViewTest(TestCase): @classmethod def setUpTestData(cls): cls.client = Client() cls.url = "/profil/" cls.template_name = "profil.html" cls.view = ProfilView cls.contributor_credentials = { "email": "contributor@gov.id", "password": "justpass"} cls.contributor = User.objects.create_contributor( **cls.contributor_credentials) cls.admin_credentials = { "email": "admin@gov.id", "password": "justpass"} cls.admin = User.objects.create_admin(**cls.admin_credentials) def test_returns_correct_profile_view(self): found = resolve(self.url) self.assertEqual(found.func.__name__, self.view.as_view().__name__) def _request_as_user(self, credentials): self.client = Client() self.client.login(**credentials) return self.client.get(self.url) def test_returns_correct_template(self): response = self._request_as_user(self.contributor_credentials) self.assertTemplateUsed(response, self.template_name) def test_unauthenticated_access_blocked(self): response = self._request_as_user({}) self.assertEqual(response.status_code, 403) def test_authorized_access_success(self): response = self._request_as_user(self.contributor_credentials) self.assertEqual(response.status_code, 200) self.assertIn("Profil Kontributor", response.content.decode()) response = self._request_as_user(self.admin_credentials) self.assertEqual(response.status_code, 200) self.assertIn("Profil Admin", response.content.decode()) class SuntingProfilViewTest(TestCase): @classmethod def setUpTestData(cls): cls.client = Client() cls.url = "/sunting/" cls.template_name = "sunting.html" cls.view = SuntingProfilView cls.contributor_credentials = { "email": "contributor@gov.id", "password": "justpass"} cls.contributor = User.objects.create_contributor( **cls.contributor_credentials) cls.admin_credentials = { "email": "admin@gov.id", "password": "justpass"} cls.admin = User.objects.create_admin(**cls.admin_credentials) def test_sunting_profile_view(self): found = resolve(self.url) self.assertEqual(found.func.__name__, self.view.as_view().__name__) def _request_as_user(self, credentials): self.client = Client() self.client.login(**credentials) return self.client.get(self.url) def test_returns_correct_template(self): self.client.login(**self.contributor_credentials) response = self.client.get(self.url) self.assertTemplateUsed(response, self.template_name) def test_unauthenticated_access_blocked(self): response = self._request_as_user({}) self.assertEqual(response.status_code, 403) def test_authorized_access_success(self): response = self._request_as_user(self.contributor_credentials) self.assertEqual(response.status_code, 200) self.assertIn("Sunting Profil Kontributor", response.content.decode()) response = self._request_as_user(self.admin_credentials) self.assertEqual(response.status_code, 200) self.assertIn("Sunting Profil Admin", response.content.decode()) def test_sunting_profile_autofocus(self): form_data = { "email": "kontributor@gov.id", "name": "kontributor", "instansi": "instansi", "nik": "nik", "alamat": "alamat", "nomor_telpon": "123456789", "twitter": "Twit", "instagram": "https://instagram.com/test_ig" } form = SuntingProfilForm(data=form_data) self.assertEqual( form.fields["twitter"].widget.attrs.get("autofocus"), "") self.assertEqual( form.fields["instagram"].widget.attrs.get("autofocus"), None) class SuksesLoginKontributorTest(TestCase): def setUp(self): self.client = Client() self.kontributor = User.objects.create_contributor(email="kontributor@gov.id", password="kontributor") self.admin = User.objects.create_admin(email="admin@gov.id", password="admin") self.url = "/sukses-kontributor/" self.view = SuksesLoginKontributorView self.template_name = "sukses_kontri.html" def test_sukses_login_kontributor_view(self): found = resolve(self.url) self.assertEqual(found.func.__name__, self.view.as_view().__name__) def test_sukses_login_kontributor_template(self): # Login self.client.login(email="kontributor@gov.id", password="kontributor") # Test response = self.client.get(self.url) self.assertTemplateUsed(response, self.template_name) # Logout self.client.logout() def test_sukses_login_kontributor_url_access(self): # Login self.client.login(email="kontributor@gov.id", password="kontributor") # Test response = self.client.get(self.url) self.assertEqual(response.status_code, 200) # Logout self.client.logout() class SuksesLoginAdminTest(TestCase): def setUp(self): self.client = Client() self.kontributor = User.objects.create_contributor(email="kontributor@gov.id", password="kontributor") self.admin = User.objects.create_admin(email="admin@gov.id", password="admin") self.url = "/sukses-admin/" self.view = SuksesLoginAdminView self.template_name = "sukses_admin.html" def test_sukses_login_admin_view(self): found = resolve(self.url) self.assertEqual(found.func.__name__, self.view.as_view().__name__) def test_sukses_login_admin_template(self): # Login self.client.login(email="admin@gov.id", password="admin") # Test response = self.client.get(self.url) self.assertTemplateUsed(response, self.template_name) # Logout self.client.logout() def test_sukses_login_admin_url_access(self): # Login self.client.login(email="admin@gov.id", password="admin") # Test response = self.client.get(self.url) self.assertEqual(response.status_code, 200) # Logout self.client.logout() class LikeMateriTest(TestCase): def setUp(self): self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True ) self.client = Client() self.url_like = '/materi/like/' content = b"Test file" self.cover = SimpleUploadedFile( "cover.jpg", content ) self.content = SimpleUploadedFile( "content.txt", content ) Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="PENDING", cover=self.cover, content=self.content).save() self.materi1 = Materi.objects.first() self.url_materi = f'/materi/{self.materi1.id}/' def test_get_method(self): response = self.client.get(self.url_like) response = json.loads(response.content) self.assertEqual(response.get("success", None), False) def test_like_materi(self): # Verify that materi doesn't have any like to start with num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 0) # Like a materi response = self.client.get(self.url_materi) session_id = response.context["session_id"] materi_id = response.context["materi_data"].id payload = { 'materi_id': materi_id, 'session_id': session_id } Client().post(self.url_like, payload) num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 1) def test_unlike_materi(self): # Verify that materi doesn't have any like to start with num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 0) # Like a materi response = self.client.get(self.url_materi) session_id = response.context["session_id"] materi_id = response.context["materi_data"].id payload = { 'materi_id': materi_id, 'session_id': session_id } Client().post(self.url_like, payload) num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 1) # Unlike a materi response = self.client.get(self.url_materi) session_id = response.context["session_id"] materi_id = response.context["materi_data"].id payload = { 'materi_id': materi_id, 'session_id': session_id } Client().post(self.url_like, payload) num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 0) def test_2_client_like_materi(self): # Verify that materi doesn't have any like to start with num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 0) # Client 1 like a materi response = self.client.get(self.url_materi) session_id = response.context["session_id"] materi_id = response.context["materi_data"].id payload = { 'materi_id': materi_id, 'session_id': session_id } Client().post(self.url_like, payload) num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 1) # Client 2 like a materi response = Client().get(self.url_materi) session_id = response.context["session_id"] materi_id = response.context["materi_data"].id payload = { 'materi_id': materi_id, 'session_id': session_id } Client().post(self.url_like, payload) num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 2) def test_incomplete_like_parameter(self): # Verify that materi doesn't have any like to start with num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 0) # missing session id response = self.client.get(self.url_materi) materi_id = response.context["materi_data"].id payload = { 'materi_id': materi_id, } ajax_response = Client().post(self.url_like, payload) ajax_response = json.loads(ajax_response.content) num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 0) self.assertEqual(ajax_response.get("success", None), False) # missing materi id response = self.client.get(self.url_materi) session_id = response.context["session_id"] payload = { 'session_id': session_id } ajax_response = Client().post(self.url_like, payload) ajax_response = json.loads(ajax_response.content) num_of_likes = Like.objects.filter(materi=self.materi1).count() self.assertEqual(num_of_likes, 0) self.assertEqual(ajax_response.get("success", None), False) class ViewMateriStatissticsTest(TestCase): def setUp(self): self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True ) self.client = Client() content = b"Test file" self.cover = SimpleUploadedFile( "cover.jpg", content ) self.content = SimpleUploadedFile( "content.txt", content ) Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="PENDING", cover=self.cover, content=self.content).save() self.materi1 = Materi.objects.first() self.url = f"/materi/{self.materi1.id}/view" # Test single view def test_count_one_materi_view(self): self.client.get(self.url) num_of_views = self.materi1.baca.all().count() self.assertEqual(num_of_views, 1) # Test more than one view def test_count_more_than_one_materi_view(self): self.client.get(self.url) num_of_views = self.materi1.baca.all().count() self.assertEqual(num_of_views, 1) Client().get(self.url) num_of_views = self.materi1.baca.all().count() self.assertEqual(num_of_views, 2) class DownloadMateriStatissticsTest(TestCase): def setUp(self): self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True ) self.client = Client() content = b"Test file" self.cover = SimpleUploadedFile( "cover.jpg", content ) self.content = SimpleUploadedFile( "content.txt", content ) Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="PENDING", cover=self.cover, content=self.content).save() self.materi1 = Materi.objects.first() self.url = f"/materi/{self.materi1.id}/unduh" # Test single download def test_count_one_materi_download(self): self.client.get(self.url) num_of_downloads = self.materi1.unduh.all().count() self.assertEqual(num_of_downloads, 1) # Test more than one download def test_count_more_than_one_materi_download(self): self.client.get(self.url) num_of_downloads = self.materi1.unduh.all().count() self.assertEqual(num_of_downloads, 1) Client().get(self.url) num_of_downloads = self.materi1.unduh.all().count() self.assertEqual(num_of_downloads, 2) class RevisiMateriTest(TestCase): def setUp(self): self.client = Client() self.view = RevisiMateriView self.template_name = "revisi.html" self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True ) self.cover = SimpleUploadedFile( "cover.jpg", b"Test file" ) self.content = SimpleUploadedFile( "content.txt", b"Test file" ) Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="REVISION", cover=self.cover, content=self.content).save() self.materi1 = Materi.objects.first() self.url = "/revisi/materi/" + str(self.materi1.id) + "/" def test_revisi_materi_view(self): found = resolve(self.url) self.assertEqual(found.func.__name__, self.view.as_view().__name__) def test_revisi_materi_template(self): # Login self.client.login(**self.contributor_credential) # Test response = self.client.get(self.url) self.assertTemplateUsed(response, self.template_name) # Logout self.client.logout() def test_revisi_materi_url_access(self): # Login self.client.login(**self.contributor_credential) # Test response = self.client.get(self.url) self.assertEqual(response.status_code, 200) # Logout self.client.logout() class GenerateDummyCommandTest(TestCase): def setUp(self): self.material_numbers = [5, 10, 25, 100] self.invalid_material_numbers = [-100, -10, -1, 0, 1, 2, 3, 4] self.stdout = StringIO() def test_command_output_with_given_num_of_materi(self): for num_of_materi in self.material_numbers: call_command("generatedummy", num_of_materi, stdout=self.stdout) self.assertIn( f"Successfully created {num_of_materi} materi", self.stdout.getvalue() ) def test_command_should_generate_materi_objects(self): for num_of_materi in self.material_numbers: call_command("generatedummy", num_of_materi, stdout=self.stdout) self.assertEqual(Materi.objects.count(), num_of_materi) Materi.objects.all().delete() def test_command_should_raise_exception_if_invalid_values_are_given(self): with self.assertRaises(IndexError): for num_of_materi in self.invalid_material_numbers: call_command("generatedummy", num_of_materi) class RemoveDummyCommandTest(TestCase): def test_calling_remove_dummy_command_should_remove_generated_dummy_objects(self): stdout = StringIO() call_command("generatedummy", 50) call_command("removedummy", stdout=stdout) self.assertIn("Successfully remove all dummy object", stdout.getvalue()) self.assertEqual(User.objects.count(), 0) self.assertEqual(Category.objects.count(), 0) self.assertEqual(Materi.objects.count(), 0) self.assertEqual(VerificationSetting.objects.count(), 0) self.assertEqual(VerificationReport.objects.count(), 0) class RatingMateriTest(TestCase): def setUp(self): self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.user_one_credential = { "email": "user_one@user.id", "password": id_generator() } self.user_two_credential = { "email": "user_two@user.id", "password": id_generator() } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True ) self.user_one = get_user_model().objects.create_user( **self.user_one_credential, name="User One") self.user_two = get_user_model().objects.create_user( **self.user_two_credential, name="User Two") self.cover = SimpleUploadedFile( "cover.jpg", b"Test file" ) self.content = SimpleUploadedFile( "content.txt", b"Test file" ) Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="PENDING", cover=self.cover, content=self.content).save() Materi(title="Materi Dua", author="Author", uploader=self.contributor, publisher="Publisher", descriptions="Deskripsi Materi Dua", status="APPROVE", cover=self.cover, content=self.content).save() self.materi1 = Materi.objects.filter(title='Materi 1').get() self.materi2 = Materi.objects.filter(title='Materi Dua').get() self.url_rate = '/materi/rate/' self.url_materi = '/materi/{}/'.format(self.materi1.id) def test_rating_model_can_be_created_with_proper_parameter(self): Rating(materi=self.materi1, user=self.user_one, score=5).save() rating = Rating.objects.first() self.assertEqual(rating.materi, self.materi1) self.assertEqual(rating.user, self.user_one) self.assertTrue(0 < rating.score < 6) self.assertEqual(rating.__str__(), "Material:Materi 1 | User:User One | Rating:5") def test_rating_model_should_not_be_created_with_rating_more_than_5(self): with self.assertRaises(ValidationError) as context: Rating(materi=self.materi1, user=self.user_one, score=6).save() self.assertTrue( 'Rating score must be integer between 1-5' in str(context.exception)) def test_rating_model_should_not_be_created_with_rating_less_than_1(self): with self.assertRaises(ValidationError) as context: Rating(materi=self.materi1, user=self.user_one, score=0).save() self.assertTrue( 'Rating score must be integer between 1-5' in str(context.exception)) def test_one_materi_should_be_able_to_be_related_to_multiple_rating(self): Rating(materi=self.materi1, user=self.user_one, score=1).save() Rating(materi=self.materi1, user=self.user_two, score=2).save() rating_one = Rating.objects.get(user=self.user_one) rating_two = Rating.objects.get(user=self.user_two) self.assertEqual(rating_one.materi, self.materi1) self.assertEqual(rating_two.materi, self.materi1) self.assertEqual(rating_one.user, self.user_one) self.assertEqual(rating_two.user, self.user_two) def test_one_user_should_be_able_to_be_related_to_two_rating(self): Rating(materi=self.materi1, user=self.user_one, score=3).save() Rating(materi=self.materi2, user=self.user_one, score=3).save() rating_one = Rating.objects.filter(materi=self.materi1).first() rating_two = Rating.objects.filter(materi=self.materi2).first() self.assertEqual(rating_one.materi, self.materi1) self.assertEqual(rating_two.materi, self.materi2) self.assertEqual(rating_one.user, self.user_one) self.assertEqual(rating_two.user, self.user_one) def test_two_rating_should_not_have_same_user_and_materi(self): with self.assertRaises(IntegrityError) as context: Rating(materi=self.materi1, user=self.user_one, score=1).save() Rating(materi=self.materi1, user=self.user_one, score=2).save() self.assertTrue('already exists' in str(context.exception)) def test_materi_in_rating_should_not_be_null(self): with self.assertRaises(IntegrityError): Rating(user=self.user_one, score=1).save() def test_user_in_rating_should_not_be_null(self): with self.assertRaises(IntegrityError): Rating(materi=self.materi1, score=1).save() def test_score_in_rating_should_not_be_null(self): with self.assertRaises(TypeError): Rating(materi=self.materi1, user=self.user_one).save() def test_rating_materi_url_use_add_rating_materi_function(self): found = resolve(self.url_rate) self.assertEqual(found.func, add_rating_materi) def test_rating_materi_get_method_should_return_403_forbidden(self): response = self.client.get(self.url_rate) response_json = json.loads(response.content) self.assertEqual(response_json.get("success", None), False) self.assertEqual(response_json.get("msg", None), "Forbidden") self.assertEqual(response.status_code, 403) def test_rating_materi_post_not_authenticated_should_return_403_forbidden(self): response = self.client.post( self.url_rate, {'materi_id': 1, 'rating_score': 5}) response_json = json.loads(response.content) self.assertEqual(response_json.get("success", None), False) self.assertEqual(response_json.get("msg", None), "Forbidden") self.assertEqual(response.status_code, 403) def test_rating_materi_not_authenticated_post_wrong_param_should_return_403_forbidden(self): for data in [{}, {'materi_id': 1}, {'rating_score': 1}, {'rating_score': 'STRING', 'materi_id': 'STRING'}]: response = self.client.post(self.url_rate, data) response_json = json.loads(response.content) self.assertEqual(response_json.get("success", None), False) self.assertEqual(response_json.get("msg", None), "Forbidden") self.assertEqual(response.status_code, 403) def test_rating_materi_authenticated_post_missing_param(self): self.client.login(**self.user_one_credential) for data in [{'rating_score': 1}, {'materi_id': 1}, {}]: response = self.client.post(self.url_rate, data) response_json = json.loads(response.content) self.assertEqual(response_json.get("success", None), False) self.assertEqual(response_json.get("msg", None), "Missing param") self.assertEqual(response.status_code, 422) def test_rating_materi_authenticated_materi_id_doesnt_exist_should_return_422(self): self.client.login(**self.user_one_credential) response = self.client.post( self.url_rate, {'materi_id': 123456, 'rating_score': 5}) response_json = json.loads(response.content) self.assertEqual(response_json.get("success", None), False) self.assertEqual(response_json.get( "msg", None), "Materi does not exist") self.assertEqual(response.status_code, 422) def test_rating_materi_authenticated_param_wrong_data_type_should_return_422(self): self.client.login(**self.user_one_credential) response = self.client.post( self.url_rate, {'materi_id': "STRING", 'rating_score': 5}) response_json = json.loads(response.content) self.assertEqual(response_json.get("success", None), False) self.assertEqual(response_json.get("msg", None), "materi_id must be an integer") self.assertEqual(response.status_code, 422) response = self.client.post( self.url_rate, {'materi_id': 1, 'rating_score': "STRING"}) response_json = json.loads(response.content) self.assertEqual(response_json.get("success", None), False) self.assertEqual(response_json.get("msg", None), "rating_score must be an integer") self.assertEqual(response.status_code, 422) def test_rating_score_should_be_between_1_and_5(self): self.client.login(**self.user_one_credential) for i in range(1, 6): Rating.objects.all().delete() response = self.client.post( self.url_rate, {'materi_id': self.materi1.id, 'rating_score': i}) response_json = json.loads(response.content) # self.assertEqual(response_json.get("success", None), True) self.assertEqual(response_json.get("msg", None), "Rating successfully created") self.assertEqual(response.status_code, 201) for i in [-100, -7, -6, -1, 0, 6, 7, 100]: Rating.objects.all().delete() response = self.client.post( self.url_rate, {'materi_id': self.materi1.id, 'rating_score': i}) response_json = json.loads(response.content) # self.assertEqual(response_json.get("success", None), False) self.assertEqual(response_json.get("msg", None), "Rating must be an integer from 1 to 5") self.assertEqual(response.status_code, 422) def test_user_should_not_able_to_rate_materi_twice(self): self.client.login(**self.user_one_credential) Rating.objects.all().delete() self.client.post( self.url_rate, {'materi_id': self.materi1.id, 'rating_score': 1}) response = self.client.post( self.url_rate, {'materi_id': self.materi1.id, 'rating_score': 2}) response_json = json.loads(response.content) # self.assertEqual(response_json.get("success", None), False) self.assertEqual(response_json.get( "msg", None), "Rating already exist") self.assertEqual(response.status_code, 409) def test_user_authenticated_visit_unrated_should_get_0_materi_rating_score_context(self): self.client.login(**self.user_one_credential) response = self.client.get(self.url_materi) self.assertEqual(0, response.context.get('materi_rating_score')) def test_user_not_authenticated_visit_unrated_should_get_0_materi_rating_score_context(self): response = self.client.get(self.url_materi) self.assertEqual(0, response.context.get('materi_rating_score')) def test_user_authenticated_visit_rated_should_get_correct_materi_rating_score_context(self): self.client.login(**self.user_one_credential) Rating(materi=self.materi1, user=self.user_one, score=1).save() response = self.client.get(self.url_materi) self.assertEqual(1, response.context.get('materi_rating_score')) class FileManagementUtilTest(TestCase): def setUp(self): self.filename = "image_with_exif_data.gif" self.file_content = open(settings.BASE_DIR + "/app/test_files/" + self.filename, "rb").read() def test_get_random_filename_isCorrect(self): generated_name = get_random_filename(self.filename) self.assertTrue(generated_name != self.filename) # 40 from 36 expected name length + 4 from extension self.assertEqual(len(generated_name), 40) self.assertTrue(generated_name[-4:] == ".gif") def test_remove_image_exifdata_isCorrect(self): with tempfile.TemporaryDirectory() as d: image_with_exif_data_path = os.path.join(d, self.filename) img = open(image_with_exif_data_path, "wb") img.write(self.file_content) img.close() remove_image_exifdata(image_with_exif_data_path) sanitized_img = open(image_with_exif_data_path, "rb").read() self.assertTrue(len(sanitized_img) < len(self.file_content)) self.assertTrue(b'")[0] + "" soup = BeautifulSoup(table_html, 'html.parser') histories_html = soup.find('tbody').find_all('tr') prev_timestamp = None for riwayat_html in histories_html: materi_data = riwayat_html.find_all("td") date_format = "%d %B %Y %H:%M:%S" materi_timestamp = datetime.strptime( materi_data[2].get_text(), date_format) if prev_timestamp: self.assertTrue(prev_timestamp > materi_timestamp) prev_timestamp = materi_timestamp def test_no_history_display_message(self): no_history_msg = "Anda belum mengunduh materi. Silahkan unduh materi yang anda butuhkan" response = self.client.get(self.history_url) resp_html = response.content.decode('utf8') self.assertIn(no_history_msg, resp_html) class MateriModelTest(TestCase): def setUp(self): self.contributor = User.objects.create( email="kontributor@gov.id", password="passwordtest", name="kontributor", is_contributor=True ) self.cover = SimpleUploadedFile( "ExampleCover221.jpg", b"Test file") self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file") self.materi = Materi.objects.create(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content, date_modified=timezone.now(), date_created=timezone.now()) def test_like_count_return_zero_when_there_is_no_like(self): self.assertEqual(0, self.materi.like_count) def test_like_count_return_right_value_when_there_is_like(self): Like.objects.create(timestamp=timezone.now(), materi=self.materi, session_id="dummysessionid1") self.assertEqual(1, self.materi.like_count) Like.objects.create(timestamp=timezone.now(), materi=self.materi, session_id="dummysessionid2") self.assertEqual(2, self.materi.like_count) class MateriFavoriteTest(TestCase): @classmethod def setUpTestData(cls): cls.url = '/favorite/' cls.user_credentials = { "email": "user@email.com", "password": "justpass" } cls.user = User.objects.create_user( **cls.user_credentials, is_contributor=True) def _request_as_user(self): self.client.login(**self.user_credentials) return self.client.get(self.url) def test_url_resolves_to_favorite_view(self): found = resolve(self.url) self.assertEqual(found.func.__name__, MateriFavorite.as_view().__name__) class RandomizedMateriTest(TestCase): def setUp(self): self.contributor = User.objects.create( email="kontributor@gov.id", password="passwordtest", name="kontributor", is_contributor=True ) self.cover = SimpleUploadedFile("ExampleCover221.jpg", b"Test file") self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file") self.materi = Materi.objects.create( title="Materi 1", author="Nandhika", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content, date_modified=timezone.now(), date_created=timezone.now(), ) self.materi = Materi.objects.create( title="Materi 2", author="Prayoga", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 2", status="APPROVE", cover=self.cover, content=self.content, date_modified=timezone.now(), date_created=timezone.now(), ) def test_randomized_materi_returns_200(self): response = Client().get("/?random=1") self.assertEqual(response.status_code, 200) def test_randomized_materi_remains_same_materi(self): response = Client().get("/?random=1") self.assertIn("Materi 1", response.content.decode()) self.assertIn("Materi 2", response.content.decode()) class YearChoicesTest(TestCase): def test_release_year_contains_the_right_current_year(self): now = dt.date.today().year choices = year_choices() self.assertEqual((now, now), choices[-1]) def test_min_release_year_is_2000(self): choices = year_choices() self.assertEqual((2000, 2000), choices[0]) TEST_IMAGE = ''' iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI WXMAAABIAAAASABGyWs+AAAACXZwQWcAAAAQAAAAEABcxq3DAAABfElEQVQ4y52TvUuCURTGf5Zg 9goR9AVlUZJ9KURuUkhIUEPQUIubRFtIJTk0NTkUFfgntAUt0eBSQwRKRFSYBYFl1GAt901eUYuw QTLM1yLPds/zPD/uPYereYjHcwD+tQ3+Uys+LwCah3g851la/lf4qwKb61Sn3z5WFUWpCHB+GUGb SCRIpVKqBkmSAMrqsViMqnIiwLx7HO/U+6+30GYyaVXBP1uHrfUAWvWMWiF4+qoOUJLJkubYcDs2 S03hvODSE7564ek5W+Kt+tloa9ax6v4OZ++jZO+jbM+pD7oE4HM1lX1vYNGoDhCyQMiCGacRm0Vf EM+uiudjke6YcRoLfiELNB2dXTkAa08LPlcT2fpJAMxWZ1H4NnKITuwD4Nl6RMgCAE1DY3PuyyQZ JLrNvZhMJgCmJwYB2A1eAHASDiFkQUr5Xn0RoJLSDg7ZCB0fVRQ29/TmP1Nf/0BFgL2dQH4LN9dR 7CMOaiXDn6FayYB9xMHeTgCz1cknd+WC3VgTorUAAAAldEVYdGNyZWF0ZS1kYXRlADIwMTAtMTIt MjZUMTQ6NDk6MjErMDk6MDAHHBB1AAAAJXRFWHRtb2RpZnktZGF0ZQAyMDEwLTEyLTI2VDE0OjQ5 OjIxKzA5OjAwWK1mQQAAAABJRU5ErkJggolQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgGAAAAH/P/ YQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAASAAAAEgARslrPgAAAAl2cEFnAAAAEAAAABAA XMatwwAAAhdJREFUOMuVk81LVFEYxn/3zocfqVebUbCyTLyYRYwD0cemCIRyUVToLloERUFBbYpo E7WIFv0TLaP6C2Y17oYWWQxRMwo5OUplkR/XOefMuW8LNYyZLB94eOE5L79zzns4johIPp/n+YtX fPn6jaq1bKaI65LY3sHohXOk02mcNxMT8vjJU5TWbEUN8Ti3bl4n0tLW/qBcniW0ltBaxFrsWl3P 7IZ8PdNa82m6RPTDxyLGmLq7JDuaqVQCllbqn6I4OUU0CJYJw7BmMR6LcPvyURbLGR49q/71KlGj dV3AlbEhBnog3mo5e8Tycrz+cKPamBrAiUOdnD/ZhlFziKpw7RS8LVry01IDcI3WbHRXu8OdS524 pgx6BlkJEKW4PxrSFP2z12iNq1UFrTVaaxDNw6vttDXMg/2O2AXC5UUkWKI7vsDdM+Z3X9Ws2tXG YLTCaMWNMY8DfREAFpcUkzPC1JzL8kKAGM3xvoDD+1uJVX+ilEIptTpECUP8PXEGB/rIzw/iNPXj de1jML0Xay3l6QKfZyewP95x8dhr7r0HpSoAODt7dktoQ0SEpsZGent78f1+fN/H9/sxxlAoFCkU CxQKRUqlEkppXNddBXTv2CXrtH/JofYVoqnUQbLZ8f/+A85aFWAolYJcLiee50ksFtuSm7e1SCaT EUREcrmcnB4ZkWQyKZ7nbepEIiHDw8OSzWZFROQX6PpZFxAtS8IAAAAldEVYdGNyZWF0ZS1kYXRl ADIwMTAtMTItMjZUMTQ6NDk6MjErMDk6MDAHHBB1AAAAJXRFWHRtb2RpZnktZGF0ZQAyMDEwLTEy LTI2VDE0OjQ5OjIxKzA5OjAwWK1mQQAAAABJRU5ErkJggolQTkcNChoKAAAADUlIRFIAAAAQAAAA EAgGAAAAH/P/YQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAASAAAAEgARslrPgAAAAl2cEFn AAAAEAAAABAAXMatwwAAAo9JREFUOMuNks1rVGcUxn/ve+9kUuOdfIzamNHEMK3RVILQQAuCWURo rSAtbsV20T/EP6O7FtxkkYWQKK7F4Kb1C6yoSVrNdDIm1YTMjDP3vfc9p4ubZEYopQceDhwOD89z zmO89/rw0SNu3b5D5a8q3gv7ZXa7dkY2sIwMf8w3X3/F9PTnhL/+9oCff7nBeq2GMYb/U5sbm1TX a8TOEQwMHbq+vLKKqqIiiAh+r3tBvKBds72der1OtVolfP78BWmadmnNVKgqI0cOkiRtNrc9Zt9H x9fK6iphs/keVflAoqpSHOzjh+8maL59yk83WzRa8G8OwzRxiHQIFOjJBXw7O8b0qV50K2H1tWf+ riCiHRbNFIUucYgoZu/Yqlz44iiXzh3EpJuE0uLKl57lNc/93wVjOyYyApeguwpElTOf9HH1YkSU e0O72cC/b1DMK9/PGP5c97zaUGwXg01cjHMxcRwz0Cf8ePkAJ47U0eRvSLehtYM06pw+1OTauZje wBG7mCTJEDqX3eCjvOXqxQGmTwXUmwlxmmdrpw+z0ybiHXnbYqasvDgbcGPJEvvsHKFzDp96Tgz3 cvjwMM/efsaBwZP0D39KabKEpgnbG3/wrvaU5psnHD/6mMF8jcqWwRgwpWOjKiLkQkOhv5+xsTLl cpnR0WOUSiVEhLVKhbXXa7xcXqHyaoV6o0Hqd1MxUjqu7XYLMFkaNXtXYC09+R5UwbkYEcVaizFm P/LWGsLJydMs3VvCWkP3gzxK7OKu7Bl81/tEhKmpKVhYWNCJiQkNglDDMKdhLpf1/0AQhDo+Pq5z c3NKmqa6uLios7MXtFgsahRFGhUKHUS7KBQ0iiIdGhrS8+dndH5+XpMk0X8AMTVx/inpU4cAAAAl dEVYdGNyZWF0ZS1kYXRlADIwMTAtMTItMjZUMTQ6NDk6MjErMDk6MDAHHBB1AAAAJXRFWHRtb2Rp ZnktZGF0ZQAyMDEwLTEyLTI2VDE0OjQ5OjIxKzA5OjAwWK1mQQAAAABJRU5ErkJggg == '''.strip() class YTUrlVideoTest(TestCase): def setUp(self): self.client = Client() self.contributor_credential = { "email": "kontributor@gov.id", "password": "passwordtest"} self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True ) self.setUpImage() self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file") self.category = Category.objects.create( id="1", name="medis", description="kategori medis") @override_settings(MEDIA_ROOT=tempfile.gettempdir()) def setUpImage(self): self.cover = InMemoryUploadedFile( BytesIO(base64.b64decode(TEST_IMAGE)), field_name='tempfile', name='tempfile.png', content_type='image/png', size=len(TEST_IMAGE), charset='utf-8', ) def test_yt_video_id_exists_in_Materi(self): materi_temp = Materi.objects.create() self.assertEqual(hasattr(materi_temp, 'yt_video_id'), True) def test_yt_video_id_exists_in_UploadMateri_page(self): self.client.login(**self.contributor_credential) response = self.client.get("/unggah/") html = response.content.decode("utf-8") self.assertIn('Youtube Video Id', html) def test_upload_materi_with_valid_yt_video_id(self): self.client.login(**self.contributor_credential) self.client.post( "/unggah/", data={"title": "Materi 1", "author": "Agas", "publisher": "Kelas SC", "release_year": "2000", "descriptions": "Deskripsi Materi 1", 'categories': "1", "cover": self.cover, "content": self.content, "yt_video_id": "jNwz4L9MGVY"} ) self.assertTrue(Materi.objects.get(title="Materi 1")) def test_upload_materi_with_invalid_yt_video_id(self): self.client.login(**self.contributor_credential) self.client.post( "/unggah/", data={"title": "Materi 2", "author": "Agas", "publisher": "Kelas SC", "release_year": "2000", "descriptions": "Deskripsi Materi 1", 'categories': "1", "cover": self.cover, "content": self.content, "yt_video_id": "randomId"} ) self.assertEqual(Materi.objects.filter(title="Materi 2").count(), 0) def test_detail_materi_has_video_if_yt_video_id_not_empty(self): self.test_upload_materi_with_valid_yt_video_id() pk = Materi.objects.get(title="Materi 1").pk response = self.client.get("/materi/"+str(pk)+"/") html = response.content.decode("utf-8") self.assertIn("Video", html) def test_detail_materi_has_no_video_if_yt_video_id_empty(self): self.client.login(**self.contributor_credential) self.client.post( "/unggah/", data={"title": "Materi 2", "author": "Agas", "publisher": "Kelas SC", "release_year": "2000", "descriptions": "Deskripsi Materi 1", 'categories': "1", "cover": self.cover, "content": self.content, } ) pk = Materi.objects.get(title="Materi 2").pk response = self.client.get("/materi/"+str(pk)+"/") html = response.content.decode("utf-8") self.assertNotIn("Video", html) class ChangePasswordTest(TestCase): def setUp(self): self.client = Client() self.kontributor = User.objects.create_contributor( email="kontributor@gov.id", password="kontributor") self.admin = User.objects.create_admin( email="admin@gov.id", password="admin") self.url = "/change-password/" self.view = PasswordChangeViews self.template_name = "change-password.html" def test_change_password_view(self): found = resolve(self.url) self.assertEqual(found.func.__name__, self.view.as_view().__name__) def test_change_password_template(self): # Login self.client.login(email="kontributor@gov.id", password="kontributor") # Test response = self.client.get(self.url) self.assertTemplateUsed(response, self.template_name) # Logout self.client.logout() def test_change_password_url_access(self): # Login self.client.login(email="kontributor@gov.id", password="kontributor") # Test response = self.client.get(self.url) self.assertEqual(response.status_code, 200) # Logout self.client.logout() class SeeRatedMateriByUser(TestCase): def setUp(self): self.client = Client() self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.admin_credential = { "email": "admin@gov.id", "password": id_generator() } self.kontributor = User.objects.create_contributor( **self.contributor_credential) self.admin = User.objects.create_admin(**self.admin_credential) self.given_rating_url = "/given-rating/" self.cover = SimpleUploadedFile( "cover.jpg", b"Test file" ) self.content = SimpleUploadedFile( "content.txt", b"Test file" ) Materi(title="Materi 2", author="Agas", uploader=self.kontributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="PENDING", cover=self.cover, content=self.content).save() Materi(title="Materi 3", author="Agas", uploader=self.kontributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="PENDING", cover=self.cover, content=self.content).save() Materi(title="Materi 1", author="Agas", uploader=self.kontributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="PENDING", cover=self.cover, content=self.content).save() self.materi1 = Materi.objects.all()[0] self.materi2 = Materi.objects.all()[1] self.materi3 = Materi.objects.all()[2] time.sleep(5) self.rating_test_1 = Rating( materi=self.materi1, user=self.kontributor, score=5) time.sleep(5) self.rating_test_2 = Rating( materi=self.materi2, user=self.kontributor, score=4) time.sleep(5) self.rating_test_3 = Rating( materi=self.materi3, user=self.kontributor, score=3) time.sleep(5) self.rating_test_4 = Rating( materi=self.materi3, user=self.admin, score=3) self.rating_test_1.save() self.rating_test_2.save() self.rating_test_3.save() self.rating_test_4.save() def test_authorize_template_used(self): self.client.login(**self.contributor_credential) response = self.client.get(self.given_rating_url) self.assertTemplateUsed(response, "given-rating.html") def test_unauthorized_user_shouldnt_be_able_to_access_see_rating_page(self): response = self.client.get(self.given_rating_url) self.assertEqual(response.status_code, 403) self.assertTemplateUsed(response, "error_403.html") def test_authorized_should_be_able_to_access_given_rating_page(self): self.client.login(**self.contributor_credential) response = self.client.get(self.given_rating_url) self.assertEqual(response.status_code, 200) self.client.login(**self.admin_credential) response = self.client.get(self.given_rating_url) self.assertEqual(response.status_code, 200) def test_given_rating_page_should_show_correct_rating(self): self.client.login(**self.contributor_credential) response = self.client.get(self.given_rating_url) self.assertIn(self.rating_test_1, response.context['rating_list']) self.assertIn(self.rating_test_2, response.context['rating_list']) self.assertIn(self.rating_test_3, response.context['rating_list']) def test_given_rating_page_should_not_show_others_rating(self): self.client.login(**self.contributor_credential) response = self.client.get(self.given_rating_url) self.assertNotIn(self.rating_test_4, response.context['rating_list']) def test_given_rating_page_no_rating_should_display_message(self): user_credential = {"email": "user@mail.com", "password": id_generator()} User.objects.create_contributor(**user_credential) self.client.login(**user_credential) response = self.client.get(self.given_rating_url) self.assertEqual(len(response.context['rating_list']), 0) self.assertIn("Anda belum pernah memberikan rating ke materi", response.content.decode("utf-8")) self.assertNotIn(self.materi1.title, response.content.decode("utf-8")) def test_given_rating_page_order_should_give_default_parameter(self): # No parameters order_by_key = timestamp and order_by : ascending self.client.login(**self.contributor_credential) response = self.client.get(self.given_rating_url) self.assertEqual(response.context['order_by'], 'dsc') self.assertEqual(response.context['order_by_key'], 'timestamp') # No order_by_key parameter, should default to timestamp response = self.client.get(self.given_rating_url + '?order=asc') self.assertEqual(response.context['order_by'], 'asc') self.assertEqual(response.context['order_by_key'], 'timestamp') # No order_by parameter, should default to asc response = self.client.get( self.given_rating_url + '?order_by_key=score') self.assertEqual(response.context['order_by'], 'dsc') self.assertEqual(response.context['order_by_key'], 'score') # INVALID PARAMETERS # Starts with negative response = self.client.get( self.given_rating_url + '?order_by_key=-score') self.assertEqual(response.context['order_by'], 'dsc') self.assertEqual(response.context['order_by_key'], 'score') # Invalid params response = self.client.get( self.given_rating_url + '?order_by_key=halohalohalo&order=haihaihaihai') self.assertEqual(response.context['order_by'], 'dsc') self.assertEqual(response.context['order_by_key'], 'timestamp') def test_given_rating_page_order_ascending_should_be_correct(self): self.client.login(**self.contributor_credential) response = self.client.get( self.given_rating_url + '?order_by_key=score&order=asc') # From Low to High # order key score self.assertEqual(response.context['order_by'], 'asc') self.assertEqual(response.context['order_by_key'], 'score') self.assertEqual(list(response.context['rating_list']), [self.rating_test_3, self.rating_test_2, self.rating_test_1]) # order key timestamp response = self.client.get( self.given_rating_url + '?order_by_key=timestamp&order=asc') self.assertEqual(response.context['order_by'], 'asc') self.assertEqual(response.context['order_by_key'], 'timestamp') self.assertEqual(list(response.context['rating_list']), [self.rating_test_1, self.rating_test_2, self.rating_test_3]) # order key materi title response = self.client.get( self.given_rating_url + '?order_by_key=materi__title&order=asc') self.assertEqual(response.context['order_by'], 'asc') self.assertEqual(response.context['order_by_key'], 'materi__title') self.assertEqual(list(response.context['rating_list']), [self.rating_test_3, self.rating_test_1, self.rating_test_2]) def test_given_rating_page_order_descending_should_be_correct(self): self.client.login(**self.contributor_credential) # From High to Low # order key score response = self.client.get( self.given_rating_url + '?order_by_key=score&order=dsc') self.assertEqual(response.context['order_by'], 'dsc') self.assertEqual(response.context['order_by_key'], 'score') self.assertEqual(list(response.context['rating_list']), [self.rating_test_1, self.rating_test_2, self.rating_test_3]) # order key timestamp response = self.client.get( self.given_rating_url + '?order_by_key=timestamp&order=dsc') self.assertEqual(response.context['order_by'], 'dsc') self.assertEqual(response.context['order_by_key'], 'timestamp') self.assertEqual(list(response.context['rating_list']), [self.rating_test_3, self.rating_test_2, self.rating_test_1]) # order key materi title response = self.client.get( self.given_rating_url + '?order_by_key=materi__title&order=dsc') self.assertEqual(response.context['order_by'], 'dsc') self.assertEqual(response.context['order_by_key'], 'materi__title') self.assertEqual(list(response.context['rating_list']), [self.rating_test_2, self.rating_test_1, self.rating_test_3]) class PasswordValidatorPolicyTest(TestCase): def setUp(self): self.password_no_lowercase = "PASSW0RD!" self.password_no_uppercase = "passw0rd!" self.password_no_digit = "Password!" self.password_no_special_char = "Passw0rd" self.password_length_lower_than_8 = "P4ss!" self.password_enforcing_policy = "Passw0rd!" self.validator = PasswordPolicyValidator() def test_using_password_no_lowercase(self): self.assertRaises( ValidationError, self.validator.validate, self.password_no_lowercase) def test_using_password_no_upprcase(self): self.assertRaises( ValidationError, self.validator.validate, self.password_no_uppercase) def test_using_password_no_digit(self): self.assertRaises( ValidationError, self.validator.validate, self.password_no_digit) def test_using_password_no_special_char(self): self.assertRaises(ValidationError, self.validator.validate, self.password_no_special_char) def test_using_password_with_length_less_than_8(self): self.assertRaises(ValidationError, self.validator.validate, self.password_length_lower_than_8) def test_using_password_using_correct_policy(self): self.assertEquals(self.validator.validate( self.password_enforcing_policy), None) class LandingPageNavbarTest(TestCase): def setUp(self): self.client = Client() self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.admin_credential = { "email": "admin@gov.id", "password": id_generator() } self.public_credential = { "email": "public@gov.id", "password": id_generator() } self.kontributor = User.objects.create_contributor( **self.contributor_credential) self.admin = User.objects.create_admin(**self.admin_credential) self.public = User.objects.create_user(**self.public_credential) def test_navbar_admin(self): self.client.login(**self.admin_credential) response = self.client.get('/') self.assertContains( response, 'Digipus') self.assertContains( response, 'Forum') self.assertContains( response, 'Berita') self.assertContains( response, 'Profil') self.assertContains( response, 'Logout') self.assertContains( response, 'Administrasi') self.assertNotContains( response, 'Dasbor') def test_navbar_contributor(self): self.client.login(**self.contributor_credential) response = self.client.get('/') self.assertContains( response, 'Digipus') self.assertContains( response, 'Forum') self.assertContains( response, 'Berita') self.assertContains( response, 'Profil') self.assertContains( response, 'Logout') self.assertContains( response, 'Dasbor') self.assertNotContains( response, 'Administrasi') def test_navbar_public(self): self.client.login(**self.public_credential) response = self.client.get('/') self.assertContains( response, 'Digipus') self.assertContains( response, 'Forum') self.assertContains( response, 'Berita') self.assertContains( response, 'Profil') self.assertContains( response, 'Logout') self.assertNotContains( response, 'Dasbor') self.assertNotContains( response, 'Administrasi') def test_navbar_anonymous(self): response = self.client.get('/') self.assertContains( response, 'Digipus') self.assertContains( response, 'Forum') self.assertContains( response, 'Berita') self.assertContains( response, '') self.assertContains( response, 'Umum') self.assertContains( response, 'Kontributor') self.assertContains(response, 'Login') self.assertContains( response, 'Kontributor') self.assertContains( response, 'Admin') self.assertNotContains( response, 'Profil') self.assertNotContains( response, 'Logout') self.assertNotContains( response, 'Dasbor') self.assertNotContains( response, 'Administrasi') class MateriRecommendationTest(TestCase): def setUp(self): self.contributor = User.objects.create( email="kontributor@gov.id", password="passwordtest", name="kontributor", is_contributor=True ) self.cover = SimpleUploadedFile("ExampleCover221.jpg", b"Test file") self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file") def test_able_to_get_recommendation_by_like_counts(self): materi1 = Materi.objects.create( title="Materi 1", author="Nandhika", uploader=self.contributor, publisher="Publisher", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content, date_modified=timezone.now(), date_created=timezone.now(), ) Like.objects.create(materi=materi1) Like.objects.create(materi=materi1) materi2 = Materi.objects.create( title="Materi 2", author="Prayoga", uploader=self.contributor, publisher="Publisher", descriptions="Deskripsi Materi 2", status="APPROVE", cover=self.cover, content=self.content, date_modified=timezone.now(), date_created=timezone.now(), ) Like.objects.create(materi=materi2) Like.objects.create(materi=materi2) Like.objects.create(materi=materi2) Materi.objects.create( title="Materi 3", author="Nandhika Prayoga", uploader=self.contributor, publisher="Publisher", descriptions="Deskripsi Materi 3", status="APPROVE", cover=self.cover, content=self.content, date_modified=timezone.now(), date_created=timezone.now(), ) response = Client().get("/?recommendation=1") list = [int(id) for id in re.findall( r"Materi\s(\d+)[^\d]", response.content.decode())] self.assertEqual(list, [2, 1, 3]) def test_set_date_as_tiebreak_if_like_counts_is_same(self): materi2 = Materi.objects.create( title="Materi 2", author="Prayoga", uploader=self.contributor, publisher="Publisher", descriptions="Deskripsi Materi 2", status="APPROVE", cover=self.cover, content=self.content, date_modified=timezone.now(), date_created=timezone.now(), ) Like.objects.create(materi=materi2) Like.objects.create(materi=materi2) materi1 = Materi.objects.create( title="Materi 1", author="Nandhika", uploader=self.contributor, publisher="Publisher", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content, date_modified=timezone.now(), date_created=timezone.now(), ) Like.objects.create(materi=materi1) Like.objects.create(materi=materi1) response = Client().get("/?recommendation=1") list = [int(id) for id in re.findall( r"Materi\s(\d+)[^\d]", response.content.decode())] self.assertEqual(list, [1, 2]) class GuestBookTest(TestCase): def test_form_name_input_has_placeholder_and_css_classes(self): form = GuestBookForm() self.assertIn('placeholder="Input your name"', form.as_p()) self.assertIn('class="form-control input-lg"', form.as_p()) def test_form_job_input_has_placeholder_and_css_classes(self): form = GuestBookForm() self.assertIn('placeholder="Input your job"', form.as_p()) self.assertIn('class="form-control input-lg"', form.as_p()) def test_form_gender_input_has_choices_and_css_classes(self): form = GuestBookForm() self.assertIn('option value="Male"', form.as_p()) self.assertIn('option value="Female">', form.as_p()) self.assertIn('class="form-control input-lg"', form.as_p()) def test_form_validation_for_blank_items(self): form = GuestBookForm(data={'name': '', 'job': '', 'gender': ''}) self.assertFalse(form.is_valid()) self.assertEqual( form.errors['name'], ['Name is required'] ) self.assertEqual( form.errors['job'], ['Job is required'] ) self.assertEqual( form.errors['gender'], ['Gender is required'] ) def test_can_create_guest_book_instance(self): guestBook = GuestBook(name='Selvy', job='Student', gender='Female') guestBook.save() self.assertEqual(GuestBook.objects.count(), 1) class MateriSearchVectorTest(TestCase): def setUp(self): Materi.SEARCH_INDEX = (("title", "A"), ("author", "B")) def test_search_vector_constructed_on_create(self): materi = Materi(title="Buku 1", author="Pembuat 1") materi.save() search_vector_string = list( Materi.objects.values_list("_search_vector", flat=True) )[0] self.assertGreaterEqual(len(search_vector_string.split(",")), 1) def test_search_vector_based_on_indexed_attribute(self): materi = Materi(title="Buku 1", author="Pembuat 1", descriptions="Deskripsi 1") materi.save() search_vector_string = list( Materi.objects.values_list("_search_vector", flat=True) )[0] self.assertIn("buku", search_vector_string) self.assertIn("pembuat", search_vector_string) def test_search_vector_not_based_on_unindexed_attribute(self): materi = Materi(title="Buku 1", author="Pembuat 1", descriptions="Deskripsi 1") materi.save() search_vector_string = list( Materi.objects.values_list("_search_vector", flat=True) )[0] self.assertNotIn("deskripsi", search_vector_string) def test_search_vector_reconstructed_on_update_indexed_field(self): materi = Materi(title="Sebelum reconstruct") materi.save() search_vector = list(Materi.objects.values_list( "_search_vector", flat=True))[0] materi.title = "Setelah reconstruct" materi.save() search_vector = list(Materi.objects.values_list( "_search_vector", flat=True))[0] self.assertIn("setelah", search_vector) def test_search_vector_not_reconstructed_on_update_unindexed_field(self): materi = Materi(descriptions="sebelum reconstruct") materi.save() search_vector = list(Materi.objects.values_list( "_search_vector", flat=True))[0] materi.descriptions = "sebelum reconstruct" materi.save() search_vector = list(Materi.objects.values_list( "_search_vector", flat=True))[0] self.assertNotIn("setelah", search_vector) class MateriSearchTest(TestCase): def test_empty_result_on_empty_table(self): search_query = "test" search_result = list(Materi.objects.search(search_query)) expected_search_result = [] self.assertSequenceEqual(search_result, expected_search_result) def test_empty_result_on_unmatched_data(self): Materi.SEARCH_INDEX = (("title", "A"), ("author", "B")) Materi(title="buku 1", author="bapak 1").save() Materi(title="artikel 2", author="ibu 1").save() search_query = "majalah" search_result = list(Materi.objects.search(search_query)) expected_search_result = [] self.assertSequenceEqual(search_result, expected_search_result) search_query = "kakak" search_result = list(Materi.objects.search(search_query)) expected_search_result = [] self.assertSequenceEqual(search_result, expected_search_result) def test_correct_rank_on_result_tested_by_similiarity_words(self): Materi.SEARCH_INDEX = (("descriptions", "A"),) materi_2 = Materi(descriptions="ini lumayan cocok lumayan cocok") materi_2.save() materi_1 = Materi( descriptions="ini sangat cocok sangat cocok sangat cocok") materi_1.save() materi_4 = Materi(descriptions="ini tidak") materi_4.save() materi_3 = Materi(descriptions="ini sedikit cocok") materi_3.save() search_query = "ini cocok" search_result = list(Materi.objects.search(search_query)) expected_search_result = [materi_1, materi_2, materi_3] self.assertSequenceEqual(search_result, expected_search_result) def test_correct_rank_on_result_tested_by_weight(self): Materi.SEARCH_INDEX = ( ("title", "A"), ("author", "C"), ("descriptions", "B"), ("publisher", "D"), ) materi_title = Materi(title="cocok") materi_title.save() materi_author = Materi(author="cocok cocok cocok") materi_author.save() materi_descriptions = Materi(descriptions="cocok cocok") materi_descriptions.save() materi_publisher = Materi(publisher="cocok cocok cocok cocok") materi_publisher.save() search_query = "cocok" search_result = list(Materi.objects.search(search_query)) expected_search_result = [ materi_title, materi_descriptions, materi_author, materi_publisher, ] self.assertSequenceEqual(search_result, expected_search_result) class BacaNantiTest(TestCase): def setUp(self): self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.user_one_credential = { "email": "user_one@user.id", "password": id_generator() } self.user_two_credential = { "email": "user_two@user.id", "password": id_generator() } self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True ) self.user_one = get_user_model().objects.create_user( **self.user_one_credential, name="User One") self.user_two = get_user_model().objects.create_user( **self.user_two_credential, name="User Two") self.cover = SimpleUploadedFile( "cover.jpg", b"Test file" ) self.content = SimpleUploadedFile( "content.txt", b"Test file" ) Materi(title="Materi 1", author="Agas", uploader=self.contributor, publisher="Kelas SC", descriptions="Deskripsi Materi 1", status="APPROVE", cover=self.cover, content=self.content).save() Materi(title="Materi Dua", author="Author", uploader=self.contributor, publisher="Publisher", descriptions="Deskripsi Materi Dua", status="APPROVE", cover=self.cover, content=self.content).save() self.materi1 = Materi.objects.filter(title='Materi 1').get() self.materi2 = Materi.objects.filter(title='Materi Dua').get() self.url = '/baca-nanti/' self.toggle_url = '/baca-nanti-toggle/' self.url_materi = '/materi/{}/'.format(self.materi1.id) def test_readlater_object_can_be_created(self): ReadLater(materi=self.materi1, user=self.user_one).save() read_later = ReadLater.objects.first() self.assertEqual(read_later.materi, self.materi1) self.assertEqual(read_later.user, self.user_one) def test_readlater_materi_must_not_unique(self): ReadLater(materi=self.materi1, user=self.user_one).save() ReadLater(materi=self.materi1, user=self.user_two).save() read_later_one = ReadLater.objects.get(user=self.user_one) read_later_two = ReadLater.objects.get(user=self.user_two) self.assertEqual(read_later_one.materi, self.materi1) self.assertEqual(read_later_one.user, self.user_one) self.assertEqual(read_later_two.materi, self.materi1) self.assertEqual(read_later_two.user, self.user_two) def test_readlater_user_must_not_unique(self): ReadLater(materi=self.materi1, user=self.user_one).save() ReadLater(materi=self.materi2, user=self.user_one).save() read_later_one = ReadLater.objects.get(materi=self.materi1) read_later_two = ReadLater.objects.get(materi=self.materi2) self.assertEqual(read_later_one.materi, self.materi1) self.assertEqual(read_later_one.user, self.user_one) self.assertEqual(read_later_two.materi, self.materi2) self.assertEqual(read_later_two.user, self.user_one) def test_readlater_materi_combined_with_user_must_be_unique(self): with self.assertRaises(IntegrityError) as context: ReadLater(materi=self.materi1, user=self.user_one).save() ReadLater(materi=self.materi1, user=self.user_one).save() self.assertTrue('already exists' in str(context.exception)) def test_readlater_materi_cant_null(self): with self.assertRaises(IntegrityError): ReadLater(user=self.user_one).save() def test_readlater_user_cant_null(self): with self.assertRaises(IntegrityError): ReadLater(materi=self.materi1).save() def test_readlater_profile_page_url_exist(self): self.client.login(**self.user_one_credential) response = self.client.get(self.url) self.assertEqual(response.status_code, 200) def test_readlater_profile_page_using_template(self): self.client.login(**self.user_one_credential) response = self.client.get(self.url) self.assertTemplateUsed( response=response, template_name="baca-nanti.html") def test_toggle_readlater_url_exist(self): self.client.login(**self.user_one_credential) response = self.client.post( self.toggle_url, {'materi_id': self.materi1.id}) self.assertEqual(response.status_code, 200) def test_checking_readlater_in_materi_create_object(self): self.client.login(**self.user_one_credential) self.client.post(self.toggle_url, {'materi_id': self.materi1.id}) read_later_exist = ReadLater.objects.filter( materi=self.materi1, user=self.user_one).exists() self.assertEqual(read_later_exist, True) def test_unchecking_readlater_in_materi_delete_object(self): self.client.login(**self.user_one_credential) self.client.post(self.toggle_url, {'materi_id': self.materi1.id}) sleep(1) self.client.post(self.toggle_url, {'materi_id': self.materi1.id}) read_later_exist = ReadLater.objects.filter( materi=self.materi1, user=self.user_one).exists() self.assertEqual(read_later_exist, False) def test_checking_readlater_in_materi_with_complete_paramater_return_success(self): self.client.login(**self.user_one_credential) response = self.client.post( self.toggle_url, {'materi_id': self.materi1.id}) self.assertJSONEqual( str(response.content, encoding='utf-8'), {"success": True, "read_later_checked": True} ) def test_unchecking_readlater_in_materi_with_complete_paramater_return_success(self): self.client.login(**self.user_one_credential) self.client.post(self.toggle_url, {'materi_id': self.materi1.id}) sleep(1) response = self.client.post( self.toggle_url, {'materi_id': self.materi1.id}) self.assertJSONEqual( str(response.content, encoding='utf-8'), {"success": True, "read_later_checked": False} ) def test_toggle_readlater_return_if_method_snot_post(self): self.client.login(**self.user_one_credential) response = self.client.get( self.toggle_url, {'materi_id': self.materi1.id}) self.assertJSONEqual( str(response.content, encoding='utf-8'), {"success": False, "msg": "Unsuported method"} ) def test_toggle_readlater_return_if_paramater_materi_id_not_found(self): self.client.login(**self.user_one_credential) response = self.client.post(self.toggle_url) self.assertJSONEqual( str(response.content, encoding='utf-8'), {"success": False, "msg": "Missing parameter"} ) class MateriStatsTest(TestCase): def setUp(self): self.credential = { 'email': "kontributor@gov.id", 'password': "P@ssw0rd", } self.path = '/stats/' self.path_json = '/stats/?data=json' self.header = 'Summary Materi per Kategori' self.contributor = User.objects.create_contributor( **self.credential, name="kontributor") self.client = Client() categories = [] for i in range(10): cat = Category(name=f'Cat{i}', description=f'Cat{i} description') cat.save() categories.append(cat) for i in range(10): for j in range(random.randint(1, 10)): m = Materi(title=f'Title{i}-{j}') m.save() m.categories.add(categories[i]) m.save() def test_stats_has_correct_template(self): self.client.login(**self.credential) response = self.client.get(self.path) self.assertTemplateUsed(response, 'statistik.html') def test_stats_as_authenticated(self): self.client.login(**self.credential) response = self.client.get(self.path) self.assertContains(response, self.header) def test_stats_as_anonymous(self): response = self.client.get(self.path) self.assertEqual(response.status_code, 302) # redirect response = self.client.get(self.path_json) self.assertEqual(response.status_code, 302) # redirect def test_stats_api_correct_data(self): self.client.login(**self.credential) response = self.client.get(self.path_json) jobj = json.loads(response.content) self.assertEqual(len(jobj['labels']), 6) class UploadMateriTest(TestCase): def setUp(self): self.client = Client() self.user = User.objects._create_user(email="kontributor@gov.id", password="kontributor", is_contributor=True) self.setUpImage() self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file") self.category = Category.objects.create( id="1", name="sains", description="kategori sains") @override_settings(MEDIA_ROOT=tempfile.gettempdir()) def setUpImage(self): self.cover = InMemoryUploadedFile( BytesIO(base64.b64decode(TEST_IMAGE)), field_name='tempfile', name='tempfile.png', content_type='image/png', size=len(TEST_IMAGE), charset='utf-8', ) def test_for_invalid_input_shows_validation_error(self): self.client.login(email="kontributor@gov.id", password="kontributor") response = self.client.post("/unggah/", data={"title": ""}) self.assertContains(response, "This field is required.") def test_data_form_upload_materi_success_save_to_db(self): self.client.login(email="kontributor@gov.id", password="kontributor") data = {"title": "Dunia Binatang", "author": "Parzival", "publisher": "Buku Asyik", "release_year": "2015", "descriptions": "Buku dunia binatang seri 1", 'categories': "1", "cover": self.cover, "content": self.content} self.client.post("/unggah/", data=data) self.assertEqual(Materi.objects.count(), 1) class NotifikasiKontributorTest(TestCase): def setUp(self): self.client = Client() self.contributor_credential = {"email": "kontributor@gov.id", "password": "passwordtest"} self.contributor = get_user_model().objects.create_user( **self.contributor_credential, name="Kontributor", is_contributor=True ) self.admin_credential = { "email": "admin@gov.id", "password": "passwordtest" } self.admin = get_user_model().objects.create_user( **self.admin_credential, name="Admin", is_admin=True) self.setUpImage() self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file") self.category = Category.objects.create(id="1", name="medis", description="kategori medis") VerificationSetting.objects.create(title="Kriteria 1", description="memenuhi kriteria 1", archived=False, pk=1) self.make_materi() @override_settings(MEDIA_ROOT=tempfile.gettempdir()) def setUpImage(self): self.cover = InMemoryUploadedFile( BytesIO(base64.b64decode(TEST_IMAGE)), field_name='tempfile', name='tempfile.png', content_type='image/png', size=len(TEST_IMAGE), charset='utf-8', ) def make_materi(self): self.client.login(**self.contributor_credential) self.client.post( "/unggah/", data={"title":"Materi 1", "author":"Agas", "publisher":"Kelas SC", "release_year":"2000", "descriptions":"Deskripsi Materi 1", 'categories':"1", "cover":self.cover, "content":self.content, "yt_video_id":"jNwz4L9MGVY"} ) self.client.logout() def admin_disapprove_materi(self, materi, pk_new_materi): self.client.login(**self.admin_credential) self.client.post( "/administration/detail-verif/"+str(pk_new_materi)+"/", data={ 'kriteria-1':'0','feedback':"a", 'action':"disapprove" } ) self.client.logout() def test_no_notification(self): self.client.login(**self.contributor_credential) notifs = NotifikasiKontributor.objects.filter(user=self.contributor) self.assertEqual(notifs.count(), 0) self.client.logout() def test_notification(self): materi = Materi.objects.get(title="Materi 1", uploader=self.contributor) pk_new_materi = materi.id self.admin_disapprove_materi(materi, pk_new_materi) self.assertEqual(NotifikasiKontributor.objects.filter(materi=materi, user=self.contributor).count(), 1) # Client as Kontributor get notifications self.client.login(**self.contributor_credential) notif = NotifikasiKontributor.objects.get(materi=materi, user=self.contributor) html = self.client.get("/dashboard/").content.decode("utf-8") self.assertIn(str(notif), html) def test_notifications_reset_when_it_is_revised(self): materi = Materi.objects.get(title="Materi 1", uploader=self.contributor) pk_new_materi = materi.id self.admin_disapprove_materi(materi, pk_new_materi) self.assertEqual(NotifikasiKontributor.objects.filter(materi=materi, user=self.contributor).count(), 1) self.client.login(**self.contributor_credential) notif = NotifikasiKontributor.objects.get(materi=materi, user=self.contributor) # Client as Kontributor check Materi detail, and the notification should be gone response = self.client.post( "/revisi/materi/"+str(pk_new_materi)+"/", data={"title":"Materi 2", "author":"Agas", "publisher":"Kelas SC", "release_year":"2000", "descriptions":"Deskripsi Materi 2", 'categories':"1", "cover":self.cover, "content":self.content, "yt_video_id":"jNwz4L9MGVY"} ) self.assertEqual(NotifikasiKontributor.objects.filter(materi=materi, user=self.contributor).count(), 0) def test_notifications_reset_when_it_is_opened_in_detail(self): materi = Materi.objects.get(title="Materi 1", uploader=self.contributor) pk_new_materi = materi.id self.admin_disapprove_materi(materi, pk_new_materi) self.assertEqual(NotifikasiKontributor.objects.filter(materi=materi, user=self.contributor).count(), 1) self.client.login(**self.contributor_credential) notif = NotifikasiKontributor.objects.get(materi=materi, user=self.contributor) # Client as Kontributor check Materi detail, and the notification should be gone self.client.get("/materi/"+str(materi.id)+"/") self.assertEqual(NotifikasiKontributor.objects.filter(materi=materi, user=self.contributor).count(), 0) class AdminNotificationTest(TestCase): def setUp(self): self.client = Client() self.contributor_credential = { "email": "kontributor@gov.id", "password": id_generator() } self.admin_credential = { "email": "admin@gov.id", "password": id_generator() } self.public_credential = { "email": "public@gov.id", "password": id_generator() } self.kontributor = User.objects.create_contributor(**self.contributor_credential) self.admin = User.objects.create_admin(**self.admin_credential) self.public = User.objects.create_user(**self.public_credential) self.setUpImage() self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file") self.category = Category.objects.create(id="1", name="medis", description="kategori medis") @override_settings(MEDIA_ROOT=tempfile.gettempdir()) def setUpImage(self): self.cover = InMemoryUploadedFile( BytesIO(base64.b64decode(TEST_IMAGE)), field_name='tempfile', name='tempfile.png', content_type='image/png', size=len(TEST_IMAGE), charset='utf-8', ) def test_notification_admin(self): self.client.login(**self.contributor_credential) self.client.post( "/unggah/", data={"title":"Materi 1", "author":"Agas", "publisher":"Kelas SC", "release_year":"2000", "descriptions":"Deskripsi Materi 1", 'categories':"1", "cover":self.cover, "content":self.content, "yt_video_id":"jNwz4L9MGVY"} ) materi = Materi.objects.get(title="Materi 1") self.assertTrue(AdminNotification.objects.get(materi=materi.id))