From 4b9b3dc6b3da077ea22fe712ace5c6cce7864dc7 Mon Sep 17 00:00:00 2001 From: Kevin Albert Simanjuntak <kevinjuntak51@gmail.com> Date: Mon, 23 Sep 2019 19:58:51 +0700 Subject: [PATCH 1/7] initial commit --- functional_tests.py | 49 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/functional_tests.py b/functional_tests.py index 0c4492d..932937a 100644 --- a/functional_tests.py +++ b/functional_tests.py @@ -1,26 +1,51 @@ from selenium import webdriver +from selenium.webdriver.common.keys import Keys +import time import unittest -class NewVisitorTest(unittest.TestCase): +class NewVisitorTest(unittest.TestCase): - def setUp(self): + def setUp(self): self.browser = webdriver.Firefox() - def tearDown(self): + def tearDown(self): self.browser.quit() - def test_can_start_a_list_and_retrieve_it_later(self): + 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 - self.browser.get('http://localhost:8000/homepage') + self.browser.get('http://localhost:8000') # 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 - -if __name__ == '__main__': - unittest.main(warnings='ignore') \ No newline at end of file + inputbox = self.browser.find_element_by_id('id_new_item') + self.assertEqual( + inputbox.get_attribute('placeholder'), + 'Enter a to-do item' + ) + + # She types "Buy peacock feathers" into a text box (Edith's hobby + # is tying fly-fishing lures) + inputbox.send_keys('Buy peacock feathers') + + # When she hits enter, the page updates, and now the page lists + # "1: Buy peacock feathers" as an item in a to-do list table + inputbox.send_keys(Keys.ENTER) + time.sleep(1) + + table = self.browser.find_element_by_id('id_list_table') + rows = table.find_elements_by_tag_name('tr') + self.assertTrue( + any(row.text == '1: Buy peacock feathers' for row in rows) + ) + + # There is still a text box inviting her to add another item. She + # enters "Use peacock feathers to make a fly" (Edith is very + # methodical) + self.fail('Finish the test!') + + # The page updates again, and now shows both items on her list \ No newline at end of file -- GitLab From 851c8cd978cace88e1e728f3c2bf8c0e55f68edd Mon Sep 17 00:00:00 2001 From: Kevin Albert Simanjuntak <kevinjuntak51@gmail.com> Date: Mon, 23 Sep 2019 21:10:18 +0700 Subject: [PATCH 2/7] refactor home page view to use a template --- lists/__pycache__/tests.cpython-37.pyc | Bin 1411 -> 1461 bytes lists/__pycache__/views.cpython-37.pyc | Bin 463 -> 304 bytes lists/templates/home.html | 3 +++ lists/templates/homepage.html | 10 ---------- lists/tests.py | 24 ++++++++++++------------ lists/views.py | 7 +------ 6 files changed, 16 insertions(+), 28 deletions(-) create mode 100644 lists/templates/home.html delete mode 100644 lists/templates/homepage.html diff --git a/lists/__pycache__/tests.cpython-37.pyc b/lists/__pycache__/tests.cpython-37.pyc index 89fc02474df93be6380eb68b1e7d219424d2ef57..f3719353bc5df3911c6e016432f677b0b2a1a4e4 100644 GIT binary patch delta 857 zcmZqX-pbAE#LLUYz`(%3dZ{CJ=0sje#+Zrf_DU%XDQr2Mxm;0Pj12A!DeNg6Eet6f zsm#sHQQRq<!3>&Q6KkAAG#PIR6s6{+q!z`O<i{766lLb6Puv$?&kQn;fq}u9fq|ho zf`Ngdh9Qe#0b>f|LdIIg8pbT91<WZ-3mI#fY8V!<)G#ezO<`WhxR8;Np@v}rTMA1J z(?TXN8zjfRkYNEw3M*WmvxYH+4J4n!5X_*-?pMX7pOK%NT9BBYs(*{6v?R@<%8kt? zqa-)Su1d<LB(o$Z)h;Ao*Ck&eC$qSu*hU{BRK;$i4^hMk(yj+$YjWLUOU}tm%`3UZ zoSs@T`6#nVJuApp1-Cd-^HPe-GfOgV2_+U6rxuljq~;dnB$lLx7N@3YGT&k;PR&WX z#Zi=6T#%nvoO+7|WZp`KB5?)=hF`j_Rxu%^>50WL0lon~F$K8=ISQ#2$*D!jnZ>CJ zMloQA#gwELmlW$2RNhhsvEo6liZ7UK$s!@n2?|CYP$V((F!C@8F!C^pFjg5%e#a;? z*_K6QG7n>LND(&!1H&zDh~r!fOA~W$aTk{)mXsF9C+DZ6YBCjxFfcF_iGm1_qrfgJ zk^pHEN3t(5JvBbFI6k!^v$#ZX@&iVXdKvWSV_3jc!<Yh&B5)KiqeMX!QgAXCfl?OO zWktda3=D)FQCgf@4DophG<+FFCqH0R5W<w0Jc~ucP7>rDSr8!yA`l(}vp~Kp;$UE4 z0O4Xb5QC9}gM$Su=BLRsiPbmsmRL$wVqSW_9?U|$oczR;)S@DGkbxkLkdOi!2qr+L X-r}&y%}*)KNws5y#SJKCpqL2&7bxV- delta 820 zcmdnW-OSDF#LLUYz`(%3@uxAib|SANW57gpdog#06t)!h7KRk|ROV*pD9#j)U<OUj zi5*T8?}bkmW%kOv#hjj6a*I2$xHz?_#I>+AG3OR{aY<rHX>ojVeoCq)(=C?b)SR?i z97U<c1^Ic!sVf<Z_!t-%e(Abe#e|fmCl<#9_y+jIl%y7yWag!(=O>mVXBg@l$K+%d zmlT7Ai}eaBZ;4Mn$1KjsF}a#WVe&gBuE}?q<?5vv7#K<zQW%>VYZ+@87BJQ@W-*m8 zFJxk5NMQ(O&}8zf;?mE^&rK~zOi$I<WGP}|U|=W$dGZ!ZT4`Q#5gP*ogC<iE4+8_k zE!MRB(!3O~(;x&tNK^yltoWk*{F3<6qMZ1m)Z+Y{vee@ElKl9L{QBI~c#zTYWtpkv zAVZ2-Kmo|e!B}PLk)N9ykeHqtl3HA%htCjXGm;rW`WYA)K<2PAFfceXFfbH{fqmJ` zP|H}tSOfAaQw>uV(*ov{dd7u}wahgP3s`EH7qF%<Eo5BC$jDH`uz)Rvxdt2zU^WY! z4N}LR!U|Cb4k9+cTP&p|X%<y%HW?+kId)YtHYJ%QIjMFbr6u`AnTa_HpvbY&hX__l zc&C<S<|#PlB&8OWC@2JH<|gK4mFATsW>>M>=z~qr<R}8U9vrrle=(XEbEM{_6qjd~ zWN5NLLYloOwXig`xTJ^|6v8YZU62q5C5s|ZuuopVq$()@@;gX~fsu`ogOP_(fRTrh zhq20F@<C>q$v>DxCa-1Dumh<o5(dSqEQkQ9M>DL5oq>S?go{DZ&B4gQ!odO-^V8&- mEX?X_2Ie4X0-FJH#w`w;-29Z%oK!ndycB~H4#)*y%me^HM$)qY diff --git a/lists/__pycache__/views.cpython-37.pyc b/lists/__pycache__/views.cpython-37.pyc index 3cf9c52c882f69073889ec4c49db7d5150d9e509..8a440d0183ac08a94c7d014c9e3b9bebc1d82784 100644 GIT binary patch literal 304 zcmZ?b<>g{vU|>)`))AY|z`*br#DQTZ1_lNP1_p*=2?hp+6owSW9EM!RC`Lwx6s8pB z7KSLM6qaBHP1ctn^_q;g*oso~Qc{bO89{so1_lt#%)r3l3^D>_O9?{_LkeRvQ!s-j zlV25QMt*LpUPei7jwWLf$SO_7TkJ)tg{7&*B`X<<SQr=>e(Abe#e|fmCl<#9_y+jI z6yz4<D5O>-rxqn=7N;s0#pGlbmlVg8Wu}%F>lIYq0vj1$keHqdvbPvyC<9{=8v_G_ zpC)sZKuT6(UV6S>aYlYoNpfjPG1ykHG}tyIf|Y@R;TDHYZhlH>PO2TqBVfaLm;kU6 BK_>tJ literal 463 zcmZ?b<>g{vU|`tsvN2YQk%8echy%k+3=9ko3=9m#It&a9DGVu$ISjdsQH+crHd78$ zE^`z!BSQ*v6iW(A6l)4=3R??96k7^=FoPz?OOP3wjJJ3^N=gcXQi}`n^NLe78E>%_ zrRJri7F9`jr<P^rDLCdNr52Sa1ZU<Z=4F-Ul_X|IaT%H!m{}N`np&DBGlEQEU|;|_ zgoS~D!5QQjF$M;P5{44S6vjDBwTvZ9H4G_CHH^*7!3>(rews|TSn?8cQ*SZn735a& zX5{Cl79^&p>SdJV=4dh(fea~PWnf?^VrF1q&}6#BUX)r`np#|Pi=znY$dwF591IK$ zzjR%#VnRyO6N_U4d;@%9N>YnUGV{{Y^Ak&wGYoZ&V{$T!ONwL4GE>Wo^$IF)ae}Oh z2ie6AawNzi21YK%B2ei1X|mtqPRUBlOV8KKC@Co@0{JIO04h?PkzZ7jTv}2Lb`z2l mL0Z9XK_WOA7#MDG*yQG?l;)(`fx@R4<XRp^9%dFs7DfQNfo&uJ diff --git a/lists/templates/home.html b/lists/templates/home.html new file mode 100644 index 0000000..94d4105 --- /dev/null +++ b/lists/templates/home.html @@ -0,0 +1,3 @@ +<html> + <title>To-Do lists</title> +</html> \ No newline at end of file diff --git a/lists/templates/homepage.html b/lists/templates/homepage.html deleted file mode 100644 index 6417b22..0000000 --- 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 049a01f..4e973ff 100644 --- a/lists/tests.py +++ b/lists/tests.py @@ -3,21 +3,21 @@ 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 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_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_uses_home_template(self): + response = self.client.get('/homepage/') + self.assertTemplateUsed(response, 'home.html') \ No newline at end of file diff --git a/lists/views.py b/lists/views.py index 01c479f..e90445a 100644 --- a/lists/views.py +++ b/lists/views.py @@ -1,9 +1,4 @@ -from django.http import HttpResponse from django.shortcuts import render -# 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 + return render(request, 'home.html') \ No newline at end of file -- GitLab From 429fb6fb29cab575a5c11d359dd3b84e7efdf7a2 Mon Sep 17 00:00:00 2001 From: Kevin Albert Simanjuntak <kevinjuntak51@gmail.com> Date: Tue, 24 Sep 2019 18:58:12 +0700 Subject: [PATCH 3/7] Front page HTML now generated from a template --- functional_tests.py | 21 +++++++++++---------- lists/templates/home.html | 10 +++++++++- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/functional_tests.py b/functional_tests.py index 932937a..c9ac63e 100644 --- a/functional_tests.py +++ b/functional_tests.py @@ -3,18 +3,19 @@ from selenium.webdriver.common.keys import Keys import time import unittest -class NewVisitorTest(unittest.TestCase): +class NewVisitorTest(unittest.TestCase): - def setUp(self): + def setUp(self): self.browser = webdriver.Firefox() - def tearDown(self): + def tearDown(self): self.browser.quit() + # She is invited to enter a to-do item straight away 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 - self.browser.get('http://localhost:8000') + # Edith has heard about a cool new online to-do app. She goes + # to check out its homepage + self.browser.get('http://localhost:8000/homepage') # She notices the page title and header mention to-do lists self.assertIn('To-Do', self.browser.title) @@ -39,13 +40,13 @@ class NewVisitorTest(unittest.TestCase): table = self.browser.find_element_by_id('id_list_table') rows = table.find_elements_by_tag_name('tr') - self.assertTrue( - any(row.text == '1: Buy peacock feathers' for row in rows) - ) + self.assertTrue(any(row.text == '1: Buy peacock feathers' for row in rows),"New to-do item did not appear in table") # There is still a text box inviting her to add another item. She # enters "Use peacock feathers to make a fly" (Edith is very # methodical) self.fail('Finish the test!') - # The page updates again, and now shows both items on her list \ No newline at end of file + # The page updates again, and now shows both items on her list +if __name__ == '__main__': + unittest.main(warnings='ignore') \ No newline at end of file diff --git a/lists/templates/home.html b/lists/templates/home.html index 94d4105..9a2a093 100644 --- a/lists/templates/home.html +++ b/lists/templates/home.html @@ -1,3 +1,11 @@ <html> - <title>To-Do lists</title> + <head> + <title>To-Do lists</title> + </head> + <body> + <h1>Your To-Do list</h1> + <input id="id_new_item" placeholder="Enter a to-do item" /> + <table id="id_list_table"> + </table> + </body> </html> \ No newline at end of file -- GitLab From e98e66bd7f85aa8ac42f210e2b146a881986d146 Mon Sep 17 00:00:00 2001 From: Kevin Albert Simanjuntak <kevinjuntak51@gmail.com> Date: Tue, 24 Sep 2019 20:48:37 +0700 Subject: [PATCH 4/7] refactor --- functional_tests.py | 23 ++++---- lists/__pycache__/tests.cpython-37.pyc | Bin 1461 -> 1766 bytes lists/__pycache__/views.cpython-37.pyc | Bin 304 -> 409 bytes lists/templates/home.html | 12 ++-- lists/tests.py | 5 ++ lists/views.py | 5 +- s | 77 +++++++++++++++++++++++++ 7 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 s diff --git a/functional_tests.py b/functional_tests.py index c9ac63e..a438209 100644 --- a/functional_tests.py +++ b/functional_tests.py @@ -35,18 +35,21 @@ class NewVisitorTest(unittest.TestCase): # When she hits enter, the page updates, and now the page lists # "1: Buy peacock feathers" as an item in a to-do list table - inputbox.send_keys(Keys.ENTER) - time.sleep(1) + inputbox.send_keys(Keys.ENTER) + time.sleep(1) table = self.browser.find_element_by_id('id_list_table') rows = table.find_elements_by_tag_name('tr') - self.assertTrue(any(row.text == '1: Buy peacock feathers' for row in rows),"New to-do item did not appear in table") - - # There is still a text box inviting her to add another item. She - # enters "Use peacock feathers to make a fly" (Edith is very - # methodical) - self.fail('Finish the test!') - - # The page updates again, and now shows both items on her list + #self.assertTrue(any(row.text == '1: Buy peacock feathers' for row in rows),f"New to-do item did not appear in table") + self.assertIn('1: Buy peacock feathers', [row.text for row in rows]) + 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(1) + table = self.browser.find_element_by_id('id_list_table') + rows = table.find_elements_by_tag_name('tr') + self.assertIn('1: Buy peacock feathers', [row.text for row in rows]) + self.assertIn('2: Use peacock feathers to make a fly',[row.text for row in rows]) + if __name__ == '__main__': unittest.main(warnings='ignore') \ No newline at end of file diff --git a/lists/__pycache__/tests.cpython-37.pyc b/lists/__pycache__/tests.cpython-37.pyc index f3719353bc5df3911c6e016432f677b0b2a1a4e4..4b6e9b94deeece6744684ad98fb68530a61ee8f0 100644 GIT binary patch delta 334 zcmdnW{fw8-iI<m)fq{X6kFzUwKFdVDXN)=%zpC=2aI`Q)v88YZGiY*cmSgN^u1{tJ zDPv$@U}9ikU}a!naAsg&C^lnYV5nipV#s1lVN794Va{YsVd-V6WvpRXz?8yV!<faq zfMp@WLMBFr8ioa|HH;~&Aa)8vFoPzWUlo^rMt*K;L1KEUeiUbBNosC<Noqw&6~CiG zUTV2QPG)h50!UPo@fM3lN@7W36(>l&UPei7jwV|X$lbSC3i69fiUb%K7>am61n*=! z7L_QOlGNgo_~gXA_~OK})cC~s0RP~S_@dOp($wM-Nsz<YK)zuVVH9Gl()7sBO$|s) qPYp>eF44oM(@&Fq@&*<YM#aewSQNQ97#J8h7&$mNSSE9_t^oj;>sDL< delta 72 zcmaFHyOo>IiI<m)fq{X6^-@RdOy-Gv&lpuEepO`&X3*r=tj5^S%<QMhHu)B-$>c3; Y!a_wH3=9k)T+9YyFmiBAwqjcY0E|x$^Z)<= diff --git a/lists/__pycache__/views.cpython-37.pyc b/lists/__pycache__/views.cpython-37.pyc index 8a440d0183ac08a94c7d014c9e3b9bebc1d82784..2bd53936920f4ce023b9f769a5b9be94588a1645 100644 GIT binary patch delta 337 zcmdnMG?SUviI<m)fq{YH7)Mv^m5IEP^(qVu3@HpLj5!Rsj8Tk?AU0DDQ!aB9Gb2L^ za|%lfLljF2YcPW*+e?r>O~zY19wj9OL8-+B`FX{unvA#Dic<4ZQj3xqLGla?3?Q0= zfq}u9fq|h|ih+TlgrSBZg)xPxh9Qe_0Tam3g-n@@&CJ0Jnyj9FRh$|5xv6>?CAm3K zym_hR@tGy5x$z~b6(zSg5ljY6<|1YW28LTK0sg@ux0usYOEej8u@|KlmZlb$tYj$S zoH*Myj|F5Uh+tr3V=UrkU|{gmWWB|ml9ia3p0AftQc_UF#K6E1B>)vE&d4t+NiHoZ l2Ad7mP{hf=z<@-6LhBZXO>TZlX-=vg$Zy3U3wRiLm;ij;PpSX_ delta 241 zcmbQqyn%_=iI<m)fq{WR{a8nA`b1vIdI<&wh7^Vr#vF!R#wbQch7_h0<`#x1rWBT7 z22IwNAhnu|x7dnO^HNfak{LmK1_lNY&CI~S;LO0lPz*A#grSBZg|V3_m_d`tuZlAx zKQ~n`qa-&+ld*`2fq_Aj@fLegYGG+=amh-CA{GV)hF`j_Rxu%^6Mq;-fD9@IsbXL( zVq;)n@Y7_D5=hBP%uCPLE6&I-DoHLaDFzz@mIiA_B3Kz17;bUc<mRW8=A_zzTn09b GhY0}KsW5H; diff --git a/lists/templates/home.html b/lists/templates/home.html index 9a2a093..dd544fc 100644 --- a/lists/templates/home.html +++ b/lists/templates/home.html @@ -4,8 +4,12 @@ </head> <body> <h1>Your To-Do list</h1> - <input id="id_new_item" placeholder="Enter a to-do item" /> - <table id="id_list_table"> - </table> - </body> + <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"> + <tr><td>1: {{ new_item_text }}</td></tr> + </table> + </body> </html> \ No newline at end of file diff --git a/lists/tests.py b/lists/tests.py index 4e973ff..44473b0 100644 --- a/lists/tests.py +++ b/lists/tests.py @@ -20,4 +20,9 @@ class HomePageTest(TestCase): def test_uses_home_template(self): response = self.client.get('/homepage/') + self.assertTemplateUsed(response, 'home.html') + + 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') \ No newline at end of file diff --git a/lists/views.py b/lists/views.py index e90445a..7ef5b31 100644 --- a/lists/views.py +++ b/lists/views.py @@ -1,4 +1,7 @@ +from django.http import HttpResponse from django.shortcuts import render def home_page(request): - return render(request, 'home.html') \ No newline at end of file + return render(request, 'home.html', { + 'new_item_text': request.POST.get('item_text', ''), + }) \ No newline at end of file diff --git a/s b/s new file mode 100644 index 0000000..31e33cf --- /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 -- GitLab From 43acb640101bdb85aa0b3779d8cb921541d22e10 Mon Sep 17 00:00:00 2001 From: Kevin Albert Simanjuntak <kevinjuntak51@gmail.com> Date: Tue, 24 Sep 2019 22:14:59 +0700 Subject: [PATCH 5/7] failed test for multiple table --- functional_tests.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/functional_tests.py b/functional_tests.py index a438209..547ee62 100644 --- a/functional_tests.py +++ b/functional_tests.py @@ -11,6 +11,11 @@ class NewVisitorTest(unittest.TestCase): def tearDown(self): self.browser.quit() + 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): # Edith has heard about a cool new online to-do app. She goes @@ -46,10 +51,8 @@ class NewVisitorTest(unittest.TestCase): inputbox.send_keys('Use peacock feathers to make a fly') inputbox.send_keys(Keys.ENTER) time.sleep(1) - table = self.browser.find_element_by_id('id_list_table') - rows = table.find_elements_by_tag_name('tr') - self.assertIn('1: Buy peacock feathers', [row.text for row in rows]) - self.assertIn('2: Use peacock feathers to make a fly',[row.text for row in rows]) - + 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') + if __name__ == '__main__': unittest.main(warnings='ignore') \ No newline at end of file -- GitLab From 29736e9f05e7eb2fde807f36e1e971764235a2bb Mon Sep 17 00:00:00 2001 From: Kevin Albert Simanjuntak <kevinjuntak51@gmail.com> Date: Tue, 24 Sep 2019 22:47:22 +0700 Subject: [PATCH 6/7] Model for list Items and associated migration --- db.sqlite3 | Bin 0 -> 139264 bytes lists/__pycache__/models.cpython-37.pyc | Bin 173 -> 378 bytes lists/__pycache__/tests.cpython-37.pyc | Bin 1766 -> 2417 bytes lists/migrations/0001_initial.py | 20 ++++++++++++++++++++ lists/migrations/0002_item_text.py | 18 ++++++++++++++++++ lists/models.py | 3 ++- lists/tests.py | 22 +++++++++++++++++++++- 7 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 lists/migrations/0001_initial.py create mode 100644 lists/migrations/0002_item_text.py diff --git a/db.sqlite3 b/db.sqlite3 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..749774212f1e7fc02410e482a508672c03819652 100644 GIT binary patch literal 139264 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 Hm=FK}O#wpx literal 0 HcmV?d00001 diff --git a/lists/__pycache__/models.cpython-37.pyc b/lists/__pycache__/models.cpython-37.pyc index 20ce025413da3c795f0bcef4dcd82ebc4e3d542f..b2cc93ad44bd444635a96baf5acdc66d806070f3 100644 GIT binary patch literal 378 zcmZ?b<>g{vU|<Na>WWQbU|@I*;=nKq0|SEt0|P^`5(5K63PTEG4nr<u6eA;pJ3|Un z3UdoX3UexB7E?2G6mtqoFoP!ROOQ@Y##?N;`6;P6#mOKp3^T(FlVD(ANM(p(Oks#( zN@dPsNnuQ3>Sc^#O<@jZ&}6yA;#rcKdy7Gn@fLeZYFc7xPKlo;+bxdx_`Jm2)cE*Y zT=DU_`6;D2AU02Yd|_!~4n(GiiGhLP7H3FmMTuKxYEH^6mXg$pl9dca+zbp5;+LMQ zRZK`}dSY=*fNy|LOhIlzjzVfha%xd>W^t;5QA|!|aY=Cu#PNCsl|>*ogK#m(Xbwg& v-%pd}7H3LUVqSW_UP=<gQdVD(f5FlS+aN3+kfS(kAWpVp1cfHZFdilV-nLgr literal 173 zcmZ?b<>g{vU|<km)fj8Tz`*br#DQTZ1_lNP1_p*=0R{$!6owSW9EM!RC`Lwx6sBMX zP3D&%b()N~*mCnzQge#^G?{L3rer1NrRVFVBo%=)uVg4<VPJp|zw}(KVnRyO6N_U4 zd;@%9N>YnUGV{{Y^Ak&wGYoZ&V{$T!ONwJ4X6Y4F-r}&y%}*)KNws4HIRRuB09AD; A<^TWy diff --git a/lists/__pycache__/tests.cpython-37.pyc b/lists/__pycache__/tests.cpython-37.pyc index 4b6e9b94deeece6744684ad98fb68530a61ee8f0..d154cb8796e7c13aed813ec9595e33ce0bb792bd 100644 GIT binary patch delta 999 zcmaFH`%#F`iI<m)fq{X+$+#=lf_);N1Y^ZSb#J2-h7|T3?p&TI9!3Uth7^tz&K8Cg z&Q#`R<|tlwh7_(8?iPj=ZZMxOg(sLnlXqfA7>6d~Ef&v`)ZC5trZX~1OfF*zXXKiE zj%gMn&*V&I1yNB328JRr5Fr64Bqz^fmSGf{yqmdIn;Rs`10qBi7#K8}im+;6U|_f< zK6xICIHTC)-OLJ;7qcuj1L?fQQjlL<QX~k{&kG{>Km<OMCfBekGD=OJ$C~IQ1yU;q zBIH4Y5{N)J63mhWiE%P8Fo19|2Ll5G2O|du2MY&F5lCd>J+XR_WvL8Nj42FJOeu^h zOf3vi%qh&l44N#rctPRfo1c=J6Ovk7lFSGSa|Q+mHU<U;76t|eX9fm_;vxnHh7yKm zhFZoH#u~<W#u~;2ObZzpA!1A^Of^jLj5SO!u`K2VEDITGnQIspu+}gyU|YygpTfM5 ziIJg(IfX@%p_ZkFIfYe{p_Ub_fF+ADg%K<ZQqG#in8F0&r7#3DXtMcLNrhyjDx_r= z6_+Szq?V-?X)5Go7MCbwmZauZ@q?VMP?C|VP@I~apO^BI2^10_AG`z+n(RfOz_`Uy zQlDB;a*L%nu`Kl#dwx<@YH~^OE#}0WoFW-eoUtb7m*$mdvVmhYiVJL6JjjA5Ziu-s zPGVVV3Yc9SB>+(cG7=&bB?wiE5Gn%44v45P0>#lSg_6|blKA4pvdp~n_{6-F_@dO3 zqRdn<7i3?tA}Fvy8W<Sa7}*#(m>?t<qW}{JBL^cNW0fAr%kbFJBV?eTCQFer1A`4i zkqRhiR6&FuhyYoFa39!tMQRKT44_0-3<^dLCNSSmlYg=cTUJOE4=C7+^>RT8r5GHp m;KT)1gk%udT(D<3Y;yBcN^?@}Kv7XFz`(%3!-xc#1jGPCz24yf delta 380 zcmew;^o*C!iI<m)fq{X6kFzUwKFdTt3C5U->fU1R3@Pj>94!nf9I4FB%u(DaoWTs5 zToadsZDwMe&d4Y}c@|SRBj@B#OtTodC-*Wd7>O`2FcgV`2yr+e!N9<9OS~ktxFkL! zKQ}eLATd2PKC?JJwIZ{)L~!zb=2kV3-9_9W9l{I@44O<uSk0N-#UjHfI{7}c!sO#D zi_JiqZm|^P7nc+XfVA>}2wo6@*N_FQij0zz53we?N`lnNf(SVfp$H-n&IYqUZZG0s zU|;~@Vi3W>$iczE!odO-_0!~;yqP1*0?a7_>p&17y|*}Qa`RJ4b5iXX85kIfK~Cgh HghM6(lqp2# diff --git a/lists/migrations/0001_initial.py b/lists/migrations/0001_initial.py new file mode 100644 index 0000000..86a31b9 --- /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 0000000..da99df0 --- /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 71a8362..7ba0fdd 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/tests.py b/lists/tests.py index 44473b0..4a9024e 100644 --- a/lists/tests.py +++ b/lists/tests.py @@ -4,6 +4,7 @@ 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): @@ -25,4 +26,23 @@ class HomePageTest(TestCase): 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') \ No newline at end of file + self.assertTemplateUsed(response, 'home.html') + +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') \ No newline at end of file -- GitLab From 324d280ad1a3de65a15e577dbcae9e014fa8ef96 Mon Sep 17 00:00:00 2001 From: Kevin Albert Simanjuntak <kevinjuntak51@gmail.com> Date: Wed, 25 Sep 2019 03:45:23 +0700 Subject: [PATCH 7/7] Redirect after POST, and show all items in template --- db.sqlite3 | Bin 139264 -> 135168 bytes functional_tests.py | 19 +++----------- lists/__pycache__/tests.cpython-37.pyc | Bin 2417 -> 3875 bytes lists/__pycache__/views.cpython-37.pyc | Bin 409 -> 520 bytes lists/templates/home.html | 6 +++-- lists/tests.py | 34 ++++++++++++++++++++++++- lists/views.py | 13 ++++++---- 7 files changed, 48 insertions(+), 24 deletions(-) diff --git a/db.sqlite3 b/db.sqlite3 index 749774212f1e7fc02410e482a508672c03819652..ebd1d000d647b958273035115175320285255a44 100644 GIT binary patch delta 773 zcmZoTz|pXPV}dlV0RsbrA_Ejm)G%i>*qCsXpV^v+ZL^}nJ#Hprfyp*9DuPA^Rwl+) z1{QjzhNgx_#zy>;Ib@Xi;i86?Mkba<lk<_q3=E8oEsZ8Gl(B-TGuN{)G_^3dnEXn{ z5+P=0XkunzI@w6p4k2b@Xl!I=Jh@)hgb!+mxt@`sv8nmwgR*7_Wrl{PmPV$N+2o92 zVrF_4mPV##CX+qn;Oflu%ngjq4U8xE%2^}SnHrfGm>W;Njx1(mWM*PwFj-OFL>g+X znVx}>nYpo%0W&LuxT<4fN^WM}<c0F$Fmp`xER4*|49q4^lUG8BnHiZG8=Fi%F0Z8w zHOExX#K_Fd#Dtf>hk=d1j)DIr{}uja{QLRq_@`|aOvvJ&T&FK6&c(~atjL+e$HT11 zn3GvtQXHRIlA6o1d6|CHhD8YqiwXoFXj1{Bz;;FlMnwfa9u00S?#KL@;23nC=qSA1 zIf1c~i&=pofBOC`#st2SjQG;x)S~$K{G3KJ<LL*p88sOBr!P!l6rKJ*o3WDBgiYLE zbMirMiRn{w80EQn)-rH_%xYvZn$DQdsK6*ceM3H@#B{5CMo%WbrPEvU8LPKz<uX<? zvM?|(9GRTUdVsl6#B{n=HscgVuFZ@I|K(wBWD!`-a)42RhlRg^f&V%G0siIu4VwiM z3i#_)S(q6DLyJ=t3Q`l3^OLg`(oz#kGE$3*6-x3Iauc&t6%rNFaw^4{nHfx-N-Hsx QsWK6#pAox$recUg0ZkmrAOHXW delta 683 zcmZozz|nAkV}dlV4g&*&5(5JRKLY~;<3tT}MxBibNBNnpc-S^8D%|5{G7^|<E2AuE zXli9*W@T)qXJ%<)XlZQBKbb>Dg&!npY-MVuXJBS%U}Q2mUq%@wW~yglZfI^|I(eat z6++C+(%jtCX!0u=ON5xIfrY7&(PSf8JA|0Ap_z$+!Q^^b6F#UNCVCbomX@ZI56YUs zl$q!mn3x+`nonkvGlq#7=vf+?8CjZ6_K<_CGte_IH#9Ien%paA4OM4i338sHh3Vw$ z$YQ33rk0i#lNIGnq#@RtSn3&>n^>3{8!)pnh^sm#rsQVkO<pK3jxfi-%)-pvaPl;H zC776no`so#siE=Y<MLX{P;)Hw%*+kVjZAs@dl=aG>lpZ7@?YU!#=oDxj(_@Q!GtXS z$#wdI;@ljGr6n2hrMx`MiX1ta#U;h@nI);Yo0sWFZP+ZB@ScC-0>MQE0&ujcfKgyO zqXVO&0w4E2o^oz=zJGlG7#J9wCprpmcTQle<YL~!kTZRM7GnZ8n<*Ou2sDbAOwY+@ zoWk5_W;9(ln^A*Ne)_@`M$zfn*^HH}#%$vLnv)N5OH60XVU*YATgp%d(v)M!F0QD^ z*r;5Rn3R)>a2bNdKiwyX(QCVAE@KTN3x6|1<m6n|Q07J^)9Kndj0%iOAn8OV28QYD pa~P``xi&K<{FjILV^aZ(z;c!Yj0zkK0wB8>_#s{mU<J!7000hWtoZ-{ diff --git a/functional_tests.py b/functional_tests.py index 547ee62..6e991b3 100644 --- a/functional_tests.py +++ b/functional_tests.py @@ -18,8 +18,6 @@ class NewVisitorTest(unittest.TestCase): # She is invited to enter a to-do item straight away 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 self.browser.get('http://localhost:8000/homepage') # She notices the page title and header mention to-do lists @@ -33,24 +31,13 @@ class NewVisitorTest(unittest.TestCase): inputbox.get_attribute('placeholder'), 'Enter a to-do item' ) - - # She types "Buy peacock feathers" into a text box (Edith's hobby - # is tying fly-fishing lures) - inputbox.send_keys('Buy peacock feathers') - - # When she hits enter, the page updates, and now the page lists - # "1: Buy peacock feathers" as an item in a to-do list table - + inputbox.send_keys('Buy peacock feathers') inputbox.send_keys(Keys.ENTER) - time.sleep(1) - table = self.browser.find_element_by_id('id_list_table') - rows = table.find_elements_by_tag_name('tr') - #self.assertTrue(any(row.text == '1: Buy peacock feathers' for row in rows),f"New to-do item did not appear in table") - self.assertIn('1: Buy peacock feathers', [row.text for row in rows]) + time.sleep(5) 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(1) + time.sleep(5) 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') diff --git a/lists/__pycache__/tests.cpython-37.pyc b/lists/__pycache__/tests.cpython-37.pyc index d154cb8796e7c13aed813ec9595e33ce0bb792bd..21ea18ac445b6272577227d401157545420486b5 100644 GIT binary patch delta 1438 zcmew;v{;VMiI<m)fq{YHXhm1-N}i2;T#Sq^lO-8-Wm33W7^2uyxKlV<7^2uxcv5&< z7@{~*_<|WU`8RtpzGG&*HQAE&kWn%tNIL@q1Bhl}U|?`&U|=X#VqjpXVaQ@wz?j0g zkdcw0hG79y33C?90@j5LlWkcf^@~8tHQ9=|85kIfctC^<h~QvgV7SGepOlrFTvB|C zH95aDuSAovNObZ<R^fV;lGNgo`24(_%J|~Mvee@E%#zgH;`s86)V%n-)a2CS;>4m# zd64xWcQ7#WFjg6Q<maXaB&Mf^q!yRx5u+dOA7%yy29P;m|0FOlFiif;B2f?XL<;Ld zCPoG@k8L4CEfdItHB4FTDa;^oFpn{dBZUpYOJSE}NMQu=Qy797G&%gLxb!pfb5jcv z(^K_}6c`v7s`woh@>0tcax#lc6hMB{WGqr-U|@I&3ad;#Mh1pk^&C0*$%!SI`FWb0 zkgx-VbP+u4ic~<Ms0s>2*0ju`;*wh|C8-r9MY0SG44TYEq99o@kSs@DYB@OkiX=c{ zU_uhaQf6Ra0GU|~iWCM$5k?_KE=E2kK1OiB)Po|MiGhKE6&BM03=9k<3|Wj>Oeu^h zOudYZFdj36SHqCSynrQzWg%lNV-3Rs))dAX#w@l4><bw{K>-$FMiv1F4y#`k2Pgni zD-{ei8H=<)fddw>O085dLJl}hjv`Q+0sH$FTXIoqVo53_U_kCK5(IgP7ew$)&S#O= zlL04zl+5CSoW#oF_{5x?cu;7AL!ww4lytzkfsv1qkBNtA@;O#9DIALZG&v{#V>RIh zg;$Xp$OhfX#%zj0d<+Z>9E=<s94s6x9IPD79GsIA*rXX%CQCA^vVh`!@>I5~+C}Q1 z2w{h~9pt@RETAL}@dk5ZP7WkWK@mB54tq1B*<=NdfXRX^VvJ6cKd^{upynvF#0Uy! zrW!_2Vw|kVDqfE_aY0<d0SPlu#6xU`2Wk<>4MmzD4}#pO$plG6ps>Q0blgE<2+|Bo zI#pVno+YWdzWFJsIg@X(DuO&Q`8|tFdJSV1GsNML+>*kEl0Vpq&mZ8dQKSJ1Q5JN6 z$bzE1UJ@MbMX4#7MWBKuJ~6E%wJ1KoKRCn}<X$#Vs%8{n<YTN-hdUNgVqnwfr^!~N z2MQE@5Mcl!OhE)VIhcW1;4B3p<Uo9I?lNRxU@(DM$-%@S$iY@*IC(8cCmTqnNCH&O LP4?$hWYh)#{vtjW delta 242 zcmZ21_fd$?iI<m)fq{X+$+#=lf_)<&7bBz2WJyL{mS6@=uFXk|@0b~*CI_+}V)oNy zpPbEU!l*QP6{jK(2Ll5G2O|du2MY(w<hz{GQX&it45<uJj42FJOeu^hOf3vi%qh&l z44N#HmAI}Ny<}uyV9;bQ0_nTOQj%Ixa*L%nu`Kl#dwx<@YH~^OE#}0WoFW+p28LU# z$@!&uC6kr7n;8`+FXIld_0wc2Qf6RaC{h6tsvtrSL`a|#k|3@c0|SFR0|P@b6Uc>3 TMQW4d`8pZZCcosfWE2Ac{3J6m diff --git a/lists/__pycache__/views.cpython-37.pyc b/lists/__pycache__/views.cpython-37.pyc index 2bd53936920f4ce023b9f769a5b9be94588a1645..c8f22a400a74cd6f793fc83c9277d53805961a68 100644 GIT binary patch delta 428 zcmbQq+`+=<#LLUYz`($;zoIMFi*X{KM7;(B149Z!3S$mKE@Kp9E>jc}BZ$wG!<@?! z#lpyt!kog=!Vtxp!Wzt=$@UVYS(E7&M^S1@W>IQ#$t|{`)V!3`B2C6yES@E)xyg(m z6$}gvObiSRtPBhc&I}9;#SRP%3^fc{3@MD+OhsxXj9E-s%ry*IEGbO&k_;)#y^M?u zC9Ekd&5XeeAjt)63mIw|OW11|Qdm>iY8W#ao0)?dG}--bu>|-BheUB^mZav!m!wvd zfUE`4Rb2WR`MIeDiRr2ORh%HEUPei7&Mj7u%3@89TWq<hB^miCMJx;q47b?xld@8i zONwu?CF>TYCYGcYfm~Vya`G+a#GITWW(EcZO{QDyMX80Qsl_El><kPHD;bJ-C%$uv z28SOb7o!Lx2NM@#5kCV1gP$f_lt4;WVqSW_UU5c#QAu)XNio<sut`xoIhn;J#d^8< dDXBTdU?+gJ74b4KFdz|plj|A9SOge(m;hPRW%&RA delta 317 zcmeBRnaRxO#LLUYz`($8jH4^|3d2M`iFy?V28I-d6viBeT*fFyMi84RhbfmiikXoi zg*k<#g&~S1g*BK#lkFu)qbB1m9*>fef}qsmg8aPVR87WPY(=SgDXB%tj39Xi1_lt# z!N9=a%)r1<EXBaUP{L5dkiwY4RKt+PxPS>{=t8DU#%AVV22EB^zbej*{M=N%jFQ}( zDBir(^7zb>)ZF-z)QXZ@oCqd^CUX%p0|Ub?mH_|YkXy{@sU@0>x7dqP3rkarOI9)z zaZV0obn<5bxq*?5v51?2fx%Cc^%i$ZR$^XyzFtO2NkI`40|P^p092$nBfqF5xwNDh ZY%W+s5hnu!0}{bC`5mJe3lAd?69C^`OYZ;x diff --git a/lists/templates/home.html b/lists/templates/home.html index dd544fc..9dba103 100644 --- a/lists/templates/home.html +++ b/lists/templates/home.html @@ -9,7 +9,9 @@ {% csrf_token %} </form> <table id="id_list_table"> - <tr><td>1: {{ new_item_text }}</td></tr> - </table> + {% for item in items %} + <tr><td>{{ forloop.counter }}: {{ item.text }}</td></tr> + {% endfor %} + </table> </body> </html> \ No newline at end of file diff --git a/lists/tests.py b/lists/tests.py index 4a9024e..8a65cfc 100644 --- a/lists/tests.py +++ b/lists/tests.py @@ -28,6 +28,27 @@ class HomePageTest(TestCase): 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()) + class ItemModelTest(TestCase): def test_saving_and_retrieving_items(self): @@ -45,4 +66,15 @@ class ItemModelTest(TestCase): 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') \ No newline at end of file + 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 7ef5b31..7454b76 100644 --- a/lists/views.py +++ b/lists/views.py @@ -1,7 +1,10 @@ -from django.http import HttpResponse -from django.shortcuts import render +from django.shortcuts import redirect, render +from lists.models import Item def home_page(request): - return render(request, 'home.html', { - 'new_item_text': request.POST.get('item_text', ''), - }) \ No newline at end of file + if request.method == 'POST': + Item.objects.create(text=request.POST['item_text']) + return redirect('/homepage/') + + items = Item.objects.all() + return render(request, 'home.html', {'items': items}) \ No newline at end of file -- GitLab