Fakultas Ilmu Komputer UI
Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
PMPL
Class Project
DIGIPUS
Commits
8e7e67a9
Commit
8e7e67a9
authored
Nov 01, 2020
by
Selvy Fitriani
Browse files
Merge branch '1706039446/110' into 'master'
[
#110
] Guest Book For Non Registered User See merge request
!112
parents
defcd506
60a1898e
Pipeline
#60185
passed with stages
in 26 minutes and 38 seconds
Changes
10
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
app/forms.py
View file @
8e7e67a9
from
django
import
forms
from
app.models
import
Materi
,
Category
,
RatingContributor
from
app.models
import
Materi
,
Category
,
RatingContributor
,
GuestBook
from
authentication.models
import
User
import
datetime
def
year_choices
():
return
[(
r
,
r
)
for
r
in
range
(
2000
,
datetime
.
date
.
today
().
year
+
1
)]
return
[(
r
,
r
)
for
r
in
range
(
2000
,
datetime
.
date
.
today
().
year
+
1
)]
class
UploadMateriForm
(
forms
.
ModelForm
):
categories
=
forms
.
ModelMultipleChoiceField
(
queryset
=
Category
.
objects
.
all
(),
widget
=
forms
.
CheckboxSelectMultiple
(
attrs
=
{
'style'
:
'column-count:2'
}),
required
=
True
)
release_year
=
forms
.
TypedChoiceField
(
coerce
=
int
,
choices
=
year_choices
,
initial
=
datetime
.
date
.
today
().
year
)
yt_video_id
=
forms
.
CharField
(
label
=
"Youtube Video Id"
,
\
help_text
=
"This is not required.<br>
\
categories
=
forms
.
ModelMultipleChoiceField
(
queryset
=
Category
.
objects
.
all
(
),
widget
=
forms
.
CheckboxSelectMultiple
(
attrs
=
{
'style'
:
'column-count:2'
}),
required
=
True
)
release_year
=
forms
.
TypedChoiceField
(
coerce
=
int
,
choices
=
year_choices
,
initial
=
datetime
.
date
.
today
().
year
)
yt_video_id
=
forms
.
CharField
(
label
=
"Youtube Video Id"
,
help_text
=
"This is not required.<br>
\
Please insert only Youtube link videos! Take a note for the video id!<br>
\
Example : https://www.youtube.com/watch?v=DkJ-50GLi2I <br> has video id DkJ-50GLi2I"
,
required
=
False
)
...
...
@@ -29,14 +33,13 @@ class UploadMateriForm(forms.ModelForm):
field
.
widget
.
attrs
[
"class"
]
=
"form-control"
field
.
widget
.
attrs
[
"placeholder"
]
=
field
.
initial
field
.
initial
=
""
self
.
fields
[
'categories'
].
widget
.
attrs
.
update
({
'class'
:
"native"
})
self
.
fields
[
'categories'
].
widget
.
attrs
.
update
({
'class'
:
"native"
})
class
SuntingProfilForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
User
fields
=
[
"email"
,
"name"
,
"instansi"
,
"nik"
,
"alamat"
,
"nomor_telpon"
,
fields
=
[
"email"
,
"name"
,
"instansi"
,
"nik"
,
"alamat"
,
"nomor_telpon"
,
"profile_picture"
,
"linkedin"
,
"facebook"
,
"twitter"
,
"instagram"
,
"biography"
,
"is_subscribing_to_material_comments"
]
...
...
@@ -50,7 +53,6 @@ class SuntingProfilForm(forms.ModelForm):
if
any
(
self
.
errors
):
key
=
list
(
self
.
errors
)[
0
]
self
.
fields
[
key
].
widget
.
attrs
[
"autofocus"
]
=
""
self
.
fields
[
"email"
].
widget
.
attrs
[
"readonly"
]
=
True
...
...
@@ -61,14 +63,43 @@ class RatingContributorForm(forms.ModelForm):
fields
=
[
'score'
,
'user'
,
'contributor'
]
SCORE_CHOICE
=
(
(
''
,
'Select score'
),
(
'1'
,
'1'
),
# First one is the value of select option and second is the displayed value in option
# First one is the value of select option and second is the displayed value in option
(
'1'
,
'1'
),
(
'2'
,
'2'
),
(
'3'
,
'3'
),
(
'4'
,
'4'
),
(
'5'
,
'5'
),
)
widgets
=
{
'score'
:
forms
.
Select
(
choices
=
SCORE_CHOICE
,
attrs
=
{
'class'
:
'form-control'
,
'id'
:
'form-rating'
},),
'score'
:
forms
.
Select
(
choices
=
SCORE_CHOICE
,
attrs
=
{
'class'
:
'form-control'
,
'id'
:
'form-rating'
},),
'user'
:
forms
.
HiddenInput
(),
'contributor'
:
forms
.
HiddenInput
()
}
class
GuestBookForm
(
forms
.
models
.
ModelForm
):
class
Meta
:
model
=
GuestBook
fields
=
[
'name'
,
'job'
,
'gender'
]
gender_choices
=
(
(
'Male'
,
'Male'
),
(
'Female'
,
'Female'
)
)
widgets
=
{
'name'
:
forms
.
fields
.
TextInput
(
attrs
=
{
'placeholder'
:
'Input your name'
,
'class'
:
'form-control input-lg'
}),
'job'
:
forms
.
fields
.
TextInput
(
attrs
=
{
'placeholder'
:
'Input your job'
,
'class'
:
'form-control input-lg'
}),
'gender'
:
forms
.
fields
.
Select
(
choices
=
gender_choices
,
attrs
=
{
'class'
:
'form-control input-lg'
})
}
error_messages
=
{
'name'
:
{
'required'
:
'Name is required'
},
'job'
:
{
'required'
:
'Job is required'
},
'gender'
:
{
'required'
:
'Gender is required'
}
}
app/migrations/0029_guestbook.py
0 → 100644
View file @
8e7e67a9
# Generated by Django 3.1 on 2020-10-31 18:19
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'app'
,
'0028_adminnotification'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'GuestBook'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'name'
,
models
.
TextField
(
default
=
''
)),
(
'job'
,
models
.
TextField
(
default
=
''
)),
(
'gender'
,
models
.
CharField
(
default
=
'Male'
,
max_length
=
6
)),
],
),
]
app/migrations/00
29
_merge_20201101_021
7
.py
→
app/migrations/00
30
_merge_20201101_0
6
21.py
View file @
8e7e67a9
# Generated by Django 3.1 on 2020-10-31
19:17
# Generated by Django 3.1 on 2020-10-31
23:21
from
django.db
import
migrations
...
...
@@ -6,8 +6,8 @@ from django.db import migrations
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'app'
,
'0029_guestbook'
),
(
'app'
,
'0028_notifikasikontributor'
),
(
'app'
,
'0028_adminnotification'
),
]
operations
=
[
...
...
app/models.py
View file @
8e7e67a9
...
...
@@ -26,9 +26,11 @@ def get_random_color():
color
=
"%06x"
%
random
.
randint
(
0
,
0xFFFFFF
)
return
color
def
current_year
():
return
datetime
.
date
.
today
().
year
class
Category
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
20
)
description
=
models
.
TextField
(
blank
=
False
,
default
=
""
)
...
...
@@ -48,7 +50,7 @@ class MateriManager(models.Manager):
if
self
.
alive_only
:
return
SoftDeletionQuerySet
(
self
.
model
).
filter
(
deleted_at
=
None
)
return
SoftDeletionQuerySet
(
self
.
model
)
def
search
(
self
,
search_text
):
search_vector
=
None
for
field
,
weight
in
Materi
.
SEARCH_INDEX
:
...
...
@@ -75,18 +77,20 @@ class SoftDeletionQuerySet(models.query.QuerySet):
def
delete
(
self
):
return
super
(
SoftDeletionQuerySet
,
self
).
update
(
deleted_at
=
timezone
.
now
())
class
SoftDeleteModel
(
models
.
Model
):
deleted_at
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
)
all_objects
=
MateriManager
(
alive_only
=
False
)
class
Meta
:
abstract
=
True
def
soft_delete
(
self
):
self
.
deleted_at
=
timezone
.
now
()
self
.
save
()
class
Materi
(
SoftDeleteModel
):
cover
=
models
.
ImageField
()
content
=
models
.
FileField
()
...
...
@@ -96,8 +100,9 @@ class Materi(SoftDeleteModel):
publisher
=
models
.
CharField
(
max_length
=
30
,
default
=
"Penerbit"
)
release_year
=
models
.
IntegerField
(
default
=
current_year
)
pages
=
models
.
IntegerField
(
default
=
0
)
descriptions
=
models
.
TextField
(
default
=
"Deskripsi"
)
status
=
models
.
CharField
(
max_length
=
30
,
choices
=
VERIFICATION_STATUS
,
default
=
VERIFICATION_STATUS
[
0
][
0
])
descriptions
=
models
.
TextField
(
default
=
"Deskripsi"
)
status
=
models
.
CharField
(
max_length
=
30
,
choices
=
VERIFICATION_STATUS
,
default
=
VERIFICATION_STATUS
[
0
][
0
])
categories
=
models
.
ManyToManyField
(
Category
)
date_created
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
date_modified
=
models
.
DateTimeField
(
auto_now
=
True
)
...
...
@@ -117,7 +122,8 @@ class Materi(SoftDeleteModel):
def
save
(
self
,
*
args
,
**
kwargs
):
super
().
save
(
*
args
,
**
kwargs
)
search_index
=
{
field
:
weight
for
(
field
,
weight
)
in
Materi
.
SEARCH_INDEX
}
search_index
=
{
field
:
weight
for
(
field
,
weight
)
in
Materi
.
SEARCH_INDEX
}
if
"update_fields"
in
kwargs
:
is_search_index_updated
=
bool
(
set
(
search_index
.
keys
())
&
set
(
kwargs
[
"update_fields"
])
...
...
@@ -127,9 +133,11 @@ class Materi(SoftDeleteModel):
self
.
_search_vector
=
None
for
field
,
weight
in
search_index
.
items
():
if
self
.
_search_vector
is
None
:
self
.
_search_vector
=
search
.
SearchVector
(
field
,
weight
=
weight
)
self
.
_search_vector
=
search
.
SearchVector
(
field
,
weight
=
weight
)
else
:
self
.
_search_vector
+=
search
.
SearchVector
(
field
,
weight
=
weight
)
self
.
_search_vector
+=
search
.
SearchVector
(
field
,
weight
=
weight
)
self
.
save
(
update_fields
=
[
"_search_vector"
])
...
...
@@ -154,7 +162,7 @@ class Materi(SoftDeleteModel):
def
like_count
(
self
):
count
=
Like
.
objects
.
filter
(
materi
=
self
).
count
()
return
count
@
property
def
comment_count
(
self
):
count
=
Comment
.
objects
.
filter
(
materi
=
self
).
count
()
...
...
@@ -181,7 +189,7 @@ class Materi(SoftDeleteModel):
@
property
def
hot_score
(
self
):
view_score
=
math
.
log
(
max
(
self
.
view_count
,
1
),
10
)
time_score
=
self
.
seconds_since_earliest_materi
/
604800
# 1 week
time_score
=
self
.
seconds_since_earliest_materi
/
604800
# 1 week
return
round
(
view_score
+
time_score
,
7
)
@
property
...
...
@@ -197,7 +205,8 @@ class Comment(models.Model):
profile
=
models
.
CharField
(
max_length
=
100
,
default
=
get_random_color
)
comment
=
models
.
CharField
(
max_length
=
240
,
default
=
"comments"
)
materi
=
models
.
ForeignKey
(
Materi
,
models
.
SET_NULL
,
null
=
True
)
user
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
SET_NULL
,
blank
=
True
,
null
=
True
)
user
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
SET_NULL
,
blank
=
True
,
null
=
True
)
timestamp
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
def
__str__
(
self
):
...
...
@@ -207,18 +216,20 @@ class Comment(models.Model):
def
like_count
(
self
):
count
=
LikeComment
.
objects
.
filter
(
comment
=
self
).
count
()
return
count
@
property
def
dislike_count
(
self
):
count
=
DislikeComment
.
objects
.
filter
(
comment
=
self
).
count
()
return
count
class
Review
(
models
.
Model
):
username
=
models
.
CharField
(
max_length
=
100
)
profile
=
models
.
CharField
(
max_length
=
100
,
default
=
get_random_color
)
review
=
models
.
TextField
(
default
=
"review"
)
materi
=
models
.
ForeignKey
(
Materi
,
models
.
SET_NULL
,
null
=
True
)
user
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
SET_NULL
,
blank
=
True
,
null
=
True
)
user
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
SET_NULL
,
blank
=
True
,
null
=
True
)
timestamp
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
def
__str__
(
self
):
...
...
@@ -247,6 +258,7 @@ class ReqMaterial(models.Model):
title
=
models
.
CharField
(
max_length
=
100
)
timestamp
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
class
SubmitVisitor
(
models
.
Model
):
user_id
=
models
.
CharField
(
max_length
=
50
)
email
=
models
.
CharField
(
max_length
=
50
)
...
...
@@ -255,13 +267,16 @@ class SubmitVisitor(models.Model):
class
ViewStatistics
(
models
.
Model
):
materi
=
models
.
ForeignKey
(
Materi
,
models
.
SET_NULL
,
null
=
True
,
related_name
=
"baca"
)
materi
=
models
.
ForeignKey
(
Materi
,
models
.
SET_NULL
,
null
=
True
,
related_name
=
"baca"
)
timestamp
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
class
DownloadStatistics
(
models
.
Model
):
materi
=
models
.
ForeignKey
(
Materi
,
models
.
SET_NULL
,
null
=
True
,
related_name
=
"unduh"
)
downloader
=
models
.
ForeignKey
(
User
,
models
.
SET_NULL
,
blank
=
True
,
null
=
True
,
related_name
=
"riwayat_unduh"
)
materi
=
models
.
ForeignKey
(
Materi
,
models
.
SET_NULL
,
null
=
True
,
related_name
=
"unduh"
)
downloader
=
models
.
ForeignKey
(
User
,
models
.
SET_NULL
,
blank
=
True
,
null
=
True
,
related_name
=
"riwayat_unduh"
)
timestamp
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
...
...
@@ -302,27 +317,39 @@ class Rating(models.Model):
class
RatingContributor
(
models
.
Model
):
timestamp
=
models
.
DateTimeField
(
auto_now
=
True
)
score
=
models
.
PositiveIntegerField
(
validators
=
[
MinValueValidator
(
1
),
MaxValueValidator
(
5
)])
contributor
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
CASCADE
,
related_name
=
'contributor'
)
user
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
CASCADE
,
related_name
=
'user'
)
score
=
models
.
PositiveIntegerField
(
validators
=
[
MinValueValidator
(
1
),
MaxValueValidator
(
5
)])
contributor
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
CASCADE
,
related_name
=
'contributor'
)
user
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
CASCADE
,
related_name
=
'user'
)
def
save
(
self
,
force_insert
=
False
,
force_update
=
False
,
using
=
None
,
update_fields
=
None
):
if
1
<=
self
.
score
<=
5
:
super
().
save
(
force_insert
,
force_update
,
using
,
update_fields
)
else
:
raise
ValidationError
(
"Rating score must be integer between 1-5"
)
class
Meta
:
unique_together
=
[
"contributor"
,
"user"
]
class
LaporanMateri
(
models
.
Model
):
materi
=
models
.
ForeignKey
(
Materi
,
on_delete
=
models
.
CASCADE
,
max_length
=
120
)
materi
=
models
.
ForeignKey
(
Materi
,
on_delete
=
models
.
CASCADE
,
max_length
=
120
)
user
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
CASCADE
)
laporan
=
models
.
TextField
(
validators
=
[
MinValueValidator
(
30
),
MaxValueValidator
(
120
)],
default
=
""
)
laporan
=
models
.
TextField
(
validators
=
[
MinValueValidator
(
30
),
MaxValueValidator
(
120
)],
default
=
""
)
timestamp
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
is_rejected
=
models
.
BooleanField
(
default
=
False
)
class
GuestBook
(
models
.
Model
):
name
=
models
.
TextField
(
default
=
''
)
job
=
models
.
TextField
(
default
=
''
)
gender
=
models
.
CharField
(
max_length
=
6
,
default
=
"Male"
)
class
ReadLater
(
models
.
Model
):
materi
=
models
.
ForeignKey
(
Materi
,
on_delete
=
models
.
CASCADE
)
user
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
CASCADE
)
...
...
@@ -331,13 +358,16 @@ class ReadLater(models.Model):
class
Meta
:
unique_together
=
[
"materi"
,
"user"
]
class
NotifikasiKontributor
(
models
.
Model
):
materi
=
models
.
ForeignKey
(
Materi
,
on_delete
=
models
.
CASCADE
,
max_length
=
120
)
materi
=
models
.
ForeignKey
(
Materi
,
on_delete
=
models
.
CASCADE
,
max_length
=
120
)
user
=
models
.
ForeignKey
(
User
,
on_delete
=
models
.
CASCADE
)
feedback
=
models
.
CharField
(
max_length
=
20
,
default
=
""
)
def
__str__
(
self
):
return
"Status: {}"
.
format
(
self
.
feedback
)
class
AdminNotification
(
models
.
Model
):
materi
=
models
.
ForeignKey
(
Materi
,
on_delete
=
models
.
CASCADE
)
app/static/app/css/guest_book.css
0 → 100644
View file @
8e7e67a9
.form-style-6
{
font
:
95%
Arial
,
Helvetica
,
sans-serif
;
max-width
:
500px
;
margin
:
25px
auto
;
padding
:
16px
;
background
:
#F7F7F7
;
align-content
:
center
;
justify-content
:
center
;
}
.form-style-6
h1
{
background
:
#43D1AF
;
padding
:
20px
0
;
font-size
:
140%
;
font-weight
:
300
;
text-align
:
center
;
color
:
#fff
;
margin
:
-16px
-16px
16px
-16px
;
}
.form-style-6
input
[
type
=
"text"
],
.form-style-6
select
{
-webkit-transition
:
all
0.30s
ease-in-out
;
-moz-transition
:
all
0.30s
ease-in-out
;
-ms-transition
:
all
0.30s
ease-in-out
;
-o-transition
:
all
0.30s
ease-in-out
;
outline
:
none
;
box-sizing
:
border-box
;
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
width
:
100%
;
background
:
#fff
;
margin-bottom
:
4%
;
border
:
1px
solid
#ccc
;
color
:
#555
;
font
:
95%
Arial
,
Helvetica
,
sans-serif
;
}
.form-style-6
input
[
type
=
"text"
]
:focus
,
.form-style-6
textarea
:focus
,
.form-style-6
select
:focus
{
box-shadow
:
0
0
5px
#43D1AF
;
padding
:
3%
;
border
:
1px
solid
#43D1AF
;
}
.form-style-6
button
[
type
=
"submit"
]
{
box-sizing
:
border-box
;
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
width
:
100%
;
padding
:
3%
;
background
:
#1da1f2
;
border-bottom
:
2px
solid
#1da1f2
;
border-top-style
:
none
;
border-right-style
:
none
;
border-left-style
:
none
;
color
:
#fff
;
}
.form-style-6
input
[
type
=
"submit"
]
:hover
,
.form-style-6
input
[
type
=
"button"
]
:hover
{
background
:
#2EBC99
;
}
\ No newline at end of file
app/templates/guest_book.html
0 → 100644
View file @
8e7e67a9
{% extends 'base.html' %}
{% load static %}
{% block title %}Digipus Home{% endblock %}
{% block header %}
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<title>
Digipus Home
</title>
<meta
charset=
"UTF-8"
>
<meta
name=
"viewport"
content=
"width=device-width, inital-scale=1"
>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"{% static 'app/css/guest_book.css' %}"
>
{% endblock header %}
</head>
<!-- Page Content -->
{% block content %}
<div
class=
"form-group form-style-6"
id=
"myForm"
>
<form
method=
"POST"
>
<h3
style=
"text-align: center;"
>
Buku Tamu Non Anggota
</h3>
{% csrf_token %}
{{form}}
<button
type=
"submit"
class=
"btn btn-success"
>
Submit
</button>
</form>
</div>
{% endblock %}
</html>
\ No newline at end of file
app/tests.py
View file @
8e7e67a9
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
...
...
@@ -37,7 +45,7 @@ from django.test import (Client, RequestFactory, TestCase, TransactionTestCase,
from
django.urls
import
resolve
,
reverse
from
django.utils
import
timezone
from
app.forms
import
SuntingProfilForm
,
year_choices
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
...
...
@@ -45,7 +53,7 @@ from app.views import UploadMateriHTML, add_rating_materi
from
.models
import
(
Category
,
Comment
,
DislikeComment
,
DownloadStatistics
,
Like
,
LikeComment
,
Materi
,
Rating
,
RatingContributor
,
ReadLater
,
ReqMaterial
,
Review
,
ViewStatistics
,
AdminNotification
,
NotifikasiKontributor
)
ReadLater
,
ReqMaterial
,
Review
,
ViewStatistics
,
GuestBook
,
AdminNotification
,
NotifikasiKontributor
)
from
.services
import
DetailMateriService
from
.views
import
(
DaftarKatalog
,
DashboardKontributorView
,
DetailMateri
,
KatalogPerKontributorView
,
MateriFavorite
,
...
...
@@ -57,16 +65,6 @@ from .views import (DaftarKatalog, DashboardKontributorView, DetailMateri,
ERROR_403_MESSAGE
=
"Kamu harus login untuk mengakses halaman ini"
from
statistics
import
mean
import
requests
from
django.test
import
LiveServerTestCase
from
selenium
import
webdriver
from
selenium.common.exceptions
import
NoSuchElementException
from
selenium.webdriver.chrome.options
import
Options
from
selenium.webdriver.common.keys
import
Keys
from
webdriver_manager.chrome
import
ChromeDriverManager
class
DaftarKatalogTest
(
TestCase
):
def
test_daftar_katalog_url_exist
(
self
):
...
...
@@ -98,14 +96,14 @@ class DaftarKatalogSortingByJumlahUnduhTest(TestCase):
self
.
client
=
Client
()
self
.
contributor_credential
=
{
"email"
:
"kontributor@gov.id"
,
"password"
:
"passwordtest"
}
"email"
:
"kontributor@gov.id"
,
"password"
:
"passwordtest"
}
self
.
contributor_credential_2
=
{
"email"
:
"kontributor2@gov.id"
,
"password"
:
"passwordtest"
}
"email"
:
"kontributor2@gov.id"
,
"password"
:
"passwordtest"
}
self
.
contributor
=
get_user_model
().
objects
.
create_user
(
**
self
.
contributor_credential
,
name
=
"Kontributor 1"
,
is_contributor
=
True
)
...
...
@@ -133,6 +131,7 @@ class DaftarKatalogSortingByJumlahUnduhTest(TestCase):
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
=
{
...
...
@@ -176,7 +175,7 @@ class DaftarKatalogSortingByTerhangatTest(TestCase):
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]"
,
lst
=
[
int
(
id
)
for
id
in
re
.
findall
(
r
"Materi\s(\d+)[^\d]"
,
response
.
content
.
decode
())]
return
lst
...
...
@@ -188,7 +187,7 @@ class DaftarKatalogSortingByTerhangatTest(TestCase):
self
.
contributor
=
get_user_model
().
objects
.
create_user
(
name
=
"Kontributor"
,
is_contributor
=
True
,
**
self
.
contributor_credential
,
**
self
.
contributor_credential
,
)
self
.
client
=
Client
()
content
=
b
"Test file"
...
...
@@ -272,7 +271,7 @@ class DaftarKatalogSortingByTerhangatTest(TestCase):
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
())
...
...
@@ -329,9 +328,9 @@ class DaftarKatalogSortingByJumlahKomentarTest(TestCase):
self
.
client
=
Client
()
self
.
contributor_credential
=
{
"email"
:
"kontributor@gov.id"
,
"password"
:
"passwordtest"
}
"email"
:
"kontributor@gov.id"
,
"password"
:
"passwordtest"
}
self
.
contributor_credential_2
=
{
"email"
:
"kontributor2@gov.id"
,
...
...
@@ -359,25 +358,27 @@ class DaftarKatalogSortingByJumlahKomentarTest(TestCase):
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"
})
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"
}
"email"
:
"kontributor@gov.id"
,
"password"
:
"passwordtest"
}
self
.
contributor_credential_2
=
{
"email"
:
"kontributor2@gov.id"
,
"password"
:
"passwordtest"
}
"email"
:
"kontributor2@gov.id"
,
"password"
:
"passwordtest"
}
self
.
contributor
=
get_user_model
().
objects
.
create_user
(
**
self
.
contributor_credential
,
name
=
"Kontributor 1"
,
is_contributor
=
True
)
...
...
@@ -410,7 +411,8 @@ class DaftarKatalogPerKontributorTest(TestCase):
def
test_katalog_per_kontributor_using_katalog_per_kontributor_func
(
self
):
found
=
resolve
(
self
.
url
)
self
.
assertEqual
(
found
.
func
.
__name__
,
KatalogPerKontributorView
.
as_view
().
__name__
)
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)
...
...
@@ -425,20 +427,22 @@ class DaftarKatalogPerKontributorTest(TestCase):
jumlah
=
response
.
context_data
[
"materi_list"
]