Fakultas Ilmu Komputer UI

Commit 2c011362 authored by Izzan Fakhril Islam's avatar Izzan Fakhril Islam
Browse files

Tutorial 2 PMPL

parent 042001ef
stages:
- test
- unit-test
- deploy
- functional-test
before_script:
- apt-get install -f
......@@ -27,19 +28,12 @@ before_script:
- python manage.py runserver 8000 &
UnitTest:
stage: test
stage: unit-test
when: on_success
script:
- coverage run --include='tutorial_*/*' manage.py test -p "unit_test*.py"
- coverage report -m
FunctionalTest:
stage: test
when: on_success
script:
- coverage run --include='tutorial_*/*' manage.py test -p "functional_test*.py"
- coverage report -m
DeployToHeroku:
image: ruby:2.4
stage: deploy
......@@ -53,3 +47,10 @@ DeployToHeroku:
environment:
name: production
url: $HEROKU_APP_HOST
FunctionalTest:
stage: functional-test
when: on_success
script:
- coverage run --include='tutorial_*/*' manage.py test -p "functional_test*.py"
- coverage report -m
body {
min-height: 2000px;
}
.navbar-static-top {
margin-bottom: 19px;
}
/*Textarea not resizeable*/
textarea {
resize:none
}
body {
min-height: 2000px;
}
.navbar-static-top {
margin-bottom: 19px;
}
/*Textarea not resizeable*/
textarea {
resize:none
}
{"paths": {"admin/js/vendor/jquery/LICENSE-JQUERY.txt": "admin/js/vendor/jquery/LICENSE-JQUERY.a158210a2737.txt", "admin/js/vendor/jquery/jquery.min.js": "admin/js/vendor/jquery/jquery.min.33cabfa15c10.js", "admin/js/vendor/jquery/jquery.js": "admin/js/vendor/jquery/jquery.aacc43d6f308.js", "admin/js/vendor/xregexp/xregexp.min.js": "admin/js/vendor/xregexp/xregexp.min.c95393b8ca4d.js", "admin/js/vendor/xregexp/xregexp.js": "admin/js/vendor/xregexp/xregexp.1865b1cf5085.js", "admin/js/vendor/xregexp/LICENSE-XREGEXP.txt": "admin/js/vendor/xregexp/LICENSE-XREGEXP.d64cecf4f157.txt", "admin/js/admin/RelatedObjectLookups.js": "admin/js/admin/RelatedObjectLookups.d2bdb1018963.js", "admin/js/admin/DateTimeShortcuts.js": "admin/js/admin/DateTimeShortcuts.1536fb6bea1d.js", "admin/img/gis/move_vertex_on.svg": "admin/img/gis/move_vertex_on.0047eba25b67.svg", "admin/img/gis/move_vertex_off.svg": "admin/img/gis/move_vertex_off.7a23bf31ef8a.svg", "admin/css/widgets.css": "admin/css/widgets.5e372b41c483.css", "admin/css/login.css": "admin/css/login.a846c0e2ef65.css", "admin/css/dashboard.css": "admin/css/dashboard.7ac78187c567.css", "admin/css/forms.css": "admin/css/forms.2003a066ae02.css", "admin/css/fonts.css": "admin/css/fonts.494e4ec545c9.css", "admin/css/rtl.css": "admin/css/rtl.4c867197b256.css", "admin/css/base.css": "admin/css/base.6b517d0d5813.css", "admin/css/changelists.css": "admin/css/changelists.f6dc691f8d62.css", "admin/js/urlify.js": "admin/js/urlify.411bc3bb651c.js", "admin/js/inlines.min.js": "admin/js/inlines.min.d75b9ed03975.js", "admin/js/core.js": "admin/js/core.fd861d43f0f5.js", "admin/js/collapse.js": "admin/js/collapse.17d715df2104.js", "admin/js/actions.js": "admin/js/actions.32861b6cbdf9.js", "admin/js/prepopulate.js": "admin/js/prepopulate.ff9208865444.js", "admin/js/cancel.js": "admin/js/cancel.1d69cba4b4bf.js", "admin/js/inlines.js": "admin/js/inlines.eda404ee376d.js", "admin/js/change_form.js": "admin/js/change_form.9e85003a1a38.js", "admin/js/SelectFilter2.js": "admin/js/SelectFilter2.17009b6d4428.js", "admin/js/jquery.init.js": "admin/js/jquery.init.95b62fa19378.js", "admin/js/popup_response.js": "admin/js/popup_response.6ce3197f8fc8.js", "admin/js/SelectBox.js": "admin/js/SelectBox.b49f008d186b.js", "admin/js/actions.min.js": "admin/js/actions.min.f51f04edab28.js", "admin/js/calendar.js": "admin/js/calendar.9ac94d055fbd.js", "admin/js/timeparse.js": "admin/js/timeparse.51258861a46a.js", "admin/js/prepopulate.min.js": "admin/js/prepopulate.min.f4057ebb9b62.js", "admin/js/collapse.min.js": "admin/js/collapse.min.dc930adb2821.js", "admin/js/prepopulate_init.js": "admin/js/prepopulate_init.0d3b53c37074.js", "admin/img/search.svg": "admin/img/search.7cf54ff789c6.svg", "admin/img/icon-calendar.svg": "admin/img/icon-calendar.ac7aea671bea.svg", "admin/img/icon-clock.svg": "admin/img/icon-clock.e1d4dfac3f2b.svg", "admin/img/icon-no.svg": "admin/img/icon-no.439e821418cd.svg", "admin/img/tooltag-add.svg": "admin/img/tooltag-add.e59d620a9742.svg", "admin/img/inline-delete.svg": "admin/img/inline-delete.fec1b761f254.svg", "admin/img/LICENSE": "admin/img/LICENSE.2c54f4e1ca1c", "admin/img/icon-changelink.svg": "admin/img/icon-changelink.18d2fd706348.svg", "admin/img/icon-unknown.svg": "admin/img/icon-unknown.a18cb4398978.svg", "admin/img/sorting-icons.svg": "admin/img/sorting-icons.3a097b59f104.svg", "admin/img/icon-yes.svg": "admin/img/icon-yes.d2f9f035226a.svg", "admin/img/icon-addlink.svg": "admin/img/icon-addlink.d519b3bab011.svg", "admin/img/icon-unknown-alt.svg": "admin/img/icon-unknown-alt.81536e128bb6.svg", "admin/img/icon-deletelink.svg": "admin/img/icon-deletelink.564ef9dc3854.svg", "admin/img/README.txt": "admin/img/README.837277fa1908.txt", "admin/img/selector-icons.svg": "admin/img/selector-icons.b4555096cea2.svg", "admin/img/calendar-icons.svg": "admin/img/calendar-icons.39b290681a8b.svg", "admin/img/tooltag-arrowright.svg": "admin/img/tooltag-arrowright.bbfb788a849e.svg", "admin/img/icon-alert.svg": "admin/img/icon-alert.034cc7d8a67f.svg", "admin/fonts/Roboto-Light-webfont.woff": "admin/fonts/Roboto-Light-webfont.b446c2399bb6.woff", "admin/fonts/Roboto-Bold-webfont.woff": "admin/fonts/Roboto-Bold-webfont.2ad99072841e.woff", "admin/fonts/Roboto-Regular-webfont.woff": "admin/fonts/Roboto-Regular-webfont.ec39515ae8c6.woff", "admin/fonts/README.txt": "admin/fonts/README.2c3d0bcdede2.txt", "admin/fonts/LICENSE.txt": "admin/fonts/LICENSE.d273d63619c9.txt"}, "version": "1.0"}
\ No newline at end of file
{"paths": {"admin/js/vendor/jquery/LICENSE-JQUERY.txt": "admin/js/vendor/jquery/LICENSE-JQUERY.a158210a2737.txt", "admin/js/vendor/jquery/jquery.min.js": "admin/js/vendor/jquery/jquery.min.33cabfa15c10.js", "admin/js/vendor/jquery/jquery.js": "admin/js/vendor/jquery/jquery.aacc43d6f308.js", "admin/js/vendor/xregexp/xregexp.min.js": "admin/js/vendor/xregexp/xregexp.min.c95393b8ca4d.js", "admin/js/vendor/xregexp/xregexp.js": "admin/js/vendor/xregexp/xregexp.1865b1cf5085.js", "admin/js/vendor/xregexp/LICENSE-XREGEXP.txt": "admin/js/vendor/xregexp/LICENSE-XREGEXP.d64cecf4f157.txt", "admin/js/admin/RelatedObjectLookups.js": "admin/js/admin/RelatedObjectLookups.d2bdb1018963.js", "admin/js/admin/DateTimeShortcuts.js": "admin/js/admin/DateTimeShortcuts.1536fb6bea1d.js", "admin/img/gis/move_vertex_on.svg": "admin/img/gis/move_vertex_on.0047eba25b67.svg", "admin/img/gis/move_vertex_off.svg": "admin/img/gis/move_vertex_off.7a23bf31ef8a.svg", "admin/css/widgets.css": "admin/css/widgets.5e372b41c483.css", "admin/css/login.css": "admin/css/login.a846c0e2ef65.css", "admin/css/dashboard.css": "admin/css/dashboard.7ac78187c567.css", "admin/css/forms.css": "admin/css/forms.2003a066ae02.css", "admin/css/fonts.css": "admin/css/fonts.494e4ec545c9.css", "admin/css/rtl.css": "admin/css/rtl.4c867197b256.css", "admin/css/base.css": "admin/css/base.6b517d0d5813.css", "admin/css/changelists.css": "admin/css/changelists.f6dc691f8d62.css", "admin/js/urlify.js": "admin/js/urlify.411bc3bb651c.js", "admin/js/inlines.min.js": "admin/js/inlines.min.d75b9ed03975.js", "admin/js/core.js": "admin/js/core.fd861d43f0f5.js", "admin/js/collapse.js": "admin/js/collapse.17d715df2104.js", "admin/js/actions.js": "admin/js/actions.32861b6cbdf9.js", "admin/js/prepopulate.js": "admin/js/prepopulate.ff9208865444.js", "admin/js/cancel.js": "admin/js/cancel.1d69cba4b4bf.js", "admin/js/inlines.js": "admin/js/inlines.eda404ee376d.js", "admin/js/change_form.js": "admin/js/change_form.9e85003a1a38.js", "admin/js/SelectFilter2.js": "admin/js/SelectFilter2.17009b6d4428.js", "admin/js/jquery.init.js": "admin/js/jquery.init.95b62fa19378.js", "admin/js/popup_response.js": "admin/js/popup_response.6ce3197f8fc8.js", "admin/js/SelectBox.js": "admin/js/SelectBox.b49f008d186b.js", "admin/js/actions.min.js": "admin/js/actions.min.f51f04edab28.js", "admin/js/calendar.js": "admin/js/calendar.9ac94d055fbd.js", "admin/js/timeparse.js": "admin/js/timeparse.51258861a46a.js", "admin/js/prepopulate.min.js": "admin/js/prepopulate.min.f4057ebb9b62.js", "admin/js/collapse.min.js": "admin/js/collapse.min.dc930adb2821.js", "admin/js/prepopulate_init.js": "admin/js/prepopulate_init.0d3b53c37074.js", "admin/img/search.svg": "admin/img/search.7cf54ff789c6.svg", "admin/img/icon-calendar.svg": "admin/img/icon-calendar.ac7aea671bea.svg", "admin/img/icon-clock.svg": "admin/img/icon-clock.e1d4dfac3f2b.svg", "admin/img/icon-no.svg": "admin/img/icon-no.439e821418cd.svg", "admin/img/tooltag-add.svg": "admin/img/tooltag-add.e59d620a9742.svg", "admin/img/inline-delete.svg": "admin/img/inline-delete.fec1b761f254.svg", "admin/img/LICENSE": "admin/img/LICENSE.2c54f4e1ca1c", "admin/img/icon-changelink.svg": "admin/img/icon-changelink.18d2fd706348.svg", "admin/img/icon-unknown.svg": "admin/img/icon-unknown.a18cb4398978.svg", "admin/img/sorting-icons.svg": "admin/img/sorting-icons.3a097b59f104.svg", "admin/img/icon-yes.svg": "admin/img/icon-yes.d2f9f035226a.svg", "admin/img/icon-addlink.svg": "admin/img/icon-addlink.d519b3bab011.svg", "admin/img/icon-unknown-alt.svg": "admin/img/icon-unknown-alt.81536e128bb6.svg", "admin/img/icon-deletelink.svg": "admin/img/icon-deletelink.564ef9dc3854.svg", "admin/img/README.txt": "admin/img/README.837277fa1908.txt", "admin/img/selector-icons.svg": "admin/img/selector-icons.b4555096cea2.svg", "admin/img/calendar-icons.svg": "admin/img/calendar-icons.39b290681a8b.svg", "admin/img/tooltag-arrowright.svg": "admin/img/tooltag-arrowright.bbfb788a849e.svg", "admin/img/icon-alert.svg": "admin/img/icon-alert.034cc7d8a67f.svg", "admin/fonts/Roboto-Light-webfont.woff": "admin/fonts/Roboto-Light-webfont.b446c2399bb6.woff", "admin/fonts/Roboto-Bold-webfont.woff": "admin/fonts/Roboto-Bold-webfont.2ad99072841e.woff", "admin/fonts/Roboto-Regular-webfont.woff": "admin/fonts/Roboto-Regular-webfont.ec39515ae8c6.woff", "admin/fonts/README.txt": "admin/fonts/README.2c3d0bcdede2.txt", "admin/fonts/LICENSE.txt": "admin/fonts/LICENSE.d273d63619c9.txt", "css/tutorial_2.css": "css/tutorial_2.366cb34e0003.css"}, "version": "1.0"}
\ No newline at end of file
......@@ -17,8 +17,10 @@ from django.conf.urls import url, include
from django.contrib import admin
from django.views.generic.base import RedirectView
import tutorial_1.urls as tutorial_1
import tutorial_2.urls as tutorial_2
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^tutorial-1/', include(tutorial_1, namespace='tutorial-1')),
url(r'^tutorial-2/', include(tutorial_2, namespace='tutorial-2')),
]
import os
from django.test import TestCase
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
GITLAB_ENV = os.environ.get("HEROKU_APP_HOST") != None
class Tutorial2FunctionalTest(TestCase):
def setUp(self):
chrome_options = Options()
chrome_options.add_argument('--dns-prefatch-disable')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
self.selenium = webdriver.Chrome('./chromedriver', chrome_options=chrome_options)
self.localhost = "http://127.0.0.1:8000/tutorial-2/"
self.cases = [
(5, "oh, tidak"),
(2, "sibuk tapi santai"),
(0, "yey, waktunya berlibur"),
]
print("GITLAB ENV:", GITLAB_ENV)
if GITLAB_ENV:
self.localhost = "https://pmpl-izzan.herokuapp.com/tutorial-2/"
super(Tutorial2FunctionalTest, self).setUp()
def tearDown(self):
self.selenium.quit()
super(Tutorial2FunctionalTest, self).tearDown()
def test_find_name(self):
selenium = self.selenium
selenium.get(self.localhost)
self.assertIn('Izzan Fakhril Islam', selenium.page_source)
def test_input_todo_item(self):
selenium = self.selenium
selenium.get(self.localhost)
todo_date = selenium.find_element_by_id('todo_date')
todo_date.send_keys('23052019')
todo_date.send_keys(Keys.TAB)
todo_date.send_keys('1245')
todo_text = selenium.find_element_by_id('activity')
todo_text.send_keys('Dummy')
selenium.find_element_by_id('todo_submit').click()
self.assertIn('Dummy', selenium.page_source)
def test_input_todo_commentary_item(self):
print("LOCALHOST:", self.localhost)
selenium = self.selenium
selenium.get(self.localhost)
todo_date = selenium.find_element_by_id('comment_date')
todo_date.send_keys('23122019')
todo_comment = selenium.find_element_by_id('comment')
todo_comment.send_keys('Dummy comment')
selenium.find_element_by_id('comment_submit').click()
self.assertIn('Dummy comment', selenium.page_source)
def test_input_todo_on_the_same_date_and_generate_comment(self):
selenium = self.selenium
selenium.get(self.localhost)
date = 24
month_and_year = '112019'
for n, comment in self.cases:
time = 1045
for i in range(n):
todo_date = selenium.find_element_by_id('todo_date')
todo_date.send_keys(str(date) + month_and_year)
todo_date.send_keys(Keys.TAB)
todo_date.send_keys(str(time))
todo_text = selenium.find_element_by_id('activity')
todo_text.send_keys('Dummy Activity' + str(n))
selenium.find_element_by_id('todo_submit').click()
time += 1
todo_date = selenium.find_element_by_id('comment_date')
todo_date.send_keys(str(date) + month_and_year)
todo_comment = selenium.find_element_by_id('comment')
todo_comment.send_keys(comment)
selenium.find_element_by_id('comment_submit').click()
self.assertIn(comment, selenium.page_source)
date += 1
# -*- coding: utf-8 -*-
# Generated by Django 1.11.17 on 2019-09-23 12:42
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='TodoList',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField()),
('todo_list', models.TextField(max_length=100)),
],
),
migrations.CreateModel(
name='TodoListCommentary',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField()),
('comment', models.TextField(max_length=100)),
],
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11.17 on 2019-09-24 06:09
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tutorial_2', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='todolistcommentary',
name='date',
field=models.DateField(),
),
]
from django.db import models
# Create your models here.
class TodoList(models.Model):
date = models.DateTimeField()
todo_list = models.TextField(max_length=100)
def __str__(self):
return "Todo at %s: %s" % (self.date.timestamp(), self.todo_list)
class TodoListCommentary(models.Model):
date = models.DateField()
comment = models.TextField(max_length=100)
def __str__(self):
return "Commentary at %s: %s" % (self.date.__str__, self.comment)
body {
min-height: 2000px;
}
.navbar-static-top {
margin-bottom: 19px;
}
/*Textarea not resizeable*/
textarea {
resize:none
}
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="description" content="Tutorial 2 PMPL">
<meta name="author" content="{{ author }}">
<!-- bootstrap csss -->
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<title>
{% block title %} Tutorial 2 PMPL by {{ author }} - {{ npm }}{% endblock %}
</title>
</head>
<style>
@import url(https://fonts.googleapis.com/css?family=Roboto|Roboto+Slab);
.container, .footer-down, .header-up{
font-family: "Roboto", "sans-serif";
font-weight: normal;
}
</style>
<body style="background-color: darkseagreen">
<header class="header-up">
{% include "tutorial_2/../partials/header.html" %}
</header>
<content>
<div class="container">
{% block content %}
{% endblock %}
</div>
</content>
<footer class="footer-down">
<!-- TODO Block Footer dan include footer.html -->
{% block footer %}
{% include "tutorial_2/../partials/footer.html" %}
{% endblock %}
</footer>
<!-- Jquery n Bootstrap Script -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="application/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
<p align="center">&copy; {{ author }}</p>
<!-- Fixed navbar -->
<style type = text/css>
.navbar-static-top{
background-color: darkgray;
font-size: 17px;
}
.navbar-brand{
font-size: 17px;
}
</style>
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{% url 'tutorial-2:index' %}" style="color: black">Tutorial 2 PMPL</a>
</div>
</div>
</nav>
{% extends "tutorial_2/../layout/base.html" %}
{% block content %}
<style>
.form-control {
@import url(https://fonts.googleapis.com/css?family=Droid+Sans+Mono);
margin-top: 3px;
margin-bottom: 3px;
font-family: "Droid Sans Mono";
}
table {
text-align: left;
padding: 8px;
width: 100%;
}
</style>
<h1 align="center" style="font-weight: bold">{{ author }}'s Todo List</h1>
<br><br>
<div class="row">
<div class="col-md-6 col-xs-6">
<h4>Todo List Table</h4>
<br>
<table>
<tr>
<th><h5><b>Date/Time</b></h5></th>
<th><h5><b>Todo</b></h5></th>
</tr>
{% for todos in todos_dict %}
<tr>
<td>{{ todos.date }}</td>
<td>{{ todos.todo_list }}</td>
</tr>
{% endfor %}
</table>
<br>
<h4>Daily Todo List Comments</h4>
<br>
<table>
<tr>
<th><h5><b>Date</b></h5></th>
<th><h5><b>Comment</b></h5></th>
</tr>
{% for commentary in todos_commentary_dict %}
<tr>
<td>{{ commentary.date }}</td>
<td>{{ commentary.comment }}</td>
</tr>
{% endfor %}
</table>
<br>
</div>
<div class="col-md-6 col-xs-6">
<h4><b>Add Todo</b></h4>
<form method="POST" action="{% url 'tutorial-2:add_todo' %}">
{% csrf_token %}
<table>
<tr>
<td>
Date/Time
</td>
<td>
<input type="datetime-local" name="date" id="todo_date" required="required" size="27"/>
</td>
</tr>
<tr>
<td>
Todo
</td>
<td>
<input type="text" name="activity" id="activity" required="required" size="27">
</td>
</tr>
</table>
<br>
<button type="submit" id="todo_submit" class="button btn-success">Submit</button>
</form>
<br>
<div class="errornote">
<p style="color: black; font-family: 'Roboto Slab'">{{ error_msg }}</p>
</div>
<h4><b>Add Daily Todo List Comment</b></h4>
<form method="POST" action="{% url 'tutorial-2:add_todo_commentary' %}">
{% csrf_token %}
<table>
<tr>
<td>
Date
</td>
<td>
<input type="date" name="date" id="comment_date" required="required" size="27"/>
</td>
</tr>
<tr>
<td>
Todo List Comment
</td>
<td>
<input type="text" name="comment" id="comment" required="required" size="27">
</td>
</tr>
</table>
<br>
<button type="submit" id="comment_submit" class="button btn-success">Submit</button>
</form>
<br>
<div class="errornote">
<p style="color: black; font-family: 'Roboto Slab'">{{ commentary_error_msg }}</p>
</div>
</div>
</div>
{% endblock %}
from django.test import TestCase
from django.test import Client
from .views import index
from .models import TodoListCommentary, TodoList
from django.http import HttpRequest
from django.utils import timezone
# Create your tests here.
DUMMY_TODO_ITEM = "Dummy todo item"
DUMMY_TODO_COMMENTARY_ITEM = "Dummy todo commentary item"
class Tutorial2UnitTest(TestCase):
def test_true(self):
self.assertTrue(1 + 1, 2)
def test_page_rendered_successfully(self):
response = Client().get('/tutorial-2/')
self.assertEqual(response.status_code, 200)
def test_name_in_page(self):
request = HttpRequest()
response = index(request)
html_response = response.content.decode('utf8')
self.assertIn('Izzan Fakhril Islam', html_response)
def test_todo_table_rendered_successfully(self):
request = HttpRequest()
response = index(request)
html_response = response.content.decode('utf8')
self.assertIn('<th><h5><b>Todo</b></h5></th>', html_response)
def test_todo_commentary_table_rendered_successfully(self):
request = HttpRequest()
response = index(request)
html_response = response.content.decode('utf8')
self.assertIn('<th><h5><b>Comment</b></h5></th>', html_response)
def test_add_todo_item_via_model(self):
TodoList.objects.create(
date=timezone.now(),
todo_list=DUMMY_TODO_ITEM
)
todo_count = TodoList.objects.all().count()
self.assertEqual(todo_count, 1)
def test_add_todo_commentary_item_via_model(self):
TodoListCommentary.objects.create(
date=timezone.now(),
comment=DUMMY_TODO_COMMENTARY_ITEM
)
todo_commentary_count = TodoListCommentary.objects.all().count()
self.assertEqual(todo_commentary_count, 1)
def test_POST_request_create_todo(self):
self.client.post(
'/tutorial-2/add_todo/',
data={
'date': '2019-09-12T15:15',
'activity': DUMMY_TODO_ITEM
}
)
todo_count = TodoList.objects.all().count()
page_response = self.client.get('/tutorial-2/')
html_response = page_response.content.decode('utf8')
self.assertEqual(todo_count, 1)
self.assertIn(DUMMY_TODO_ITEM, html_response)
def test_POST_request_create_todo_commentary(self):
self.client.post(
'/tutorial-2/add_todo_commentary/',
data={
'date': '2019-09-12',
'comment': DUMMY_TODO_COMMENTARY_ITEM
}
)
todo_comment_count = TodoListCommentary.objects.all().count()
page_response = self.client.get('/tutorial-2/')
html_response = page_response.content.decode('utf8')
self.assertEqual(todo_comment_count, 1)
self.assertIn(DUMMY_TODO_COMMENTARY_ITEM, html_response)
from django.conf.urls import url
from .views import index, add_todo, add_todo_commentary
urlpatterns = [
url(r'^$', index, name='index'),
url(r'add_todo/$', add_todo, name='add_todo'),
url(r'add_todo_commentary/$', add_todo_commentary, name='add_todo_commentary')
]
from django.shortcuts import render
from django.shortcuts import render, redirect
from .models import TodoList, TodoListCommentary
from datetime import datetime
from django.http import HttpResponseRedirect
from django.urls import reverse
import pytz
# Create your views here.
todo = {}
todo_commentary = {}
HTML_FILE = "tutorial_2.html"
URL = "/tutorial-2/"
response = {
'author': 'Izzan Fakhril Islam',
'npm': '1606875806',
}
def index(request):
todo_dict = TodoList.objects.all().values()
todo_commentary_dict = TodoListCommentary.objects.all().values()
response['todos_dict'] = convert_queryset_into_json(todo_dict)
response['todos_commentary_dict'] = convert_queryset_into_json(todo_commentary_dict)
return render(request, HTML_FILE, response)
def add_todo(request):