diff --git a/db.sqlite3 b/db.sqlite3 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8862305decc3f4831038bb0a36c04746229841b9 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/functional_tests.py b/functional_tests.py index 0c4492dbfcf3265559396a8461bb4cf1fe6daac2..2f0f4fbc2c853a09c75342b5d922925157261804 100644 --- a/functional_tests.py +++ b/functional_tests.py @@ -1,4 +1,6 @@ from selenium import webdriver +from selenium.webdriver.common.keys import Keys +import time import unittest class NewVisitorTest(unittest.TestCase): @@ -9,18 +11,69 @@ class NewVisitorTest(unittest.TestCase): def tearDown(self): self.browser.quit() - def test_can_start_a_list_and_retrieve_it_later(self): - # Edith has heard about a cool new online to-do app. She goes - # to check out its homepage + def check_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') + self.assertIn(row_text, [row.text for row in rows]) + + # She is invited to enter a to-do item straight away + def test_can_start_a_list_and_retrieve_it_later(self): self.browser.get('http://localhost:8000/homepage') # She notices the page title and header mention to-do lists - body_text = self.browser.find_element_by_tag_name('body').text - self.assertIn('Tutorial PMPL', self.browser.title) - self.assertIn('Kevin Albert Simanjuntak', body_text) - self.assertIn('NPM', body_text) + self.assertIn('To-Do', self.browser.title) + header_text = self.browser.find_element_by_tag_name('h1').text + self.assertIn('To-Do', header_text) # She is invited to enter a to-do item straight away - + inputbox = self.browser.find_element_by_id('id_new_item') + self.assertEqual( + inputbox.get_attribute('placeholder'), + 'Enter a to-do item' + ) + inputbox.send_keys('Buy peacock feathers') + inputbox.send_keys(Keys.ENTER) + time.sleep(5) + self.check_comment_based_on_total_list() + inputbox = self.browser.find_element_by_id('id_new_item') + inputbox.send_keys('Use peacock feathers to make a fly') + inputbox.send_keys(Keys.ENTER) + time.sleep(5) + self.check_comment_based_on_total_list() + inputbox = self.browser.find_element_by_id('id_new_item') + inputbox.send_keys('Buy peacock') + inputbox.send_keys(Keys.ENTER) + time.sleep(5) + self.check_comment_based_on_total_list() + inputbox = self.browser.find_element_by_id('id_new_item') + inputbox.send_keys('Buy feathers') + inputbox.send_keys(Keys.ENTER) + time.sleep(5) + self.check_comment_based_on_total_list() + inputbox = self.browser.find_element_by_id('id_new_item') + inputbox.send_keys('feathers') + inputbox.send_keys(Keys.ENTER) + time.sleep(5) + self.check_comment_based_on_total_list() + inputbox = self.browser.find_element_by_id('id_new_item') + inputbox.send_keys('Buy') + inputbox.send_keys(Keys.ENTER) + time.sleep(5) + self.check_comment_based_on_total_list() + self.check_for_row_in_list_table('1: Buy peacock feathers') + self.check_for_row_in_list_table('2: Use peacock feathers to make a fly') + #comment = self.browser.find_element_by_id('comment').text + #self.assertIn('oakwowakkoaw', comment) + def check_comment_based_on_total_list(self): + table = self.browser.find_element_by_id('id_list_table') + rows = table.find_elements_by_tag_name('tr') + comment = self.browser.find_element_by_id('comment').text + if len(rows)==0: + self.assertIn('yey, waktunya berlibur',comment) + elif len(rows)<5: + self.assertIn('sibuk tapi santai',comment) + else: + self.assertIn('oh tidak',comment) + if __name__ == '__main__': unittest.main(warnings='ignore') \ No newline at end of file diff --git a/lists/__pycache__/models.cpython-37.pyc b/lists/__pycache__/models.cpython-37.pyc index 20ce025413da3c795f0bcef4dcd82ebc4e3d542f..b2cc93ad44bd444635a96baf5acdc66d806070f3 100644 Binary files a/lists/__pycache__/models.cpython-37.pyc and b/lists/__pycache__/models.cpython-37.pyc differ diff --git a/lists/__pycache__/tests.cpython-37.pyc b/lists/__pycache__/tests.cpython-37.pyc index 89fc02474df93be6380eb68b1e7d219424d2ef57..8bd39b6fd9d0148c7c3a36812ddb5df3f6b0da8e 100644 Binary files a/lists/__pycache__/tests.cpython-37.pyc and b/lists/__pycache__/tests.cpython-37.pyc differ diff --git a/lists/__pycache__/views.cpython-37.pyc b/lists/__pycache__/views.cpython-37.pyc index 3cf9c52c882f69073889ec4c49db7d5150d9e509..7acca25d96cbff180a2ddd40b224692d8f0e009e 100644 Binary files a/lists/__pycache__/views.cpython-37.pyc and b/lists/__pycache__/views.cpython-37.pyc differ diff --git a/lists/migrations/0001_initial.py b/lists/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..86a31b92753ecad65fe8c90a79d8126717dc620f --- /dev/null +++ b/lists/migrations/0001_initial.py @@ -0,0 +1,20 @@ +# Generated by Django 2.0 on 2019-09-24 15:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Item', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + ), + ] diff --git a/lists/migrations/0002_item_text.py b/lists/migrations/0002_item_text.py new file mode 100644 index 0000000000000000000000000000000000000000..da99df0da549fe120da8f7ee730e31d28453390b --- /dev/null +++ b/lists/migrations/0002_item_text.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0 on 2019-09-24 15:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lists', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='text', + field=models.TextField(default=''), + ), + ] diff --git a/lists/models.py b/lists/models.py index 71a836239075aa6e6e4ecb700e9c42c95c022d91..7ba0fddfe438a342c9e3619446dd95ebad45c1d4 100644 --- a/lists/models.py +++ b/lists/models.py @@ -1,3 +1,4 @@ from django.db import models -# Create your models here. +class Item(models.Model): + text = models.TextField(default='') \ No newline at end of file diff --git a/lists/templates/home.html b/lists/templates/home.html new file mode 100644 index 0000000000000000000000000000000000000000..3e7afa097405fd0df1f430695a90e9f5afe0f082 --- /dev/null +++ b/lists/templates/home.html @@ -0,0 +1,19 @@ +<html> + <head> + <title>To-Do lists</title> + </head> + <body> + <h1>Your To-Do list</h1> + <form method="POST"> + <input name="item_text" id="id_new_item" placeholder="Enter a to-do item" /> + {% csrf_token %} + </form> + <table id="id_list_table"> + {% for item in items %} + <tr><td>{{ forloop.counter }}: {{ item.text }}</td></tr> + {% endfor %} + </table> + + <h2 id="comment">{{comment}}</h2> + </body> +</html> \ No newline at end of file diff --git a/lists/templates/homepage.html b/lists/templates/homepage.html deleted file mode 100644 index 6417b223312bcf5f6fc01f8ec9699cf0e1f87008..0000000000000000000000000000000000000000 --- a/lists/templates/homepage.html +++ /dev/null @@ -1,10 +0,0 @@ -<html> -<head> - <meta charset="UTF-8"> - <title>Tutorial PMPL</title> -</head> -<body> - <h1>Name: {{ name }}</h1> - <h2> NPM: {{npm}} </h2> -</body> -</html> \ No newline at end of file diff --git a/lists/tests.py b/lists/tests.py index 049a01f43cce358f3c8794a9d967ece0d5a70ec3..1fd5411ecebe23622a29ab208ab6188aabc1ce5c 100644 --- a/lists/tests.py +++ b/lists/tests.py @@ -3,21 +3,91 @@ from django.test import TestCase from django.http import HttpRequest from django.test import Client from lists.views import home_page +from django.template.loader import render_to_string +from lists.models import Item class HomePageTest(TestCase): + def test_home_page_returns_correct_html(self): + response = self.client.get('/homepage/') + html = response.content.decode('utf8') + self.assertTrue(html.startswith('<html>')) + self.assertIn('<title>To-Do lists</title>', html) + self.assertTrue(html.strip().endswith('</html>')) + self.assertTemplateUsed(response, 'home.html') + def test_home_page_is_exist(self): response = Client().get('/homepage/') self.assertEqual(response.status_code,200) - def test_root_url_resolves_to_home_page_view(self): - found = resolve('/homepage/') - self.assertEqual(found.func, home_page) + def test_uses_home_template(self): + response = self.client.get('/homepage/') + self.assertTemplateUsed(response, 'home.html') - def test_home_page_returns_correct_html(self): - request = HttpRequest() - response = home_page(request) - html = response.content.decode('utf8') - self.assertTrue(html.startswith('<html>')) - self.assertIn('<title>Tutorial PMPL</title>', html) - self.assertIn('Kevin Albert Simanjuntak', html) - self.assertTrue(html.endswith('</html>')) \ No newline at end of file + def test_can_save_a_POST_request(self): + response = self.client.post('/homepage/', data={'item_text': 'A new list item'}) + self.assertIn('A new list item', response.content.decode()) + self.assertTemplateUsed(response, 'home.html') + + def test_only_saves_items_when_necessary(self): + self.client.get('/homepage/') + self.assertEqual(Item.objects.count(), 0) + def test_can_save_a_POST_request(self): + response = self.client.post('/homepage/', data={'item_text': 'A new list item'}) + self.assertEqual(Item.objects.count(), 1) + new_item = Item.objects.first() + self.assertEqual(new_item.text, 'A new list item') + + self.assertEqual(response.status_code, 302) + self.assertEqual(response['location'], '/homepage/') + + def test_displays_all_list_items(self): + Item.objects.create(text='itemey 1') + Item.objects.create(text='itemey 2') + + response = self.client.get('/homepage/') + + self.assertIn('itemey 1', response.content.decode()) + self.assertIn('itemey 2', response.content.decode()) + + def test_displays_comment(self): + response = self.client.get('/homepage/') + self.assertIn('<h2 id="comment">yey, waktunya berlibur</h2>', response.content.decode()) + Item.objects.create(text='itemey 1') + Item.objects.create(text='itemey 2') + response = self.client.get('/homepage/') + self.assertIn('<h2 id="comment">sibuk tapi santai</h2>', response.content.decode()) + Item.objects.create(text='itemey 3') + Item.objects.create(text='itemey 4') + Item.objects.create(text='itemey 5') + response = self.client.get('/homepage/') + self.assertIn('<h2 id="comment">oh tidak</h2>', response.content.decode()) + +class ItemModelTest(TestCase): + + def test_saving_and_retrieving_items(self): + first_item = Item() + first_item.text = 'The first (ever) list item' + first_item.save() + + second_item = Item() + second_item.text = 'Item the second' + second_item.save() + + saved_items = Item.objects.all() + self.assertEqual(saved_items.count(), 2) + + first_saved_item = saved_items[0] + second_saved_item = saved_items[1] + self.assertEqual(first_saved_item.text, 'The first (ever) list item') + self.assertEqual(second_saved_item.text, 'Item the second') + + def test_can_save_a_POST_request(self): + self.client.post('/homepage/', data={'item_text': 'A new list item'}) + self.assertEqual(Item.objects.count(), 1) + new_item = Item.objects.first() + self.assertEqual(new_item.text, 'A new list item') + + def test_redirects_after_POST(self): + response = self.client.post('/homepage/', data={'item_text': 'A new list item'}) + self.assertEqual(response.status_code, 302) + self.assertEqual(response['location'], '/homepage/') \ No newline at end of file diff --git a/lists/views.py b/lists/views.py index 01c479fbedd9062c7eab889e442b19517ce6fccd..16ce10ed08869688061d8edc4f15e5c5c16c95e2 100644 --- a/lists/views.py +++ b/lists/views.py @@ -1,9 +1,19 @@ -from django.http import HttpResponse -from django.shortcuts import render +from django.shortcuts import redirect, render +from lists.models import Item -# Create your views here. -name = "Kevin Albert Simanjuntak" -npm = "1606835595" def home_page(request): - response = {"name" : name, "npm" : npm} - return render(request, 'homepage.html', response) \ No newline at end of file + response={} + if request.method == 'POST': + Item.objects.create(text=request.POST['item_text']) + return redirect('/homepage/') + + items = Item.objects.all() + response['items'] = items + if not items: + comment = 'yey, waktunya berlibur' + elif len(items)<5: + comment = 'sibuk tapi santai' + else: + comment = 'oh tidak' + response['comment'] = comment + return render(request, 'home.html', response) \ No newline at end of file diff --git a/s b/s new file mode 100644 index 0000000000000000000000000000000000000000..31e33cf22fbfd990c726b76f2cad4b506991086f --- /dev/null +++ b/s @@ -0,0 +1,77 @@ +[1mdiff --git a/functional_tests.py b/functional_tests.py[m +[1mindex c9ac63e..a438209 100644[m +[1m--- a/functional_tests.py[m +[1m+++ b/functional_tests.py[m +[36m@@ -35,18 +35,21 @@[m [mclass NewVisitorTest(unittest.TestCase):[m + [m + # When she hits enter, the page updates, and now the page lists[m + # "1: Buy peacock feathers" as an item in a to-do list table[m +[31m- inputbox.send_keys(Keys.ENTER) [m +[31m- time.sleep(1) [m + [m +[32m+[m[32m inputbox.send_keys(Keys.ENTER)[m +[32m+[m[32m time.sleep(1)[m + table = self.browser.find_element_by_id('id_list_table')[m + rows = table.find_elements_by_tag_name('tr') [m +[31m- self.assertTrue(any(row.text == '1: Buy peacock feathers' for row in rows),"New to-do item did not appear in table")[m +[31m-[m +[31m- # There is still a text box inviting her to add another item. She[m +[31m- # enters "Use peacock feathers to make a fly" (Edith is very[m +[31m- # methodical)[m +[31m- self.fail('Finish the test!')[m +[31m-[m +[31m- # The page updates again, and now shows both items on her list [m +[32m+[m[32m #self.assertTrue(any(row.text == '1: Buy peacock feathers' for row in rows),f"New to-do item did not appear in table")[m +[32m+[m[32m self.assertIn('1: Buy peacock feathers', [row.text for row in rows])[m +[32m+[m[32m inputbox = self.browser.find_element_by_id('id_new_item')[m +[32m+[m[32m inputbox.send_keys('Use peacock feathers to make a fly')[m +[32m+[m[32m inputbox.send_keys(Keys.ENTER)[m +[32m+[m[32m time.sleep(1)[m +[32m+[m[32m table = self.browser.find_element_by_id('id_list_table')[m +[32m+[m[32m rows = table.find_elements_by_tag_name('tr')[m +[32m+[m[32m self.assertIn('1: Buy peacock feathers', [row.text for row in rows])[m +[32m+[m[32m self.assertIn('2: Use peacock feathers to make a fly',[row.text for row in rows])[m +[32m+[m[41m [m + if __name__ == '__main__': [m + unittest.main(warnings='ignore')[m +\ No newline at end of file[m +[1mdiff --git a/lists/__pycache__/tests.cpython-37.pyc b/lists/__pycache__/tests.cpython-37.pyc[m +[1mindex f371935..4b6e9b9 100644[m +Binary files a/lists/__pycache__/tests.cpython-37.pyc and b/lists/__pycache__/tests.cpython-37.pyc differ +[1mdiff --git a/lists/__pycache__/views.cpython-37.pyc b/lists/__pycache__/views.cpython-37.pyc[m +[1mindex 8a440d0..2bd5393 100644[m +Binary files a/lists/__pycache__/views.cpython-37.pyc and b/lists/__pycache__/views.cpython-37.pyc differ +[1mdiff --git a/lists/templates/home.html b/lists/templates/home.html[m +[1mindex 9a2a093..dd544fc 100644[m +[1m--- a/lists/templates/home.html[m +[1m+++ b/lists/templates/home.html[m +[36m@@ -4,8 +4,12 @@[m + </head>[m + <body>[m + <h1>Your To-Do list</h1>[m +[31m- <input id="id_new_item" placeholder="Enter a to-do item" />[m +[31m- <table id="id_list_table">[m +[31m- </table>[m +[31m- </body>[m +[32m+[m [32m<form method="POST">[m +[32m+[m[41m [m [32m<input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />[m +[32m+[m[41m [m [32m{% csrf_token %}[m +[32m+[m [32m</form>[m +[32m+[m [32m<table id="id_list_table">[m +[32m+[m[41m [m [32m<tr><td>1: {{ new_item_text }}</td></tr>[m +[32m+[m[41m [m [32m</table>[m +[32m+[m [32m</body>[m + </html>[m +\ No newline at end of file[m +[1mdiff --git a/lists/tests.py b/lists/tests.py[m +[1mindex 4e973ff..44473b0 100644[m +[1m--- a/lists/tests.py[m +[1m+++ b/lists/tests.py[m +[36m@@ -20,4 +20,9 @@[m [mclass HomePageTest(TestCase):[m + [m + def test_uses_home_template(self):[m + response = self.client.get('/homepage/')[m +[32m+[m[32m self.assertTemplateUsed(response, 'home.html')[m +[32m+[m +[32m+[m[32m def test_can_save_a_POST_request(self):[m +[32m+[m[32m response = self.client.post('/homepage/', data={'item_t \ No newline at end of file