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'.*(