Fakultas Ilmu Komputer UI

Commit 4e075d2d authored by Raden Fikri Ihza Dwi Nanda's avatar Raden Fikri Ihza Dwi Nanda
Browse files

Finish UAS take home

parent ac8c4c09
# Created by https://www.gitignore.io/api/python,intellij+iml
### Intellij+iml ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Intellij+iml Patch ###
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
*.iml
modules.xml
.idea/misc.xml
*.ipr
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
media/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
# End of https://www.gitignore.io/api/python,intellij+iml
db.sqlite3
geckodriver.log
virtualenv
env
__pycache__
*.pyc
/static
.static/
chromedriver
\ No newline at end of file
......@@ -13,7 +13,9 @@ Test:
- python3 manage.py collectstatic --no-input
script:
# - python3 manage.py test lists
- python3 manage.py test accounts
- coverage run manage.py test lists accounts
- coverage report -m --omit='superlists/settings.py,manage.py'
- python3 manage.py test lists accounts
tags:
- test
......
......@@ -33,49 +33,11 @@ class FunctionalTest(StaticLiveServerTestCase):
def tearDown(self):
self.browser.quit()
def wait_for_row_in_list_table(self, row_text):
start_time = time.time()
while True:
try:
table = self.browser.find_element_by_id('id_list_table')
rows = table.find_elements_by_tag_name('tr')
self.assertIn(row_text, [row.text for row in rows])
return
except (AssertionError, WebDriverException) as e:
if time.time() - start_time > MAX_WAIT:
raise e
time.sleep(0.5)
def wait_for(self, fn):
start_time = time.time()
while True:
try:
return fn()
except (AssertionError, WebDriverException) as e:
if time.time() - start_time > MAX_WAIT:
raise e
time.sleep(0.5)
def wait_to_be_logged_in(self, email):
self.wait_for(
lambda: self.browser.find_element_by_link_text('Log out')
)
navbar = self.browser.find_element_by_css_selector('.navbar')
self.assertIn(email, navbar.text)
def wait_to_be_logged_out(self, email):
self.wait_for(
lambda: self.browser.find_element_by_name('email')
)
navbar = self.browser.find_element_by_css_selector('.navbar')
self.assertNotIn(email, navbar.text)
@wait
def wait_for_row_in_list_table(self, row_text):
table = self.browser.find_element_by_id('id_list_table')
rows = table.find_elements_by_tag_name('tr')
rows = table.find_elements_by_tag_name('p')
self.assertIn(row_text, [row.text for row in rows])
@wait
......@@ -88,6 +50,12 @@ class FunctionalTest(StaticLiveServerTestCase):
navbar = self.browser.find_element_by_css_selector('.navbar')
self.assertNotIn(email, navbar.text)
@wait
def wait_for_row_not_in_list_table(self, row_text):
table = self.browser.find_element_by_id('id_list_table')
rows = table.find_elements_by_tag_name('p')
self.assertNotIn(row_text, [row.text for row in rows])
@wait
def wait_for(self, fn):
return fn()
from .base import FunctionalTest
from selenium import webdriver
class WebOwnerTest(FunctionalTest):
def test_display_author_name(self):
self.browser.get(self.live_server_url)
header_text = self.browser.find_element_by_id('header_text').text
self.assertIn('Raden Fikri Ihza Dwi Nanda', header_text)
footer_text = self.browser.find_element_by_id('footer_text').text
self.assertIn('Raden Fikri Ihza Dwi Nanda', footer_text)
\ No newline at end of file
......@@ -83,3 +83,40 @@ class NewVisitorTest(FunctionalTest):
page_text = self.browser.find_element_by_tag_name('body').text
self.assertNotIn('Buy peacock feathers', page_text)
self.assertIn('Buy milk', page_text)
def test_user_can_delete_item_created(self):
# Edith starts a new to-do list
self.browser.get(self.live_server_url)
inputbox = self.browser.find_element_by_id('id_new_item')
inputbox.send_keys('Buy peacock feathers')
inputbox.send_keys(Keys.ENTER)
# Now he has one item created
self.wait_for_row_in_list_table('1: Buy peacock feathers')
# He wants to delete this item
# He notices there's a delete button on screen, he clicks it
delete_button = self.browser.find_elements_by_class_name('delete-list-btn')[0]
delete_button.click()
# Now the item is gone
self.wait_for_row_not_in_list_table('1: Buy peacock feathers')
# Now he wants to add some new items
inputbox = self.browser.find_element_by_id('id_new_item')
inputbox.send_keys('Buy peacock feathers')
inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1: Buy peacock feathers')
inputbox = self.browser.find_element_by_id('id_new_item')
inputbox.send_keys('Buy duck feathers')
inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('2: Buy duck feathers')
# Now he wants to specifically delete first item
delete_button = self.browser.find_elements_by_class_name('delete-list-btn')[0]
delete_button.click()
# Now the first item is gone and there's only previously second item
self.wait_for_row_in_list_table('1: Buy duck feathers')
page_text = self.browser.find_element_by_tag_name('body').text
self.assertNotIn('Buy peacock feathers', page_text)
\ No newline at end of file
......@@ -14,6 +14,9 @@
<body>
<div class="header">
<p id="header_text">Raden Fikri Ihza Dwi Nanda</p>
</div>
<div class="container">
<nav class="navbar navbar-default" role="navigation">
......@@ -78,6 +81,9 @@
</div>
</div>
<div class="footer">
<p id="footer_text">Raden Fikri Ihza Dwi Nanda</p>
</div>
</body>
</html>
\ No newline at end of file
......@@ -7,10 +7,20 @@
{% block table %}
<table id="id_list_table" class="table">
{% for item in list.item_set.all %}
<tr><td>{{ forloop.counter }}: {{ item.text }}</td></tr>
<tr><td>
<p>{{ forloop.counter }}: {{ item.text }} </p>
<button onclick="deleteItem({{ list.id }}, {{ item.id }})"
type="button" class="btn btn-primary btn-sm delete-list-btn">Remove</button>
</td></tr>
{% endfor %}
</table>
<div class ="has-error">{{error}}</div>
<p>{{ comment }}</p>
<script type="text/javascript">
function deleteItem(list_id, item_id) {
var url = "/lists/delete_item";
document.location.href = url + "/" + list_id + "/" + item_id;
}
</script>
{% endblock %}
\ No newline at end of file
......@@ -120,4 +120,17 @@ class NewItemTest(TestCase):
)
self.assertRedirects(response, f'/lists/{correct_list.id}/')
\ No newline at end of file
class DeleteItemTest(TestCase):
def test_can_delete_todo_list_item(self):
new_list = List.objects.create()
self.client.post(
f'/lists/{new_list.id}/add_item',
data={'item_text': 'A new item for an existing list'}
)
new_item = Item.objects.first()
self.client.get(f'/lists/delete_item/{new_list.id}/{new_item.id}')
self.assertEqual(Item.objects.count(), 0)
\ No newline at end of file
......@@ -20,4 +20,5 @@ urlpatterns = [
url(r'^new$', views.new_list, name='new_list'),
url(r'^(\d+)/$', views.view_list, name='view_list'),
url(r'^(\d+)/add_item$', views.add_item, name='add_item'),
url(r'^delete_item/(\d+)/(\d+)$', views.delete_item, name='delete_item'),
]
......@@ -33,3 +33,9 @@ def add_item(request, list_id):
return redirect(f'/lists/{list_.id}/')
else:
return render(request, 'list.html', {'list': list_,'error':"You can't have an empty list item"})
def delete_item(request, list_id, item_id):
list_ = List.objects.get(id=list_id)
item = Item.objects.get(list=list_, id=item_id)
item.delete()
return redirect(f'/lists/{list_.id}/')
\ No newline at end of file
......@@ -33,7 +33,7 @@ ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
#'django.contrib.admin',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment